diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000000..05f39760b195 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,60 @@ + + +**Description** + + + +**Steps to reproduce the issue:** +1. +2. +3. + +**Describe the results you received:** + + +**Describe the results you expected:** + + +**Additional information you deem important (e.g. issue happens only occasionally):** + + **Output of `show version`:** + + ``` + (paste your output here) + ``` + + **Attach debug file `sudo generate_dump`:** + + ``` + (paste your output here) + ``` diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000000..2ac7d9e47730 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,26 @@ + + +**- What I did** + +**- How I did it** + +**- How to verify it** + +**- Description for the changelog** + + + +**- A picture of a cute animal (not mandatory but encouraged)** diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..fb7ccac93dc4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,75 @@ +# Build system related +.platform +.screen + +# Build artifacts +fsroot/ +fs.* +target/ +*.deb +*.changes +*.buildinfo + +# Subdirectories in src +src/hiredis/* +!src/hiredis/Makefile +src/igb/* +!src/igb/Makefile +src/initramfs-tools/* +!src/initramfs-tools/Makefile +src/isc-dhcp/* +!src/isc-dhcp/Makefile +!src/isc-dhcp/patch/ +src/libnl3/* +!src/libnl3/Makefile +src/libteam/* +!src/libteam/Makefile +src/lldpd/* +!src/lldpd/Makefile +!src/lldpd/patch/ +src/mpdecimal/* +!src/mpdecimal/Makefile +src/python-click/* +!src/python-click/Makefile +src/python3/* +!src/python3/Makefile +src/redis/* +!src/redis/Makefile +src/snmpd/* +!src/snmpd/Makefile +src/sonic-device-data/src/device/ +src/sonic-device-data/src/debian/ +src/supervisor/* +!src/supervisor/Makefile +!src/supervisor/patch/ +src/thrift/* +!src/thrift/Makefile + +# Autogenerated Dockerfiles +dockers/docker-base/Dockerfile +dockers/docker-config-engine/Dockerfile +dockers/docker-database/Dockerfile +dockers/docker-dhcp-relay/Dockerfile +dockers/docker-fpm-frr/Dockerfile +dockers/docker-fpm-gobgp/Dockerfile +dockers/docker-fpm-quagga/Dockerfile +dockers/docker-lldp-sv2/Dockerfile +dockers/docker-orchagent/Dockerfile +dockers/docker-platform-monitor/Dockerfile +dockers/docker-router-advertiser/Dockerfile +dockers/docker-snmp-sv2/Dockerfile +dockers/docker-teamd/Dockerfile +dockers/docker-sonic-mgmt/Dockerfile +dockers/docker-sonic-telemetry/Dockerfile +platform/*/docker-saiserver-*/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/ + +# Config engine +src/sonic-config-engine/**/*.pyc +src/sonic-config-engine/build +src/sonic-config-engine/sonic_config_engine.egg-info diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000000..915b19cb1372 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,64 @@ +[submodule "sonic-swss-common"] + path = src/sonic-swss-common + url = https://github.com/Azure/sonic-swss-common +[submodule "sonic-linux-kernel"] + path = src/sonic-linux-kernel + url = https://github.com/Azure/sonic-linux-kernel +[submodule "sonic-sairedis"] + path = src/sonic-sairedis + url = https://github.com/Azure/sonic-sairedis +[submodule "sonic-swss"] + path = src/sonic-swss + url = https://github.com/Azure/sonic-swss +[submodule "src/p4c-bm/p4c-bm"] + path = platform/p4/p4c-bm/p4c-bm + url = https://github.com/krambn/p4c-bm +[submodule "src/p4-hlir/p4-hlir"] + path = platform/p4/p4-hlir/p4-hlir + url = https://github.com/p4lang/p4-hlir +[submodule "quagga"] + path = src/sonic-quagga + url = https://github.com/Azure/sonic-quagga + branch = debian/0.99.24.1 +[submodule "sonic-dbsyncd"] + path = src/sonic-dbsyncd + url = https://github.com/Azure/sonic-dbsyncd +[submodule "src/sonic-py-swsssdk"] + path = src/sonic-py-swsssdk + url = https://github.com/Azure/sonic-py-swsssdk.git +[submodule "src/sonic-snmpagent"] + path = src/sonic-snmpagent + url = https://github.com/Azure/sonic-snmpagent +[submodule "src/ptf"] + path = src/ptf + url = https://github.com/p4lang/ptf.git +[submodule "src/sonic-utilities"] + path = src/sonic-utilities + url = https://github.com/Azure/sonic-utilities +[submodule "platform/broadcom/sonic-platform-modules-arista"] + path = platform/broadcom/sonic-platform-modules-arista + url = https://github.com/aristanetworks/sonic +[submodule "src/sonic-platform-common"] + path = src/sonic-platform-common + url = https://github.com/Azure/sonic-platform-common +[submodule "src/sonic-platform-daemons"] + path = src/sonic-platform-daemons + url = https://github.com/Azure/sonic-platform-daemons +[submodule "src/sonic-frr/frr"] + path = src/sonic-frr/frr + url = https://github.com/Azure/sonic-frr.git +[submodule "platform/p4/p4-hlir/p4-hlir-v1.1"] + path = platform/p4/p4-hlir/p4-hlir-v1.1 + url = https://github.com/p4lang/p4-hlir.git +[submodule "platform/p4/SAI-P4-BM"] + path = platform/p4/SAI-P4-BM + url = https://github.com/Mellanox/SAI-P4-BM.git +[submodule "platform/barefoot/sonic-platform-modules-arista"] + path = platform/barefoot/sonic-platform-modules-arista + url = https://github.com/aristanetworks/sonic +[submodule "platform/mellanox/hw-management/hw-mgmt"] + path = platform/mellanox/hw-management/hw-mgmt + url = https://github.com/Mellanox/hw-mgmt/ +[submodule "src/redis-dump-load"] + path = src/redis-dump-load + url = https://github.com/p/redis-dump-load.git diff --git a/Makefile b/Makefile new file mode 100644 index 000000000000..4bc42cd3728c --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +# SONiC make file + +NOSTRETCH ?= 0 + +%:: + @echo "+++ --- Making $@ --- +++" +ifeq ($(NOSTRETCH), 0) + BLDENV=stretch make -f Makefile.work stretch +endif + make -f Makefile.work $@ + +stretch: + @echo "+++ Making $@ +++" +ifeq ($(NOSTRETCH), 0) + BLDENV=stretch make -f Makefile.work stretch +endif + +clean reset init configure showtag sonic-slave-build sonic-slave-bash : + @echo "+++ Making $@ +++" + make -f Makefile.work $@ diff --git a/Makefile.work b/Makefile.work new file mode 100644 index 000000000000..6c4828134a8a --- /dev/null +++ b/Makefile.work @@ -0,0 +1,177 @@ +############################################################################### +## Wrapper for starting make inside sonic-slave container +# +# Supported parameters: +# +# * PLATFORM: Specific platform we wish to build images for. +# * BUILD_NUMBER: Desired version-number to pass to the building-system. +# * ENABLE_DHCP_GRAPH_SERVICE: Enables get-graph service to fetch minigraph files +# through http. +# * SHUTDOWN_BGP_ON_START: Sets admin-down state for all bgp peerings after restart. +# * ENABLE_PFCWD_ON_START: Enable PFC Watchdog (PFCWD) on server-facing ports +# * by default for TOR switch. +# * ENABLE_SYNCD_RPC: Enables rpc-based syncd builds. +# * INSTALL_DEBUG_TOOLS: Install debug tools and debug symbol packeages. +# * USERNAME: Desired username -- default at rules/config +# * PASSWORD: Desired password -- default at rules/config +# * KEEP_SLAVE_ON: Keeps slave container up and active after building process concludes. +# * Note that rm=true is still set, so once user quits from the docker +# * session, the docker will be removed. +# * Please note that with current Stretch build structure, +# * user of KEEP_SLAVE_ON feature will have to be conscious +# * about which docker to stay inside after build is done. +# * - If user desires to stay inside Stretch docker, please issue +# * make KEEP_SLAVE_ON=yes stretch +# * - If user desires to stay inside Jessie docker, please issue +# * (a successful "make stretch" may be needed before the following command) +# * make NOSTRETCH=1 KEEP_SLAVE_ON=yes +# * SOURCE_FOLDER: host path to be mount as /var/$(USER)/src, only effective when KEEP_SLAVE_ON=yes +# * SONIC_BUILD_JOBS: Specifying number of concurrent build job(s) to run +# * KERNEL_PROCURE_METHOD: Specifying method of obtaining kernel Debian package: download or build +# +############################################################################### + +SHELL = /bin/bash + +USER := $(shell id -un) +PWD := $(shell pwd) + +ifeq ($(USER), root) +$(error Add your user account to docker group and use your user account to make. root or sudo are not supported!) +endif + +# Remove lock file in case previous run was forcefully stopped +$(shell rm -f .screen) + +MAKEFLAGS += -B + +ifeq ($(BLDENV), stretch) +SLAVE_BASE_TAG = $(shell sha1sum sonic-slave-stretch/Dockerfile | awk '{print substr($$1,0,11);}') +SLAVE_TAG = $(shell cat sonic-slave-stretch/Dockerfile.user sonic-slave-stretch/Dockerfile | sha1sum | awk '{print substr($$1,0,11);}') +SLAVE_BASE_IMAGE = sonic-slave-stretch-base +SLAVE_IMAGE = sonic-slave-stretch-$(USER) +SLAVE_DIR = sonic-slave-stretch +else +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) +SLAVE_DIR = sonic-slave +endif + +OVERLAY_MODULE_CHECK := lsmod | grep "^overlay " > /dev/null 2>&1 || (echo "ERROR: Module 'overlay' not loaded. Try running 'sudo modprobe overlay'."; exit 1) + +BUILD_TIMESTAMP := $(shell date +%Y%m%d\.%H%M%S) + +ifeq ($(DOCKER_BUILDER_MOUNT),) +override DOCKER_BUILDER_MOUNT := "$(PWD):/sonic" +endif + +ifeq ($(DOCKER_BUILDER_WORKDIR),) +override DOCKER_BUILDER_WORKDIR := "/sonic" +endif + +DOCKER_RUN := docker run --rm=true --privileged \ + -v $(DOCKER_BUILDER_MOUNT) \ + -w $(DOCKER_BUILDER_WORKDIR) \ + -e "http_proxy=$(http_proxy)" \ + -e "https_proxy=$(https_proxy)" \ + -i$(if $(TERM),t,) + +include rules/config + +ifeq ($(SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD), y) + DOCKER_RUN += -v /var/run/docker.sock:/var/run/docker.sock +endif + +DOCKER_BASE_BUILD = docker build --no-cache \ + -t $(SLAVE_BASE_IMAGE) \ + --build-arg http_proxy=$(http_proxy) \ + --build-arg https_proxy=$(https_proxy) \ + $(SLAVE_DIR) && \ + docker tag $(SLAVE_BASE_IMAGE):latest $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) + +DOCKER_BUILD = docker build --no-cache \ + --build-arg user=$(USER) \ + --build-arg uid=$(shell id -u) \ + --build-arg guid=$(shell id -g) \ + --build-arg hostname=$(shell echo $$HOSTNAME) \ + -t $(SLAVE_IMAGE) \ + -f $(SLAVE_DIR)/Dockerfile.user \ + $(SLAVE_DIR) && \ + docker tag $(SLAVE_IMAGE):latest $(SLAVE_IMAGE):$(SLAVE_TAG) + +SONIC_BUILD_INSTRUCTION := make \ + -f slave.mk \ + PLATFORM=$(PLATFORM) \ + BUILD_NUMBER=$(BUILD_NUMBER) \ + BUILD_TIMESTAMP=$(BUILD_TIMESTAMP) \ + ENABLE_DHCP_GRAPH_SERVICE=$(ENABLE_DHCP_GRAPH_SERVICE) \ + SHUTDOWN_BGP_ON_START=$(SHUTDOWN_BGP_ON_START) \ + SONIC_ENABLE_PFCWD_ON_START=$(ENABLE_PFCWD_ON_START) \ + SONIC_ENABLE_SYNCD_RPC=$(ENABLE_SYNCD_RPC) \ + SONIC_INSTALL_DEBUG_TOOLS=$(INSTALL_DEBUG_TOOLS) \ + PASSWORD=$(PASSWORD) \ + USERNAME=$(USERNAME) \ + SONIC_BUILD_JOBS=$(SONIC_BUILD_JOBS) \ + KERNEL_PROCURE_METHOD=$(KERNEL_PROCURE_METHOD) \ + HTTP_PROXY=$(http_proxy) \ + HTTPS_PROXY=$(https_proxy) \ + SONIC_ENABLE_SYSTEM_TELEMETRY=$(ENABLE_SYSTEM_TELEMETRY) + +.PHONY: sonic-slave-build sonic-slave-bash init reset + +.DEFAULT_GOAL := all + +%:: + @$(OVERLAY_MODULE_CHECK) + @docker inspect --type image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) &> /dev/null || \ + { echo Image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) not found. Building... ; \ + $(DOCKER_BASE_BUILD) ; } + @docker inspect --type image $(SLAVE_IMAGE):$(SLAVE_TAG) &> /dev/null || \ + { echo Image $(SLAVE_IMAGE):$(SLAVE_TAG) not found. Building... ; \ + $(DOCKER_BUILD) ; } +ifeq "$(KEEP_SLAVE_ON)" "yes" + ifdef SOURCE_FOLDER + @$(DOCKER_RUN) -v $(SOURCE_FOLDER):/var/$(USER)/src $(SLAVE_IMAGE):$(SLAVE_TAG) bash -c "$(SONIC_BUILD_INSTRUCTION) $@; /bin/bash" + else + @$(DOCKER_RUN) $(SLAVE_IMAGE):$(SLAVE_TAG) bash -c "$(SONIC_BUILD_INSTRUCTION) $@; /bin/bash" + endif +else + @$(DOCKER_RUN) $(SLAVE_IMAGE):$(SLAVE_TAG) $(SONIC_BUILD_INSTRUCTION) $@ +endif + +sonic-slave-build : + $(DOCKER_BASE_BUILD) + $(DOCKER_BUILD) + +sonic-slave-bash : + @$(OVERLAY_MODULE_CHECK) + @docker inspect --type image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) &> /dev/null || \ + { echo Image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) not found. Building... ; \ + $(DOCKER_BASE_BUILD) ; } + @docker inspect --type image $(SLAVE_IMAGE):$(SLAVE_TAG) &> /dev/null || \ + { echo Image $(SLAVE_IMAGE):$(SLAVE_TAG) not found. Building... ; \ + $(DOCKER_BUILD) ; } + @$(DOCKER_RUN) -t $(SLAVE_IMAGE):$(SLAVE_TAG) bash + +showtag: + @echo $(SLAVE_IMAGE):$(SLAVE_TAG) + @echo $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) + +init : + @git submodule update --init --recursive + @git submodule foreach --recursive '[ -f .git ] && echo "gitdir: $$(realpath --relative-to=. $$(cut -d" " -f2 .git))" > .git' + +reset : + @echo && echo -n "Warning! All local changes will be lost. Proceed? [y/N]: " + @read ans && \ + if [ $$ans == y ]; then \ + git clean -xfdf; \ + git reset --hard; \ + git submodule foreach --recursive git clean -xfdf; \ + git submodule foreach --recursive git reset --hard; \ + git submodule update --init --recursive;\ + else \ + echo "Reset aborted"; \ + fi diff --git a/README.buildsystem.md b/README.buildsystem.md new file mode 100644 index 000000000000..6735e1ce8968 --- /dev/null +++ b/README.buildsystem.md @@ -0,0 +1,209 @@ +# SONiC Buildimage Guide +## Overview +SONiC buildimage is a *GNU make* based environment for build process automation. +It consists of two main parts: + * Backend - collection of makefiles and other helpers that define generic target groups, used by recipes + * Frontend - collection of recipes, that define metadata for each build target + +## Structure +File structure of SONiC Buildimage is as follows: +``` +sonic-buildimage/ + Makefile + slave.mk + sonic-slave/ + Dockerfile + rules/ + config + functions + recipe1.mk + .. + dockers/ + docker1/ + Dockerfile.template + .. + src/ + submodule1/ + .. + package1/ + Makefile + .. + platform/ + vendor1/ + .. + target/ + debs/ + python-wheels/ +``` +### Backend +**Makefile**, **slave.mk** and **sonic-slave/Dockerfile** are the backend of buildimage. +*slave.mk* is the actual makefile. It defines a set of rules for *target groups* (more on that later). +You can find a make rule for every target that is defined in recipe there. +*Makefile* is a wrapper over sonic-slave docker image. + +Every part of build is executed in a docker container called sonic-slave, specifically crafted for this environment. +If build is started for the first time on a particular host, a new sonic-slave image will be built form *sonic-slave/Dockerfile* on the machine. +It might take some time, so be patient. +After that all subsequent make commands will be executed inside this container. +*Makefile* takes every target that is passed to make command and delegates it as an entry point to a container, +making process of running container transparent. + +### Frontend +**rules/** has a collection of recipes for platform independent targets. +Every recipe is a file that describes a metadata of a specific target, that is needed for its build. +You might find **rules/config** very useful, as it is a configuration file for a build system, which enables/disables some tweaks. +**dockers/** directory is a place where you can find Dockerfiles for generic docker images. +**src/** is a place where a source code for generic packages goes. +It has both submodules (simple case, just run dpkg-buildpackage to build), +and directories with more complcated components, that provide their own Makefiles. +**platform/** contains all vendor-specific recipes, submodules etc. +Every **platform/[VENDOR]/** directory is a derived part of buildimage frontend, that defines rules and targets for a concrete vendor. + +### Build output +**target/** is basically a build output. You can find all build artifacts there. + +## Recipes and target groups +Now let's go over a definition of recipes and target groups. +**Recipe** is a small makefile that defines a target and set of variables for building it. +If you want to add a new target to buildimage (.deb package or docker image), you have to create a recipe for this target. +**Target group** is a set of targets that are built according to the same rules. +Every recipe sets a target group to which this target belongs. + +### Recipe example +Lets take a recipe for swsscommon as an example: +```make +# libswsscommon package + +LIBSWSSCOMMON = libswsscommon_1.0.0_amd64.deb +$(LIBSWSSCOMMON)_SRC_PATH = $(SRC_PATH)/sonic-swss-common +$(LIBSWSSCOMMON)_DEPENDS += $(LIBHIREDIS_DEV) $(LIBNL3_DEV) $(LIBNL_GENL3_DEV) \ + $(LIBNL_ROUTE3_DEV) $(LIBNL_NF3_DEV) \ + $(LIBNL_CLI_DEV) +$(LIBSWSSCOMMON)_RDEPENDS += $(LIBHIREDIS) $(LIBNL3) $(LIBNL_GENL3) \ + $(LIBNL_ROUTE3) $(LIBNL_NF3) $(LIBNL_CLI) +SONIC_DPKG_DEBS += $(LIBSWSSCOMMON) + +LIBSWSSCOMMON_DEV = libswsscommon-dev_1.0.0_amd64.deb +$(eval $(call add_derived_package,$(LIBSWSSCOMMON),$(LIBSWSSCOMMON_DEV))) +``` +First we define our package swsscommon. +Then we secify **SRC_PATH** (path to sources), +**DEPENDS** (build dependencies), +and **RDEPENDS** (runtime dependencies for docker installation). +Then we add our target to SONIC_DPKG_DEBS target group. +At the end we define a dev package for swsscommon and make it derived from main one. +Using **add_derived_package** just makes a deep copy of package's metadata, so that we don't have to repeat ourselves. + +### Target groups +**SONIC_DPKG_DEBS** +Main target group for building .deb packages. +Define: +```make +SOME_NEW_DEB = some_new_deb.deb # name of your package +$(SOME_NEW_DEB)_SRC_PATH = $(SRC_PATH)/project_name # path to directory with sources +$(SOME_NEW_DEB)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # build dependencies +$(SOME_NEW_DEB)_RDEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # runtime dependencies +SONIC_DPKG_DEBS += $(SOME_NEW_DEB) # add package to this target group +``` + +**SONIC_PYTHON_STDEB_DEBS** +Same as above, but instead of building package using dpkg-buildpackage it executes `python setup.py --command-packages=stdeb.command bdist_deb`. +Define: +```make +SOME_NEW_DEB = some_new_deb.deb # name of your package +$(SOME_NEW_DEB)_SRC_PATH = $(SRC_PATH)/project_name # path to directory with sources +$(SOME_NEW_DEB)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # build dependencies +$(SOME_NEW_DEB)_RDEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # runtime dependencies +SONIC_PYTHON_STDEB_DEBS += $(SOME_NEW_DEB) # add package to this target group +``` + +**SONIC_MAKE_DEBS** +This is a bit more flexible case. +If you have to do some specific type of build or apply pathes prior to build, just define your own Makefile and add it to buildimage. +Define: +```make +SOME_NEW_DEB = some_new_deb.deb # name of your package +$(SOME_NEW_DEB)_SRC_PATH = $(SRC_PATH)/project_name # path to directory with sources +$(SOME_NEW_DEB)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # build dependencies +$(SOME_NEW_DEB)_RDEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # runtime dependencies +SONIC_MAKE_DEBS += $(SOME_NEW_DEB) # add package to this target group +``` + +If some packages have to be built locally due to some legal issues or they are already prebuilt and available online, you might find next four target groups useful. + +**SONIC_COPY_DEBS** +Those packages will be just copied from specified location on your machine. +Define: +```make +SOME_NEW_DEB = some_new_deb.deb # name of your package +$(SOME_NEW_DEB)_PATH = path/to/some_new_deb.deb # path to file +SONIC_COPY_DEBS += $(SOME_NEW_DEB) # add package to this target group +``` + +**SONIC_COPY_FILES** +Same as above, but applicable for regular files. Use when you need some regular files for installation in docker container. +Define: +```make +SOME_NEW_FILE = some_new_file # name of your file +$(SOME_NEW_FILE)_PATH = path/to/some_new_file # path to file +SONIC_COPY_FILES += $(SOME_NEW_FILE) # add file to this target group +``` + +**SONIC_ONLINE_DEBS** +Target group for debian packages that should be fetched from an online source. +Define: +```make +SOME_NEW_DEB = some_new_deb.deb # name of your package +$(SOME_NEW_DEB)_URL = https://url/to/this/deb.deb # path to file # URL for downloading +SONIC_ONLINE_DEBS += $(SOME_NEW_DEB) # add file to this target group +``` + +**SONIC_ONLINE_FILES** +Target group for regular files that should be fetched from an online source. +Define: +```make +SOME_NEW_FILE = some_new_file # name of your file +$(SOME_NEW_FILE)_URL = https://url/to/this/file # URL for downloading +SONIC_ONLINE_FILES += $(SOME_NEW_FILE) # add file to this target group +``` + +Docker images also have their target groups. +**SONIC_SIMPLE_DOCKER_IMAGES** +As you see from a name of the group, it is intended to build a docker image from a regular Dockerfile. +Define: +```make +SOME_DOCKER = some_docker.gz # name of your docker +$(SOME_DOCKER)_PATH = path/to/your/docker # path to your Dockerfile +SONIC_SIMPLE_DOCKER_IMAGES += $(SOME_DOCKER) # add docker to this group +``` + +**SONIC_DOCKER_IMAGES** +This one is a bit more sophisticated. You can define debian packages from buildimage that will be installed to it, and corresponding Dockerfile will be dinamically generated from a template. +Define: +```make +SOME_DOCKER = some_docker.gz # name of your docker +$(SOME_DOCKER)_PATH = path/to/your/docker # path to your Dockerfile +$(SOME_DOCKER)_DEPENDS += $(SOME_DEB1) $(SOME_DEB2) # .deb packages to install into image +$(SOME_DOCKER)_PYTHON_WHEELS += $(SOME_WHL1) $(SOME_WHL2) # python wheels to install into image +$(SOME_DOCKER)_LOAD_DOCKERS += $(SOME_OTHER_DOCkER) # docker image from which this one is built +SONIC_DOCKER_IMAGES += $(SOME_DOCKER) # add docker to this group +``` + +## Tips & Tricks +Although every target is built inside a sonic-slave container, which exits at the end of build, you can enter bash of sonic-slave using this command: +``` +$ make sonic-slave-bash +``` +It is very useful for debugging when you add a new target and facing some troubles. + +sonic-slave environment is built only once, but if sonic-slave/Dockerfile was updated, you can rebuild it with this command: +``` +$ make sonic-slave-build +``` + +One can print out all available targets by executing the following command: +``` +$ make list +``` + +All target groups are used by one or another recipe, so use those recipes as a reference when adding new ones. diff --git a/README.md b/README.md index d6525945899e..1734cfa83457 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,154 @@ -# Build Switch Images - buildimage +*master*: +Barefoot: [![Barefoot](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-all/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-all) +Broadcom: [![Broadcom](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-all/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-all) +Mellanox: [![Mellanox](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-all/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-all) +Nephos: [![Nephos](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-all/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-all) +P4: [![P4](https://sonic-jenkins.westus2.cloudapp.azure.com/job/p4/job/buildimage-p4-all/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/p4/job/buildimage-p4-all) +VS: [![VS](https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-all/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-all) -# Description -Build an [Open Network Install Environment (ONIE)](https://github.com/opencomputeproject/onie) compatiable network operating system (NOS) installer image for network switches, and also build docker images running inside the NOS. +*201811*: +Broadcom: [![Broadcom](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201811/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201811/) +Barefoot: [![Mellanox](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-201811/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-201811/) +Centec: [![Centec](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-201811/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-201811/) +Nephos: [![Nephos](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201811/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201811/) +Marvell: [![Marvell](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-201811/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-201811/) +Mellanox: [![Mellanox](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201811/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201811/) +VS: [![VS](https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-201811/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-201811) -# Usage -## Build NOS installer image +*201807*: +Broadcom: [![Broadcom](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201807/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201807/) +Barefoot: [![Mellanox](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-201807/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-201807/) +Centec: [![Centec](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-201807/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-201807/) +Nephos: [![Nephos](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201807/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201807/) +Marvell: [![Marvell](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-201807/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-201807/) +Mellanox: [![Mellanox](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201807/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201807/) - ./build_debian USERNAME PASSWORD_ENCRYPTED && ./build_image.sh - -For example, the user name is 'acsadmin' and the password is 'YourPaSsWoRd'. +*201803*: +Broadcom: [![Broadcom](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201803/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201803/) +Cavium: [![Cavium](https://sonic-jenkins.westus2.cloudapp.azure.com/job/cavium/job/buildimage-cavm-201803/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/cavium/job/buildimage-cavm-201803/) +Centec: [![Centec](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-201803/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-201803/) +Nephos: [![Nephos](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201803/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201803/) +Marvell: [![Marvell](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-201803/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-201803/) +Mellanox: [![Mellanox](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201803/badge/icon)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201803/) - ./build_debian.sh "acsadmin" "$(perl -e 'print crypt("YourPaSsWoRd", "salt"),"\n"')" && ./build_image.sh +# sonic-buildimage -The root is disabled, but the created user could sudo. +## Build SONiC Switch Images +# Description -## Build docker images +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) - ./build_docker.sh docker-sswsyncd - ./build_docker.sh docker-database - ./build_docker.sh docker-bgp - ./build_docker.sh docker-snmp - ./build_docker.sh docker-lldp +# Hardware +Any server can be a build image server. We are using a server with 1T hard disk. The OS is Ubuntu 16.04. -# Contribution guide +# Prerequisites -All contributors must sign a contribution license agreement before contributions can be accepted. Contact kasubra@microsoft.com or daloher@microsoft.com. Later this will be automated. +## SAI Version +Please refer to [SONiC roadmap](https://github.com/Azure/SONiC/wiki/Sonic-Roadmap-Planning) on the SAI version for each SONiC release. -### GitHub Workflow +## 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 https://github.com/Azure/sonic-buildimage.git + +## Usage + +To build SONiC installer image and docker images, run the following commands: + + # Ensure the 'overlay' module is loaded on your development system + sudo modprobe overlay + + # Enter the source directory + cd sonic-buildimage + + # (Optional) Checkout a specific branch. By default, it uses master branch + git checkout [branch_name] + + # Execute make init once after cloning the repo, or after fetching remote repo with submodule updates + make init + + # Execute make configure once to configure ASIC + make configure PLATFORM=[ASIC_VENDOR] + + # Build Debian Stretch required targets (Manual execution optional; will also be executed as part of the build) + BLDENV=stretch make stretch + + # Build SONiC image + make all + + **NOTE**: + +- Recommend reserving 50G free space to build one platform. +- Use `http_proxy=[your_proxy] https_proxy=[your_proxy] make` to enable http(s) proxy in the build process. +- Add your user account to `docker` group and use your user account to make. `root` or `sudo` are not supported. + +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 +- PLATFORM=mellanox +- PLATFORM=cavium +- PLATFORM=centec +- PLATFORM=nephos +- 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. + + make configure PLATFORM=broadcom + # build debian stretch required targets + BLDENV=stretch make stretch + # build ONIE image + make target/sonic-broadcom.bin + # build EOS image + make target/sonic-aboot-broadcom.swi + +You may find the rules/config file useful. It contains configuration options for the build process, like adding more verbosity or showing dependencies, username and password for base image etc. + +Every docker image is built and saved to target/ directory. +So, for instance, to build only docker-database, execute: + + make target/docker-database.gz + +Same goes for debian packages, which are under target/debs/: + + make target/debs/swss_1.0.0_amd64.deb + +Every target has a clean target, so in order to clean swss, execute: + + make target/debs/swss_1.0.0_amd64.deb-clean + +It is recommended to use clean targets to clean all packages that are built together, like dev packages for instance. In order to be more familiar with build process and make some changes to it, it is recommended to read this short [Documentation](README.buildsystem.md). + +## Notes: +- If you are running make for the first time, a sonic-slave-${USER} docker image will be built automatically. +This may take a while, but it is a one-time action, so please be patient. + +- The root user account is disabled. However, the created user can sudo. + +- The target directory is ./target, containing the NOS installer image and docker images. + - sonic-generic.bin: SONiC switch installer image (ONIE compatiable) + - sonic-aboot.bin: SONiC switch installer image (Aboot compatiable) + - docker-base.gz: base docker image where other docker images are built from, only used in build process (gzip tar archive) + - docker-database.gz: docker image for in-memory key-value store, used as inter-process communication (gzip tar archive) + - docker-fpm.gz: docker image for quagga with fpm module enabled (gzip tar archive) + - docker-orchagent-brcm.gz: docker image for SWitch State Service (SWSS) on Broadcom platform (gzip tar archive) + - docker-orchagent-cavm.gz: docker image for SWitch State Service (SWSS) on Cavium platform (gzip tar archive) + - docker-orchagent-mlnx.gz: docker image for SWitch State Service (SWSS) on Mellanox platform (gzip tar archive) + - docker-orchagent-nephos.gz: docker image for SWitch State Service (SWSS) on Nephos platform (gzip tar archive) + - docker-syncd-brcm.gz: docker image for the daemon to sync database and Broadcom switch ASIC (gzip tar archive) + - 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-syncd-nephos.gz: docker image for the daemon to sync database and Nephos 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 + +All contributors must sign a contribution license agreement before contributions can be accepted. Contact sonic-cla-agreements@microsoft.com. + +## GitHub Workflow We're following basic GitHub Flow. If you have no idea what we're talking about, check out [GitHub's official guide](https://guides.github.com/introduction/flow/). Note that merge is only performed by the repository maintainer. @@ -59,3 +180,5 @@ For example: * Push your changes to your private fork and do "pull-request" to this repository * Use a pull request to do code review * Use issues to keep track of what is going on + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/ThirdPartyLicenses.txt b/ThirdPartyLicenses.txt index 99bc267e11f9..376506337e79 100644 --- a/ThirdPartyLicenses.txt +++ b/ThirdPartyLicenses.txt @@ -976,3 +976,197 @@ Microsoft is offering you a license to use the following components, to the exte * Public License instead of this License. But first, please read * . */ + +4. apt-clean, apt-gzip-indexes, apt-no-languages imported from docker v1.11.1 +/* + * Apache License + * Version 2.0, January 2004 + * https://www.apache.org/licenses/ + * + * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + * + * 1. Definitions. + * + * "License" shall mean the terms and conditions for use, reproduction, + * and distribution as defined by Sections 1 through 9 of this document. + * + * "Licensor" shall mean the copyright owner or entity authorized by + * the copyright owner that is granting the License. + * + * "Legal Entity" shall mean the union of the acting entity and all + * other entities that control, are controlled by, or are under common + * control with that entity. For the purposes of this definition, + * "control" means (i) the power, direct or indirect, to cause the + * direction or management of such entity, whether by contract or + * otherwise, or (ii) ownership of fifty percent (50%) or more of the + * outstanding shares, or (iii) beneficial ownership of such entity. + * + * "You" (or "Your") shall mean an individual or Legal Entity + * exercising permissions granted by this License. + * + * "Source" form shall mean the preferred form for making modifications, + * including but not limited to software source code, documentation + * source, and configuration files. + * + * "Object" form shall mean any form resulting from mechanical + * transformation or translation of a Source form, including but + * not limited to compiled object code, generated documentation, + * and conversions to other media types. + * + * "Work" shall mean the work of authorship, whether in Source or + * Object form, made available under the License, as indicated by a + * copyright notice that is included in or attached to the work + * (an example is provided in the Appendix below). + * + * "Derivative Works" shall mean any work, whether in Source or Object + * form, that is based on (or derived from) the Work and for which the + * editorial revisions, annotations, elaborations, or other modifications + * represent, as a whole, an original work of authorship. For the purposes + * of this License, Derivative Works shall not include works that remain + * separable from, or merely link (or bind by name) to the interfaces of, + * the Work and Derivative Works thereof. + * + * "Contribution" shall mean any work of authorship, including + * the original version of the Work and any modifications or additions + * to that Work or Derivative Works thereof, that is intentionally + * submitted to Licensor for inclusion in the Work by the copyright owner + * or by an individual or Legal Entity authorized to submit on behalf of + * the copyright owner. For the purposes of this definition, "submitted" + * means any form of electronic, verbal, or written communication sent + * to the Licensor or its representatives, including but not limited to + * communication on electronic mailing lists, source code control systems, + * and issue tracking systems that are managed by, or on behalf of, the + * Licensor for the purpose of discussing and improving the Work, but + * excluding communication that is conspicuously marked or otherwise + * designated in writing by the copyright owner as "Not a Contribution." + * + * "Contributor" shall mean Licensor and any individual or Legal Entity + * on behalf of whom a Contribution has been received by Licensor and + * subsequently incorporated within the Work. + * + * 2. Grant of Copyright License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * copyright license to reproduce, prepare Derivative Works of, + * publicly display, publicly perform, sublicense, and distribute the + * Work and such Derivative Works in Source or Object form. + * + * 3. Grant of Patent License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * (except as stated in this section) patent license to make, have made, + * use, offer to sell, sell, import, and otherwise transfer the Work, + * where such license applies only to those patent claims licensable + * by such Contributor that are necessarily infringed by their + * Contribution(s) alone or by combination of their Contribution(s) + * with the Work to which such Contribution(s) was submitted. If You + * institute patent litigation against any entity (including a + * cross-claim or counterclaim in a lawsuit) alleging that the Work + * or a Contribution incorporated within the Work constitutes direct + * or contributory patent infringement, then any patent licenses + * granted to You under this License for that Work shall terminate + * as of the date such litigation is filed. + * + * 4. Redistribution. You may reproduce and distribute copies of the + * Work or Derivative Works thereof in any medium, with or without + * modifications, and in Source or Object form, provided that You + * meet the following conditions: + * + * (a) You must give any other recipients of the Work or + * Derivative Works a copy of this License; and + * + * (b) You must cause any modified files to carry prominent notices + * stating that You changed the files; and + * + * (c) You must retain, in the Source form of any Derivative Works + * that You distribute, all copyright, patent, trademark, and + * attribution notices from the Source form of the Work, + * excluding those notices that do not pertain to any part of + * the Derivative Works; and + * + * (d) If the Work includes a "NOTICE" text file as part of its + * distribution, then any Derivative Works that You distribute must + * include a readable copy of the attribution notices contained + * within such NOTICE file, excluding those notices that do not + * pertain to any part of the Derivative Works, in at least one + * of the following places: within a NOTICE text file distributed + * as part of the Derivative Works; within the Source form or + * documentation, if provided along with the Derivative Works; or, + * within a display generated by the Derivative Works, if and + * wherever such third-party notices normally appear. The contents + * of the NOTICE file are for informational purposes only and + * do not modify the License. You may add Your own attribution + * notices within Derivative Works that You distribute, alongside + * or as an addendum to the NOTICE text from the Work, provided + * that such additional attribution notices cannot be construed + * as modifying the License. + * + * You may add Your own copyright statement to Your modifications and + * may provide additional or different license terms and conditions + * for use, reproduction, or distribution of Your modifications, or + * for any such Derivative Works as a whole, provided Your use, + * reproduction, and distribution of the Work otherwise complies with + * the conditions stated in this License. + * + * 5. Submission of Contributions. Unless You explicitly state otherwise, + * any Contribution intentionally submitted for inclusion in the Work + * by You to the Licensor shall be under the terms and conditions of + * this License, without any additional terms or conditions. + * Notwithstanding the above, nothing herein shall supersede or modify + * the terms of any separate license agreement you may have executed + * with Licensor regarding such Contributions. + * + * 6. Trademarks. This License does not grant permission to use the trade + * names, trademarks, service marks, or product names of the Licensor, + * except as required for reasonable and customary use in describing the + * origin of the Work and reproducing the content of the NOTICE file. + * + * 7. Disclaimer of Warranty. Unless required by applicable law or + * agreed to in writing, Licensor provides the Work (and each + * Contributor provides its Contributions) on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied, including, without limitation, any warranties or conditions + * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + * PARTICULAR PURPOSE. You are solely responsible for determining the + * appropriateness of using or redistributing the Work and assume any + * risks associated with Your exercise of permissions under this License. + * + * 8. Limitation of Liability. In no event and under no legal theory, + * whether in tort (including negligence), contract, or otherwise, + * unless required by applicable law (such as deliberate and grossly + * negligent acts) or agreed to in writing, shall any Contributor be + * liable to You for damages, including any direct, indirect, special, + * incidental, or consequential damages of any character arising as a + * result of this License or out of the use or inability to use the + * Work (including but not limited to damages for loss of goodwill, + * work stoppage, computer failure or malfunction, or any and all + * other commercial damages or losses), even if such Contributor + * has been advised of the possibility of such damages. + * + * 9. Accepting Warranty or Additional Liability. While redistributing + * the Work or Derivative Works thereof, You may choose to offer, + * and charge a fee for, acceptance of support, warranty, indemnity, + * or other liability obligations and/or rights consistent with this + * License. However, in accepting such obligations, You may act only + * on Your own behalf and on Your sole responsibility, not on behalf + * of any other Contributor, and only if You agree to indemnify, + * defend, and hold each Contributor harmless for any liability + * incurred by, or claims asserted against, such Contributor by reason + * of your accepting any such warranty or additional liability. + * + * END OF TERMS AND CONDITIONS + * + * Copyright 2013-2016 Docker, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/build_debian.sh b/build_debian.sh index 453a6c1d6cf6..5d438cf249cb 100755 --- a/build_debian.sh +++ b/build_debian.sh @@ -3,26 +3,22 @@ ## an ONIE installer image. ## ## USAGE: -## ./build_debian USERNAME PASSWORD_ENCRYPTED -## PARAMETERS: +## USERNAME=username PASSWORD=password ./build_debian +## ENVIRONMENT: ## USERNAME ## The name of the default admin user -## PASSWORD_ENCRYPTED -## The encrypted password, expected by chpasswd command +## PASSWORD +## The password, expected by chpasswd command ## Default user -USERNAME=$1 [ -n "$USERNAME" ] || { - echo "Error: no or empty USERNAME argument" + echo "Error: no or empty USERNAME" exit 1 } -## Password for the default user, customizable by environment variable -## By default it is an empty password -## You may get a crypted password by: perl -e 'print crypt("YourPaSsWoRd", "salt"),"\n"' -PASSWORD_ENCRYPTED=$2 -[ -n "$PASSWORD_ENCRYPTED" ] || { - echo "Error: no or empty PASSWORD_ENCRYPTED argument" +## Password for the default user +[ -n "$PASSWORD" ] || { + echo "Error: no or empty PASSWORD" exit 1 } @@ -32,10 +28,15 @@ PASSWORD_ENCRYPTED=$2 ## Enable debug output for script set -x -e +## docker engine version (with platform) +DOCKER_VERSION=1.11.1-0~stretch_amd64 +LINUX_KERNEL_VERSION=4.9.0-7 + ## Working directory to prepare the file system FILESYSTEM_ROOT=./fsroot +PLATFORM_DIR=platform ## Hostname for the linux image -HOSTNAME=acs +HOSTNAME=sonic DEFAULT_USERINFO="Default admin user,,," ## Read ONIE image related config file @@ -55,44 +56,46 @@ DEFAULT_USERINFO="Default admin user,,," ## Prepare the file system directory if [[ -d $FILESYSTEM_ROOT ]]; then - sudo rm -r $FILESYSTEM_ROOT || die "Failed to clean chroot directory" + sudo rm -rf $FILESYSTEM_ROOT || die "Failed to clean chroot directory" fi mkdir -p $FILESYSTEM_ROOT +mkdir -p $FILESYSTEM_ROOT/$PLATFORM_DIR +mkdir -p $FILESYSTEM_ROOT/$PLATFORM_DIR/x86_64-grub +touch $FILESYSTEM_ROOT/$PLATFORM_DIR/firsttime ## Build a basic Debian system by debootstrap echo '[INFO] Debootstrap...' -sudo debootstrap --arch amd64 jessie $FILESYSTEM_ROOT http://ftp.us.debian.org/debian +sudo http_proxy=$http_proxy debootstrap --variant=minbase --arch amd64 stretch $FILESYSTEM_ROOT http://debian-archive.trafficmanager.net/debian ## Config hostname and hosts, otherwise 'sudo ...' will complain 'sudo: unable to resolve host ...' sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo '$HOSTNAME' > /etc/hostname" sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo '127.0.0.1 $HOSTNAME' >> /etc/hosts" +sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo '127.0.0.1 localhost' >> /etc/hosts" ## Config basic fstab sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c 'echo "proc /proc proc defaults 0 0" >> /etc/fstab' sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c 'echo "sysfs /sys sysfs defaults 0 0" >> /etc/fstab' +## Setup proxy +[ -n "$http_proxy" ] && sudo /bin/bash -c "echo 'Acquire::http::Proxy \"$http_proxy\";' > $FILESYSTEM_ROOT/etc/apt/apt.conf.d/01proxy" + ## Note: mounting is necessary to makedev and install linux image echo '[INFO] Mount all' ## Output all the mounted device for troubleshooting mount trap_push 'sudo umount $FILESYSTEM_ROOT/proc || true' sudo LANG=C chroot $FILESYSTEM_ROOT mount proc /proc -t proc -clean_sys() { - sudo umount $FILESYSTEM_ROOT/sys/fs/cgroup/* \ - $FILESYSTEM_ROOT/sys/fs/cgroup \ - $FILESYSTEM_ROOT/sys || true -} -trap_push 'sudo umount $FILESYSTEM_ROOT/sys || true' -sudo LANG=C chroot $FILESYSTEM_ROOT mount sysfs /sys -t sysfs ## Pointing apt to public apt mirrors and getting latest packages, needed for latest security updates -sudo cp files/sources.list $FILESYSTEM_ROOT/etc/apt/ +sudo cp files/apt/sources.list $FILESYSTEM_ROOT/etc/apt/ +sudo cp files/apt/apt.conf.d/{81norecommends,apt-{clean,gzip-indexes,no-languages}} $FILESYSTEM_ROOT/etc/apt/apt.conf.d/ +sudo LANG=C chroot $FILESYSTEM_ROOT bash -c 'apt-mark auto `apt-mark showmanual`' ## Note: set lang to prevent locale warnings in your chroot sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y update sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y upgrade echo '[INFO] Install packages for building image' -sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install makedev psmisc +sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install makedev psmisc systemd-sysv ## Create device files echo '[INFO] MAKEDEV' @@ -104,42 +107,75 @@ sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c 'cd /dev && MAKEDEV generic' ## However, 'dpkg -i' plus 'apt-get install -f' will ignore the recommended dependency. So ## we install busybox explicitly sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install busybox -echo '[INFO] Install ACS linux kernel image' +echo '[INFO] Install SONiC linux kernel image' ## Note: duplicate apt-get command to ensure every line return zero -sudo dpkg --root=$FILESYSTEM_ROOT -i deps/initramfs-tools_*.deb || \ +sudo dpkg --root=$FILESYSTEM_ROOT -i target/debs/initramfs-tools-core_*.deb || \ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f -sudo dpkg --root=$FILESYSTEM_ROOT -i deps/linux-image-3.16.0-4-amd64_*.deb || \ +sudo dpkg --root=$FILESYSTEM_ROOT -i target/debs/initramfs-tools_*.deb || \ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f - -## Update initramfs for booting with squashfs+aufs +sudo dpkg --root=$FILESYSTEM_ROOT -i target/debs/linux-image-${LINUX_KERNEL_VERSION}-amd64_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install acl + +## Update initramfs for booting with squashfs+overlay cat files/initramfs-tools/modules | sudo tee -a $FILESYSTEM_ROOT/etc/initramfs-tools/modules > /dev/null +## Hook into initramfs: change fs type from vfat to ext4 on arista switches +sudo mkdir -p $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/ +sudo cp files/initramfs-tools/arista-convertfs $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-convertfs +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-convertfs +sudo cp files/initramfs-tools/mke2fs $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/mke2fs +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/mke2fs +sudo cp files/initramfs-tools/setfacl $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/setfacl +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/setfacl + +# Hook into initramfs: rename the management interfaces on arista switches +sudo cp files/initramfs-tools/arista-net $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-net +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-net + +# Hook into initramfs: resize root partition after migration from another NOS to SONiC on Dell switches +sudo cp files/initramfs-tools/resize-rootfs $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/resize-rootfs +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/resize-rootfs + ## Hook into initramfs: after partition mount and loop file mount ## 1. Prepare layered file system ## 2. Bind-mount docker working directory (docker aufs cannot work over aufs rootfs) sudo cp files/initramfs-tools/union-mount $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/union-mount sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/union-mount +sudo cp files/initramfs-tools/varlog $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/varlog +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/varlog +# Management interface (eth0) dhcp can be optionally turned off (during a migration from another NOS to SONiC) +sudo cp files/initramfs-tools/mgmt-intf-dhcp $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/mgmt-intf-dhcp +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/mgmt-intf-dhcp sudo cp files/initramfs-tools/union-fsck $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/union-fsck sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/union-fsck -sudo chroot $FILESYSTEM_ROOT update-initramfs -u +pushd $FILESYSTEM_ROOT/usr/share/initramfs-tools/scripts/init-bottom && sudo patch -p1 < $OLDPWD/files/initramfs-tools/udev.patch; popd + +## Install latest intel ixgbe driver +sudo cp target/files/ixgbe.ko $FILESYSTEM_ROOT/lib/modules/${LINUX_KERNEL_VERSION}-amd64/kernel/drivers/net/ethernet/intel/ixgbe/ixgbe.ko ## Install docker echo '[INFO] Install docker' -curl -sSL https://get.docker.com/ | sudo LANG=C chroot $FILESYSTEM_ROOT sh -## Remove garbage left by docker installation script -sudo rm $FILESYSTEM_ROOT/etc/apt/sources.list.d/docker.list -sudo chroot $FILESYSTEM_ROOT service docker stop -sudo chroot $FILESYSTEM_ROOT service dbus stop -## Add docker config drop-in to select aufs, otherwise it may other storage driver -## Note: $_ means last argument of last command +## Install apparmor utils since they're missing and apparmor is enabled in the kernel +## Otherwise Docker will fail to start +sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install apparmor +docker_deb_url=https://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_${DOCKER_VERSION}.deb +docker_deb_temp=`mktemp` +trap_push "rm -f $docker_deb_temp" +wget $docker_deb_url -qO $docker_deb_temp +sudo dpkg --root=$FILESYSTEM_ROOT -i $docker_deb_temp || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f + +## Add docker config drop-in to select aufs, otherwise it may select other storage driver sudo mkdir -p $FILESYSTEM_ROOT/etc/systemd/system/docker.service.d/ +## Note: $_ means last argument of last command sudo cp files/docker/docker.service.conf $_ ## Create default user ## Note: user should be in the group with the same name, and also in sudo/docker group sudo LANG=C chroot $FILESYSTEM_ROOT useradd -G sudo,docker $USERNAME -c "$DEFAULT_USERINFO" -m -s /bin/bash ## Create password for the default user -echo $USERNAME:$PASSWORD_ENCRYPTED | sudo LANG=C chroot $FILESYSTEM_ROOT chpasswd -e +echo "$USERNAME:$PASSWORD" | sudo LANG=C chroot $FILESYSTEM_ROOT chpasswd ## Pre-install hardware drivers sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install \ @@ -148,28 +184,161 @@ sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install \ ## Pre-install the fundamental packages ## Note: gdisk is needed for sgdisk in install.sh ## Note: parted is needed for partprobe in install.sh -sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install \ +## Note: ca-certificates is needed for easy_install +## Note: don't install python-apt by pip, older than Debian repo one +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install \ + file \ + ifupdown \ + iproute2 \ + bridge-utils \ + isc-dhcp-client \ sudo \ vim \ tcpdump \ + dbus \ ntp \ + ntpstat \ openssh-server \ python \ python-setuptools \ + monit \ python-apt \ + traceroute \ + iputils-ping \ + net-tools \ + bsdmainutils \ + ca-certificates \ + i2c-tools \ + efibootmgr \ + usbutils \ + pciutils \ + iptables-persistent \ + logrotate \ + curl \ + kexec-tools \ + less \ + unzip \ gdisk \ - parted \ - efibootmgr + sysfsutils \ + grub2-common \ + rsyslog \ + ethtool \ + screen \ + hping3 \ + python-scapy \ + tcptraceroute \ + mtr-tiny \ + locales + +#Adds a locale to a debian system in non-interactive mode +sudo sed -i '/^#.* en_US.* /s/^#//' $FILESYSTEM_ROOT/etc/locale.gen && \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT locale-gen "en_US.UTF-8" +sudo LANG=en_US.UTF-8 DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT update-locale "LANG=en_US.UTF-8" +sudo LANG=C chroot $FILESYSTEM_ROOT bash -c "find /usr/share/i18n/locales/ ! -name 'en_US' -type f -exec rm -f {} +" + +# Install certain fundamental packages from stretch-backports in order to get +# more up-to-date (but potentially less stable) versions +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y -t stretch-backports install \ + picocom + +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y download \ + grub-pc-bin + +sudo mv $FILESYSTEM_ROOT/grub-pc-bin*.deb $FILESYSTEM_ROOT/$PLATFORM_DIR/x86_64-grub + +## Disable kexec supported reboot which was installed by default +sudo sed -i 's/LOAD_KEXEC=true/LOAD_KEXEC=false/' $FILESYSTEM_ROOT/etc/default/kexec + +## Fix ping tools permission so non root user can directly use them +## Note: this is a workaround since aufs doesn't support extended attributes +## Ref: https://github.com/moby/moby/issues/5650#issuecomment-303499489 +## TODO: remove workaround when the overlay filesystem support extended attributes +sudo chmod u+s $FILESYSTEM_ROOT/bin/ping{,6} + +## Remove sshd host keys, and will regenerate on first sshd start +sudo rm -f $FILESYSTEM_ROOT/etc/ssh/ssh_host_*_key* +sudo cp files/sshd/host-ssh-keygen.sh $FILESYSTEM_ROOT/usr/local/bin/ +sudo cp -f files/sshd/sshd.service $FILESYSTEM_ROOT/lib/systemd/system/ssh.service +## Config sshd +sudo augtool --autosave "set /files/etc/ssh/sshd_config/UseDNS no" -r $FILESYSTEM_ROOT +sudo sed -i 's/^ListenAddress ::/#ListenAddress ::/' $FILESYSTEM_ROOT/etc/ssh/sshd_config +sudo sed -i 's/^#ListenAddress 0.0.0.0/ListenAddress 0.0.0.0/' $FILESYSTEM_ROOT/etc/ssh/sshd_config + +## Config monit +sudo sed -i ' + s/^# set logfile syslog/set logfile syslog/; + s/^\s*set logfile \/var/# set logfile \/var/; + s/^# set httpd port/set httpd port/; + s/^# use address localhost/ use address localhost/; + s/^# allow localhost/ allow localhost/; + s/^# allow admin:monit/ allow admin:monit/; + s/^# allow @monit/ allow @monit/; + s/^# allow @users readonly/ allow @users readonly/ + ' $FILESYSTEM_ROOT/etc/monit/monitrc + +sudo tee -a $FILESYSTEM_ROOT/etc/monit/monitrc > /dev/null <<'EOF' +check filesystem root-overlay with path / + if space usage > 90% for 5 times within 10 cycles then alert +check filesystem var-log with path /var/log + if space usage > 90% for 5 times within 10 cycles then alert +check system $HOST + if memory usage > 90% for 5 times within 10 cycles then alert + if cpu usage (user) > 90% for 5 times within 10 cycles then alert + if cpu usage (system) > 90% for 5 times within 10 cycles then alert +EOF + +## Config sysctl +sudo mkdir -p $FILESYSTEM_ROOT/var/core +sudo augtool --autosave " +set /files/etc/sysctl.conf/kernel.core_pattern '|/usr/bin/coredump-compress %e %t %p' + +set /files/etc/sysctl.conf/kernel.softlockup_panic 1 +set /files/etc/sysctl.conf/kernel.panic 10 +set /files/etc/sysctl.conf/fs.suid_dumpable 2 + +set /files/etc/sysctl.conf/net.ipv4.conf.default.forwarding 1 +set /files/etc/sysctl.conf/net.ipv4.conf.all.forwarding 1 +set /files/etc/sysctl.conf/net.ipv4.conf.eth0.forwarding 0 + +set /files/etc/sysctl.conf/net.ipv4.conf.default.arp_accept 0 +set /files/etc/sysctl.conf/net.ipv4.conf.default.arp_announce 0 +set /files/etc/sysctl.conf/net.ipv4.conf.default.arp_filter 0 +set /files/etc/sysctl.conf/net.ipv4.conf.default.arp_notify 0 +set /files/etc/sysctl.conf/net.ipv4.conf.default.arp_ignore 0 +set /files/etc/sysctl.conf/net.ipv4.conf.all.arp_accept 0 +set /files/etc/sysctl.conf/net.ipv4.conf.all.arp_announce 1 +set /files/etc/sysctl.conf/net.ipv4.conf.all.arp_filter 0 +set /files/etc/sysctl.conf/net.ipv4.conf.all.arp_notify 1 +set /files/etc/sysctl.conf/net.ipv4.conf.all.arp_ignore 2 + +set /files/etc/sysctl.conf/net.ipv4.neigh.default.base_reachable_time_ms 1800000 +set /files/etc/sysctl.conf/net.ipv6.neigh.default.base_reachable_time_ms 1800000 + +set /files/etc/sysctl.conf/net.ipv6.conf.default.forwarding 1 +set /files/etc/sysctl.conf/net.ipv6.conf.all.forwarding 1 +set /files/etc/sysctl.conf/net.ipv6.conf.eth0.forwarding 0 + +set /files/etc/sysctl.conf/net.ipv6.conf.default.accept_dad 0 +set /files/etc/sysctl.conf/net.ipv6.conf.all.accept_dad 0 +set /files/etc/sysctl.conf/net.ipv6.conf.eth0.accept_dad 0 + +set /files/etc/sysctl.conf/net.ipv6.conf.default.keep_addr_on_down 1 +set /files/etc/sysctl.conf/net.ipv6.conf.all.keep_addr_on_down 1 +set /files/etc/sysctl.conf/net.ipv6.conf.eth0.keep_addr_on_down 1 + +set /files/etc/sysctl.conf/net.ipv6.conf.eth0.accept_ra_defrtr 0 + +set /files/etc/sysctl.conf/net.core.rmem_max 2097152 +set /files/etc/sysctl.conf/net.core.wmem_max 2097152 +" -r $FILESYSTEM_ROOT ## docker-py is needed by Ansible docker module -sudo LANG=C chroot $FILESYSTEM_ROOT easy_install pip -sudo LANG=C chroot $FILESYSTEM_ROOT pip install 'docker-py==1.6.0' -## Remove pip which is unnecessary in the base image -sudo LANG=C chroot $FILESYSTEM_ROOT pip uninstall -y pip +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT easy_install pip +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install 'docker-py==1.6.0' +## Note: keep pip installed for maintainance purpose -echo '[INFO] Install apt-transport-sftp package from deps directory' -sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install libssh2-1 -sudo dpkg --root=$FILESYSTEM_ROOT -i deps/apt-transport-sftp_*.deb +## Create /var/run/redis folder for docker-database to mount +sudo mkdir -p $FILESYSTEM_ROOT/var/run/redis ## Config DHCP for eth0 sudo tee -a $FILESYSTEM_ROOT/etc/network/interfaces > /dev/null < /dev/null <&2 - exit 1 +usage() { + cat >&2 <&2 + usage + exit 1 + ;; + esac +done +shift "$((OPTIND - 1))" -## File name for docker image -docker_image_gz=$docker_image_name.gz +## Dockerfile directory +DOCKER_BUILD_DIR=dockers/$1 +shift 1 -[ -n "$docker_image_gz" ] || { - echo "Error: Output docker image filename is empty" +[ -f "$DOCKER_BUILD_DIR"/Dockerfile ] || { + echo "Invalid DOCKER_BUILD_DIR directory" >&2 exit 1 } -function cleanup { - rm -rf $DOCKER_BUILD_DIR/files - rm -rf $DOCKER_BUILD_DIR/deps - docker rmi -f $docker_image_name || true +[ -n "$docker_image_name" ] || { + docker_image_name=$(basename $DOCKER_BUILD_DIR) } -trap cleanup exit ## Copy dependencies ## Note: Dockerfile ADD doesn't support reference files outside the folder, so copy it locally -mkdir -p $DOCKER_BUILD_DIR/deps -cp deps/*.deb $DOCKER_BUILD_DIR/deps +if ls deps/* 1>/dev/null 2>&1; then + trap_push "rm -rf $DOCKER_BUILD_DIR/deps" + mkdir -p $DOCKER_BUILD_DIR/deps + cp -r deps/* $DOCKER_BUILD_DIR/deps +fi ## Copy the suggested Debian sources ## ref: https://wiki.debian.org/SourcesList -mkdir -p $DOCKER_BUILD_DIR/files -cp files/sources.list $DOCKER_BUILD_DIR/files -docker build -t $docker_image_name $DOCKER_BUILD_DIR - -if [ -n "$REGISTRY_SERVER" ] && [ -n "$REGISTRY_PORT" ]; then - ## Add registry information as tag, so will push as latest - ## Temporarily add -f option to prevent error message of Docker engine version < 1.10.0 - docker tag -f $docker_image_name $REGISTRY_SERVER:$REGISTRY_PORT/$docker_image_name - - ## Login the docker image registry server - ## Note: user name and password are passed from command line, use fake email address to bypass login check - docker login -u $REGISTRY_USERNAME -p "$REGISTRY_PASSWD" -e "@" $REGISTRY_SERVER:$REGISTRY_PORT - docker push $REGISTRY_SERVER:$REGISTRY_PORT/$docker_image_name +trap_push "rm -rf $DOCKER_BUILD_DIR/deps" +cp -r files $DOCKER_BUILD_DIR/files +docker_try_rmi $docker_image_name + +## Build the docker image +docker build --no-cache -t $docker_image_name $DOCKER_BUILD_DIR +## Get the ID of the built image +## Note: inspect output has quotation characters, so sed to remove it as an argument +image_id=$(docker inspect --format="{{json .Id}}" $docker_image_name | sed -e 's/^"//' -e 's/"$//') + +## Flatten the image by importing an exported container on this image +## Note: it will squash the image with only one layer and lost all metadata such as ENTRYPOINT, +## so apply only to the base image +## TODO: wait docker-squash supporting Docker 1.10+ +## ref: https://github.com/jwilder/docker-squash/issues/45 +if [ "$docker_image_name" = "docker-base" ]; then + ## Run old image in a container + tmp_container=$(docker run -d ${docker_image_name} /bin/bash) + ## Export the container's filesystem, then import as a new image + docker export $tmp_container | docker import - ${docker_image_name} + ## Remove the container + docker rm -f $tmp_container || true + ## Remove the old image + docker rmi -f $image_id || true fi -docker save $docker_image_name | gzip -c > $docker_image_gz +## Save the docker image in a gz file +mkdir -p target +docker save $docker_image_name | gzip -c > target/$docker_image_name.gz + +if [ -n "$1" ]; then + ./push_docker.sh target/$docker_image_name.gz $@ $docker_image_tag +fi diff --git a/build_image.sh b/build_image.sh index 34e5d783956b..706f4e937cf6 100755 --- a/build_image.sh +++ b/build_image.sh @@ -12,33 +12,127 @@ exit 1 } -## Retrieval short version of Git revision hash for partition metadata -[ -z $(git status --untracked-files=no -s) ] || { - echo "Error: There is local changes not committed to git repo. Cannot get a revision hash for partition metadata." - exit 1 -} -GIT_REVISION=$(git rev-parse --short HEAD) +IMAGE_VERSION=$(. functions.sh && sonic_get_version) + +generate_onie_installer_image() +{ + # Copy platform-specific ONIE installer config files where onie-mk-demo.sh expects them + rm -rf ./installer/x86_64/platforms/ + mkdir -p ./installer/x86_64/platforms/ + for VENDOR in `ls ./device`; do + for PLATFORM in `ls ./device/$VENDOR`; do + if [ -f ./device/$VENDOR/$PLATFORM/installer.conf ]; then + cp ./device/$VENDOR/$PLATFORM/installer.conf ./installer/x86_64/platforms/$PLATFORM + fi + + done + done -sudo rm -f $OUTPUT_ONIE_IMAGE -if [ "$TARGET_MACHINE" = "generic" ]; then ## Generate an ONIE installer image ## Note: Don't leave blank between lines. It is single line command. - CONSOLE_SPEED=9600 \ - CONSOLE_DEV=0 \ - CONSOLE_FLAG=0 \ - CONSOLE_PORT=0x3f8 \ ./onie-mk-demo.sh $TARGET_PLATFORM $TARGET_MACHINE $TARGET_PLATFORM-$TARGET_MACHINE-$ONIEIMAGE_VERSION \ - installer $TARGET_MACHINE/platform.conf $OUTPUT_ONIE_IMAGE OS $GIT_REVISION $ONIE_IMAGE_PART_SIZE \ + installer platform/$TARGET_MACHINE/platform.conf $OUTPUT_ONIE_IMAGE OS $IMAGE_VERSION $ONIE_IMAGE_PART_SIZE \ $ONIE_INSTALLER_PAYLOAD +} + +if [ "$IMAGE_TYPE" = "onie" ]; then + echo "Build ONIE installer" + mkdir -p `dirname $OUTPUT_ONIE_IMAGE` + sudo rm -f $OUTPUT_ONIE_IMAGE + + generate_onie_installer_image + +## Build a raw partition dump image using the ONIE installer that can be +## used to dd' in-lieu of using the onie-nos-installer. Used while migrating +## into SONiC from other NOS. +elif [ "$IMAGE_TYPE" = "raw" ]; then + + echo "Build RAW image" + mkdir -p `dirname $OUTPUT_RAW_IMAGE` + sudo rm -f $OUTPUT_RAW_IMAGE + + generate_onie_installer_image + + echo "Creating SONiC raw partition : $OUTPUT_RAW_IMAGE of size $RAW_IMAGE_DISK_SIZE MB" + fallocate -l "$RAW_IMAGE_DISK_SIZE"M $OUTPUT_RAW_IMAGE + + ## Generate a partition dump that can be used to 'dd' in-lieu of using the onie-nos-installer + ## Run the installer + ## The 'build' install mode of the installer is used to generate this dump. + sudo chmod a+x $OUTPUT_ONIE_IMAGE + sudo ./$OUTPUT_ONIE_IMAGE + + [ -r $OUTPUT_RAW_IMAGE ] || { + echo "Error : $OUTPUT_RAW_IMAGE not generated!" + exit 1 + } + + gzip $OUTPUT_RAW_IMAGE + + [ -r $OUTPUT_RAW_IMAGE.gz ] || { + echo "Error : gzip $OUTPUT_RAW_IMAGE failed!" + exit 1 + } + + mv $OUTPUT_RAW_IMAGE.gz $OUTPUT_RAW_IMAGE + echo "The compressed raw image is in $OUTPUT_RAW_IMAGE" + +elif [ "$IMAGE_TYPE" = "kvm" ]; then + + echo "Build KVM image" + KVM_IMAGE_DISK=${OUTPUT_KVM_IMAGE%.gz} + sudo rm -f $KVM_IMAGE_DISK $KVM_IMAGE_DISK.gz + + generate_onie_installer_image + + SONIC_USERNAME=$USERNAME PASSWD=$PASSWORD sudo -E ./build_kvm_image.sh $KVM_IMAGE_DISK $onie_recovery_image $OUTPUT_ONIE_IMAGE $KVM_IMAGE_DISK_SIZE + + if [ $? -ne 0 ]; then + echo "Error : build kvm image failed" + exit 1 + fi + + [ -r $KVM_IMAGE_DISK ] || { + echo "Error : $KVM_IMAGE_DISK not generated!" + exit 1 + } + + gzip $KVM_IMAGE_DISK + + [ -r $KVM_IMAGE_DISK.gz ] || { + echo "Error : gzip $KVM_IMAGE_DISK failed!" + exit 1 + } + + echo "The compressed kvm image is in $KVM_IMAGE_DISK.gz" + ## Use 'aboot' as target machine category which includes Aboot as bootloader -elif [ "$TARGET_MACHINE" = "aboot" ]; then - ## Add Aboot boot0 file into the image - cp $ONIE_INSTALLER_PAYLOAD $OUTPUT_ONIE_IMAGE - pushd files/Aboot && sudo zip -g $OLDPWD/$OUTPUT_ONIE_IMAGE boot0; popd - echo "$GIT_REVISION" >> .imagehash - zip -g $OUTPUT_ONIE_IMAGE .imagehash +elif [ "$IMAGE_TYPE" = "aboot" ]; then + echo "Build Aboot installer" + mkdir -p `dirname $OUTPUT_ABOOT_IMAGE` + sudo rm -f $OUTPUT_ABOOT_IMAGE + sudo rm -f $ABOOT_BOOT_IMAGE + ## Add main payload + cp $ONIE_INSTALLER_PAYLOAD $OUTPUT_ABOOT_IMAGE + ## Add Aboot boot0 file + j2 -f env files/Aboot/boot0.j2 ./onie-image.conf > files/Aboot/boot0 + sed -i -e "s/%%IMAGE_VERSION%%/$IMAGE_VERSION/g" files/Aboot/boot0 + pushd files/Aboot && zip -g $OLDPWD/$OUTPUT_ABOOT_IMAGE boot0; popd + pushd files/Aboot && zip -g $OLDPWD/$ABOOT_BOOT_IMAGE boot0; popd + echo "$IMAGE_VERSION" >> .imagehash + zip -g $OUTPUT_ABOOT_IMAGE .imagehash + zip -g $ABOOT_BOOT_IMAGE .imagehash rm .imagehash + echo "SWI_VERSION=42.0.0" > version + echo "SWI_MAX_HWEPOCH=2" >> version + echo "SWI_VARIANT=US" >> version + zip -g $OUTPUT_ABOOT_IMAGE version + zip -g $ABOOT_BOOT_IMAGE version + rm version + + zip -g $OUTPUT_ABOOT_IMAGE $ABOOT_BOOT_IMAGE + rm $ABOOT_BOOT_IMAGE else - echo "Error: Non supported target platform: $TARGET_PLATFORM" + echo "Error: Non supported image type $IMAGE_TYPE" exit 1 fi diff --git a/build_kvm_image.sh b/build_kvm_image.sh new file mode 100755 index 000000000000..b08db96f573c --- /dev/null +++ b/build_kvm_image.sh @@ -0,0 +1,77 @@ +#!/bin/sh -ex + +# Copyright (C) 2014 Curt Brune +# +# SPDX-License-Identifier: GPL-2.0 + +MEM=2048 +DISK=$1 +ONIE_RECOVERY_ISO=$2 +INSTALLER=$3 +DISK_SIZE=$4 + +INSTALLER_DISK="./sonic-installer.img" + +# VM will listen on telnet port $KVM_PORT +KVM_PORT=9000 + +on_exit() +{ + rm -f $kvm_log +} + +kvm_log=$(mktemp) +trap on_exit EXIT + +create_disk() +{ + echo "Creating SONiC kvm disk : $DISK of size $DISK_SIZE GB" + qemu-img create -f qcow2 $DISK ${DISK_SIZE}G +} + +prepare_installer_disk() +{ + fallocate -l 1024M $INSTALLER_DISK + + mkfs.vfat $INSTALLER_DISK + + tmpdir=$(mktemp -d) + + mount -o loop $INSTALLER_DISK $tmpdir + + cp $INSTALLER $tmpdir/onie-installer.bin + + umount $tmpdir +} + +create_disk +prepare_installer_disk + +/usr/bin/kvm -m $MEM \ + -name "onie" \ + -boot "order=cd,once=d" -cdrom "$ONIE_RECOVERY_ISO" \ + -device e1000,netdev=onienet \ + -netdev user,id=onienet,hostfwd=:0.0.0.0:3041-:22 \ + -vnc 0.0.0.0:0 \ + -vga std \ + -drive file=$DISK,media=disk,if=virtio,index=0 \ + -drive file=$INSTALLER_DISK,if=virtio,index=1 \ + -serial telnet:127.0.0.1:$KVM_PORT,server > $kvm_log 2>&1 & + +kvm_pid=$! + +sleep 2.0 + +[ -d "/proc/$kvm_pid" ] || { + echo "ERROR: kvm died." + cat $kvm_log + exit 1 +} + +echo "to kill kvm: sudo kill $kvm_pid" + +./check_install.py -u $SONIC_USERNAME -P $PASSWD -p $KVM_PORT + +kill $kvm_pid + +exit 0 diff --git a/check_install.py b/check_install.py new file mode 100755 index 000000000000..09979f61e4ba --- /dev/null +++ b/check_install.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python + +import pexpect +import argparse +import sys +import time + +def main(): + + parser = argparse.ArgumentParser(description='test_login cmdline parser') + parser.add_argument('-u', default="admin", help='login user name') + parser.add_argument('-P', default="YourPaSsWoRd", help='login password') + parser.add_argument('-p', type=int, default=9000, help='local port') + + args = parser.parse_args() + + KEY_UP = '\x1b[A' + KEY_DOWN = '\x1b[B' + KEY_RIGHT = '\x1b[C' + KEY_LEFT = '\x1b[D' + + login_prompt = 'sonic login:' + passwd_prompt = 'Password:' + cmd_prompt = "%s@sonic:~\$ $" % args.u + grub_selection = "The highlighted entry will be executed" + + p = pexpect.spawn("telnet 127.0.0.1 %s" % args.p, timeout=600, logfile=sys.stdout) + + # select ONIE embed + p.expect(grub_selection) + p.sendline(KEY_DOWN) + + # install sonic image + while True: + i = p.expect([login_prompt, passwd_prompt, grub_selection, cmd_prompt]) + if i == 0: + # send user name + p.sendline(args.u) + elif i == 1: + # send password + p.sendline(args.P) + elif i == 2: + # select onie install + p.sendline() + else: + break + + # check version + time.sleep(5) + p.sendline('show version') + p.expect([cmd_prompt]) + p.sendline('show ip bgp sum') + p.expect([cmd_prompt]) + p.sendline('sync') + p.expect([cmd_prompt]) + +if __name__ == '__main__': + main() diff --git a/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/port_config.ini b/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/port_config.ini new file mode 100755 index 000000000000..f41bf2ef648f --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/port_config.ini @@ -0,0 +1,73 @@ +# name lanes alias index +Ethernet0 13 tenGigE0 0 +Ethernet1 14 tenGigE1 1 +Ethernet2 15 tenGigE2 2 +Ethernet3 16 tenGigE3 3 +Ethernet4 21 tenGigE4 4 +Ethernet5 22 tenGigE5 5 +Ethernet6 23 tenGigE6 6 +Ethernet7 24 tenGigE7 7 +Ethernet8 25 tenGigE8 8 +Ethernet9 26 tenGigE9 9 +Ethernet10 27 tenGigE10 10 +Ethernet11 28 tenGigE11 11 +Ethernet12 29 tenGigE12 12 +Ethernet13 30 tenGigE13 13 +Ethernet14 31 tenGigE14 14 +Ethernet15 32 tenGigE15 15 +Ethernet16 45 tenGigE16 16 +Ethernet17 46 tenGigE17 17 +Ethernet18 47 tenGigE18 18 +Ethernet19 48 tenGigE19 19 +Ethernet20 49 tenGigE20 20 +Ethernet21 50 tenGigE21 21 +Ethernet22 51 tenGigE22 22 +Ethernet23 52 tenGigE23 23 +Ethernet24 53 tenGigE24 24 +Ethernet25 54 tenGigE25 25 +Ethernet26 55 tenGigE26 26 +Ethernet27 56 tenGigE27 27 +Ethernet28 57 tenGigE28 28 +Ethernet29 58 tenGigE29 29 +Ethernet30 59 tenGigE30 30 +Ethernet31 60 tenGigE31 31 +Ethernet32 61 tenGigE32 32 +Ethernet33 62 tenGigE33 33 +Ethernet34 63 tenGigE34 34 +Ethernet35 64 tenGigE35 35 +Ethernet36 65 tenGigE36 36 +Ethernet37 66 tenGigE37 37 +Ethernet38 67 tenGigE38 38 +Ethernet39 68 tenGigE39 39 +Ethernet40 69 tenGigE40 40 +Ethernet41 70 tenGigE41 41 +Ethernet42 71 tenGigE42 42 +Ethernet43 72 tenGigE43 43 +Ethernet44 73 tenGigE44 44 +Ethernet45 74 tenGigE45 45 +Ethernet46 75 tenGigE46 46 +Ethernet47 76 tenGigE47 47 +Ethernet48 97 tenGigE48 48 +Ethernet49 98 tenGigE49 49 +Ethernet50 99 tenGigE50 50 +Ethernet51 100 tenGigE51 51 +Ethernet52 101 tenGigE52 52 +Ethernet53 102 tenGigE53 53 +Ethernet54 103 tenGigE54 54 +Ethernet55 104 tenGigE55 55 +Ethernet56 81 tenGigE56 56 +Ethernet57 82 tenGigE57 57 +Ethernet58 83 tenGigE58 58 +Ethernet59 84 tenGigE59 59 +Ethernet60 105 tenGigE60 60 +Ethernet61 106 tenGigE61 61 +Ethernet62 107 tenGigE62 62 +Ethernet63 108 tenGigE63 63 +Ethernet64 109 tenGigE64 64 +Ethernet65 110 tenGigE65 65 +Ethernet66 111 tenGigE66 66 +Ethernet67 112 tenGigE67 67 +Ethernet68 77 tenGigE68 68 +Ethernet69 78 tenGigE69 69 +Ethernet70 79 tenGigE70 70 +Ethernet71 80 tenGigE71 71 diff --git a/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/sai.profile b/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/sai.profile new file mode 100755 index 000000000000..aec436d22608 --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-as5712-72x10G.config.bcm diff --git a/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/td2-as5712-72x10G.config.bcm b/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/td2-as5712-72x10G.config.bcm new file mode 100644 index 000000000000..85ad634792c5 --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/td2-as5712-72x10G.config.bcm @@ -0,0 +1,144 @@ +os=unix +bcm_stat_flags=0 +parity_enable=0 +parity_correction=0 + +l2_mem_entries=163840 +l3_mem_entries=81920 +mmu_lossless=0 +lls_num_l2uc=12 +module_64ports=0 + +#SFI +serdes_if_type=9 + +port_init_cl72=0 +phy_an_c73=5 # TSCMOD_CL73_CL37 + +#sdk6.5.5 only supports 156(default) or 125 +#xgxs_lcpll_xtal_refclk=1 +tslam_dma_enable=1 +table_dma_enable=1 + +#for 72 ports with 48 10G ports and 6 40G ports for breakout mode +pbmp_oversubscribe=0x1fffffffffffffffffe +pbmp_xport_xe=0x1fffffffffffffffffe + +rate_ext_mdio_divisor=96 + +#SFP+ 1-4 from WC3 +portmap_1=13:10 +portmap_2=14:10 +portmap_3=15:10 +portmap_4=16:10 + +#SFP+ 5-8 from WC5 +portmap_5=21:10 +portmap_6=22:10 +portmap_7=23:10 +portmap_8=24:10 + +#SFP+ 9-12 from WC6 +portmap_9=25:10 +portmap_10=26:10 +portmap_11=27:10 +portmap_12=28:10 + +#SFP+ 13-16 from WC7 +portmap_13=29:10 +portmap_14=30:10 +portmap_15=31:10 +portmap_16=32:10 + +#SFP+ 17-20 from WC11 +portmap_17=45:10 +portmap_18=46:10 +portmap_19=47:10 +portmap_20=48:10 + +#SFP+ 21-24 from WC12 +portmap_21=49:10 +portmap_22=50:10 +portmap_23=51:10 +portmap_24=52:10 + +#SFP+ 25-28 from WC13 +portmap_25=53:10 +portmap_26=54:10 +portmap_27=55:10 +portmap_28=56:10 + +#SFP+ 29-32 from WC14 +portmap_29=57:10 +portmap_30=58:10 +portmap_31=59:10 +portmap_32=60:10 + +#SFP+ 33-36 from WC15 +portmap_33=61:10 +portmap_34=62:10 +portmap_35=63:10 +portmap_36=64:10 + +#SFP+ 37-40 from WC16 +portmap_37=65:10 +portmap_38=66:10 +portmap_39=67:10 +portmap_40=68:10 + +#SFP+ 41-44 from WC17 +portmap_41=69:10 +portmap_42=70:10 +portmap_43=71:10 +portmap_44=72:10 + +#SFP+ 45-48 from WC18 +portmap_45=73:10 +portmap_46=74:10 +portmap_47=75:10 +portmap_48=76:10 + +# QSFP+ 49/WC24/port 49 +portmap_49=97:10 +portmap_50=98:10 +portmap_51=99:10 +portmap_52=100:10 + +# QSFP+ 51/WC25/port 50 +portmap_53=101:10 +portmap_54=102:10 +portmap_55=103:10 +portmap_56=104:10 + +# QSFP+ 53/WC20/port 51 +portmap_57=81:10 +portmap_58=82:10 +portmap_59=83:10 +portmap_60=84:10 + +# QSFP+ 50/WC26/port 52 +portmap_61=105:10 +portmap_62=106:10 +portmap_63=107:10 +portmap_64=108:10 + +# QSFP+ 52/WC27/port 53 +portmap_65=109:10 +portmap_66=110:10 +portmap_67=111:10 +portmap_68=112:10 + +# QSFP+ 54/WC19/port 54 +portmap_69=77:10 +portmap_70=78:10 +portmap_71=79:10 +portmap_72=80:10 + +# L3 ECMP +# - In Trident2, VP LAGs share the same table as ECMP group table. +# The first N entries are reserved for VP LAGs, where N is the value of the +# config property "max_vp_lags". By default this was set to 256 +l3_max_ecmp_mode=1 +max_vp_lags=0 + +stable_size=0x2000000 diff --git a/device/accton/x86_64-accton_as5712_54x-r0/default_sku b/device/accton/x86_64-accton_as5712_54x-r0/default_sku new file mode 100644 index 000000000000..a65f8088752a --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS5712-54X t1 diff --git a/device/accton/x86_64-accton_as5712_54x-r0/installer.conf b/device/accton/x86_64-accton_as5712_54x-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as5712_54x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as5712_54x-r0/led_proc_init.soc new file mode 100644 index 000000000000..85030e1db349 --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/led_proc_init.soc @@ -0,0 +1,162 @@ +# LED setting for active +# ----------------------------------------------------------------------------- +# for as5712_54x (48xg+6qxg) +# +# on green - if link up +# off - if link down +# blink - if active +# ----------------------------------------------------------------------------- +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=1 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=2 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=5 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=6 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=9 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=10 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=13 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=14 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=17 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=18 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=21 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=22 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=25 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=26 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=29 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=30 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=33 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=34 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=37 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=38 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=41 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=42 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=45 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=46 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=49 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=50 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=53 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=54 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=58 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=61 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=62 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=1 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=2 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=5 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=6 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=9 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=10 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=13 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=14 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=17 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=18 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=21 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=22 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=25 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=26 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=29 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=30 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=33 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=34 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=38 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=41 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=42 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=45 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=46 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=49 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=50 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=53 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=54 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=57 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=58 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=59 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=61 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=62 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 + +led 0 stop +led 0 prog \ + 06 FE 80 D2 19 71 08 E0 60 FE E9 D2 0F 75 10 81 \ + 61 FD 02 3F 60 FF 28 32 0F 87 67 4A 96 FF 06 FF \ + D2 2B 74 16 02 1F 60 FF 28 32 0F 87 67 4A 96 FF \ + 06 FF D2 13 74 28 02 0F 60 FF 28 32 0F 87 67 4A \ + 96 FF 06 FF D2 0B 74 3A 3A 48 32 07 32 08 C7 32 \ + 04 C7 97 71 57 77 69 32 00 32 01 B7 97 71 63 32 \ + 0E 77 6B 26 FD 97 27 77 6B 32 0F 87 57 00 00 00 +led 0 start + +led 1 stop +led 1 prog \ + 06 FE 80 D2 19 71 08 E0 60 FE E9 D2 0F 75 10 81 \ + 61 FD 02 20 67 89 02 24 67 89 02 10 67 89 02 28 \ + 67 89 02 2C 67 89 02 0C 67 89 02 2C 67 79 02 28 \ + 67 79 02 24 67 79 02 20 67 79 02 10 67 79 02 0C \ + 67 79 02 0B 60 FF 28 32 0F 87 67 56 96 FF 06 FF \ + D2 FF 74 46 3A 36 32 07 32 08 C7 32 04 C7 97 71 \ + 63 77 75 32 00 32 01 B7 97 71 6F 32 0E 77 77 26 \ + FD 97 27 77 77 32 0F 87 57 12 A0 F8 15 1A 01 75 \ + 85 28 67 56 57 32 0F 87 57 12 A0 F8 15 1A 01 71 \ + A1 28 67 56 80 28 67 56 80 28 67 56 80 28 67 56 \ + 57 32 0F 87 32 0F 87 32 0F 87 32 0F 87 57 00 00 +led 1 start diff --git a/device/accton/x86_64-accton_as5712_54x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as5712_54x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..7681caafeef4 --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom" + #Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as5712_54x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as5712_54x-r0/plugins/psuutil.py new file mode 100755 index 000000000000..841070637b3e --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/plugins/psuutil.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "57-0038", + 2: "58-003b", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as5712_54x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as5712_54x-r0/plugins/sfputil.py new file mode 100755 index 000000000000..7c585ab2d6ef --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/plugins/sfputil.py @@ -0,0 +1,275 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# +try: + 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 = 71 + PORTS_IN_BLOCK = 72 + QSFP_PORT_START = 48 + QSFP_PORT_END = 72 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" + BASE_CPLD2_PATH = "/sys/bus/i2c/devices/{0}-0061/" + BASE_CPLD3_PATH = "/sys/bus/i2c/devices/{0}-0062/" + I2C_BUS_ORDER = -1 + + #The sidebands of QSFP is different. + #present is in-order. + #But lp_mode and reset are not. + qsfp_sb_map = [1, 3, 5, 2, 4, 6] + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 0: [1, 2], + 1: [2, 3], + 2: [3, 4], + 3: [4, 5], + 4: [5, 6], + 5: [6, 7], + 6: [7, 8], + 7: [8, 9], + 8: [9, 10], + 9: [10, 11], + 10: [11, 12], + 11: [12, 13], + 12: [13, 14], + 13: [14, 15], + 14: [15, 16], + 15: [16, 17], + 16: [17, 18], + 17: [18, 19], + 18: [19, 20], + 19: [20, 21], + 20: [21, 22], + 21: [22, 23], + 22: [23, 24], + 23: [24, 25], + 24: [25, 26], + 25: [26, 27], + 26: [27, 28], + 27: [28, 29], + 28: [29, 30], + 29: [30, 31], + 30: [31, 32], + 31: [32, 33], + 32: [33, 34], + 33: [34, 35], + 34: [35, 36], + 35: [36, 37], + 36: [37, 38], + 37: [38, 39], + 38: [39, 40], + 39: [40, 41], + 40: [41, 42], + 41: [42, 43], + 42: [43, 44], + 43: [44, 45], + 44: [45, 46], + 45: [46, 47], + 46: [47, 48], + 47: [48, 49], + 48: [49, 50],#QSFP49 + 49: [49, 50], + 50: [49, 50], + 51: [49, 50], + 52: [50, 52],#QSFP50 + 53: [50, 52], + 54: [50, 52], + 55: [50, 52], + 56: [51, 54],#QSFP51 + 57: [51, 54], + 58: [51, 54], + 59: [51, 54], + 60: [52, 51],#QSFP52 + 61: [52, 51], + 62: [52, 51], + 63: [52, 51], + 64: [53, 53], #QSFP53 + 65: [53, 53], + 66: [53, 53], + 67: [53, 53], + 68: [54, 55],#QSFP54 + 69: [54, 55], + 70: [54, 55], + 71: [54, 55], + } + + @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 = self.BASE_OOM_PATH + "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][1] + ) + + SfpUtilBase.__init__(self) + + #Two i2c buses might get flipped order, check them both. + def update_i2c_order(self): + if self.I2C_BUS_ORDER < 0: + eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom" + if os.path.exists(eeprom_path): + self.I2C_BUS_ORDER = 0 + eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + if os.path.exists(eeprom_path): + self.I2C_BUS_ORDER = 1 + return self.I2C_BUS_ORDER + + 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 + + order = self.update_i2c_order() + if port_num < 24: + present_path = self.BASE_CPLD2_PATH.format(order) + else: + present_path = self.BASE_CPLD3_PATH.format(order) + + present_path = present_path + "module_present_" + str(self._port_to_i2c_mapping[port_num][0]) + self.__port_to_is_present = present_path + + try: + val_file = open(self.__port_to_is_present) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def qsfp_sb_remap(self, port_num): + qsfp_start = self.qsfp_port_start + qsfp_index = self._port_to_i2c_mapping[port_num][0] - qsfp_start + qsfp_index = self.qsfp_sb_map[qsfp_index-1] + return qsfp_start+qsfp_index + + def get_low_power_mode(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + order = self.update_i2c_order() + lp_mode_path = self.BASE_CPLD3_PATH.format(order) + lp_mode_path = lp_mode_path + "module_lp_mode_" + q = self.qsfp_sb_remap(port_num) + lp_mode_path = lp_mode_path + str(q) + + try: + val_file = open(lp_mode_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def set_low_power_mode(self, port_num, lpmode): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + order = self.update_i2c_order() + lp_mode_path = self.BASE_CPLD3_PATH.format(order) + lp_mode_path = lp_mode_path + "module_lp_mode_" + q = self.qsfp_sb_remap(port_num) + lp_mode_path = lp_mode_path + str(q) + + try: + reg_file = open(lp_mode_path, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + if lpmode is True: + reg_value = '1' + else: + reg_value = '0' + + reg_file.write(reg_value) + reg_file.close() + + return True + + def reset(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + order = self.update_i2c_order() + lp_mode_path = self.BASE_CPLD3_PATH.format(order) + mod_rst_path = lp_mode_path + "module_reset_" + q = self.qsfp_sb_remap(port_num) + mod_rst_path = mod_rst_path + str(q) + + try: + reg_file = open(mod_rst_path, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + #toggle reset + reg_file.seek(0) + reg_file.write('0') + time.sleep(1) + reg_file.seek(0) + reg_file.write('1') + reg_file.close() + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError + diff --git a/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/port_config.ini b/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/port_config.ini new file mode 100644 index 000000000000..fd2022dc2c9d --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 49,50,51,52 fortyGigE1 +Ethernet4 53,54,55,56 fortyGigE2 +Ethernet8 57,58,59,60 fortyGigE3 +Ethernet12 61,62,63,64 fortyGigE4 +Ethernet16 65,66,67,68 fortyGigE5 +Ethernet20 69,70,71,72 fortyGigE6 +Ethernet24 73,74,75,76 fortyGigE7 +Ethernet28 77,78,79,80 fortyGigE8 +Ethernet32 33,34,35,36 fortyGigE9 +Ethernet36 37,38,39,40 fortyGigE10 +Ethernet40 41,42,43,44 fortyGigE11 +Ethernet44 45,46,47,48 fortyGigE12 +Ethernet48 81,82,83,84 fortyGigE13 +Ethernet52 85,86,87,88 fortyGigE14 +Ethernet56 89,90,91,92 fortyGigE15 +Ethernet60 93,94,95,96 fortyGigE16 +Ethernet64 97,98,99,100 fortyGigE17 +Ethernet68 101,102,103,104 fortyGigE18 +Ethernet72 105,106,107,108 fortyGigE19 +Ethernet76 109,110,111,112 fortyGigE20 +Ethernet80 17,18,19,20 fortyGigE21 +Ethernet84 21,22,23,24 fortyGigE22 +Ethernet88 25,26,27,28 fortyGigE23 +Ethernet92 29,30,31,32 fortyGigE24 +Ethernet96 113,114,115,116 fortyGigE25 +Ethernet100 117,118,119,120 fortyGigE26 +Ethernet104 121,122,123,124 fortyGigE27 +Ethernet108 125,126,127,128 fortyGigE28 +Ethernet112 1,2,3,4 fortyGigE29 +Ethernet116 5,6,7,8 fortyGigE30 +Ethernet120 9,10,11,12 fortyGigE31 +Ethernet124 13,14,15,16 fortyGigE32 diff --git a/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/sai.profile b/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/sai.profile new file mode 100644 index 000000000000..22432e548b4a --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-as6712-32x40G.config.bcm diff --git a/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/td2-as6712-32x40G.config.bcm b/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/td2-as6712-32x40G.config.bcm new file mode 100644 index 000000000000..54f3c366fdc4 --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/td2-as6712-32x40G.config.bcm @@ -0,0 +1,132 @@ +os=unix +bcm_stat_flags=0 +parity_enable=0 +parity_correction=0 + +l2_mem_entries=163840 +l3_mem_entries=81920 +mmu_lossless=0 +lls_num_l2uc=12 +module_64ports=0 + +#SFI +serdes_if_type=9 + +port_init_cl72=0 +phy_an_c73=5 # TSCMOD_CL73_CL37 + +#sdk6.5.5 only supports 156(default) or 125 +#xgxs_lcpll_xtal_refclk=1 +tslam_dma_enable=1 +table_dma_enable=1 + +#for 32x40G ports for breakout mode +pbmp_oversubscribe=0x1fffffffe +pbmp_xport_xe=0x1fffffffe + +rate_ext_mdio_divisor=96 + +#QSFP+ 1 from WC0 +portmap_1=1:40 + +#QSFP+ 2 from WC1 +portmap_2=5:40 + +#QSFP+ 3 from WC2 +portmap_3=9:40 + +#QSFP+ 4 from WC3 +portmap_4=13:40 + +#QSFP+ 5 from WC4 +portmap_5=17:40 + +#QSFP+ 6 from WC5 +portmap_6=21:40 + +#QSFP+ 7 from WC6 +portmap_7=25:40 + +#QSFP+ 8 from WC7 +portmap_8=29:40 + +#QSFP+ 9 from WC8 +portmap_9=33:40 + +#QSFP+ 10 from WC9 +portmap_10=37:40 + +#QSFP+ 11 from WC10 +portmap_11=41:40 + +#QSFP+ 12 from WC11 +portmap_12=45:40 + +#QSFP+ 13 from WC12 +portmap_13=49:40 + +#QSFP+ 14 from WC13 +portmap_14=53:40 + +#QSFP+ 15 from WC14 +portmap_15=57:40 + +#QSFP+ 16 from WC15 +portmap_16=61:40 + +#QSFP+ 17 from WC16 +portmap_17=65:40 + +#QSFP+ 18 from WC17 +portmap_18=69:40 + +#QSFP+ 19 from WC18 +portmap_19=73:40 + +#QSFP+ 20 from WC19 +portmap_20=77:40 + +#QSFP+ 21 from WC20 +portmap_21=81:40 + +#QSFP+ 22 from WC21 +portmap_22=85:40 + +#QSFP+ 23 from WC22 +portmap_23=89:40 + +#QSFP+ 24 from WC23 +portmap_24=93:40 + +#QSFP+ 25 from WC24 +portmap_25=97:40 + +#QSFP+ 26 from WC25 +portmap_26=101:40 + +#QSFP+ 27 from WC26 +portmap_27=105:40 + +#QSFP+ 28 from WC27 +portmap_28=109:40 + +#QSFP+ 29 from WC28 +portmap_29=113:40 + +#QSFP+ 30 from WC29 +portmap_30=117:40 + +#QSFP+ 31 from WC30 +portmap_31=121:40 + +#QSFP+ 32 from WC31 +portmap_32=125:40 + +# L3 ECMP +# - In Trident2, VP LAGs share the same table as ECMP group table. +# The first N entries are reserved for VP LAGs, where N is the value of the +# config property "max_vp_lags". By default this was set to 256 +l3_max_ecmp_mode=1 +max_vp_lags=0 + +stable_size=0x2000000 diff --git a/device/accton/x86_64-accton_as6712_32x-r0/default_sku b/device/accton/x86_64-accton_as6712_32x-r0/default_sku new file mode 100644 index 000000000000..d8cdd655905b --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS6712-32X t1 diff --git a/device/accton/x86_64-accton_as6712_32x-r0/installer.conf b/device/accton/x86_64-accton_as6712_32x-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as6712_32x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as6712_32x-r0/led_proc_init.soc new file mode 100644 index 000000000000..9e29adf790de --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/led_proc_init.soc @@ -0,0 +1,104 @@ +# LED setting for active +# ----------------------------------------------------------------------------- +# for as6712_32x (32 qxg) +# ----------------------------------------------------------------------------- + +s CMIC_LEDUP0_DATA_RAM 0 +s CMIC_LEDUP1_DATA_RAM 0 + +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=1 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=2 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=5 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=6 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=7 + +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=9 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=10 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=13 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=14 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=15 + + +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=62 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=61 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=58 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=54 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=53 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=50 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=49 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=46 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=45 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=42 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=41 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=38 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=37 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=34 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=33 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=30 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=29 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=26 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=25 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=22 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=21 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=18 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=17 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=16 + + +led 0 stop +led 0 prog \ + 02 F9 42 80 02 F7 42 00 02 F8 42 00 02 F4 42 90 02 \ + F3 42 10 67 6A 67 6A 67 38 67 6A 67 6A 67 6A 67 6A \ + 67 6A 67 6A 86 F8 06 F3 D6 F8 74 14 86 F0 3E F4 67 \ + 6A 57 67 7E 57 06 F8 88 80 4A 00 27 97 75 35 90 4A \ + 00 27 4A 01 27 B7 97 71 4F 77 32 06 F5 D6 F0 74 62 \ + 02 F5 4A 07 37 4E 07 02 F0 42 00 4E 07 02 F5 4A 07 \ + 71 32 77 35 16 F7 06 F9 17 4D DA 07 74 7B 12 F7 52 \ + 00 86 F9 57 86 F7 57 16 F7 06 F9 07 4D DA 07 74 8F \ + 12 F7 52 00 86 F9 57 86 F7 57 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 +led 0 start + +led 1 stop +led 1 prog \ + 02 F9 42 80 02 F7 42 00 02 F8 42 01 02 F4 42 90 02 \ + F3 42 11 67 6A 67 6A 67 38 67 6A 67 6A 67 6A 67 6A \ + 67 6A 67 6A 86 F8 06 F3 D6 F8 74 14 86 F0 3E F4 67 \ + 6A 57 67 7E 57 06 F8 88 80 4A 00 27 97 75 35 90 4A \ + 00 27 4A 01 27 B7 97 71 4F 77 32 06 F5 D6 F0 74 62 \ + 02 F5 4A 07 37 4E 07 02 F0 42 00 4E 07 02 F5 4A 07 \ + 71 32 77 35 16 F7 06 F9 17 4D DA 07 74 7B 12 F7 52 \ + 00 86 F9 57 86 F7 57 16 F7 06 F9 07 4D DA 07 74 8F \ + 12 F7 52 00 86 F9 57 86 F7 57 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 +led 1 start diff --git a/device/accton/x86_64-accton_as6712_32x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as6712_32x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..7681caafeef4 --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom" + #Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as6712_32x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as6712_32x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..191654429e6b --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/plugins/psuutil.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "35-0038", + 2: "36-003b", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as6712_32x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as6712_32x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..3c93649d760e --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/plugins/sfputil.py @@ -0,0 +1,215 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + 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 = 31 + PORTS_IN_BLOCK = 32 + QSFP_PORT_START = 0 + QSFP_PORT_END = 32 + + I2C_DEV_PATH = "/sys/bus/i2c/devices/" + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" + CPLD_ADDRESS = ['-0062', '-0064'] + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 0: [1, 2], + 1: [2, 3], + 2: [3, 4], + 3: [4, 5], + 4: [5, 6], + 5: [6, 7], + 6: [7, 8], + 7: [8, 9], + 8: [9, 10], + 9: [10, 11], + 10: [11, 12], + 11: [12, 13], + 12: [13, 14], + 13: [14, 15], + 14: [15, 16], + 15: [16, 17], + 16: [17, 18], + 17: [18, 19], + 18: [19, 20], + 19: [20, 21], + 20: [21, 22], + 21: [22, 23], + 22: [23, 24], + 23: [24, 25], + 24: [25, 26], + 25: [26, 27], + 26: [27, 28], + 27: [28, 29], + 28: [29, 30], + 29: [30, 31], + 30: [31, 32], + 31: [32, 33], + 32: [33, 34], + 33: [34, 35], + 34: [35, 36], + 35: [36, 37], + 36: [37, 38], + 37: [38, 39], + 38: [39, 40], + 39: [40, 41], + 40: [41, 42], + 41: [42, 43], + 42: [43, 44], + 43: [44, 45], + 44: [45, 46], + 45: [46, 47], + 46: [47, 48], + 47: [48, 49], + 48: [49, 50],#QSFP49 + 49: [49, 50], + 50: [49, 50], + 51: [49, 50], + 52: [50, 52],#QSFP50 + 53: [50, 52], + 54: [50, 52], + 55: [50, 52], + 56: [51, 54],#QSFP51 + 57: [51, 54], + 58: [51, 54], + 59: [51, 54], + 60: [52, 51],#QSFP52 + 61: [52, 51], + 62: [52, 51], + 63: [52, 51], + 64: [53, 53], #QSFP53 + 65: [53, 53], + 66: [53, 53], + 67: [53, 53], + 68: [54, 55],#QSFP54 + 69: [54, 55], + 70: [54, 55], + 71: [54, 55], + } + + @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 = self.BASE_OOM_PATH + "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][1] + ) + + SfpUtilBase.__init__(self) + + def get_cpld_dev_path(self, port_num): + if port_num < 16: + cpld_num = 0 + else: + cpld_num = 1 + + #cpld can be at either bus 0 or bus 1. + cpld_path = self.I2C_DEV_PATH + str(0) + self.CPLD_ADDRESS[cpld_num] + if not os.path.exists(cpld_path): + cpld_path = self.I2C_DEV_PATH + str(1) + self.CPLD_ADDRESS[cpld_num] + return cpld_path + + 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 + + cpld_path = self.get_cpld_dev_path(port_num) + present_path = cpld_path + "/module_present_" + present_path += str(self._port_to_i2c_mapping[port_num][0]) + + self.__port_to_is_present = present_path + + try: + val_file = open(self.__port_to_is_present) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + 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): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + cpld_path = self.get_cpld_dev_path(port_num) + _path = cpld_path + "/module_reset_" + _path += str(self._port_to_i2c_mapping[port_num][0]) + + try: + reg_file = open(_path, 'w') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_file.seek(0) + reg_file.write('1') + time.sleep(1) + reg_file.seek(0) + reg_file.write('0') + reg_file.close() + + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError + diff --git a/device/accton/x86_64-accton_as6712_32x-r0/sensors.conf b/device/accton/x86_64-accton_as6712_32x-r0/sensors.conf new file mode 100644 index 000000000000..84ee0fd9f333 --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/sensors.conf @@ -0,0 +1,23 @@ +# libsensors configuration file for AS6712-32X +# ------------------------------------------------ + +chip "cpr_4011_4mxx-i2c-*-3c" + label in1 "PSU1_VIN" + label in2 "PSU1_VOUT" + label curr1 "PSU1_IIN" + label curr2 "PSU1_IOUT" + label power1 "PSU1_PIN" + label power2 "PSU1_POUT" + label fan1 "PSU1_FAN" + label temp1 "PSU1_TEMP" + +chip "cpr_4011_4mxx-i2c-*-3f" + label in1 "PSU2_VIN" + label in2 "PSU2_VOUT" + label curr1 "PSU2_IIN" + label curr2 "PSU2_IOUT" + label power1 "PSU2_PIN" + label power2 "PSU2_POUT" + label fan1 "PSU2_FAN" + label temp1 "PSU2_TEMP" + diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/buffers.json.j2 b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/buffers.json.j2 new file mode 100644 index 000000000000..9354b7ec5b59 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/buffers_defaults_t0.j2 b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..7e7c32676eb7 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/buffers_defaults_t0.j2 @@ -0,0 +1,72 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20971328' %} +{% set ingress_lossy_pool_size = '20971328' %} +{% set egress_lossless_pool_size = '20971328' %} +{% set egress_lossy_pool_size = '20971328' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0, 48) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(48, 54) %} + {%- if PORT_ALL.append("Ethernet%d" % (48 + (port_idx-48) * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xon":"78400", + "xoff":"132160", + "size":"3584", + "static_th":"82880" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"3584", + "dynamic_th":"-1" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"3584", + "dynamic_th":"-4" + } + }, +{%- endmacro %} + +{# the typo of generate_pg_profils dued to buffers_config.j2 #} +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + } +{%- endmacro %} + +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + } +{%- endmacro %} \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/buffers_defaults_t1.j2 b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..7e7c32676eb7 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/buffers_defaults_t1.j2 @@ -0,0 +1,72 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20971328' %} +{% set ingress_lossy_pool_size = '20971328' %} +{% set egress_lossless_pool_size = '20971328' %} +{% set egress_lossy_pool_size = '20971328' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0, 48) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(48, 54) %} + {%- if PORT_ALL.append("Ethernet%d" % (48 + (port_idx-48) * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xon":"78400", + "xoff":"132160", + "size":"3584", + "static_th":"82880" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"3584", + "dynamic_th":"-1" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"3584", + "dynamic_th":"-4" + } + }, +{%- endmacro %} + +{# the typo of generate_pg_profils dued to buffers_config.j2 #} +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + } +{%- endmacro %} + +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + } +{%- endmacro %} \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/pg_profile_lookup.ini b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/pg_profile_lookup.ini new file mode 100644 index 000000000000..d98b0eca6d19 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 3584 32256 59136 36736 + 25000 5m 3584 41216 68096 45696 + 40000 5m 3584 47488 74368 51968 + 50000 5m 3584 52864 79744 57344 + 100000 5m 3584 78400 132160 82880 + 10000 40m 3584 32256 59136 36736 + 25000 40m 3584 41216 68096 45696 + 40000 40m 3584 47488 74368 51968 + 50000 40m 3584 52864 79744 57344 + 100000 40m 3584 78400 132160 82880 + 10000 300m 3584 32256 65856 36736 + 25000 300m 3584 41216 84672 45696 + 40000 300m 3584 47488 101024 51968 + 50000 300m 3584 52864 113120 57344 + 100000 300m 3584 78400 198688 82880 \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config.ini b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config.ini new file mode 100644 index 000000000000..52c59bc9d297 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias index +Ethernet0 8 Ethernet1/1 0 +Ethernet1 9 Ethernet2/1 1 +Ethernet2 10 Ethernet3/1 2 +Ethernet3 11 Ethernet4/1 3 +Ethernet4 12 Ethernet5/1 4 +Ethernet5 13 Ethernet6/1 5 +Ethernet6 14 Ethernet7/1 6 +Ethernet7 15 Ethernet8/1 7 +Ethernet8 16 Ethernet9/1 8 +Ethernet9 17 Ethernet10/1 9 +Ethernet10 18 Ethernet11/1 10 +Ethernet11 19 Ethernet12/1 11 +Ethernet12 20 Ethernet13/1 12 +Ethernet13 21 Ethernet14/1 13 +Ethernet14 22 Ethernet15/1 14 +Ethernet15 23 Ethernet16/1 15 +Ethernet16 32 Ethernet17/1 16 +Ethernet17 33 Ethernet18/1 17 +Ethernet18 34 Ethernet19/1 18 +Ethernet19 35 Ethernet20/1 19 +Ethernet20 40 Ethernet21/1 20 +Ethernet21 41 Ethernet22/1 21 +Ethernet22 42 Ethernet23/1 22 +Ethernet23 43 Ethernet24/1 23 +Ethernet24 48 Ethernet25/1 24 +Ethernet25 49 Ethernet26/1 25 +Ethernet26 50 Ethernet27/1 26 +Ethernet27 51 Ethernet28/1 27 +Ethernet28 56 Ethernet29/1 28 +Ethernet29 57 Ethernet30/1 29 +Ethernet30 58 Ethernet31/1 30 +Ethernet31 59 Ethernet32/1 31 +Ethernet32 64 Ethernet33/1 32 +Ethernet33 65 Ethernet34/1 33 +Ethernet34 66 Ethernet35/1 34 +Ethernet35 67 Ethernet36/1 35 +Ethernet36 68 Ethernet37/1 36 +Ethernet37 69 Ethernet38/1 37 +Ethernet38 70 Ethernet39/1 38 +Ethernet39 71 Ethernet40/1 39 +Ethernet40 72 Ethernet41/1 40 +Ethernet41 73 Ethernet42/1 41 +Ethernet42 74 Ethernet43/1 42 +Ethernet43 75 Ethernet44/1 43 +Ethernet44 76 Ethernet45/1 44 +Ethernet45 77 Ethernet46/1 45 +Ethernet46 78 Ethernet47/1 46 +Ethernet47 79 Ethernet48/1 47 +Ethernet48 84,85,86,87 Ethernet49/1 48 +Ethernet49 80,81,82,83 Ethernet50/1 49 +Ethernet50 104,105,106,107 Ethernet51/1 50 +Ethernet51 108,109,110,111 Ethernet52/1 51 +Ethernet52 112,113,114,115 Ethernet53/1 52 +Ethernet53 116,117,118,119 Ethernet54/1 53 \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config.nps b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config.nps new file mode 100644 index 000000000000..e639b4572feb --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config.nps @@ -0,0 +1,414 @@ +init start stage unit=0 low-level +init set port-map unit=0 port=0 eth-macro=2 lane=0 max-speed=25g active=true +init set port-map unit=0 port=1 eth-macro=2 lane=1 max-speed=25g active=true +init set port-map unit=0 port=2 eth-macro=2 lane=2 max-speed=25g active=true +init set port-map unit=0 port=3 eth-macro=2 lane=3 max-speed=25g active=true +init set port-map unit=0 port=4 eth-macro=3 lane=0 max-speed=25g active=true +init set port-map unit=0 port=5 eth-macro=3 lane=1 max-speed=25g active=true +init set port-map unit=0 port=6 eth-macro=3 lane=2 max-speed=25g active=true +init set port-map unit=0 port=7 eth-macro=3 lane=3 max-speed=25g active=true +init set port-map unit=0 port=8 eth-macro=4 lane=0 max-speed=25g active=true +init set port-map unit=0 port=9 eth-macro=4 lane=1 max-speed=25g active=true +init set port-map unit=0 port=10 eth-macro=4 lane=2 max-speed=25g active=true +init set port-map unit=0 port=11 eth-macro=4 lane=3 max-speed=25g active=true +init set port-map unit=0 port=12 eth-macro=5 lane=0 max-speed=25g active=true +init set port-map unit=0 port=13 eth-macro=5 lane=1 max-speed=25g active=true +init set port-map unit=0 port=14 eth-macro=5 lane=2 max-speed=25g active=true +init set port-map unit=0 port=15 eth-macro=5 lane=3 max-speed=25g active=true +init set port-map unit=0 port=16 eth-macro=8 lane=0 max-speed=25g active=true +init set port-map unit=0 port=17 eth-macro=8 lane=1 max-speed=25g active=true +init set port-map unit=0 port=18 eth-macro=8 lane=2 max-speed=25g active=true +init set port-map unit=0 port=19 eth-macro=8 lane=3 max-speed=25g active=true +init set port-map unit=0 port=20 eth-macro=10 lane=0 max-speed=25g active=true +init set port-map unit=0 port=21 eth-macro=10 lane=1 max-speed=25g active=true +init set port-map unit=0 port=22 eth-macro=10 lane=2 max-speed=25g active=true +init set port-map unit=0 port=23 eth-macro=10 lane=3 max-speed=25g active=true +init set port-map unit=0 port=24 eth-macro=12 lane=0 max-speed=25g active=true +init set port-map unit=0 port=25 eth-macro=12 lane=1 max-speed=25g active=true +init set port-map unit=0 port=26 eth-macro=12 lane=2 max-speed=25g active=true +init set port-map unit=0 port=27 eth-macro=12 lane=3 max-speed=25g active=true +init set port-map unit=0 port=28 eth-macro=14 lane=0 max-speed=25g active=true +init set port-map unit=0 port=29 eth-macro=14 lane=1 max-speed=25g active=true +init set port-map unit=0 port=30 eth-macro=14 lane=2 max-speed=25g active=true +init set port-map unit=0 port=31 eth-macro=14 lane=3 max-speed=25g active=true +init set port-map unit=0 port=32 eth-macro=16 lane=0 max-speed=25g active=true +init set port-map unit=0 port=33 eth-macro=16 lane=1 max-speed=25g active=true +init set port-map unit=0 port=34 eth-macro=16 lane=2 max-speed=25g active=true +init set port-map unit=0 port=35 eth-macro=16 lane=3 max-speed=25g active=true +init set port-map unit=0 port=36 eth-macro=17 lane=0 max-speed=25g active=true +init set port-map unit=0 port=37 eth-macro=17 lane=1 max-speed=25g active=true +init set port-map unit=0 port=38 eth-macro=17 lane=2 max-speed=25g active=true +init set port-map unit=0 port=39 eth-macro=17 lane=3 max-speed=25g active=true +init set port-map unit=0 port=40 eth-macro=18 lane=0 max-speed=25g active=true +init set port-map unit=0 port=41 eth-macro=18 lane=1 max-speed=25g active=true +init set port-map unit=0 port=42 eth-macro=18 lane=2 max-speed=25g active=true +init set port-map unit=0 port=43 eth-macro=18 lane=3 max-speed=25g active=true +init set port-map unit=0 port=44 eth-macro=19 lane=0 max-speed=25g active=true +init set port-map unit=0 port=45 eth-macro=19 lane=1 max-speed=25g active=true +init set port-map unit=0 port=46 eth-macro=19 lane=2 max-speed=25g active=true +init set port-map unit=0 port=47 eth-macro=19 lane=3 max-speed=25g active=true +init set port-map unit=0 port=48 eth-macro=21 lane=0 max-speed=100g active=true +init set port-map unit=0 port=49 eth-macro=20 lane=0 max-speed=100g active=true +init set port-map unit=0 port=50 eth-macro=26 lane=0 max-speed=100g active=true +init set port-map unit=0 port=51 eth-macro=27 lane=0 max-speed=100g active=true +init set port-map unit=0 port=52 eth-macro=28 lane=0 max-speed=100g active=true +init set port-map unit=0 port=53 eth-macro=29 lane=0 max-speed=100g active=true +init set port-map unit=0 port=129 eth-macro=0 lane=1 max-speed=10g active=true guarantee=true cpi=true +init set port-map unit=0 port=130 eth-macro=0 lane=0 max-speed=10g active=true guarantee=true cpi=true init-done=true +init start stage unit=0 task-rsrc +init start stage unit=0 module +init start stage unit=0 task +phy set lane-swap portlist=0 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=1 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=2 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=3 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=4 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=5 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=6 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=7 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=8 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=9 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=10 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=11 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=12 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=13 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=14 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=15 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=16 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=17 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=18 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=19 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=20 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=21 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=22 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=23 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=24 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=25 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=26 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=27 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=28 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=29 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=30 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=31 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=32 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=33 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=34 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=35 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=36 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=37 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=38 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=39 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=40 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=41 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=42 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=43 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=44 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=45 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=46 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=47 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=48 lane-cnt=4 property=tx data=0x1.3.0.2 +phy set lane-swap portlist=49 lane-cnt=4 property=tx data=0x0.3.1.2 +phy set lane-swap portlist=50 lane-cnt=4 property=tx data=0x1.3.0.2 +phy set lane-swap portlist=51 lane-cnt=4 property=tx data=0x2.0.3.1 +phy set lane-swap portlist=52 lane-cnt=4 property=tx data=0x3.2.1.0 +phy set lane-swap portlist=53 lane-cnt=4 property=tx data=0x3.2.1.0 +phy set lane-swap portlist=0 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=1 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=2 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=3 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=4 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=5 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=6 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=7 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=8 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=9 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=10 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=11 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=12 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=13 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=14 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=15 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=16 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=17 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=18 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=19 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=20 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=21 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=22 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=23 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=24 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=25 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=26 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=27 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=28 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=29 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=30 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=31 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=32 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=33 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=34 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=35 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=36 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=37 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=38 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=39 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=40 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=41 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=42 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=43 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=44 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=45 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=46 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=47 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=48 lane-cnt=4 property=rx data=0x2.1.0.3 +phy set lane-swap portlist=49 lane-cnt=4 property=rx data=0x0.1.3.2 +phy set lane-swap portlist=50 lane-cnt=4 property=rx data=0x3.1.0.2 +phy set lane-swap portlist=51 lane-cnt=4 property=rx data=0x1.3.0.2 +phy set lane-swap portlist=52 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set lane-swap portlist=53 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set polarity-rev portlist=0 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=1 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=2 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=3 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=4 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=5 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=6 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=7 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=8 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=9 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=10 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=11 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=12 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=13 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=14 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=15 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=16 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=17 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=18 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=19 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=20 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=21 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=22 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=23 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=24 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=25 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=26 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=27 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=28 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=29 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=30 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=31 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=32 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=33 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=34 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=35 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=36 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=37 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=38 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=39 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=40 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=41 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=42 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=43 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=44 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=45 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=46 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=47 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=48 lane-cnt=4 property=tx data=0x0.0.0.1 +phy set polarity-rev portlist=49 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=50 lane-cnt=4 property=tx data=0x1.1.0.0 +phy set polarity-rev portlist=51 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=52 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=53 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=0 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=1 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=2 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=3 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=4 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=5 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=6 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=7 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=8 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=9 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=10 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=11 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=12 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=13 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=14 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=15 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=16 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=17 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=18 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=19 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=20 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=21 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=22 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=23 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=24 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=25 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=26 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=27 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=28 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=29 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=30 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=31 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=32 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=33 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=34 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=35 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=36 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=37 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=38 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=39 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=40 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=41 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=42 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=43 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=44 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=45 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=46 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=47 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=48 lane-cnt=4 property=rx data=0x0.1.0.1 +phy set polarity-rev portlist=49 lane-cnt=4 property=rx data=0x1.0.1.0 +phy set polarity-rev portlist=50 lane-cnt=4 property=rx data=0x0.0.1.0 +phy set polarity-rev portlist=51 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=52 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=53 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set pre-emphasis portlist=0 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=0 lane-cnt=4 property=cn1 data=0x1.1.1.1 +phy set pre-emphasis portlist=0 lane-cnt=4 property=c0 data=0x1a.1a.1a.1a +phy set pre-emphasis portlist=0 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=4 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=4 lane-cnt=4 property=cn1 data=0x1.1.1.1 +phy set pre-emphasis portlist=4 lane-cnt=4 property=c0 data=0x1a.1a.1a.1a +phy set pre-emphasis portlist=4 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=8 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=8 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=8 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=8 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=12 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=12 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=12 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=12 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=16 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=16 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=16 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=16 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=20 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=20 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=20 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=20 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=24 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=24 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=24 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=24 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=28 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=28 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=28 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=28 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=32 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=32 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=32 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=32 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=36 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=36 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=36 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=36 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=40 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=40 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=40 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=40 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=44 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=44 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=44 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=44 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=48 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=48 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=48 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=48 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=49 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=49 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=49 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=49 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=50 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=50 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=50 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=50 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=51 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=51 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=51 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=51 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=52 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=52 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=52 lane-cnt=4 property=c0 data=0x1a.1a.1a.1a +phy set pre-emphasis portlist=52 lane-cnt=4 property=c1 data=0x8.8.8.8 +phy set pre-emphasis portlist=53 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=53 lane-cnt=4 property=cn1 data=0x1.1.1.1 +phy set pre-emphasis portlist=53 lane-cnt=4 property=c0 data=0x1a.1a.1a.1a +phy set pre-emphasis portlist=53 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set mdio portlist=0 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=1 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=2 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=3 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=4 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=5 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=6 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=7 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=8 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=9 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=10 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=11 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=12 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=13 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=14 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=15 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=16 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=17 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=18 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=19 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=20 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=21 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=22 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=23 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=24 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=25 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=26 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=27 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=28 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=29 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=30 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=31 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=32 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=33 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=34 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=35 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=36 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=37 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=38 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=39 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=40 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=41 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=42 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=43 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=44 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=45 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=46 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=47 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=48 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=49 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=50 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=51 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=52 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=53 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=129 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=130 devad=0x1E addr=0x2 data=0x0000 +port set property portlist=0-47 speed=25g +port set property portlist=48-53 speed=100g +port set property portlist=129-130 speed=10g +port set property portlist=0-47 medium-type=sr +port set property portlist=48-53 medium-type=sr4 +port set property portlist=129-130 medium-type=kr +port set adver portlist=129-130 speed-10g-kr +port set property portlist=129-130 an=enable +port set property portlist=0-53,129-130 admin=enable + diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/qos.json.j2 b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/qos.json.j2 new file mode 100644 index 000000000000..5c5fc6e4969b --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/qos.json.j2 @@ -0,0 +1,136 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "1", + "1": "0", + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "1", + "1": "0", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"1", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + }, + "WRED_PROFILE": { + "AZURE_LOSSY" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"613984", + "red_min_threshold":"76608", + "yellow_max_threshold":"628320", + "yellow_min_threshold":"78400", + "green_max_threshold": "642656", + "green_min_threshold": "80192" + }, + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"613984", + "red_min_threshold":"76608", + "yellow_max_threshold":"628320", + "yellow_min_threshold":"78400", + "green_max_threshold": "642656", + "green_min_threshold": "80192" + } + }, + "QUEUE": { + } +} diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/sai.profile b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/sai.profile new file mode 100644 index 000000000000..880f47910ac1 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/led_proc_init.nps +SAI_DSH_CONFIG_FILE=/usr/share/sonic/hwsku/port_config.nps diff --git a/device/accton/x86_64-accton_as7116_54x-r0/default_sku b/device/accton/x86_64-accton_as7116_54x-r0/default_sku new file mode 100644 index 000000000000..829dce6b5748 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7116-54X t1 diff --git a/device/accton/x86_64-accton_as7116_54x-r0/installer.conf b/device/accton/x86_64-accton_as7116_54x-r0/installer.conf new file mode 100644 index 000000000000..4eeedca86a48 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pci=noaer" \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7116_54x-r0/led_proc_init.nps b/device/accton/x86_64-accton_as7116_54x-r0/led_proc_init.nps new file mode 100644 index 000000000000..e25c78018adb --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/led_proc_init.nps @@ -0,0 +1,10 @@ +#unit NPS_CFG_TYPE_XXX param0 param1 value +#---- ---------------- ------ ------ ----- +0 NPS_CFG_TYPE_USE_UNIT_PORT 0 0 1 +0 NPS_CFG_TYPE_LED_CFG 0 0 5 +0 NPS_CFG_TYPE_CPI_PORT_MODE 129 0 1 +0 NPS_CFG_TYPE_CPI_PORT_MODE 130 0 1 +0 NPS_CFG_TYPE_USER_BUF_CTRL 0 0 1 +0 NPS_CFG_TYPE_HASH_L2_FDB_REGION_ENTRY_NUM 0 0 49152 +0 NPS_CFG_TYPE_HASH_L3_WITH_IPV6_PREFIX_64_REGION_ENTRY_NUM 0 0 32768 + diff --git a/device/accton/x86_64-accton_as7116_54x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7116_54x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..1e7d1046d93d --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/plugins/eeprom.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7116_54x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7116_54x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..08fd2648f314 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/plugins/psuutil.py @@ -0,0 +1,92 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/10-0050", + "/sys/bus/i2c/devices/11-0053"] + + def __init__(self): + PsuBase.__init__(self) + + + # Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + attr_file = 'psu_power_good' + attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU status + if (attr_value == 1): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_absent = 0 + attr_file ='psu_present' + attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU presence + if (attr_value == 1): + status = 1 + + return status + diff --git a/device/accton/x86_64-accton_as7116_54x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7116_54x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..1a6c1103891e --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/plugins/sfputil.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + _port_start = 0 + _port_end = 53 + _qsfp_port_start = 48 + _ports_in_block = 54 + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 0 : 37, + 1 : 38, + 2 : 39, + 3 : 40, + 4 : 41, + 5 : 42, + 6 : 43, + 7 : 44, + 8 : 45, + 9 : 46, + 10 : 47, + 11 : 48, + 12 : 49, + 13 : 50, + 14 : 51, + 15 : 52, + 16 : 53, + 17 : 54, + 18 : 55, + 19 : 56, + 20 : 57, + 21 : 58, + 22 : 59, + 23 : 60, + 24 : 61, + 25 : 62, + 26 : 63, + 27 : 64, + 28 : 65, + 29 : 66, + 30 : 67, + 31 : 68, + 32 : 69, + 33 : 70, + 34 : 71, + 35 : 72, + 36 : 73, + 37 : 74, + 38 : 75, + 39 : 76, + 40 : 77, + 41 : 78, + 42 : 79, + 43 : 80, + 44 : 81, + 45 : 82, + 46 : 83, + 47 : 84, + 48 : 21, + 49 : 22, + 50 : 23, + 51 : 24, + 52 : 25, + 53 : 26, + } + + _qsfp_ports = range(_qsfp_port_start, _ports_in_block + 1) + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom' + for x in range(self._port_start, self._port_end + 1): + port_eeprom_path = eeprom_path.format(self._port_to_i2c_mapping[x]) + self._port_to_eeprom_mapping[x] = port_eeprom_path + + SfpUtilBase.__init__(self) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + path = "/sys/bus/i2c/devices/{0}-0050/sfp_port_reset" + port_ps = path.format(self._port_to_i2c_mapping[port_num]) + + try: + reg_file = open(port_ps, 'w') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + #toggle reset + reg_file.seek(0) + reg_file.write('1') + time.sleep(1) + reg_file.seek(0) + reg_file.write('0') + reg_file.close() + return True + + def set_low_power_mode(self, port_nuM, lpmode): + raise NotImplementedError + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present" + port_ps = path.format(self._port_to_i2c_mapping[port_num]) + + + try: + reg_file = open(port_ps) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + + def get_transceiver_change_event(self, timeout=0): + raise NotImplementedError + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return self._qsfp_ports + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping diff --git a/device/accton/x86_64-accton_as7116_54x-r0/sensors.conf b/device/accton/x86_64-accton_as7116_54x-r0/sensors.conf new file mode 100644 index 000000000000..9edb51a9e72d --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/sensors.conf @@ -0,0 +1,13 @@ +# libsensors configuration file + +chip "as7116_54x_fan-*" + label fan1 "front fan 1" + label fan2 "front fan 2" + label fan3 "front fan 3" + label fan4 "front fan 4" + label fan5 "front fan 5" + label fan6 "rear fan 1" + label fan7 "rear fan 2" + label fan8 "rear fan 3" + label fan9 "rear fan 4" + label fan10 "rear fan 5" diff --git a/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/port_config.ini b/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/port_config.ini new file mode 100755 index 000000000000..74865956f61b --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/port_config.ini @@ -0,0 +1,55 @@ +# name lanes +Ethernet0 0 +Ethernet1 1 +Ethernet2 2 +Ethernet3 3 +Ethernet4 4 +Ethernet5 5 +Ethernet6 6 +Ethernet7 7 +Ethernet8 8 +Ethernet9 9 +Ethernet10 10 +Ethernet11 11 +Ethernet12 12 +Ethernet13 13 +Ethernet14 14 +Ethernet15 15 +Ethernet16 16 +Ethernet17 17 +Ethernet18 18 +Ethernet19 19 +Ethernet20 20 +Ethernet21 21 +Ethernet22 22 +Ethernet23 23 +Ethernet24 24 +Ethernet25 25 +Ethernet26 26 +Ethernet27 27 +Ethernet28 28 +Ethernet29 29 +Ethernet30 30 +Ethernet31 31 +Ethernet32 32 +Ethernet33 33 +Ethernet34 34 +Ethernet35 35 +Ethernet36 36 +Ethernet37 37 +Ethernet38 38 +Ethernet39 39 +Ethernet40 40 +Ethernet41 41 +Ethernet42 42 +Ethernet43 43 +Ethernet44 44 +Ethernet45 45 +Ethernet46 46 +Ethernet47 47 +Ethernet48 48 +Ethernet49 49 +Ethernet50 50 +Ethernet51 51 +Ethernet52 52 +Ethernet53 53 diff --git a/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/qos.json.j2 b/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/qos.json.j2 new file mode 100755 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/sai.profile b/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/sai.profile new file mode 100755 index 000000000000..178dcd002853 --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/sai.profile @@ -0,0 +1,2 @@ +mode=1 +hwId=as7212-54x diff --git a/device/accton/x86_64-accton_as7212_54x-r0/default_sku b/device/accton/x86_64-accton_as7212_54x-r0/default_sku new file mode 100644 index 000000000000..d8a1bd55cd48 --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/default_sku @@ -0,0 +1 @@ +AS7212-54x t1 diff --git a/device/accton/x86_64-accton_as7212_54x-r0/installer.conf b/device/accton/x86_64-accton_as7212_54x-r0/installer.conf new file mode 100755 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as7212_54x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7212_54x-r0/plugins/eeprom.py new file mode 100755 index 000000000000..7681caafeef4 --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom" + #Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7212_54x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7212_54x-r0/plugins/sfputil.py new file mode 100755 index 000000000000..fa706867a585 --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/plugins/sfputil.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class sfputil(SfpUtilBase): + """Platform specific sfputil class""" + + port_start = 0 + port_end = 31 + ports_in_block = 32 + + port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 9 : 18, + 10 : 19, + 11 : 20, + 12 : 21, + 1 : 22, + 2 : 23, + 3 : 24, + 4 : 25, + 6 : 26, + 5 : 27, + 8 : 28, + 7 : 29, + 13 : 30, + 14 : 31, + 15 : 32, + 16 : 33, + 17 : 34, + 18 : 35, + 19 : 36, + 20 : 37, + 25 : 38, + 26 : 39, + 27 : 40, + 28 : 41, + 29 : 42, + 30 : 43, + 31 : 44, + 32 : 45, + 21 : 46, + 22 : 47, + 23 : 48, + 24 : 49, + } + + _qsfp_ports = range(0, ports_in_block + 1) + + def __init__(self): + # Override port_to_eeprom_mapping for class initialization + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom' + for x in range(self.port_start, self.port_end + 1): + port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x+1]) + self.port_to_eeprom_mapping[x] = port_eeprom_path + SfpUtilBase.__init__(self) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + path = "/sys/bus/i2c/devices/{0}-0050/sfp_port_reset" + port_ps = path.format(self.port_to_i2c_mapping[port_num+1]) + + try: + reg_file = open(port_ps, 'w') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + #toggle reset + reg_file.seek(0) + reg_file.write('1') + time.sleep(1) + reg_file.seek(0) + reg_file.write('0') + reg_file.close() + return True + + def set_low_power_mode(self, port_nuM, lpmode): + raise NotImplementedErro + + def get_low_power_mode(self, port_num): + raise NotImplementedErro + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present" + port_ps = path.format(self.port_to_i2c_mapping[port_num+1]) + + + try: + reg_file = open(port_ps) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return range(0, self.ports_in_block + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/port_config.ini b/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/port_config.ini new file mode 100644 index 000000000000..2c4d0c023772 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias index +Ethernet0 41 twentyfiveGigE1 0 +Ethernet1 42 twentyfiveGigE2 1 +Ethernet2 43 twentyfiveGigE3 2 +Ethernet3 44 twentyfiveGigE4 3 +Ethernet4 49 twentyfiveGigE5 4 +Ethernet5 50 twentyfiveGigE6 5 +Ethernet6 51 twentyfiveGigE7 6 +Ethernet7 52 twentyfiveGigE8 7 +Ethernet8 53 twentyfiveGigE9 8 +Ethernet9 54 twentyfiveGigE10 9 +Ethernet10 55 twentyfiveGigE11 10 +Ethernet11 56 twentyfiveGigE12 11 +Ethernet12 65 twentyfiveGigE13 12 +Ethernet13 66 twentyfiveGigE14 13 +Ethernet14 67 twentyfiveGigE15 14 +Ethernet15 68 twentyfiveGigE16 15 +Ethernet16 33 twentyfiveGigE17 16 +Ethernet17 34 twentyfiveGigE18 17 +Ethernet18 35 twentyfiveGigE19 18 +Ethernet19 36 twentyfiveGigE20 19 +Ethernet20 37 twentyfiveGigE21 20 +Ethernet21 38 twentyfiveGigE22 21 +Ethernet22 39 twentyfiveGigE23 22 +Ethernet23 40 twentyfiveGigE24 23 +Ethernet24 69 twentyfiveGigE25 24 +Ethernet25 70 twentyfiveGigE26 25 +Ethernet26 71 twentyfiveGigE27 26 +Ethernet27 72 twentyfiveGigE28 27 +Ethernet28 81 twentyfiveGigE29 28 +Ethernet29 82 twentyfiveGigE30 29 +Ethernet30 83 twentyfiveGigE31 30 +Ethernet31 84 twentyfiveGigE32 31 +Ethernet32 85 twentyfiveGigE33 32 +Ethernet33 86 twentyfiveGigE34 33 +Ethernet34 87 twentyfiveGigE35 34 +Ethernet35 88 twentyfiveGigE36 35 +Ethernet36 97 twentyfiveGigE37 36 +Ethernet37 98 twentyfiveGigE38 37 +Ethernet38 99 twentyfiveGigE39 38 +Ethernet39 100 twentyfiveGigE40 39 +Ethernet40 101 twentyfiveGigE41 40 +Ethernet41 102 twentyfiveGigE42 41 +Ethernet42 103 twentyfiveGigE43 42 +Ethernet43 104 twentyfiveGigE44 43 +Ethernet44 105 twentyfiveGigE45 44 +Ethernet45 106 twentyfiveGigE46 45 +Ethernet46 107 twentyfiveGigE47 46 +Ethernet47 108 twentyfiveGigE48 47 +Ethernet48 5,6,7,8 hundredGigE49 48 +Ethernet52 1,2,3,4 hundredGigE50 52 +Ethernet56 109,110,111,112 hundredGigE51 56 +Ethernet60 21,22,23,24 hundredGigE52 60 +Ethernet64 9,10,11,12 hundredGigE53 64 +Ethernet68 117,118,119,120 hundredGigE54 68 diff --git a/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/sai.profile b/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/sai.profile new file mode 100644 index 000000000000..31aefe2c2905 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-as7312-48x25G+6x100G.config.bcm diff --git a/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/th-as7312-48x25G+6x100G.config.bcm b/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/th-as7312-48x25G+6x100G.config.bcm new file mode 100644 index 000000000000..eef4d987e8ed --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/th-as7312-48x25G+6x100G.config.bcm @@ -0,0 +1,519 @@ +# accton_as7312_54x 48x25G+6x100G SDK config +os=unix +schan_intr_enable=0 + +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_oversubscribe=0x0407ffc00ff00ff003fc3ffc00200222 +pbmp_xport_xe=0x0407ffd00ff00ff403fc3ffc00200222 + +## FC10 ## +dport_map_port_42=1 +dport_map_port_43=2 +dport_map_port_44=3 +dport_map_port_45=4 + +## FC12 ## +dport_map_port_50=5 +dport_map_port_51=6 +dport_map_port_52=7 +dport_map_port_53=8 + +## FC13 ## +dport_map_port_54=9 +dport_map_port_55=10 +dport_map_port_56=11 +dport_map_port_57=12 + +## FC16 ## +dport_map_port_68=13 +dport_map_port_69=14 +dport_map_port_70=15 +dport_map_port_71=16 + +## FC8 ## +dport_map_port_34=17 +dport_map_port_35=18 +dport_map_port_36=19 +dport_map_port_37=20 + +## FC9 ## +dport_map_port_38=21 +dport_map_port_39=22 +dport_map_port_40=23 +dport_map_port_41=24 + +## FC17 ## +dport_map_port_72=25 +dport_map_port_73=26 +dport_map_port_74=27 +dport_map_port_75=28 + +## FC20 ## +dport_map_port_84=29 +dport_map_port_85=30 +dport_map_port_86=31 +dport_map_port_87=32 + +## FC21 ## +dport_map_port_88=33 +dport_map_port_89=34 +dport_map_port_90=35 +dport_map_port_91=36 + +## FC24 ## +dport_map_port_102=37 +dport_map_port_103=38 +dport_map_port_104=39 +dport_map_port_105=40 + +## FC25 ## +dport_map_port_106=41 +dport_map_port_107=42 +dport_map_port_108=43 +dport_map_port_109=44 + +## FC26 ## +dport_map_port_110=45 +dport_map_port_111=46 +dport_map_port_112=47 +dport_map_port_113=48 + +## FC1 ## +dport_map_port_5=49 + +## FC0 ## +dport_map_port_1=50 + +## FC27 ## +dport_map_port_114=51 + +## FC5 ## +dport_map_port_21=52 + +## FC2 ## +dport_map_port_9=53 + +## FC29 ## +dport_map_port_122=54 + +#for KR +#dport_map_port_66=55 +#dport_map_port_100=56 + +/* Port Map */ +## FC10 ## +portmap_42=41:25 +portmap_43=42:25 +portmap_44=43:25 +portmap_45=44:25 + +## FC12 ## +portmap_50=49:25 +portmap_51=50:25 +portmap_52=51:25 +portmap_53=52:25 + + +## FC13 ## +portmap_54=53:25 +portmap_55=54:25 +portmap_56=55:25 +portmap_57=56:25 + +## FC16 ## +portmap_68=65:25 +portmap_69=66:25 +portmap_70=67:25 +portmap_71=68:25 + + +## FC8 ## +portmap_34=33:25 +portmap_35=34:25 +portmap_36=35:25 +portmap_37=36:25 + +## FC9 ## +portmap_38=37:25 +portmap_39=38:25 +portmap_40=39:25 +portmap_41=40:25 + +## FC17 ## +portmap_72=69:25 +portmap_73=70:25 +portmap_74=71:25 +portmap_75=72:25 + +## FC20 ## +portmap_84=81:25 +portmap_85=82:25 +portmap_86=83:25 +portmap_87=84:25 + + +## FC21 ## +portmap_88=85:25 +portmap_89=86:25 +portmap_90=87:25 +portmap_91=88:25 + +## FC24 ## +portmap_102=97:25 +portmap_103=98:25 +portmap_104=99:25 +portmap_105=100:25 + +## FC25 ## +portmap_106=101:25 +portmap_107=102:25 +portmap_108=103:25 +portmap_109=104:25 + +## FC26 ## +portmap_110=105:25 +portmap_111=106:25 +portmap_112=107:25 +portmap_113=108:25 + +## FC1 ## +portmap_5=5:100 + +## FC0 ## +portmap_1=1:100 + +## FC27 ## +portmap_114=109:100 + +## FC5 ## +portmap_21=21:100 + +## FC2 ## +portmap_9=9:100 + +## FC29 ## +portmap_122=117:100 + +# CPU to MAC +# TSC-E management port 1 +#portmap_66=129:10 +# TSC-E management port 2 +#portmap_100=131:10 + +xgxs_rx_lane_map_42=0x2310 +xgxs_rx_lane_map_43=0x2310 +xgxs_rx_lane_map_44=0x2310 +xgxs_rx_lane_map_45=0x2310 +xgxs_rx_lane_map_50=0x3210 +xgxs_rx_lane_map_51=0x3210 +xgxs_rx_lane_map_52=0x3210 +xgxs_rx_lane_map_53=0x3210 +xgxs_rx_lane_map_54=0x3210 +xgxs_rx_lane_map_55=0x3210 +xgxs_rx_lane_map_56=0x3210 +xgxs_rx_lane_map_57=0x3210 +xgxs_rx_lane_map_68=0x0123 +xgxs_rx_lane_map_69=0x0123 +xgxs_rx_lane_map_70=0x0123 +xgxs_rx_lane_map_71=0x0123 +xgxs_rx_lane_map_34=0x0123 +xgxs_rx_lane_map_35=0x0123 +xgxs_rx_lane_map_36=0x0123 +xgxs_rx_lane_map_37=0x0123 +xgxs_rx_lane_map_38=0x0123 +xgxs_rx_lane_map_39=0x0123 +xgxs_rx_lane_map_40=0x0123 +xgxs_rx_lane_map_41=0x0123 +xgxs_rx_lane_map_72=0x3210 +xgxs_rx_lane_map_73=0x3210 +xgxs_rx_lane_map_74=0x3210 +xgxs_rx_lane_map_75=0x3210 +xgxs_rx_lane_map_84=0x1032 +xgxs_rx_lane_map_85=0x1032 +xgxs_rx_lane_map_86=0x1032 +xgxs_rx_lane_map_87=0x1032 +xgxs_rx_lane_map_88=0x2301 +xgxs_rx_lane_map_89=0x2301 +xgxs_rx_lane_map_90=0x2301 +xgxs_rx_lane_map_91=0x2301 +xgxs_rx_lane_map_102=0x0123 +xgxs_rx_lane_map_103=0x0123 +xgxs_rx_lane_map_104=0x0123 +xgxs_rx_lane_map_105=0x0123 +xgxs_rx_lane_map_106=0x3210 +xgxs_rx_lane_map_107=0x3210 +xgxs_rx_lane_map_108=0x3210 +xgxs_rx_lane_map_109=0x3210 +xgxs_rx_lane_map_110=0x1032 +xgxs_rx_lane_map_111=0x1032 +xgxs_rx_lane_map_112=0x1032 +xgxs_rx_lane_map_113=0x1032 +xgxs_rx_lane_map_5=0x3210 +xgxs_rx_lane_map_1=0x3210 +xgxs_rx_lane_map_114=0x0123 +xgxs_rx_lane_map_21=0x0213 +xgxs_rx_lane_map_9=0x3210 +xgxs_rx_lane_map_122=0x1230 + +xgxs_tx_lane_map_42=0x0132 +xgxs_tx_lane_map_43=0x0132 +xgxs_tx_lane_map_44=0x0132 +xgxs_tx_lane_map_45=0x0132 +xgxs_tx_lane_map_50=0x3210 +xgxs_tx_lane_map_51=0x3210 +xgxs_tx_lane_map_52=0x3210 +xgxs_tx_lane_map_53=0x3210 +xgxs_tx_lane_map_54=0x3210 +xgxs_tx_lane_map_55=0x3210 +xgxs_tx_lane_map_56=0x3210 +xgxs_tx_lane_map_57=0x3210 +xgxs_tx_lane_map_68=0x0123 +xgxs_tx_lane_map_69=0x0123 +xgxs_tx_lane_map_70=0x0123 +xgxs_tx_lane_map_71=0x0123 +xgxs_tx_lane_map_34=0x0123 +xgxs_tx_lane_map_35=0x0123 +xgxs_tx_lane_map_36=0x0123 +xgxs_tx_lane_map_37=0x0123 +xgxs_tx_lane_map_38=0x0123 +xgxs_tx_lane_map_39=0x0123 +xgxs_tx_lane_map_40=0x0123 +xgxs_tx_lane_map_41=0x0123 +xgxs_tx_lane_map_72=0x0123 +xgxs_tx_lane_map_73=0x0123 +xgxs_tx_lane_map_74=0x0123 +xgxs_tx_lane_map_75=0x0123 +xgxs_tx_lane_map_84=0x0123 +xgxs_tx_lane_map_85=0x0123 +xgxs_tx_lane_map_86=0x0123 +xgxs_tx_lane_map_87=0x0123 +xgxs_tx_lane_map_88=0x2301 +xgxs_tx_lane_map_89=0x2301 +xgxs_tx_lane_map_90=0x2301 +xgxs_tx_lane_map_91=0x2301 +xgxs_tx_lane_map_102=0x0123 +xgxs_tx_lane_map_103=0x0123 +xgxs_tx_lane_map_104=0x0123 +xgxs_tx_lane_map_105=0x0123 +xgxs_tx_lane_map_106=0x3210 +xgxs_tx_lane_map_107=0x3210 +xgxs_tx_lane_map_108=0x3210 +xgxs_tx_lane_map_109=0x3210 +xgxs_tx_lane_map_110=0x1032 +xgxs_tx_lane_map_111=0x1032 +xgxs_tx_lane_map_112=0x1032 +xgxs_tx_lane_map_113=0x1032 +xgxs_tx_lane_map_5=0x3210 +xgxs_tx_lane_map_1=0x3210 +xgxs_tx_lane_map_114=0x0123 +xgxs_tx_lane_map_21=0x3210 +xgxs_tx_lane_map_9=0x3210 +xgxs_tx_lane_map_122=0x3210 + +#Polarity RX +phy_xaui_rx_polarity_flip_34=0x1 +phy_xaui_rx_polarity_flip_35=0x1 +phy_xaui_rx_polarity_flip_36=0x1 +phy_xaui_rx_polarity_flip_37=0x1 +phy_xaui_rx_polarity_flip_38=0x1 +phy_xaui_rx_polarity_flip_39=0x1 +phy_xaui_rx_polarity_flip_40=0x1 +phy_xaui_rx_polarity_flip_41=0x1 +phy_xaui_rx_polarity_flip_84=0x1 +phy_xaui_rx_polarity_flip_85=0x0 +phy_xaui_rx_polarity_flip_86=0x1 +phy_xaui_rx_polarity_flip_87=0x0 +phy_xaui_rx_polarity_flip_88=0x1 +phy_xaui_rx_polarity_flip_89=0x0 +phy_xaui_rx_polarity_flip_90=0x1 +phy_xaui_rx_polarity_flip_91=0x1 +phy_xaui_rx_polarity_flip_102=0x0 +phy_xaui_rx_polarity_flip_103=0x0 +phy_xaui_rx_polarity_flip_104=0x1 +phy_xaui_rx_polarity_flip_105=0x0 +phy_xaui_rx_polarity_flip_122=0xf +#Polarity TX +phy_xaui_tx_polarity_flip_42=0x1 +phy_xaui_tx_polarity_flip_43=0x1 +phy_xaui_tx_polarity_flip_44=0x1 +phy_xaui_tx_polarity_flip_45=0x1 +phy_xaui_tx_polarity_flip_34=0x1 +phy_xaui_tx_polarity_flip_35=0x1 +phy_xaui_tx_polarity_flip_36=0x1 +phy_xaui_tx_polarity_flip_37=0x1 +phy_xaui_tx_polarity_flip_38=0x0 +phy_xaui_tx_polarity_flip_39=0x1 +phy_xaui_tx_polarity_flip_40=0x0 +phy_xaui_tx_polarity_flip_41=0x1 +phy_xaui_tx_polarity_flip_72=0x1 +phy_xaui_tx_polarity_flip_73=0x1 +phy_xaui_tx_polarity_flip_74=0x1 +phy_xaui_tx_polarity_flip_75=0x1 +phy_xaui_tx_polarity_flip_84=0x1 +phy_xaui_tx_polarity_flip_85=0x1 +phy_xaui_tx_polarity_flip_86=0x1 +phy_xaui_tx_polarity_flip_87=0x1 +phy_xaui_tx_polarity_flip_88=0x1 +phy_xaui_tx_polarity_flip_89=0x1 +phy_xaui_tx_polarity_flip_90=0x1 +phy_xaui_tx_polarity_flip_91=0x1 +phy_xaui_tx_polarity_flip_102=0x1 +phy_xaui_tx_polarity_flip_103=0x1 +phy_xaui_tx_polarity_flip_104=0x1 +phy_xaui_tx_polarity_flip_105=0x1 +phy_xaui_tx_polarity_flip_122=0xb + +#Driver Current +serdes_driver_current_42=0x8 +serdes_driver_current_43=0x8 +serdes_driver_current_44=0x8 +serdes_driver_current_45=0x8 +serdes_driver_current_50=0x8 +serdes_driver_current_51=0x8 +serdes_driver_current_52=0x8 +serdes_driver_current_53=0x8 +serdes_driver_current_54=0x8 +serdes_driver_current_55=0x8 +serdes_driver_current_56=0x8 +serdes_driver_current_57=0x8 +serdes_driver_current_68=0x8 +serdes_driver_current_69=0x8 +serdes_driver_current_70=0x8 +serdes_driver_current_71=0x8 +serdes_driver_current_34=0x8 +serdes_driver_current_35=0x8 +serdes_driver_current_36=0x8 +serdes_driver_current_37=0x8 +serdes_driver_current_38=0x8 +serdes_driver_current_39=0x8 +serdes_driver_current_40=0x8 +serdes_driver_current_41=0x8 +serdes_driver_current_72=0x8 +serdes_driver_current_73=0x8 +serdes_driver_current_74=0x8 +serdes_driver_current_75=0x8 +serdes_driver_current_84=0x8 +serdes_driver_current_85=0x8 +serdes_driver_current_86=0x8 +serdes_driver_current_87=0x8 +serdes_driver_current_88=0x8 +serdes_driver_current_89=0x8 +serdes_driver_current_90=0x8 +serdes_driver_current_91=0x8 +serdes_driver_current_102=0x8 +serdes_driver_current_103=0x8 +serdes_driver_current_104=0x8 +serdes_driver_current_105=0x8 +serdes_driver_current_106=0x8 +serdes_driver_current_107=0x8 +serdes_driver_current_108=0x8 +serdes_driver_current_109=0x8 +serdes_driver_current_110=0x8 +serdes_driver_current_111=0x8 +serdes_driver_current_112=0x8 +serdes_driver_current_113=0x8 +serdes_driver_current_lane0_5=0x8 +serdes_driver_current_lane1_5=0x8 +serdes_driver_current_lane2_5=0x8 +serdes_driver_current_lane3_5=0x8 +serdes_driver_current_lane0_1=0x8 +serdes_driver_current_lane1_1=0x8 +serdes_driver_current_lane2_1=0x8 +serdes_driver_current_lane3_1=0x8 +serdes_driver_current_lane0_114=0x8 +serdes_driver_current_lane1_114=0x8 +serdes_driver_current_lane2_114=0x8 +serdes_driver_current_lane3_114=0x8 +serdes_driver_current_lane0_21=0x8 +serdes_driver_current_lane1_21=0x8 +serdes_driver_current_lane2_21=0x8 +serdes_driver_current_lane3_21=0x8 +serdes_driver_current_lane0_9=0x8 +serdes_driver_current_lane1_9=0x8 +serdes_driver_current_lane2_9=0x8 +serdes_driver_current_lane3_9=0x8 +serdes_driver_current_lane0_122=0x8 +serdes_driver_current_lane1_122=0x8 +serdes_driver_current_lane2_122=0x8 +serdes_driver_current_lane3_122=0x8 + +#Preemphasis +serdes_preemphasis_42=0x264006 +serdes_preemphasis_43=0x264006 +serdes_preemphasis_44=0x254106 +serdes_preemphasis_45=0x254106 +serdes_preemphasis_50=0x254106 +serdes_preemphasis_51=0x254106 +serdes_preemphasis_52=0x254106 +serdes_preemphasis_53=0x254106 +serdes_preemphasis_54=0x254106 +serdes_preemphasis_55=0x254106 +serdes_preemphasis_56=0x254106 +serdes_preemphasis_57=0x234306 +serdes_preemphasis_68=0x234306 +serdes_preemphasis_69=0x204606 +serdes_preemphasis_70=0x204606 +serdes_preemphasis_71=0x204606 +serdes_preemphasis_34=0x234306 +serdes_preemphasis_35=0x234306 +serdes_preemphasis_36=0x234306 +serdes_preemphasis_37=0x234306 +serdes_preemphasis_38=0x234306 +serdes_preemphasis_39=0x234306 +serdes_preemphasis_40=0x234306 +serdes_preemphasis_41=0x234306 +serdes_preemphasis_72=0x1e4806 +serdes_preemphasis_73=0x1e4806 +serdes_preemphasis_74=0x1e4806 +serdes_preemphasis_75=0x1e4806 +serdes_preemphasis_84=0x1e4806 +serdes_preemphasis_85=0x1a4c06 +serdes_preemphasis_86=0x1a4c06 +serdes_preemphasis_87=0x1b4b06 +serdes_preemphasis_88=0x1b4b06 +serdes_preemphasis_89=0x1e4806 +serdes_preemphasis_90=0x1e4806 +serdes_preemphasis_91=0x1e4806 +serdes_preemphasis_102=0x1e4806 +serdes_preemphasis_103=0x1e4806 +serdes_preemphasis_104=0x1e4806 +serdes_preemphasis_105=0x1e4806 +serdes_preemphasis_106=0x1e4806 +serdes_preemphasis_107=0x1e4806 +serdes_preemphasis_108=0x1e4806 +serdes_preemphasis_109=0x1e4806 +serdes_preemphasis_110=0x1e4806 +serdes_preemphasis_111=0x1d4906 +serdes_preemphasis_112=0x234306 +serdes_preemphasis_113=0x1f4706 +serdes_preemphasis_lane0_5=0x294106 +serdes_preemphasis_lane1_5=0x294106 +serdes_preemphasis_lane2_5=0x294106 +serdes_preemphasis_lane3_5=0x294106 +serdes_preemphasis_lane0_1=0x294106 +serdes_preemphasis_lane1_1=0x294106 +serdes_preemphasis_lane2_1=0x294106 +serdes_preemphasis_lane3_1=0x294106 +serdes_preemphasis_lane0_114=0x2a4006 +serdes_preemphasis_lane1_114=0x2a4006 +serdes_preemphasis_lane2_114=0x2a4006 +serdes_preemphasis_lane3_114=0x2a4006 +serdes_preemphasis_lane0_21=0x2c3c08 +serdes_preemphasis_lane1_21=0x2a4006 +serdes_preemphasis_lane2_21=0x2a4006 +serdes_preemphasis_lane3_21=0x2a4006 +serdes_preemphasis_lane0_9=0x284206 +serdes_preemphasis_lane1_9=0x284206 +serdes_preemphasis_lane2_9=0x284206 +serdes_preemphasis_lane3_9=0x284206 +serdes_preemphasis_lane0_122=0x283e06 +serdes_preemphasis_lane1_122=0x283e06 +serdes_preemphasis_lane2_122=0x283e06 +serdes_preemphasis_lane3_122=0x294601 diff --git a/device/accton/x86_64-accton_as7312_54x-r0/default_sku b/device/accton/x86_64-accton_as7312_54x-r0/default_sku new file mode 100644 index 000000000000..c3c21a98f0e4 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7312-54X t1 diff --git a/device/accton/x86_64-accton_as7312_54x-r0/installer.conf b/device/accton/x86_64-accton_as7312_54x-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as7312_54x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7312_54x-r0/led_proc_init.soc new file mode 100755 index 000000000000..3074649497e0 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/led_proc_init.soc @@ -0,0 +1,79 @@ +# accton_as7312_54x 48x25G+6x100G SDK port LED macro init SOC +s CMIC_LEDUP0_DATA_RAM 0 +s CMIC_LEDUP1_DATA_RAM 0 + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=63 REMAP_PORT_2=63 REMAP_PORT_3=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=63 REMAP_PORT_5=63 REMAP_PORT_6=63 REMAP_PORT_7=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=27 REMAP_PORT_9=26 REMAP_PORT_10=25 REMAP_PORT_11=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=63 REMAP_PORT_18=63 REMAP_PORT_19=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31 REMAP_PORT_21=30 REMAP_PORT_22=29 REMAP_PORT_23=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=15 REMAP_PORT_25=14 REMAP_PORT_26=13 REMAP_PORT_27=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=19 REMAP_PORT_29=18 REMAP_PORT_30=17 REMAP_PORT_31=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=63 REMAP_PORT_34=63 REMAP_PORT_35=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=63 REMAP_PORT_37=63 REMAP_PORT_38=63 REMAP_PORT_39=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35 REMAP_PORT_41=34 REMAP_PORT_42=33 REMAP_PORT_43=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=23 REMAP_PORT_49=22 REMAP_PORT_50=21 REMAP_PORT_51=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=19 REMAP_PORT_1=18 REMAP_PORT_2=17 REMAP_PORT_3=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=23 REMAP_PORT_5=22 REMAP_PORT_6=21 REMAP_PORT_7=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=3 REMAP_PORT_9=2 REMAP_PORT_10=1 REMAP_PORT_11=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=7 REMAP_PORT_17=6 REMAP_PORT_18=5 REMAP_PORT_19=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 REMAP_PORT_21=10 REMAP_PORT_22=9 REMAP_PORT_23=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=63 REMAP_PORT_25=63 REMAP_PORT_26=63 REMAP_PORT_27=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=63 REMAP_PORT_29=63 REMAP_PORT_30=63 REMAP_PORT_31=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=15 REMAP_PORT_33=14 REMAP_PORT_34=13 REMAP_PORT_35=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=63 REMAP_PORT_41=63 REMAP_PORT_42=63 REMAP_PORT_43=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=31 REMAP_PORT_49=30 REMAP_PORT_50=29 REMAP_PORT_51=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=35 REMAP_PORT_53=34 REMAP_PORT_54=33 REMAP_PORT_55=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=63 REMAP_PORT_57=63 REMAP_PORT_58=63 REMAP_PORT_59=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=63 REMAP_PORT_62=63 REMAP_PORT_63=63 + +led 0 stop +led 0 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ + 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 start +led auto on + +led 1 stop +led 1 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ + 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 1 start +led auto on diff --git a/device/accton/x86_64-accton_as7312_54x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7312_54x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..7681caafeef4 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom" + #Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7312_54x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7312_54x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..d73e65bf7981 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/plugins/psuutil.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 2: "11-0053", + 1: "10-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7312_54x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7312_54x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..aa889a3c4e43 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/plugins/sfputil.py @@ -0,0 +1,223 @@ +# 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 = 71 + PORTS_IN_BLOCK = 72 + QSFP_PORT_START = 48 + QSFP_PORT_END = 72 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _cpld_mapping = { + 0: "4-0060", + 1: "5-0062", + 2: "6-0064", + } + _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: 30, + 13: 31, + 14: 32, + 15: 33, + 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, + 32: 50, + 33: 51, + 34: 52, + 35: 53, + 36: 54, + 37: 55, + 38: 56, + 39: 57, + 40: 58, + 41: 59, + 42: 60, + 43: 61, + 44: 62, + 45: 63, + 46: 64, + 47: 65, + 48: 66, #QSFP49 + 49: 66, + 50: 66, + 51: 66, + 52: 67, #QSFP50 + 53: 67, + 54: 67, + 55: 67, + 56: 68, #QSFP51 + 57: 68, + 58: 68, + 59: 68, + 60: 69, #QSFP52 + 61: 69, + 62: 69, + 63: 69, + 64: 70, #QSFP53 + 65: 70, + 66: 70, + 67: 70, + 68: 71, #QSFP54 + 69: 71, + 70: 71, + 71: 71, + } + + @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): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x]) + + SfpUtilBase.__init__(self) + + + # For port 48~51 are QSFP, here presumed they're all split to 4 lanes. + def get_cage_num(self, port_num): + cage_num = port_num + if (port_num >= self.QSFP_PORT_START): + cage_num = (port_num - self.QSFP_PORT_START)/4 + cage_num = cage_num + self.QSFP_PORT_START + + return cage_num + + # For cage 0~23 and 48~51 are at cpld2, others are at cpld3. + def get_cpld_num(self, port_num): + cpld_i = 1 + cage_num = self.get_cage_num(port_num) + if (port_num > 23 and port_num < self.QSFP_PORT_START): + cpld_i = 2 + + if (cage_num >= 52): + cpld_i = 2 + + return cpld_i + + 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 + + cage_num = self.get_cage_num(port_num) + cpld_i = self.get_cpld_num(port_num) + + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_present_{1}" + port_ps = path.format(cpld_ps, cage_num+1) + + try: + val_file = open(port_ps) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + 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): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + cage_num = self.get_cage_num(port_num) + cpld_i = self.get_cpld_num(port_num) + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_reset_{1}" + port_ps = path.format(cpld_ps, cage_num+1) + try: + reg_file = open(port_ps, 'w') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = '0' + + reg_file.write(reg_value) + reg_file.close() + + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/port_config.ini b/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/port_config.ini new file mode 100755 index 000000000000..18b0ed20d305 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias index +Ethernet0 41 twentyfiveGigE1 0 +Ethernet1 42 twentyfiveGigE2 1 +Ethernet2 43 twentyfiveGigE3 2 +Ethernet3 44 twentyfiveGigE4 3 +Ethernet4 49 twentyfiveGigE5 4 +Ethernet5 50 twentyfiveGigE6 5 +Ethernet6 51 twentyfiveGigE7 6 +Ethernet7 52 twentyfiveGigE8 7 +Ethernet8 53 twentyfiveGigE9 8 +Ethernet9 54 twentyfiveGigE10 9 +Ethernet10 55 twentyfiveGigE11 10 +Ethernet11 56 twentyfiveGigE12 11 +Ethernet12 65 twentyfiveGigE13 12 +Ethernet13 66 twentyfiveGigE14 13 +Ethernet14 67 twentyfiveGigE15 14 +Ethernet15 68 twentyfiveGigE16 15 +Ethernet16 33 twentyfiveGigE17 16 +Ethernet17 34 twentyfiveGigE18 17 +Ethernet18 35 twentyfiveGigE19 18 +Ethernet19 36 twentyfiveGigE20 19 +Ethernet20 37 twentyfiveGigE21 20 +Ethernet21 38 twentyfiveGigE22 21 +Ethernet22 39 twentyfiveGigE23 22 +Ethernet23 40 twentyfiveGigE24 23 +Ethernet24 69 twentyfiveGigE25 24 +Ethernet25 70 twentyfiveGigE26 25 +Ethernet26 71 twentyfiveGigE27 26 +Ethernet27 72 twentyfiveGigE28 27 +Ethernet28 81 twentyfiveGigE29 28 +Ethernet29 82 twentyfiveGigE30 29 +Ethernet30 83 twentyfiveGigE31 30 +Ethernet31 84 twentyfiveGigE32 31 +Ethernet32 85 twentyfiveGigE33 32 +Ethernet33 86 twentyfiveGigE34 33 +Ethernet34 87 twentyfiveGigE35 34 +Ethernet35 88 twentyfiveGigE36 35 +Ethernet36 97 twentyfiveGigE37 36 +Ethernet37 98 twentyfiveGigE38 37 +Ethernet38 99 twentyfiveGigE39 38 +Ethernet39 100 twentyfiveGigE40 39 +Ethernet40 101 twentyfiveGigE41 40 +Ethernet41 102 twentyfiveGigE42 41 +Ethernet42 103 twentyfiveGigE43 42 +Ethernet43 104 twentyfiveGigE44 43 +Ethernet44 105 twentyfiveGigE45 44 +Ethernet45 106 twentyfiveGigE46 45 +Ethernet46 107 twentyfiveGigE47 46 +Ethernet47 108 twentyfiveGigE48 47 +Ethernet48 5,6,7,8 hundredGigE49 48 +Ethernet52 1,2,3,4 hundredGigE50 52 +Ethernet56 109,110,111,112 hundredGigE51 56 +Ethernet60 21,22,23,24 hundredGigE52 60 +Ethernet64 9,10,11,12 hundredGigE53 64 +Ethernet68 117,118,119,120 hundredGigE54 68 diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/sai.profile b/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/sai.profile new file mode 100644 index 000000000000..31aefe2c2905 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-as7312-48x25G+6x100G.config.bcm diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/th-as7312-48x25G+6x100G.config.bcm b/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/th-as7312-48x25G+6x100G.config.bcm new file mode 100644 index 000000000000..eef4d987e8ed --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/th-as7312-48x25G+6x100G.config.bcm @@ -0,0 +1,519 @@ +# accton_as7312_54x 48x25G+6x100G SDK config +os=unix +schan_intr_enable=0 + +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_oversubscribe=0x0407ffc00ff00ff003fc3ffc00200222 +pbmp_xport_xe=0x0407ffd00ff00ff403fc3ffc00200222 + +## FC10 ## +dport_map_port_42=1 +dport_map_port_43=2 +dport_map_port_44=3 +dport_map_port_45=4 + +## FC12 ## +dport_map_port_50=5 +dport_map_port_51=6 +dport_map_port_52=7 +dport_map_port_53=8 + +## FC13 ## +dport_map_port_54=9 +dport_map_port_55=10 +dport_map_port_56=11 +dport_map_port_57=12 + +## FC16 ## +dport_map_port_68=13 +dport_map_port_69=14 +dport_map_port_70=15 +dport_map_port_71=16 + +## FC8 ## +dport_map_port_34=17 +dport_map_port_35=18 +dport_map_port_36=19 +dport_map_port_37=20 + +## FC9 ## +dport_map_port_38=21 +dport_map_port_39=22 +dport_map_port_40=23 +dport_map_port_41=24 + +## FC17 ## +dport_map_port_72=25 +dport_map_port_73=26 +dport_map_port_74=27 +dport_map_port_75=28 + +## FC20 ## +dport_map_port_84=29 +dport_map_port_85=30 +dport_map_port_86=31 +dport_map_port_87=32 + +## FC21 ## +dport_map_port_88=33 +dport_map_port_89=34 +dport_map_port_90=35 +dport_map_port_91=36 + +## FC24 ## +dport_map_port_102=37 +dport_map_port_103=38 +dport_map_port_104=39 +dport_map_port_105=40 + +## FC25 ## +dport_map_port_106=41 +dport_map_port_107=42 +dport_map_port_108=43 +dport_map_port_109=44 + +## FC26 ## +dport_map_port_110=45 +dport_map_port_111=46 +dport_map_port_112=47 +dport_map_port_113=48 + +## FC1 ## +dport_map_port_5=49 + +## FC0 ## +dport_map_port_1=50 + +## FC27 ## +dport_map_port_114=51 + +## FC5 ## +dport_map_port_21=52 + +## FC2 ## +dport_map_port_9=53 + +## FC29 ## +dport_map_port_122=54 + +#for KR +#dport_map_port_66=55 +#dport_map_port_100=56 + +/* Port Map */ +## FC10 ## +portmap_42=41:25 +portmap_43=42:25 +portmap_44=43:25 +portmap_45=44:25 + +## FC12 ## +portmap_50=49:25 +portmap_51=50:25 +portmap_52=51:25 +portmap_53=52:25 + + +## FC13 ## +portmap_54=53:25 +portmap_55=54:25 +portmap_56=55:25 +portmap_57=56:25 + +## FC16 ## +portmap_68=65:25 +portmap_69=66:25 +portmap_70=67:25 +portmap_71=68:25 + + +## FC8 ## +portmap_34=33:25 +portmap_35=34:25 +portmap_36=35:25 +portmap_37=36:25 + +## FC9 ## +portmap_38=37:25 +portmap_39=38:25 +portmap_40=39:25 +portmap_41=40:25 + +## FC17 ## +portmap_72=69:25 +portmap_73=70:25 +portmap_74=71:25 +portmap_75=72:25 + +## FC20 ## +portmap_84=81:25 +portmap_85=82:25 +portmap_86=83:25 +portmap_87=84:25 + + +## FC21 ## +portmap_88=85:25 +portmap_89=86:25 +portmap_90=87:25 +portmap_91=88:25 + +## FC24 ## +portmap_102=97:25 +portmap_103=98:25 +portmap_104=99:25 +portmap_105=100:25 + +## FC25 ## +portmap_106=101:25 +portmap_107=102:25 +portmap_108=103:25 +portmap_109=104:25 + +## FC26 ## +portmap_110=105:25 +portmap_111=106:25 +portmap_112=107:25 +portmap_113=108:25 + +## FC1 ## +portmap_5=5:100 + +## FC0 ## +portmap_1=1:100 + +## FC27 ## +portmap_114=109:100 + +## FC5 ## +portmap_21=21:100 + +## FC2 ## +portmap_9=9:100 + +## FC29 ## +portmap_122=117:100 + +# CPU to MAC +# TSC-E management port 1 +#portmap_66=129:10 +# TSC-E management port 2 +#portmap_100=131:10 + +xgxs_rx_lane_map_42=0x2310 +xgxs_rx_lane_map_43=0x2310 +xgxs_rx_lane_map_44=0x2310 +xgxs_rx_lane_map_45=0x2310 +xgxs_rx_lane_map_50=0x3210 +xgxs_rx_lane_map_51=0x3210 +xgxs_rx_lane_map_52=0x3210 +xgxs_rx_lane_map_53=0x3210 +xgxs_rx_lane_map_54=0x3210 +xgxs_rx_lane_map_55=0x3210 +xgxs_rx_lane_map_56=0x3210 +xgxs_rx_lane_map_57=0x3210 +xgxs_rx_lane_map_68=0x0123 +xgxs_rx_lane_map_69=0x0123 +xgxs_rx_lane_map_70=0x0123 +xgxs_rx_lane_map_71=0x0123 +xgxs_rx_lane_map_34=0x0123 +xgxs_rx_lane_map_35=0x0123 +xgxs_rx_lane_map_36=0x0123 +xgxs_rx_lane_map_37=0x0123 +xgxs_rx_lane_map_38=0x0123 +xgxs_rx_lane_map_39=0x0123 +xgxs_rx_lane_map_40=0x0123 +xgxs_rx_lane_map_41=0x0123 +xgxs_rx_lane_map_72=0x3210 +xgxs_rx_lane_map_73=0x3210 +xgxs_rx_lane_map_74=0x3210 +xgxs_rx_lane_map_75=0x3210 +xgxs_rx_lane_map_84=0x1032 +xgxs_rx_lane_map_85=0x1032 +xgxs_rx_lane_map_86=0x1032 +xgxs_rx_lane_map_87=0x1032 +xgxs_rx_lane_map_88=0x2301 +xgxs_rx_lane_map_89=0x2301 +xgxs_rx_lane_map_90=0x2301 +xgxs_rx_lane_map_91=0x2301 +xgxs_rx_lane_map_102=0x0123 +xgxs_rx_lane_map_103=0x0123 +xgxs_rx_lane_map_104=0x0123 +xgxs_rx_lane_map_105=0x0123 +xgxs_rx_lane_map_106=0x3210 +xgxs_rx_lane_map_107=0x3210 +xgxs_rx_lane_map_108=0x3210 +xgxs_rx_lane_map_109=0x3210 +xgxs_rx_lane_map_110=0x1032 +xgxs_rx_lane_map_111=0x1032 +xgxs_rx_lane_map_112=0x1032 +xgxs_rx_lane_map_113=0x1032 +xgxs_rx_lane_map_5=0x3210 +xgxs_rx_lane_map_1=0x3210 +xgxs_rx_lane_map_114=0x0123 +xgxs_rx_lane_map_21=0x0213 +xgxs_rx_lane_map_9=0x3210 +xgxs_rx_lane_map_122=0x1230 + +xgxs_tx_lane_map_42=0x0132 +xgxs_tx_lane_map_43=0x0132 +xgxs_tx_lane_map_44=0x0132 +xgxs_tx_lane_map_45=0x0132 +xgxs_tx_lane_map_50=0x3210 +xgxs_tx_lane_map_51=0x3210 +xgxs_tx_lane_map_52=0x3210 +xgxs_tx_lane_map_53=0x3210 +xgxs_tx_lane_map_54=0x3210 +xgxs_tx_lane_map_55=0x3210 +xgxs_tx_lane_map_56=0x3210 +xgxs_tx_lane_map_57=0x3210 +xgxs_tx_lane_map_68=0x0123 +xgxs_tx_lane_map_69=0x0123 +xgxs_tx_lane_map_70=0x0123 +xgxs_tx_lane_map_71=0x0123 +xgxs_tx_lane_map_34=0x0123 +xgxs_tx_lane_map_35=0x0123 +xgxs_tx_lane_map_36=0x0123 +xgxs_tx_lane_map_37=0x0123 +xgxs_tx_lane_map_38=0x0123 +xgxs_tx_lane_map_39=0x0123 +xgxs_tx_lane_map_40=0x0123 +xgxs_tx_lane_map_41=0x0123 +xgxs_tx_lane_map_72=0x0123 +xgxs_tx_lane_map_73=0x0123 +xgxs_tx_lane_map_74=0x0123 +xgxs_tx_lane_map_75=0x0123 +xgxs_tx_lane_map_84=0x0123 +xgxs_tx_lane_map_85=0x0123 +xgxs_tx_lane_map_86=0x0123 +xgxs_tx_lane_map_87=0x0123 +xgxs_tx_lane_map_88=0x2301 +xgxs_tx_lane_map_89=0x2301 +xgxs_tx_lane_map_90=0x2301 +xgxs_tx_lane_map_91=0x2301 +xgxs_tx_lane_map_102=0x0123 +xgxs_tx_lane_map_103=0x0123 +xgxs_tx_lane_map_104=0x0123 +xgxs_tx_lane_map_105=0x0123 +xgxs_tx_lane_map_106=0x3210 +xgxs_tx_lane_map_107=0x3210 +xgxs_tx_lane_map_108=0x3210 +xgxs_tx_lane_map_109=0x3210 +xgxs_tx_lane_map_110=0x1032 +xgxs_tx_lane_map_111=0x1032 +xgxs_tx_lane_map_112=0x1032 +xgxs_tx_lane_map_113=0x1032 +xgxs_tx_lane_map_5=0x3210 +xgxs_tx_lane_map_1=0x3210 +xgxs_tx_lane_map_114=0x0123 +xgxs_tx_lane_map_21=0x3210 +xgxs_tx_lane_map_9=0x3210 +xgxs_tx_lane_map_122=0x3210 + +#Polarity RX +phy_xaui_rx_polarity_flip_34=0x1 +phy_xaui_rx_polarity_flip_35=0x1 +phy_xaui_rx_polarity_flip_36=0x1 +phy_xaui_rx_polarity_flip_37=0x1 +phy_xaui_rx_polarity_flip_38=0x1 +phy_xaui_rx_polarity_flip_39=0x1 +phy_xaui_rx_polarity_flip_40=0x1 +phy_xaui_rx_polarity_flip_41=0x1 +phy_xaui_rx_polarity_flip_84=0x1 +phy_xaui_rx_polarity_flip_85=0x0 +phy_xaui_rx_polarity_flip_86=0x1 +phy_xaui_rx_polarity_flip_87=0x0 +phy_xaui_rx_polarity_flip_88=0x1 +phy_xaui_rx_polarity_flip_89=0x0 +phy_xaui_rx_polarity_flip_90=0x1 +phy_xaui_rx_polarity_flip_91=0x1 +phy_xaui_rx_polarity_flip_102=0x0 +phy_xaui_rx_polarity_flip_103=0x0 +phy_xaui_rx_polarity_flip_104=0x1 +phy_xaui_rx_polarity_flip_105=0x0 +phy_xaui_rx_polarity_flip_122=0xf +#Polarity TX +phy_xaui_tx_polarity_flip_42=0x1 +phy_xaui_tx_polarity_flip_43=0x1 +phy_xaui_tx_polarity_flip_44=0x1 +phy_xaui_tx_polarity_flip_45=0x1 +phy_xaui_tx_polarity_flip_34=0x1 +phy_xaui_tx_polarity_flip_35=0x1 +phy_xaui_tx_polarity_flip_36=0x1 +phy_xaui_tx_polarity_flip_37=0x1 +phy_xaui_tx_polarity_flip_38=0x0 +phy_xaui_tx_polarity_flip_39=0x1 +phy_xaui_tx_polarity_flip_40=0x0 +phy_xaui_tx_polarity_flip_41=0x1 +phy_xaui_tx_polarity_flip_72=0x1 +phy_xaui_tx_polarity_flip_73=0x1 +phy_xaui_tx_polarity_flip_74=0x1 +phy_xaui_tx_polarity_flip_75=0x1 +phy_xaui_tx_polarity_flip_84=0x1 +phy_xaui_tx_polarity_flip_85=0x1 +phy_xaui_tx_polarity_flip_86=0x1 +phy_xaui_tx_polarity_flip_87=0x1 +phy_xaui_tx_polarity_flip_88=0x1 +phy_xaui_tx_polarity_flip_89=0x1 +phy_xaui_tx_polarity_flip_90=0x1 +phy_xaui_tx_polarity_flip_91=0x1 +phy_xaui_tx_polarity_flip_102=0x1 +phy_xaui_tx_polarity_flip_103=0x1 +phy_xaui_tx_polarity_flip_104=0x1 +phy_xaui_tx_polarity_flip_105=0x1 +phy_xaui_tx_polarity_flip_122=0xb + +#Driver Current +serdes_driver_current_42=0x8 +serdes_driver_current_43=0x8 +serdes_driver_current_44=0x8 +serdes_driver_current_45=0x8 +serdes_driver_current_50=0x8 +serdes_driver_current_51=0x8 +serdes_driver_current_52=0x8 +serdes_driver_current_53=0x8 +serdes_driver_current_54=0x8 +serdes_driver_current_55=0x8 +serdes_driver_current_56=0x8 +serdes_driver_current_57=0x8 +serdes_driver_current_68=0x8 +serdes_driver_current_69=0x8 +serdes_driver_current_70=0x8 +serdes_driver_current_71=0x8 +serdes_driver_current_34=0x8 +serdes_driver_current_35=0x8 +serdes_driver_current_36=0x8 +serdes_driver_current_37=0x8 +serdes_driver_current_38=0x8 +serdes_driver_current_39=0x8 +serdes_driver_current_40=0x8 +serdes_driver_current_41=0x8 +serdes_driver_current_72=0x8 +serdes_driver_current_73=0x8 +serdes_driver_current_74=0x8 +serdes_driver_current_75=0x8 +serdes_driver_current_84=0x8 +serdes_driver_current_85=0x8 +serdes_driver_current_86=0x8 +serdes_driver_current_87=0x8 +serdes_driver_current_88=0x8 +serdes_driver_current_89=0x8 +serdes_driver_current_90=0x8 +serdes_driver_current_91=0x8 +serdes_driver_current_102=0x8 +serdes_driver_current_103=0x8 +serdes_driver_current_104=0x8 +serdes_driver_current_105=0x8 +serdes_driver_current_106=0x8 +serdes_driver_current_107=0x8 +serdes_driver_current_108=0x8 +serdes_driver_current_109=0x8 +serdes_driver_current_110=0x8 +serdes_driver_current_111=0x8 +serdes_driver_current_112=0x8 +serdes_driver_current_113=0x8 +serdes_driver_current_lane0_5=0x8 +serdes_driver_current_lane1_5=0x8 +serdes_driver_current_lane2_5=0x8 +serdes_driver_current_lane3_5=0x8 +serdes_driver_current_lane0_1=0x8 +serdes_driver_current_lane1_1=0x8 +serdes_driver_current_lane2_1=0x8 +serdes_driver_current_lane3_1=0x8 +serdes_driver_current_lane0_114=0x8 +serdes_driver_current_lane1_114=0x8 +serdes_driver_current_lane2_114=0x8 +serdes_driver_current_lane3_114=0x8 +serdes_driver_current_lane0_21=0x8 +serdes_driver_current_lane1_21=0x8 +serdes_driver_current_lane2_21=0x8 +serdes_driver_current_lane3_21=0x8 +serdes_driver_current_lane0_9=0x8 +serdes_driver_current_lane1_9=0x8 +serdes_driver_current_lane2_9=0x8 +serdes_driver_current_lane3_9=0x8 +serdes_driver_current_lane0_122=0x8 +serdes_driver_current_lane1_122=0x8 +serdes_driver_current_lane2_122=0x8 +serdes_driver_current_lane3_122=0x8 + +#Preemphasis +serdes_preemphasis_42=0x264006 +serdes_preemphasis_43=0x264006 +serdes_preemphasis_44=0x254106 +serdes_preemphasis_45=0x254106 +serdes_preemphasis_50=0x254106 +serdes_preemphasis_51=0x254106 +serdes_preemphasis_52=0x254106 +serdes_preemphasis_53=0x254106 +serdes_preemphasis_54=0x254106 +serdes_preemphasis_55=0x254106 +serdes_preemphasis_56=0x254106 +serdes_preemphasis_57=0x234306 +serdes_preemphasis_68=0x234306 +serdes_preemphasis_69=0x204606 +serdes_preemphasis_70=0x204606 +serdes_preemphasis_71=0x204606 +serdes_preemphasis_34=0x234306 +serdes_preemphasis_35=0x234306 +serdes_preemphasis_36=0x234306 +serdes_preemphasis_37=0x234306 +serdes_preemphasis_38=0x234306 +serdes_preemphasis_39=0x234306 +serdes_preemphasis_40=0x234306 +serdes_preemphasis_41=0x234306 +serdes_preemphasis_72=0x1e4806 +serdes_preemphasis_73=0x1e4806 +serdes_preemphasis_74=0x1e4806 +serdes_preemphasis_75=0x1e4806 +serdes_preemphasis_84=0x1e4806 +serdes_preemphasis_85=0x1a4c06 +serdes_preemphasis_86=0x1a4c06 +serdes_preemphasis_87=0x1b4b06 +serdes_preemphasis_88=0x1b4b06 +serdes_preemphasis_89=0x1e4806 +serdes_preemphasis_90=0x1e4806 +serdes_preemphasis_91=0x1e4806 +serdes_preemphasis_102=0x1e4806 +serdes_preemphasis_103=0x1e4806 +serdes_preemphasis_104=0x1e4806 +serdes_preemphasis_105=0x1e4806 +serdes_preemphasis_106=0x1e4806 +serdes_preemphasis_107=0x1e4806 +serdes_preemphasis_108=0x1e4806 +serdes_preemphasis_109=0x1e4806 +serdes_preemphasis_110=0x1e4806 +serdes_preemphasis_111=0x1d4906 +serdes_preemphasis_112=0x234306 +serdes_preemphasis_113=0x1f4706 +serdes_preemphasis_lane0_5=0x294106 +serdes_preemphasis_lane1_5=0x294106 +serdes_preemphasis_lane2_5=0x294106 +serdes_preemphasis_lane3_5=0x294106 +serdes_preemphasis_lane0_1=0x294106 +serdes_preemphasis_lane1_1=0x294106 +serdes_preemphasis_lane2_1=0x294106 +serdes_preemphasis_lane3_1=0x294106 +serdes_preemphasis_lane0_114=0x2a4006 +serdes_preemphasis_lane1_114=0x2a4006 +serdes_preemphasis_lane2_114=0x2a4006 +serdes_preemphasis_lane3_114=0x2a4006 +serdes_preemphasis_lane0_21=0x2c3c08 +serdes_preemphasis_lane1_21=0x2a4006 +serdes_preemphasis_lane2_21=0x2a4006 +serdes_preemphasis_lane3_21=0x2a4006 +serdes_preemphasis_lane0_9=0x284206 +serdes_preemphasis_lane1_9=0x284206 +serdes_preemphasis_lane2_9=0x284206 +serdes_preemphasis_lane3_9=0x284206 +serdes_preemphasis_lane0_122=0x283e06 +serdes_preemphasis_lane1_122=0x283e06 +serdes_preemphasis_lane2_122=0x283e06 +serdes_preemphasis_lane3_122=0x294601 diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/default_sku b/device/accton/x86_64-accton_as7312_54xs-r0/default_sku new file mode 100644 index 000000000000..9e6062dee23b --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7312-54XS t1 diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/installer.conf b/device/accton/x86_64-accton_as7312_54xs-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7312_54xs-r0/led_proc_init.soc new file mode 100755 index 000000000000..3074649497e0 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/led_proc_init.soc @@ -0,0 +1,79 @@ +# accton_as7312_54x 48x25G+6x100G SDK port LED macro init SOC +s CMIC_LEDUP0_DATA_RAM 0 +s CMIC_LEDUP1_DATA_RAM 0 + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=63 REMAP_PORT_2=63 REMAP_PORT_3=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=63 REMAP_PORT_5=63 REMAP_PORT_6=63 REMAP_PORT_7=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=27 REMAP_PORT_9=26 REMAP_PORT_10=25 REMAP_PORT_11=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=63 REMAP_PORT_18=63 REMAP_PORT_19=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31 REMAP_PORT_21=30 REMAP_PORT_22=29 REMAP_PORT_23=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=15 REMAP_PORT_25=14 REMAP_PORT_26=13 REMAP_PORT_27=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=19 REMAP_PORT_29=18 REMAP_PORT_30=17 REMAP_PORT_31=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=63 REMAP_PORT_34=63 REMAP_PORT_35=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=63 REMAP_PORT_37=63 REMAP_PORT_38=63 REMAP_PORT_39=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35 REMAP_PORT_41=34 REMAP_PORT_42=33 REMAP_PORT_43=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=23 REMAP_PORT_49=22 REMAP_PORT_50=21 REMAP_PORT_51=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=19 REMAP_PORT_1=18 REMAP_PORT_2=17 REMAP_PORT_3=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=23 REMAP_PORT_5=22 REMAP_PORT_6=21 REMAP_PORT_7=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=3 REMAP_PORT_9=2 REMAP_PORT_10=1 REMAP_PORT_11=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=7 REMAP_PORT_17=6 REMAP_PORT_18=5 REMAP_PORT_19=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 REMAP_PORT_21=10 REMAP_PORT_22=9 REMAP_PORT_23=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=63 REMAP_PORT_25=63 REMAP_PORT_26=63 REMAP_PORT_27=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=63 REMAP_PORT_29=63 REMAP_PORT_30=63 REMAP_PORT_31=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=15 REMAP_PORT_33=14 REMAP_PORT_34=13 REMAP_PORT_35=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=63 REMAP_PORT_41=63 REMAP_PORT_42=63 REMAP_PORT_43=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=31 REMAP_PORT_49=30 REMAP_PORT_50=29 REMAP_PORT_51=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=35 REMAP_PORT_53=34 REMAP_PORT_54=33 REMAP_PORT_55=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=63 REMAP_PORT_57=63 REMAP_PORT_58=63 REMAP_PORT_59=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=63 REMAP_PORT_62=63 REMAP_PORT_63=63 + +led 0 stop +led 0 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ + 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 start +led auto on + +led 1 stop +led 1 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ + 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 1 start +led auto on diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7312_54xs-r0/plugins/eeprom.py new file mode 100644 index 000000000000..7681caafeef4 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom" + #Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7312_54xs-r0/plugins/psuutil.py new file mode 100644 index 000000000000..d73e65bf7981 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/plugins/psuutil.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 2: "11-0053", + 1: "10-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7312_54xs-r0/plugins/sfputil.py new file mode 100644 index 000000000000..aa889a3c4e43 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/plugins/sfputil.py @@ -0,0 +1,223 @@ +# 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 = 71 + PORTS_IN_BLOCK = 72 + QSFP_PORT_START = 48 + QSFP_PORT_END = 72 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _cpld_mapping = { + 0: "4-0060", + 1: "5-0062", + 2: "6-0064", + } + _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: 30, + 13: 31, + 14: 32, + 15: 33, + 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, + 32: 50, + 33: 51, + 34: 52, + 35: 53, + 36: 54, + 37: 55, + 38: 56, + 39: 57, + 40: 58, + 41: 59, + 42: 60, + 43: 61, + 44: 62, + 45: 63, + 46: 64, + 47: 65, + 48: 66, #QSFP49 + 49: 66, + 50: 66, + 51: 66, + 52: 67, #QSFP50 + 53: 67, + 54: 67, + 55: 67, + 56: 68, #QSFP51 + 57: 68, + 58: 68, + 59: 68, + 60: 69, #QSFP52 + 61: 69, + 62: 69, + 63: 69, + 64: 70, #QSFP53 + 65: 70, + 66: 70, + 67: 70, + 68: 71, #QSFP54 + 69: 71, + 70: 71, + 71: 71, + } + + @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): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x]) + + SfpUtilBase.__init__(self) + + + # For port 48~51 are QSFP, here presumed they're all split to 4 lanes. + def get_cage_num(self, port_num): + cage_num = port_num + if (port_num >= self.QSFP_PORT_START): + cage_num = (port_num - self.QSFP_PORT_START)/4 + cage_num = cage_num + self.QSFP_PORT_START + + return cage_num + + # For cage 0~23 and 48~51 are at cpld2, others are at cpld3. + def get_cpld_num(self, port_num): + cpld_i = 1 + cage_num = self.get_cage_num(port_num) + if (port_num > 23 and port_num < self.QSFP_PORT_START): + cpld_i = 2 + + if (cage_num >= 52): + cpld_i = 2 + + return cpld_i + + 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 + + cage_num = self.get_cage_num(port_num) + cpld_i = self.get_cpld_num(port_num) + + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_present_{1}" + port_ps = path.format(cpld_ps, cage_num+1) + + try: + val_file = open(port_ps) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + 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): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + cage_num = self.get_cage_num(port_num) + cpld_i = self.get_cpld_num(port_num) + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_reset_{1}" + port_ps = path.format(cpld_ps, cage_num+1) + try: + reg_file = open(port_ps, 'w') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = '0' + + reg_file.write(reg_value) + reg_file.close() + + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/port_config.ini b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/port_config.ini new file mode 100644 index 000000000000..2c4d0c023772 --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias index +Ethernet0 41 twentyfiveGigE1 0 +Ethernet1 42 twentyfiveGigE2 1 +Ethernet2 43 twentyfiveGigE3 2 +Ethernet3 44 twentyfiveGigE4 3 +Ethernet4 49 twentyfiveGigE5 4 +Ethernet5 50 twentyfiveGigE6 5 +Ethernet6 51 twentyfiveGigE7 6 +Ethernet7 52 twentyfiveGigE8 7 +Ethernet8 53 twentyfiveGigE9 8 +Ethernet9 54 twentyfiveGigE10 9 +Ethernet10 55 twentyfiveGigE11 10 +Ethernet11 56 twentyfiveGigE12 11 +Ethernet12 65 twentyfiveGigE13 12 +Ethernet13 66 twentyfiveGigE14 13 +Ethernet14 67 twentyfiveGigE15 14 +Ethernet15 68 twentyfiveGigE16 15 +Ethernet16 33 twentyfiveGigE17 16 +Ethernet17 34 twentyfiveGigE18 17 +Ethernet18 35 twentyfiveGigE19 18 +Ethernet19 36 twentyfiveGigE20 19 +Ethernet20 37 twentyfiveGigE21 20 +Ethernet21 38 twentyfiveGigE22 21 +Ethernet22 39 twentyfiveGigE23 22 +Ethernet23 40 twentyfiveGigE24 23 +Ethernet24 69 twentyfiveGigE25 24 +Ethernet25 70 twentyfiveGigE26 25 +Ethernet26 71 twentyfiveGigE27 26 +Ethernet27 72 twentyfiveGigE28 27 +Ethernet28 81 twentyfiveGigE29 28 +Ethernet29 82 twentyfiveGigE30 29 +Ethernet30 83 twentyfiveGigE31 30 +Ethernet31 84 twentyfiveGigE32 31 +Ethernet32 85 twentyfiveGigE33 32 +Ethernet33 86 twentyfiveGigE34 33 +Ethernet34 87 twentyfiveGigE35 34 +Ethernet35 88 twentyfiveGigE36 35 +Ethernet36 97 twentyfiveGigE37 36 +Ethernet37 98 twentyfiveGigE38 37 +Ethernet38 99 twentyfiveGigE39 38 +Ethernet39 100 twentyfiveGigE40 39 +Ethernet40 101 twentyfiveGigE41 40 +Ethernet41 102 twentyfiveGigE42 41 +Ethernet42 103 twentyfiveGigE43 42 +Ethernet43 104 twentyfiveGigE44 43 +Ethernet44 105 twentyfiveGigE45 44 +Ethernet45 106 twentyfiveGigE46 45 +Ethernet46 107 twentyfiveGigE47 46 +Ethernet47 108 twentyfiveGigE48 47 +Ethernet48 5,6,7,8 hundredGigE49 48 +Ethernet52 1,2,3,4 hundredGigE50 52 +Ethernet56 109,110,111,112 hundredGigE51 56 +Ethernet60 21,22,23,24 hundredGigE52 60 +Ethernet64 9,10,11,12 hundredGigE53 64 +Ethernet68 117,118,119,120 hundredGigE54 68 diff --git a/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/sai.profile b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/sai.profile new file mode 100644 index 000000000000..0e465ce12edd --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/etc/bcm/td3-as7326-48x25G+8x100G.config.bcm diff --git a/device/accton/x86_64-accton_as7326_56x-r0/default_sku b/device/accton/x86_64-accton_as7326_56x-r0/default_sku new file mode 100644 index 000000000000..922268da79b6 --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7326-56X t1 diff --git a/device/accton/x86_64-accton_as7326_56x-r0/installer.conf b/device/accton/x86_64-accton_as7326_56x-r0/installer.conf new file mode 100644 index 000000000000..9fa12f888545 --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="tg3.short_preamble=1 tg3.bcm5718s_reset=1" diff --git a/device/accton/x86_64-accton_as7326_56x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7326_56x-r0/led_proc_init.soc new file mode 100755 index 000000000000..d96b2d00c583 --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/led_proc_init.soc @@ -0,0 +1,79 @@ +# accton_as7326_56x 48x25G+8x100G SDK port LED macro init SOC +s CMIC_LEDUP0_DATA_RAM 0 +s CMIC_LEDUP1_DATA_RAM 0 + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=63 REMAP_PORT_2=63 REMAP_PORT_3=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=63 REMAP_PORT_5=63 REMAP_PORT_6=63 REMAP_PORT_7=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=27 REMAP_PORT_9=26 REMAP_PORT_10=25 REMAP_PORT_11=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=63 REMAP_PORT_18=63 REMAP_PORT_19=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31 REMAP_PORT_21=30 REMAP_PORT_22=29 REMAP_PORT_23=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=15 REMAP_PORT_25=14 REMAP_PORT_26=13 REMAP_PORT_27=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=19 REMAP_PORT_29=18 REMAP_PORT_30=17 REMAP_PORT_31=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=63 REMAP_PORT_34=63 REMAP_PORT_35=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=63 REMAP_PORT_37=63 REMAP_PORT_38=63 REMAP_PORT_39=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35 REMAP_PORT_41=34 REMAP_PORT_42=33 REMAP_PORT_43=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=23 REMAP_PORT_49=22 REMAP_PORT_50=21 REMAP_PORT_51=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=19 REMAP_PORT_1=18 REMAP_PORT_2=17 REMAP_PORT_3=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=23 REMAP_PORT_5=22 REMAP_PORT_6=21 REMAP_PORT_7=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=3 REMAP_PORT_9=2 REMAP_PORT_10=1 REMAP_PORT_11=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=7 REMAP_PORT_17=6 REMAP_PORT_18=5 REMAP_PORT_19=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 REMAP_PORT_21=10 REMAP_PORT_22=9 REMAP_PORT_23=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=63 REMAP_PORT_25=63 REMAP_PORT_26=63 REMAP_PORT_27=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=63 REMAP_PORT_29=63 REMAP_PORT_30=63 REMAP_PORT_31=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=15 REMAP_PORT_33=14 REMAP_PORT_34=13 REMAP_PORT_35=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=63 REMAP_PORT_41=63 REMAP_PORT_42=63 REMAP_PORT_43=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=31 REMAP_PORT_49=30 REMAP_PORT_50=29 REMAP_PORT_51=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=35 REMAP_PORT_53=34 REMAP_PORT_54=33 REMAP_PORT_55=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=63 REMAP_PORT_57=63 REMAP_PORT_58=63 REMAP_PORT_59=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=63 REMAP_PORT_62=63 REMAP_PORT_63=63 + +led 0 stop +led 0 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ + 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 start +led auto on + +led 1 stop +led 1 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ + 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 1 start +led auto on diff --git a/device/accton/x86_64-accton_as7326_56x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7326_56x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..1e7d1046d93d --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/plugins/eeprom.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7326_56x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7326_56x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..a3c30bc478e7 --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/plugins/psuutil.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 2: "13-0053", + 1: "17-0051", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7326_56x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7326_56x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..4844d220158f --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/plugins/sfputil.py @@ -0,0 +1,211 @@ +# 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 = 81 + PORTS_IN_BLOCK = 82 + QSFP_PORT_START = 48 + QSFP_PORT_END = 82 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _cpld_mapping = { + 1: "12-0062", + 2: "18-0060", + 3: "19-0064", + } + + _port_to_i2c_mapping = { + 0: 42, + 1: 41, + 2: 44, + 3: 43, + 4: 47, + 5: 45, + 6: 46, + 7: 50, + 8: 48, + 9: 49, + 10: 51, + 11: 52, + 12: 53, + 13: 56, + 14: 55, + 15: 54, + 16: 58, + 17: 57, + 18: 59, + 19: 60, + 20: 61, + 21: 63, + 22: 62, + 23: 64, + 24: 66, + 25: 68, + 26: 65, + 27: 67, + 28: 69, + 29: 71, + 30: 72, + 31: 70, + 32: 74, + 33: 73, + 34: 76, + 35: 75, + 36: 77, + 37: 79, + 38: 78, + 39: 80, + 40: 81, + 41: 82, + 42: 84, + 43: 85, + 44: 83, + 45: 87, + 46: 88, + 47: 86, + 48: 25, #QSFP49 + 49: 25, + 50: 25, + 51: 25, + 52: 26, #QSFP50 + 53: 26, + 54: 26, + 55: 26, + 56: 27, #QSFP51 + 57: 26, + 58: 26, + 59: 26, + 60: 28, #QSFP52 + 61: 26, + 62: 26, + 63: 26, + 64: 29, #QSFP53 + 65: 26, + 66: 26, + 67: 26, + 68: 30, #QSFP54 + 69: 26, + 70: 26, + 71: 26, + 72: 31, #QSFP55 + 73: 26, + 74: 26, + 75: 26, + 76: 32, #QSFP56 + 77: 26, + 78: 26, + 79: 26, + 80: 22, + 81: 23} + + @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): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x]) + + SfpUtilBase.__init__(self) + + + # For port 48~51 are QSFP, here presumed they're all split to 4 lanes. + def get_cage_num(self, port_num): + cage_num = port_num + if (port_num >= self.QSFP_PORT_START): + cage_num = (port_num - self.QSFP_PORT_START)/4 + cage_num = cage_num + self.QSFP_PORT_START + + return cage_num + + # For cage 0~23 and 48~51 are at cpld2, others are at cpld3. + def get_cpld_num(self, port_num): + cpld_i = 1 + cage_num = self.get_cage_num(port_num) + if (port_num > 29): + cpld_i = 2 + return cpld_i + + 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 + + cage_num = self.get_cage_num(port_num) + cpld_i = self.get_cpld_num(port_num) + #print "[ROY] cpld:%d" % cpld_i + + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_present_{1}" + port_ps = path.format(cpld_ps, cage_num+1) + + try: + val_file = open(port_ps) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + 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 + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/accton/x86_64-accton_as7512_32x-r0/AS7512-C32/port_config.ini b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-C32/port_config.ini new file mode 100644 index 000000000000..c10cd2786941 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-C32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes +Ethernet0 16,17,18,19 +Ethernet4 20,21,22,23 +Ethernet8 24,25,26,27 +Ethernet12 28,29,30,31 +Ethernet16 32,33,34,35 +Ethernet20 36,37,38,39 +Ethernet24 40,41,42,43 +Ethernet28 44,45,46,47 +Ethernet32 0,1,2,3 +Ethernet36 4,5,6,7 +Ethernet40 8,9,10,11 +Ethernet44 12,13,14,15 +Ethernet48 48,49,50,51 +Ethernet52 52,53,54,55 +Ethernet56 56,57,58,59 +Ethernet60 60,61,62,63 +Ethernet64 127,126,125,124 +Ethernet68 123,122,121,120 +Ethernet72 115,114,113,112 +Ethernet76 119,118,117,116 +Ethernet80 79,78,77,76 +Ethernet84 75,74,73,72 +Ethernet88 64,65,66,67 +Ethernet92 71,70,68,69 +Ethernet96 111,110,109,108 +Ethernet100 107,106,105,104 +Ethernet104 103,102,101,100 +Ethernet108 99,98,97,96 +Ethernet112 95,94,93,92 +Ethernet116 91,90,89,88 +Ethernet120 87,86,85,84 +Ethernet124 83,82,81,80 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/AS7512-C32/sai.profile b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-C32/sai.profile new file mode 100644 index 000000000000..457c339c58ab --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-C32/sai.profile @@ -0,0 +1,2 @@ +mode=3 +hwId=as7512 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/AS7512-S128/port_config.ini b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-S128/port_config.ini new file mode 100644 index 000000000000..c3b669950405 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-S128/port_config.ini @@ -0,0 +1,129 @@ +# name lanes +Ethernet1 0 +Ethernet2 1 +Ethernet3 2 +Ethernet4 3 +Ethernet5 4 +Ethernet6 5 +Ethernet7 6 +Ethernet8 7 +Ethernet9 8 +Ethernet10 9 +Ethernet11 10 +Ethernet12 11 +Ethernet13 12 +Ethernet14 13 +Ethernet15 14 +Ethernet16 15 +Ethernet17 16 +Ethernet18 17 +Ethernet19 18 +Ethernet20 19 +Ethernet21 20 +Ethernet22 21 +Ethernet23 22 +Ethernet24 23 +Ethernet25 24 +Ethernet26 25 +Ethernet27 26 +Ethernet28 27 +Ethernet29 28 +Ethernet30 29 +Ethernet31 30 +Ethernet32 31 +Ethernet33 32 +Ethernet34 33 +Ethernet35 34 +Ethernet36 35 +Ethernet37 36 +Ethernet38 37 +Ethernet39 38 +Ethernet40 39 +Ethernet41 40 +Ethernet42 41 +Ethernet43 42 +Ethernet44 43 +Ethernet45 44 +Ethernet46 45 +Ethernet47 46 +Ethernet48 47 +Ethernet49 48 +Ethernet50 49 +Ethernet51 50 +Ethernet52 51 +Ethernet53 52 +Ethernet54 53 +Ethernet55 54 +Ethernet56 55 +Ethernet57 56 +Ethernet58 57 +Ethernet59 58 +Ethernet60 59 +Ethernet61 60 +Ethernet62 61 +Ethernet63 62 +Ethernet64 63 +Ethernet65 64 +Ethernet66 65 +Ethernet67 66 +Ethernet68 67 +Ethernet69 68 +Ethernet70 69 +Ethernet71 70 +Ethernet72 71 +Ethernet73 72 +Ethernet74 73 +Ethernet75 74 +Ethernet76 75 +Ethernet77 76 +Ethernet78 77 +Ethernet79 78 +Ethernet80 79 +Ethernet81 80 +Ethernet82 81 +Ethernet83 82 +Ethernet84 83 +Ethernet85 84 +Ethernet86 85 +Ethernet87 86 +Ethernet88 87 +Ethernet89 88 +Ethernet90 89 +Ethernet91 90 +Ethernet92 91 +Ethernet93 92 +Ethernet94 93 +Ethernet95 94 +Ethernet96 95 +Ethernet97 96 +Ethernet98 97 +Ethernet99 98 +Ethernet100 99 +Ethernet101 100 +Ethernet102 101 +Ethernet103 102 +Ethernet104 103 +Ethernet105 104 +Ethernet106 105 +Ethernet107 106 +Ethernet108 107 +Ethernet109 108 +Ethernet110 109 +Ethernet111 110 +Ethernet112 111 +Ethernet113 112 +Ethernet114 113 +Ethernet115 114 +Ethernet116 115 +Ethernet117 116 +Ethernet118 117 +Ethernet119 118 +Ethernet120 119 +Ethernet121 120 +Ethernet122 121 +Ethernet123 122 +Ethernet124 123 +Ethernet125 124 +Ethernet126 125 +Ethernet127 126 +Ethernet128 127 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/AS7512-S128/sai.profile b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-S128/sai.profile new file mode 100644 index 000000000000..471c4395758f --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-S128/sai.profile @@ -0,0 +1,2 @@ +mode=0 +hwId=as7512 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/AS7512/port_config.ini b/device/accton/x86_64-accton_as7512_32x-r0/AS7512/port_config.ini new file mode 100644 index 000000000000..c10cd2786941 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/AS7512/port_config.ini @@ -0,0 +1,33 @@ +# name lanes +Ethernet0 16,17,18,19 +Ethernet4 20,21,22,23 +Ethernet8 24,25,26,27 +Ethernet12 28,29,30,31 +Ethernet16 32,33,34,35 +Ethernet20 36,37,38,39 +Ethernet24 40,41,42,43 +Ethernet28 44,45,46,47 +Ethernet32 0,1,2,3 +Ethernet36 4,5,6,7 +Ethernet40 8,9,10,11 +Ethernet44 12,13,14,15 +Ethernet48 48,49,50,51 +Ethernet52 52,53,54,55 +Ethernet56 56,57,58,59 +Ethernet60 60,61,62,63 +Ethernet64 127,126,125,124 +Ethernet68 123,122,121,120 +Ethernet72 115,114,113,112 +Ethernet76 119,118,117,116 +Ethernet80 79,78,77,76 +Ethernet84 75,74,73,72 +Ethernet88 64,65,66,67 +Ethernet92 71,70,68,69 +Ethernet96 111,110,109,108 +Ethernet100 107,106,105,104 +Ethernet104 103,102,101,100 +Ethernet108 99,98,97,96 +Ethernet112 95,94,93,92 +Ethernet116 91,90,89,88 +Ethernet120 87,86,85,84 +Ethernet124 83,82,81,80 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/AS7512/sai.profile b/device/accton/x86_64-accton_as7512_32x-r0/AS7512/sai.profile new file mode 100644 index 000000000000..017996f7d7cc --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/AS7512/sai.profile @@ -0,0 +1,2 @@ +mode=1 +hwId=as7512 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/default_sku b/device/accton/x86_64-accton_as7512_32x-r0/default_sku new file mode 100644 index 000000000000..45eb53f68a97 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/default_sku @@ -0,0 +1 @@ +AS7512 t1 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/fancontrol b/device/accton/x86_64-accton_as7512_32x-r0/fancontrol new file mode 100644 index 000000000000..c80163771e86 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/fancontrol @@ -0,0 +1,7 @@ +INTERVAL=10 +FCTEMPS=/sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/3-004b/hwmon/hwmon[[:print:]]*/temp1_input /sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/3-004a/hwmon/hwmon[[:print:]]*/temp1_input +FCFANS=/sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/2-0066/fan1_front_speed_rpm /sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/2-0066/fan2_front_speed_rpm /sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/2-0066/fan3_front_speed_rpm /sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/2-0066/fan4_front_speed_rpm /sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/2-0066/fan5_front_speed_rpm /sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/2-0066/fan6_front_speed_rpm +MINTEMP=/sys/bus/i2c/devices/2-0066/fan_pwm=20 +MAXTEMP=/sys/bus/i2c/devices/2-0066/fan_pwm=60 +MINSTART=/sys/bus/i2c/devices/2-0066/fan_pwm=150 +MINSTOP=/sys/bus/i2c/devices/2-0066/fan_pwm=7 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/installer.conf b/device/accton/x86_64-accton_as7512_32x-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7512_32x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..6e2c0c8bb96f --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/plugins/eeprom.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +############################################################################# +# Cavium +# +# 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: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + _TLV_INFO_MAX_LEN = 256 + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7512_32x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7512_32x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..ac89ddb19227 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/plugins/sfputil.py @@ -0,0 +1,80 @@ +#! /usr/bin/python + +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 = {} + + _qsfp_ports = range(0, ports_in_block + 1) + + def __init__(self): + # Override port_to_eeprom_mapping for class initialization + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom' + for x in range(self.port_start, self.port_end + 1): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + 18) + SfpUtilBase.__init__(self) + + def reset(self, port_num): + raise NotImplementedErro + + def set_low_power_mode(self, port_nuM, lpmode): + raise NotImplementedErro + + def get_low_power_mode(self, port_num): + raise NotImplementedErro + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present" + port_ps = path.format(port_num+18) + + + try: + reg_file = open(port_ps) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return range(0, self.ports_in_block + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/port_config.ini b/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/port_config.ini new file mode 100644 index 000000000000..1fa6d21d9609 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 49,50,51,52 hundredGigE1 +Ethernet4 53,54,55,56 hundredGigE2 +Ethernet8 57,58,59,60 hundredGigE3 +Ethernet12 61,62,63,64 hundredGigE4 +Ethernet16 65,66,67,68 hundredGigE5 +Ethernet20 69,70,71,72 hundredGigE6 +Ethernet24 73,74,75,76 hundredGigE7 +Ethernet28 77,78,79,80 hundredGigE8 +Ethernet32 33,34,35,36 hundredGigE9 +Ethernet36 37,38,39,40 hundredGigE10 +Ethernet40 41,42,43,44 hundredGigE11 +Ethernet44 45,46,47,48 hundredGigE12 +Ethernet48 81,82,83,84 hundredGigE13 +Ethernet52 85,86,87,88 hundredGigE14 +Ethernet56 89,90,91,92 hundredGigE15 +Ethernet60 93,94,95,96 hundredGigE16 +Ethernet64 97,98,99,100 hundredGigE17 +Ethernet68 101,102,103,104 hundredGigE18 +Ethernet72 105,106,107,108 hundredGigE19 +Ethernet76 109,110,111,112 hundredGigE20 +Ethernet80 17,18,19,20 hundredGigE21 +Ethernet84 21,22,23,24 hundredGigE22 +Ethernet88 25,26,27,28 hundredGigE23 +Ethernet92 29,30,31,32 hundredGigE24 +Ethernet96 113,114,115,116 hundredGigE25 +Ethernet100 117,118,119,120 hundredGigE26 +Ethernet104 121,122,123,124 hundredGigE27 +Ethernet108 125,126,127,128 hundredGigE28 +Ethernet112 1,2,3,4 hundredGigE29 +Ethernet116 5,6,7,8 hundredGigE30 +Ethernet120 9,10,11,12 hundredGigE31 +Ethernet124 13,14,15,16 hundredGigE32 diff --git a/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/sai.profile b/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/sai.profile new file mode 100644 index 000000000000..28953a08f205 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-as7712-32x100G.config.bcm diff --git a/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/th-as7712-32x100G.config.bcm b/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/th-as7712-32x100G.config.bcm new file mode 100644 index 000000000000..09d97c5e4c63 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/th-as7712-32x100G.config.bcm @@ -0,0 +1,570 @@ +# accton_as7712_32x 32x100G SDK config +os=unix +schan_intr_enable=0 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_oversubscribe=0x444444441111111104444444422222222 +pbmp_xport_xe=0x444444451111111144444444422222222 + +# +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=8 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +max_vp_lags=0 +miim_intr_enable=0 +oversubscribe_mode=1 + +# portmap_0=x:xx +#FC0 +portmap_1=1:100 + +#FC1 +portmap_5=5:100 + +#FC2 +portmap_9=9:100 + +#FC3 +portmap_13=13:100 + +#FC4 +portmap_17=17:100 + +#FC5 +portmap_21=21:100 + +#FC6 +portmap_25=25:100 + +#FC7 +portmap_29=29:100 + +# Tile-1 +#FC8 +portmap_34=33:100 + +#FC9 +portmap_38=37:100 + +#FC10 +portmap_42=41:100 + +#FC11 +portmap_46=45:100 + +#FC12 +portmap_50=49:100 + +#FC13 +portmap_54=53:100 + +#FC14 +portmap_58=57:100 + +#FC15 +portmap_62=61:100 + +#TSC-E Management port 1 +#portmap_66=129:10 +#portmap_67=133:10 + +# Tile-2 +#FC16 +portmap_68=65:100 + +#FC17 +portmap_72=69:100 + +#FC18 +portmap_76=73:100 + +#FC19 +portmap_80=77:100 + +#FC20 +portmap_84=81:100 + +#FC21 +portmap_88=85:100 + +#FC22 +portmap_92=89:100 + +#FC23 +portmap_96=93:100 + +#TSC-E Management port 2 +#portmap_100=131:10 +#portmap_101=134:10 + +# Tile-3 +#FC24 +portmap_102=97:100 + +#FC25 +portmap_106=101:100 + +#FC26 +portmap_110=105:100 + +#FC27 +portmap_114=109:100 + +#FC28 +portmap_118=113:100 + +#FC29 +portmap_122=117:100 + +#FC30 +portmap_126=121:100 + +#FC31 +portmap_130=125:100 + + + +## TX/RX Lane Swap +######### +# port5 # +# FC16 # +######### +xgxs_tx_lane_map_68=0x0123 +xgxs_rx_lane_map_68=0x0123 + +######### +# port8 # +# FC19 # +######### +xgxs_tx_lane_map_80=0x0123 +xgxs_rx_lane_map_80=0x0123 + +######### +# port13# +# FC20 # +######### +xgxs_tx_lane_map_84=0x1032 +xgxs_rx_lane_map_84=0x1032 + +######### +# port14# +# FC21 # +######### +xgxs_tx_lane_map_88=0x0123 +xgxs_rx_lane_map_88=0x0123 + +######### +# port15# +# FC22 # +######### +xgxs_tx_lane_map_92=0x1032 +xgxs_rx_lane_map_92=0x1032 + +######### +# port17# +# FC24 # +######### +xgxs_tx_lane_map_102=0x1032 +xgxs_rx_lane_map_102=0x1032 + +######### +# port18# +# FC25 # +######### +xgxs_tx_lane_map_106=0x0123 +xgxs_rx_lane_map_106=0x0123 + +######### +# port19# +# FC26 # +######### +xgxs_tx_lane_map_110=0x1032 +xgxs_rx_lane_map_110=0x1032 + +######### +# port20# +# FC27 # +######### +xgxs_tx_lane_map_114=0x0123 +xgxs_rx_lane_map_114=0x0123 + +######### +# port26# +# FC29 # +######### +xgxs_tx_lane_map_122=0x0123 +xgxs_rx_lane_map_122=0x0123 + +######### +# port27# +# FC30 # +######### +xgxs_tx_lane_map_126=0x0123 +xgxs_rx_lane_map_126=0x0123 + +######### +# port29# +# FC0 # +######### +xgxs_tx_lane_map_1=0x0123 +xgxs_rx_lane_map_1=0x0123 + +# port30# +# FC1 # +######### +xgxs_tx_lane_map_5=0x0123 +xgxs_rx_lane_map_5=0x0123 + +######### +# port31# +# FC2 # +######### +xgxs_tx_lane_map_9=0x0123 +xgxs_rx_lane_map_9=0x0123 + +######### +# port32# +# FC3 # +######### +xgxs_tx_lane_map_13=0x0123 +xgxs_rx_lane_map_13=0x0123 + + +## RX / TX Serdes lane polarity flip list +## RX / TX Serdes lane polarity flip list +######### +# FC4 # +# port21 # +######### +phy_xaui_tx_polarity_flip_17=0xf + +######### +# FC20 # +# port13 # +######### +phy_xaui_rx_polarity_flip_84=0xf +phy_xaui_tx_polarity_flip_84=0x6 + +######### +# FC21 # +# port14 # +######### +phy_xaui_rx_polarity_flip_88=0xf + +######### +# FC22 # +# port15 # +######### +phy_xaui_rx_polarity_flip_92=0xf +phy_xaui_tx_polarity_flip_92=0xe + + +######### +# FC23 # +# port16 # +######### +phy_xaui_tx_polarity_flip_96=0x1 + +######### +# FC24 # +# port17 # +######### +phy_xaui_tx_polarity_flip_102=0x1 + + +######### +# FC25 # +# port18 # +######### +phy_xaui_rx_polarity_flip_106=0xf + +######### +# FC26 # +# port19 # +######### +phy_xaui_tx_polarity_flip_110=0xe + +######### +# FC27 # +# port20 # +######### +phy_xaui_rx_polarity_flip_114=0x2 + +######### +# FC28 # +# port25 # +######### +phy_xaui_rx_polarity_flip_118=0xa +phy_xaui_tx_polarity_flip_118=0xf + +#Driver Current +serdes_driver_current_lane0_1=0x8 +serdes_driver_current_lane1_1=0x8 +serdes_driver_current_lane2_1=0x8 +serdes_driver_current_lane3_1=0x8 +serdes_driver_current_lane0_5=0x8 +serdes_driver_current_lane1_5=0x8 +serdes_driver_current_lane2_5=0x8 +serdes_driver_current_lane3_5=0x8 +serdes_driver_current_lane0_9=0x8 +serdes_driver_current_lane1_9=0x8 +serdes_driver_current_lane2_9=0x8 +serdes_driver_current_lane3_9=0x8 +serdes_driver_current_lane0_13=0x8 +serdes_driver_current_lane1_13=0x8 +serdes_driver_current_lane2_13=0x8 +serdes_driver_current_lane3_13=0x8 +serdes_driver_current_lane0_17=0x8 +serdes_driver_current_lane1_17=0x8 +serdes_driver_current_lane2_17=0x8 +serdes_driver_current_lane3_17=0x8 +serdes_driver_current_lane0_21=0x8 +serdes_driver_current_lane1_21=0x8 +serdes_driver_current_lane2_21=0x8 +serdes_driver_current_lane3_21=0x8 +serdes_driver_current_lane0_25=0x8 +serdes_driver_current_lane1_25=0x8 +serdes_driver_current_lane2_25=0x8 +serdes_driver_current_lane3_25=0x8 +serdes_driver_current_lane0_29=0x8 +serdes_driver_current_lane1_29=0x8 +serdes_driver_current_lane2_29=0x8 +serdes_driver_current_lane3_29=0x8 +serdes_driver_current_lane0_34=0x8 +serdes_driver_current_lane1_34=0x8 +serdes_driver_current_lane2_34=0x8 +serdes_driver_current_lane3_34=0x8 +serdes_driver_current_lane0_38=0x8 +serdes_driver_current_lane1_38=0x8 +serdes_driver_current_lane2_38=0x8 +serdes_driver_current_lane3_38=0x8 +serdes_driver_current_lane0_42=0x8 +serdes_driver_current_lane1_42=0x8 +serdes_driver_current_lane2_42=0x8 +serdes_driver_current_lane3_42=0x8 +serdes_driver_current_lane0_46=0x8 +serdes_driver_current_lane1_46=0x8 +serdes_driver_current_lane2_46=0x8 +serdes_driver_current_lane3_46=0x8 +serdes_driver_current_lane0_50=0x8 +serdes_driver_current_lane1_50=0x8 +serdes_driver_current_lane2_50=0x8 +serdes_driver_current_lane3_50=0x8 +serdes_driver_current_lane0_54=0x8 +serdes_driver_current_lane1_54=0x8 +serdes_driver_current_lane2_54=0x8 +serdes_driver_current_lane3_54=0x8 +serdes_driver_current_lane0_58=0x8 +serdes_driver_current_lane1_58=0x8 +serdes_driver_current_lane2_58=0x8 +serdes_driver_current_lane3_58=0x8 +serdes_driver_current_lane0_62=0x8 +serdes_driver_current_lane1_62=0x8 +serdes_driver_current_lane2_62=0x8 +serdes_driver_current_lane3_62=0x8 +serdes_driver_current_lane0_68=0x8 +serdes_driver_current_lane1_68=0x8 +serdes_driver_current_lane2_68=0x8 +serdes_driver_current_lane3_68=0x8 +serdes_driver_current_lane0_72=0x8 +serdes_driver_current_lane1_72=0x8 +serdes_driver_current_lane2_72=0x8 +serdes_driver_current_lane3_72=0x8 +serdes_driver_current_lane0_76=0x8 +serdes_driver_current_lane1_76=0x8 +serdes_driver_current_lane2_76=0x8 +serdes_driver_current_lane3_76=0x8 +serdes_driver_current_lane0_80=0x8 +serdes_driver_current_lane1_80=0x8 +serdes_driver_current_lane2_80=0x8 +serdes_driver_current_lane3_80=0x8 +serdes_driver_current_lane0_84=0x8 +serdes_driver_current_lane1_84=0x8 +serdes_driver_current_lane2_84=0x8 +serdes_driver_current_lane3_84=0x8 +serdes_driver_current_lane0_88=0x8 +serdes_driver_current_lane1_88=0x8 +serdes_driver_current_lane2_88=0x8 +serdes_driver_current_lane3_88=0x8 +serdes_driver_current_lane0_92=0x8 +serdes_driver_current_lane1_92=0x8 +serdes_driver_current_lane2_92=0x8 +serdes_driver_current_lane3_92=0x8 +serdes_driver_current_lane0_96=0x8 +serdes_driver_current_lane1_96=0x8 +serdes_driver_current_lane2_96=0x8 +serdes_driver_current_lane3_96=0x8 +serdes_driver_current_lane0_102=0x8 +serdes_driver_current_lane1_102=0x8 +serdes_driver_current_lane2_102=0x8 +serdes_driver_current_lane3_102=0x8 +serdes_driver_current_lane0_106=0x8 +serdes_driver_current_lane1_106=0x8 +serdes_driver_current_lane2_106=0x8 +serdes_driver_current_lane3_106=0x8 +serdes_driver_current_lane0_110=0x8 +serdes_driver_current_lane1_110=0x8 +serdes_driver_current_lane2_110=0x8 +serdes_driver_current_lane3_110=0x8 +serdes_driver_current_lane0_114=0x8 +serdes_driver_current_lane1_114=0x8 +serdes_driver_current_lane2_114=0x8 +serdes_driver_current_lane3_114=0x8 +serdes_driver_current_lane0_118=0x8 +serdes_driver_current_lane1_118=0x8 +serdes_driver_current_lane2_118=0x8 +serdes_driver_current_lane3_118=0x8 +serdes_driver_current_lane0_122=0x8 +serdes_driver_current_lane1_122=0x8 +serdes_driver_current_lane2_122=0x8 +serdes_driver_current_lane3_122=0x8 +serdes_driver_current_lane0_126=0x8 +serdes_driver_current_lane1_126=0x8 +serdes_driver_current_lane2_126=0x8 +serdes_driver_current_lane3_126=0x8 +serdes_driver_current_lane0_130=0x8 +serdes_driver_current_lane1_130=0x8 +serdes_driver_current_lane2_130=0x8 +serdes_driver_current_lane3_130=0x8 + +#Preemphasis +serdes_preemphasis_lane0_1=0x264204 +serdes_preemphasis_lane1_1=0x264204 +serdes_preemphasis_lane2_1=0x264204 +serdes_preemphasis_lane3_1=0x264204 +serdes_preemphasis_lane0_5=0x224406 +serdes_preemphasis_lane1_5=0x224406 +serdes_preemphasis_lane2_5=0x264204 +serdes_preemphasis_lane3_5=0x244206 +serdes_preemphasis_lane0_9=0x204606 +serdes_preemphasis_lane1_9=0x264204 +serdes_preemphasis_lane2_9=0x204606 +serdes_preemphasis_lane3_9=0x224406 +serdes_preemphasis_lane0_13=0x204606 +serdes_preemphasis_lane1_13=0x224406 +serdes_preemphasis_lane2_13=0x224406 +serdes_preemphasis_lane3_13=0x244206 +serdes_preemphasis_lane0_17=0x204606 +serdes_preemphasis_lane1_17=0x204606 +serdes_preemphasis_lane2_17=0x204606 +serdes_preemphasis_lane3_17=0x204606 +serdes_preemphasis_lane0_21=0x204606 +serdes_preemphasis_lane1_21=0x204606 +serdes_preemphasis_lane2_21=0x204606 +serdes_preemphasis_lane3_21=0x224406 +serdes_preemphasis_lane0_25=0x204606 +serdes_preemphasis_lane1_25=0x204606 +serdes_preemphasis_lane2_25=0x204606 +serdes_preemphasis_lane3_25=0x204606 +serdes_preemphasis_lane0_29=0x204606 +serdes_preemphasis_lane1_29=0x204606 +serdes_preemphasis_lane2_29=0x204606 +serdes_preemphasis_lane3_29=0x204606 +serdes_preemphasis_lane0_34=0x284601 +serdes_preemphasis_lane1_34=0x284601 +serdes_preemphasis_lane2_34=0x284601 +serdes_preemphasis_lane3_34=0x284601 +serdes_preemphasis_lane0_38=0x204604 +serdes_preemphasis_lane1_38=0x204604 +serdes_preemphasis_lane2_38=0x224406 +serdes_preemphasis_lane3_38=0x224406 +serdes_preemphasis_lane0_42=0x284601 +serdes_preemphasis_lane1_42=0x294501 +serdes_preemphasis_lane2_42=0x284601 +serdes_preemphasis_lane3_42=0x284601 +serdes_preemphasis_lane0_46=0x204802 +serdes_preemphasis_lane1_46=0x204802 +serdes_preemphasis_lane2_46=0x204802 +serdes_preemphasis_lane3_46=0x204802 +serdes_preemphasis_lane0_50=0x1e4f01 +serdes_preemphasis_lane1_50=0x1e4d01 +serdes_preemphasis_lane2_50=0x1e4f01 +serdes_preemphasis_lane3_50=0x1e4f01 +serdes_preemphasis_lane0_54=0x1f4a03 +serdes_preemphasis_lane1_54=0x1f4a03 +serdes_preemphasis_lane2_54=0x1f4a03 +serdes_preemphasis_lane3_54=0x1f4a03 +serdes_preemphasis_lane0_58=0x1e4f01 +serdes_preemphasis_lane1_58=0x1e4f01 +serdes_preemphasis_lane2_58=0x1e4f01 +serdes_preemphasis_lane3_58=0x1e4f01 +serdes_preemphasis_lane0_62=0x1e4e02 +serdes_preemphasis_lane1_62=0x1e4e02 +serdes_preemphasis_lane2_62=0x1e4e02 +serdes_preemphasis_lane3_62=0x1e4e02 +serdes_preemphasis_lane0_68=0x1e4f01 +serdes_preemphasis_lane1_68=0x1e4f01 +serdes_preemphasis_lane2_68=0x1e4f01 +serdes_preemphasis_lane3_68=0x1e4f01 +serdes_preemphasis_lane0_72=0x1e4e02 +serdes_preemphasis_lane1_72=0x1e4e02 +serdes_preemphasis_lane2_72=0x1e4e02 +serdes_preemphasis_lane3_72=0x1e4e02 +serdes_preemphasis_lane0_76=0x1c4d02 +serdes_preemphasis_lane1_76=0x195002 +serdes_preemphasis_lane2_76=0x195002 +serdes_preemphasis_lane3_76=0x195002 +serdes_preemphasis_lane0_80=0x1e4e02 +serdes_preemphasis_lane1_80=0x1e4e02 +serdes_preemphasis_lane2_80=0x1e4e02 +serdes_preemphasis_lane3_80=0x1e4e02 +serdes_preemphasis_lane0_84=0x234701 +serdes_preemphasis_lane1_84=0x234701 +serdes_preemphasis_lane2_84=0x234701 +serdes_preemphasis_lane3_84=0x234701 +serdes_preemphasis_lane0_88=0x224802 +serdes_preemphasis_lane1_88=0x224602 +serdes_preemphasis_lane2_88=0x224802 +serdes_preemphasis_lane3_88=0x224802 +serdes_preemphasis_lane0_92=0x234801 +serdes_preemphasis_lane1_92=0x244701 +serdes_preemphasis_lane2_92=0x234801 +serdes_preemphasis_lane3_92=0x234601 +serdes_preemphasis_lane0_96=0x204406 +serdes_preemphasis_lane1_96=0x204406 +serdes_preemphasis_lane2_96=0x204406 +serdes_preemphasis_lane3_96=0x224602 +serdes_preemphasis_lane0_102=0x204606 +serdes_preemphasis_lane1_102=0x235002 +serdes_preemphasis_lane2_102=0x204606 +serdes_preemphasis_lane3_102=0x204606 +serdes_preemphasis_lane0_106=0x204606 +serdes_preemphasis_lane1_106=0x204606 +serdes_preemphasis_lane2_106=0x204606 +serdes_preemphasis_lane3_106=0x204606 +serdes_preemphasis_lane0_110=0x204606 +serdes_preemphasis_lane1_110=0x224406 +serdes_preemphasis_lane2_110=0x224406 +serdes_preemphasis_lane3_110=0x224406 +serdes_preemphasis_lane0_114=0x224406 +serdes_preemphasis_lane1_114=0x204606 +serdes_preemphasis_lane2_114=0x204606 +serdes_preemphasis_lane3_114=0x224406 +serdes_preemphasis_lane0_118=0x224406 +serdes_preemphasis_lane1_118=0x224406 +serdes_preemphasis_lane2_118=0x224406 +serdes_preemphasis_lane3_118=0x224406 +serdes_preemphasis_lane0_122=0x244404 +serdes_preemphasis_lane1_122=0x244404 +serdes_preemphasis_lane2_122=0x244404 +serdes_preemphasis_lane3_122=0x244404 +serdes_preemphasis_lane0_126=0x234504 +serdes_preemphasis_lane1_126=0x234404 +serdes_preemphasis_lane2_126=0x224406 +serdes_preemphasis_lane3_126=0x224406 +serdes_preemphasis_lane0_130=0x244404 +serdes_preemphasis_lane1_130=0x244404 +serdes_preemphasis_lane2_130=0x234504 +serdes_preemphasis_lane3_130=0x264501 diff --git a/device/accton/x86_64-accton_as7712_32x-r0/default_sku b/device/accton/x86_64-accton_as7712_32x-r0/default_sku new file mode 100644 index 000000000000..fb1c5c5afc92 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7712-32X t1 diff --git a/device/accton/x86_64-accton_as7712_32x-r0/fancontrol b/device/accton/x86_64-accton_as7712_32x-r0/fancontrol new file mode 100644 index 000000000000..9d057024f946 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +FCTEMPS=/sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/sys_temp +FCFANS=/sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan1_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan2_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan3_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan4_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan5_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan6_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan11_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan12_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan13_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan14_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan15_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan16_input +MINTEMP=/sys/bus/i2c/devices/2-0066/pwm1=135 +MAXTEMP=/sys/bus/i2c/devices/2-0066/pwm1=160 +MINSTART=/sys/bus/i2c/devices/2-0066/pwm1=100 +MINSTOP=/sys/bus/i2c/devices/2-0066/pwm1=32 +MINPWM=/sys/bus/i2c/devices/2-0066/pwm1=32 +MAXPWM=/sys/bus/i2c/devices/2-0066/pwm1=69 diff --git a/device/accton/x86_64-accton_as7712_32x-r0/installer.conf b/device/accton/x86_64-accton_as7712_32x-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as7712_32x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7712_32x-r0/led_proc_init.soc new file mode 100755 index 000000000000..719cb777719f --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/led_proc_init.soc @@ -0,0 +1,41 @@ +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=62 REMAP_PORT_18=61 REMAP_PORT_19=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=59 REMAP_PORT_21=58 REMAP_PORT_22=57 REMAP_PORT_23=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=55 REMAP_PORT_25=54 REMAP_PORT_26=53 REMAP_PORT_27=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=51 REMAP_PORT_29=50 REMAP_PORT_30=49 REMAP_PORT_31=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=47 REMAP_PORT_33=46 REMAP_PORT_34=45 REMAP_PORT_35=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=43 REMAP_PORT_37=42 REMAP_PORT_38=41 REMAP_PORT_39=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=39 REMAP_PORT_41=38 REMAP_PORT_42=37 REMAP_PORT_43=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=35 REMAP_PORT_45=34 REMAP_PORT_46=33 REMAP_PORT_47=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=35 REMAP_PORT_1=34 REMAP_PORT_2=33 REMAP_PORT_3=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=39 REMAP_PORT_5=38 REMAP_PORT_6=37 REMAP_PORT_7=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=43 REMAP_PORT_9=42 REMAP_PORT_10=41 REMAP_PORT_11=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=47 REMAP_PORT_13=46 REMAP_PORT_14=45 REMAP_PORT_15=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=3 REMAP_PORT_17=2 REMAP_PORT_18=1 REMAP_PORT_19=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=7 REMAP_PORT_21=6 REMAP_PORT_22=5 REMAP_PORT_23=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=11 REMAP_PORT_25=10 REMAP_PORT_26=9 REMAP_PORT_27=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=15 REMAP_PORT_29=14 REMAP_PORT_30=13 REMAP_PORT_31=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 REMAP_PORT_33=18 REMAP_PORT_34=17 REMAP_PORT_35=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 REMAP_PORT_37=22 REMAP_PORT_38=21 REMAP_PORT_39=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 REMAP_PORT_41=26 REMAP_PORT_42=25 REMAP_PORT_43=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 REMAP_PORT_45=30 REMAP_PORT_46=29 REMAP_PORT_47=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 prog 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 84 67 98 57 80 18 71 EB 67 98 67 84 57 67 84 67 84 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 start + +led 1 prog 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 84 67 98 57 80 18 71 EB 67 98 67 84 57 67 84 67 84 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 1 start + +led auto on \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7712_32x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7712_32x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..7681caafeef4 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom" + #Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7712_32x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7712_32x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..d7600a2af4b1 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/plugins/psuutil.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "11-0053", + 2: "10-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7712_32x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7712_32x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..5d1346e9b937 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/plugins/sfputil.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + _port_start = 0 + _port_end = 31 + ports_in_block = 32 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 9 : 18, + 10 : 19, + 11 : 20, + 12 : 21, + 1 : 22, + 2 : 23, + 3 : 24, + 4 : 25, + 6 : 26, + 5 : 27, + 8 : 28, + 7 : 29, + 13 : 30, + 14 : 31, + 15 : 32, + 16 : 33, + 17 : 34, + 18 : 35, + 19 : 36, + 20 : 37, + 25 : 38, + 26 : 39, + 27 : 40, + 28 : 41, + 29 : 42, + 30 : 43, + 31 : 44, + 32 : 45, + 21 : 46, + 22 : 47, + 23 : 48, + 24 : 49, + } + + _qsfp_ports = range(0, ports_in_block + 1) + + 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+1]) + self._port_to_eeprom_mapping[x] = port_eeprom_path + SfpUtilBase.__init__(self) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + path = "/sys/bus/i2c/devices/4-0060/module_reset_{0}" + port_ps = path.format(port_num+1) + + try: + reg_file = open(port_ps, 'w') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + #toggle reset + reg_file.seek(0) + reg_file.write('1') + time.sleep(1) + reg_file.seek(0) + reg_file.write('0') + reg_file.close() + return True + + def set_low_power_mode(self, port_nuM, lpmode): + raise NotImplementedError + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + path = "/sys/bus/i2c/devices/4-0060/module_present_{0}" + port_ps = path.format(port_num+1) + + + try: + reg_file = open(port_ps) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return range(0, self.ports_in_block + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/accton/x86_64-accton_as7712_32x-r0/sensors.conf b/device/accton/x86_64-accton_as7712_32x-r0/sensors.conf new file mode 100644 index 000000000000..33d75d598123 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/sensors.conf @@ -0,0 +1,23 @@ +# libsensors configuration file for AS7712-32X +# ------------------------------------------------ +# + +#Comment out the following for sku-sensors-data.yml +#chip "ym2651-*" +# label power1 "PSU Output Power" +# label temp1 "Power Supply Temp" +# label fan1 "Fan Speed" +# +#chip "as7712_32x_fan-*" +# label fan1 "Fan tray 1 front" +# label fan2 "Fan tray 2 front" +# label fan3 "Fan tray 3 front" +# label fan4 "Fan tray 4 front" +# label fan5 "Fan tray 5 front" +# label fan6 "Fan tray 6 front" +# label fan11 "Fan tray 1 rear" +# label fan12 "Fan tray 2 rear" +# label fan13 "Fan tray 3 rear" +# label fan14 "Fan tray 4 rear" +# label fan15 "Fan tray 5 rear" +# label fan16 "Fan tray 6 rear" diff --git a/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/port_config.ini b/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/port_config.ini new file mode 100644 index 000000000000..1fa6d21d9609 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 49,50,51,52 hundredGigE1 +Ethernet4 53,54,55,56 hundredGigE2 +Ethernet8 57,58,59,60 hundredGigE3 +Ethernet12 61,62,63,64 hundredGigE4 +Ethernet16 65,66,67,68 hundredGigE5 +Ethernet20 69,70,71,72 hundredGigE6 +Ethernet24 73,74,75,76 hundredGigE7 +Ethernet28 77,78,79,80 hundredGigE8 +Ethernet32 33,34,35,36 hundredGigE9 +Ethernet36 37,38,39,40 hundredGigE10 +Ethernet40 41,42,43,44 hundredGigE11 +Ethernet44 45,46,47,48 hundredGigE12 +Ethernet48 81,82,83,84 hundredGigE13 +Ethernet52 85,86,87,88 hundredGigE14 +Ethernet56 89,90,91,92 hundredGigE15 +Ethernet60 93,94,95,96 hundredGigE16 +Ethernet64 97,98,99,100 hundredGigE17 +Ethernet68 101,102,103,104 hundredGigE18 +Ethernet72 105,106,107,108 hundredGigE19 +Ethernet76 109,110,111,112 hundredGigE20 +Ethernet80 17,18,19,20 hundredGigE21 +Ethernet84 21,22,23,24 hundredGigE22 +Ethernet88 25,26,27,28 hundredGigE23 +Ethernet92 29,30,31,32 hundredGigE24 +Ethernet96 113,114,115,116 hundredGigE25 +Ethernet100 117,118,119,120 hundredGigE26 +Ethernet104 121,122,123,124 hundredGigE27 +Ethernet108 125,126,127,128 hundredGigE28 +Ethernet112 1,2,3,4 hundredGigE29 +Ethernet116 5,6,7,8 hundredGigE30 +Ethernet120 9,10,11,12 hundredGigE31 +Ethernet124 13,14,15,16 hundredGigE32 diff --git a/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/sai.profile b/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/sai.profile new file mode 100644 index 000000000000..65944732653c --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-as7716-32x100G.config.bcm diff --git a/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/th-as7716-32x100G.config.bcm b/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/th-as7716-32x100G.config.bcm new file mode 100644 index 000000000000..1231bf302be7 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/th-as7716-32x100G.config.bcm @@ -0,0 +1,570 @@ +# accton_as7716_32x 32x100G SDK config +os=unix +schan_intr_enable=0 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_oversubscribe=0x444444441111111104444444422222222 +pbmp_xport_xe=0x444444451111111144444444422222222 + +# +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=8 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +max_vp_lags=0 +miim_intr_enable=0 +oversubscribe_mode=1 + +# portmap_0=x:xx +#FC0 +portmap_1=1:100 + +#FC1 +portmap_5=5:100 + +#FC2 +portmap_9=9:100 + +#FC3 +portmap_13=13:100 + +#FC4 +portmap_17=17:100 + +#FC5 +portmap_21=21:100 + +#FC6 +portmap_25=25:100 + +#FC7 +portmap_29=29:100 + +# Tile-1 +#FC8 +portmap_34=33:100 + +#FC9 +portmap_38=37:100 + +#FC10 +portmap_42=41:100 + +#FC11 +portmap_46=45:100 + +#FC12 +portmap_50=49:100 + +#FC13 +portmap_54=53:100 + +#FC14 +portmap_58=57:100 + +#FC15 +portmap_62=61:100 + +#TSC-E Management port 1 +#portmap_66=129:10 +#portmap_67=133:10 + +# Tile-2 +#FC16 +portmap_68=65:100 + +#FC17 +portmap_72=69:100 + +#FC18 +portmap_76=73:100 + +#FC19 +portmap_80=77:100 + +#FC20 +portmap_84=81:100 + +#FC21 +portmap_88=85:100 + +#FC22 +portmap_92=89:100 + +#FC23 +portmap_96=93:100 + +#TSC-E Management port 2 +#portmap_100=131:10 +#portmap_101=134:10 + +# Tile-3 +#FC24 +portmap_102=97:100 + +#FC25 +portmap_106=101:100 + +#FC26 +portmap_110=105:100 + +#FC27 +portmap_114=109:100 + +#FC28 +portmap_118=113:100 + +#FC29 +portmap_122=117:100 + +#FC30 +portmap_126=121:100 + +#FC31 +portmap_130=125:100 + + + +## TX/RX Lane Swap +######### +# port5 # +# FC16 # +######### +xgxs_tx_lane_map_68=0x0123 +xgxs_rx_lane_map_68=0x0123 + +######### +# port8 # +# FC19 # +######### +xgxs_tx_lane_map_80=0x0123 +xgxs_rx_lane_map_80=0x0123 + +######### +# port13# +# FC20 # +######### +xgxs_tx_lane_map_84=0x1032 +xgxs_rx_lane_map_84=0x1032 + +######### +# port14# +# FC21 # +######### +xgxs_tx_lane_map_88=0x0123 +xgxs_rx_lane_map_88=0x0123 + +######### +# port15# +# FC22 # +######### +xgxs_tx_lane_map_92=0x1032 +xgxs_rx_lane_map_92=0x1032 + +######### +# port17# +# FC24 # +######### +xgxs_tx_lane_map_102=0x1032 +xgxs_rx_lane_map_102=0x1032 + +######### +# port18# +# FC25 # +######### +xgxs_tx_lane_map_106=0x0123 +xgxs_rx_lane_map_106=0x0123 + +######### +# port19# +# FC26 # +######### +xgxs_tx_lane_map_110=0x1032 +xgxs_rx_lane_map_110=0x1032 + +######### +# port20# +# FC27 # +######### +xgxs_tx_lane_map_114=0x0123 +xgxs_rx_lane_map_114=0x0123 + +######### +# port26# +# FC29 # +######### +xgxs_tx_lane_map_122=0x0123 +xgxs_rx_lane_map_122=0x0123 + +######### +# port27# +# FC30 # +######### +xgxs_tx_lane_map_126=0x0123 +xgxs_rx_lane_map_126=0x0123 + +######### +# port29# +# FC0 # +######### +xgxs_tx_lane_map_1=0x0123 +xgxs_rx_lane_map_1=0x0123 + +# port30# +# FC1 # +######### +xgxs_tx_lane_map_5=0x0123 +xgxs_rx_lane_map_5=0x0123 + +######### +# port31# +# FC2 # +######### +xgxs_tx_lane_map_9=0x0123 +xgxs_rx_lane_map_9=0x0123 + +######### +# port32# +# FC3 # +######### +xgxs_tx_lane_map_13=0x0123 +xgxs_rx_lane_map_13=0x0123 + + +## RX / TX Serdes lane polarity flip list +## RX / TX Serdes lane polarity flip list +######### +# FC4 # +# port21 # +######### +phy_xaui_tx_polarity_flip_17=0xf + +######### +# FC20 # +# port13 # +######### +phy_xaui_rx_polarity_flip_84=0xf +phy_xaui_tx_polarity_flip_84=0x6 + +######### +# FC21 # +# port14 # +######### +phy_xaui_rx_polarity_flip_88=0xf + +######### +# FC22 # +# port15 # +######### +phy_xaui_rx_polarity_flip_92=0xf +phy_xaui_tx_polarity_flip_92=0xe + + +######### +# FC23 # +# port16 # +######### +phy_xaui_tx_polarity_flip_96=0x1 + +######### +# FC24 # +# port17 # +######### +phy_xaui_tx_polarity_flip_102=0x1 + + +######### +# FC25 # +# port18 # +######### +phy_xaui_rx_polarity_flip_106=0xf + +######### +# FC26 # +# port19 # +######### +phy_xaui_tx_polarity_flip_110=0xe + +######### +# FC27 # +# port20 # +######### +phy_xaui_rx_polarity_flip_114=0x2 + +######### +# FC28 # +# port25 # +######### +phy_xaui_rx_polarity_flip_118=0xa +phy_xaui_tx_polarity_flip_118=0xf + +#Driver Current +serdes_driver_current_lane0_1=0x8 +serdes_driver_current_lane1_1=0x8 +serdes_driver_current_lane2_1=0x8 +serdes_driver_current_lane3_1=0x8 +serdes_driver_current_lane0_5=0x8 +serdes_driver_current_lane1_5=0x8 +serdes_driver_current_lane2_5=0x8 +serdes_driver_current_lane3_5=0x8 +serdes_driver_current_lane0_9=0x8 +serdes_driver_current_lane1_9=0x8 +serdes_driver_current_lane2_9=0x8 +serdes_driver_current_lane3_9=0x8 +serdes_driver_current_lane0_13=0x8 +serdes_driver_current_lane1_13=0x8 +serdes_driver_current_lane2_13=0x8 +serdes_driver_current_lane3_13=0x8 +serdes_driver_current_lane0_17=0x8 +serdes_driver_current_lane1_17=0x8 +serdes_driver_current_lane2_17=0x8 +serdes_driver_current_lane3_17=0x8 +serdes_driver_current_lane0_21=0x8 +serdes_driver_current_lane1_21=0x8 +serdes_driver_current_lane2_21=0x8 +serdes_driver_current_lane3_21=0x8 +serdes_driver_current_lane0_25=0x8 +serdes_driver_current_lane1_25=0x8 +serdes_driver_current_lane2_25=0x8 +serdes_driver_current_lane3_25=0x8 +serdes_driver_current_lane0_29=0x8 +serdes_driver_current_lane1_29=0x8 +serdes_driver_current_lane2_29=0x8 +serdes_driver_current_lane3_29=0x8 +serdes_driver_current_lane0_34=0x8 +serdes_driver_current_lane1_34=0x8 +serdes_driver_current_lane2_34=0x8 +serdes_driver_current_lane3_34=0x8 +serdes_driver_current_lane0_38=0x8 +serdes_driver_current_lane1_38=0x8 +serdes_driver_current_lane2_38=0x8 +serdes_driver_current_lane3_38=0x8 +serdes_driver_current_lane0_42=0x8 +serdes_driver_current_lane1_42=0x8 +serdes_driver_current_lane2_42=0x8 +serdes_driver_current_lane3_42=0x8 +serdes_driver_current_lane0_46=0x8 +serdes_driver_current_lane1_46=0x8 +serdes_driver_current_lane2_46=0x8 +serdes_driver_current_lane3_46=0x8 +serdes_driver_current_lane0_50=0x8 +serdes_driver_current_lane1_50=0x8 +serdes_driver_current_lane2_50=0x8 +serdes_driver_current_lane3_50=0x8 +serdes_driver_current_lane0_54=0x8 +serdes_driver_current_lane1_54=0x8 +serdes_driver_current_lane2_54=0x8 +serdes_driver_current_lane3_54=0x8 +serdes_driver_current_lane0_58=0x8 +serdes_driver_current_lane1_58=0x8 +serdes_driver_current_lane2_58=0x8 +serdes_driver_current_lane3_58=0x8 +serdes_driver_current_lane0_62=0x8 +serdes_driver_current_lane1_62=0x8 +serdes_driver_current_lane2_62=0x8 +serdes_driver_current_lane3_62=0x8 +serdes_driver_current_lane0_68=0x8 +serdes_driver_current_lane1_68=0x8 +serdes_driver_current_lane2_68=0x8 +serdes_driver_current_lane3_68=0x8 +serdes_driver_current_lane0_72=0x8 +serdes_driver_current_lane1_72=0x8 +serdes_driver_current_lane2_72=0x8 +serdes_driver_current_lane3_72=0x8 +serdes_driver_current_lane0_76=0x8 +serdes_driver_current_lane1_76=0x8 +serdes_driver_current_lane2_76=0x8 +serdes_driver_current_lane3_76=0x8 +serdes_driver_current_lane0_80=0x8 +serdes_driver_current_lane1_80=0x8 +serdes_driver_current_lane2_80=0x8 +serdes_driver_current_lane3_80=0x8 +serdes_driver_current_lane0_84=0x8 +serdes_driver_current_lane1_84=0x8 +serdes_driver_current_lane2_84=0x8 +serdes_driver_current_lane3_84=0x8 +serdes_driver_current_lane0_88=0x8 +serdes_driver_current_lane1_88=0x8 +serdes_driver_current_lane2_88=0x8 +serdes_driver_current_lane3_88=0x8 +serdes_driver_current_lane0_92=0x8 +serdes_driver_current_lane1_92=0x8 +serdes_driver_current_lane2_92=0x8 +serdes_driver_current_lane3_92=0x8 +serdes_driver_current_lane0_96=0x8 +serdes_driver_current_lane1_96=0x8 +serdes_driver_current_lane2_96=0x8 +serdes_driver_current_lane3_96=0x8 +serdes_driver_current_lane0_102=0x8 +serdes_driver_current_lane1_102=0x8 +serdes_driver_current_lane2_102=0x8 +serdes_driver_current_lane3_102=0x8 +serdes_driver_current_lane0_106=0x8 +serdes_driver_current_lane1_106=0x8 +serdes_driver_current_lane2_106=0x8 +serdes_driver_current_lane3_106=0x8 +serdes_driver_current_lane0_110=0x8 +serdes_driver_current_lane1_110=0x8 +serdes_driver_current_lane2_110=0x8 +serdes_driver_current_lane3_110=0x8 +serdes_driver_current_lane0_114=0x8 +serdes_driver_current_lane1_114=0x8 +serdes_driver_current_lane2_114=0x8 +serdes_driver_current_lane3_114=0x8 +serdes_driver_current_lane0_118=0x8 +serdes_driver_current_lane1_118=0x8 +serdes_driver_current_lane2_118=0x8 +serdes_driver_current_lane3_118=0x8 +serdes_driver_current_lane0_122=0x8 +serdes_driver_current_lane1_122=0x8 +serdes_driver_current_lane2_122=0x8 +serdes_driver_current_lane3_122=0x8 +serdes_driver_current_lane0_126=0x8 +serdes_driver_current_lane1_126=0x8 +serdes_driver_current_lane2_126=0x8 +serdes_driver_current_lane3_126=0x8 +serdes_driver_current_lane0_130=0x8 +serdes_driver_current_lane1_130=0x8 +serdes_driver_current_lane2_130=0x8 +serdes_driver_current_lane3_130=0x8 + +#Preemphasis +serdes_preemphasis_lane0_1=0x264204 +serdes_preemphasis_lane1_1=0x264204 +serdes_preemphasis_lane2_1=0x264204 +serdes_preemphasis_lane3_1=0x264204 +serdes_preemphasis_lane0_5=0x224406 +serdes_preemphasis_lane1_5=0x224406 +serdes_preemphasis_lane2_5=0x264204 +serdes_preemphasis_lane3_5=0x244206 +serdes_preemphasis_lane0_9=0x204606 +serdes_preemphasis_lane1_9=0x264204 +serdes_preemphasis_lane2_9=0x204606 +serdes_preemphasis_lane3_9=0x224406 +serdes_preemphasis_lane0_13=0x204606 +serdes_preemphasis_lane1_13=0x224406 +serdes_preemphasis_lane2_13=0x224406 +serdes_preemphasis_lane3_13=0x244206 +serdes_preemphasis_lane0_17=0x204606 +serdes_preemphasis_lane1_17=0x204606 +serdes_preemphasis_lane2_17=0x204606 +serdes_preemphasis_lane3_17=0x204606 +serdes_preemphasis_lane0_21=0x204606 +serdes_preemphasis_lane1_21=0x204606 +serdes_preemphasis_lane2_21=0x204606 +serdes_preemphasis_lane3_21=0x224406 +serdes_preemphasis_lane0_25=0x204606 +serdes_preemphasis_lane1_25=0x204606 +serdes_preemphasis_lane2_25=0x204606 +serdes_preemphasis_lane3_25=0x204606 +serdes_preemphasis_lane0_29=0x204606 +serdes_preemphasis_lane1_29=0x204606 +serdes_preemphasis_lane2_29=0x204606 +serdes_preemphasis_lane3_29=0x204606 +serdes_preemphasis_lane0_34=0x284601 +serdes_preemphasis_lane1_34=0x284601 +serdes_preemphasis_lane2_34=0x284601 +serdes_preemphasis_lane3_34=0x284601 +serdes_preemphasis_lane0_38=0x204604 +serdes_preemphasis_lane1_38=0x204604 +serdes_preemphasis_lane2_38=0x224406 +serdes_preemphasis_lane3_38=0x224406 +serdes_preemphasis_lane0_42=0x284601 +serdes_preemphasis_lane1_42=0x294501 +serdes_preemphasis_lane2_42=0x284601 +serdes_preemphasis_lane3_42=0x284601 +serdes_preemphasis_lane0_46=0x204802 +serdes_preemphasis_lane1_46=0x204802 +serdes_preemphasis_lane2_46=0x204802 +serdes_preemphasis_lane3_46=0x204802 +serdes_preemphasis_lane0_50=0x1e4f01 +serdes_preemphasis_lane1_50=0x1e4d01 +serdes_preemphasis_lane2_50=0x1e4f01 +serdes_preemphasis_lane3_50=0x1e4f01 +serdes_preemphasis_lane0_54=0x1f4a03 +serdes_preemphasis_lane1_54=0x1f4a03 +serdes_preemphasis_lane2_54=0x1f4a03 +serdes_preemphasis_lane3_54=0x1f4a03 +serdes_preemphasis_lane0_58=0x1e4f01 +serdes_preemphasis_lane1_58=0x1e4f01 +serdes_preemphasis_lane2_58=0x1e4f01 +serdes_preemphasis_lane3_58=0x1e4f01 +serdes_preemphasis_lane0_62=0x1e4e02 +serdes_preemphasis_lane1_62=0x1e4e02 +serdes_preemphasis_lane2_62=0x1e4e02 +serdes_preemphasis_lane3_62=0x1e4e02 +serdes_preemphasis_lane0_68=0x1e4f01 +serdes_preemphasis_lane1_68=0x1e4f01 +serdes_preemphasis_lane2_68=0x1e4f01 +serdes_preemphasis_lane3_68=0x1e4f01 +serdes_preemphasis_lane0_72=0x1e4e02 +serdes_preemphasis_lane1_72=0x1e4e02 +serdes_preemphasis_lane2_72=0x1e4e02 +serdes_preemphasis_lane3_72=0x1e4e02 +serdes_preemphasis_lane0_76=0x1c4d02 +serdes_preemphasis_lane1_76=0x195002 +serdes_preemphasis_lane2_76=0x195002 +serdes_preemphasis_lane3_76=0x195002 +serdes_preemphasis_lane0_80=0x1e4e02 +serdes_preemphasis_lane1_80=0x1e4e02 +serdes_preemphasis_lane2_80=0x1e4e02 +serdes_preemphasis_lane3_80=0x1e4e02 +serdes_preemphasis_lane0_84=0x234701 +serdes_preemphasis_lane1_84=0x234701 +serdes_preemphasis_lane2_84=0x234701 +serdes_preemphasis_lane3_84=0x234701 +serdes_preemphasis_lane0_88=0x224802 +serdes_preemphasis_lane1_88=0x224602 +serdes_preemphasis_lane2_88=0x224802 +serdes_preemphasis_lane3_88=0x224802 +serdes_preemphasis_lane0_92=0x234801 +serdes_preemphasis_lane1_92=0x244701 +serdes_preemphasis_lane2_92=0x234801 +serdes_preemphasis_lane3_92=0x234601 +serdes_preemphasis_lane0_96=0x204406 +serdes_preemphasis_lane1_96=0x204406 +serdes_preemphasis_lane2_96=0x204406 +serdes_preemphasis_lane3_96=0x224602 +serdes_preemphasis_lane0_102=0x204606 +serdes_preemphasis_lane1_102=0x235002 +serdes_preemphasis_lane2_102=0x204606 +serdes_preemphasis_lane3_102=0x204606 +serdes_preemphasis_lane0_106=0x204606 +serdes_preemphasis_lane1_106=0x204606 +serdes_preemphasis_lane2_106=0x204606 +serdes_preemphasis_lane3_106=0x204606 +serdes_preemphasis_lane0_110=0x204606 +serdes_preemphasis_lane1_110=0x224406 +serdes_preemphasis_lane2_110=0x224406 +serdes_preemphasis_lane3_110=0x224406 +serdes_preemphasis_lane0_114=0x224406 +serdes_preemphasis_lane1_114=0x204606 +serdes_preemphasis_lane2_114=0x204606 +serdes_preemphasis_lane3_114=0x224406 +serdes_preemphasis_lane0_118=0x224406 +serdes_preemphasis_lane1_118=0x224406 +serdes_preemphasis_lane2_118=0x224406 +serdes_preemphasis_lane3_118=0x224406 +serdes_preemphasis_lane0_122=0x244404 +serdes_preemphasis_lane1_122=0x244404 +serdes_preemphasis_lane2_122=0x244404 +serdes_preemphasis_lane3_122=0x244404 +serdes_preemphasis_lane0_126=0x234504 +serdes_preemphasis_lane1_126=0x234404 +serdes_preemphasis_lane2_126=0x224406 +serdes_preemphasis_lane3_126=0x224406 +serdes_preemphasis_lane0_130=0x244404 +serdes_preemphasis_lane1_130=0x244404 +serdes_preemphasis_lane2_130=0x234504 +serdes_preemphasis_lane3_130=0x264501 diff --git a/device/accton/x86_64-accton_as7716_32x-r0/default_sku b/device/accton/x86_64-accton_as7716_32x-r0/default_sku new file mode 100644 index 000000000000..4cd528a50e93 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7716-32X t1 diff --git a/device/accton/x86_64-accton_as7716_32x-r0/installer.conf b/device/accton/x86_64-accton_as7716_32x-r0/installer.conf new file mode 100644 index 000000000000..d97e3195e8fd --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="tg3.short_preamble=1 tg3.bcm5718s_reset=1" diff --git a/device/accton/x86_64-accton_as7716_32x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7716_32x-r0/led_proc_init.soc new file mode 100755 index 000000000000..719cb777719f --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/led_proc_init.soc @@ -0,0 +1,41 @@ +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=62 REMAP_PORT_18=61 REMAP_PORT_19=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=59 REMAP_PORT_21=58 REMAP_PORT_22=57 REMAP_PORT_23=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=55 REMAP_PORT_25=54 REMAP_PORT_26=53 REMAP_PORT_27=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=51 REMAP_PORT_29=50 REMAP_PORT_30=49 REMAP_PORT_31=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=47 REMAP_PORT_33=46 REMAP_PORT_34=45 REMAP_PORT_35=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=43 REMAP_PORT_37=42 REMAP_PORT_38=41 REMAP_PORT_39=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=39 REMAP_PORT_41=38 REMAP_PORT_42=37 REMAP_PORT_43=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=35 REMAP_PORT_45=34 REMAP_PORT_46=33 REMAP_PORT_47=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=35 REMAP_PORT_1=34 REMAP_PORT_2=33 REMAP_PORT_3=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=39 REMAP_PORT_5=38 REMAP_PORT_6=37 REMAP_PORT_7=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=43 REMAP_PORT_9=42 REMAP_PORT_10=41 REMAP_PORT_11=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=47 REMAP_PORT_13=46 REMAP_PORT_14=45 REMAP_PORT_15=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=3 REMAP_PORT_17=2 REMAP_PORT_18=1 REMAP_PORT_19=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=7 REMAP_PORT_21=6 REMAP_PORT_22=5 REMAP_PORT_23=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=11 REMAP_PORT_25=10 REMAP_PORT_26=9 REMAP_PORT_27=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=15 REMAP_PORT_29=14 REMAP_PORT_30=13 REMAP_PORT_31=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 REMAP_PORT_33=18 REMAP_PORT_34=17 REMAP_PORT_35=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 REMAP_PORT_37=22 REMAP_PORT_38=21 REMAP_PORT_39=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 REMAP_PORT_41=26 REMAP_PORT_42=25 REMAP_PORT_43=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 REMAP_PORT_45=30 REMAP_PORT_46=29 REMAP_PORT_47=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 prog 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 84 67 98 57 80 18 71 EB 67 98 67 84 57 67 84 67 84 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 start + +led 1 prog 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 84 67 98 57 80 18 71 EB 67 98 67 84 57 67 84 67 84 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 1 start + +led auto on \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7716_32x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7716_32x-r0/plugins/eeprom.py new file mode 100755 index 000000000000..c0122e65844a --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0056/eeprom" + #Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7716_32x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7716_32x-r0/plugins/psuutil.py new file mode 100755 index 000000000000..d8fddc23550b --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/plugins/psuutil.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "18-0053", + 2: "17-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7716_32x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7716_32x-r0/plugins/sfputil.py new file mode 100755 index 000000000000..98e1278ca7d0 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/plugins/sfputil.py @@ -0,0 +1,142 @@ +# 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 = 31 + PORTS_IN_BLOCK = 32 + + BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" + BASE_CPLD_PATH = "/sys/bus/i2c/devices/11-0060/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 0: [1, 29], + 1: [2, 30], + 2: [3, 31], + 3: [4, 32], + 4: [5, 34], + 5: [6, 33], + 6: [7, 36], + 7: [8, 35], + 8: [9, 25], + 9: [10, 26], + 10: [11, 27], + 11: [12, 28], + 12: [14, 37], + 13: [15, 38], + 14: [16, 39], + 15: [17, 40], + 16: [18, 41], + 17: [19, 42], + 18: [20, 43], + 19: [21, 44], + 20: [22, 53], + 21: [23, 54], + 22: [24, 55], + 23: [25, 56], + 24: [26, 45], + 25: [27, 46], + 26: [28, 47], + 27: [29, 48], + 28: [30, 49], + 29: [31, 50], + 30: [32, 51], + 31: [33, 52], + } + + @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(self.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 = self.BASE_OOM_PATH + "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][1] + ) + + 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 + + present_path = self.BASE_CPLD_PATH + "module_present_" + str(port_num+1) + self.__port_to_is_present = present_path + + try: + val_file = open(self.__port_to_is_present) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + 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): + if port_num < self.port_start or port_num > self.port_end: + return False + + mod_rst_path = self.BASE_CPLD_PATH + "module_reset_" + str(port_num+1) + self.__port_to_mod_rst = mod_rst_path + try: + reg_file = open(self.__port_to_mod_rst, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = '1' + + reg_file.write(reg_value) + reg_file.close() + + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/port_config.ini b/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/port_config.ini new file mode 100755 index 000000000000..1fa6d21d9609 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 49,50,51,52 hundredGigE1 +Ethernet4 53,54,55,56 hundredGigE2 +Ethernet8 57,58,59,60 hundredGigE3 +Ethernet12 61,62,63,64 hundredGigE4 +Ethernet16 65,66,67,68 hundredGigE5 +Ethernet20 69,70,71,72 hundredGigE6 +Ethernet24 73,74,75,76 hundredGigE7 +Ethernet28 77,78,79,80 hundredGigE8 +Ethernet32 33,34,35,36 hundredGigE9 +Ethernet36 37,38,39,40 hundredGigE10 +Ethernet40 41,42,43,44 hundredGigE11 +Ethernet44 45,46,47,48 hundredGigE12 +Ethernet48 81,82,83,84 hundredGigE13 +Ethernet52 85,86,87,88 hundredGigE14 +Ethernet56 89,90,91,92 hundredGigE15 +Ethernet60 93,94,95,96 hundredGigE16 +Ethernet64 97,98,99,100 hundredGigE17 +Ethernet68 101,102,103,104 hundredGigE18 +Ethernet72 105,106,107,108 hundredGigE19 +Ethernet76 109,110,111,112 hundredGigE20 +Ethernet80 17,18,19,20 hundredGigE21 +Ethernet84 21,22,23,24 hundredGigE22 +Ethernet88 25,26,27,28 hundredGigE23 +Ethernet92 29,30,31,32 hundredGigE24 +Ethernet96 113,114,115,116 hundredGigE25 +Ethernet100 117,118,119,120 hundredGigE26 +Ethernet104 121,122,123,124 hundredGigE27 +Ethernet108 125,126,127,128 hundredGigE28 +Ethernet112 1,2,3,4 hundredGigE29 +Ethernet116 5,6,7,8 hundredGigE30 +Ethernet120 9,10,11,12 hundredGigE31 +Ethernet124 13,14,15,16 hundredGigE32 diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/sai.profile b/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/sai.profile new file mode 100755 index 000000000000..65944732653c --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-as7716-32x100G.config.bcm diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/th-as7716-32x100G.config.bcm b/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/th-as7716-32x100G.config.bcm new file mode 100644 index 000000000000..1231bf302be7 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/th-as7716-32x100G.config.bcm @@ -0,0 +1,570 @@ +# accton_as7716_32x 32x100G SDK config +os=unix +schan_intr_enable=0 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_oversubscribe=0x444444441111111104444444422222222 +pbmp_xport_xe=0x444444451111111144444444422222222 + +# +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=8 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +max_vp_lags=0 +miim_intr_enable=0 +oversubscribe_mode=1 + +# portmap_0=x:xx +#FC0 +portmap_1=1:100 + +#FC1 +portmap_5=5:100 + +#FC2 +portmap_9=9:100 + +#FC3 +portmap_13=13:100 + +#FC4 +portmap_17=17:100 + +#FC5 +portmap_21=21:100 + +#FC6 +portmap_25=25:100 + +#FC7 +portmap_29=29:100 + +# Tile-1 +#FC8 +portmap_34=33:100 + +#FC9 +portmap_38=37:100 + +#FC10 +portmap_42=41:100 + +#FC11 +portmap_46=45:100 + +#FC12 +portmap_50=49:100 + +#FC13 +portmap_54=53:100 + +#FC14 +portmap_58=57:100 + +#FC15 +portmap_62=61:100 + +#TSC-E Management port 1 +#portmap_66=129:10 +#portmap_67=133:10 + +# Tile-2 +#FC16 +portmap_68=65:100 + +#FC17 +portmap_72=69:100 + +#FC18 +portmap_76=73:100 + +#FC19 +portmap_80=77:100 + +#FC20 +portmap_84=81:100 + +#FC21 +portmap_88=85:100 + +#FC22 +portmap_92=89:100 + +#FC23 +portmap_96=93:100 + +#TSC-E Management port 2 +#portmap_100=131:10 +#portmap_101=134:10 + +# Tile-3 +#FC24 +portmap_102=97:100 + +#FC25 +portmap_106=101:100 + +#FC26 +portmap_110=105:100 + +#FC27 +portmap_114=109:100 + +#FC28 +portmap_118=113:100 + +#FC29 +portmap_122=117:100 + +#FC30 +portmap_126=121:100 + +#FC31 +portmap_130=125:100 + + + +## TX/RX Lane Swap +######### +# port5 # +# FC16 # +######### +xgxs_tx_lane_map_68=0x0123 +xgxs_rx_lane_map_68=0x0123 + +######### +# port8 # +# FC19 # +######### +xgxs_tx_lane_map_80=0x0123 +xgxs_rx_lane_map_80=0x0123 + +######### +# port13# +# FC20 # +######### +xgxs_tx_lane_map_84=0x1032 +xgxs_rx_lane_map_84=0x1032 + +######### +# port14# +# FC21 # +######### +xgxs_tx_lane_map_88=0x0123 +xgxs_rx_lane_map_88=0x0123 + +######### +# port15# +# FC22 # +######### +xgxs_tx_lane_map_92=0x1032 +xgxs_rx_lane_map_92=0x1032 + +######### +# port17# +# FC24 # +######### +xgxs_tx_lane_map_102=0x1032 +xgxs_rx_lane_map_102=0x1032 + +######### +# port18# +# FC25 # +######### +xgxs_tx_lane_map_106=0x0123 +xgxs_rx_lane_map_106=0x0123 + +######### +# port19# +# FC26 # +######### +xgxs_tx_lane_map_110=0x1032 +xgxs_rx_lane_map_110=0x1032 + +######### +# port20# +# FC27 # +######### +xgxs_tx_lane_map_114=0x0123 +xgxs_rx_lane_map_114=0x0123 + +######### +# port26# +# FC29 # +######### +xgxs_tx_lane_map_122=0x0123 +xgxs_rx_lane_map_122=0x0123 + +######### +# port27# +# FC30 # +######### +xgxs_tx_lane_map_126=0x0123 +xgxs_rx_lane_map_126=0x0123 + +######### +# port29# +# FC0 # +######### +xgxs_tx_lane_map_1=0x0123 +xgxs_rx_lane_map_1=0x0123 + +# port30# +# FC1 # +######### +xgxs_tx_lane_map_5=0x0123 +xgxs_rx_lane_map_5=0x0123 + +######### +# port31# +# FC2 # +######### +xgxs_tx_lane_map_9=0x0123 +xgxs_rx_lane_map_9=0x0123 + +######### +# port32# +# FC3 # +######### +xgxs_tx_lane_map_13=0x0123 +xgxs_rx_lane_map_13=0x0123 + + +## RX / TX Serdes lane polarity flip list +## RX / TX Serdes lane polarity flip list +######### +# FC4 # +# port21 # +######### +phy_xaui_tx_polarity_flip_17=0xf + +######### +# FC20 # +# port13 # +######### +phy_xaui_rx_polarity_flip_84=0xf +phy_xaui_tx_polarity_flip_84=0x6 + +######### +# FC21 # +# port14 # +######### +phy_xaui_rx_polarity_flip_88=0xf + +######### +# FC22 # +# port15 # +######### +phy_xaui_rx_polarity_flip_92=0xf +phy_xaui_tx_polarity_flip_92=0xe + + +######### +# FC23 # +# port16 # +######### +phy_xaui_tx_polarity_flip_96=0x1 + +######### +# FC24 # +# port17 # +######### +phy_xaui_tx_polarity_flip_102=0x1 + + +######### +# FC25 # +# port18 # +######### +phy_xaui_rx_polarity_flip_106=0xf + +######### +# FC26 # +# port19 # +######### +phy_xaui_tx_polarity_flip_110=0xe + +######### +# FC27 # +# port20 # +######### +phy_xaui_rx_polarity_flip_114=0x2 + +######### +# FC28 # +# port25 # +######### +phy_xaui_rx_polarity_flip_118=0xa +phy_xaui_tx_polarity_flip_118=0xf + +#Driver Current +serdes_driver_current_lane0_1=0x8 +serdes_driver_current_lane1_1=0x8 +serdes_driver_current_lane2_1=0x8 +serdes_driver_current_lane3_1=0x8 +serdes_driver_current_lane0_5=0x8 +serdes_driver_current_lane1_5=0x8 +serdes_driver_current_lane2_5=0x8 +serdes_driver_current_lane3_5=0x8 +serdes_driver_current_lane0_9=0x8 +serdes_driver_current_lane1_9=0x8 +serdes_driver_current_lane2_9=0x8 +serdes_driver_current_lane3_9=0x8 +serdes_driver_current_lane0_13=0x8 +serdes_driver_current_lane1_13=0x8 +serdes_driver_current_lane2_13=0x8 +serdes_driver_current_lane3_13=0x8 +serdes_driver_current_lane0_17=0x8 +serdes_driver_current_lane1_17=0x8 +serdes_driver_current_lane2_17=0x8 +serdes_driver_current_lane3_17=0x8 +serdes_driver_current_lane0_21=0x8 +serdes_driver_current_lane1_21=0x8 +serdes_driver_current_lane2_21=0x8 +serdes_driver_current_lane3_21=0x8 +serdes_driver_current_lane0_25=0x8 +serdes_driver_current_lane1_25=0x8 +serdes_driver_current_lane2_25=0x8 +serdes_driver_current_lane3_25=0x8 +serdes_driver_current_lane0_29=0x8 +serdes_driver_current_lane1_29=0x8 +serdes_driver_current_lane2_29=0x8 +serdes_driver_current_lane3_29=0x8 +serdes_driver_current_lane0_34=0x8 +serdes_driver_current_lane1_34=0x8 +serdes_driver_current_lane2_34=0x8 +serdes_driver_current_lane3_34=0x8 +serdes_driver_current_lane0_38=0x8 +serdes_driver_current_lane1_38=0x8 +serdes_driver_current_lane2_38=0x8 +serdes_driver_current_lane3_38=0x8 +serdes_driver_current_lane0_42=0x8 +serdes_driver_current_lane1_42=0x8 +serdes_driver_current_lane2_42=0x8 +serdes_driver_current_lane3_42=0x8 +serdes_driver_current_lane0_46=0x8 +serdes_driver_current_lane1_46=0x8 +serdes_driver_current_lane2_46=0x8 +serdes_driver_current_lane3_46=0x8 +serdes_driver_current_lane0_50=0x8 +serdes_driver_current_lane1_50=0x8 +serdes_driver_current_lane2_50=0x8 +serdes_driver_current_lane3_50=0x8 +serdes_driver_current_lane0_54=0x8 +serdes_driver_current_lane1_54=0x8 +serdes_driver_current_lane2_54=0x8 +serdes_driver_current_lane3_54=0x8 +serdes_driver_current_lane0_58=0x8 +serdes_driver_current_lane1_58=0x8 +serdes_driver_current_lane2_58=0x8 +serdes_driver_current_lane3_58=0x8 +serdes_driver_current_lane0_62=0x8 +serdes_driver_current_lane1_62=0x8 +serdes_driver_current_lane2_62=0x8 +serdes_driver_current_lane3_62=0x8 +serdes_driver_current_lane0_68=0x8 +serdes_driver_current_lane1_68=0x8 +serdes_driver_current_lane2_68=0x8 +serdes_driver_current_lane3_68=0x8 +serdes_driver_current_lane0_72=0x8 +serdes_driver_current_lane1_72=0x8 +serdes_driver_current_lane2_72=0x8 +serdes_driver_current_lane3_72=0x8 +serdes_driver_current_lane0_76=0x8 +serdes_driver_current_lane1_76=0x8 +serdes_driver_current_lane2_76=0x8 +serdes_driver_current_lane3_76=0x8 +serdes_driver_current_lane0_80=0x8 +serdes_driver_current_lane1_80=0x8 +serdes_driver_current_lane2_80=0x8 +serdes_driver_current_lane3_80=0x8 +serdes_driver_current_lane0_84=0x8 +serdes_driver_current_lane1_84=0x8 +serdes_driver_current_lane2_84=0x8 +serdes_driver_current_lane3_84=0x8 +serdes_driver_current_lane0_88=0x8 +serdes_driver_current_lane1_88=0x8 +serdes_driver_current_lane2_88=0x8 +serdes_driver_current_lane3_88=0x8 +serdes_driver_current_lane0_92=0x8 +serdes_driver_current_lane1_92=0x8 +serdes_driver_current_lane2_92=0x8 +serdes_driver_current_lane3_92=0x8 +serdes_driver_current_lane0_96=0x8 +serdes_driver_current_lane1_96=0x8 +serdes_driver_current_lane2_96=0x8 +serdes_driver_current_lane3_96=0x8 +serdes_driver_current_lane0_102=0x8 +serdes_driver_current_lane1_102=0x8 +serdes_driver_current_lane2_102=0x8 +serdes_driver_current_lane3_102=0x8 +serdes_driver_current_lane0_106=0x8 +serdes_driver_current_lane1_106=0x8 +serdes_driver_current_lane2_106=0x8 +serdes_driver_current_lane3_106=0x8 +serdes_driver_current_lane0_110=0x8 +serdes_driver_current_lane1_110=0x8 +serdes_driver_current_lane2_110=0x8 +serdes_driver_current_lane3_110=0x8 +serdes_driver_current_lane0_114=0x8 +serdes_driver_current_lane1_114=0x8 +serdes_driver_current_lane2_114=0x8 +serdes_driver_current_lane3_114=0x8 +serdes_driver_current_lane0_118=0x8 +serdes_driver_current_lane1_118=0x8 +serdes_driver_current_lane2_118=0x8 +serdes_driver_current_lane3_118=0x8 +serdes_driver_current_lane0_122=0x8 +serdes_driver_current_lane1_122=0x8 +serdes_driver_current_lane2_122=0x8 +serdes_driver_current_lane3_122=0x8 +serdes_driver_current_lane0_126=0x8 +serdes_driver_current_lane1_126=0x8 +serdes_driver_current_lane2_126=0x8 +serdes_driver_current_lane3_126=0x8 +serdes_driver_current_lane0_130=0x8 +serdes_driver_current_lane1_130=0x8 +serdes_driver_current_lane2_130=0x8 +serdes_driver_current_lane3_130=0x8 + +#Preemphasis +serdes_preemphasis_lane0_1=0x264204 +serdes_preemphasis_lane1_1=0x264204 +serdes_preemphasis_lane2_1=0x264204 +serdes_preemphasis_lane3_1=0x264204 +serdes_preemphasis_lane0_5=0x224406 +serdes_preemphasis_lane1_5=0x224406 +serdes_preemphasis_lane2_5=0x264204 +serdes_preemphasis_lane3_5=0x244206 +serdes_preemphasis_lane0_9=0x204606 +serdes_preemphasis_lane1_9=0x264204 +serdes_preemphasis_lane2_9=0x204606 +serdes_preemphasis_lane3_9=0x224406 +serdes_preemphasis_lane0_13=0x204606 +serdes_preemphasis_lane1_13=0x224406 +serdes_preemphasis_lane2_13=0x224406 +serdes_preemphasis_lane3_13=0x244206 +serdes_preemphasis_lane0_17=0x204606 +serdes_preemphasis_lane1_17=0x204606 +serdes_preemphasis_lane2_17=0x204606 +serdes_preemphasis_lane3_17=0x204606 +serdes_preemphasis_lane0_21=0x204606 +serdes_preemphasis_lane1_21=0x204606 +serdes_preemphasis_lane2_21=0x204606 +serdes_preemphasis_lane3_21=0x224406 +serdes_preemphasis_lane0_25=0x204606 +serdes_preemphasis_lane1_25=0x204606 +serdes_preemphasis_lane2_25=0x204606 +serdes_preemphasis_lane3_25=0x204606 +serdes_preemphasis_lane0_29=0x204606 +serdes_preemphasis_lane1_29=0x204606 +serdes_preemphasis_lane2_29=0x204606 +serdes_preemphasis_lane3_29=0x204606 +serdes_preemphasis_lane0_34=0x284601 +serdes_preemphasis_lane1_34=0x284601 +serdes_preemphasis_lane2_34=0x284601 +serdes_preemphasis_lane3_34=0x284601 +serdes_preemphasis_lane0_38=0x204604 +serdes_preemphasis_lane1_38=0x204604 +serdes_preemphasis_lane2_38=0x224406 +serdes_preemphasis_lane3_38=0x224406 +serdes_preemphasis_lane0_42=0x284601 +serdes_preemphasis_lane1_42=0x294501 +serdes_preemphasis_lane2_42=0x284601 +serdes_preemphasis_lane3_42=0x284601 +serdes_preemphasis_lane0_46=0x204802 +serdes_preemphasis_lane1_46=0x204802 +serdes_preemphasis_lane2_46=0x204802 +serdes_preemphasis_lane3_46=0x204802 +serdes_preemphasis_lane0_50=0x1e4f01 +serdes_preemphasis_lane1_50=0x1e4d01 +serdes_preemphasis_lane2_50=0x1e4f01 +serdes_preemphasis_lane3_50=0x1e4f01 +serdes_preemphasis_lane0_54=0x1f4a03 +serdes_preemphasis_lane1_54=0x1f4a03 +serdes_preemphasis_lane2_54=0x1f4a03 +serdes_preemphasis_lane3_54=0x1f4a03 +serdes_preemphasis_lane0_58=0x1e4f01 +serdes_preemphasis_lane1_58=0x1e4f01 +serdes_preemphasis_lane2_58=0x1e4f01 +serdes_preemphasis_lane3_58=0x1e4f01 +serdes_preemphasis_lane0_62=0x1e4e02 +serdes_preemphasis_lane1_62=0x1e4e02 +serdes_preemphasis_lane2_62=0x1e4e02 +serdes_preemphasis_lane3_62=0x1e4e02 +serdes_preemphasis_lane0_68=0x1e4f01 +serdes_preemphasis_lane1_68=0x1e4f01 +serdes_preemphasis_lane2_68=0x1e4f01 +serdes_preemphasis_lane3_68=0x1e4f01 +serdes_preemphasis_lane0_72=0x1e4e02 +serdes_preemphasis_lane1_72=0x1e4e02 +serdes_preemphasis_lane2_72=0x1e4e02 +serdes_preemphasis_lane3_72=0x1e4e02 +serdes_preemphasis_lane0_76=0x1c4d02 +serdes_preemphasis_lane1_76=0x195002 +serdes_preemphasis_lane2_76=0x195002 +serdes_preemphasis_lane3_76=0x195002 +serdes_preemphasis_lane0_80=0x1e4e02 +serdes_preemphasis_lane1_80=0x1e4e02 +serdes_preemphasis_lane2_80=0x1e4e02 +serdes_preemphasis_lane3_80=0x1e4e02 +serdes_preemphasis_lane0_84=0x234701 +serdes_preemphasis_lane1_84=0x234701 +serdes_preemphasis_lane2_84=0x234701 +serdes_preemphasis_lane3_84=0x234701 +serdes_preemphasis_lane0_88=0x224802 +serdes_preemphasis_lane1_88=0x224602 +serdes_preemphasis_lane2_88=0x224802 +serdes_preemphasis_lane3_88=0x224802 +serdes_preemphasis_lane0_92=0x234801 +serdes_preemphasis_lane1_92=0x244701 +serdes_preemphasis_lane2_92=0x234801 +serdes_preemphasis_lane3_92=0x234601 +serdes_preemphasis_lane0_96=0x204406 +serdes_preemphasis_lane1_96=0x204406 +serdes_preemphasis_lane2_96=0x204406 +serdes_preemphasis_lane3_96=0x224602 +serdes_preemphasis_lane0_102=0x204606 +serdes_preemphasis_lane1_102=0x235002 +serdes_preemphasis_lane2_102=0x204606 +serdes_preemphasis_lane3_102=0x204606 +serdes_preemphasis_lane0_106=0x204606 +serdes_preemphasis_lane1_106=0x204606 +serdes_preemphasis_lane2_106=0x204606 +serdes_preemphasis_lane3_106=0x204606 +serdes_preemphasis_lane0_110=0x204606 +serdes_preemphasis_lane1_110=0x224406 +serdes_preemphasis_lane2_110=0x224406 +serdes_preemphasis_lane3_110=0x224406 +serdes_preemphasis_lane0_114=0x224406 +serdes_preemphasis_lane1_114=0x204606 +serdes_preemphasis_lane2_114=0x204606 +serdes_preemphasis_lane3_114=0x224406 +serdes_preemphasis_lane0_118=0x224406 +serdes_preemphasis_lane1_118=0x224406 +serdes_preemphasis_lane2_118=0x224406 +serdes_preemphasis_lane3_118=0x224406 +serdes_preemphasis_lane0_122=0x244404 +serdes_preemphasis_lane1_122=0x244404 +serdes_preemphasis_lane2_122=0x244404 +serdes_preemphasis_lane3_122=0x244404 +serdes_preemphasis_lane0_126=0x234504 +serdes_preemphasis_lane1_126=0x234404 +serdes_preemphasis_lane2_126=0x224406 +serdes_preemphasis_lane3_126=0x224406 +serdes_preemphasis_lane0_130=0x244404 +serdes_preemphasis_lane1_130=0x244404 +serdes_preemphasis_lane2_130=0x234504 +serdes_preemphasis_lane3_130=0x264501 diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/default_sku b/device/accton/x86_64-accton_as7716_32xb-r0/default_sku new file mode 100644 index 000000000000..973e749a1fc7 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7716-32XB t1 diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/installer.conf b/device/accton/x86_64-accton_as7716_32xb-r0/installer.conf new file mode 100755 index 000000000000..d97e3195e8fd --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="tg3.short_preamble=1 tg3.bcm5718s_reset=1" diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7716_32xb-r0/led_proc_init.soc new file mode 100755 index 000000000000..719cb777719f --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/led_proc_init.soc @@ -0,0 +1,41 @@ +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=62 REMAP_PORT_18=61 REMAP_PORT_19=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=59 REMAP_PORT_21=58 REMAP_PORT_22=57 REMAP_PORT_23=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=55 REMAP_PORT_25=54 REMAP_PORT_26=53 REMAP_PORT_27=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=51 REMAP_PORT_29=50 REMAP_PORT_30=49 REMAP_PORT_31=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=47 REMAP_PORT_33=46 REMAP_PORT_34=45 REMAP_PORT_35=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=43 REMAP_PORT_37=42 REMAP_PORT_38=41 REMAP_PORT_39=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=39 REMAP_PORT_41=38 REMAP_PORT_42=37 REMAP_PORT_43=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=35 REMAP_PORT_45=34 REMAP_PORT_46=33 REMAP_PORT_47=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=35 REMAP_PORT_1=34 REMAP_PORT_2=33 REMAP_PORT_3=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=39 REMAP_PORT_5=38 REMAP_PORT_6=37 REMAP_PORT_7=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=43 REMAP_PORT_9=42 REMAP_PORT_10=41 REMAP_PORT_11=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=47 REMAP_PORT_13=46 REMAP_PORT_14=45 REMAP_PORT_15=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=3 REMAP_PORT_17=2 REMAP_PORT_18=1 REMAP_PORT_19=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=7 REMAP_PORT_21=6 REMAP_PORT_22=5 REMAP_PORT_23=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=11 REMAP_PORT_25=10 REMAP_PORT_26=9 REMAP_PORT_27=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=15 REMAP_PORT_29=14 REMAP_PORT_30=13 REMAP_PORT_31=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 REMAP_PORT_33=18 REMAP_PORT_34=17 REMAP_PORT_35=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 REMAP_PORT_37=22 REMAP_PORT_38=21 REMAP_PORT_39=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 REMAP_PORT_41=26 REMAP_PORT_42=25 REMAP_PORT_43=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 REMAP_PORT_45=30 REMAP_PORT_46=29 REMAP_PORT_47=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 prog 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 84 67 98 57 80 18 71 EB 67 98 67 84 57 67 84 67 84 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 start + +led 1 prog 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 84 67 98 57 80 18 71 EB 67 98 67 84 57 67 84 67 84 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 1 start + +led auto on \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7716_32xb-r0/plugins/eeprom.py new file mode 100755 index 000000000000..6fa5719afbad --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + #Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7716_32xb-r0/plugins/psuutil.py new file mode 100755 index 000000000000..5a4b0fe83d87 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/plugins/psuutil.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "0-0053", + 2: "0-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7716_32xb-r0/plugins/sfputil.py new file mode 100755 index 000000000000..b582602fa9b5 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/plugins/sfputil.py @@ -0,0 +1,144 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + import sys, getopt + import commands + 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 + + BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" + BASE_CPLD_PATH = "/sys/bus/i2c/devices/0-0060/" + BASE_I2C_PATH = "/sys/bus/i2c/devices/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 0: [1, 29], + 1: [2, 30], + 2: [3, 31], + 3: [4, 32], + 4: [5, 34], + 5: [6, 33], + 6: [7, 36], + 7: [8, 35], + 8: [9, 25], + 9: [10, 26], + 10: [11, 27], + 11: [12, 28], + 12: [14, 37], + 13: [15, 38], + 14: [16, 39], + 15: [17, 40], + 16: [18, 41], + 17: [19, 42], + 18: [20, 43], + 19: [21, 44], + 20: [22, 53], + 21: [23, 54], + 22: [24, 55], + 23: [25, 56], + 24: [26, 45], + 25: [27, 46], + 26: [28, 47], + 27: [29, 48], + 28: [30, 49], + 29: [31, 50], + 30: [32, 51], + 31: [33, 52], + } + + @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(self.PORT_START, self.PORTS_IN_BLOCK + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + 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 + + present_path = self.BASE_CPLD_PATH + "module_present_" + str(port_num+1) + self.__port_to_is_present = present_path + + try: + val_file = open(self.__port_to_is_present) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def __init__(self): + eeprom_path = self.BASE_I2C_PATH + + for x in range(0, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x][1] + ) + if(x < 9): + if(self.get_presence(x)==1): + self.port_to_eeprom_mapping[x] = self.BASE_I2C_PATH + "0-000" +str(x+1) + "/eeprom" + + else: + if(self.get_presence(x)==1): + self.port_to_eeprom_mapping[x] = self.BASE_I2C_PATH + "0-00" +str(x+1)+ "/eeprom" + + SfpUtilBase.__init__(self) + + + + 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): + if port_num < self.port_start or port_num > self.port_end: + return False + + mod_rst_cmd = "ipmitool raw 0x34 0x11 " + str(port_num+1) + " 0x11 0x1" + (status, output) = commands.getstatusoutput (mod_rst_cmd) + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/port_config.ini b/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/port_config.ini new file mode 100644 index 000000000000..20d1b84edce5 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias +Ethernet0 73,74,75,76 hundredGigE1 +Ethernet4 65,66,67,68 hundredGigE2 +Ethernet8 81,82,83,84 hundredGigE3 +Ethernet12 89,90,91,92 hundredGigE4 +Ethernet16 105,106,107,108 hundredGigE5 +Ethernet20 97,98,99,100 hundredGigE6 +Ethernet24 113,114,115,116 hundredGigE7 +Ethernet28 121,122,123,124 hundredGigE8 +Ethernet32 41,42,43,44 hundredGigE9 +Ethernet36 33,34,35,36 hundredGigE10 +Ethernet40 49,50,51,52 hundredGigE11 +Ethernet44 57,58,59,60 hundredGigE12 +Ethernet48 137,138,139,140 hundredGigE13 +Ethernet52 129,130,131,132 hundredGigE14 +Ethernet56 145,146,147,148 hundredGigE15 +Ethernet60 153,154,155,156 hundredGigE16 +Ethernet64 173,174,175,176 hundredGigE17 +Ethernet68 165,166,167,168 hundredGigE18 +Ethernet72 181,182,183,184 hundredGigE19 +Ethernet76 189,190,191,192 hundredGigE20 +Ethernet80 13,14,15,16 hundredGigE21 +Ethernet84 5,6,7,8 hundredGigE22 +Ethernet88 29,30,31,32 hundredGigE23 +Ethernet92 21,22,23,24 hundredGigE24 +Ethernet96 205,206,207,208 hundredGigE25 +Ethernet100 197,198,199,200 hundredGigE26 +Ethernet104 213,214,215,216 hundredGigE27 +Ethernet108 221,222,223,224 hundredGigE28 +Ethernet112 229,230,231,232 hundredGigE29 +Ethernet116 237,238,239,240 hundredGigE30 +Ethernet120 245,246,247,248 hundredGigE31 +Ethernet124 253,254,255,256 hundredGigE32 +Ethernet128 69,70,71,72 hundredGigE33 +Ethernet132 77,78,79,80 hundredGigE34 +Ethernet136 93,94,95,96 hundredGigE35 +Ethernet140 85,86,87,88 hundredGigE36 +Ethernet144 101,102,103,104 hundredGigE37 +Ethernet148 109,110,111,112 hundredGigE38 +Ethernet152 125,126,127,128 hundredGigE39 +Ethernet156 117,118,119,120 hundredGigE40 +Ethernet160 37,38,39,40 hundredGigE41 +Ethernet164 45,46,47,48 hundredGigE42 +Ethernet168 61,62,63,64 hundredGigE43 +Ethernet172 53,54,55,56 hundredGigE44 +Ethernet176 133,134,135,136 hundredGigE45 +Ethernet180 141,142,143,144 hundredGigE46 +Ethernet184 157,158,159,160 hundredGigE47 +Ethernet188 149,150,151,152 hundredGigE48 +Ethernet192 161,162,163,164 hundredGigE49 +Ethernet196 169,170,171,172 hundredGigE50 +Ethernet200 185,186,187,188 hundredGigE51 +Ethernet204 177,178,179,180 hundredGigE52 +Ethernet208 1,2,3,4 hundredGigE53 +Ethernet212 9,10,11,12 hundredGigE54 +Ethernet216 25,26,27,28 hundredGigE55 +Ethernet220 17,18,19,20 hundredGigE56 +Ethernet224 193,194,195,196 hundredGigE57 +Ethernet228 201,202,203,204 hundredGigE58 +Ethernet232 217,218,219,220 hundredGigE59 +Ethernet236 209,210,211,212 hundredGigE60 +Ethernet240 225,226,227,228 hundredGigE61 +Ethernet244 233,234,235,236 hundredGigE62 +Ethernet248 249,250,251,252 hundredGigE63 +Ethernet252 241,242,243,244 hundredGigE64 diff --git a/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/sai.profile b/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/sai.profile new file mode 100644 index 000000000000..e2f945e9a073 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-as7816-64x100G.config.bcm diff --git a/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/th2-as7816-64x100G.config.bcm b/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/th2-as7816-64x100G.config.bcm new file mode 100644 index 000000000000..78f6b419864e --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/th2-as7816-64x100G.config.bcm @@ -0,0 +1,875 @@ +# accton_as7816_64x 64x100G SDK config +os=unix +schan_intr_enable=0 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +pbmp_oversubscribe=0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +# platform specific setting +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=8 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +oversubscribe_mode=1 + +#add loopback port +# port 33 is the first loopback port +portmap_33=260:10 +# port 66 is the first management port +portmap_66=257:10 +# port 67 is the second loopback port +portmap_67=261:10 +# port 100 is the second management port +portmap_100=259:10 +# port 101 is the third loopback port +portmap_101=262:10 +# port 135 is the fourth loopback port +portmap_135=263:10 + +#Port0 +#FC18 +portmap_36=73:100 +phy_chain_rx_lane_map_physical{73.0}=0x3210 +phy_chain_tx_lane_map_physical{73.0}=0x3021 +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{76.0}=0x1 +phy_chain_tx_polarity_flip_physical{73.0}=0x0 +phy_chain_tx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x1 +phy_chain_tx_polarity_flip_physical{76.0}=0x0 +#Port1 +#FC16 +portmap_34=65:100 +phy_chain_rx_lane_map_physical{65.0}=0x3210 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_rx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 +#Port2 +#FC20 +portmap_38=81:100 +phy_chain_rx_lane_map_physical{81.0}=0x1230 +phy_chain_tx_lane_map_physical{81.0}=0x1032 +phy_chain_rx_polarity_flip_physical{81.0}=0x1 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x1 +phy_chain_rx_polarity_flip_physical{84.0}=0x0 +phy_chain_tx_polarity_flip_physical{81.0}=0x1 +phy_chain_tx_polarity_flip_physical{82.0}=0x1 +phy_chain_tx_polarity_flip_physical{83.0}=0x1 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 +#Port3 +#FC22 +portmap_40=89:100 +phy_chain_rx_lane_map_physical{89.0}=0x0132 +phy_chain_tx_lane_map_physical{89.0}=0x1203 +phy_chain_rx_polarity_flip_physical{89.0}=0x1 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{91.0}=0x0 +phy_chain_rx_polarity_flip_physical{92.0}=0x1 +phy_chain_tx_polarity_flip_physical{89.0}=0x1 +phy_chain_tx_polarity_flip_physical{90.0}=0x0 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x1 +#Port4 +#FC26 +portmap_44=105:100 +phy_chain_rx_lane_map_physical{105.0}=0x3210 +phy_chain_tx_lane_map_physical{105.0}=0x0231 +phy_chain_rx_polarity_flip_physical{105.0}=0x0 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 +phy_chain_tx_polarity_flip_physical{105.0}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_tx_polarity_flip_physical{107.0}=0x0 +phy_chain_tx_polarity_flip_physical{108.0}=0x1 +#Port5 +#FC24 +portmap_42=97:100 +phy_chain_rx_lane_map_physical{97.0}=0x0213 +phy_chain_tx_lane_map_physical{97.0}=0x3210 +phy_chain_rx_polarity_flip_physical{97.0}=0x1 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 +phy_chain_tx_polarity_flip_physical{97.0}=0x1 +phy_chain_tx_polarity_flip_physical{98.0}=0x1 +phy_chain_tx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +#Port6 +#FC 28 +portmap_46=113:100 +phy_chain_rx_lane_map_physical{113.0}=0x3021 +phy_chain_tx_lane_map_physical{113.0}=0x0312 +phy_chain_rx_polarity_flip_physical{113.0}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x1 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +phy_chain_tx_polarity_flip_physical{114.0}=0x0 +phy_chain_tx_polarity_flip_physical{115.0}=0x0 +phy_chain_tx_polarity_flip_physical{116.0}=0x1 +#Port7 +#FC30 +portmap_48=121:100 +phy_chain_rx_lane_map_physical{121.0}=0x3021 +phy_chain_tx_lane_map_physical{121.0}=0x2130 +phy_chain_rx_polarity_flip_physical{121.0}=0x0 +phy_chain_rx_polarity_flip_physical{122.0}=0x1 +phy_chain_rx_polarity_flip_physical{123.0}=0x1 +phy_chain_rx_polarity_flip_physical{124.0}=0x0 +phy_chain_tx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x1 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +phy_chain_tx_polarity_flip_physical{124.0}=0x0 +#Port8 +#FC10 +portmap_11=41:100 +phy_chain_rx_lane_map_physical{41.0}=0x0132 +phy_chain_tx_lane_map_physical{41.0}=0x1302 +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x0 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +#Port9 +#FC8 +portmap_9=33:100 +phy_chain_rx_lane_map_physical{33.0}=0x2310 +phy_chain_tx_lane_map_physical{33.0}=0x0213 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x1 +phy_chain_tx_polarity_flip_physical{34.0}=0x1 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 +#Port10 +#FC12 +portmap_13=49:100 +phy_chain_rx_lane_map_physical{49.0}=0x3210 +phy_chain_tx_lane_map_physical{49.0}=0x3102 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 +#Port11 +#FC14 +portmap_15=57:100 +phy_chain_rx_lane_map_physical{57.0}=0x3210 +phy_chain_tx_lane_map_physical{57.0}=0x1302 +phy_chain_rx_polarity_flip_physical{57.0}=0x1 +phy_chain_rx_polarity_flip_physical{58.0}=0x0 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_tx_polarity_flip_physical{58.0}=0x0 +phy_chain_tx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x1 +#Port12 +#FC34 +portmap_70=137:100 +phy_chain_rx_lane_map_physical{137.0}=0x3210 +phy_chain_tx_lane_map_physical{137.0}=0x0213 +phy_chain_rx_polarity_flip_physical{137.0}=0x0 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{140.0}=0x0 +phy_chain_tx_polarity_flip_physical{137.0}=0x1 +phy_chain_tx_polarity_flip_physical{138.0}=0x0 +phy_chain_tx_polarity_flip_physical{139.0}=0x0 +phy_chain_tx_polarity_flip_physical{140.0}=0x0 +#Port13 +#FC32 +portmap_68=129:100 +phy_chain_rx_lane_map_physical{129.0}=0x3021 +phy_chain_tx_lane_map_physical{129.0}=0x1203 +phy_chain_rx_polarity_flip_physical{129.0}=0x1 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +phy_chain_tx_polarity_flip_physical{130.0}=0x1 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x1 +#Port14 +#FC36 +portmap_72=145:100 +phy_chain_rx_lane_map_physical{145.0}=0x0213 +phy_chain_tx_lane_map_physical{145.0}=0x2301 +phy_chain_rx_polarity_flip_physical{145.0}=0x1 +phy_chain_rx_polarity_flip_physical{146.0}=0x1 +phy_chain_rx_polarity_flip_physical{147.0}=0x0 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 +phy_chain_tx_polarity_flip_physical{145.0}=0x0 +phy_chain_tx_polarity_flip_physical{146.0}=0x0 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x1 +#Port15 +#FC38 +portmap_74=153:100 +phy_chain_rx_lane_map_physical{153.0}=0x0213 +phy_chain_tx_lane_map_physical{153.0}=0x1302 +phy_chain_rx_polarity_flip_physical{153.0}=0x1 +phy_chain_rx_polarity_flip_physical{154.0}=0x0 +phy_chain_rx_polarity_flip_physical{155.0}=0x1 +phy_chain_rx_polarity_flip_physical{156.0}=0x1 +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x1 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 +#Port16 +#FC43 +portmap_79=173:100 +phy_chain_rx_lane_map_physical{173.0}=0x1032 +phy_chain_tx_lane_map_physical{173.0}=0x1203 +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x0 +phy_chain_rx_polarity_flip_physical{175.0}=0x0 +phy_chain_rx_polarity_flip_physical{176.0}=0x0 +phy_chain_tx_polarity_flip_physical{173.0}=0x1 +phy_chain_tx_polarity_flip_physical{174.0}=0x1 +phy_chain_tx_polarity_flip_physical{175.0}=0x0 +phy_chain_tx_polarity_flip_physical{176.0}=0x1 +#Port17 +#FC41 +portmap_77=165:100 +phy_chain_rx_lane_map_physical{165.0}=0x1230 +phy_chain_tx_lane_map_physical{165.0}=0x2130 +phy_chain_rx_polarity_flip_physical{165.0}=0x1 +phy_chain_rx_polarity_flip_physical{166.0}=0x0 +phy_chain_rx_polarity_flip_physical{167.0}=0x1 +phy_chain_rx_polarity_flip_physical{168.0}=0x1 +phy_chain_tx_polarity_flip_physical{165.0}=0x1 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x1 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 +#Port18 +#FC45 +portmap_81=181:100 +phy_chain_rx_lane_map_physical{181.0}=0x0312 +phy_chain_tx_lane_map_physical{181.0}=0x3120 +phy_chain_rx_polarity_flip_physical{181.0}=0x0 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x1 +phy_chain_rx_polarity_flip_physical{184.0}=0x0 +phy_chain_tx_polarity_flip_physical{181.0}=0x0 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x1 +phy_chain_tx_polarity_flip_physical{184.0}=0x0 +#Port19 +#FC47 +portmap_83=189:100 +phy_chain_rx_lane_map_physical{189.0}=0x0132 +phy_chain_tx_lane_map_physical{189.0}=0x3210 +phy_chain_rx_polarity_flip_physical{189.0}=0x0 +phy_chain_rx_polarity_flip_physical{190.0}=0x1 +phy_chain_rx_polarity_flip_physical{191.0}=0x1 +phy_chain_rx_polarity_flip_physical{192.0}=0x1 +phy_chain_tx_polarity_flip_physical{189.0}=0x1 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x0 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 +#Port20 +#FC3 +portmap_4=13:100 +phy_chain_rx_lane_map_physical{13.0}=0x3120 +phy_chain_tx_lane_map_physical{13.0}=0x3210 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x1 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 +#Port21 +#FC1 +portmap_2=5:100 +phy_chain_rx_lane_map_physical{5.0}=0x0213 +phy_chain_tx_lane_map_physical{5.0}=0x0321 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 +#Port22 +#FC7 +portmap_8=29:100 +phy_chain_rx_lane_map_physical{29.0}=0x3021 +phy_chain_tx_lane_map_physical{29.0}=0x2130 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +#Port23 +#FC5 +portmap_6=21:100 +phy_chain_rx_lane_map_physical{21.0}=0x0321 +phy_chain_tx_lane_map_physical{21.0}=0x0123 +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x1 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x1 +#Port24 +#FC51 +portmap_105=205:100 +phy_chain_rx_lane_map_physical{205.0}=0x0132 +phy_chain_tx_lane_map_physical{205.0}=0x1230 +phy_chain_rx_polarity_flip_physical{205.0}=0x1 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x1 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 +phy_chain_tx_polarity_flip_physical{205.0}=0x0 +phy_chain_tx_polarity_flip_physical{206.0}=0x1 +phy_chain_tx_polarity_flip_physical{207.0}=0x0 +phy_chain_tx_polarity_flip_physical{208.0}=0x1 +#Port25 +#FC49 +portmap_103=197:100 +phy_chain_rx_lane_map_physical{197.0}=0x1230 +phy_chain_tx_lane_map_physical{197.0}=0x3021 +phy_chain_rx_polarity_flip_physical{197.0}=0x0 +phy_chain_rx_polarity_flip_physical{198.0}=0x0 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x0 +phy_chain_tx_polarity_flip_physical{197.0}=0x1 +phy_chain_tx_polarity_flip_physical{198.0}=0x0 +phy_chain_tx_polarity_flip_physical{199.0}=0x1 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 +#Port26 +#FC53 +portmap_107=213:100 +phy_chain_rx_lane_map_physical{213.0}=0x3210 +phy_chain_tx_lane_map_physical{213.0}=0x1230 +phy_chain_rx_polarity_flip_physical{213.0}=0x0 +phy_chain_rx_polarity_flip_physical{214.0}=0x1 +phy_chain_rx_polarity_flip_physical{215.0}=0x0 +phy_chain_rx_polarity_flip_physical{216.0}=0x1 +phy_chain_tx_polarity_flip_physical{213.0}=0x0 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x1 +#Port27 +#FC55 +portmap_109=221:100 +phy_chain_rx_lane_map_physical{221.0}=0x3210 +phy_chain_tx_lane_map_physical{221.0}=0x3210 +phy_chain_rx_polarity_flip_physical{221.0}=0x1 +phy_chain_rx_polarity_flip_physical{222.0}=0x1 +phy_chain_rx_polarity_flip_physical{223.0}=0x0 +phy_chain_rx_polarity_flip_physical{224.0}=0x0 +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x0 +phy_chain_tx_polarity_flip_physical{223.0}=0x0 +phy_chain_tx_polarity_flip_physical{224.0}=0x0 +#Port28 +#FC57 +portmap_111=229:100 +phy_chain_rx_lane_map_physical{229.0}=0x2301 +phy_chain_tx_lane_map_physical{229.0}=0x3210 +phy_chain_rx_polarity_flip_physical{229.0}=0x1 +phy_chain_rx_polarity_flip_physical{230.0}=0x1 +phy_chain_rx_polarity_flip_physical{231.0}=0x0 +phy_chain_rx_polarity_flip_physical{232.0}=0x1 +phy_chain_tx_polarity_flip_physical{229.0}=0x0 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x0 +phy_chain_tx_polarity_flip_physical{232.0}=0x0 +#Port29 +#FC59 +portmap_113=237:100 +phy_chain_rx_lane_map_physical{237.0}=0x0123 +phy_chain_tx_lane_map_physical{237.0}=0x3210 +phy_chain_rx_polarity_flip_physical{237.0}=0x1 +phy_chain_rx_polarity_flip_physical{238.0}=0x0 +phy_chain_rx_polarity_flip_physical{239.0}=0x1 +phy_chain_rx_polarity_flip_physical{240.0}=0x1 +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 +#Port30 +#FC61 +portmap_115=245:100 +phy_chain_rx_lane_map_physical{245.0}=0x0213 +phy_chain_tx_lane_map_physical{245.0}=0x3210 +phy_chain_rx_polarity_flip_physical{245.0}=0x0 +phy_chain_rx_polarity_flip_physical{246.0}=0x0 +phy_chain_rx_polarity_flip_physical{247.0}=0x1 +phy_chain_rx_polarity_flip_physical{248.0}=0x1 +phy_chain_tx_polarity_flip_physical{245.0}=0x1 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x1 +phy_chain_tx_polarity_flip_physical{248.0}=0x0 +#Port31 +#FC63 +portmap_117=253:100 +phy_chain_rx_lane_map_physical{253.0}=0x0213 +phy_chain_tx_lane_map_physical{253.0}=0x0312 +phy_chain_rx_polarity_flip_physical{253.0}=0x0 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x0 +phy_chain_rx_polarity_flip_physical{256.0}=0x1 +phy_chain_tx_polarity_flip_physical{253.0}=0x0 +phy_chain_tx_polarity_flip_physical{254.0}=0x1 +phy_chain_tx_polarity_flip_physical{255.0}=0x0 +phy_chain_tx_polarity_flip_physical{256.0}=0x0 +#Port32 +#FC17 +portmap_35=69:100 +phy_chain_rx_lane_map_physical{69.0}=0x1032 +phy_chain_tx_lane_map_physical{69.0}=0x3102 +phy_chain_rx_polarity_flip_physical{69.0}=0x1 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x1 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x0 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +phy_chain_tx_polarity_flip_physical{72.0}=0x1 +#Port33 +#FC19 +portmap_37=77:100 +phy_chain_rx_lane_map_physical{77.0}=0x1230 +phy_chain_tx_lane_map_physical{77.0}=0x3021 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x0 +phy_chain_rx_polarity_flip_physical{79.0}=0x1 +phy_chain_rx_polarity_flip_physical{80.0}=0x0 +phy_chain_tx_polarity_flip_physical{77.0}=0x0 +phy_chain_tx_polarity_flip_physical{78.0}=0x0 +phy_chain_tx_polarity_flip_physical{79.0}=0x1 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +#Port34 +#FC23 +portmap_41=93:100 +phy_chain_rx_lane_map_physical{93.0}=0x1032 +phy_chain_tx_lane_map_physical{93.0}=0x0231 +phy_chain_rx_polarity_flip_physical{93.0}=0x1 +phy_chain_rx_polarity_flip_physical{94.0}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x1 +phy_chain_rx_polarity_flip_physical{96.0}=0x1 +phy_chain_tx_polarity_flip_physical{93.0}=0x0 +phy_chain_tx_polarity_flip_physical{94.0}=0x1 +phy_chain_tx_polarity_flip_physical{95.0}=0x1 +phy_chain_tx_polarity_flip_physical{96.0}=0x1 +#Port35 +#FC21 +portmap_39=85:100 +phy_chain_rx_lane_map_physical{85.0}=0x0312 +phy_chain_tx_lane_map_physical{85.0}=0x1230 +phy_chain_rx_polarity_flip_physical{85.0}=0x0 +phy_chain_rx_polarity_flip_physical{86.0}=0x0 +phy_chain_rx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x1 +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x0 +phy_chain_tx_polarity_flip_physical{87.0}=0x1 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +#Port36 +#FC25 +portmap_43=101:100 +phy_chain_rx_lane_map_physical{101.0}=0x1302 +phy_chain_tx_lane_map_physical{101.0}=0x0213 +phy_chain_rx_polarity_flip_physical{101.0}=0x1 +phy_chain_rx_polarity_flip_physical{102.0}=0x0 +phy_chain_rx_polarity_flip_physical{103.0}=0x0 +phy_chain_rx_polarity_flip_physical{104.0}=0x0 +phy_chain_tx_polarity_flip_physical{101.0}=0x0 +phy_chain_tx_polarity_flip_physical{102.0}=0x1 +phy_chain_tx_polarity_flip_physical{103.0}=0x0 +phy_chain_tx_polarity_flip_physical{104.0}=0x1 +#Port37 +#FC27 +portmap_45=109:100 +phy_chain_rx_lane_map_physical{109.0}=0x0213 +phy_chain_tx_lane_map_physical{109.0}=0x1032 +phy_chain_rx_polarity_flip_physical{109.0}=0x1 +phy_chain_rx_polarity_flip_physical{110.0}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x0 +phy_chain_rx_polarity_flip_physical{112.0}=0x0 +phy_chain_tx_polarity_flip_physical{109.0}=0x0 +phy_chain_tx_polarity_flip_physical{110.0}=0x1 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +phy_chain_tx_polarity_flip_physical{112.0}=0x1 +#Port38 +#FC31 +portmap_49=125:100 +phy_chain_rx_lane_map_physical{125.0}=0x2130 +phy_chain_tx_lane_map_physical{125.0}=0x1203 +phy_chain_rx_polarity_flip_physical{125.0}=0x0 +phy_chain_rx_polarity_flip_physical{126.0}=0x0 +phy_chain_rx_polarity_flip_physical{127.0}=0x1 +phy_chain_rx_polarity_flip_physical{128.0}=0x1 +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x1 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 +#Port39 +#FC29 +portmap_47=117:100 +phy_chain_rx_lane_map_physical{117.0}=0x3102 +phy_chain_tx_lane_map_physical{117.0}=0x2310 +phy_chain_rx_polarity_flip_physical{117.0}=0x1 +phy_chain_rx_polarity_flip_physical{118.0}=0x0 +phy_chain_rx_polarity_flip_physical{119.0}=0x1 +phy_chain_rx_polarity_flip_physical{120.0}=0x0 +phy_chain_tx_polarity_flip_physical{117.0}=0x1 +phy_chain_tx_polarity_flip_physical{118.0}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x1 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +#Port40 +#FC9 +portmap_10=37:100 +phy_chain_rx_lane_map_physical{37.0}=0x3210 +phy_chain_tx_lane_map_physical{37.0}=0x1302 +phy_chain_rx_polarity_flip_physical{37.0}=0x1 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x0 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 +#Port41 +#FC11 +portmap_12=45:100 +phy_chain_rx_lane_map_physical{45.0}=0x3210 +phy_chain_tx_lane_map_physical{45.0}=0x0123 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{46.0}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x0 +phy_chain_rx_polarity_flip_physical{48.0}=0x0 +phy_chain_tx_polarity_flip_physical{45.0}=0x0 +phy_chain_tx_polarity_flip_physical{46.0}=0x1 +phy_chain_tx_polarity_flip_physical{47.0}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x1 +#Port42 +#FC15 +portmap_16=61:100 +phy_chain_rx_lane_map_physical{61.0}=0x3210 +phy_chain_tx_lane_map_physical{61.0}=0x1230 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x1 +phy_chain_rx_polarity_flip_physical{63.0}=0x0 +phy_chain_rx_polarity_flip_physical{64.0}=0x0 +phy_chain_tx_polarity_flip_physical{61.0}=0x0 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +phy_chain_tx_polarity_flip_physical{64.0}=0x0 +#Port43 +#FC13 +portmap_14=53:100 +phy_chain_rx_lane_map_physical{53.0}=0x3210 +phy_chain_tx_lane_map_physical{53.0}=0x3210 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +phy_chain_rx_polarity_flip_physical{56.0}=0x0 +phy_chain_tx_polarity_flip_physical{53.0}=0x1 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x0 +#Port44 +#FC33 +portmap_69=133:100 +phy_chain_rx_lane_map_physical{133.0}=0x0312 +phy_chain_tx_lane_map_physical{133.0}=0x2310 +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x0 +phy_chain_rx_polarity_flip_physical{135.0}=0x1 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 +phy_chain_tx_polarity_flip_physical{133.0}=0x0 +phy_chain_tx_polarity_flip_physical{134.0}=0x1 +phy_chain_tx_polarity_flip_physical{135.0}=0x0 +phy_chain_tx_polarity_flip_physical{136.0}=0x1 +#Port45 +#FC35 +portmap_71=141:100 +phy_chain_rx_lane_map_physical{141.0}=0x3012 +phy_chain_tx_lane_map_physical{141.0}=0x0123 +phy_chain_rx_polarity_flip_physical{141.0}=0x1 +phy_chain_rx_polarity_flip_physical{142.0}=0x0 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x0 +phy_chain_tx_polarity_flip_physical{141.0}=0x1 +phy_chain_tx_polarity_flip_physical{142.0}=0x1 +phy_chain_tx_polarity_flip_physical{143.0}=0x0 +phy_chain_tx_polarity_flip_physical{144.0}=0x0 +#Port46 +#FC39 +portmap_75=157:100 +phy_chain_rx_lane_map_physical{157.0}=0x2103 +phy_chain_tx_lane_map_physical{157.0}=0x0231 +phy_chain_rx_polarity_flip_physical{157.0}=0x0 +phy_chain_rx_polarity_flip_physical{158.0}=0x0 +phy_chain_rx_polarity_flip_physical{159.0}=0x1 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x1 +phy_chain_tx_polarity_flip_physical{159.0}=0x0 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 +#Port47 +#FC37 +portmap_73=149:100 +phy_chain_rx_lane_map_physical{149.0}=0x3120 +phy_chain_tx_lane_map_physical{149.0}=0x1023 +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x0 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 +phy_chain_tx_polarity_flip_physical{149.0}=0x1 +phy_chain_tx_polarity_flip_physical{150.0}=0x0 +phy_chain_tx_polarity_flip_physical{151.0}=0x0 +phy_chain_tx_polarity_flip_physical{152.0}=0x1 +#Port48 +#FC40 +portmap_76=161:100 +phy_chain_rx_lane_map_physical{161.0}=0x3012 +phy_chain_tx_lane_map_physical{161.0}=0x1023 +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x0 +phy_chain_tx_polarity_flip_physical{161.0}=0x0 +phy_chain_tx_polarity_flip_physical{162.0}=0x1 +phy_chain_tx_polarity_flip_physical{163.0}=0x0 +phy_chain_tx_polarity_flip_physical{164.0}=0x0 +#Port49 +#FC42 +portmap_78=169:100 +phy_chain_rx_lane_map_physical{169.0}=0x3210 +phy_chain_tx_lane_map_physical{169.0}=0x2031 +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x0 +phy_chain_tx_polarity_flip_physical{169.0}=0x1 +phy_chain_tx_polarity_flip_physical{170.0}=0x0 +phy_chain_tx_polarity_flip_physical{171.0}=0x0 +phy_chain_tx_polarity_flip_physical{172.0}=0x0 +#Port50 +#FC46 +portmap_82=185:100 +phy_chain_rx_lane_map_physical{185.0}=0x2310 +phy_chain_tx_lane_map_physical{185.0}=0x3021 +phy_chain_rx_polarity_flip_physical{185.0}=0x1 +phy_chain_rx_polarity_flip_physical{186.0}=0x0 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 +phy_chain_tx_polarity_flip_physical{185.0}=0x0 +phy_chain_tx_polarity_flip_physical{186.0}=0x1 +phy_chain_tx_polarity_flip_physical{187.0}=0x0 +phy_chain_tx_polarity_flip_physical{188.0}=0x0 +#Port51 +#FC44 +portmap_80=177:100 +phy_chain_rx_lane_map_physical{177.0}=0x1032 +phy_chain_tx_lane_map_physical{177.0}=0x2301 +phy_chain_rx_polarity_flip_physical{177.0}=0x1 +phy_chain_rx_polarity_flip_physical{178.0}=0x1 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x1 +phy_chain_tx_polarity_flip_physical{177.0}=0x1 +phy_chain_tx_polarity_flip_physical{178.0}=0x1 +phy_chain_tx_polarity_flip_physical{179.0}=0x1 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 +#Port52 +#FC6 +portmap_7=25:100 +phy_chain_rx_lane_map_physical{25.0}=0x3102 +phy_chain_tx_lane_map_physical{25.0}=0x0132 +phy_chain_rx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x1 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +#Port53 +#FC4 +portmap_5=17:100 +phy_chain_rx_lane_map_physical{17.0}=0x3120 +phy_chain_tx_lane_map_physical{17.0}=0x3021 +phy_chain_rx_polarity_flip_physical{17.0}=0x0 +phy_chain_rx_polarity_flip_physical{18.0}=0x1 +phy_chain_rx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_tx_polarity_flip_physical{18.0}=0x0 +phy_chain_tx_polarity_flip_physical{19.0}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x0 +#Port54 +#FC0 +portmap_1=1:100 +phy_chain_rx_lane_map_physical{1.0}=0x2130 +phy_chain_tx_lane_map_physical{1.0}=0x1203 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +#Port55 +#FC2 +portmap_3=9:100 +phy_chain_rx_lane_map_physical{9.0}=0x1203 +phy_chain_tx_lane_map_physical{9.0}=0x1230 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x1 +phy_chain_tx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 +#Port56 +#FC48 +portmap_102=193:100 +phy_chain_rx_lane_map_physical{193.0}=0x2103 +phy_chain_tx_lane_map_physical{193.0}=0x1230 +phy_chain_rx_polarity_flip_physical{193.0}=0x0 +phy_chain_rx_polarity_flip_physical{194.0}=0x1 +phy_chain_rx_polarity_flip_physical{195.0}=0x0 +phy_chain_rx_polarity_flip_physical{196.0}=0x1 +phy_chain_tx_polarity_flip_physical{193.0}=0x0 +phy_chain_tx_polarity_flip_physical{194.0}=0x0 +phy_chain_tx_polarity_flip_physical{195.0}=0x1 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 +#Port57 +#FC50 +portmap_104=201:100 +phy_chain_rx_lane_map_physical{201.0}=0x0321 +phy_chain_tx_lane_map_physical{201.0}=0x3021 +phy_chain_rx_polarity_flip_physical{201.0}=0x0 +phy_chain_rx_polarity_flip_physical{202.0}=0x0 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x0 +phy_chain_tx_polarity_flip_physical{201.0}=0x1 +phy_chain_tx_polarity_flip_physical{202.0}=0x1 +phy_chain_tx_polarity_flip_physical{203.0}=0x0 +phy_chain_tx_polarity_flip_physical{204.0}=0x1 +#Port58 +#FC54 +portmap_108=217:100 +phy_chain_rx_lane_map_physical{217.0}=0x1203 +phy_chain_tx_lane_map_physical{217.0}=0x2031 +phy_chain_rx_polarity_flip_physical{217.0}=0x1 +phy_chain_rx_polarity_flip_physical{218.0}=0x0 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{220.0}=0x1 +phy_chain_tx_polarity_flip_physical{217.0}=0x1 +phy_chain_tx_polarity_flip_physical{218.0}=0x0 +phy_chain_tx_polarity_flip_physical{219.0}=0x1 +phy_chain_tx_polarity_flip_physical{220.0}=0x0 +#Port59 +#FC52 +portmap_106=209:100 +phy_chain_rx_lane_map_physical{209.0}=0x0321 +phy_chain_tx_lane_map_physical{209.0}=0x3102 +phy_chain_rx_polarity_flip_physical{209.0}=0x0 +phy_chain_rx_polarity_flip_physical{210.0}=0x0 +phy_chain_rx_polarity_flip_physical{211.0}=0x1 +phy_chain_rx_polarity_flip_physical{212.0}=0x0 +phy_chain_tx_polarity_flip_physical{209.0}=0x0 +phy_chain_tx_polarity_flip_physical{210.0}=0x0 +phy_chain_tx_polarity_flip_physical{211.0}=0x1 +phy_chain_tx_polarity_flip_physical{212.0}=0x0 +#Port60 +#FC56 +portmap_110=225:100 +phy_chain_rx_lane_map_physical{225.0}=0x2103 +phy_chain_tx_lane_map_physical{225.0}=0x2031 +phy_chain_rx_polarity_flip_physical{225.0}=0x0 +phy_chain_rx_polarity_flip_physical{226.0}=0x0 +phy_chain_rx_polarity_flip_physical{227.0}=0x1 +phy_chain_rx_polarity_flip_physical{228.0}=0x1 +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x0 +phy_chain_tx_polarity_flip_physical{227.0}=0x1 +phy_chain_tx_polarity_flip_physical{228.0}=0x1 +#Port61 +#FC58 +portmap_112=233:100 +phy_chain_rx_lane_map_physical{233.0}=0x2130 +phy_chain_tx_lane_map_physical{233.0}=0x0312 +phy_chain_rx_polarity_flip_physical{233.0}=0x0 +phy_chain_rx_polarity_flip_physical{234.0}=0x1 +phy_chain_rx_polarity_flip_physical{235.0}=0x1 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x1 +phy_chain_tx_polarity_flip_physical{236.0}=0x0 +#Port62 +#FC62 +portmap_116=249:100 +phy_chain_rx_lane_map_physical{249.0}=0x1302 +phy_chain_tx_lane_map_physical{249.0}=0x1302 +phy_chain_rx_polarity_flip_physical{249.0}=0x0 +phy_chain_rx_polarity_flip_physical{250.0}=0x1 +phy_chain_rx_polarity_flip_physical{251.0}=0x0 +phy_chain_rx_polarity_flip_physical{252.0}=0x1 +phy_chain_tx_polarity_flip_physical{249.0}=0x1 +phy_chain_tx_polarity_flip_physical{250.0}=0x1 +phy_chain_tx_polarity_flip_physical{251.0}=0x1 +phy_chain_tx_polarity_flip_physical{252.0}=0x1 +#Port63 +#FC60 +portmap_114=241:100 +phy_chain_rx_lane_map_physical{241.0}=0x3012 +phy_chain_tx_lane_map_physical{241.0}=0x2301 +phy_chain_rx_polarity_flip_physical{241.0}=0x1 +phy_chain_rx_polarity_flip_physical{242.0}=0x1 +phy_chain_rx_polarity_flip_physical{243.0}=0x0 +phy_chain_rx_polarity_flip_physical{244.0}=0x1 +phy_chain_tx_polarity_flip_physical{241.0}=0x1 +phy_chain_tx_polarity_flip_physical{242.0}=0x0 +phy_chain_tx_polarity_flip_physical{243.0}=0x1 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 diff --git a/device/accton/x86_64-accton_as7816_64x-r0/default_sku b/device/accton/x86_64-accton_as7816_64x-r0/default_sku new file mode 100644 index 000000000000..31d29c2deb8d --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7816-64X t1 diff --git a/device/accton/x86_64-accton_as7816_64x-r0/installer.conf b/device/accton/x86_64-accton_as7816_64x-r0/installer.conf new file mode 100644 index 000000000000..9fa12f888545 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="tg3.short_preamble=1 tg3.bcm5718s_reset=1" diff --git a/device/accton/x86_64-accton_as7816_64x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7816_64x-r0/led_proc_init.soc new file mode 100755 index 000000000000..75a36c6f9c68 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/led_proc_init.soc @@ -0,0 +1,155 @@ +m CMIC_LEDUP0_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000 +m CMIC_LEDUP1_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000 +m CMIC_LEDUP2_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000 +m CMIC_LEDUP3_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000 + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=62 REMAP_PORT_2=61 REMAP_PORT_3=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=59 REMAP_PORT_5=58 REMAP_PORT_6=57 REMAP_PORT_7=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=55 REMAP_PORT_9=54 REMAP_PORT_10=53 REMAP_PORT_11=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=51 REMAP_PORT_13=50 REMAP_PORT_14=49 REMAP_PORT_15=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 REMAP_PORT_17=46 REMAP_PORT_18=45 REMAP_PORT_19=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 REMAP_PORT_21=42 REMAP_PORT_22=41 REMAP_PORT_23=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 REMAP_PORT_25=38 REMAP_PORT_26=37 REMAP_PORT_27=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 REMAP_PORT_29=34 REMAP_PORT_30=33 REMAP_PORT_31=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=31 REMAP_PORT_33=30 REMAP_PORT_34=29 REMAP_PORT_35=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=23 REMAP_PORT_41=22 REMAP_PORT_42=21 REMAP_PORT_43=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=19 REMAP_PORT_45=18 REMAP_PORT_46=17 REMAP_PORT_47=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=62 REMAP_PORT_2=61 REMAP_PORT_3=60 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=59 REMAP_PORT_5=58 REMAP_PORT_6=57 REMAP_PORT_7=56 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=55 REMAP_PORT_9=54 REMAP_PORT_10=53 REMAP_PORT_11=52 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=51 REMAP_PORT_13=50 REMAP_PORT_14=49 REMAP_PORT_15=48 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 REMAP_PORT_17=46 REMAP_PORT_18=45 REMAP_PORT_19=44 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 REMAP_PORT_21=42 REMAP_PORT_22=41 REMAP_PORT_23=40 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 REMAP_PORT_25=38 REMAP_PORT_26=37 REMAP_PORT_27=36 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 REMAP_PORT_29=34 REMAP_PORT_30=33 REMAP_PORT_31=32 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=31 REMAP_PORT_33=30 REMAP_PORT_34=29 REMAP_PORT_35=28 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=23 REMAP_PORT_41=22 REMAP_PORT_42=21 REMAP_PORT_43=20 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=19 REMAP_PORT_45=18 REMAP_PORT_46=17 REMAP_PORT_47=16 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 stop +led 0 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \ + 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +led 1 stop +led 1 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \ + 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +led 2 stop +led 2 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \ + 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +led 3 stop +led 3 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \ + 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +led auto on +led 0 start +led 1 start +led 2 start +led 3 start diff --git a/device/accton/x86_64-accton_as7816_64x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7816_64x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..1e7d1046d93d --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/plugins/eeprom.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7816_64x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7816_64x-r0/plugins/psuutil.py new file mode 100755 index 000000000000..707c7c897c82 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/plugins/psuutil.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "10-0053", + 2: "9-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7816_64x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7816_64x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..e0d3c46ab3ae --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/plugins/sfputil.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + _port_start = 0 + _port_end = 63 + ports_in_block = 64 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 61 : 25, + 62 : 26, + 63 : 27, + 64 : 28, + 55 : 29, + 56 : 30, + 53 : 31, + 54 : 32, + 9 : 33, + 10 : 34, + 11 : 35, + 12 : 36, + 1 : 37, + 2 : 38, + 3 : 39, + 4 : 40, + 6 : 41, + 5 : 42, + 8 : 43, + 7 : 44, + 13 : 45, + 14 : 46, + 15 : 47, + 16 : 48, + 17 : 49, + 18 : 50, + 19 : 51, + 20 : 52, + 25 : 53, + 26 : 54, + 27 : 55, + 28 : 56, + 29 : 57, + 30 : 58, + 31 : 59, + 32 : 60, + 21 : 61, + 22 : 62, + 23 : 63, + 24 : 64, + 41 : 65, + 42 : 66, + 43 : 67, + 44 : 68, + 33 : 69, + 34 : 70, + 35 : 71, + 36 : 72, + 45 : 73, + 46 : 74, + 47 : 75, + 48 : 76, + 37 : 77, + 38 : 78, + 39 : 79, + 40 : 80, + 57 : 81, + 58 : 82, + 59 : 83, + 60 : 84, + 49 : 85, + 50 : 86, + 51 : 87, + 52 : 88,} + + _qsfp_ports = range(0, ports_in_block + 1) + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom' + for x in range(0, self._port_end + 1): + port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x+1]) + self._port_to_eeprom_mapping[x] = port_eeprom_path + SfpUtilBase.__init__(self) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + path = "/sys/bus/i2c/devices/19-0060/module_reset_{0}" + port_ps = path.format(port_num+1) + + try: + reg_file = open(port_ps, 'w') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + #HW will clear reset after set. + reg_file.seek(0) + reg_file.write('1') + reg_file.close() + return True + + def set_low_power_mode(self, port_nuM, lpmode): + raise NotImplementedError + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present" + port_ps = path.format(self.port_to_i2c_mapping[port_num+1]) + + + try: + reg_file = open(port_ps) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return range(0, self.ports_in_block + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/port_config.ini b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/port_config.ini new file mode 100644 index 000000000000..745cc69428b4 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 33,34,35,36 Ethernet1/0/1 0 100000 +Ethernet4 37,38,39,40 Ethernet1/0/5 1 100000 +Ethernet8 41,42,43,44 Ethernet1/0/9 2 100000 +Ethernet12 45,46,47,48 Ethernet1/0/13 3 100000 +Ethernet16 49,50,51,52 Ethernet1/0/17 4 100000 +Ethernet20 53,54,55,56 Ethernet1/0/21 5 100000 +Ethernet24 57,58,59,60 Ethernet1/0/25 6 100000 +Ethernet28 61,62,63,64 Ethernet1/0/29 7 100000 +Ethernet32 65,66,67,68 Ethernet1/0/33 8 100000 +Ethernet36 69,70,71,72 Ethernet1/0/37 9 100000 +Ethernet40 73,74,75,76 Ethernet1/0/41 10 100000 +Ethernet44 77,78,79,80 Ethernet1/0/45 11 100000 +Ethernet48 81,82,83,84 Ethernet1/0/49 12 100000 +Ethernet52 85,86,87,88 Ethernet1/0/53 13 100000 +Ethernet56 89,90,91,92 Ethernet1/0/57 14 100000 +Ethernet60 93,94,95,96 Ethernet1/0/61 15 100000 +Ethernet64 97,98,99,100 Ethernet1/0/65 16 100000 +Ethernet68 101,102,103,104 Ethernet1/0/69 17 100000 +Ethernet72 105,106,107,108 Ethernet1/0/73 18 100000 +Ethernet76 109,110,111,112 Ethernet1/0/77 19 100000 +Ethernet80 113,114,115,116 Ethernet1/0/81 20 100000 +Ethernet84 117,118,119,120 Ethernet1/0/85 21 100000 +Ethernet88 121,122,123,124 Ethernet1/0/89 22 100000 +Ethernet92 125,126,127,128 Ethernet1/0/93 23 100000 +Ethernet96 1,2,3,4 Ethernet1/0/97 24 100000 +Ethernet100 5,6,7,8 Ethernet1/0/101 25 100000 +Ethernet104 9,10,11,12 Ethernet1/0/105 26 100000 +Ethernet108 13,14,15,16 Ethernet1/0/109 27 100000 +Ethernet112 17,18,19,20 Ethernet1/0/113 28 100000 +Ethernet116 21,22,23,24 Ethernet1/0/117 29 100000 +Ethernet120 25,26,27,28 Ethernet1/0/121 30 100000 +Ethernet124 29,30,31,32 Ethernet1/0/125 31 100000 \ No newline at end of file diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/sai.profile b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/sai.profile new file mode 100644 index 000000000000..b6e792ad0a18 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-snh60a0-32x100G.config.bcm diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/th-snh60a0-32x100G.config.bcm b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/th-snh60a0-32x100G.config.bcm new file mode 100644 index 000000000000..395827122e16 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/th-snh60a0-32x100G.config.bcm @@ -0,0 +1,163 @@ +# This property file is for ZION-320F 100G mode only. +# Zion-320F uses Tomahawk BCM56960 as its mac. Besides, it is phyless. +# Note: The settings in this file are not verified yet. + + + +# Set stat collection interval in microseconds. +# Setting this to 0 will prevent counters from being started. +bcm_stat_interval.0=1000000 + +# Linkscan interval in microseconds. +# If non-zero, bcm_init() will start linkscan +bcm_linkscan_interval.0=450000 + + + +# BCM56960 : MMU Cell Buffer Allocation Profile to support ASF (cut-thru) Forwarding +# 0: No cut-through support +# 1: Similar speed profile (Default) +# 2: Extreme speed profile + +os=unix + + + +# EagleCore ports +#portmap_66=129:10 +#portmap_100=131:10 + +# Loopback ports +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +#FalconCore[0 - 7] must map to logical port[1 - 32] +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_6=21:100 +portmap_7=25:100 +portmap_8=29:100 +#FalconCore[8 - 15] must map to logical port[34 - 65] +portmap_34=33:100 +portmap_35=37:100 +portmap_36=41:100 +portmap_37=45:100 +portmap_38=49:100 +portmap_39=53:100 +portmap_40=57:100 +portmap_41=61:100 +#FalconCore[16 - 23] must map to logical port[68 - 99] +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 +#FalconCore[24 - 31] must map to logical port[102 - 133] +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_106=113:100 +portmap_107=117:100 +portmap_108=121:100 +portmap_109=125:100 + +pbmp_xport_xe=0x3fd000000ff4000003fc000001fe +pbmp_oversubscribe=0x0000000000000000000000000000000000003fc000000ff0000003fc000001fe + + + +#core-0 +xgxs_rx_lane_map_ce0=0x3012 +xgxs_rx_lane_map_ce1=0x1230 +xgxs_rx_lane_map_ce2=0x3012 +xgxs_rx_lane_map_ce3=0x1230 +xgxs_rx_lane_map_ce4=0x1230 +xgxs_rx_lane_map_ce5=0x1230 +xgxs_rx_lane_map_ce6=0x1230 +xgxs_rx_lane_map_ce7=0x1230 + +#core-8 +xgxs_rx_lane_map_ce8=0x1032 +xgxs_rx_lane_map_ce9=0x1230 +xgxs_rx_lane_map_ce10=0x1032 +xgxs_rx_lane_map_ce11=0x1230 +xgxs_rx_lane_map_ce12=0x1230 +xgxs_rx_lane_map_ce13=0x3012 +xgxs_rx_lane_map_ce14=0x1230 +xgxs_rx_lane_map_ce15=0x3012 + +#core-16 +xgxs_rx_lane_map_ce16=0x3012 +xgxs_rx_lane_map_ce17=0x3012 +xgxs_rx_lane_map_ce18=0x1230 +xgxs_rx_lane_map_ce19=0x3012 +xgxs_rx_lane_map_ce20=0x3012 +xgxs_rx_lane_map_ce21=0x3012 +xgxs_rx_lane_map_ce22=0x3012 +xgxs_rx_lane_map_ce23=0x3012 + +#core-24 +xgxs_rx_lane_map_ce24=0x3210 +xgxs_rx_lane_map_ce25=0x3012 +xgxs_rx_lane_map_ce26=0x3210 +xgxs_rx_lane_map_ce27=0x3012 +xgxs_rx_lane_map_ce28=0x3012 +xgxs_rx_lane_map_ce29=0x1230 +xgxs_rx_lane_map_ce30=0x3012 +xgxs_rx_lane_map_ce31=0x3012 + +# +# Remap XGXS tx lanes to desired mapping by hardware provide. +#core-0 +xgxs_tx_lane_map_ce0=0x3210 +xgxs_tx_lane_map_ce1=0x1032 +xgxs_tx_lane_map_ce2=0x3210 +xgxs_tx_lane_map_ce3=0x1032 +xgxs_tx_lane_map_ce4=0x3210 +xgxs_tx_lane_map_ce5=0x3210 +xgxs_tx_lane_map_ce6=0x3210 +xgxs_tx_lane_map_ce7=0x1230 + +#core-8 +xgxs_tx_lane_map_ce8=0x2301 +xgxs_tx_lane_map_ce9=0x3210 +xgxs_tx_lane_map_ce10=0x2301 +xgxs_tx_lane_map_ce11=0x3210 +xgxs_tx_lane_map_ce12=0x0123 +xgxs_tx_lane_map_ce13=0x3210 +xgxs_tx_lane_map_ce14=0x0123 +xgxs_tx_lane_map_ce15=0x3210 + +#core-16 +xgxs_tx_lane_map_ce16=0x2301 +xgxs_tx_lane_map_ce17=0x3210 +xgxs_tx_lane_map_ce18=0x0123 +xgxs_tx_lane_map_ce19=0x1032 +xgxs_tx_lane_map_ce20=0x0123 +xgxs_tx_lane_map_ce21=0x1032 +xgxs_tx_lane_map_ce22=0x0123 +xgxs_tx_lane_map_ce23=0x1032 + +#core-24 +xgxs_tx_lane_map_ce24=0x1032 +xgxs_tx_lane_map_ce25=0x1032 +xgxs_tx_lane_map_ce26=0x1032 +xgxs_tx_lane_map_ce27=0x1032 +xgxs_tx_lane_map_ce28=0x1032 +xgxs_tx_lane_map_ce29=0x1032 +xgxs_tx_lane_map_ce30=0x3210 +xgxs_tx_lane_map_ce31=0x3210 + + + +ptp_ts_pll_fref=25000000 +ptp_bs_fref=25000000 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/default_sku b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/default_sku new file mode 100755 index 000000000000..588c4a951df7 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/default_sku @@ -0,0 +1 @@ +Alphanetworks-SNH60A0-320FV2 t1 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/fancontrol b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/fancontrol new file mode 100644 index 000000000000..24184113d2be --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +FCTEMPS=/sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/4-004d/hwmon/hwmon3/temp1_input +FCFANS=/sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan1_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan2_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan3_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan4_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan5_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan6_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan11_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan12_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan13_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan14_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan15_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan16_input +MINTEMP=/sys/bus/i2c/devices/0-005e/fan_pwm=50 +MAXTEMP=/sys/bus/i2c/devices/0-005e/fan_pwm=70 +MINSTART=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MINSTOP=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MINPWM=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MAXPWM=/sys/bus/i2c/devices/0-005e/fan_pwm=200 \ No newline at end of file diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/installer.conf b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/led_proc_init.soc b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/led_proc_init.soc new file mode 100644 index 000000000000..c05dbe3326f9 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/led_proc_init.soc @@ -0,0 +1,45 @@ +# LED microprocessor initialization for alphanetworks snh60a0-320fv2 + +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=15 REMAP_PORT_17=14 REMAP_PORT_18=13 REMAP_PORT_19=12 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 REMAP_PORT_21=10 REMAP_PORT_22=9 REMAP_PORT_23=8 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=7 REMAP_PORT_25=6 REMAP_PORT_26=5 REMAP_PORT_27=4 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=3 REMAP_PORT_29=2 REMAP_PORT_30=1 REMAP_PORT_31=0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=62 REMAP_PORT_34=61 REMAP_PORT_35=60 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=59 REMAP_PORT_37=58 REMAP_PORT_38=57 REMAP_PORT_39=56 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=55 REMAP_PORT_41=54 REMAP_PORT_42=53 REMAP_PORT_43=52 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=51 REMAP_PORT_45=50 REMAP_PORT_46=49 REMAP_PORT_47=48 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=47 REMAP_PORT_49=46 REMAP_PORT_50=45 REMAP_PORT_51=44 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=43 REMAP_PORT_53=42 REMAP_PORT_54=41 REMAP_PORT_55=40 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=39 REMAP_PORT_57=38 REMAP_PORT_58=37 REMAP_PORT_59=36 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=35 REMAP_PORT_61=34 REMAP_PORT_62=33 REMAP_PORT_63=32 + +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 stop +led 0 prog 2A 01 86 FF 06 FF C2 7F 60 FF 02 20 60 FE 67 2E 06 FE F2 04 60 FE D2 40 74 0E 70 1C 02 00 60 FE 67 2E 06 FE F2 04 60 FE D2 20 74 20 70 70 02 A0 F6 FE 04 D2 01 70 39 74 5F 06 FE 28 32 00 32 01 B7 97 71 46 75 4E 06 FF C2 04 74 4E 70 5F 67 76 67 72 67 76 67 76 67 76 67 76 67 76 67 76 57 67 76 67 76 67 76 67 76 67 76 67 76 67 76 67 76 57 3A 80 32 0E 87 57 32 0F 87 57 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 2A 01 86 FF 06 FF C2 7F 60 FF 02 00 60 FE 67 1C 06 FE F2 04 60 FE D2 40 74 0E 70 5E 02 A0 F6 FE 04 D2 01 70 27 74 4D 06 FE 28 32 00 32 01 B7 97 71 34 75 3C 06 FF C2 04 74 3C 70 4D 67 64 67 60 67 64 67 64 67 64 67 64 67 64 67 64 57 67 64 67 64 67 64 67 64 67 64 67 64 67 64 67 64 57 3A 80 32 0E 87 57 32 0F 87 57 +led 1 auto on +led 1 start diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/eeprom.py b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/eeprom.py new file mode 100644 index 000000000000..c0122e65844a --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0056/eeprom" + #Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/led_control.py b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/led_control.py new file mode 100644 index 000000000000..bab96d69dc47 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/led_control.py @@ -0,0 +1,255 @@ +#!/usr/bin/env python +# +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +# try: +# from sonic_led.led_control_base import LedControlBase +# import swsssdk +# except ImportError, e: +# raise ImportError (str(e) + " - required module not found") + +import time + +class LedControlBase(object): +# __metaclass__ = abc.ABCMeta + +# @abc.abstractmethod + def port_link_state_change(self, port, state): + """ + Called when port link state changes. Update port link state LED here. + + :param port: A string, SONiC port name (e.shg., "Ethernet0") + :param state: A string, the port link state (either "up" or "down") + """ + return + +### Zion specified ### +read_fan_fault = 0 +is_fan_all_OK = 0 +read_power_status = 0 +is_power_all_OK = 0 +is_thermal_high = 0 +is_reset_button_push = 0 +########################## + +def sysled_task(): + while True: + system_led_check() + time.sleep(5) + +### Zion specified ### +def system_led_check(): + global read_fan_fault, read_power_status, is_fan_all_OK, is_power_all_OK, is_thermal_high, is_reset_button_push + is_fan_all_OK = 1 + is_power_all_OK = 0 + is_thermal_high = 0 + is_reset_button_push = 0 + with open("/sys/bus/i2c/devices/1-005e/fan1_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan1_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan2_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan2_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan3_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan3_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan4_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan4_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan5_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan5_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan6_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan6_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + + + with open("/sys/bus/i2c/devices/1-005e/psu1_power_good", "r") as f1: + read_power_status = f1.read() + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f11: + if str(read_power_status) == str("1\n"): + f11.write("1") + else: + f11.write("4") + with open("/sys/bus/i2c/devices/1-005e/psu1_present", "r") as f1: + read_power_status = f1.read() + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f11: + if str(read_power_status) == str("1\n"): + is_power_all_OK = is_power_all_OK + 1 + f11.write("1") + else: + f11.write("4") + with open("/sys/bus/i2c/devices/1-005e/psu2_power_good", "r") as f1: + read_power_status = f1.read() + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f11: + if str(read_power_status) == str("1\n"): + f11.write("1") + else: + f11.write("4") + with open("/sys/bus/i2c/devices/1-005e/psu2_present", "r") as f1: + read_power_status = f1.read() + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f11: + if str(read_power_status) == str("1\n"): + is_power_all_OK = is_power_all_OK + 1 + f11.write("1") + else: + f11.write("4") + + + with open("/sys/bus/i2c/devices/9-005f/swi_ctrl", "r") as f5: + is_reset_button_push = f5.read() + if str(is_reset_button_push) == "1\n": + is_reset_button_push = 1 + else: + is_reset_button_push = 0 + + with open("/sys/bus/i2c/devices/4-004d/hwmon/hwmon3/temp1_input", "r") as f3: + is_thermal_high = f3.read() + if int(is_thermal_high) >= 70000: + is_thermal_high = 1 + else: + is_thermal_high = 0 + + with open("/sys/bus/i2c/devices/9-005f/sys_status", "w") as f2: + if is_reset_button_push == 1: + f2.write("3") + elif is_fan_all_OK == 0 or is_power_all_OK == 0 or is_thermal_high == 1: + f2.write("4") + else: + f2.write("1") + + return +########## + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + PORT_TABLE_PREFIX = "PORT_TABLE:" + + SONIC_PORT_NAME_PREFIX = "Ethernet" + + LED_SYSFS_PATH_BREAKOUT_CAPABLE = "/sys/class/leds/qsfp{0}_{1}/brightness" + LED_SYSFS_PATH_NO_BREAKOUT = "/sys/class/leds/qsfp{0}/brightness" + + QSFP_BREAKOUT_START_IDX = 1 + QSFP_BREAKOUT_END_IDX = 24 + QSFP_NO_BREAKOUT_START_IDX = 25 + QSFP_NO_BREAKOUT_END_IDX = 32 + + LED_COLOR_OFF = 0 + LED_COLOR_GREEN = 1 + LED_COLOR_YELLOW = 2 + + # Helper method to map SONiC port name to Arista QSFP index + def _port_name_to_qsfp_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + sonic_port_num = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + + swss = swsssdk.SonicV2Connector() + swss.connect(swss.APPL_DB) + + lanes = swss.get(swss.APPL_DB, self.PORT_TABLE_PREFIX + port_name, 'lanes') + + # SONiC port nums are 0-based and increment by 4 + # Arista QSFP indices are 1-based and increment by 1 + return (((sonic_port_num/4) + 1), sonic_port_num%4, len(lanes.split(','))) + + + # Concrete implementation of port_link_state_change() method + def port_link_state_change_bk(self, port, state): + qsfp_index, lane_index, lanes = self._port_name_to_qsfp_index(port) + + # Ignore invalid QSFP indices + if qsfp_index <= 0 or lanes <= 0 or lanes > 4: + return + + # QSFP indices 1-24 are breakout-capable and have four LEDs, and each LED indicate one lane. + # whereas indices 25-32 are not breakout-capable, and only have one + if qsfp_index <= self.QSFP_BREAKOUT_END_IDX: + # assuming 40G, then we need to control four lanes + led_sysfs_paths = [ self.LED_SYSFS_PATH_BREAKOUT_CAPABLE.format(qsfp_index, i) for i in range(lane_index + 1, lane_index + 1 + lanes) ] + else: + led_sysfs_paths = [ self.LED_SYSFS_PATH_NO_BREAKOUT.format(qsfp_index) ] + + for led_sysfs_path in led_sysfs_paths: + led_file = open(led_sysfs_path, "w") + + if state == "up": + led_file.write("%d" % self.LED_COLOR_GREEN) + else: + led_file.write("%d" % self.LED_COLOR_OFF) + + led_file.close() + + # Constructor + def __init__(self): + # Initialize all front-panel status LEDs to green + with open("/sys/bus/i2c/devices/9-005f/sys_locator", "w") as f: + f.write("0") + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/sys_status", "w") as f: + f.write("1") + + # Initialize all fan LEDs to green + with open("/sys/bus/i2c/devices/9-005f/fan1_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan2_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan3_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan4_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan5_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan6_led", "w") as f: + f.write("1") + sysled_task() + + # Initialize: Turn all front panel QSFP LEDs off + # # for qsfp_index in range(self.QSFP_BREAKOUT_START_IDX, self.QSFP_BREAKOUT_END_IDX + 1): + # # for lane in range(1, 5): + # # led_sysfs_path = self.LED_SYSFS_PATH_BREAKOUT_CAPABLE.format(qsfp_index, lane) + # # with open(led_sysfs_path, 'w') as led_file: + # # led_file.write("%d" % self.LED_COLOR_OFF) + + # # for qsfp_index in range(self.QSFP_NO_BREAKOUT_START_IDX, self.QSFP_NO_BREAKOUT_END_IDX + 1): + # # led_sysfs_path = self.LED_SYSFS_PATH_NO_BREAKOUT.format(qsfp_index) + # # with open(led_sysfs_path, 'w') as led_file: + # # led_file.write("%d" % self.LED_COLOR_OFF) diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/psuutil.py b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/psuutil.py new file mode 100644 index 000000000000..7a3b87f24d2d --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/psuutil.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +############################################################################# +# Alphanetworks +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = { + 1: "/psu1_present", + 2: "/psu2_present", + } + self.psu_oper_status = { + 1: "/psu1_power_good", + 2: "/psu2_power_good", + } + self.psu_mapping = "0-005e" + if not os.path.exists(self.psu_path+self.psu_mapping): + self.psu_mapping = "1-005e" + + def get_num_psus(self): + return len(self.psu_presence) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping+self.psu_oper_status[index] + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping + self.psu_presence[index] + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/sfputil.py b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/sfputil.py new file mode 100644 index 000000000000..9e502578f153 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/sfputil.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + first_port = 0 + last_port = 31 + port_num = 32 + + port_to_eeprom = {} + port_to_i2cbus_mapping = { + 1 : 14, + 2 : 15, + 3 : 16, + 4 : 17, + } + + eeprom_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_eeprom" + port_reset_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_port_reset" + present_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_is_present" + + _qsfp_ports = range(first_port, port_num + 1) + @property + def port_start(self): + return self.first_port + + @property + def port_end(self): + return self.last_port + + @property + def qsfp_ports(self): + return range(self.first_port, self.port_num + 1) + + @property + def port_to_eeprom_mapping(self): + return self.port_to_eeprom + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError + + def __init__(self): + path = self.eeprom_path + for x in range(self.first_port, self.last_port + 1): + index = (x % 8) + i2c_index = (x / 8) + 1 + self.port_to_eeprom[x] = path.format(self.port_to_i2cbus_mapping[i2c_index], (index + 1)) + SfpUtilBase.__init__(self) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + index = (port_num % 8) + i2c_index = (port_num / 8) + 1 + path = self.port_reset_path + port_path = path.format(self.port_to_i2cbus_mapping[i2c_index], (index + 1)) + + try: + reg_file = open(port_path, 'w') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # reset + reg_file.write('1') + + time.sleep(1) + + reg_file.write('0') + + reg_file.close() + return True + + def set_low_power_mode(self, port_nuM, lpmode): + raise NotImplementedError + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + index = (port_num % 8) + i2c_index = (port_num / 8) + 1 + path = self.present_path + port_path = path.format(self.port_to_i2cbus_mapping[i2c_index], (index + 1)) + + + try: + reg_file = open(port_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/sensors.conf b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/sensors.conf new file mode 100644 index 000000000000..90562c389f00 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/sensors.conf @@ -0,0 +1,17 @@ +# libsensors configuration file for snh60a0_320f +# ------------------------------------------------ + +bus "i2c-1" "SMBus I801 adapter at f000" +chip "goreme_power_cpld-*" + label fan1 "Fan tray 1 front" + label fan2 "Fan tray 2 front" + label fan3 "Fan tray 3 front" + label fan4 "Fan tray 4 front" + label fan5 "Fan tray 5 front" + label fan6 "Fan tray 6 front" + label fan11 "Fan tray 1 rear" + label fan12 "Fan tray 2 rear" + label fan13 "Fan tray 3 rear" + label fan14 "Fan tray 4 rear" + label fan15 "Fan tray 5 rear" + label fan16 "Fan tray 6 rear" diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/port_config.ini b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/port_config.ini new file mode 100644 index 000000000000..d365e18da78e --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/port_config.ini @@ -0,0 +1,67 @@ +# name lanes alias index speed +Ethernet0 5,6,7,8 Ethernet1/0/1 0 100000 +Ethernet4 9,10,11,12 Ethernet1/0/5 1 100000 +Ethernet8 13,14,15,16 Ethernet1/0/9 2 100000 +Ethernet12 1,2,3,4 Ethernet1/0/13 3 100000 +Ethernet16 21,22,23,24 Ethernet1/0/17 4 100000 +Ethernet20 25,26,27,28 Ethernet1/0/21 5 100000 +Ethernet24 29,30,31,32 Ethernet1/0/25 6 100000 +Ethernet28 17,18,19,20 Ethernet1/0/29 7 100000 +Ethernet32 37,38,39,40 Ethernet1/0/33 8 100000 +Ethernet36 41,42,43,44 Ethernet1/0/37 9 100000 +Ethernet40 45,46,47,48 Ethernet1/0/41 10 100000 +Ethernet44 33,34,35,36 Ethernet1/0/45 11 100000 +Ethernet48 53,54,55,56 Ethernet1/0/49 12 100000 +Ethernet52 57,58,59,60 Ethernet1/0/53 13 100000 +Ethernet56 61,62,63,64 Ethernet1/0/57 14 100000 +Ethernet60 49,50,51,52 Ethernet1/0/61 15 100000 +Ethernet64 69,70,71,72 Ethernet1/0/65 16 100000 +Ethernet68 73,74,75,76 Ethernet1/0/69 17 100000 +Ethernet72 77,78,79,80 Ethernet1/0/73 18 100000 +Ethernet76 65,66,67,68 Ethernet1/0/77 19 100000 +Ethernet80 85,86,87,88 Ethernet1/0/81 20 100000 +Ethernet84 89,90,91,92 Ethernet1/0/85 21 100000 +Ethernet88 93,94,95,96 Ethernet1/0/89 22 100000 +Ethernet92 81,82,83,84 Ethernet1/0/93 23 100000 +Ethernet96 101,102,103,104 Ethernet1/0/97 24 100000 +Ethernet100 105,106,107,108 Ethernet1/0/101 25 100000 +Ethernet104 109,110,111,112 Ethernet1/0/105 26 100000 +Ethernet108 97,98,99,100 Ethernet1/0/109 27 100000 +Ethernet112 117,118,119,120 Ethernet1/0/113 28 100000 +Ethernet116 121,122,123,124 Ethernet1/0/117 29 100000 +Ethernet120 125,126,127,128 Ethernet1/0/121 30 100000 +Ethernet124 113,114,115,116 Ethernet1/0/125 31 100000 +Ethernet128 133,134,135,136 Ethernet1/0/129 32 100000 +Ethernet132 137,138,139,140 Ethernet1/0/133 33 100000 +Ethernet136 141,142,143,144 Ethernet1/0/137 34 100000 +Ethernet140 129,130,131,132 Ethernet1/0/141 35 100000 +Ethernet144 149,150,151,152 Ethernet1/0/145 36 100000 +Ethernet148 153,154,155,156 Ethernet1/0/149 37 100000 +Ethernet152 157,158,159,160 Ethernet1/0/153 38 100000 +Ethernet156 145,146,147,148 Ethernet1/0/157 39 100000 +Ethernet160 165,166,167,168 Ethernet1/0/161 40 100000 +Ethernet164 169,170,171,172 Ethernet1/0/165 41 100000 +Ethernet168 173,174,175,176 Ethernet1/0/169 42 100000 +Ethernet172 161,162,163,164 Ethernet1/0/173 43 100000 +Ethernet176 181,182,183,184 Ethernet1/0/177 44 100000 +Ethernet180 185,186,187,188 Ethernet1/0/181 45 100000 +Ethernet184 189,190,191,192 Ethernet1/0/185 46 100000 +Ethernet188 177,178,179,180 Ethernet1/0/189 47 100000 +Ethernet192 197,198,199,200 Ethernet1/0/193 48 100000 +Ethernet196 201,202,203,204 Ethernet1/0/197 49 100000 +Ethernet200 205,206,207,208 Ethernet1/0/201 50 100000 +Ethernet204 193,194,195,196 Ethernet1/0/205 51 100000 +Ethernet208 213,214,215,216 Ethernet1/0/209 52 100000 +Ethernet212 217,218,219,220 Ethernet1/0/213 53 100000 +Ethernet216 221,222,223,224 Ethernet1/0/217 54 100000 +Ethernet220 209,210,211,212 Ethernet1/0/221 55 100000 +Ethernet224 229,230,231,232 Ethernet1/0/225 56 100000 +Ethernet228 233,234,235,236 Ethernet1/0/229 57 100000 +Ethernet232 237,238,239,240 Ethernet1/0/233 58 100000 +Ethernet236 225,226,227,228 Ethernet1/0/237 59 100000 +Ethernet240 245,246,247,248 Ethernet1/0/241 60 100000 +Ethernet244 249,250,251,252 Ethernet1/0/245 61 100000 +Ethernet248 253,254,255,256 Ethernet1/0/249 62 100000 +Ethernet252 241,242,243,244 Ethernet1/0/253 63 100000 +Ethernet256 257 Ethernet1/0/257 64 10000 +Ethernet260 259 Ethernet1/0/261 65 10000 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/sai.profile b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/sai.profile new file mode 100644 index 000000000000..04555733c028 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-snh60b0-64x100G.config.bcm diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/th2-snh60b0-64x100G.config.bcm b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/th2-snh60b0-64x100G.config.bcm new file mode 100644 index 000000000000..60ca5053b971 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/th2-snh60b0-64x100G.config.bcm @@ -0,0 +1,535 @@ +# This property file is for GOREME-2U 1x100G mode only. +# GOREME-2U uses Tomahawk2 BCM56970 as its mac. Besides, it is phyless. +# Note: The settings in this file are not verified yet. + +os=unix + +bcm_stat_interval.0=1000000 +bcm_linkscan_interval.0=250000 + +# Tuning MDIO_OUTPUT_DELAY as 0xf based on HW RD suggesstion and DVT result. +mdio_output_delay.0=0xf + +# Mode control to select L2 Table DMA mode aka L2MODE_POLL (0) or +# L2MOD_FIFO mechanism aka L2MODE_FIFO (1) for L2 table change notification. +l2xmsg_mode=1 + +# Memory table size configs +l2_mem_entries=40960 +l3_mem_entries=40960 + +portmap_66=257:10 +portmap_100=259:10 + +# Falcon core - front port +# FalconCore[0 - 15] must map to logical port[1-16], PIPE-0. +portmap_1=5:100 +portmap_2=9:100 +portmap_3=13:100 +portmap_4=1:100 +portmap_5=21:100 +portmap_6=25:100 +portmap_7=29:100 +portmap_8=17:100 +portmap_9=37:100 +portmap_10=41:100 +portmap_11=45:100 +portmap_12=33:100 +portmap_13=53:100 +portmap_14=57:100 +portmap_15=61:100 +portmap_16=49:100 + +# FalconCore[16 - 31] must map to logical port[34-49], PIPE-1. +portmap_34=69:100 +portmap_35=73:100 +portmap_36=77:100 +portmap_37=65:100 +portmap_38=85:100 +portmap_39=89:100 +portmap_40=93:100 +portmap_41=81:100 +portmap_42=101:100 +portmap_43=105:100 +portmap_44=109:100 +portmap_45=97:100 +portmap_46=117:100 +portmap_47=121:100 +portmap_48=125:100 +portmap_49=113:100 + +# FalconCore[32 - 47] must map to logical port[68-83], PIPE-2. +portmap_68=133:100 +portmap_69=137:100 +portmap_70=141:100 +portmap_71=129:100 +portmap_72=149:100 +portmap_73=153:100 +portmap_74=157:100 +portmap_75=145:100 +portmap_76=165:100 +portmap_77=169:100 +portmap_78=173:100 +portmap_79=161:100 +portmap_80=181:100 +portmap_81=185:100 +portmap_82=189:100 +portmap_83=177:100 + +# FalconCore[48 - 63] must map to logical port[102-117], PIPE-3. +portmap_102=197:100 +portmap_103=201:100 +portmap_104=205:100 +portmap_105=193:100 +portmap_106=213:100 +portmap_107=217:100 +portmap_108=221:100 +portmap_109=209:100 +portmap_110=229:100 +portmap_111=233:100 +portmap_112=237:100 +portmap_113=225:100 +portmap_114=245:100 +portmap_115=249:100 +portmap_116=253:100 +portmap_117=241:100 + +# Configure all front port as CE ports. +pbmp_xport_xe=0x00000000000000000000000000000000003fffd0000ffff40003fffc0001fffe + +# Oversubscription mode +# +# Refers to a switch being configured such that the I/O bandwidth is greater than the +# core bandwidth. +# BCM56970 device supports a maximum I/O bandwidth of 6,400 Gbps when the average packet size +# is greater than 250 bytes. +pbmp_oversubscribe=0x00000000000000000000000000000000003fffc0000ffff00003fffc0001fffe + + + +# core-0~7 +xgxs_rx_lane_map_ce0=0x0213 +xgxs_rx_lane_map_ce1=0x3102 +xgxs_rx_lane_map_ce2=0x1032 +xgxs_rx_lane_map_ce3=0x2103 +xgxs_rx_lane_map_ce4=0x0213 +xgxs_rx_lane_map_ce5=0x2103 +xgxs_rx_lane_map_ce6=0x1230 +xgxs_rx_lane_map_ce7=0x3120 + +# core-8~15 +xgxs_rx_lane_map_ce8=0x0123 +xgxs_rx_lane_map_ce9=0x3102 +xgxs_rx_lane_map_ce10=0x1230 +xgxs_rx_lane_map_ce11=0x0123 +xgxs_rx_lane_map_ce12=0x0123 +xgxs_rx_lane_map_ce13=0X1230 +xgxs_rx_lane_map_ce14=0x1230 +xgxs_rx_lane_map_ce15=0x0123 + +# core-16~23 +xgxs_rx_lane_map_ce16=0x0123 +xgxs_rx_lane_map_ce17=0x1230 +xgxs_rx_lane_map_ce18=0x1230 +xgxs_rx_lane_map_ce19=0x0123 +xgxs_rx_lane_map_ce20=0x0123 +xgxs_rx_lane_map_ce21=0x1230 +xgxs_rx_lane_map_ce22=0x1230 +xgxs_rx_lane_map_ce23=0x0123 + +# core-24~31 +xgxs_rx_lane_map_ce24=0x0123 +xgxs_rx_lane_map_ce25=0x0231 +xgxs_rx_lane_map_ce26=0x2130 +xgxs_rx_lane_map_ce27=0x2103 +xgxs_rx_lane_map_ce28=0x3012 +xgxs_rx_lane_map_ce29=0x3102 +xgxs_rx_lane_map_ce30=0x1032 +xgxs_rx_lane_map_ce31=0x2103 + +# core-32~39 +xgxs_rx_lane_map_ce32=0x3102 +xgxs_rx_lane_map_ce33=0x3102 +xgxs_rx_lane_map_ce34=0x0132 +xgxs_rx_lane_map_ce35=0x3021 +xgxs_rx_lane_map_ce36=0x0213 +xgxs_rx_lane_map_ce37=0x3012 +xgxs_rx_lane_map_ce38=0x2130 +xgxs_rx_lane_map_ce39=0x0123 + +# core-40~47 +xgxs_rx_lane_map_ce40=0x0312 +xgxs_rx_lane_map_ce41=0x0132 +xgxs_rx_lane_map_ce42=0x1230 +xgxs_rx_lane_map_ce43=0x0123 +xgxs_rx_lane_map_ce44=0x0312 +xgxs_rx_lane_map_ce45=0x0132 +xgxs_rx_lane_map_ce46=0x1230 +xgxs_rx_lane_map_ce47=0x0123 + +# core-48~55 +xgxs_rx_lane_map_ce48=0x0123 +xgxs_rx_lane_map_ce49=0x0132 +xgxs_rx_lane_map_ce50=0x1230 +xgxs_rx_lane_map_ce51=0x0123 +xgxs_rx_lane_map_ce52=0x0312 +xgxs_rx_lane_map_ce53=0x0132 +xgxs_rx_lane_map_ce54=0x1230 +xgxs_rx_lane_map_ce55=0x0123 + +# core-56~63 +xgxs_rx_lane_map_ce56=0x0123 +xgxs_rx_lane_map_ce57=0x0312 +xgxs_rx_lane_map_ce58=0x1032 +xgxs_rx_lane_map_ce59=0x2103 +xgxs_rx_lane_map_ce60=0x2103 +xgxs_rx_lane_map_ce61=0x3120 +xgxs_rx_lane_map_ce62=0x1032 +xgxs_rx_lane_map_ce63=0x0213 + +# Remap XGXS tx lanes to desired mapping by hardware provide. +#core-0~7 +xgxs_tx_lane_map_ce0=0x2301 +xgxs_tx_lane_map_ce1=0x2301 +xgxs_tx_lane_map_ce2=0x1302 +xgxs_tx_lane_map_ce3=0x3210 +xgxs_tx_lane_map_ce4=0x2301 +xgxs_tx_lane_map_ce5=0x2301 +xgxs_tx_lane_map_ce6=0x0213 +xgxs_tx_lane_map_ce7=0x3210 + +#core-8~15 +xgxs_tx_lane_map_ce8=0x1230 +xgxs_tx_lane_map_ce9=0x2301 +xgxs_tx_lane_map_ce10=0x0231 +xgxs_tx_lane_map_ce11=0x1230 +xgxs_tx_lane_map_ce12=0x3102 +xgxs_tx_lane_map_ce13=0x2301 +xgxs_tx_lane_map_ce14=0x0231 +xgxs_tx_lane_map_ce15=0x1230 + +#core-16~23 +xgxs_tx_lane_map_ce16=0x3102 +xgxs_tx_lane_map_ce17=0x2301 +xgxs_tx_lane_map_ce18=0x0231 +xgxs_tx_lane_map_ce19=0x1230 +xgxs_tx_lane_map_ce20=0x3102 +xgxs_tx_lane_map_ce21=0x2301 +xgxs_tx_lane_map_ce22=0x0231 +xgxs_tx_lane_map_ce23=0x1230 + +#core-24~31 +xgxs_tx_lane_map_ce24=0x3102 +xgxs_tx_lane_map_ce25=0x2301 +xgxs_tx_lane_map_ce26=0x0321 +xgxs_tx_lane_map_ce27=0x3210 +xgxs_tx_lane_map_ce28=0x1302 +xgxs_tx_lane_map_ce29=0x2031 +xgxs_tx_lane_map_ce30=0x3120 +xgxs_tx_lane_map_ce31=0x3210 + +#core-32~39 +xgxs_tx_lane_map_ce32=0x2310 +xgxs_tx_lane_map_ce33=0x2301 +xgxs_tx_lane_map_ce34=0x1203 +xgxs_tx_lane_map_ce35=0x1032 +xgxs_tx_lane_map_ce36=0x2130 +xgxs_tx_lane_map_ce37=0x2301 +xgxs_tx_lane_map_ce38=0x1302 +xgxs_tx_lane_map_ce39=0x3210 + +#core-40~47 +xgxs_tx_lane_map_ce40=0x3201 +xgxs_tx_lane_map_ce41=0x0231 +xgxs_tx_lane_map_ce42=0x1203 +xgxs_tx_lane_map_ce43=0x1230 +xgxs_tx_lane_map_ce44=0x3201 +xgxs_tx_lane_map_ce45=0x0231 +xgxs_tx_lane_map_ce46=0x1203 +xgxs_tx_lane_map_ce47=0x3210 + +#core-48~55 +xgxs_tx_lane_map_ce48=0x3201 +xgxs_tx_lane_map_ce49=0x0231 +xgxs_tx_lane_map_ce50=0x1203 +xgxs_tx_lane_map_ce51=0x3210 +xgxs_tx_lane_map_ce52=0x3201 +xgxs_tx_lane_map_ce53=0x0231 +xgxs_tx_lane_map_ce54=0x1203 +xgxs_tx_lane_map_ce55=0x3210 + +#core-56~63 +xgxs_tx_lane_map_ce56=0x1203 +xgxs_tx_lane_map_ce57=0x2301 +xgxs_tx_lane_map_ce58=0x0213 +xgxs_tx_lane_map_ce59=0x3210 +xgxs_tx_lane_map_ce60=0x0213 +xgxs_tx_lane_map_ce61=0x3021 +xgxs_tx_lane_map_ce62=0x3210 +xgxs_tx_lane_map_ce63=0x3210 + +serdes_preemphasis_lane0_ce0=0x0c5800 +serdes_preemphasis_lane1_ce0=0x0c5800 +serdes_preemphasis_lane2_ce0=0x0c5800 +serdes_preemphasis_lane3_ce0=0x0c5800 +serdes_preemphasis_lane0_ce1=0x0c5800 +serdes_preemphasis_lane1_ce1=0x0c5800 +serdes_preemphasis_lane2_ce1=0x0c5800 +serdes_preemphasis_lane3_ce1=0x0c5800 +serdes_preemphasis_lane0_ce2=0x0c5800 +serdes_preemphasis_lane1_ce2=0x0c5800 +serdes_preemphasis_lane2_ce2=0x0c5800 +serdes_preemphasis_lane3_ce2=0x0c5800 +serdes_preemphasis_lane0_ce3=0x0c5800 +serdes_preemphasis_lane1_ce3=0x0c5800 +serdes_preemphasis_lane2_ce3=0x0c5800 +serdes_preemphasis_lane3_ce3=0x0c5800 +serdes_preemphasis_lane0_ce4=0x0c5800 +serdes_preemphasis_lane1_ce4=0x0c5800 +serdes_preemphasis_lane2_ce4=0x0c5800 +serdes_preemphasis_lane3_ce4=0x0c5800 +serdes_preemphasis_lane0_ce5=0x0c5800 +serdes_preemphasis_lane1_ce5=0x0c5800 +serdes_preemphasis_lane2_ce5=0x0c5800 +serdes_preemphasis_lane3_ce5=0x0c5800 +serdes_preemphasis_lane0_ce6=0x0c5800 +serdes_preemphasis_lane1_ce6=0x0c5800 +serdes_preemphasis_lane2_ce6=0x0c5800 +serdes_preemphasis_lane3_ce6=0x0c5800 +serdes_preemphasis_lane0_ce7=0x0c5800 +serdes_preemphasis_lane1_ce7=0x0c5800 +serdes_preemphasis_lane2_ce7=0x0c5800 +serdes_preemphasis_lane3_ce7=0x0c5800 +serdes_preemphasis_lane0_ce8=0x0c5800 +serdes_preemphasis_lane1_ce8=0x0c5800 +serdes_preemphasis_lane2_ce8=0x0c5800 +serdes_preemphasis_lane3_ce8=0x0c5800 +serdes_preemphasis_lane0_ce9=0x0c5800 +serdes_preemphasis_lane1_ce9=0x0c5800 +serdes_preemphasis_lane2_ce9=0x0c5800 +serdes_preemphasis_lane3_ce9=0x0c5800 +serdes_preemphasis_lane0_ce10=0x0c5800 +serdes_preemphasis_lane1_ce10=0x0c5800 +serdes_preemphasis_lane2_ce10=0x0c5800 +serdes_preemphasis_lane3_ce10=0x0c5800 +serdes_preemphasis_lane0_ce11=0x0c5800 +serdes_preemphasis_lane1_ce11=0x0c5800 +serdes_preemphasis_lane2_ce11=0x0c5800 +serdes_preemphasis_lane3_ce11=0x0c5800 +serdes_preemphasis_lane0_ce12=0x0c5800 +serdes_preemphasis_lane1_ce12=0x0c5800 +serdes_preemphasis_lane2_ce12=0x0c5800 +serdes_preemphasis_lane3_ce12=0x0c5800 +serdes_preemphasis_lane0_ce13=0x0c5800 +serdes_preemphasis_lane1_ce13=0x0c5800 +serdes_preemphasis_lane2_ce13=0x0c5800 +serdes_preemphasis_lane3_ce13=0x0c5800 +serdes_preemphasis_lane0_ce14=0x0c5800 +serdes_preemphasis_lane1_ce14=0x0c5800 +serdes_preemphasis_lane2_ce14=0x0c5800 +serdes_preemphasis_lane3_ce14=0x0c5800 +serdes_preemphasis_lane0_ce15=0x0c5800 +serdes_preemphasis_lane1_ce15=0x0c5800 +serdes_preemphasis_lane2_ce15=0x0c5800 +serdes_preemphasis_lane3_ce15=0x0c5800 +serdes_preemphasis_lane0_ce16=0x085408 +serdes_preemphasis_lane1_ce16=0x085408 +serdes_preemphasis_lane2_ce16=0x085408 +serdes_preemphasis_lane3_ce16=0x085408 +serdes_preemphasis_lane0_ce17=0x085408 +serdes_preemphasis_lane1_ce17=0x085408 +serdes_preemphasis_lane2_ce17=0x085408 +serdes_preemphasis_lane3_ce17=0x085408 +serdes_preemphasis_lane0_ce18=0x085408 +serdes_preemphasis_lane1_ce18=0x085408 +serdes_preemphasis_lane2_ce18=0x085408 +serdes_preemphasis_lane3_ce18=0x085408 +serdes_preemphasis_lane0_ce19=0x085408 +serdes_preemphasis_lane1_ce19=0x085408 +serdes_preemphasis_lane2_ce19=0x085408 +serdes_preemphasis_lane3_ce19=0x085408 +serdes_preemphasis_lane0_ce20=0x085408 +serdes_preemphasis_lane1_ce20=0x085408 +serdes_preemphasis_lane2_ce20=0x085408 +serdes_preemphasis_lane3_ce20=0x085408 +serdes_preemphasis_lane0_ce21=0x085408 +serdes_preemphasis_lane1_ce21=0x085408 +serdes_preemphasis_lane2_ce21=0x085408 +serdes_preemphasis_lane3_ce21=0x085408 +serdes_preemphasis_lane0_ce22=0x085408 +serdes_preemphasis_lane1_ce22=0x085408 +serdes_preemphasis_lane2_ce22=0x085408 +serdes_preemphasis_lane3_ce22=0x085408 +serdes_preemphasis_lane0_ce23=0x085408 +serdes_preemphasis_lane1_ce23=0x085408 +serdes_preemphasis_lane2_ce23=0x085408 +serdes_preemphasis_lane3_ce23=0x085408 +serdes_preemphasis_lane0_ce24=0x085408 +serdes_preemphasis_lane1_ce24=0x085408 +serdes_preemphasis_lane2_ce24=0x085408 +serdes_preemphasis_lane3_ce24=0x085408 +serdes_preemphasis_lane0_ce25=0x085408 +serdes_preemphasis_lane1_ce25=0x085408 +serdes_preemphasis_lane2_ce25=0x085408 +serdes_preemphasis_lane3_ce25=0x085408 +serdes_preemphasis_lane0_ce26=0x0a500a +serdes_preemphasis_lane1_ce26=0x0a500a +serdes_preemphasis_lane2_ce26=0x0a500a +serdes_preemphasis_lane3_ce26=0x0a500a +serdes_preemphasis_lane0_ce27=0x0a500a +serdes_preemphasis_lane1_ce27=0x0a500a +serdes_preemphasis_lane2_ce27=0x0a500a +serdes_preemphasis_lane3_ce27=0x0a500a +serdes_preemphasis_lane0_ce28=0x0a500a +serdes_preemphasis_lane1_ce28=0x0a500a +serdes_preemphasis_lane2_ce28=0x0a500a +serdes_preemphasis_lane3_ce28=0x0a500a +serdes_preemphasis_lane0_ce29=0x0a500a +serdes_preemphasis_lane1_ce29=0x0a500a +serdes_preemphasis_lane2_ce29=0x0a500a +serdes_preemphasis_lane3_ce29=0x0a500a +serdes_preemphasis_lane0_ce30=0x0a500a +serdes_preemphasis_lane1_ce30=0x0a500a +serdes_preemphasis_lane2_ce30=0x0a500a +serdes_preemphasis_lane3_ce30=0x0a500a +serdes_preemphasis_lane0_ce31=0x0a500a +serdes_preemphasis_lane1_ce31=0x0a500a +serdes_preemphasis_lane2_ce31=0x0a500a +serdes_preemphasis_lane3_ce31=0x0a500a +serdes_preemphasis_lane0_ce32=0x0a500a +serdes_preemphasis_lane1_ce32=0x0a500a +serdes_preemphasis_lane2_ce32=0x0a500a +serdes_preemphasis_lane3_ce32=0x0a500a +serdes_preemphasis_lane0_ce33=0x0a500a +serdes_preemphasis_lane1_ce33=0x0a500a +serdes_preemphasis_lane2_ce33=0x0a500a +serdes_preemphasis_lane3_ce33=0x0a500a +serdes_preemphasis_lane0_ce34=0x0a500a +serdes_preemphasis_lane1_ce34=0x0a500a +serdes_preemphasis_lane2_ce34=0x0a500a +serdes_preemphasis_lane3_ce34=0x0a500a +serdes_preemphasis_lane0_ce35=0x0a500a +serdes_preemphasis_lane1_ce35=0x0a500a +serdes_preemphasis_lane2_ce35=0x0a500a +serdes_preemphasis_lane3_ce35=0x0a500a +serdes_preemphasis_lane0_ce36=0x0a500a +serdes_preemphasis_lane1_ce36=0x0a500a +serdes_preemphasis_lane2_ce36=0x0a500a +serdes_preemphasis_lane3_ce36=0x0a500a +serdes_preemphasis_lane0_ce37=0x0a500a +serdes_preemphasis_lane1_ce37=0x0a500a +serdes_preemphasis_lane2_ce37=0x0a500a +serdes_preemphasis_lane3_ce37=0x0a500a +serdes_preemphasis_lane0_ce38=0x0a500a +serdes_preemphasis_lane1_ce38=0x0a500a +serdes_preemphasis_lane2_ce38=0x0a500a +serdes_preemphasis_lane3_ce38=0x0a500a +serdes_preemphasis_lane0_ce39=0x0a500a +serdes_preemphasis_lane1_ce39=0x0a500a +serdes_preemphasis_lane2_ce39=0x0a500a +serdes_preemphasis_lane3_ce39=0x0a500a +serdes_preemphasis_lane0_ce40=0x085408 +serdes_preemphasis_lane1_ce40=0x085408 +serdes_preemphasis_lane2_ce40=0x085408 +serdes_preemphasis_lane3_ce40=0x085408 +serdes_preemphasis_lane0_ce41=0x085408 +serdes_preemphasis_lane1_ce41=0x085408 +serdes_preemphasis_lane2_ce41=0x085408 +serdes_preemphasis_lane3_ce41=0x085408 +serdes_preemphasis_lane0_ce42=0x085408 +serdes_preemphasis_lane1_ce42=0x085408 +serdes_preemphasis_lane2_ce42=0x085408 +serdes_preemphasis_lane3_ce42=0x085408 +serdes_preemphasis_lane0_ce43=0x085408 +serdes_preemphasis_lane1_ce43=0x085408 +serdes_preemphasis_lane2_ce43=0x085408 +serdes_preemphasis_lane3_ce43=0x085408 +serdes_preemphasis_lane0_ce44=0x085408 +serdes_preemphasis_lane1_ce44=0x085408 +serdes_preemphasis_lane2_ce44=0x085408 +serdes_preemphasis_lane3_ce44=0x085408 +serdes_preemphasis_lane0_ce45=0x085408 +serdes_preemphasis_lane1_ce45=0x085408 +serdes_preemphasis_lane2_ce45=0x085408 +serdes_preemphasis_lane3_ce45=0x085408 +serdes_preemphasis_lane0_ce46=0x085408 +serdes_preemphasis_lane1_ce46=0x085408 +serdes_preemphasis_lane2_ce46=0x085408 +serdes_preemphasis_lane3_ce46=0x085408 +serdes_preemphasis_lane0_ce47=0x085408 +serdes_preemphasis_lane1_ce47=0x085408 +serdes_preemphasis_lane2_ce47=0x085408 +serdes_preemphasis_lane3_ce47=0x085408 +serdes_preemphasis_lane0_ce48=0x085408 +serdes_preemphasis_lane1_ce48=0x085408 +serdes_preemphasis_lane2_ce48=0x085408 +serdes_preemphasis_lane3_ce48=0x085408 +serdes_preemphasis_lane0_ce49=0x085408 +serdes_preemphasis_lane1_ce49=0x085408 +serdes_preemphasis_lane2_ce49=0x085408 +serdes_preemphasis_lane3_ce49=0x085408 +serdes_preemphasis_lane0_ce50=0x085408 +serdes_preemphasis_lane1_ce50=0x085408 +serdes_preemphasis_lane2_ce50=0x085408 +serdes_preemphasis_lane3_ce50=0x085408 +serdes_preemphasis_lane0_ce51=0x085408 +serdes_preemphasis_lane1_ce51=0x085408 +serdes_preemphasis_lane2_ce51=0x085408 +serdes_preemphasis_lane3_ce51=0x085408 +serdes_preemphasis_lane0_ce52=0x085408 +serdes_preemphasis_lane1_ce52=0x085408 +serdes_preemphasis_lane2_ce52=0x085408 +serdes_preemphasis_lane3_ce52=0x085408 +serdes_preemphasis_lane0_ce53=0x085408 +serdes_preemphasis_lane1_ce53=0x085408 +serdes_preemphasis_lane2_ce53=0x085408 +serdes_preemphasis_lane3_ce53=0x085408 +serdes_preemphasis_lane0_ce54=0x085408 +serdes_preemphasis_lane1_ce54=0x085408 +serdes_preemphasis_lane2_ce54=0x085408 +serdes_preemphasis_lane3_ce54=0x085408 +serdes_preemphasis_lane0_ce55=0x085408 +serdes_preemphasis_lane1_ce55=0x085408 +serdes_preemphasis_lane2_ce55=0x085408 +serdes_preemphasis_lane3_ce55=0x085408 +serdes_preemphasis_lane0_ce56=0x0c5800 +serdes_preemphasis_lane1_ce56=0x0c5800 +serdes_preemphasis_lane2_ce56=0x0c5800 +serdes_preemphasis_lane3_ce56=0x0c5800 +serdes_preemphasis_lane0_ce57=0x0c5800 +serdes_preemphasis_lane1_ce57=0x0c5800 +serdes_preemphasis_lane2_ce57=0x0c5800 +serdes_preemphasis_lane3_ce57=0x0c5800 +serdes_preemphasis_lane0_ce58=0x0c5800 +serdes_preemphasis_lane1_ce58=0x0c5800 +serdes_preemphasis_lane2_ce58=0x0c5800 +serdes_preemphasis_lane3_ce58=0x0c5800 +serdes_preemphasis_lane0_ce59=0x0c5800 +serdes_preemphasis_lane1_ce59=0x0c5800 +serdes_preemphasis_lane2_ce59=0x0c5800 +serdes_preemphasis_lane3_ce59=0x0c5800 +serdes_preemphasis_lane0_ce60=0x0c5800 +serdes_preemphasis_lane1_ce60=0x0c5800 +serdes_preemphasis_lane2_ce60=0x0c5800 +serdes_preemphasis_lane3_ce60=0x0c5800 +serdes_preemphasis_lane0_ce61=0x0c5800 +serdes_preemphasis_lane1_ce61=0x0c5800 +serdes_preemphasis_lane2_ce61=0x0c5800 +serdes_preemphasis_lane3_ce61=0x0c5800 +serdes_preemphasis_lane0_ce62=0x0c5800 +serdes_preemphasis_lane1_ce62=0x0c5800 +serdes_preemphasis_lane2_ce62=0x0c5800 +serdes_preemphasis_lane3_ce62=0x0c5800 +serdes_preemphasis_lane0_ce63=0x0c5800 +serdes_preemphasis_lane1_ce63=0x0c5800 +serdes_preemphasis_lane2_ce63=0x0c5800 +serdes_preemphasis_lane3_ce63=0x0c5800 + +# # The TX and RX polarity flip variable. +# # It is affected by lane swapping, we used to debug for TE QSFP28 transceiver. +# # + +# # Used to select the reference clock for Timestamping and BroadSync/10Mhz PLL value. +# # 25MHz LVPECL to BS_PLL0_REFCLK, BS_PLL1_REFCLK, and TS_PLL_REFCLK +# ptp_ts_pll_fref=25000000 +# ptp_bs_fref=25000000 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/default_sku b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/default_sku new file mode 100755 index 000000000000..e262bc70c380 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/default_sku @@ -0,0 +1 @@ +Alphanetworks-SNH60B0-640F t1 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/fancontrol b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/fancontrol new file mode 100644 index 000000000000..9d443b3d3e61 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +FCTEMPS=/sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/3-004d/hwmon/hwmon2/temp1_input +FCFANS=/sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan1_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan2_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan3_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan4_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan11_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan12_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan13_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan14_input +MINTEMP=/sys/bus/i2c/devices/0-005e/fan_pwm=50 +MAXTEMP=/sys/bus/i2c/devices/0-005e/fan_pwm=70 +MINSTART=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MINSTOP=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MINPWM=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MAXPWM=/sys/bus/i2c/devices/0-005e/fan_pwm=200 \ No newline at end of file diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/installer.conf b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/led_proc_init.soc b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/led_proc_init.soc new file mode 100644 index 000000000000..3fa944a9faba --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/led_proc_init.soc @@ -0,0 +1,111 @@ +# LED microprocessor initialization for alphanetworks snh60b0-640f + +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=0x3f REMAP_PORT_1=0x3e REMAP_PORT_2=0x3d REMAP_PORT_3=0x3c +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=0x3b REMAP_PORT_5=0x3a REMAP_PORT_6=0x39 REMAP_PORT_7=0x38 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0x37 REMAP_PORT_9=0x36 REMAP_PORT_10=0x35 REMAP_PORT_11=0x34 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0x33 REMAP_PORT_13=0x32 REMAP_PORT_14=0x31 REMAP_PORT_15=0x30 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x2f REMAP_PORT_17=0x2e REMAP_PORT_18=0x2d REMAP_PORT_19=0x2c +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x2b REMAP_PORT_21=0x2a REMAP_PORT_22=0x29 REMAP_PORT_23=0x28 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x27 REMAP_PORT_25=0x26 REMAP_PORT_26=0x25 REMAP_PORT_27=0x24 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x23 REMAP_PORT_29=0x22 REMAP_PORT_30=0x21 REMAP_PORT_31=0x20 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x1f REMAP_PORT_33=0x1e REMAP_PORT_34=0x1d REMAP_PORT_35=0x1c +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x1b REMAP_PORT_37=0x1a REMAP_PORT_38=0x19 REMAP_PORT_39=0x18 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x17 REMAP_PORT_41=0x16 REMAP_PORT_42=0x15 REMAP_PORT_43=0x14 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x13 REMAP_PORT_45=0x12 REMAP_PORT_46=0x11 REMAP_PORT_47=0x10 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0xf REMAP_PORT_49=0xe REMAP_PORT_50=0xd REMAP_PORT_51=0xc +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0xb REMAP_PORT_53=0xa REMAP_PORT_54=9 REMAP_PORT_55=8 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0xb REMAP_PORT_9=0xa REMAP_PORT_10=9 REMAP_PORT_11=8 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0xf REMAP_PORT_13=0xe REMAP_PORT_14=0xd REMAP_PORT_15=0xc +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x13 REMAP_PORT_17=0x12 REMAP_PORT_18=0x11 REMAP_PORT_19=0x10 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x17 REMAP_PORT_21=0x16 REMAP_PORT_22=0x15 REMAP_PORT_23=0x14 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x1b REMAP_PORT_25=0x1a REMAP_PORT_26=0x19 REMAP_PORT_27=0x18 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x1f REMAP_PORT_29=0x1e REMAP_PORT_30=0x1d REMAP_PORT_31=0x1c +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x23 REMAP_PORT_33=0x22 REMAP_PORT_34=0x21 REMAP_PORT_35=0x20 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x27 REMAP_PORT_37=0x26 REMAP_PORT_38=0x25 REMAP_PORT_39=0x24 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x2b REMAP_PORT_41=0x2a REMAP_PORT_42=0x29 REMAP_PORT_43=0x28 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x2f REMAP_PORT_45=0x2e REMAP_PORT_46=0x2d REMAP_PORT_47=0x2c +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0x33 REMAP_PORT_49=0x32 REMAP_PORT_50=0x31 REMAP_PORT_51=0x30 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0x37 REMAP_PORT_53=0x36 REMAP_PORT_54=0x35 REMAP_PORT_55=0x34 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=0x3b REMAP_PORT_57=0x3a REMAP_PORT_58=0x39 REMAP_PORT_59=0x38 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=0x3f REMAP_PORT_61=0x3e REMAP_PORT_62=0x3d REMAP_PORT_63=0x3c + +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=0x3f REMAP_PORT_1=0x3e REMAP_PORT_2=0x3d REMAP_PORT_3=0x3c +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=0x3b REMAP_PORT_5=0x3a REMAP_PORT_6=0x39 REMAP_PORT_7=0x38 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0x37 REMAP_PORT_9=0x36 REMAP_PORT_10=0x35 REMAP_PORT_11=0x34 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0x33 REMAP_PORT_13=0x32 REMAP_PORT_14=0x31 REMAP_PORT_15=0x30 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x2f REMAP_PORT_17=0x2e REMAP_PORT_18=0x2d REMAP_PORT_19=0x2c +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x2b REMAP_PORT_21=0x2a REMAP_PORT_22=0x29 REMAP_PORT_23=0x28 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x27 REMAP_PORT_25=0x26 REMAP_PORT_26=0x25 REMAP_PORT_27=0x24 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x23 REMAP_PORT_29=0x22 REMAP_PORT_30=0x21 REMAP_PORT_31=0x20 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x1f REMAP_PORT_33=0x1e REMAP_PORT_34=0x1d REMAP_PORT_35=0x1c +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x1b REMAP_PORT_37=0x1a REMAP_PORT_38=0x19 REMAP_PORT_39=0x18 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x17 REMAP_PORT_41=0x16 REMAP_PORT_42=0x15 REMAP_PORT_43=0x14 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x13 REMAP_PORT_45=0x12 REMAP_PORT_46=0x11 REMAP_PORT_47=0x10 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0xf REMAP_PORT_49=0xe REMAP_PORT_50=0xd REMAP_PORT_51=0xc +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0xb REMAP_PORT_53=0xa REMAP_PORT_54=9 REMAP_PORT_55=8 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0xb REMAP_PORT_9=0xa REMAP_PORT_10=9 REMAP_PORT_11=8 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0xf REMAP_PORT_13=0xe REMAP_PORT_14=0xd REMAP_PORT_15=0xc +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x13 REMAP_PORT_17=0x12 REMAP_PORT_18=0x11 REMAP_PORT_19=0x10 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x17 REMAP_PORT_21=0x16 REMAP_PORT_22=0x15 REMAP_PORT_23=0x14 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x1b REMAP_PORT_25=0x1a REMAP_PORT_26=0x19 REMAP_PORT_27=0x18 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x1f REMAP_PORT_29=0x1e REMAP_PORT_30=0x1d REMAP_PORT_31=0x1c +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x23 REMAP_PORT_33=0x22 REMAP_PORT_34=0x21 REMAP_PORT_35=0x20 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x27 REMAP_PORT_37=0x26 REMAP_PORT_38=0x25 REMAP_PORT_39=0x24 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x2b REMAP_PORT_41=0x2a REMAP_PORT_42=0x29 REMAP_PORT_43=0x28 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x2f REMAP_PORT_45=0x2e REMAP_PORT_46=0x2d REMAP_PORT_47=0x2c +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0x33 REMAP_PORT_49=0x32 REMAP_PORT_50=0x31 REMAP_PORT_51=0x30 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0x37 REMAP_PORT_53=0x36 REMAP_PORT_54=0x35 REMAP_PORT_55=0x34 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=0x3b REMAP_PORT_57=0x3a REMAP_PORT_58=0x39 REMAP_PORT_59=0x38 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=0x3f REMAP_PORT_61=0x3e REMAP_PORT_62=0x3d REMAP_PORT_63=0x3c + +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=0x3f REMAP_PORT_1=1 REMAP_PORT_2=0x3f REMAP_PORT_3=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=0x3f REMAP_PORT_5=0x3f REMAP_PORT_6=0x3f REMAP_PORT_7=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0x3f REMAP_PORT_9=0x3f REMAP_PORT_10=0x3f REMAP_PORT_11=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0x3f REMAP_PORT_13=0x3f REMAP_PORT_14=0x3f REMAP_PORT_15=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x3f REMAP_PORT_17=0x3f REMAP_PORT_18=0x3f REMAP_PORT_19=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x3f REMAP_PORT_21=0x3f REMAP_PORT_22=0x3f REMAP_PORT_23=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x3f REMAP_PORT_25=0x3f REMAP_PORT_26=0x3f REMAP_PORT_27=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x3f REMAP_PORT_29=0x3f REMAP_PORT_30=0x3f REMAP_PORT_31=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x3f REMAP_PORT_33=0x3f REMAP_PORT_34=0x3f REMAP_PORT_35=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x3f REMAP_PORT_37=0x3f REMAP_PORT_38=0x3f REMAP_PORT_39=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x3f REMAP_PORT_41=0x3f REMAP_PORT_42=0x3f REMAP_PORT_43=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x3f REMAP_PORT_45=0x3f REMAP_PORT_46=0x3f REMAP_PORT_47=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0x3f REMAP_PORT_49=0x3f REMAP_PORT_50=0x3f REMAP_PORT_51=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0x3f REMAP_PORT_53=0x3f REMAP_PORT_54=0x3f REMAP_PORT_55=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=0x3f REMAP_PORT_57=0x3f REMAP_PORT_58=0x3f REMAP_PORT_59=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=0x3f REMAP_PORT_61=0x3f REMAP_PORT_62=0x3f REMAP_PORT_63=0x3f + +led 0 stop +led 0 prog 86 FF 06 FF C2 7F 60 FF 02 41 60 FE 67 1A 06 FE E2 04 60 FE D2 01 74 0C 77 51 02 9F F6 FE E2 04 04 D2 01 70 27 74 48 06 FE E2 04 90 28 32 00 32 01 B7 97 71 37 75 3F 06 FF C2 10 70 48 74 3F 67 57 67 53 67 57 67 57 57 67 57 67 57 67 57 67 57 57 3A 40 32 0E 87 57 32 0F 87 57 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 86 FF 06 FF C2 7F 60 FF 02 41 60 FE 67 1A 06 FE E2 04 60 FE D2 01 74 0C 77 51 02 9F F6 FE E2 04 04 D2 01 70 27 74 48 06 FE E2 04 90 28 32 00 32 01 B7 97 71 37 75 3F 06 FF C2 10 70 48 74 3F 67 57 67 53 67 57 67 57 57 67 57 67 57 67 57 67 57 57 3A 40 32 0E 87 57 32 0F 87 57 +led 1 auto on +led 1 start + +led 2 stop +led 2 prog 86 FF 06 FF C2 7F 60 FF 02 41 60 FE 67 1A 06 FE E2 04 60 FE D2 01 74 0C 77 51 02 9F F6 FE E2 04 04 D2 01 70 27 74 48 06 FE E2 04 90 28 32 00 32 01 B7 97 71 37 75 3F 06 FF C2 10 70 48 74 3F 67 57 67 53 67 57 67 57 57 67 57 67 57 67 57 67 57 57 3A 40 32 0E 87 57 32 0F 87 57 +led 2 auto on +led 2 start + +led 3 stop +led 3 prog 86 FF 06 FF C2 7F 60 FF 02 41 60 FE 67 1A 06 FE E2 04 60 FE D2 01 74 0C 77 51 02 9F F6 FE E2 04 04 D2 01 70 27 74 48 06 FE E2 04 90 28 32 00 32 01 B7 97 71 37 75 3F 06 FF C2 10 70 48 74 3F 67 57 67 53 67 57 67 57 57 67 57 67 57 67 57 67 57 57 3A 40 32 0E 87 57 32 0F 87 57 +led 3 auto on +led 3 start + +led 4 stop +led 4 prog 86 FF 06 FF C2 7F 60 FF 02 02 60 FE 67 1A 06 FE E2 01 60 FE D2 00 74 0C 77 6A 02 9F F6 FE 04 D2 01 70 25 74 51 06 FE 90 28 32 03 32 04 97 75 64 97 71 58 75 5E 06 FE 90 28 32 00 32 01 B7 97 71 43 75 4B 06 FF C2 10 70 4E 74 4B 67 6C 57 67 70 57 67 70 67 70 67 70 57 67 6C 67 70 77 35 67 70 67 6C 77 35 67 70 67 70 77 35 3A 06 32 0E 87 57 32 0F 87 57 +led 4 auto on +led 4 start diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/eeprom.py b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/eeprom.py new file mode 100644 index 000000000000..c0122e65844a --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0056/eeprom" + #Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/led_control.py b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/led_control.py new file mode 100644 index 000000000000..457b1d750b28 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/led_control.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python +# +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +# try: +# from sonic_led.led_control_base import LedControlBase +# import swsssdk +# except ImportError, e: +# raise ImportError (str(e) + " - required module not found") + +import time + +class LedControlBase(object): +# __metaclass__ = abc.ABCMeta + +# @abc.abstractmethod + def port_link_state_change(self, port, state): + """ + Called when port link state changes. Update port link state LED here. + + :param port: A string, SONiC port name (e.g., "Ethernet0") + :param state: A string, the port link state (either "up" or "down") + """ + return + +### Goreme specified ### +read_fan_fault = 0 +is_fan_all_OK = 0 +read_power_status = 0 +is_power_all_OK = 0 +is_thermal_high = 0 +is_reset_button_push = 0 +########################## + +def sysled_task(): + while True: + system_led_check() + time.sleep(5) + +########## Goreme System LED checking +def system_led_check(): + global read_fan_fault, read_power_status, is_fan_all_OK, is_power_all_OK, is_thermal_high, is_reset_button_push + is_fan_all_OK = 1 + is_power_all_OK = 0 + is_thermal_high = 0 + is_reset_button_push = 0 + with open("/sys/bus/i2c/devices/0-005e/fan1_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + with open("/sys/bus/i2c/devices/0-005e/fan2_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + with open("/sys/bus/i2c/devices/0-005e/fan3_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + with open("/sys/bus/i2c/devices/0-005e/fan4_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + + with open("/sys/bus/i2c/devices/8-005f/fan1_led", "w") as f11: + if int(is_fan_all_OK) == 1: + f11.write("1") + else: + f11.write("4") + + + with open("/sys/bus/i2c/devices/0-005e/psu1_power_good", "r") as f1: + read_power_status = f1.read() + if str(read_power_status) != str("1\n"): + is_power_all_OK = -10 + with open("/sys/bus/i2c/devices/0-005e/psu1_present", "r") as f1: + read_power_status = f1.read() + if str(read_power_status) == str("1\n"): + is_power_all_OK = is_power_all_OK + 1 + with open("/sys/bus/i2c/devices/0-005e/psu2_power_good", "r") as f1: + read_power_status = f1.read() + if str(read_power_status) != str("1\n"): + is_power_all_OK = -10 + with open("/sys/bus/i2c/devices/0-005e/psu2_present", "r") as f1: + read_power_status = f1.read() + if str(read_power_status) == str("1\n"): + is_power_all_OK = is_power_all_OK + 1 + + with open("/sys/bus/i2c/devices/8-005f/sys_pwr", "w") as f11: + if int(is_power_all_OK) > 0: + f11.write("1") + else: + f11.write("4") + + + with open("/sys/bus/i2c/devices/8-005f/swi_ctrl", "r") as f5: + is_reset_button_push = f5.read() + if str(is_reset_button_push) == "1\n": + is_reset_button_push = 1 + else: + is_reset_button_push = 0 + + with open("/sys/bus/i2c/devices/3-004d/hwmon/hwmon2/temp1_input", "r") as f3: + is_thermal_high = f3.read() + if int(is_thermal_high) >= 70000: + is_thermal_high = 1 + else: + is_thermal_high = 0 + + with open("/sys/bus/i2c/devices/8-005f/sys_status", "w") as f2: + if is_reset_button_push == 1: + f2.write("3") + elif is_fan_all_OK == 0 or is_power_all_OK == 0 or is_thermal_high == 1: + f2.write("4") + else: + f2.write("1") + + return +########## + +class LedControl(LedControlBase): + """Platform specific LED control class""" + PORT_TABLE_PREFIX = "PORT_TABLE:" + + SONIC_PORT_NAME_PREFIX = "Ethernet" + + LED_SYSFS_PATH_BREAKOUT_CAPABLE = "/sys/class/leds/qsfp{0}_{1}/brightness" + LED_SYSFS_PATH_NO_BREAKOUT = "/sys/class/leds/qsfp{0}/brightness" + + QSFP_BREAKOUT_START_IDX = 1 + QSFP_BREAKOUT_END_IDX = 24 + QSFP_NO_BREAKOUT_START_IDX = 25 + QSFP_NO_BREAKOUT_END_IDX = 32 + + LED_COLOR_OFF = 0 + LED_COLOR_GREEN = 1 + LED_COLOR_YELLOW = 2 + + # Helper method to map SONiC port name to Arista QSFP index + def _port_name_to_qsfp_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + sonic_port_num = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + + swss = swsssdk.SonicV2Connector() + swss.connect(swss.APPL_DB) + + lanes = swss.get(swss.APPL_DB, self.PORT_TABLE_PREFIX + port_name, 'lanes') + + # SONiC port nums are 0-based and increment by 4 + # Arista QSFP indices are 1-based and increment by 1 + return (((sonic_port_num/4) + 1), sonic_port_num%4, len(lanes.split(','))) + + + + # Concrete implementation of port_link_state_change() method + def port_link_state_change_bk(self, port, state): + qsfp_index, lane_index, lanes = self._port_name_to_qsfp_index(port) + + # Ignore invalid QSFP indices + if qsfp_index <= 0 or lanes <= 0 or lanes > 4: + return + + # QSFP indices 0-24 are breakout-capable and have four LEDs, and each LED indicate one lane. + # whereas indices 25-32 are not breakout-capable, and only have one + if qsfp_index <= self.QSFP_BREAKOUT_END_IDX: + # assuming 40G, then we need to control four lanes + led_sysfs_paths = [ self.LED_SYSFS_PATH_BREAKOUT_CAPABLE.format(qsfp_index, i) for i in range(lane_index + 1, lane_index + 1 + lanes) ] + else: + led_sysfs_paths = [ self.LED_SYSFS_PATH_NO_BREAKOUT.format(qsfp_index) ] + + for led_sysfs_path in led_sysfs_paths: + led_file = open(led_sysfs_path, "w") + + if state == "up": + led_file.write("%d" % self.LED_COLOR_GREEN) + else: + led_file.write("%d" % self.LED_COLOR_OFF) + + led_file.close() + + # Constructor + def __init__(self): + # Initialize all front-panel status LEDs to green + with open("/sys/bus/i2c/devices/8-005f/sys_locator", "w") as f: + f.write("0") + with open("/sys/bus/i2c/devices/8-005f/sys_pwr", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/8-005f/sys_status", "w") as f: + f.write("1") + + # Initialize all fan LEDs to green + with open("/sys/bus/i2c/devices/8-005f/fan1_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/8-005f/fan2_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/8-005f/fan3_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/8-005f/fan4_led", "w") as f: + f.write("1") + sysled_task() + + # Initialize: Turn all front panel QSFP LEDs off + # # for qsfp_index in range(self.QSFP_BREAKOUT_START_IDX, self.QSFP_BREAKOUT_END_IDX + 1): + # # for lane in range(1, 5): + # # led_sysfs_path = self.LED_SYSFS_PATH_BREAKOUT_CAPABLE.format(qsfp_index, lane) + # # with open(led_sysfs_path, 'w') as led_file: + # # led_file.write("%d" % self.LED_COLOR_OFF) + + # # for qsfp_index in range(self.QSFP_NO_BREAKOUT_START_IDX, self.QSFP_NO_BREAKOUT_END_IDX + 1): + # # led_sysfs_path = self.LED_SYSFS_PATH_NO_BREAKOUT.format(qsfp_index) + # # with open(led_sysfs_path, 'w') as led_file: + # # led_file.write("%d" % self.LED_COLOR_OFF) diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/psuutil.py b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/psuutil.py new file mode 100644 index 000000000000..7a3b87f24d2d --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/psuutil.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +############################################################################# +# Alphanetworks +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = { + 1: "/psu1_present", + 2: "/psu2_present", + } + self.psu_oper_status = { + 1: "/psu1_power_good", + 2: "/psu2_power_good", + } + self.psu_mapping = "0-005e" + if not os.path.exists(self.psu_path+self.psu_mapping): + self.psu_mapping = "1-005e" + + def get_num_psus(self): + return len(self.psu_presence) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping+self.psu_oper_status[index] + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping + self.psu_presence[index] + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/sfputil.py b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/sfputil.py new file mode 100644 index 000000000000..cc3cd4e8611d --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/sfputil.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + first_port = 0 + last_port = 65 + port_num = 63 + + port_to_eeprom = {} + port_to_i2cbus_mapping = { + 1 : 13, + 2 : 14, + 3 : 15, + 4 : 16, + 5 : 23, + } + + eeprom_path_1 = "/sys/bus/i2c/devices/{0}-0020/sfp{1}_eeprom" + eeprom_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_eeprom" + port_reset_path_1 = "/sys/bus/i2c/devices/{0}-0020/sfp{1}_port_reset" + port_reset_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_port_reset" + present_path_1 = "/sys/bus/i2c/devices/{0}-0020/sfp{1}_is_present" + present_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_is_present" + + _qsfp_ports = range(first_port, port_num) + + @property + def port_start(self): + return self.first_port + + @property + def port_end(self): + return self.last_port + + @property + def qsfp_ports(self): + return range(self.first_port, self.port_num + 1) + + @property + def port_to_eeprom_mapping(self): + return self.port_to_eeprom + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError + + def __init__(self): + for x in range(self.first_port, self.last_port + 1): + cpld_index = (x / 16) + 1 + index = (x % 16) + 1 + if cpld_index == 5: + path = self.eeprom_path_1 + else: + path = self.eeprom_path + self.port_to_eeprom[x] = path.format(self.port_to_i2cbus_mapping[cpld_index], index) + SfpUtilBase.__init__(self) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + cpld_index = (port_num / 16) + 1 + index = (port_num % 16) + 1 + if cpld_index == 5: + path = self.port_reset_path_1 + else: + path = self.port_reset_path + port_path = path.format(self.port_to_i2cbus_mapping[cpld_index], index) + + try: + reg_file = open(port_path, 'w') + except IOError as e: + if cpld_index < 5: + print "Error: unable to open file: %s" % str(e) + return False + + # reset + reg_file.write('1') + + time.sleep(1) + + reg_file.write('0') + + reg_file.close() + return True + + def set_low_power_mode(self, port_nuM, lpmode): + raise NotImplementedError + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + cpld_index = (port_num / 16) + 1 + index = (port_num % 16) + 1 + if cpld_index == 5: + path = self.present_path_1 + else: + path = self.present_path + port_path = path.format(self.port_to_i2cbus_mapping[cpld_index], index) + + + try: + reg_file = open(port_path) + except IOError as e: + if cpld_index < 5: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/sensors.conf b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/sensors.conf new file mode 100644 index 000000000000..0650d9da652b --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/sensors.conf @@ -0,0 +1,13 @@ +# libsensors configuration file for snh60b0_640f +# ------------------------------------------------ + +bus "i2c-1" "SMBus I801 adapter at f000" +chip "goreme_power_cpld-*" + label fan1 "Fan tray 1 front" + label fan2 "Fan tray 2 front" + label fan3 "Fan tray 3 front" + label fan4 "Fan tray 4 front" + label fan11 "Fan tray 1 rear" + label fan12 "Fan tray 2 rear" + label fan13 "Fan tray 3 rear" + label fan14 "Fan tray 4 rear" diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/port_config.ini b/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/port_config.ini new file mode 100644 index 000000000000..1cc6c91b1308 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index +Ethernet0 125,126,127,128 Ethernet1/1 1 +Ethernet4 121,122,123,124 Ethernet2/1 2 +Ethernet8 13,14,15,16 Ethernet3/1 3 +Ethernet12 9,10,11,12 Ethernet4/1 4 +Ethernet16 17,18,19,20 Ethernet5/1 5 +Ethernet20 21,22,23,24 Ethernet6/1 6 +Ethernet24 25,26,27,28 Ethernet7/1 7 +Ethernet28 29,30,31,32 Ethernet8/1 8 +Ethernet32 37,38,39,40 Ethernet9/1 9 +Ethernet36 33,34,35,36 Ethernet10/1 10 +Ethernet40 45,46,47,48 Ethernet11/1 11 +Ethernet44 41,42,43,44 Ethernet12/1 12 +Ethernet48 53,54,55,56 Ethernet13/1 13 +Ethernet52 49,50,51,52 Ethernet14/1 14 +Ethernet56 69,70,71,72 Ethernet15/1 15 +Ethernet60 65,66,67,68 Ethernet16/1 16 +Ethernet64 77 Ethernet17/1 17 +Ethernet65 78 Ethernet17/2 17 +Ethernet66 79 Ethernet17/3 17 +Ethernet67 80 Ethernet17/4 17 +Ethernet68 73 Ethernet18/1 18 +Ethernet69 74 Ethernet18/2 18 +Ethernet70 75 Ethernet18/3 18 +Ethernet71 76 Ethernet18/4 18 +Ethernet72 93 Ethernet19/1 19 +Ethernet73 94 Ethernet19/2 19 +Ethernet74 95 Ethernet19/3 19 +Ethernet75 96 Ethernet19/4 19 +Ethernet76 89 Ethernet20/1 20 +Ethernet77 90 Ethernet20/2 20 +Ethernet78 91 Ethernet20/3 20 +Ethernet79 92 Ethernet20/4 20 +Ethernet80 101 Ethernet21/1 21 +Ethernet81 102 Ethernet21/2 21 +Ethernet82 103 Ethernet21/3 21 +Ethernet83 104 Ethernet21/4 21 +Ethernet84 97 Ethernet22/1 22 +Ethernet85 98 Ethernet22/2 22 +Ethernet86 99 Ethernet22/3 22 +Ethernet87 100 Ethernet22/4 22 +Ethernet88 109 Ethernet23/1 23 +Ethernet89 110 Ethernet23/2 23 +Ethernet90 111 Ethernet23/3 23 +Ethernet91 112 Ethernet23/4 23 +Ethernet92 105 Ethernet24/1 24 +Ethernet93 106 Ethernet24/2 24 +Ethernet94 107 Ethernet24/3 24 +Ethernet95 108 Ethernet24/4 24 +Ethernet96 61,62,63,64 Ethernet25 25 +Ethernet100 57,58,59,60 Ethernet26 26 +Ethernet104 81,82,83,84 Ethernet27 27 +Ethernet108 85,86,87,88 Ethernet28 28 +Ethernet112 117,118,119,120 Ethernet29 29 +Ethernet116 113,114,115,116 Ethernet30 30 +Ethernet120 5,6,7,8 Ethernet31 31 +Ethernet124 1,2,3,4 Ethernet32 32 diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/sai.profile b/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/sai.profile new file mode 100644 index 000000000000..5c613675c37f --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-a7050-qx32-16x40G+32x10G+8x40G.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/td2-a7050-qx32-16x40G+32x10G+8x40G.config.bcm b/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/td2-a7050-qx32-16x40G+32x10G+8x40G.config.bcm new file mode 100644 index 000000000000..4ce6b2d4a9d6 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/td2-a7050-qx32-16x40G+32x10G+8x40G.config.bcm @@ -0,0 +1,706 @@ +#/****************************************************************************** +# * +# * File: config.bcm.cloverdales (7050-QX32) +# * Name: +# * +# * Description: This file contains SDK properties for an Arista +# * Cloverdales platform. +# * +# *----------------------------------------------------------------------------- +# ******************************************************************************/ +#################################################################### +# BCM Config file for Cloverdale platform +# - 16x40g + 32x10g + 8x40G Portmode + +# Old LPM only configuration +# l2_mem_entries=163840 +# l3_mem_entries=90112 +# l3_alpm_enable=0 +# ipv6_lpm_128b_enable=0 +# +# ALPM enable +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l2_mem_entries=32768 +l3_mem_entries=16384 + +# From old config file +os=unix +higig2_hdr_mode=1 + +# Parity +parity_correction=1 +parity_enable=1 +stat_if_parity_enable=0 + +# l2 thread related config vars +l2xmsg_hostbuf_size=8192 +l2xmsg_mode=1 + +bcm_num_cos=8 +bcm_stat_interval=2000000 +lls_num_l2uc=12 +max_vp_lags=0 +miim_intr_enable=0 +mmu_lossless=0 +module_64ports=0 +schan_intr_enable=0 +stable_size=0x2000000 +tdma_timeout_usec=5000000 + +# for GLC transceiver +phy_an_c73=0x0 +phy_an_c37=0x3 + +########################### +#port_init_speed_xe=40000 +#port_init_speed_xe.0=40000 + +#load_firmware=0x0102 +load_firmware.0=2 + +######################### +# All ports are in oversubscription mode +pbmp_oversubscribe=0x1fffffffffffffffffffffffffe +pbmp_xport_xe.0=0x1fffffffffffffffffffffffffe + +########################################## +#skip_L2_USER_ENTRY=0 +phy_aux_voltage_enable=1 +############################### +serdes_fiber_pref=1 +############################### +mdio_output_delay.0=0x0d +############################### +serdes_sgmii_m=0 +xgxs_lcpll_xtal_refclk=1 +xgxs_lcpll_xtal_refclk.0=1 +xgxs_lcpll_xtal_refclk.1=1 +xgxs_lcpll_xtal_refclk.2=1 +xgxs_lcpll_xtal_refclk.3=1 +tdma_intr_enable=1 +tslam_intr_enable=1 +tslam_dma_enable.2=1 +tslam_dma_enable.3=1 +#dport_map_port=0 +#pci2eb_overrid=0 +#bcm_xlate_port_enable.0=0 +#xgxs_pdetect_1=0 +table_dma_enable.0=1 +table_dma_enable.1=1 +table_dma_enable.2=1 +table_dma_enable.3=1 + + +phy_84328_1.0=1 +phy_84328_5.0=1 +phy_84328_9.0=1 +phy_84328_13.0=1 +phy_84328_101.0=1 +phy_84328_102.0=1 +phy_84328_103.0=1 +phy_84328_104.0=1 + +phy_an_c37_1.0=0 +phy_an_c37_5.0=0 +phy_an_c37_9.0=0 +phy_an_c37_13.0=0 +phy_an_c37_17.0=0 +phy_an_c37_21.0=0 +phy_an_c37_25.0=0 +phy_an_c37_29.0=0 +phy_an_c37_33.0=0 +phy_an_c37_37.0=0 +phy_an_c37_41.0=0 +phy_an_c37_45.0=0 +phy_an_c37_49.0=0 +phy_an_c37_53.0=0 +phy_an_c37_57.0=0 +phy_an_c37_61.0=0 +phy_an_c37_65.0=3 +phy_an_c37_66.0=3 +phy_an_c37_67.0=3 +phy_an_c37_68.0=3 +phy_an_c37_69.0=3 +phy_an_c37_70.0=3 +phy_an_c37_71.0=3 +phy_an_c37_72.0=3 +phy_an_c37_73.0=3 +phy_an_c37_74.0=3 +phy_an_c37_75.0=3 +phy_an_c37_76.0=3 +phy_an_c37_77.0=3 +phy_an_c37_78.0=3 +phy_an_c37_79.0=3 +phy_an_c37_80.0=3 +phy_an_c37_81.0=3 +phy_an_c37_82.0=3 +phy_an_c37_83.0=3 +phy_an_c37_84.0=3 +phy_an_c37_85.0=3 +phy_an_c37_86.0=3 +phy_an_c37_87.0=3 +phy_an_c37_88.0=3 +phy_an_c37_89.0=3 +phy_an_c37_90.0=3 +phy_an_c37_91.0=3 +phy_an_c37_92.0=3 +phy_an_c37_93.0=3 +phy_an_c37_94.0=3 +phy_an_c37_95.0=3 +phy_an_c37_96.0=3 +phy_an_c37_97.0=0 +phy_an_c37_98.0=0 +phy_an_c37_99.0=0 +phy_an_c37_100.0=0 +phy_an_c37_101.0=0 +phy_an_c37_102.0=0 +phy_an_c37_103.0=0 +phy_an_c37_104.0=0 + +phy_an_c73_1.0=2 +phy_an_c73_5.0=2 +phy_an_c73_9.0=2 +phy_an_c73_13.0=2 +phy_an_c73_17.0=2 +phy_an_c73_21.0=2 +phy_an_c73_25.0=2 +phy_an_c73_29.0=2 +phy_an_c73_33.0=2 +phy_an_c73_37.0=2 +phy_an_c73_41.0=2 +phy_an_c73_45.0=2 +phy_an_c73_49.0=2 +phy_an_c73_53.0=2 +phy_an_c73_57.0=2 +phy_an_c73_61.0=2 +phy_an_c73_65.0=0 +phy_an_c73_66.0=0 +phy_an_c73_67.0=0 +phy_an_c73_68.0=0 +phy_an_c73_69.0=0 +phy_an_c73_70.0=0 +phy_an_c73_71.0=0 +phy_an_c73_72.0=0 +phy_an_c73_73.0=0 +phy_an_c73_74.0=0 +phy_an_c73_75.0=0 +phy_an_c73_76.0=0 +phy_an_c73_77.0=0 +phy_an_c73_78.0=0 +phy_an_c73_79.0=0 +phy_an_c73_80.0=0 +phy_an_c73_81.0=0 +phy_an_c73_82.0=0 +phy_an_c73_83.0=0 +phy_an_c73_84.0=0 +phy_an_c73_85.0=0 +phy_an_c73_86.0=0 +phy_an_c73_87.0=0 +phy_an_c73_88.0=0 +phy_an_c73_89.0=0 +phy_an_c73_90.0=0 +phy_an_c73_91.0=0 +phy_an_c73_92.0=0 +phy_an_c73_93.0=0 +phy_an_c73_94.0=0 +phy_an_c73_95.0=0 +phy_an_c73_96.0=0 +phy_an_c73_97.0=2 +phy_an_c73_98.0=2 +phy_an_c73_99.0=2 +phy_an_c73_100.0=2 +phy_an_c73_101.0=2 +phy_an_c73_102.0=2 +phy_an_c73_103.0=2 +phy_an_c73_104.0=2 + +phy_aux_voltage_enable_1.0=0x1 +phy_aux_voltage_enable_5.0=0x1 +phy_aux_voltage_enable_9.0=0x1 +phy_aux_voltage_enable_13.0=0x1 +phy_aux_voltage_enable_101.0=0x1 +phy_aux_voltage_enable_102.0=0x1 +phy_aux_voltage_enable_103.0=0x1 +phy_aux_voltage_enable_104.0=0x1 + +phy_ext_rom_boot.0=0 + +phy_ext_rom_boot_1.0=0x0 +phy_ext_rom_boot_5.0=0x0 +phy_ext_rom_boot_9.0=0x0 +phy_ext_rom_boot_13.0=0x0 +phy_ext_rom_boot_101.0=0x0 +phy_ext_rom_boot_102.0=0x0 +phy_ext_rom_boot_103.0=0x0 +phy_ext_rom_boot_104.0=0x0 + + +phy_line_tx_mode_1.0=1 +phy_line_tx_mode_5.0=1 +phy_line_tx_mode_9.0=1 +phy_line_tx_mode_13.0=1 +phy_line_tx_mode_101.0=1 +phy_line_tx_mode_102.0=1 +phy_line_tx_mode_103.0=1 +phy_line_tx_mode_104.0=1 + + +phy_rx_polarity_flip_1.0=0x0 +phy_rx_polarity_flip_5.0=0x0 +phy_rx_polarity_flip_9.0=0x0 +phy_rx_polarity_flip_13.0=0x0 +phy_rx_polarity_flip_101.0=0x0 +phy_rx_polarity_flip_102.0=0x0 +phy_rx_polarity_flip_103.0=0x0 +phy_rx_polarity_flip_104.0=0x0 + +phy_system_tx_mode_1.0=0 +phy_system_tx_mode_5.0=0 +phy_system_tx_mode_9.0=0 +phy_system_tx_mode_13.0=0 +phy_system_tx_mode_101.0=0 +phy_system_tx_mode_102.0=0 +phy_system_tx_mode_103.0=0 +phy_system_tx_mode_104.0=0 + + +phy_tx_polarity_flip_1.0=0x0 +phy_tx_polarity_flip_5.0=0x0 +phy_tx_polarity_flip_9.0=0x0 +phy_tx_polarity_flip_13.0=0x0 +phy_tx_polarity_flip_101.0=0x0 +phy_tx_polarity_flip_102.0=0x0 +phy_tx_polarity_flip_103.0=0x0 +phy_tx_polarity_flip_104.0=0x0 + + +phy_xaui_rx_polarity_flip_1.0=0x0 +phy_xaui_rx_polarity_flip_5.0=0x0 +phy_xaui_rx_polarity_flip_9.0=0x0 +phy_xaui_rx_polarity_flip_13.0=0x0 +phy_xaui_rx_polarity_flip_17.0=0x0 +phy_xaui_rx_polarity_flip_21.0=0x0 +phy_xaui_rx_polarity_flip_25.0=0x0 +phy_xaui_rx_polarity_flip_29.0=0x0 +phy_xaui_rx_polarity_flip_33.0=0x0 +phy_xaui_rx_polarity_flip_37.0=0x0 +phy_xaui_rx_polarity_flip_41.0=0x0 +phy_xaui_rx_polarity_flip_45.0=0x0 +phy_xaui_rx_polarity_flip_49.0=0x0 +phy_xaui_rx_polarity_flip_53.0=0x0 +phy_xaui_rx_polarity_flip_57.0=0x0 +phy_xaui_rx_polarity_flip_61.0=0x0 +phy_xaui_rx_polarity_flip_65.0=0x0 +phy_xaui_rx_polarity_flip_66.0=0x0 +phy_xaui_rx_polarity_flip_67.0=0x0 +phy_xaui_rx_polarity_flip_68.0=0x0 +phy_xaui_rx_polarity_flip_69.0=0x0 +phy_xaui_rx_polarity_flip_70.0=0x0 +phy_xaui_rx_polarity_flip_71.0=0x0 +phy_xaui_rx_polarity_flip_72.0=0x0 +phy_xaui_rx_polarity_flip_73.0=0x0 +phy_xaui_rx_polarity_flip_74.0=0x0 +phy_xaui_rx_polarity_flip_75.0=0x0 +phy_xaui_rx_polarity_flip_76.0=0x0 +phy_xaui_rx_polarity_flip_77.0=0x0 +phy_xaui_rx_polarity_flip_78.0=0x0 +phy_xaui_rx_polarity_flip_79.0=0x0 +phy_xaui_rx_polarity_flip_80.0=0x0 +phy_xaui_rx_polarity_flip_81.0=0x0 +phy_xaui_rx_polarity_flip_82.0=0x0 +phy_xaui_rx_polarity_flip_83.0=0x0 +phy_xaui_rx_polarity_flip_84.0=0x0 +phy_xaui_rx_polarity_flip_85.0=0x0 +phy_xaui_rx_polarity_flip_86.0=0x0 +phy_xaui_rx_polarity_flip_87.0=0x0 +phy_xaui_rx_polarity_flip_88.0=0x0 +phy_xaui_rx_polarity_flip_89.0=0x0 +phy_xaui_rx_polarity_flip_90.0=0x0 +phy_xaui_rx_polarity_flip_91.0=0x0 +phy_xaui_rx_polarity_flip_92.0=0x0 +phy_xaui_rx_polarity_flip_93.0=0x0 +phy_xaui_rx_polarity_flip_94.0=0x0 +phy_xaui_rx_polarity_flip_95.0=0x0 +phy_xaui_rx_polarity_flip_96.0=0x0 +phy_xaui_rx_polarity_flip_97.0=0x0 +phy_xaui_rx_polarity_flip_98.0=0x0 +phy_xaui_rx_polarity_flip_99.0=0x0 +phy_xaui_rx_polarity_flip_100.0=0x0 +phy_xaui_rx_polarity_flip_101.0=0x0 +phy_xaui_rx_polarity_flip_102.0=0x0 +phy_xaui_rx_polarity_flip_103.0=0x0 +phy_xaui_rx_polarity_flip_104.0=0x0 + +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_5.0=0x0 +phy_xaui_tx_polarity_flip_9.0=0x0 +phy_xaui_tx_polarity_flip_13.0=0x0 +phy_xaui_tx_polarity_flip_17.0=0x0 +phy_xaui_tx_polarity_flip_21.0=0x0 +phy_xaui_tx_polarity_flip_25.0=0x0 +phy_xaui_tx_polarity_flip_29.0=0x0 +phy_xaui_tx_polarity_flip_33.0=0x0 +phy_xaui_tx_polarity_flip_37.0=0x0 +phy_xaui_tx_polarity_flip_41.0=0x0 +phy_xaui_tx_polarity_flip_45.0=0x0 +phy_xaui_tx_polarity_flip_49.0=0x0 +phy_xaui_tx_polarity_flip_53.0=0x0 +phy_xaui_tx_polarity_flip_57.0=0x0 +phy_xaui_tx_polarity_flip_61.0=0x0 +phy_xaui_tx_polarity_flip_65.0=0x0 +phy_xaui_tx_polarity_flip_66.0=0x0 +phy_xaui_tx_polarity_flip_67.0=0x0 +phy_xaui_tx_polarity_flip_68.0=0x0 +phy_xaui_tx_polarity_flip_69.0=0x0 +phy_xaui_tx_polarity_flip_70.0=0x0 +phy_xaui_tx_polarity_flip_71.0=0x0 +phy_xaui_tx_polarity_flip_72.0=0x0 +phy_xaui_tx_polarity_flip_73.0=0x0 +phy_xaui_tx_polarity_flip_74.0=0x0 +phy_xaui_tx_polarity_flip_75.0=0x0 +phy_xaui_tx_polarity_flip_76.0=0x0 +phy_xaui_tx_polarity_flip_77.0=0x0 +phy_xaui_tx_polarity_flip_78.0=0x0 +phy_xaui_tx_polarity_flip_79.0=0x0 +phy_xaui_tx_polarity_flip_80.0=0x0 +phy_xaui_tx_polarity_flip_81.0=0x0 +phy_xaui_tx_polarity_flip_82.0=0x0 +phy_xaui_tx_polarity_flip_83.0=0x0 +phy_xaui_tx_polarity_flip_84.0=0x0 +phy_xaui_tx_polarity_flip_85.0=0x0 +phy_xaui_tx_polarity_flip_86.0=0x0 +phy_xaui_tx_polarity_flip_87.0=0x0 +phy_xaui_tx_polarity_flip_88.0=0x0 +phy_xaui_tx_polarity_flip_89.0=0x0 +phy_xaui_tx_polarity_flip_90.0=0x0 +phy_xaui_tx_polarity_flip_91.0=0x0 +phy_xaui_tx_polarity_flip_92.0=0x0 +phy_xaui_tx_polarity_flip_93.0=0x0 +phy_xaui_tx_polarity_flip_94.0=0x0 +phy_xaui_tx_polarity_flip_95.0=0x0 +phy_xaui_tx_polarity_flip_96.0=0x0 +phy_xaui_tx_polarity_flip_97.0=0x0 +phy_xaui_tx_polarity_flip_98.0=0x0 +phy_xaui_tx_polarity_flip_99.0=0x0 +phy_xaui_tx_polarity_flip_100.0=0x0 +phy_xaui_tx_polarity_flip_101.0=0x0 +phy_xaui_tx_polarity_flip_102.0=0x0 +phy_xaui_tx_polarity_flip_103.0=0x0 +phy_xaui_tx_polarity_flip_104.0=0x0 + +port_init_autoneg_17.0=0 +port_init_autoneg_21.0=0 +port_init_autoneg_25.0=0 +port_init_autoneg_29.0=0 +port_init_autoneg_33.0=0 +port_init_autoneg_37.0=0 +port_init_autoneg_41.0=0 +port_init_autoneg_45.0=0 +port_init_autoneg_49.0=0 +port_init_autoneg_53.0=0 +port_init_autoneg_57.0=0 +port_init_autoneg_61.0=0 +port_init_autoneg_65.0=0 +port_init_autoneg_66.0=0 +port_init_autoneg_67.0=0 +port_init_autoneg_68.0=0 +port_init_autoneg_69.0=0 +port_init_autoneg_70.0=0 +port_init_autoneg_71.0=0 +port_init_autoneg_72.0=0 +port_init_autoneg_73.0=0 +port_init_autoneg_74.0=0 +port_init_autoneg_75.0=0 +port_init_autoneg_76.0=0 +port_init_autoneg_77.0=0 +port_init_autoneg_78.0=0 +port_init_autoneg_79.0=0 +port_init_autoneg_80.0=0 +port_init_autoneg_81.0=0 +port_init_autoneg_82.0=0 +port_init_autoneg_83.0=0 +port_init_autoneg_84.0=0 +port_init_autoneg_85.0=0 +port_init_autoneg_86.0=0 +port_init_autoneg_87.0=0 +port_init_autoneg_88.0=0 +port_init_autoneg_89.0=0 +port_init_autoneg_90.0=0 +port_init_autoneg_91.0=0 +port_init_autoneg_92.0=0 +port_init_autoneg_93.0=0 +port_init_autoneg_94.0=0 +port_init_autoneg_95.0=0 +port_init_autoneg_96.0=0 +port_init_autoneg_97.0=0 +port_init_autoneg_98.0=0 +port_init_autoneg_99.0=0 +port_init_autoneg_100.0=0 + +port_init_cl72_hg.0=0x11 + + +portmap_1.0=125:40 +portmap_5.0=121:40 +portmap_9.0=13:40 +portmap_13.0=9:40 +portmap_17.0=17:40 +portmap_21.0=21:40 +portmap_25.0=25:40 +portmap_29.0=29:40 +portmap_33.0=37:40 +portmap_37.0=33:40 +portmap_41.0=45:40 +portmap_45.0=41:40 +portmap_49.0=53:40 +portmap_53.0=49:40 +portmap_57.0=69:40 +portmap_61.0=65:40 +portmap_65.0=77:10 +portmap_66.0=78:10 +portmap_67.0=79:10 +portmap_68.0=80:10 +portmap_69.0=73:10 +portmap_70.0=74:10 +portmap_71.0=75:10 +portmap_72.0=76:10 +portmap_73.0=93:10 +portmap_74.0=94:10 +portmap_75.0=95:10 +portmap_76.0=96:10 +portmap_77.0=89:10 +portmap_78.0=90:10 +portmap_79.0=91:10 +portmap_80.0=92:10 +portmap_81.0=101:10 +portmap_82.0=102:10 +portmap_83.0=103:10 +portmap_84.0=104:10 +portmap_85.0=97:10 +portmap_86.0=98:10 +portmap_87.0=99:10 +portmap_88.0=100:10 +portmap_89.0=109:10 +portmap_90.0=110:10 +portmap_91.0=111:10 +portmap_92.0=112:10 +portmap_93.0=105:10 +portmap_94.0=106:10 +portmap_95.0=107:10 +portmap_96.0=108:10 +portmap_97.0=61:40 +portmap_98.0=57:40 +portmap_99.0=81:40 +portmap_100.0=85:40 +portmap_101.0=117:40 +portmap_102.0=113:40 +portmap_103.0=5:40 +portmap_104.0=1:40 + +port_phy_addr_1.0=0x4 +port_phy_addr_5.0=0x0 +port_phy_addr_9.0=0x2c +port_phy_addr_13.0=0x28 +port_phy_addr_17.0=0x7f +port_phy_addr_21.0=0x7f +port_phy_addr_25.0=0x7f +port_phy_addr_29.0=0x7f +port_phy_addr_33.0=0x7f +port_phy_addr_37.0=0x7f +port_phy_addr_41.0=0x7f +port_phy_addr_45.0=0x7f +port_phy_addr_49.0=0x7f +port_phy_addr_53.0=0x7f +port_phy_addr_57.0=0x7f +port_phy_addr_61.0=0x7f +port_phy_addr_65.0=0x7f +port_phy_addr_66.0=0x7f +port_phy_addr_67.0=0x7f +port_phy_addr_68.0=0x7f +port_phy_addr_69.0=0x7f +port_phy_addr_70.0=0x7f +port_phy_addr_71.0=0x7f +port_phy_addr_72.0=0x7f +port_phy_addr_73.0=0x7f +port_phy_addr_74.0=0x7f +port_phy_addr_75.0=0x7f +port_phy_addr_76.0=0x7f +port_phy_addr_77.0=0x7f +port_phy_addr_78.0=0x7f +port_phy_addr_79.0=0x7f +port_phy_addr_80.0=0x7f +port_phy_addr_81.0=0x7f +port_phy_addr_82.0=0x7f +port_phy_addr_83.0=0x7f +port_phy_addr_84.0=0x7f +port_phy_addr_85.0=0x7f +port_phy_addr_86.0=0x7f +port_phy_addr_87.0=0x7f +port_phy_addr_88.0=0x7f +port_phy_addr_89.0=0x7f +port_phy_addr_90.0=0x7f +port_phy_addr_91.0=0x7f +port_phy_addr_92.0=0x7f +port_phy_addr_93.0=0x7f +port_phy_addr_94.0=0x7f +port_phy_addr_95.0=0x7f +port_phy_addr_96.0=0x7f +port_phy_addr_97.0=0x7f +port_phy_addr_98.0=0x7f +port_phy_addr_99.0=0x7f +port_phy_addr_100.0=0x7f +port_phy_addr_101.0=0x54 +port_phy_addr_102.0=0x50 +port_phy_addr_103.0=0x7c +port_phy_addr_104.0=0x78 + +port_phy_clause_1.0=0x2d +port_phy_clause_5.0=0x2d +port_phy_clause_9.0=0x2d +port_phy_clause_13.0=0x2d +port_phy_clause_101.0=0x2d +port_phy_clause_102.0=0x2d +port_phy_clause_103.0=0x2d +port_phy_clause_104.0=0x2d + +port_phy_id0_1.0=0x600d +port_phy_id0_5.0=0x600d +port_phy_id0_9.0=0x600d +port_phy_id0_13.0=0x600d +port_phy_id0_101.0=0x600d +port_phy_id0_102.0=0x600d +port_phy_id0_103.0=0x600d +port_phy_id0_104.0=0x600d + +port_phy_id1_1.0=0x8500 +port_phy_id1_5.0=0x8500 +port_phy_id1_9.0=0x8500 +port_phy_id1_13.0=0x8500 +port_phy_id1_101.0=0x8500 +port_phy_id1_102.0=0x8500 +port_phy_id1_103.0=0x8500 +port_phy_id1_104.0=0x8500 + +xgxs_rx_lane_map_1.0=0x0123 +xgxs_rx_lane_map_5.0=0x0123 +xgxs_rx_lane_map_9.0=0x0123 +xgxs_rx_lane_map_13.0=0x0123 +xgxs_rx_lane_map_17.0=0x2031 +xgxs_rx_lane_map_21.0=0x2031 +xgxs_rx_lane_map_25.0=0x2031 +xgxs_rx_lane_map_29.0=0x2031 +xgxs_rx_lane_map_33.0=0x3120 +xgxs_rx_lane_map_37.0=0x3120 +xgxs_rx_lane_map_41.0=0x3120 +xgxs_rx_lane_map_45.0=0x3120 +xgxs_rx_lane_map_49.0=0x3120 +xgxs_rx_lane_map_53.0=0x3120 +xgxs_rx_lane_map_57.0=0x3120 +xgxs_rx_lane_map_61.0=0x3120 +xgxs_rx_lane_map_65.0=0x3120 +xgxs_rx_lane_map_69.0=0x3120 +xgxs_rx_lane_map_73.0=0x3120 +xgxs_rx_lane_map_77.0=0x3120 +xgxs_rx_lane_map_81.0=0x3120 +xgxs_rx_lane_map_85.0=0x3120 +xgxs_rx_lane_map_89.0=0x3120 +xgxs_rx_lane_map_93.0=0x3120 +xgxs_rx_lane_map_97.0=0x1302 +xgxs_rx_lane_map_98.0=0x1302 +xgxs_rx_lane_map_99.0=0x0213 +xgxs_tx_lane_map_100.0=0x0213 +xgxs_tx_lane_map_101.0=0x0123 +xgxs_tx_lane_map_102.0=0x0123 +xgxs_tx_lane_map_103.0=0x0123 +xgxs_tx_lane_map_104.0=0x0123 + +xgxs_tx_lane_map_1.0=0x0123 +xgxs_tx_lane_map_5.0=0x0123 +xgxs_tx_lane_map_9.0=0x0123 +xgxs_tx_lane_map_13.0=0x0123 +xgxs_tx_lane_map_17.0=0x1302 +xgxs_tx_lane_map_21.0=0x1302 +xgxs_tx_lane_map_25.0=0x1302 +xgxs_tx_lane_map_29.0=0x1302 +xgxs_tx_lane_map_33.0=0x3120 +xgxs_tx_lane_map_37.0=0x3120 +xgxs_tx_lane_map_41.0=0x3120 +xgxs_tx_lane_map_45.0=0x3120 +xgxs_tx_lane_map_49.0=0x3120 +xgxs_tx_lane_map_53.0=0x3120 +xgxs_tx_lane_map_57.0=0x3120 +xgxs_tx_lane_map_61.0=0x3120 +xgxs_tx_lane_map_65.0=0x3120 +xgxs_tx_lane_map_69.0=0x3120 +xgxs_tx_lane_map_73.0=0x3120 +xgxs_tx_lane_map_77.0=0x3120 +xgxs_tx_lane_map_81.0=0x3120 +xgxs_tx_lane_map_85.0=0x3120 +xgxs_tx_lane_map_89.0=0x3120 +xgxs_tx_lane_map_93.0=0x3120 +xgxs_tx_lane_map_97.0=0x2031 +xgxs_tx_lane_map_98.0=0x2031 +xgxs_tx_lane_map_99.0=0x0213 +xgxs_rx_lane_map_100.0=0x0213 +xgxs_rx_lane_map_101.0=0x0123 +xgxs_rx_lane_map_102.0=0x0123 +xgxs_rx_lane_map_103.0=0x0123 +xgxs_rx_lane_map_104.0=0x0123 + +serdes_firmware_mode_1.0=1 +serdes_firmware_mode_5.0=1 +serdes_firmware_mode_9.0=1 +serdes_firmware_mode_13.0=1 +serdes_firmware_mode_17.0=2 +serdes_firmware_mode_21.0=2 +serdes_firmware_mode_25.0=2 +serdes_firmware_mode_29.0=2 +serdes_firmware_mode_33.0=2 +serdes_firmware_mode_37.0=2 +serdes_firmware_mode_41.0=2 +serdes_firmware_mode_45.0=2 +serdes_firmware_mode_49.0=2 +serdes_firmware_mode_53.0=2 +serdes_firmware_mode_57.0=2 +serdes_firmware_mode_61.0=2 +serdes_firmware_mode_65.0=2 +serdes_firmware_mode_66.0=2 +serdes_firmware_mode_67.0=2 +serdes_firmware_mode_68.0=2 +serdes_firmware_mode_69.0=2 +serdes_firmware_mode_70.0=2 +serdes_firmware_mode_71.0=2 +serdes_firmware_mode_72.0=2 +serdes_firmware_mode_73.0=2 +serdes_firmware_mode_74.0=2 +serdes_firmware_mode_75.0=2 +serdes_firmware_mode_76.0=2 +serdes_firmware_mode_77.0=2 +serdes_firmware_mode_78.0=2 +serdes_firmware_mode_79.0=2 +serdes_firmware_mode_80.0=2 +serdes_firmware_mode_81.0=2 +serdes_firmware_mode_82.0=2 +serdes_firmware_mode_83.0=2 +serdes_firmware_mode_84.0=2 +serdes_firmware_mode_85.0=2 +serdes_firmware_mode_86.0=2 +serdes_firmware_mode_87.0=2 +serdes_firmware_mode_88.0=2 +serdes_firmware_mode_89.0=2 +serdes_firmware_mode_90.0=2 +serdes_firmware_mode_91.0=2 +serdes_firmware_mode_92.0=2 +serdes_firmware_mode_93.0=2 +serdes_firmware_mode_94.0=2 +serdes_firmware_mode_95.0=2 +serdes_firmware_mode_96.0=2 +serdes_firmware_mode_97.0=2 +serdes_firmware_mode_98.0=2 +serdes_firmware_mode_99.0=2 +serdes_firmware_mode_100.0=2 +serdes_firmware_mode_101.0=1 +serdes_firmware_mode_102.0=1 +serdes_firmware_mode_103.0=1 +serdes_firmware_mode_104.0=1 diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/buffers.json.j2 b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/buffers.json.j2 new file mode 100644 index 000000000000..b67cf577ab75 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/buffers_defaults_t1.j2 b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..40d32ef316da --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/buffers_defaults_t1.j2 @@ -0,0 +1,45 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7582515", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/pg_profile_lookup.ini b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/pg_profile_lookup.ini new file mode 100644 index 000000000000..135a598465ba --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/pg_profile_lookup.ini @@ -0,0 +1,11 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 40000 5m 41808 18432 40560 -3 2496 + 50000 5m 41808 18432 40560 -3 2496 + 100000 5m 41808 18432 40560 -3 2496 + 40000 40m 51376 18432 50128 -3 2496 + 50000 40m 51376 18432 50128 -3 2496 + 100000 40m 51376 18432 50128 -3 2496 + 40000 300m 51376 18432 50128 -3 2496 + 50000 300m 51376 18432 50128 -3 2496 + 100000 300m 51376 18432 50128 -3 2496 diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/port_config.ini b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/port_config.ini new file mode 100644 index 000000000000..212e1da4b0b2 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 125,126,127,128 Ethernet1/1 1 40000 +Ethernet4 121,122,123,124 Ethernet2/1 2 40000 +Ethernet8 13,14,15,16 Ethernet3/1 3 40000 +Ethernet12 9,10,11,12 Ethernet4/1 4 40000 +Ethernet16 17,18,19,20 Ethernet5/1 5 40000 +Ethernet20 21,22,23,24 Ethernet6/1 6 40000 +Ethernet24 25,26,27,28 Ethernet7/1 7 40000 +Ethernet28 29,30,31,32 Ethernet8/1 8 40000 +Ethernet32 37,38,39,40 Ethernet9/1 9 40000 +Ethernet36 33,34,35,36 Ethernet10/1 10 40000 +Ethernet40 45,46,47,48 Ethernet11/1 11 40000 +Ethernet44 41,42,43,44 Ethernet12/1 12 40000 +Ethernet48 53,54,55,56 Ethernet13/1 13 40000 +Ethernet52 49,50,51,52 Ethernet14/1 14 40000 +Ethernet56 69,70,71,72 Ethernet15/1 15 40000 +Ethernet60 65,66,67,68 Ethernet16/1 16 40000 +Ethernet64 77,78,79,80 Ethernet17/1 17 40000 +Ethernet68 73,74,75,76 Ethernet18/1 18 40000 +Ethernet72 93,94,95,96 Ethernet19/1 19 40000 +Ethernet76 89,90,91,92 Ethernet20/1 20 40000 +Ethernet80 101,102,103,104 Ethernet21/1 21 40000 +Ethernet84 97,98,99,100 Ethernet22/1 22 40000 +Ethernet88 109,110,111,112 Ethernet23/1 23 40000 +Ethernet92 105,106,107,108 Ethernet24/1 24 40000 +Ethernet96 61,62,63,64 Ethernet25 25 40000 +Ethernet100 57,58,59,60 Ethernet26 26 40000 +Ethernet104 81,82,83,84 Ethernet27 27 40000 +Ethernet108 85,86,87,88 Ethernet28 28 40000 +Ethernet112 117,118,119,120 Ethernet29 29 40000 +Ethernet116 113,114,115,116 Ethernet30 30 40000 +Ethernet120 5,6,7,8 Ethernet31 31 40000 +Ethernet124 1,2,3,4 Ethernet32 32 40000 diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/qos.json.j2 b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/sai.profile b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/sai.profile new file mode 100644 index 000000000000..27d83fcc20e9 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-a7050-qx32-32x40G.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/td2-a7050-qx32-32x40G.config.bcm b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/td2-a7050-qx32-32x40G.config.bcm new file mode 100644 index 000000000000..76b1af3aba16 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/td2-a7050-qx32-32x40G.config.bcm @@ -0,0 +1,872 @@ +#/****************************************************************************** +# * +# * File: config.bcm.cloverdales (7050-QX32) +# * Name: +# * +# * Description: This file contains SDK properties for an Arista +# * Cloverdales platform. +# * +# *----------------------------------------------------------------------------- +# ******************************************************************************/ +#################################################################### +# BCM Config file for Cloverdale platform +# - 32x40g Portmode + +# Old LPM only configuration +# l2_mem_entries=163840 +# l3_mem_entries=90112 +# l3_alpm_enable=0 +# ipv6_lpm_128b_enable=0 +# +# ALPM enable +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l2_mem_entries=32768 +l3_mem_entries=16384 + +# From old config file +os=unix +higig2_hdr_mode=1 + +# Parity +parity_correction=1 +parity_enable=1 +stat_if_parity_enable=0 + +# l2 thread related config vars +l2xmsg_hostbuf_size=8192 +l2xmsg_mode=1 + +bcm_num_cos=8 +bcm_stat_interval=2000000 +lls_num_l2uc=12 +max_vp_lags=0 +miim_intr_enable=0 +mmu_lossless=0 +module_64ports=0 +schan_intr_enable=0 +stable_size=0x2000000 +tdma_timeout_usec=5000000 + +# for GLC transceiver +phy_an_c73=0x0 +phy_an_c37=0x3 + +########################### +#port_init_speed_xe=40000 +#port_init_speed_xe.0=40000 + +#load_firmware=0x0102 +load_firmware.0=2 + +######################### +# All ports are in oversubscription mode +pbmp_oversubscribe=0x1fffffffffffffffffffffffffe +pbmp_xport_xe.0=0x1fffffffe + +phy_84328_1.0=1 +phy_84328_2.0=1 +phy_84328_29.0=1 +phy_84328_3.0=1 +phy_84328_30.0=1 +phy_84328_31.0=1 +phy_84328_32.0=1 +phy_84328_4.0=1 +phy_an_c37_1.0=3 +phy_an_c37_10.0=3 +phy_an_c37_11.0=3 +phy_an_c37_12.0=3 +phy_an_c37_13.0=3 +phy_an_c37_14.0=3 +phy_an_c37_15.0=3 +phy_an_c37_16.0=3 +phy_an_c37_17.0=3 +phy_an_c37_18.0=3 +phy_an_c37_19.0=3 +phy_an_c37_2.0=3 +phy_an_c37_20.0=3 +phy_an_c37_21.0=3 +phy_an_c37_22.0=3 +phy_an_c37_23.0=3 +phy_an_c37_24.0=3 +phy_an_c37_25.0=3 +phy_an_c37_26.0=3 +phy_an_c37_27.0=3 +phy_an_c37_28.0=3 +phy_an_c37_29.0=3 +phy_an_c37_3.0=3 +phy_an_c37_30.0=3 +phy_an_c37_31.0=3 +phy_an_c37_32.0=3 +phy_an_c37_4.0=3 +phy_an_c37_5.0=3 +phy_an_c37_6.0=3 +phy_an_c37_7.0=3 +phy_an_c37_8.0=3 +phy_an_c37_9.0=3 +phy_an_c73_1.0=1 +phy_an_c73_10.0=1 +phy_an_c73_11.0=1 +phy_an_c73_12.0=1 +phy_an_c73_13.0=1 +phy_an_c73_14.0=1 +phy_an_c73_15.0=1 +phy_an_c73_16.0=1 +phy_an_c73_17.0=1 +phy_an_c73_18.0=1 +phy_an_c73_19.0=1 +phy_an_c73_2.0=1 +phy_an_c73_20.0=1 +phy_an_c73_21.0=1 +phy_an_c73_22.0=1 +phy_an_c73_23.0=1 +phy_an_c73_24.0=1 +phy_an_c73_25.0=1 +phy_an_c73_26.0=1 +phy_an_c73_27.0=1 +phy_an_c73_28.0=1 +phy_an_c73_29.0=1 +phy_an_c73_3.0=1 +phy_an_c73_30.0=1 +phy_an_c73_31.0=1 +phy_an_c73_32.0=1 +phy_an_c73_4.0=1 +phy_an_c73_5.0=1 +phy_an_c73_6.0=1 +phy_an_c73_7.0=1 +phy_an_c73_8.0=1 +phy_an_c73_9.0=1 +phy_aux_voltage_enable_1.0=0x1 +phy_aux_voltage_enable_2.0=0x1 +phy_aux_voltage_enable_29.0=0x1 +phy_aux_voltage_enable_3.0=0x1 +phy_aux_voltage_enable_30.0=0x1 +phy_aux_voltage_enable_31.0=0x1 +phy_aux_voltage_enable_32.0=0x1 +phy_aux_voltage_enable_4.0=0x1 +phy_ext_rom_boot.0=0 +phy_ext_rom_boot_1.0=0x0 +phy_ext_rom_boot_2.0=0x0 +phy_ext_rom_boot_29.0=0x0 +phy_ext_rom_boot_3.0=0x0 +phy_ext_rom_boot_30.0=0x0 +phy_ext_rom_boot_31.0=0x0 +phy_ext_rom_boot_32.0=0x0 +phy_ext_rom_boot_4.0=0x0 +phy_line_tx_mode_1.0=1 +phy_line_tx_mode_2.0=1 +phy_line_tx_mode_29.0=1 +phy_line_tx_mode_3.0=1 +phy_line_tx_mode_30.0=1 +phy_line_tx_mode_31.0=1 +phy_line_tx_mode_32.0=1 +phy_line_tx_mode_4.0=1 +phy_rx_polarity_flip_1.0=0x0 +phy_rx_polarity_flip_2.0=0x0 +phy_rx_polarity_flip_29.0=0x0 +phy_rx_polarity_flip_3.0=0x0 +phy_rx_polarity_flip_30.0=0x0 +phy_rx_polarity_flip_31.0=0x0 +phy_rx_polarity_flip_32.0=0x0 +phy_rx_polarity_flip_4.0=0x0 +phy_system_tx_mode_1.0=0 +phy_system_tx_mode_2.0=0 +phy_system_tx_mode_29.0=0 +phy_system_tx_mode_3.0=0 +phy_system_tx_mode_30.0=0 +phy_system_tx_mode_31.0=0 +phy_system_tx_mode_32.0=0 +phy_system_tx_mode_4.0=0 +phy_tx_polarity_flip_1.0=0x0 +phy_tx_polarity_flip_2.0=0x0 +phy_tx_polarity_flip_29.0=0x0 +phy_tx_polarity_flip_3.0=0x0 +phy_tx_polarity_flip_30.0=0x0 +phy_tx_polarity_flip_31.0=0x0 +phy_tx_polarity_flip_32.0=0x0 +phy_tx_polarity_flip_4.0=0x0 +phy_xaui_rx_polarity_flip_1.0=0x0 +phy_xaui_rx_polarity_flip_10.0=0x0 +phy_xaui_rx_polarity_flip_11.0=0x0 +phy_xaui_rx_polarity_flip_12.0=0x0 +phy_xaui_rx_polarity_flip_13.0=0x0 +phy_xaui_rx_polarity_flip_14.0=0x0 +phy_xaui_rx_polarity_flip_15.0=0x0 +phy_xaui_rx_polarity_flip_16.0=0x0 +phy_xaui_rx_polarity_flip_17.0=0x0 +phy_xaui_rx_polarity_flip_18.0=0x0 +phy_xaui_rx_polarity_flip_19.0=0x0 +phy_xaui_rx_polarity_flip_2.0=0x0 +phy_xaui_rx_polarity_flip_20.0=0x0 +phy_xaui_rx_polarity_flip_21.0=0x0 +phy_xaui_rx_polarity_flip_22.0=0x0 +phy_xaui_rx_polarity_flip_23.0=0x0 +phy_xaui_rx_polarity_flip_24.0=0x0 +phy_xaui_rx_polarity_flip_25.0=0x0 +phy_xaui_rx_polarity_flip_26.0=0x0 +phy_xaui_rx_polarity_flip_27.0=0x0 +phy_xaui_rx_polarity_flip_28.0=0x0 +phy_xaui_rx_polarity_flip_29.0=0x0 +phy_xaui_rx_polarity_flip_3.0=0x0 +phy_xaui_rx_polarity_flip_30.0=0x0 +phy_xaui_rx_polarity_flip_31.0=0x0 +phy_xaui_rx_polarity_flip_32.0=0x0 +phy_xaui_rx_polarity_flip_4.0=0x0 +phy_xaui_rx_polarity_flip_5.0=0x0 +phy_xaui_rx_polarity_flip_6.0=0x0 +phy_xaui_rx_polarity_flip_7.0=0x0 +phy_xaui_rx_polarity_flip_8.0=0x0 +phy_xaui_rx_polarity_flip_9.0=0x0 +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_10.0=0x0 +phy_xaui_tx_polarity_flip_11.0=0x0 +phy_xaui_tx_polarity_flip_12.0=0x0 +phy_xaui_tx_polarity_flip_13.0=0x0 +phy_xaui_tx_polarity_flip_14.0=0x0 +phy_xaui_tx_polarity_flip_15.0=0x0 +phy_xaui_tx_polarity_flip_16.0=0x0 +phy_xaui_tx_polarity_flip_17.0=0x0 +phy_xaui_tx_polarity_flip_18.0=0x0 +phy_xaui_tx_polarity_flip_19.0=0x0 +phy_xaui_tx_polarity_flip_2.0=0x0 +phy_xaui_tx_polarity_flip_20.0=0x0 +phy_xaui_tx_polarity_flip_21.0=0x0 +phy_xaui_tx_polarity_flip_22.0=0x0 +phy_xaui_tx_polarity_flip_23.0=0x0 +phy_xaui_tx_polarity_flip_24.0=0x0 +phy_xaui_tx_polarity_flip_25.0=0x0 +phy_xaui_tx_polarity_flip_26.0=0x0 +phy_xaui_tx_polarity_flip_27.0=0x0 +phy_xaui_tx_polarity_flip_28.0=0x0 +phy_xaui_tx_polarity_flip_29.0=0x0 +phy_xaui_tx_polarity_flip_3.0=0x0 +phy_xaui_tx_polarity_flip_30.0=0x0 +phy_xaui_tx_polarity_flip_31.0=0x0 +phy_xaui_tx_polarity_flip_32.0=0x0 +phy_xaui_tx_polarity_flip_4.0=0x0 +phy_xaui_tx_polarity_flip_5.0=0x0 +phy_xaui_tx_polarity_flip_6.0=0x0 +phy_xaui_tx_polarity_flip_7.0=0x0 +phy_xaui_tx_polarity_flip_8.0=0x0 +phy_xaui_tx_polarity_flip_9.0=0x0 +port_init_autoneg_10.0=0 +port_init_autoneg_11.0=0 +port_init_autoneg_12.0=0 +port_init_autoneg_13.0=0 +port_init_autoneg_14.0=0 +port_init_autoneg_15.0=0 +port_init_autoneg_16.0=0 +port_init_autoneg_17.0=0 +port_init_autoneg_18.0=0 +port_init_autoneg_19.0=0 +port_init_autoneg_20.0=0 +port_init_autoneg_21.0=0 +port_init_autoneg_22.0=0 +port_init_autoneg_23.0=0 +port_init_autoneg_24.0=0 +port_init_autoneg_25.0=0 +port_init_autoneg_26.0=0 +port_init_autoneg_27.0=0 +port_init_autoneg_28.0=0 +port_init_autoneg_5.0=0 +port_init_autoneg_6.0=0 +port_init_autoneg_7.0=0 +port_init_autoneg_8.0=0 +port_init_autoneg_9.0=0 +port_init_cl72_hg.0=0x11 +port_phy_addr_1.0=0x4 +port_phy_addr_10.0=0x7f +port_phy_addr_11.0=0x7f +port_phy_addr_12.0=0x7f +port_phy_addr_13.0=0x7f +port_phy_addr_14.0=0x7f +port_phy_addr_15.0=0x7f +port_phy_addr_16.0=0x7f +port_phy_addr_17.0=0x7f +port_phy_addr_18.0=0x7f +port_phy_addr_19.0=0x7f +port_phy_addr_2.0=0x0 +port_phy_addr_20.0=0x7f +port_phy_addr_21.0=0x7f +port_phy_addr_22.0=0x7f +port_phy_addr_23.0=0x7f +port_phy_addr_24.0=0x7f +port_phy_addr_25.0=0x7f +port_phy_addr_26.0=0x7f +port_phy_addr_27.0=0x7f +port_phy_addr_28.0=0x7f +port_phy_addr_29.0=0x54 +port_phy_addr_3.0=0x2c +port_phy_addr_30.0=0x50 +port_phy_addr_31.0=0x7c +port_phy_addr_32.0=0x78 +port_phy_addr_4.0=0x28 +port_phy_addr_5.0=0x7f +port_phy_addr_6.0=0x7f +port_phy_addr_7.0=0x7f +port_phy_addr_8.0=0x7f +port_phy_addr_9.0=0x7f +port_phy_clause_1.0=0x2d +port_phy_clause_2.0=0x2d +port_phy_clause_29.0=0x2d +port_phy_clause_3.0=0x2d +port_phy_clause_30.0=0x2d +port_phy_clause_31.0=0x2d +port_phy_clause_32.0=0x2d +port_phy_clause_4.0=0x2d +port_phy_id0_1.0=0x600d +port_phy_id0_2.0=0x600d +port_phy_id0_29.0=0x600d +port_phy_id0_3.0=0x600d +port_phy_id0_30.0=0x600d +port_phy_id0_31.0=0x600d +port_phy_id0_32.0=0x600d +port_phy_id0_4.0=0x600d +port_phy_id1_1.0=0x8500 +port_phy_id1_2.0=0x8500 +port_phy_id1_29.0=0x8500 +port_phy_id1_3.0=0x8500 +port_phy_id1_30.0=0x8500 +port_phy_id1_31.0=0x8500 +port_phy_id1_32.0=0x8500 +port_phy_id1_4.0=0x8500 +portmap_1.0=125:40 +portmap_10.0=33:40 +portmap_11.0=45:40 +portmap_12.0=41:40 +portmap_13.0=53:40 +portmap_14.0=49:40 +portmap_15.0=69:40 +portmap_16.0=65:40 +portmap_17.0=77:40 +portmap_18.0=73:40 +portmap_19.0=93:40 +portmap_2.0=121:40 +portmap_20.0=89:40 +portmap_21.0=101:40 +portmap_22.0=97:40 +portmap_23.0=109:40 +portmap_24.0=105:40 +portmap_25.0=61:40 +portmap_26.0=57:40 +portmap_27.0=81:40 +portmap_28.0=85:40 +portmap_29.0=117:40 +portmap_3.0=13:40 +portmap_30.0=113:40 +portmap_31.0=5:40 +portmap_32.0=1:40 +portmap_4.0=9:40 +portmap_5.0=17:40 +portmap_6.0=21:40 +portmap_7.0=25:40 +portmap_8.0=29:40 +portmap_9.0=37:40 +serdes_firmware_mode_1.0=1 +serdes_firmware_mode_10.0=2 +serdes_firmware_mode_11.0=2 +serdes_firmware_mode_12.0=2 +serdes_firmware_mode_13.0=2 +serdes_firmware_mode_14.0=2 +serdes_firmware_mode_15.0=2 +serdes_firmware_mode_16.0=2 +serdes_firmware_mode_17.0=2 +serdes_firmware_mode_18.0=2 +serdes_firmware_mode_19.0=2 +serdes_firmware_mode_2.0=1 +serdes_firmware_mode_20.0=2 +serdes_firmware_mode_21.0=2 +serdes_firmware_mode_22.0=2 +serdes_firmware_mode_23.0=2 +serdes_firmware_mode_24.0=2 +serdes_firmware_mode_25.0=2 +serdes_firmware_mode_26.0=2 +serdes_firmware_mode_27.0=2 +serdes_firmware_mode_28.0=2 +serdes_firmware_mode_29.0=1 +serdes_firmware_mode_3.0=1 +serdes_firmware_mode_30.0=1 +serdes_firmware_mode_31.0=1 +serdes_firmware_mode_32.0=1 +serdes_firmware_mode_4.0=1 +serdes_firmware_mode_5.0=2 +serdes_firmware_mode_6.0=2 +serdes_firmware_mode_7.0=2 +serdes_firmware_mode_8.0=2 +serdes_firmware_mode_9.0=2 +xgxs_lcpll_xtal_refclk.0=1 +xgxs_rx_lane_map_1.0=0x0123 +xgxs_rx_lane_map_10.0=0x3120 +xgxs_rx_lane_map_11.0=0x3120 +xgxs_rx_lane_map_12.0=0x3120 +xgxs_rx_lane_map_13.0=0x3120 +xgxs_rx_lane_map_14.0=0x3120 +xgxs_rx_lane_map_15.0=0x3120 +xgxs_rx_lane_map_16.0=0x3120 +xgxs_rx_lane_map_17.0=0x3120 +xgxs_rx_lane_map_18.0=0x3120 +xgxs_rx_lane_map_19.0=0x3120 +xgxs_rx_lane_map_2.0=0x0123 +xgxs_rx_lane_map_20.0=0x3120 +xgxs_rx_lane_map_21.0=0x3120 +xgxs_rx_lane_map_22.0=0x3120 +xgxs_rx_lane_map_23.0=0x3120 +xgxs_rx_lane_map_24.0=0x3120 +xgxs_rx_lane_map_25.0=0x2031 +xgxs_rx_lane_map_26.0=0x2031 +xgxs_rx_lane_map_27.0=0x0213 +xgxs_rx_lane_map_28.0=0x0213 +xgxs_rx_lane_map_29.0=0x0123 +xgxs_rx_lane_map_3.0=0x0123 +xgxs_rx_lane_map_30.0=0x0123 +xgxs_rx_lane_map_31.0=0x0123 +xgxs_rx_lane_map_32.0=0x0123 +xgxs_rx_lane_map_4.0=0x0123 +xgxs_rx_lane_map_5.0=0x2031 +xgxs_rx_lane_map_6.0=0x2031 +xgxs_rx_lane_map_7.0=0x2031 +xgxs_rx_lane_map_8.0=0x2031 +xgxs_rx_lane_map_9.0=0x3120 +xgxs_tx_lane_map_1.0=0x0123 +xgxs_tx_lane_map_10.0=0x3120 +xgxs_tx_lane_map_11.0=0x3120 +xgxs_tx_lane_map_12.0=0x3120 +xgxs_tx_lane_map_13.0=0x3120 +xgxs_tx_lane_map_14.0=0x3120 +xgxs_tx_lane_map_15.0=0x3120 +xgxs_tx_lane_map_16.0=0x3120 +xgxs_tx_lane_map_17.0=0x3120 +xgxs_tx_lane_map_18.0=0x3120 +xgxs_tx_lane_map_19.0=0x3120 +xgxs_tx_lane_map_2.0=0x0123 +xgxs_tx_lane_map_20.0=0x3120 +xgxs_tx_lane_map_21.0=0x3120 +xgxs_tx_lane_map_22.0=0x3120 +xgxs_tx_lane_map_23.0=0x3120 +xgxs_tx_lane_map_24.0=0x3120 +xgxs_tx_lane_map_25.0=0x2031 +xgxs_tx_lane_map_26.0=0x2031 +xgxs_tx_lane_map_27.0=0x0213 +xgxs_tx_lane_map_28.0=0x0213 +xgxs_tx_lane_map_29.0=0x0123 +xgxs_tx_lane_map_3.0=0x0123 +xgxs_tx_lane_map_30.0=0x0123 +xgxs_tx_lane_map_31.0=0x0123 +xgxs_tx_lane_map_32.0=0x0123 +xgxs_tx_lane_map_4.0=0x0123 +xgxs_tx_lane_map_5.0=0x1302 +xgxs_tx_lane_map_6.0=0x1302 +xgxs_tx_lane_map_7.0=0x1302 +xgxs_tx_lane_map_8.0=0x1302 +xgxs_tx_lane_map_9.0=0x3120 + +########################################## +#skip_L2_USER_ENTRY=0 +phy_aux_voltage_enable=1 +############################### +serdes_fiber_pref=1 +############################### +mdio_output_delay.0=0x0d +############################### +serdes_sgmii_m=0 +xgxs_lcpll_xtal_refclk=1 +xgxs_lcpll_xtal_refclk.1=1 +xgxs_lcpll_xtal_refclk.2=1 +xgxs_lcpll_xtal_refclk.3=1 +tdma_intr_enable=1 +tslam_intr_enable=1 +tslam_dma_enable.2=1 +tslam_dma_enable.3=1 +#dport_map_port=0 +#dport_map_enable=0 +#dport_map_indexed=0 +#bcm_xlate_port_enable.0=0 +#xgxs_pdetect_1=0 +table_dma_enable.0=1 +table_dma_enable.1=1 +table_dma_enable.2=1 +table_dma_enable.3=1 +serdes_driver_current_lane0_1=2 +serdes_pre_driver_current_lane0_1=2 +serdes_preemphasis_lane0_1=0x8fc0 +serdes_driver_current_lane1_1=2 +serdes_pre_driver_current_lane1_1=2 +serdes_preemphasis_lane1_1=0x8fc0 +serdes_driver_current_lane2_1=2 +serdes_pre_driver_current_lane2_1=2 +serdes_preemphasis_lane2_1=0x8fc0 +serdes_driver_current_lane3_1=2 +serdes_pre_driver_current_lane3_1=2 +serdes_preemphasis_lane3_1=0x8fc0 +serdes_driver_current_lane0_2=3 +serdes_pre_driver_current_lane0_2=2 +serdes_preemphasis_lane0_2=0x8fc0 +serdes_driver_current_lane1_2=3 +serdes_pre_driver_current_lane1_2=2 +serdes_preemphasis_lane1_2=0x8fc0 +serdes_driver_current_lane2_2=3 +serdes_pre_driver_current_lane2_2=2 +serdes_preemphasis_lane2_2=0x8fc0 +serdes_driver_current_lane3_2=3 +serdes_pre_driver_current_lane3_2=2 +serdes_preemphasis_lane3_2=0x8fc0 +serdes_driver_current_lane0_3=2 +serdes_pre_driver_current_lane0_3=2 +serdes_preemphasis_lane0_3=0x8fc0 +serdes_driver_current_lane1_3=2 +serdes_pre_driver_current_lane1_3=2 +serdes_preemphasis_lane1_3=0x8fc0 +serdes_driver_current_lane2_3=2 +serdes_pre_driver_current_lane2_3=2 +serdes_preemphasis_lane2_3=0x8fc0 +serdes_driver_current_lane3_3=2 +serdes_pre_driver_current_lane3_3=2 +serdes_preemphasis_lane3_3=0x8fc0 +serdes_driver_current_lane0_4=2 +serdes_pre_driver_current_lane0_4=2 +serdes_preemphasis_lane0_4=0x8fc0 +serdes_driver_current_lane1_4=2 +serdes_pre_driver_current_lane1_4=2 +serdes_preemphasis_lane1_4=0x8fc0 +serdes_driver_current_lane2_4=2 +serdes_pre_driver_current_lane2_4=2 +serdes_preemphasis_lane2_4=0x8fc0 +serdes_driver_current_lane3_4=2 +serdes_pre_driver_current_lane3_4=2 +serdes_preemphasis_lane3_4=0x8fc0 +serdes_driver_current_lane0_5=4 +serdes_pre_driver_current_lane0_5=4 +serdes_preemphasis_lane0_5=0xbf00 +serdes_driver_current_lane1_5=4 +serdes_pre_driver_current_lane1_5=4 +serdes_preemphasis_lane1_5=0xbf00 +serdes_driver_current_lane2_5=4 +serdes_pre_driver_current_lane2_5=4 +serdes_preemphasis_lane2_5=0xbf00 +serdes_driver_current_lane3_5=4 +serdes_pre_driver_current_lane3_5=4 +serdes_preemphasis_lane3_5=0xbf00 +serdes_driver_current_lane0_6=4 +serdes_pre_driver_current_lane0_6=4 +serdes_preemphasis_lane0_6=0xbb10 +serdes_driver_current_lane1_6=4 +serdes_pre_driver_current_lane1_6=4 +serdes_preemphasis_lane1_6=0xbb10 +serdes_driver_current_lane2_6=4 +serdes_pre_driver_current_lane2_6=4 +serdes_preemphasis_lane2_6=0xbb10 +serdes_driver_current_lane3_6=4 +serdes_pre_driver_current_lane3_6=4 +serdes_preemphasis_lane3_6=0xbb10 +serdes_driver_current_lane0_7=3 +serdes_pre_driver_current_lane0_7=3 +serdes_preemphasis_lane0_7=0xcad0 +serdes_driver_current_lane1_7=3 +serdes_pre_driver_current_lane1_7=3 +serdes_preemphasis_lane1_7=0xcad0 +serdes_driver_current_lane2_7=3 +serdes_pre_driver_current_lane2_7=3 +serdes_preemphasis_lane2_7=0xcad0 +serdes_driver_current_lane3_7=3 +serdes_pre_driver_current_lane3_7=3 +serdes_preemphasis_lane3_7=0xcad0 +serdes_driver_current_lane0_8=3 +serdes_pre_driver_current_lane0_8=3 +serdes_preemphasis_lane0_8=0xcad0 +serdes_driver_current_lane1_8=3 +serdes_pre_driver_current_lane1_8=3 +serdes_preemphasis_lane1_8=0xcad0 +serdes_driver_current_lane2_8=3 +serdes_pre_driver_current_lane2_8=3 +serdes_preemphasis_lane2_8=0xcad0 +serdes_driver_current_lane3_8=3 +serdes_pre_driver_current_lane3_8=3 +serdes_preemphasis_lane3_8=0xcad0 +serdes_driver_current_lane0_9=3 +serdes_pre_driver_current_lane0_9=3 +serdes_preemphasis_lane0_9=0xc2f0 +serdes_driver_current_lane1_9=3 +serdes_pre_driver_current_lane1_9=3 +serdes_preemphasis_lane1_9=0xc2f0 +serdes_driver_current_lane2_9=3 +serdes_pre_driver_current_lane2_9=3 +serdes_preemphasis_lane2_9=0xc2f0 +serdes_driver_current_lane3_9=3 +serdes_pre_driver_current_lane3_9=3 +serdes_preemphasis_lane3_9=0xc2f0 +serdes_driver_current_lane0_10=3 +serdes_pre_driver_current_lane0_10=3 +serdes_preemphasis_lane0_10=0xc6e0 +serdes_driver_current_lane1_10=3 +serdes_pre_driver_current_lane1_10=3 +serdes_preemphasis_lane1_10=0xc6e0 +serdes_driver_current_lane2_10=3 +serdes_pre_driver_current_lane2_10=3 +serdes_preemphasis_lane2_10=0xc6e0 +serdes_driver_current_lane3_10=3 +serdes_pre_driver_current_lane3_10=3 +serdes_preemphasis_lane3_10=0xc6e0 +serdes_driver_current_lane0_11=3 +serdes_pre_driver_current_lane0_11=3 +serdes_preemphasis_lane0_11=0xc2f0 +serdes_driver_current_lane1_11=3 +serdes_pre_driver_current_lane1_11=3 +serdes_preemphasis_lane1_11=0xc2f0 +serdes_driver_current_lane2_11=3 +serdes_pre_driver_current_lane2_11=3 +serdes_preemphasis_lane2_11=0xc2f0 +serdes_driver_current_lane3_11=3 +serdes_pre_driver_current_lane3_11=3 +serdes_preemphasis_lane3_11=0xc2f0 +serdes_driver_current_lane0_12=3 +serdes_pre_driver_current_lane0_12=3 +serdes_preemphasis_lane0_12=0xc2f0 +serdes_driver_current_lane1_12=3 +serdes_pre_driver_current_lane1_12=3 +serdes_preemphasis_lane1_12=0xc2f0 +serdes_driver_current_lane2_12=3 +serdes_pre_driver_current_lane2_12=3 +serdes_preemphasis_lane2_12=0xc2f0 +serdes_driver_current_lane3_12=3 +serdes_pre_driver_current_lane3_12=3 +serdes_preemphasis_lane3_12=0xc2f0 +serdes_driver_current_lane0_13=3 +serdes_pre_driver_current_lane0_13=3 +serdes_preemphasis_lane0_13=0xc2f0 +serdes_driver_current_lane1_13=3 +serdes_pre_driver_current_lane1_13=3 +serdes_preemphasis_lane1_13=0xc2f0 +serdes_driver_current_lane2_13=3 +serdes_pre_driver_current_lane2_13=3 +serdes_preemphasis_lane2_13=0xc2f0 +serdes_driver_current_lane3_13=3 +serdes_pre_driver_current_lane3_13=3 +serdes_preemphasis_lane3_13=0xc2f0 +serdes_driver_current_lane0_14=3 +serdes_pre_driver_current_lane0_14=3 +serdes_preemphasis_lane0_14=0xc2f0 +serdes_driver_current_lane1_14=3 +serdes_pre_driver_current_lane1_14=3 +serdes_preemphasis_lane1_14=0xc2f0 +serdes_driver_current_lane2_14=3 +serdes_pre_driver_current_lane2_14=3 +serdes_preemphasis_lane2_14=0xc2f0 +serdes_driver_current_lane3_14=3 +serdes_pre_driver_current_lane3_14=3 +serdes_preemphasis_lane3_14=0xc2f0 +serdes_driver_current_lane0_15=3 +serdes_pre_driver_current_lane0_15=3 +serdes_preemphasis_lane0_15=0xc2f0 +serdes_driver_current_lane1_15=3 +serdes_pre_driver_current_lane1_15=3 +serdes_preemphasis_lane1_15=0xc2f0 +serdes_driver_current_lane2_15=3 +serdes_pre_driver_current_lane2_15=3 +serdes_preemphasis_lane2_15=0xc2f0 +serdes_driver_current_lane3_15=3 +serdes_pre_driver_current_lane3_15=3 +serdes_preemphasis_lane3_15=0xc2f0 +serdes_driver_current_lane0_16=3 +serdes_pre_driver_current_lane0_16=3 +serdes_preemphasis_lane0_16=0xc2f0 +serdes_driver_current_lane1_16=3 +serdes_pre_driver_current_lane1_16=3 +serdes_preemphasis_lane1_16=0xc2f0 +serdes_driver_current_lane2_16=3 +serdes_pre_driver_current_lane2_16=3 +serdes_preemphasis_lane2_16=0xc2f0 +serdes_driver_current_lane3_16=3 +serdes_pre_driver_current_lane3_16=3 +serdes_preemphasis_lane3_16=0xc2f0 +serdes_driver_current_lane0_17=3 +serdes_pre_driver_current_lane0_17=3 +serdes_preemphasis_lane0_17=0xc2f0 +serdes_driver_current_lane1_17=3 +serdes_pre_driver_current_lane1_17=3 +serdes_preemphasis_lane1_17=0xc2f0 +serdes_driver_current_lane2_17=3 +serdes_pre_driver_current_lane2_17=3 +serdes_preemphasis_lane2_17=0xc2f0 +serdes_driver_current_lane3_17=3 +serdes_pre_driver_current_lane3_17=3 +serdes_preemphasis_lane3_17=0xc2f0 +serdes_driver_current_lane0_18=3 +serdes_pre_driver_current_lane0_18=3 +serdes_preemphasis_lane0_18=0xc2f0 +serdes_driver_current_lane1_18=3 +serdes_pre_driver_current_lane1_18=3 +serdes_preemphasis_lane1_18=0xc2f0 +serdes_driver_current_lane2_18=3 +serdes_pre_driver_current_lane2_18=3 +serdes_preemphasis_lane2_18=0xc2f0 +serdes_driver_current_lane3_18=3 +serdes_pre_driver_current_lane3_18=3 +serdes_preemphasis_lane3_18=0xc2f0 +serdes_driver_current_lane0_19=3 +serdes_pre_driver_current_lane0_19=3 +serdes_preemphasis_lane0_19=0xc2f0 +serdes_driver_current_lane1_19=3 +serdes_pre_driver_current_lane1_19=3 +serdes_preemphasis_lane1_19=0xc2f0 +serdes_driver_current_lane2_19=3 +serdes_pre_driver_current_lane2_19=3 +serdes_preemphasis_lane2_19=0xc2f0 +serdes_driver_current_lane3_19=3 +serdes_pre_driver_current_lane3_19=3 +serdes_preemphasis_lane3_19=0xc2f0 +serdes_driver_current_lane0_20=3 +serdes_pre_driver_current_lane0_20=3 +serdes_preemphasis_lane0_20=0xc2f0 +serdes_driver_current_lane1_20=3 +serdes_pre_driver_current_lane1_20=3 +serdes_preemphasis_lane1_20=0xc2f0 +serdes_driver_current_lane2_20=3 +serdes_pre_driver_current_lane2_20=3 +serdes_preemphasis_lane2_20=0xc2f0 +serdes_driver_current_lane3_20=3 +serdes_pre_driver_current_lane3_20=3 +serdes_preemphasis_lane3_20=0xc2f0 +serdes_driver_current_lane0_21=3 +serdes_pre_driver_current_lane0_21=3 +serdes_preemphasis_lane0_21=0xc6e0 +serdes_driver_current_lane1_21=3 +serdes_pre_driver_current_lane1_21=3 +serdes_preemphasis_lane1_21=0xc6e0 +serdes_driver_current_lane2_21=3 +serdes_pre_driver_current_lane2_21=3 +serdes_preemphasis_lane2_21=0xc6e0 +serdes_driver_current_lane3_21=3 +serdes_pre_driver_current_lane3_21=3 +serdes_preemphasis_lane3_21=0xc6e0 +serdes_driver_current_lane0_22=3 +serdes_pre_driver_current_lane0_22=3 +serdes_preemphasis_lane0_22=0xc6e0 +serdes_driver_current_lane1_22=3 +serdes_pre_driver_current_lane1_22=3 +serdes_preemphasis_lane1_22=0xc6e0 +serdes_driver_current_lane2_22=3 +serdes_pre_driver_current_lane2_22=3 +serdes_preemphasis_lane2_22=0xc6e0 +serdes_driver_current_lane3_22=3 +serdes_pre_driver_current_lane3_22=3 +serdes_preemphasis_lane3_22=0xc6e0 +serdes_driver_current_lane0_23=3 +serdes_pre_driver_current_lane0_23=3 +serdes_preemphasis_lane0_23=0xcad0 +serdes_driver_current_lane1_23=3 +serdes_pre_driver_current_lane1_23=3 +serdes_preemphasis_lane1_23=0xcad0 +serdes_driver_current_lane2_23=3 +serdes_pre_driver_current_lane2_23=3 +serdes_preemphasis_lane2_23=0xcad0 +serdes_driver_current_lane3_23=3 +serdes_pre_driver_current_lane3_23=3 +serdes_preemphasis_lane3_23=0xcad0 +serdes_driver_current_lane0_24=3 +serdes_pre_driver_current_lane0_24=3 +serdes_preemphasis_lane0_24=0xcad0 +serdes_driver_current_lane1_24=3 +serdes_pre_driver_current_lane1_24=3 +serdes_preemphasis_lane1_24=0xcad0 +serdes_driver_current_lane2_24=3 +serdes_pre_driver_current_lane2_24=3 +serdes_preemphasis_lane2_24=0xcad0 +serdes_driver_current_lane3_24=3 +serdes_pre_driver_current_lane3_24=3 +serdes_preemphasis_lane3_24=0xcad0 +serdes_driver_current_lane0_25=5 +serdes_pre_driver_current_lane0_25=5 +serdes_preemphasis_lane0_25=0xc2f0 +serdes_driver_current_lane1_25=5 +serdes_pre_driver_current_lane1_25=5 +serdes_preemphasis_lane1_25=0xc2f0 +serdes_driver_current_lane2_25=5 +serdes_pre_driver_current_lane2_25=5 +serdes_preemphasis_lane2_25=0xc2f0 +serdes_driver_current_lane3_25=5 +serdes_pre_driver_current_lane3_25=5 +serdes_preemphasis_lane3_25=0xc2f0 +serdes_driver_current_lane0_26=5 +serdes_pre_driver_current_lane0_26=5 +serdes_preemphasis_lane0_26=0xc2f0 +serdes_driver_current_lane1_26=5 +serdes_pre_driver_current_lane1_26=5 +serdes_preemphasis_lane1_26=0xc2f0 +serdes_driver_current_lane2_26=5 +serdes_pre_driver_current_lane2_26=5 +serdes_preemphasis_lane2_26=0xc2f0 +serdes_driver_current_lane3_26=5 +serdes_pre_driver_current_lane3_26=5 +serdes_preemphasis_lane3_26=0xc2f0 +serdes_driver_current_lane0_27=5 +serdes_pre_driver_current_lane0_27=5 +serdes_preemphasis_lane0_27=0xc2f0 +serdes_driver_current_lane1_27=5 +serdes_pre_driver_current_lane1_27=5 +serdes_preemphasis_lane1_27=0xc2f0 +serdes_driver_current_lane2_27=5 +serdes_pre_driver_current_lane2_27=5 +serdes_preemphasis_lane2_27=0xc2f0 +serdes_driver_current_lane3_27=5 +serdes_pre_driver_current_lane3_27=5 +serdes_preemphasis_lane3_27=0xc2f0 +serdes_driver_current_lane0_28=8 +serdes_pre_driver_current_lane0_28=6 +serdes_preemphasis_lane0_28=0xc2f0 +serdes_driver_current_lane1_28=8 +serdes_pre_driver_current_lane1_28=6 +serdes_preemphasis_lane1_28=0xc2f0 +serdes_driver_current_lane2_28=8 +serdes_pre_driver_current_lane2_28=6 +serdes_preemphasis_lane2_28=0xc2f0 +serdes_driver_current_lane3_28=8 +serdes_pre_driver_current_lane3_28=6 +serdes_preemphasis_lane3_28=0xc2f0 +serdes_driver_current_lane0_29=2 +serdes_pre_driver_current_lane0_29=2 +serdes_preemphasis_lane0_29=0x8fc0 +serdes_driver_current_lane1_29=2 +serdes_pre_driver_current_lane1_29=2 +serdes_preemphasis_lane1_29=0x8fc0 +serdes_driver_current_lane2_29=2 +serdes_pre_driver_current_lane2_29=2 +serdes_preemphasis_lane2_29=0x8fc0 +serdes_driver_current_lane3_29=2 +serdes_pre_driver_current_lane3_29=2 +serdes_preemphasis_lane3_29=0x8fc0 +serdes_driver_current_lane0_30=2 +serdes_pre_driver_current_lane0_30=2 +serdes_preemphasis_lane0_30=0x8fc0 +serdes_driver_current_lane1_30=2 +serdes_pre_driver_current_lane1_30=2 +serdes_preemphasis_lane1_30=0x8fc0 +serdes_driver_current_lane2_30=2 +serdes_pre_driver_current_lane2_30=2 +serdes_preemphasis_lane2_30=0x8fc0 +serdes_driver_current_lane3_30=2 +serdes_pre_driver_current_lane3_30=2 +serdes_preemphasis_lane3_30=0x8fc0 +serdes_driver_current_lane0_31=2 +serdes_pre_driver_current_lane0_31=2 +serdes_preemphasis_lane0_31=0x8fc0 +serdes_driver_current_lane1_31=2 +serdes_pre_driver_current_lane1_31=2 +serdes_preemphasis_lane1_31=0x8fc0 +serdes_driver_current_lane2_31=2 +serdes_pre_driver_current_lane2_31=2 +serdes_preemphasis_lane2_31=0x8fc0 +serdes_driver_current_lane3_31=2 +serdes_pre_driver_current_lane3_31=2 +serdes_preemphasis_lane3_31=0x8fc0 +serdes_driver_current_lane0_32=2 +serdes_pre_driver_current_lane0_32=2 +serdes_preemphasis_lane0_32=0x8fc0 +serdes_driver_current_lane1_32=2 +serdes_pre_driver_current_lane1_32=2 +serdes_preemphasis_lane1_32=0x8fc0 +serdes_driver_current_lane2_32=2 +serdes_pre_driver_current_lane2_32=2 +serdes_preemphasis_lane2_32=0x8fc0 +serdes_driver_current_lane3_32=2 +serdes_pre_driver_current_lane3_32=2 +serdes_preemphasis_lane3_32=0x8fc0 diff --git a/device/arista/x86_64-arista_7050_qx32/default_sku b/device/arista/x86_64-arista_7050_qx32/default_sku new file mode 100644 index 000000000000..8c19bef02a08 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/default_sku @@ -0,0 +1 @@ +Arista-7050-QX32 t1 diff --git a/device/arista/x86_64-arista_7050_qx32/fancontrol b/device/arista/x86_64-arista_7050_qx32/fancontrol new file mode 100644 index 000000000000..1d94fcf7674c --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=5 +DEVPATH=hwmon1=devices/platform/sb800-fans hwmon2=devices/pci0000:00/0000:00:09.0/0000:04:00.0/i2c-5/5-004c +DEVNAME=hwmon1=fans hwmon2=max6658 +FCTEMPS=hwmon1/pwm4=hwmon2/temp1_input hwmon1/pwm3=hwmon2/temp1_input hwmon1/pwm2=hwmon2/temp1_input hwmon1/pwm1=hwmon2/temp1_input +FCFANS=hwmon1/pwm4=hwmon1/fan4_input hwmon1/pwm3=hwmon1/fan3_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm1=hwmon1/fan1_input +MINTEMP=hwmon1/pwm4=30 hwmon1/pwm3=30 hwmon1/pwm2=30 hwmon1/pwm1=30 +MINPWM=hwmon1/pwm4=179 hwmon1/pwm3=179 hwmon1/pwm2=179 hwmon1/pwm1=179 +MAXTEMP=hwmon1/pwm4=40 hwmon1/pwm3=40 hwmon1/pwm2=40 hwmon1/pwm1=40 +MINSTART=hwmon1/pwm4=179 hwmon1/pwm3=179 hwmon1/pwm2=179 hwmon1/pwm1=179 +MINSTOP=hwmon1/pwm4=179 hwmon1/pwm3=179 hwmon1/pwm2=179 hwmon1/pwm1=179 diff --git a/device/arista/x86_64-arista_7050_qx32/platform_reboot b/device/arista/x86_64-arista_7050_qx32/platform_reboot new file mode 100755 index 000000000000..da438b8fe52b --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/platform_reboot @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# Copyright (c) 2018 Arista Networks, Inc. All rights reserved. +# Arista Networks, Inc. Confidential and Proprietary. + +# Reboot script for 7050QX-32 + +from __future__ import print_function +import sys +import mmap, os +import subprocess +from struct import pack, unpack + +class MmapResource( object ): + """Resource implementation for a directly-mapped memory region.""" + + def __init__( self, path ): + try: + fd = os.open( path, os.O_RDWR ) + except EnvironmentError: + print( "FAIL can not open scd memory-map resource file" ) + print( "FAIL are you running on the proper platform?" ) + sys.exit( 1 ) + try: + size = os.fstat( fd ).st_size + except EnvironmentError: + print( "FAIL can not fstat scd memory-map resource file" ) + print( "FAIL are you running on the proper platform?" ) + sys.exit( 1 ) + try: + self.mmap_ = mmap.mmap( fd, size, mmap.MAP_SHARED, + mmap.PROT_READ | mmap.PROT_WRITE ) + except EnvironmentError: + print( "FAIL can not map scd memory-map file" ) + print( "FAIL are you running on the proper platform?" ) + sys.exit( 1 ) + finally: + try: + # Note that closing the file descriptor has no effect on the memory map + os.close( fd ) + except EnvironmentError: + print( "FAIL failed to close scd memory-map file" ) + sys.exit( 1 ) + + def read32( self, addr ): + return unpack( ' /sys/devices/pci0000:00/0000:00:02.2/0000:02:00.0/mux diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/pg_profile_lookup.ini b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/pg_profile_lookup.ini new file mode 100644 index 000000000000..135a598465ba --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/pg_profile_lookup.ini @@ -0,0 +1,11 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 40000 5m 41808 18432 40560 -3 2496 + 50000 5m 41808 18432 40560 -3 2496 + 100000 5m 41808 18432 40560 -3 2496 + 40000 40m 51376 18432 50128 -3 2496 + 50000 40m 51376 18432 50128 -3 2496 + 100000 40m 51376 18432 50128 -3 2496 + 40000 300m 51376 18432 50128 -3 2496 + 50000 300m 51376 18432 50128 -3 2496 + 100000 300m 51376 18432 50128 -3 2496 diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/port_config.ini b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/port_config.ini new file mode 100644 index 000000000000..857b126bf833 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 9,10,11,12 Ethernet5/1 5 40000 +Ethernet4 13,14,15,16 Ethernet6/1 6 40000 +Ethernet8 17,18,19,20 Ethernet7/1 7 40000 +Ethernet12 21,22,23,24 Ethernet8/1 8 40000 +Ethernet16 29,30,31,32 Ethernet9/1 9 40000 +Ethernet20 25,26,27,28 Ethernet10/1 10 40000 +Ethernet24 33,34,35,36 Ethernet11/1 11 40000 +Ethernet28 37,38,39,40 Ethernet12/1 12 40000 +Ethernet32 45,46,47,48 Ethernet13/1 13 40000 +Ethernet36 41,42,43,44 Ethernet14/1 14 40000 +Ethernet40 49,50,51,52 Ethernet15/1 15 40000 +Ethernet44 53,54,55,56 Ethernet16/1 16 40000 +Ethernet48 69,70,71,72 Ethernet17/1 17 40000 +Ethernet52 65,66,67,68 Ethernet18/1 18 40000 +Ethernet56 73,74,75,76 Ethernet19/1 19 40000 +Ethernet60 77,78,79,80 Ethernet20/1 20 40000 +Ethernet64 93,94,95,96 Ethernet21/1 21 40000 +Ethernet68 89,90,91,92 Ethernet22/1 22 40000 +Ethernet72 97,98,99,100 Ethernet23/1 23 40000 +Ethernet76 101,102,103,104 Ethernet24/1 24 40000 +Ethernet80 109,110,111,112 Ethernet25/1 25 40000 +Ethernet84 105,106,107,108 Ethernet26/1 26 40000 +Ethernet88 121,122,123,124 Ethernet27/1 27 40000 +Ethernet92 125,126,127,128 Ethernet28/1 28 40000 +Ethernet96 61,62,63,64 Ethernet29 29 40000 +Ethernet100 57,58,59,60 Ethernet30 30 40000 +Ethernet104 81,82,83,84 Ethernet31 31 40000 +Ethernet108 85,86,87,88 Ethernet32 32 40000 +Ethernet112 117,118,119,120 Ethernet33 33 40000 +Ethernet116 113,114,115,116 Ethernet34 34 40000 +Ethernet120 1,2,3,4 Ethernet35 35 40000 +Ethernet124 5,6,7,8 Ethernet36 36 40000 diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/qos.json.j2 b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/sai.profile b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/sai.profile new file mode 100644 index 000000000000..6479c4c14d3f --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-a7050-qx32s-32x40G.config.bcm diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/td2-a7050-qx32s-32x40G.config.bcm b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/td2-a7050-qx32s-32x40G.config.bcm new file mode 100644 index 000000000000..3b1a4514409c --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/td2-a7050-qx32s-32x40G.config.bcm @@ -0,0 +1,744 @@ +#/****************************************************************************** +# * +# * File: config.bcm.clearlake (7050-QX32S) +# * Name: +# * +# * Description: This file contains SDK properties for an Arista +# * Clearlake platform. +# * +# *----------------------------------------------------------------------------- +# ******************************************************************************/ +#################################################################### +# BCM Config file for Clearlake platform +# - 32x40g Portmode + +# ALPM enable +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l2_mem_entries=32768 +l3_mem_entries=16384 + +# From old config file +os=unix +higig2_hdr_mode=1 + +# Parity +parity_correction=1 +parity_enable=1 +stat_if_parity_enable=0 + +# l2 thread related config vars +l2xmsg_hostbuf_size=8192 +l2xmsg_mode=1 + +bcm_num_cos=8 +bcm_stat_interval=2000000 +lls_num_l2uc=12 +max_vp_lags=0 +miim_intr_enable=0 +mmu_lossless=0 +module_64ports=0 + +stable_size=0x2000000 + +schan_intr_enable=0 +tdma_timeout_usec=5000000 +tslam_timeout_usec=15000000 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 + +############################### +serdes_fiber_pref=1 +############################### +mdio_output_delay=0x0d +############################### +xgxs_lcpll_xtal_refclk=1 +tdma_intr_enable=1 +tslam_intr_enable=1 +table_dma_enable=1 + +pbmp_oversubscribe.0=0x1fffffffffffffffffffffffffe +pbmp_xport_xe.0=0x1fffffffffffffffffffffffffe +phy_an_c37_1.0=3 +phy_an_c37_5.0=3 +phy_an_c37_9.0=3 +phy_an_c37_13.0=3 +phy_an_c37_17.0=3 +phy_an_c37_21.0=3 +phy_an_c37_25.0=3 +phy_an_c37_29.0=3 +phy_an_c37_33.0=3 +phy_an_c37_37.0=3 +phy_an_c37_41.0=3 +phy_an_c37_45.0=3 +phy_an_c37_49.0=3 +phy_an_c37_53.0=3 +phy_an_c37_57.0=3 +phy_an_c37_61.0=3 +phy_an_c37_65.0=3 +phy_an_c37_69.0=3 +phy_an_c37_73.0=3 +phy_an_c37_77.0=3 +phy_an_c37_81.0=3 +phy_an_c37_85.0=3 +phy_an_c37_89.0=3 +phy_an_c37_93.0=3 +phy_an_c37_97.0=0 +phy_an_c37_98.0=0 +phy_an_c37_99.0=0 +phy_an_c37_100.0=0 +phy_an_c37_101.0=0 +phy_an_c37_102.0=0 +phy_an_c37_103.0=0 +phy_an_c37_104.0=0 +phy_an_c73_1.0=0 +phy_an_c73_5.0=0 +phy_an_c73_9.0=0 +phy_an_c73_13.0=0 +phy_an_c73_17.0=0 +phy_an_c73_21.0=0 +phy_an_c73_25.0=0 +phy_an_c73_29.0=0 +phy_an_c73_33.0=0 +phy_an_c73_37.0=0 +phy_an_c73_41.0=0 +phy_an_c73_45.0=0 +phy_an_c73_49.0=0 +phy_an_c73_53.0=0 +phy_an_c73_57.0=0 +phy_an_c73_61.0=0 +phy_an_c73_65.0=0 +phy_an_c73_69.0=0 +phy_an_c73_73.0=0 +phy_an_c73_77.0=0 +phy_an_c73_81.0=0 +phy_an_c73_85.0=0 +phy_an_c73_89.0=0 +phy_an_c73_93.0=0 +phy_an_c73_97.0=2 +phy_an_c73_98.0=2 +phy_an_c73_99.0=2 +phy_an_c73_100.0=2 +phy_an_c73_101.0=2 +phy_an_c73_102.0=2 +phy_an_c73_103.0=2 +phy_an_c73_104.0=2 +phy_xaui_rx_polarity_flip_1.0=0x0 +phy_xaui_rx_polarity_flip_5.0=0x0 +phy_xaui_rx_polarity_flip_9.0=0x4 +phy_xaui_rx_polarity_flip_13.0=0x0 +phy_xaui_rx_polarity_flip_17.0=0xb +phy_xaui_rx_polarity_flip_21.0=0x3 +phy_xaui_rx_polarity_flip_25.0=0xb +phy_xaui_rx_polarity_flip_29.0=0xf +phy_xaui_rx_polarity_flip_33.0=0xb +phy_xaui_rx_polarity_flip_37.0=0x3 +phy_xaui_rx_polarity_flip_41.0=0xb +phy_xaui_rx_polarity_flip_45.0=0x0 +phy_xaui_rx_polarity_flip_49.0=0x4 +phy_xaui_rx_polarity_flip_53.0=0xc +phy_xaui_rx_polarity_flip_57.0=0x4 +phy_xaui_rx_polarity_flip_61.0=0x0 +phy_xaui_rx_polarity_flip_65.0=0xb +phy_xaui_rx_polarity_flip_69.0=0x3 +phy_xaui_rx_polarity_flip_73.0=0xb +phy_xaui_rx_polarity_flip_77.0=0xf +phy_xaui_rx_polarity_flip_81.0=0xb +phy_xaui_rx_polarity_flip_85.0=0x3 +phy_xaui_rx_polarity_flip_89.0=0x4 +phy_xaui_rx_polarity_flip_93.0=0x0 +phy_xaui_rx_polarity_flip_97.0=0xb +phy_xaui_rx_polarity_flip_98.0=0x3 +phy_xaui_rx_polarity_flip_99.0=0x4 +phy_xaui_rx_polarity_flip_100.0=0x0 +phy_xaui_rx_polarity_flip_101.0=0x0 +phy_xaui_rx_polarity_flip_102.0=0xe +phy_xaui_rx_polarity_flip_103.0=0x0 +phy_xaui_rx_polarity_flip_104.0=0x0 +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_5.0=0x0 +phy_xaui_tx_polarity_flip_9.0=0x2 +phy_xaui_tx_polarity_flip_13.0=0x0 +phy_xaui_tx_polarity_flip_17.0=0xd +phy_xaui_tx_polarity_flip_21.0=0xc +phy_xaui_tx_polarity_flip_25.0=0xd +phy_xaui_tx_polarity_flip_29.0=0xf +phy_xaui_tx_polarity_flip_33.0=0xd +phy_xaui_tx_polarity_flip_37.0=0xc +phy_xaui_tx_polarity_flip_41.0=0xd +phy_xaui_tx_polarity_flip_45.0=0x0 +phy_xaui_tx_polarity_flip_49.0=0x2 +phy_xaui_tx_polarity_flip_53.0=0x3 +phy_xaui_tx_polarity_flip_57.0=0x2 +phy_xaui_tx_polarity_flip_61.0=0x0 +phy_xaui_tx_polarity_flip_65.0=0xd +phy_xaui_tx_polarity_flip_69.0=0xc +phy_xaui_tx_polarity_flip_73.0=0xd +phy_xaui_tx_polarity_flip_77.0=0xf +phy_xaui_tx_polarity_flip_81.0=0xd +phy_xaui_tx_polarity_flip_85.0=0xc +phy_xaui_tx_polarity_flip_89.0=0x2 +phy_xaui_tx_polarity_flip_93.0=0x0 +phy_xaui_tx_polarity_flip_97.0=0xd +phy_xaui_tx_polarity_flip_98.0=0xc +phy_xaui_tx_polarity_flip_99.0=0x2 +phy_xaui_tx_polarity_flip_100.0=0x0 +phy_xaui_tx_polarity_flip_101.0=0x0 +phy_xaui_tx_polarity_flip_102.0=0x7 +phy_xaui_tx_polarity_flip_103.0=0x2 +phy_xaui_tx_polarity_flip_104.0=0x0 +port_init_autoneg_1.0=0 +port_init_autoneg_5.0=0 +port_init_autoneg_9.0=0 +port_init_autoneg_13.0=0 +port_init_autoneg_17.0=0 +port_init_autoneg_21.0=0 +port_init_autoneg_25.0=0 +port_init_autoneg_29.0=0 +port_init_autoneg_33.0=0 +port_init_autoneg_37.0=0 +port_init_autoneg_41.0=0 +port_init_autoneg_45.0=0 +port_init_autoneg_49.0=0 +port_init_autoneg_53.0=0 +port_init_autoneg_57.0=0 +port_init_autoneg_61.0=0 +port_init_autoneg_65.0=0 +port_init_autoneg_69.0=0 +port_init_autoneg_73.0=0 +port_init_autoneg_77.0=0 +port_init_autoneg_81.0=0 +port_init_autoneg_85.0=0 +port_init_autoneg_89.0=0 +port_init_autoneg_93.0=0 +port_init_autoneg_97.0=0 +port_init_autoneg_98.0=0 +port_init_autoneg_99.0=0 +port_init_autoneg_100.0=0 +port_init_autoneg_101.0=0 +port_init_autoneg_102.0=0 +port_init_autoneg_103.0=0 +port_init_autoneg_104.0=0 +port_init_cl72_hg.0=0x11 +port_phy_addr_1.0=0x7f +port_phy_addr_5.0=0x7f +port_phy_addr_9.0=0x7f +port_phy_addr_13.0=0x7f +port_phy_addr_17.0=0x7f +port_phy_addr_21.0=0x7f +port_phy_addr_25.0=0x7f +port_phy_addr_29.0=0x7f +port_phy_addr_33.0=0x7f +port_phy_addr_37.0=0x7f +port_phy_addr_41.0=0x7f +port_phy_addr_45.0=0x7f +port_phy_addr_49.0=0x7f +port_phy_addr_53.0=0x7f +port_phy_addr_57.0=0x7f +port_phy_addr_61.0=0x7f +port_phy_addr_65.0=0x7f +port_phy_addr_69.0=0x7f +port_phy_addr_73.0=0x7f +port_phy_addr_77.0=0x7f +port_phy_addr_81.0=0x7f +port_phy_addr_85.0=0x7f +port_phy_addr_89.0=0x7f +port_phy_addr_93.0=0x7f +port_phy_addr_97.0=0x7f +port_phy_addr_98.0=0x7f +port_phy_addr_99.0=0x7f +port_phy_addr_100.0=0x7f +port_phy_addr_101.0=0x7f +port_phy_addr_102.0=0x7f +port_phy_addr_103.0=0x7f +port_phy_addr_104.0=0x7f +portmap_1.0=9:40 +portmap_5.0=13:40 +portmap_9.0=17:40 +portmap_13.0=21:40 +portmap_17.0=29:40 +portmap_21.0=25:40 +portmap_25.0=33:40 +portmap_29.0=37:40 +portmap_33.0=45:40 +portmap_37.0=41:40 +portmap_41.0=49:40 +portmap_45.0=53:40 +portmap_49.0=69:40 +portmap_53.0=65:40 +portmap_57.0=73:40 +portmap_61.0=77:40 +portmap_65.0=93:40 +portmap_69.0=89:40 +portmap_73.0=97:40 +portmap_77.0=101:40 +portmap_81.0=109:40 +portmap_85.0=105:40 +portmap_89.0=121:40 +portmap_93.0=125:40 +portmap_97.0=61:40 +portmap_98.0=57:40 +portmap_99.0=81:40 +portmap_100.0=85:40 +portmap_101.0=117:40 +portmap_102.0=113:40 +portmap_103.0=1:40 +portmap_104.0=5:40 +serdes_firmware_mode_1.0=2 +serdes_firmware_mode_5.0=2 +serdes_firmware_mode_9.0=2 +serdes_firmware_mode_13.0=2 +serdes_firmware_mode_17.0=2 +serdes_firmware_mode_21.0=2 +serdes_firmware_mode_25.0=2 +serdes_firmware_mode_29.0=2 +serdes_firmware_mode_33.0=2 +serdes_firmware_mode_37.0=2 +serdes_firmware_mode_41.0=2 +serdes_firmware_mode_45.0=2 +serdes_firmware_mode_49.0=2 +serdes_firmware_mode_53.0=2 +serdes_firmware_mode_57.0=2 +serdes_firmware_mode_61.0=2 +serdes_firmware_mode_65.0=2 +serdes_firmware_mode_69.0=2 +serdes_firmware_mode_73.0=2 +serdes_firmware_mode_77.0=2 +serdes_firmware_mode_81.0=2 +serdes_firmware_mode_85.0=2 +serdes_firmware_mode_89.0=2 +serdes_firmware_mode_93.0=2 +serdes_firmware_mode_97.0=2 +serdes_firmware_mode_98.0=2 +serdes_firmware_mode_99.0=2 +serdes_firmware_mode_100.0=2 +serdes_firmware_mode_101.0=2 +serdes_firmware_mode_102.0=2 +serdes_firmware_mode_103.0=2 +serdes_firmware_mode_104.0=2 +xgxs_rx_lane_map_1.0=0x3210 +xgxs_rx_lane_map_5.0=0x0321 +xgxs_rx_lane_map_9.0=0x1302 +xgxs_rx_lane_map_13.0=0x0213 +xgxs_rx_lane_map_17.0=0x1302 +xgxs_rx_lane_map_21.0=0x1302 +xgxs_rx_lane_map_25.0=0x1302 +xgxs_rx_lane_map_29.0=0x0213 +xgxs_rx_lane_map_33.0=0x1302 +xgxs_rx_lane_map_37.0=0x1302 +xgxs_rx_lane_map_41.0=0x1302 +xgxs_rx_lane_map_45.0=0x0213 +xgxs_rx_lane_map_49.0=0x1302 +xgxs_rx_lane_map_53.0=0x1302 +xgxs_rx_lane_map_57.0=0x1302 +xgxs_rx_lane_map_61.0=0x0213 +xgxs_rx_lane_map_65.0=0x1302 +xgxs_rx_lane_map_69.0=0x1302 +xgxs_rx_lane_map_73.0=0x1302 +xgxs_rx_lane_map_77.0=0x0213 +xgxs_rx_lane_map_81.0=0x1302 +xgxs_rx_lane_map_85.0=0x1302 +xgxs_rx_lane_map_89.0=0x1302 +xgxs_rx_lane_map_93.0=0x0213 +xgxs_rx_lane_map_97.0=0x1302 +xgxs_rx_lane_map_98.0=0x1302 +xgxs_rx_lane_map_99.0=0x1302 +xgxs_rx_lane_map_100.0=0x0213 +xgxs_rx_lane_map_101.0=0x0213 +xgxs_rx_lane_map_102.0=0x1302 +xgxs_rx_lane_map_103.0=0x0123 +xgxs_rx_lane_map_104.0=0x2031 +xgxs_tx_lane_map_1.0=0x0123 +xgxs_tx_lane_map_5.0=0x0321 +xgxs_tx_lane_map_9.0=0x2031 +xgxs_tx_lane_map_13.0=0x0213 +xgxs_tx_lane_map_17.0=0x2031 +xgxs_tx_lane_map_21.0=0x2031 +xgxs_tx_lane_map_25.0=0x2031 +xgxs_tx_lane_map_29.0=0x0213 +xgxs_tx_lane_map_33.0=0x2031 +xgxs_tx_lane_map_37.0=0x2031 +xgxs_tx_lane_map_41.0=0x2031 +xgxs_tx_lane_map_45.0=0x0213 +xgxs_tx_lane_map_49.0=0x2031 +xgxs_tx_lane_map_53.0=0x2031 +xgxs_tx_lane_map_57.0=0x2031 +xgxs_tx_lane_map_61.0=0x0213 +xgxs_tx_lane_map_65.0=0x2031 +xgxs_tx_lane_map_69.0=0x2031 +xgxs_tx_lane_map_73.0=0x2031 +xgxs_tx_lane_map_77.0=0x0213 +xgxs_tx_lane_map_81.0=0x2031 +xgxs_tx_lane_map_85.0=0x2031 +xgxs_tx_lane_map_89.0=0x2031 +xgxs_tx_lane_map_93.0=0x0213 +xgxs_tx_lane_map_97.0=0x2031 +xgxs_tx_lane_map_98.0=0x2031 +xgxs_tx_lane_map_99.0=0x2031 +xgxs_tx_lane_map_100.0=0x0213 +xgxs_tx_lane_map_101.0=0x0213 +xgxs_tx_lane_map_102.0=0x2031 +xgxs_tx_lane_map_103.0=0x3120 +xgxs_tx_lane_map_104.0=0x1302 + +# tuning parameters +serdes_preemphasis_lane0_1.0=0x81f7 +serdes_preemphasis_lane1_1.0=0x81f7 +serdes_preemphasis_lane2_1.0=0x81f7 +serdes_preemphasis_lane3_1.0=0x81f7 +serdes_pre_driver_current_lane0_5.0=0x7 +serdes_driver_current_lane0_5.0=0x7 +serdes_preemphasis_lane0_5.0=0xc2f0 +serdes_pre_driver_current_lane1_5.0=0x7 +serdes_driver_current_lane1_5.0=0x7 +serdes_preemphasis_lane1_5.0=0xc2f0 +serdes_pre_driver_current_lane2_5.0=0x7 +serdes_driver_current_lane2_5.0=0x7 +serdes_preemphasis_lane2_5.0=0xc2f0 +serdes_pre_driver_current_lane3_5.0=0x7 +serdes_driver_current_lane3_5.0=0x7 +serdes_preemphasis_lane3_5.0=0xc2f0 +serdes_pre_driver_current_lane0_9.0=0x7 +serdes_driver_current_lane0_9.0=0x7 +serdes_preemphasis_lane0_9.0=0xbb10 +serdes_pre_driver_current_lane1_9.0=0x7 +serdes_driver_current_lane1_9.0=0x7 +serdes_preemphasis_lane1_9.0=0xbb10 +serdes_pre_driver_current_lane2_9.0=0x7 +serdes_driver_current_lane2_9.0=0x7 +serdes_preemphasis_lane2_9.0=0xbb10 +serdes_pre_driver_current_lane3_9.0=0x7 +serdes_driver_current_lane3_9.0=0x7 +serdes_preemphasis_lane3_9.0=0xbb10 +serdes_pre_driver_current_lane0_13.0=0x7 +serdes_driver_current_lane0_13.0=0x7 +serdes_preemphasis_lane0_13.0=0xbb10 +serdes_pre_driver_current_lane1_13.0=0x7 +serdes_driver_current_lane1_13.0=0x7 +serdes_preemphasis_lane1_13.0=0xbb10 +serdes_pre_driver_current_lane2_13.0=0x7 +serdes_driver_current_lane2_13.0=0x7 +serdes_preemphasis_lane2_13.0=0xbb10 +serdes_pre_driver_current_lane3_13.0=0x7 +serdes_driver_current_lane3_13.0=0x7 +serdes_preemphasis_lane3_13.0=0xbb10 +serdes_pre_driver_current_lane0_17.0=0x6 +serdes_driver_current_lane0_17.0=0x6 +serdes_preemphasis_lane0_17.0=0xb720 +serdes_pre_driver_current_lane1_17.0=0x6 +serdes_driver_current_lane1_17.0=0x6 +serdes_preemphasis_lane1_17.0=0xb720 +serdes_pre_driver_current_lane2_17.0=0x6 +serdes_driver_current_lane2_17.0=0x6 +serdes_preemphasis_lane2_17.0=0xb720 +serdes_pre_driver_current_lane3_17.0=0x6 +serdes_driver_current_lane3_17.0=0x6 +serdes_preemphasis_lane3_17.0=0xb720 +serdes_pre_driver_current_lane0_21.0=0x7 +serdes_driver_current_lane0_21.0=0x7 +serdes_preemphasis_lane0_21.0=0xbb10 +serdes_pre_driver_current_lane1_21.0=0x7 +serdes_driver_current_lane1_21.0=0x7 +serdes_preemphasis_lane1_21.0=0xbb10 +serdes_pre_driver_current_lane2_21.0=0x7 +serdes_driver_current_lane2_21.0=0x7 +serdes_preemphasis_lane2_21.0=0xbb10 +serdes_pre_driver_current_lane3_21.0=0x7 +serdes_driver_current_lane3_21.0=0x7 +serdes_preemphasis_lane3_21.0=0xbb10 +serdes_pre_driver_current_lane0_25.0=0x5 +serdes_driver_current_lane0_25.0=0x5 +serdes_preemphasis_lane0_25.0=0xb720 +serdes_pre_driver_current_lane1_25.0=0x5 +serdes_driver_current_lane1_25.0=0x5 +serdes_preemphasis_lane1_25.0=0xb720 +serdes_pre_driver_current_lane2_25.0=0x5 +serdes_driver_current_lane2_25.0=0x5 +serdes_preemphasis_lane2_25.0=0xb720 +serdes_pre_driver_current_lane3_25.0=0x5 +serdes_driver_current_lane3_25.0=0x5 +serdes_preemphasis_lane3_25.0=0xb720 +serdes_pre_driver_current_lane0_29.0=0x5 +serdes_driver_current_lane0_29.0=0x5 +serdes_preemphasis_lane0_29.0=0xb720 +serdes_pre_driver_current_lane1_29.0=0x5 +serdes_driver_current_lane1_29.0=0x5 +serdes_preemphasis_lane1_29.0=0xb720 +serdes_pre_driver_current_lane2_29.0=0x5 +serdes_driver_current_lane2_29.0=0x5 +serdes_preemphasis_lane2_29.0=0xb720 +serdes_pre_driver_current_lane3_29.0=0x5 +serdes_driver_current_lane3_29.0=0x5 +serdes_preemphasis_lane3_29.0=0xb720 +serdes_pre_driver_current_lane0_33.0=0x4 +serdes_driver_current_lane0_33.0=0x4 +serdes_preemphasis_lane0_33.0=0xb720 +serdes_pre_driver_current_lane1_33.0=0x4 +serdes_driver_current_lane1_33.0=0x4 +serdes_preemphasis_lane1_33.0=0xb720 +serdes_pre_driver_current_lane2_33.0=0x4 +serdes_driver_current_lane2_33.0=0x4 +serdes_preemphasis_lane2_33.0=0xb720 +serdes_pre_driver_current_lane3_33.0=0x4 +serdes_driver_current_lane3_33.0=0x4 +serdes_preemphasis_lane3_33.0=0xb720 +serdes_pre_driver_current_lane0_37.0=0x5 +serdes_driver_current_lane0_37.0=0x5 +serdes_preemphasis_lane0_37.0=0xb720 +serdes_pre_driver_current_lane1_37.0=0x5 +serdes_driver_current_lane1_37.0=0x5 +serdes_preemphasis_lane1_37.0=0xb720 +serdes_pre_driver_current_lane2_37.0=0x5 +serdes_driver_current_lane2_37.0=0x5 +serdes_preemphasis_lane2_37.0=0xb720 +serdes_pre_driver_current_lane3_37.0=0x5 +serdes_driver_current_lane3_37.0=0x5 +serdes_preemphasis_lane3_37.0=0xb720 +serdes_pre_driver_current_lane0_41.0=0x3 +serdes_driver_current_lane0_41.0=0x3 +serdes_preemphasis_lane0_41.0=0xb330 +serdes_pre_driver_current_lane1_41.0=0x3 +serdes_driver_current_lane1_41.0=0x3 +serdes_preemphasis_lane1_41.0=0xb330 +serdes_pre_driver_current_lane2_41.0=0x3 +serdes_driver_current_lane2_41.0=0x3 +serdes_preemphasis_lane2_41.0=0xb330 +serdes_pre_driver_current_lane3_41.0=0x3 +serdes_driver_current_lane3_41.0=0x3 +serdes_preemphasis_lane3_41.0=0xb330 +serdes_pre_driver_current_lane0_45.0=0x4 +serdes_driver_current_lane0_45.0=0x4 +serdes_preemphasis_lane0_45.0=0xb720 +serdes_pre_driver_current_lane1_45.0=0x4 +serdes_driver_current_lane1_45.0=0x4 +serdes_preemphasis_lane1_45.0=0xb720 +serdes_pre_driver_current_lane2_45.0=0x4 +serdes_driver_current_lane2_45.0=0x4 +serdes_preemphasis_lane2_45.0=0xb720 +serdes_pre_driver_current_lane3_45.0=0x4 +serdes_driver_current_lane3_45.0=0x4 +serdes_preemphasis_lane3_45.0=0xb720 +serdes_pre_driver_current_lane0_49.0=0x3 +serdes_driver_current_lane0_49.0=0x3 +serdes_preemphasis_lane0_49.0=0xb330 +serdes_pre_driver_current_lane1_49.0=0x3 +serdes_driver_current_lane1_49.0=0x3 +serdes_preemphasis_lane1_49.0=0xb330 +serdes_pre_driver_current_lane2_49.0=0x3 +serdes_driver_current_lane2_49.0=0x3 +serdes_preemphasis_lane2_49.0=0xb330 +serdes_pre_driver_current_lane3_49.0=0x3 +serdes_driver_current_lane3_49.0=0x3 +serdes_preemphasis_lane3_49.0=0xb330 +serdes_pre_driver_current_lane0_53.0=0x4 +serdes_driver_current_lane0_53.0=0x4 +serdes_preemphasis_lane0_53.0=0xb720 +serdes_pre_driver_current_lane1_53.0=0x4 +serdes_driver_current_lane1_53.0=0x4 +serdes_preemphasis_lane1_53.0=0xb720 +serdes_pre_driver_current_lane2_53.0=0x4 +serdes_driver_current_lane2_53.0=0x4 +serdes_preemphasis_lane2_53.0=0xb720 +serdes_pre_driver_current_lane3_53.0=0x4 +serdes_driver_current_lane3_53.0=0x4 +serdes_preemphasis_lane3_53.0=0xb720 +serdes_pre_driver_current_lane0_57.0=0x3 +serdes_driver_current_lane0_57.0=0x3 +serdes_preemphasis_lane0_57.0=0xb330 +serdes_pre_driver_current_lane1_57.0=0x3 +serdes_driver_current_lane1_57.0=0x3 +serdes_preemphasis_lane1_57.0=0xb330 +serdes_pre_driver_current_lane2_57.0=0x3 +serdes_driver_current_lane2_57.0=0x3 +serdes_preemphasis_lane2_57.0=0xb330 +serdes_pre_driver_current_lane3_57.0=0x3 +serdes_driver_current_lane3_57.0=0x3 +serdes_preemphasis_lane3_57.0=0xb330 +serdes_pre_driver_current_lane0_61.0=0x4 +serdes_driver_current_lane0_61.0=0x4 +serdes_preemphasis_lane0_61.0=0xb720 +serdes_pre_driver_current_lane1_61.0=0x4 +serdes_driver_current_lane1_61.0=0x4 +serdes_preemphasis_lane1_61.0=0xb720 +serdes_pre_driver_current_lane2_61.0=0x4 +serdes_driver_current_lane2_61.0=0x4 +serdes_preemphasis_lane2_61.0=0xb720 +serdes_pre_driver_current_lane3_61.0=0x4 +serdes_driver_current_lane3_61.0=0x4 +serdes_preemphasis_lane3_61.0=0xb720 +serdes_pre_driver_current_lane0_65.0=0x4 +serdes_driver_current_lane0_65.0=0x4 +serdes_preemphasis_lane0_65.0=0xb720 +serdes_pre_driver_current_lane1_65.0=0x4 +serdes_driver_current_lane1_65.0=0x4 +serdes_preemphasis_lane1_65.0=0xb720 +serdes_pre_driver_current_lane2_65.0=0x4 +serdes_driver_current_lane2_65.0=0x4 +serdes_preemphasis_lane2_65.0=0xb720 +serdes_pre_driver_current_lane3_65.0=0x4 +serdes_driver_current_lane3_65.0=0x4 +serdes_preemphasis_lane3_65.0=0xb720 +serdes_pre_driver_current_lane0_69.0=0x4 +serdes_driver_current_lane0_69.0=0x4 +serdes_preemphasis_lane0_69.0=0xb720 +serdes_pre_driver_current_lane1_69.0=0x4 +serdes_driver_current_lane1_69.0=0x4 +serdes_preemphasis_lane1_69.0=0xb720 +serdes_pre_driver_current_lane2_69.0=0x4 +serdes_driver_current_lane2_69.0=0x4 +serdes_preemphasis_lane2_69.0=0xb720 +serdes_pre_driver_current_lane3_69.0=0x4 +serdes_driver_current_lane3_69.0=0x4 +serdes_preemphasis_lane3_69.0=0xb720 +serdes_pre_driver_current_lane0_73.0=0x4 +serdes_driver_current_lane0_73.0=0x4 +serdes_preemphasis_lane0_73.0=0xb720 +serdes_pre_driver_current_lane1_73.0=0x4 +serdes_driver_current_lane1_73.0=0x4 +serdes_preemphasis_lane1_73.0=0xb720 +serdes_pre_driver_current_lane2_73.0=0x4 +serdes_driver_current_lane2_73.0=0x4 +serdes_preemphasis_lane2_73.0=0xb720 +serdes_pre_driver_current_lane3_73.0=0x4 +serdes_driver_current_lane3_73.0=0x4 +serdes_preemphasis_lane3_73.0=0xb720 +serdes_pre_driver_current_lane0_77.0=0x5 +serdes_driver_current_lane0_77.0=0x5 +serdes_preemphasis_lane0_77.0=0xb720 +serdes_pre_driver_current_lane1_77.0=0x5 +serdes_driver_current_lane1_77.0=0x5 +serdes_preemphasis_lane1_77.0=0xb720 +serdes_pre_driver_current_lane2_77.0=0x5 +serdes_driver_current_lane2_77.0=0x5 +serdes_preemphasis_lane2_77.0=0xb720 +serdes_pre_driver_current_lane3_77.0=0x5 +serdes_driver_current_lane3_77.0=0x5 +serdes_preemphasis_lane3_77.0=0xb720 +serdes_pre_driver_current_lane0_81.0=0x5 +serdes_driver_current_lane0_81.0=0x5 +serdes_preemphasis_lane0_81.0=0xb720 +serdes_pre_driver_current_lane1_81.0=0x5 +serdes_driver_current_lane1_81.0=0x5 +serdes_preemphasis_lane1_81.0=0xb720 +serdes_pre_driver_current_lane2_81.0=0x5 +serdes_driver_current_lane2_81.0=0x5 +serdes_preemphasis_lane2_81.0=0xb720 +serdes_pre_driver_current_lane3_81.0=0x5 +serdes_driver_current_lane3_81.0=0x5 +serdes_preemphasis_lane3_81.0=0xb720 +serdes_pre_driver_current_lane0_85.0=0x5 +serdes_driver_current_lane0_85.0=0x5 +serdes_preemphasis_lane0_85.0=0xb720 +serdes_pre_driver_current_lane1_85.0=0x5 +serdes_driver_current_lane1_85.0=0x5 +serdes_preemphasis_lane1_85.0=0xb720 +serdes_pre_driver_current_lane2_85.0=0x5 +serdes_driver_current_lane2_85.0=0x5 +serdes_preemphasis_lane2_85.0=0xb720 +serdes_pre_driver_current_lane3_85.0=0x5 +serdes_driver_current_lane3_85.0=0x5 +serdes_preemphasis_lane3_85.0=0xb720 +serdes_pre_driver_current_lane0_89.0=0x6 +serdes_driver_current_lane0_89.0=0x6 +serdes_preemphasis_lane0_89.0=0xb720 +serdes_pre_driver_current_lane1_89.0=0x6 +serdes_driver_current_lane1_89.0=0x6 +serdes_preemphasis_lane1_89.0=0xb720 +serdes_pre_driver_current_lane2_89.0=0x6 +serdes_driver_current_lane2_89.0=0x6 +serdes_preemphasis_lane2_89.0=0xb720 +serdes_pre_driver_current_lane3_89.0=0x6 +serdes_driver_current_lane3_89.0=0x6 +serdes_preemphasis_lane3_89.0=0xb720 +serdes_pre_driver_current_lane0_93.0=0x7 +serdes_driver_current_lane0_93.0=0x7 +serdes_preemphasis_lane0_93.0=0xbb10 +serdes_pre_driver_current_lane1_93.0=0x7 +serdes_driver_current_lane1_93.0=0x7 +serdes_preemphasis_lane1_93.0=0xbb10 +serdes_pre_driver_current_lane2_93.0=0x7 +serdes_driver_current_lane2_93.0=0x7 +serdes_preemphasis_lane2_93.0=0xbb10 +serdes_pre_driver_current_lane3_93.0=0x7 +serdes_driver_current_lane3_93.0=0x7 +serdes_preemphasis_lane3_93.0=0xbb10 +serdes_pre_driver_current_lane0_97.0=0x5 +serdes_driver_current_lane0_97.0=0x5 +serdes_preemphasis_lane0_97.0=0xb720 +serdes_pre_driver_current_lane1_97.0=0x5 +serdes_driver_current_lane1_97.0=0x5 +serdes_preemphasis_lane1_97.0=0xb720 +serdes_pre_driver_current_lane2_97.0=0x5 +serdes_driver_current_lane2_97.0=0x5 +serdes_preemphasis_lane2_97.0=0xb720 +serdes_pre_driver_current_lane3_97.0=0x5 +serdes_driver_current_lane3_97.0=0x5 +serdes_preemphasis_lane3_97.0=0xb720 +serdes_pre_driver_current_lane0_98.0=0x6 +serdes_driver_current_lane0_98.0=0x6 +serdes_preemphasis_lane0_98.0=0xb720 +serdes_pre_driver_current_lane1_98.0=0x6 +serdes_driver_current_lane1_98.0=0x6 +serdes_preemphasis_lane1_98.0=0xb720 +serdes_pre_driver_current_lane2_98.0=0x6 +serdes_driver_current_lane2_98.0=0x6 +serdes_preemphasis_lane2_98.0=0xb720 +serdes_pre_driver_current_lane3_98.0=0x6 +serdes_driver_current_lane3_98.0=0x6 +serdes_preemphasis_lane3_98.0=0xb720 +serdes_pre_driver_current_lane0_99.0=0x5 +serdes_driver_current_lane0_99.0=0x5 +serdes_preemphasis_lane0_99.0=0xb720 +serdes_pre_driver_current_lane1_99.0=0x5 +serdes_driver_current_lane1_99.0=0x5 +serdes_preemphasis_lane1_99.0=0xb720 +serdes_pre_driver_current_lane2_99.0=0x5 +serdes_driver_current_lane2_99.0=0x5 +serdes_preemphasis_lane2_99.0=0xb720 +serdes_pre_driver_current_lane3_99.0=0x5 +serdes_driver_current_lane3_99.0=0x5 +serdes_preemphasis_lane3_99.0=0xb720 +serdes_pre_driver_current_lane0_100.0=0x7 +serdes_driver_current_lane0_100.0=0x7 +serdes_preemphasis_lane0_100.0=0xbb10 +serdes_pre_driver_current_lane1_100.0=0x7 +serdes_driver_current_lane1_100.0=0x7 +serdes_preemphasis_lane1_100.0=0xbb10 +serdes_pre_driver_current_lane2_100.0=0x7 +serdes_driver_current_lane2_100.0=0x7 +serdes_preemphasis_lane2_100.0=0xbb10 +serdes_pre_driver_current_lane3_100.0=0x7 +serdes_driver_current_lane3_100.0=0x7 +serdes_preemphasis_lane3_100.0=0xbb10 +serdes_pre_driver_current_lane0_101.0=0x7 +serdes_driver_current_lane0_101.0=0x7 +serdes_preemphasis_lane0_101.0=0xbb10 +serdes_pre_driver_current_lane1_101.0=0x7 +serdes_driver_current_lane1_101.0=0x7 +serdes_preemphasis_lane1_101.0=0xbb10 +serdes_pre_driver_current_lane2_101.0=0x7 +serdes_driver_current_lane2_101.0=0x7 +serdes_preemphasis_lane2_101.0=0xbb10 +serdes_pre_driver_current_lane3_101.0=0x7 +serdes_driver_current_lane3_101.0=0x7 +serdes_preemphasis_lane3_101.0=0xbb10 +serdes_pre_driver_current_lane0_102.0=0x7 +serdes_driver_current_lane0_102.0=0x7 +serdes_preemphasis_lane0_102.0=0xbb10 +serdes_pre_driver_current_lane1_102.0=0x7 +serdes_driver_current_lane1_102.0=0x7 +serdes_preemphasis_lane1_102.0=0xbb10 +serdes_pre_driver_current_lane2_102.0=0x7 +serdes_driver_current_lane2_102.0=0x7 +serdes_preemphasis_lane2_102.0=0xbb10 +serdes_pre_driver_current_lane3_102.0=0x7 +serdes_driver_current_lane3_102.0=0x7 +serdes_preemphasis_lane3_102.0=0xbb10 +serdes_preemphasis_lane0_103.0=0x81f4 +serdes_preemphasis_lane1_103.0=0x81f4 +serdes_preemphasis_lane2_103.0=0x81f4 +serdes_preemphasis_lane3_103.0=0x81f4 +serdes_preemphasis_lane0_104.0=0x81f5 +serdes_preemphasis_lane1_104.0=0x81f5 +serdes_preemphasis_lane2_104.0=0x81f5 +serdes_preemphasis_lane3_104.0=0x81f5 diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/buffers.json.j2 b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/buffers.json.j2 new file mode 100644 index 000000000000..b67cf577ab75 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/buffers_defaults_t1.j2 b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..f72e3eb06fb5 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/buffers_defaults_t1.j2 @@ -0,0 +1,49 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% if PORT_ALL.append("Ethernet0") %}{% endif %} + {% if PORT_ALL.append("Ethernet1") %}{% endif %} + {% if PORT_ALL.append("Ethernet2") %}{% endif %} + {% if PORT_ALL.append("Ethernet3") %}{% endif %} + {% for port_idx in range(1,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "8072396", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/hwsku-init b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/hwsku-init new file mode 100755 index 000000000000..ffc913582aa7 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/hwsku-init @@ -0,0 +1,3 @@ +#!/bin/bash + +echo 1 > /sys/devices/pci0000:00/0000:00:02.2/0000:02:00.0/mux diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/pg_profile_lookup.ini b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/pg_profile_lookup.ini new file mode 100644 index 000000000000..f961fd33b138 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/pg_profile_lookup.ini @@ -0,0 +1,14 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 41808 18432 40560 -4 2496 + 40000 5m 41808 18432 40560 -4 2496 + 50000 5m 41808 18432 40560 -4 2496 + 100000 5m 41808 18432 40560 -4 2496 + 10000 40m 41808 18432 40560 -4 2496 + 40000 40m 41808 18432 40560 -4 2496 + 50000 40m 41808 18432 40560 -4 2496 + 100000 40m 41808 18432 40560 -4 2496 + 10000 300m 41808 18432 40560 -4 2496 + 40000 300m 41808 18432 40560 -4 2496 + 50000 300m 41808 18432 40560 -4 2496 + 100000 300m 41808 18432 40560 -4 2496 diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/port_config.ini b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/port_config.ini new file mode 100644 index 000000000000..dafdb570e9cc --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/port_config.ini @@ -0,0 +1,36 @@ +# name lanes alias index +Ethernet0 9 Ethernet1 1 +Ethernet1 10 Ethernet2 2 +Ethernet2 11 Ethernet3 3 +Ethernet3 12 Ethernet4 4 +Ethernet4 13,14,15,16 Ethernet6/1 6 +Ethernet8 17,18,19,20 Ethernet7/1 7 +Ethernet12 21,22,23,24 Ethernet8/1 8 +Ethernet16 29,30,31,32 Ethernet9/1 9 +Ethernet20 25,26,27,28 Ethernet10/1 10 +Ethernet24 33,34,35,36 Ethernet11/1 11 +Ethernet28 37,38,39,40 Ethernet12/1 12 +Ethernet32 45,46,47,48 Ethernet13/1 13 +Ethernet36 41,42,43,44 Ethernet14/1 14 +Ethernet40 49,50,51,52 Ethernet15/1 15 +Ethernet44 53,54,55,56 Ethernet16/1 16 +Ethernet48 69,70,71,72 Ethernet17/1 17 +Ethernet52 65,66,67,68 Ethernet18/1 18 +Ethernet56 73,74,75,76 Ethernet19/1 19 +Ethernet60 77,78,79,80 Ethernet20/1 20 +Ethernet64 93,94,95,96 Ethernet21/1 21 +Ethernet68 89,90,91,92 Ethernet22/1 22 +Ethernet72 97,98,99,100 Ethernet23/1 23 +Ethernet76 101,102,103,104 Ethernet24/1 24 +Ethernet80 109,110,111,112 Ethernet25/1 25 +Ethernet84 105,106,107,108 Ethernet26/1 26 +Ethernet88 121,122,123,124 Ethernet27/1 27 +Ethernet92 125,126,127,128 Ethernet28/1 28 +Ethernet96 61,62,63,64 Ethernet29 29 +Ethernet100 57,58,59,60 Ethernet30 30 +Ethernet104 81,82,83,84 Ethernet31 31 +Ethernet108 85,86,87,88 Ethernet32 32 +Ethernet112 117,118,119,120 Ethernet33 33 +Ethernet116 113,114,115,116 Ethernet34 34 +Ethernet120 1,2,3,4 Ethernet35 35 +Ethernet124 5,6,7,8 Ethernet36 36 diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/qos.json.j2 b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/qos.json.j2 new file mode 100644 index 000000000000..1accac3ddd0d --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/qos.json.j2 @@ -0,0 +1,148 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable": "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"312000", + "red_min_threshold":"104000", + "yellow_max_threshold":"312000", + "yellow_min_threshold":"104000", + "green_max_threshold":"312000", + "green_min_threshold":"104000" + } + }, + "QUEUE": { + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|3-4" : { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|3" : { + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|4" : { + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0" : { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|1" : { + "scheduler" : "[SCHEDULER|scheduler.2]" + } + } +} diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/sai.profile b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/sai.profile new file mode 100644 index 000000000000..9a50433cabdc --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-a7050-q31s4-31x40G-4x10G.config.bcm diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/td2-a7050-q31s4-31x40G-4x10G.config.bcm b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/td2-a7050-q31s4-31x40G-4x10G.config.bcm new file mode 100644 index 000000000000..4819c7929ecd --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/td2-a7050-q31s4-31x40G-4x10G.config.bcm @@ -0,0 +1,675 @@ +arl_clean_timeout_usec=15000000 +bcm_num_cos.0=8 +bcm_stat_flags=1 +bcm_stat_jumbo.0=9236 +cdma_timeout_usec.0=15000000 +dma_desc_timeout_usec.0=15000000 +higig2_hdr_mode.0=1 +ipv6_lpm_128b_enable.0=2 +l2xmsg_mode.0=1 +max_vp_lags.0=0 +mdio_output_delay=0x0d +miim_intr_enable.0=0 +module_64ports.0=0 +os=unix +pbmp_oversubscribe.0=0x1fffffffffffffffffffffffffe +pbmp_xport_xe.0=0x1fffffffffffffffffffffffffe +phy_an_c37_1.0=3 +phy_an_c37_5.0=3 +phy_an_c37_9.0=3 +phy_an_c37_13.0=3 +phy_an_c37_17.0=3 +phy_an_c37_21.0=3 +phy_an_c37_25.0=3 +phy_an_c37_29.0=3 +phy_an_c37_33.0=3 +phy_an_c37_37.0=3 +phy_an_c37_41.0=3 +phy_an_c37_45.0=3 +phy_an_c37_49.0=3 +phy_an_c37_53.0=3 +phy_an_c37_57.0=3 +phy_an_c37_61.0=3 +phy_an_c37_65.0=3 +phy_an_c37_69.0=3 +phy_an_c37_73.0=3 +phy_an_c37_77.0=3 +phy_an_c37_81.0=3 +phy_an_c37_85.0=3 +phy_an_c37_89.0=3 +phy_an_c37_93.0=3 +phy_an_c37_97.0=0 +phy_an_c37_98.0=0 +phy_an_c37_99.0=0 +phy_an_c37_100.0=0 +phy_an_c37_101.0=0 +phy_an_c37_102.0=0 +phy_an_c37_103.0=0 +phy_an_c37_104.0=0 +phy_an_c73_1.0=0 +phy_an_c73_5.0=0 +phy_an_c73_9.0=0 +phy_an_c73_13.0=0 +phy_an_c73_17.0=0 +phy_an_c73_21.0=0 +phy_an_c73_25.0=0 +phy_an_c73_29.0=0 +phy_an_c73_33.0=0 +phy_an_c73_37.0=0 +phy_an_c73_41.0=0 +phy_an_c73_45.0=0 +phy_an_c73_49.0=0 +phy_an_c73_53.0=0 +phy_an_c73_57.0=0 +phy_an_c73_61.0=0 +phy_an_c73_65.0=0 +phy_an_c73_69.0=0 +phy_an_c73_73.0=0 +phy_an_c73_77.0=0 +phy_an_c73_81.0=0 +phy_an_c73_85.0=0 +phy_an_c73_89.0=0 +phy_an_c73_93.0=0 +phy_an_c73_97.0=2 +phy_an_c73_98.0=2 +phy_an_c73_99.0=2 +phy_an_c73_100.0=2 +phy_an_c73_101.0=2 +phy_an_c73_102.0=2 +phy_an_c73_103.0=2 +phy_an_c73_104.0=2 +phy_xaui_rx_polarity_flip_1.0=0x0 +phy_xaui_rx_polarity_flip_5.0=0x0 +phy_xaui_rx_polarity_flip_9.0=0x4 +phy_xaui_rx_polarity_flip_13.0=0x0 +phy_xaui_rx_polarity_flip_17.0=0xb +phy_xaui_rx_polarity_flip_21.0=0x3 +phy_xaui_rx_polarity_flip_25.0=0xb +phy_xaui_rx_polarity_flip_29.0=0xf +phy_xaui_rx_polarity_flip_33.0=0xb +phy_xaui_rx_polarity_flip_37.0=0x3 +phy_xaui_rx_polarity_flip_41.0=0xb +phy_xaui_rx_polarity_flip_45.0=0x0 +phy_xaui_rx_polarity_flip_49.0=0x4 +phy_xaui_rx_polarity_flip_53.0=0xc +phy_xaui_rx_polarity_flip_57.0=0x4 +phy_xaui_rx_polarity_flip_61.0=0x0 +phy_xaui_rx_polarity_flip_65.0=0xb +phy_xaui_rx_polarity_flip_69.0=0x3 +phy_xaui_rx_polarity_flip_73.0=0xb +phy_xaui_rx_polarity_flip_77.0=0xf +phy_xaui_rx_polarity_flip_81.0=0xb +phy_xaui_rx_polarity_flip_85.0=0x3 +phy_xaui_rx_polarity_flip_89.0=0x4 +phy_xaui_rx_polarity_flip_93.0=0x0 +phy_xaui_rx_polarity_flip_97.0=0xb +phy_xaui_rx_polarity_flip_98.0=0x3 +phy_xaui_rx_polarity_flip_99.0=0x4 +phy_xaui_rx_polarity_flip_100.0=0x0 +phy_xaui_rx_polarity_flip_101.0=0x0 +phy_xaui_rx_polarity_flip_102.0=0xe +phy_xaui_rx_polarity_flip_103.0=0x0 +phy_xaui_rx_polarity_flip_104.0=0x0 +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_5.0=0x0 +phy_xaui_tx_polarity_flip_9.0=0x2 +phy_xaui_tx_polarity_flip_13.0=0x0 +phy_xaui_tx_polarity_flip_17.0=0xd +phy_xaui_tx_polarity_flip_21.0=0xc +phy_xaui_tx_polarity_flip_25.0=0xd +phy_xaui_tx_polarity_flip_29.0=0xf +phy_xaui_tx_polarity_flip_33.0=0xd +phy_xaui_tx_polarity_flip_37.0=0xc +phy_xaui_tx_polarity_flip_41.0=0xd +phy_xaui_tx_polarity_flip_45.0=0x0 +phy_xaui_tx_polarity_flip_49.0=0x2 +phy_xaui_tx_polarity_flip_53.0=0x3 +phy_xaui_tx_polarity_flip_57.0=0x2 +phy_xaui_tx_polarity_flip_61.0=0x0 +phy_xaui_tx_polarity_flip_65.0=0xd +phy_xaui_tx_polarity_flip_69.0=0xc +phy_xaui_tx_polarity_flip_73.0=0xd +phy_xaui_tx_polarity_flip_77.0=0xf +phy_xaui_tx_polarity_flip_81.0=0xd +phy_xaui_tx_polarity_flip_85.0=0xc +phy_xaui_tx_polarity_flip_89.0=0x2 +phy_xaui_tx_polarity_flip_93.0=0x0 +phy_xaui_tx_polarity_flip_97.0=0xd +phy_xaui_tx_polarity_flip_98.0=0xc +phy_xaui_tx_polarity_flip_99.0=0x2 +phy_xaui_tx_polarity_flip_100.0=0x0 +phy_xaui_tx_polarity_flip_101.0=0x0 +phy_xaui_tx_polarity_flip_102.0=0x7 +phy_xaui_tx_polarity_flip_103.0=0x2 +phy_xaui_tx_polarity_flip_104.0=0x0 +port_init_autoneg_1.0=0 +port_init_autoneg_5.0=0 +port_init_autoneg_9.0=0 +port_init_autoneg_13.0=0 +port_init_autoneg_17.0=0 +port_init_autoneg_21.0=0 +port_init_autoneg_25.0=0 +port_init_autoneg_29.0=0 +port_init_autoneg_33.0=0 +port_init_autoneg_37.0=0 +port_init_autoneg_41.0=0 +port_init_autoneg_45.0=0 +port_init_autoneg_49.0=0 +port_init_autoneg_53.0=0 +port_init_autoneg_57.0=0 +port_init_autoneg_61.0=0 +port_init_autoneg_65.0=0 +port_init_autoneg_69.0=0 +port_init_autoneg_73.0=0 +port_init_autoneg_77.0=0 +port_init_autoneg_81.0=0 +port_init_autoneg_85.0=0 +port_init_autoneg_89.0=0 +port_init_autoneg_93.0=0 +port_init_autoneg_97.0=0 +port_init_autoneg_98.0=0 +port_init_autoneg_99.0=0 +port_init_autoneg_100.0=0 +port_init_autoneg_101.0=0 +port_init_autoneg_102.0=0 +port_init_autoneg_103.0=0 +port_init_autoneg_104.0=0 +port_init_cl72.0=0 +portmap_1.0=9:10 +portmap_2.0=10:10 +portmap_3.0=11:10 +portmap_4.0=12:10 +portmap_5.0=13:40 +portmap_9.0=17:40 +portmap_13.0=21:40 +portmap_17.0=29:40 +portmap_21.0=25:40 +portmap_25.0=33:40 +portmap_29.0=37:40 +portmap_33.0=45:40 +portmap_37.0=41:40 +portmap_41.0=49:40 +portmap_45.0=53:40 +portmap_49.0=69:40 +portmap_53.0=65:40 +portmap_57.0=73:40 +portmap_61.0=77:40 +portmap_65.0=93:40 +portmap_69.0=89:40 +portmap_73.0=97:40 +portmap_77.0=101:40 +portmap_81.0=109:40 +portmap_85.0=105:40 +portmap_89.0=121:40 +portmap_93.0=125:40 +portmap_97.0=61:40 +portmap_98.0=57:40 +portmap_99.0=81:40 +portmap_100.0=85:40 +portmap_101.0=117:40 +portmap_102.0=113:40 +portmap_103.0=1:40 +portmap_104.0=5:40 +schan_intr_enable=0 +serdes_firmware_mode_1.0=2 +serdes_firmware_mode_5.0=2 +serdes_firmware_mode_9.0=2 +serdes_firmware_mode_13.0=2 +serdes_firmware_mode_17.0=2 +serdes_firmware_mode_21.0=2 +serdes_firmware_mode_25.0=2 +serdes_firmware_mode_29.0=2 +serdes_firmware_mode_33.0=2 +serdes_firmware_mode_37.0=2 +serdes_firmware_mode_41.0=2 +serdes_firmware_mode_45.0=2 +serdes_firmware_mode_49.0=2 +serdes_firmware_mode_53.0=2 +serdes_firmware_mode_57.0=2 +serdes_firmware_mode_61.0=2 +serdes_firmware_mode_65.0=2 +serdes_firmware_mode_69.0=2 +serdes_firmware_mode_73.0=2 +serdes_firmware_mode_77.0=2 +serdes_firmware_mode_81.0=2 +serdes_firmware_mode_85.0=2 +serdes_firmware_mode_89.0=2 +serdes_firmware_mode_93.0=2 +serdes_firmware_mode_97.0=2 +serdes_firmware_mode_98.0=2 +serdes_firmware_mode_99.0=2 +serdes_firmware_mode_100.0=2 +serdes_firmware_mode_101.0=2 +serdes_firmware_mode_102.0=2 +serdes_firmware_mode_103.0=2 +serdes_firmware_mode_104.0=2 +stable_size=0x2000000 +tdma_timeout_usec.0=15000000 +tslam_timeout_usec.0=15000000 +xgxs_lcpll_xtal_refclk.0=1 +xgxs_rx_lane_map_1.0=0x3210 +xgxs_rx_lane_map_5.0=0x0321 +xgxs_rx_lane_map_9.0=0x1302 +xgxs_rx_lane_map_13.0=0x0213 +xgxs_rx_lane_map_17.0=0x1302 +xgxs_rx_lane_map_21.0=0x1302 +xgxs_rx_lane_map_25.0=0x1302 +xgxs_rx_lane_map_29.0=0x0213 +xgxs_rx_lane_map_33.0=0x1302 +xgxs_rx_lane_map_37.0=0x1302 +xgxs_rx_lane_map_41.0=0x1302 +xgxs_rx_lane_map_45.0=0x0213 +xgxs_rx_lane_map_49.0=0x1302 +xgxs_rx_lane_map_53.0=0x1302 +xgxs_rx_lane_map_57.0=0x1302 +xgxs_rx_lane_map_61.0=0x0213 +xgxs_rx_lane_map_65.0=0x1302 +xgxs_rx_lane_map_69.0=0x1302 +xgxs_rx_lane_map_73.0=0x1302 +xgxs_rx_lane_map_77.0=0x0213 +xgxs_rx_lane_map_81.0=0x1302 +xgxs_rx_lane_map_85.0=0x1302 +xgxs_rx_lane_map_89.0=0x1302 +xgxs_rx_lane_map_93.0=0x0213 +xgxs_rx_lane_map_97.0=0x1302 +xgxs_rx_lane_map_98.0=0x1302 +xgxs_rx_lane_map_99.0=0x1302 +xgxs_rx_lane_map_100.0=0x0213 +xgxs_rx_lane_map_101.0=0x0213 +xgxs_rx_lane_map_102.0=0x1302 +xgxs_rx_lane_map_103.0=0x0123 +xgxs_rx_lane_map_104.0=0x2031 +xgxs_tx_lane_map_1.0=0x0123 +xgxs_tx_lane_map_5.0=0x0321 +xgxs_tx_lane_map_9.0=0x2031 +xgxs_tx_lane_map_13.0=0x0213 +xgxs_tx_lane_map_17.0=0x2031 +xgxs_tx_lane_map_21.0=0x2031 +xgxs_tx_lane_map_25.0=0x2031 +xgxs_tx_lane_map_29.0=0x0213 +xgxs_tx_lane_map_33.0=0x2031 +xgxs_tx_lane_map_37.0=0x2031 +xgxs_tx_lane_map_41.0=0x2031 +xgxs_tx_lane_map_45.0=0x0213 +xgxs_tx_lane_map_49.0=0x2031 +xgxs_tx_lane_map_53.0=0x2031 +xgxs_tx_lane_map_57.0=0x2031 +xgxs_tx_lane_map_61.0=0x0213 +xgxs_tx_lane_map_65.0=0x2031 +xgxs_tx_lane_map_69.0=0x2031 +xgxs_tx_lane_map_73.0=0x2031 +xgxs_tx_lane_map_77.0=0x0213 +xgxs_tx_lane_map_81.0=0x2031 +xgxs_tx_lane_map_85.0=0x2031 +xgxs_tx_lane_map_89.0=0x2031 +xgxs_tx_lane_map_93.0=0x0213 +xgxs_tx_lane_map_97.0=0x2031 +xgxs_tx_lane_map_98.0=0x2031 +xgxs_tx_lane_map_99.0=0x2031 +xgxs_tx_lane_map_100.0=0x0213 +xgxs_tx_lane_map_101.0=0x0213 +xgxs_tx_lane_map_102.0=0x2031 +xgxs_tx_lane_map_103.0=0x3120 +xgxs_tx_lane_map_104.0=0x1302 + +# tuning parameters +serdes_preemphasis_lane0_1.0=0x81f7 +serdes_preemphasis_lane1_1.0=0x81f7 +serdes_preemphasis_lane2_1.0=0x81f7 +serdes_preemphasis_lane3_1.0=0x81f7 +serdes_pre_driver_current_lane0_5.0=0x7 +serdes_driver_current_lane0_5.0=0x7 +serdes_preemphasis_lane0_5.0=0xc2f0 +serdes_pre_driver_current_lane1_5.0=0x7 +serdes_driver_current_lane1_5.0=0x7 +serdes_preemphasis_lane1_5.0=0xc2f0 +serdes_pre_driver_current_lane2_5.0=0x7 +serdes_driver_current_lane2_5.0=0x7 +serdes_preemphasis_lane2_5.0=0xc2f0 +serdes_pre_driver_current_lane3_5.0=0x7 +serdes_driver_current_lane3_5.0=0x7 +serdes_preemphasis_lane3_5.0=0xc2f0 +serdes_pre_driver_current_lane0_9.0=0x7 +serdes_driver_current_lane0_9.0=0x7 +serdes_preemphasis_lane0_9.0=0xbb10 +serdes_pre_driver_current_lane1_9.0=0x7 +serdes_driver_current_lane1_9.0=0x7 +serdes_preemphasis_lane1_9.0=0xbb10 +serdes_pre_driver_current_lane2_9.0=0x7 +serdes_driver_current_lane2_9.0=0x7 +serdes_preemphasis_lane2_9.0=0xbb10 +serdes_pre_driver_current_lane3_9.0=0x7 +serdes_driver_current_lane3_9.0=0x7 +serdes_preemphasis_lane3_9.0=0xbb10 +serdes_pre_driver_current_lane0_13.0=0x7 +serdes_driver_current_lane0_13.0=0x7 +serdes_preemphasis_lane0_13.0=0xbb10 +serdes_pre_driver_current_lane1_13.0=0x7 +serdes_driver_current_lane1_13.0=0x7 +serdes_preemphasis_lane1_13.0=0xbb10 +serdes_pre_driver_current_lane2_13.0=0x7 +serdes_driver_current_lane2_13.0=0x7 +serdes_preemphasis_lane2_13.0=0xbb10 +serdes_pre_driver_current_lane3_13.0=0x7 +serdes_driver_current_lane3_13.0=0x7 +serdes_preemphasis_lane3_13.0=0xbb10 +serdes_pre_driver_current_lane0_17.0=0x6 +serdes_driver_current_lane0_17.0=0x6 +serdes_preemphasis_lane0_17.0=0xb720 +serdes_pre_driver_current_lane1_17.0=0x6 +serdes_driver_current_lane1_17.0=0x6 +serdes_preemphasis_lane1_17.0=0xb720 +serdes_pre_driver_current_lane2_17.0=0x6 +serdes_driver_current_lane2_17.0=0x6 +serdes_preemphasis_lane2_17.0=0xb720 +serdes_pre_driver_current_lane3_17.0=0x6 +serdes_driver_current_lane3_17.0=0x6 +serdes_preemphasis_lane3_17.0=0xb720 +serdes_pre_driver_current_lane0_21.0=0x7 +serdes_driver_current_lane0_21.0=0x7 +serdes_preemphasis_lane0_21.0=0xbb10 +serdes_pre_driver_current_lane1_21.0=0x7 +serdes_driver_current_lane1_21.0=0x7 +serdes_preemphasis_lane1_21.0=0xbb10 +serdes_pre_driver_current_lane2_21.0=0x7 +serdes_driver_current_lane2_21.0=0x7 +serdes_preemphasis_lane2_21.0=0xbb10 +serdes_pre_driver_current_lane3_21.0=0x7 +serdes_driver_current_lane3_21.0=0x7 +serdes_preemphasis_lane3_21.0=0xbb10 +serdes_pre_driver_current_lane0_25.0=0x5 +serdes_driver_current_lane0_25.0=0x5 +serdes_preemphasis_lane0_25.0=0xb720 +serdes_pre_driver_current_lane1_25.0=0x5 +serdes_driver_current_lane1_25.0=0x5 +serdes_preemphasis_lane1_25.0=0xb720 +serdes_pre_driver_current_lane2_25.0=0x5 +serdes_driver_current_lane2_25.0=0x5 +serdes_preemphasis_lane2_25.0=0xb720 +serdes_pre_driver_current_lane3_25.0=0x5 +serdes_driver_current_lane3_25.0=0x5 +serdes_preemphasis_lane3_25.0=0xb720 +serdes_pre_driver_current_lane0_29.0=0x5 +serdes_driver_current_lane0_29.0=0x5 +serdes_preemphasis_lane0_29.0=0xb720 +serdes_pre_driver_current_lane1_29.0=0x5 +serdes_driver_current_lane1_29.0=0x5 +serdes_preemphasis_lane1_29.0=0xb720 +serdes_pre_driver_current_lane2_29.0=0x5 +serdes_driver_current_lane2_29.0=0x5 +serdes_preemphasis_lane2_29.0=0xb720 +serdes_pre_driver_current_lane3_29.0=0x5 +serdes_driver_current_lane3_29.0=0x5 +serdes_preemphasis_lane3_29.0=0xb720 +serdes_pre_driver_current_lane0_33.0=0x4 +serdes_driver_current_lane0_33.0=0x4 +serdes_preemphasis_lane0_33.0=0xb720 +serdes_pre_driver_current_lane1_33.0=0x4 +serdes_driver_current_lane1_33.0=0x4 +serdes_preemphasis_lane1_33.0=0xb720 +serdes_pre_driver_current_lane2_33.0=0x4 +serdes_driver_current_lane2_33.0=0x4 +serdes_preemphasis_lane2_33.0=0xb720 +serdes_pre_driver_current_lane3_33.0=0x4 +serdes_driver_current_lane3_33.0=0x4 +serdes_preemphasis_lane3_33.0=0xb720 +serdes_pre_driver_current_lane0_37.0=0x5 +serdes_driver_current_lane0_37.0=0x5 +serdes_preemphasis_lane0_37.0=0xb720 +serdes_pre_driver_current_lane1_37.0=0x5 +serdes_driver_current_lane1_37.0=0x5 +serdes_preemphasis_lane1_37.0=0xb720 +serdes_pre_driver_current_lane2_37.0=0x5 +serdes_driver_current_lane2_37.0=0x5 +serdes_preemphasis_lane2_37.0=0xb720 +serdes_pre_driver_current_lane3_37.0=0x5 +serdes_driver_current_lane3_37.0=0x5 +serdes_preemphasis_lane3_37.0=0xb720 +serdes_pre_driver_current_lane0_41.0=0x3 +serdes_driver_current_lane0_41.0=0x3 +serdes_preemphasis_lane0_41.0=0xb330 +serdes_pre_driver_current_lane1_41.0=0x3 +serdes_driver_current_lane1_41.0=0x3 +serdes_preemphasis_lane1_41.0=0xb330 +serdes_pre_driver_current_lane2_41.0=0x3 +serdes_driver_current_lane2_41.0=0x3 +serdes_preemphasis_lane2_41.0=0xb330 +serdes_pre_driver_current_lane3_41.0=0x3 +serdes_driver_current_lane3_41.0=0x3 +serdes_preemphasis_lane3_41.0=0xb330 +serdes_pre_driver_current_lane0_45.0=0x4 +serdes_driver_current_lane0_45.0=0x4 +serdes_preemphasis_lane0_45.0=0xb720 +serdes_pre_driver_current_lane1_45.0=0x4 +serdes_driver_current_lane1_45.0=0x4 +serdes_preemphasis_lane1_45.0=0xb720 +serdes_pre_driver_current_lane2_45.0=0x4 +serdes_driver_current_lane2_45.0=0x4 +serdes_preemphasis_lane2_45.0=0xb720 +serdes_pre_driver_current_lane3_45.0=0x4 +serdes_driver_current_lane3_45.0=0x4 +serdes_preemphasis_lane3_45.0=0xb720 +serdes_pre_driver_current_lane0_49.0=0x3 +serdes_driver_current_lane0_49.0=0x3 +serdes_preemphasis_lane0_49.0=0xb330 +serdes_pre_driver_current_lane1_49.0=0x3 +serdes_driver_current_lane1_49.0=0x3 +serdes_preemphasis_lane1_49.0=0xb330 +serdes_pre_driver_current_lane2_49.0=0x3 +serdes_driver_current_lane2_49.0=0x3 +serdes_preemphasis_lane2_49.0=0xb330 +serdes_pre_driver_current_lane3_49.0=0x3 +serdes_driver_current_lane3_49.0=0x3 +serdes_preemphasis_lane3_49.0=0xb330 +serdes_pre_driver_current_lane0_53.0=0x4 +serdes_driver_current_lane0_53.0=0x4 +serdes_preemphasis_lane0_53.0=0xb720 +serdes_pre_driver_current_lane1_53.0=0x4 +serdes_driver_current_lane1_53.0=0x4 +serdes_preemphasis_lane1_53.0=0xb720 +serdes_pre_driver_current_lane2_53.0=0x4 +serdes_driver_current_lane2_53.0=0x4 +serdes_preemphasis_lane2_53.0=0xb720 +serdes_pre_driver_current_lane3_53.0=0x4 +serdes_driver_current_lane3_53.0=0x4 +serdes_preemphasis_lane3_53.0=0xb720 +serdes_pre_driver_current_lane0_57.0=0x3 +serdes_driver_current_lane0_57.0=0x3 +serdes_preemphasis_lane0_57.0=0xb330 +serdes_pre_driver_current_lane1_57.0=0x3 +serdes_driver_current_lane1_57.0=0x3 +serdes_preemphasis_lane1_57.0=0xb330 +serdes_pre_driver_current_lane2_57.0=0x3 +serdes_driver_current_lane2_57.0=0x3 +serdes_preemphasis_lane2_57.0=0xb330 +serdes_pre_driver_current_lane3_57.0=0x3 +serdes_driver_current_lane3_57.0=0x3 +serdes_preemphasis_lane3_57.0=0xb330 +serdes_pre_driver_current_lane0_61.0=0x4 +serdes_driver_current_lane0_61.0=0x4 +serdes_preemphasis_lane0_61.0=0xb720 +serdes_pre_driver_current_lane1_61.0=0x4 +serdes_driver_current_lane1_61.0=0x4 +serdes_preemphasis_lane1_61.0=0xb720 +serdes_pre_driver_current_lane2_61.0=0x4 +serdes_driver_current_lane2_61.0=0x4 +serdes_preemphasis_lane2_61.0=0xb720 +serdes_pre_driver_current_lane3_61.0=0x4 +serdes_driver_current_lane3_61.0=0x4 +serdes_preemphasis_lane3_61.0=0xb720 +serdes_pre_driver_current_lane0_65.0=0x4 +serdes_driver_current_lane0_65.0=0x4 +serdes_preemphasis_lane0_65.0=0xb720 +serdes_pre_driver_current_lane1_65.0=0x4 +serdes_driver_current_lane1_65.0=0x4 +serdes_preemphasis_lane1_65.0=0xb720 +serdes_pre_driver_current_lane2_65.0=0x4 +serdes_driver_current_lane2_65.0=0x4 +serdes_preemphasis_lane2_65.0=0xb720 +serdes_pre_driver_current_lane3_65.0=0x4 +serdes_driver_current_lane3_65.0=0x4 +serdes_preemphasis_lane3_65.0=0xb720 +serdes_pre_driver_current_lane0_69.0=0x4 +serdes_driver_current_lane0_69.0=0x4 +serdes_preemphasis_lane0_69.0=0xb720 +serdes_pre_driver_current_lane1_69.0=0x4 +serdes_driver_current_lane1_69.0=0x4 +serdes_preemphasis_lane1_69.0=0xb720 +serdes_pre_driver_current_lane2_69.0=0x4 +serdes_driver_current_lane2_69.0=0x4 +serdes_preemphasis_lane2_69.0=0xb720 +serdes_pre_driver_current_lane3_69.0=0x4 +serdes_driver_current_lane3_69.0=0x4 +serdes_preemphasis_lane3_69.0=0xb720 +serdes_pre_driver_current_lane0_73.0=0x4 +serdes_driver_current_lane0_73.0=0x4 +serdes_preemphasis_lane0_73.0=0xb720 +serdes_pre_driver_current_lane1_73.0=0x4 +serdes_driver_current_lane1_73.0=0x4 +serdes_preemphasis_lane1_73.0=0xb720 +serdes_pre_driver_current_lane2_73.0=0x4 +serdes_driver_current_lane2_73.0=0x4 +serdes_preemphasis_lane2_73.0=0xb720 +serdes_pre_driver_current_lane3_73.0=0x4 +serdes_driver_current_lane3_73.0=0x4 +serdes_preemphasis_lane3_73.0=0xb720 +serdes_pre_driver_current_lane0_77.0=0x5 +serdes_driver_current_lane0_77.0=0x5 +serdes_preemphasis_lane0_77.0=0xb720 +serdes_pre_driver_current_lane1_77.0=0x5 +serdes_driver_current_lane1_77.0=0x5 +serdes_preemphasis_lane1_77.0=0xb720 +serdes_pre_driver_current_lane2_77.0=0x5 +serdes_driver_current_lane2_77.0=0x5 +serdes_preemphasis_lane2_77.0=0xb720 +serdes_pre_driver_current_lane3_77.0=0x5 +serdes_driver_current_lane3_77.0=0x5 +serdes_preemphasis_lane3_77.0=0xb720 +serdes_pre_driver_current_lane0_81.0=0x5 +serdes_driver_current_lane0_81.0=0x5 +serdes_preemphasis_lane0_81.0=0xb720 +serdes_pre_driver_current_lane1_81.0=0x5 +serdes_driver_current_lane1_81.0=0x5 +serdes_preemphasis_lane1_81.0=0xb720 +serdes_pre_driver_current_lane2_81.0=0x5 +serdes_driver_current_lane2_81.0=0x5 +serdes_preemphasis_lane2_81.0=0xb720 +serdes_pre_driver_current_lane3_81.0=0x5 +serdes_driver_current_lane3_81.0=0x5 +serdes_preemphasis_lane3_81.0=0xb720 +serdes_pre_driver_current_lane0_85.0=0x5 +serdes_driver_current_lane0_85.0=0x5 +serdes_preemphasis_lane0_85.0=0xb720 +serdes_pre_driver_current_lane1_85.0=0x5 +serdes_driver_current_lane1_85.0=0x5 +serdes_preemphasis_lane1_85.0=0xb720 +serdes_pre_driver_current_lane2_85.0=0x5 +serdes_driver_current_lane2_85.0=0x5 +serdes_preemphasis_lane2_85.0=0xb720 +serdes_pre_driver_current_lane3_85.0=0x5 +serdes_driver_current_lane3_85.0=0x5 +serdes_preemphasis_lane3_85.0=0xb720 +serdes_pre_driver_current_lane0_89.0=0x6 +serdes_driver_current_lane0_89.0=0x6 +serdes_preemphasis_lane0_89.0=0xb720 +serdes_pre_driver_current_lane1_89.0=0x6 +serdes_driver_current_lane1_89.0=0x6 +serdes_preemphasis_lane1_89.0=0xb720 +serdes_pre_driver_current_lane2_89.0=0x6 +serdes_driver_current_lane2_89.0=0x6 +serdes_preemphasis_lane2_89.0=0xb720 +serdes_pre_driver_current_lane3_89.0=0x6 +serdes_driver_current_lane3_89.0=0x6 +serdes_preemphasis_lane3_89.0=0xb720 +serdes_pre_driver_current_lane0_93.0=0x7 +serdes_driver_current_lane0_93.0=0x7 +serdes_preemphasis_lane0_93.0=0xbb10 +serdes_pre_driver_current_lane1_93.0=0x7 +serdes_driver_current_lane1_93.0=0x7 +serdes_preemphasis_lane1_93.0=0xbb10 +serdes_pre_driver_current_lane2_93.0=0x7 +serdes_driver_current_lane2_93.0=0x7 +serdes_preemphasis_lane2_93.0=0xbb10 +serdes_pre_driver_current_lane3_93.0=0x7 +serdes_driver_current_lane3_93.0=0x7 +serdes_preemphasis_lane3_93.0=0xbb10 +serdes_pre_driver_current_lane0_97.0=0x5 +serdes_driver_current_lane0_97.0=0x5 +serdes_preemphasis_lane0_97.0=0xb720 +serdes_pre_driver_current_lane1_97.0=0x5 +serdes_driver_current_lane1_97.0=0x5 +serdes_preemphasis_lane1_97.0=0xb720 +serdes_pre_driver_current_lane2_97.0=0x5 +serdes_driver_current_lane2_97.0=0x5 +serdes_preemphasis_lane2_97.0=0xb720 +serdes_pre_driver_current_lane3_97.0=0x5 +serdes_driver_current_lane3_97.0=0x5 +serdes_preemphasis_lane3_97.0=0xb720 +serdes_pre_driver_current_lane0_98.0=0x6 +serdes_driver_current_lane0_98.0=0x6 +serdes_preemphasis_lane0_98.0=0xb720 +serdes_pre_driver_current_lane1_98.0=0x6 +serdes_driver_current_lane1_98.0=0x6 +serdes_preemphasis_lane1_98.0=0xb720 +serdes_pre_driver_current_lane2_98.0=0x6 +serdes_driver_current_lane2_98.0=0x6 +serdes_preemphasis_lane2_98.0=0xb720 +serdes_pre_driver_current_lane3_98.0=0x6 +serdes_driver_current_lane3_98.0=0x6 +serdes_preemphasis_lane3_98.0=0xb720 +serdes_pre_driver_current_lane0_99.0=0x5 +serdes_driver_current_lane0_99.0=0x5 +serdes_preemphasis_lane0_99.0=0xb720 +serdes_pre_driver_current_lane1_99.0=0x5 +serdes_driver_current_lane1_99.0=0x5 +serdes_preemphasis_lane1_99.0=0xb720 +serdes_pre_driver_current_lane2_99.0=0x5 +serdes_driver_current_lane2_99.0=0x5 +serdes_preemphasis_lane2_99.0=0xb720 +serdes_pre_driver_current_lane3_99.0=0x5 +serdes_driver_current_lane3_99.0=0x5 +serdes_preemphasis_lane3_99.0=0xb720 +serdes_pre_driver_current_lane0_100.0=0x7 +serdes_driver_current_lane0_100.0=0x7 +serdes_preemphasis_lane0_100.0=0xbb10 +serdes_pre_driver_current_lane1_100.0=0x7 +serdes_driver_current_lane1_100.0=0x7 +serdes_preemphasis_lane1_100.0=0xbb10 +serdes_pre_driver_current_lane2_100.0=0x7 +serdes_driver_current_lane2_100.0=0x7 +serdes_preemphasis_lane2_100.0=0xbb10 +serdes_pre_driver_current_lane3_100.0=0x7 +serdes_driver_current_lane3_100.0=0x7 +serdes_preemphasis_lane3_100.0=0xbb10 +serdes_pre_driver_current_lane0_101.0=0x7 +serdes_driver_current_lane0_101.0=0x7 +serdes_preemphasis_lane0_101.0=0xbb10 +serdes_pre_driver_current_lane1_101.0=0x7 +serdes_driver_current_lane1_101.0=0x7 +serdes_preemphasis_lane1_101.0=0xbb10 +serdes_pre_driver_current_lane2_101.0=0x7 +serdes_driver_current_lane2_101.0=0x7 +serdes_preemphasis_lane2_101.0=0xbb10 +serdes_pre_driver_current_lane3_101.0=0x7 +serdes_driver_current_lane3_101.0=0x7 +serdes_preemphasis_lane3_101.0=0xbb10 +serdes_pre_driver_current_lane0_102.0=0x7 +serdes_driver_current_lane0_102.0=0x7 +serdes_preemphasis_lane0_102.0=0xbb10 +serdes_pre_driver_current_lane1_102.0=0x7 +serdes_driver_current_lane1_102.0=0x7 +serdes_preemphasis_lane1_102.0=0xbb10 +serdes_pre_driver_current_lane2_102.0=0x7 +serdes_driver_current_lane2_102.0=0x7 +serdes_preemphasis_lane2_102.0=0xbb10 +serdes_pre_driver_current_lane3_102.0=0x7 +serdes_driver_current_lane3_102.0=0x7 +serdes_preemphasis_lane3_102.0=0xbb10 +serdes_preemphasis_lane0_103.0=0x81f4 +serdes_preemphasis_lane1_103.0=0x81f4 +serdes_preemphasis_lane2_103.0=0x81f4 +serdes_preemphasis_lane3_103.0=0x81f4 +serdes_preemphasis_lane0_104.0=0x81f5 +serdes_preemphasis_lane1_104.0=0x81f5 +serdes_preemphasis_lane2_104.0=0x81f5 +serdes_preemphasis_lane3_104.0=0x81f5 diff --git a/device/arista/x86_64-arista_7050_qx32s/default_sku b/device/arista/x86_64-arista_7050_qx32s/default_sku new file mode 100644 index 000000000000..657093e0b603 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/default_sku @@ -0,0 +1 @@ +Arista-7050-QX-32S t1 diff --git a/device/arista/x86_64-arista_7050_qx32s/fancontrol b/device/arista/x86_64-arista_7050_qx32s/fancontrol new file mode 100644 index 000000000000..9c329897c9e4 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=5 +DEVPATH=hwmon2=devices/pci0000:00/0000:00:02.2/0000:02:00.0/i2c-2/2-004c hwmon4=devices/pci0000:00/0000:00:02.2/0000:02:00.0/i2c-3/3-0060 +DEVNAME=hwmon2=max6658 hwmon4=crow_cpld +FCTEMPS=hwmon4/pwm4=hwmon2/temp1_input hwmon4/pwm3=hwmon2/temp1_input hwmon4/pwm2=hwmon2/temp1_input hwmon4/pwm1=hwmon2/temp1_input +FCFANS=hwmon4/pwm4=hwmon4/fan4_input hwmon4/pwm3=hwmon4/fan3_input hwmon4/pwm2=hwmon4/fan2_input hwmon4/pwm1=hwmon4/fan1_input +MINTEMP=hwmon4/pwm4=35 hwmon4/pwm3=35 hwmon4/pwm2=35 hwmon4/pwm1=35 +MINPWM=hwmon4/pwm4=179 hwmon4/pwm3=179 hwmon4/pwm2=179 hwmon4/pwm1=179 +MAXTEMP=hwmon4/pwm4=45 hwmon4/pwm3=45 hwmon4/pwm2=45 hwmon4/pwm1=45 +MINSTART=hwmon4/pwm4=179 hwmon4/pwm3=179 hwmon4/pwm2=179 hwmon4/pwm1=179 +MINSTOP=hwmon4/pwm4=179 hwmon4/pwm3=179 hwmon4/pwm2=179 hwmon4/pwm1=179 diff --git a/device/arista/x86_64-arista_7050_qx32s/platform_reboot b/device/arista/x86_64-arista_7050_qx32s/platform_reboot new file mode 100755 index 000000000000..6e9da639509d --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/platform_reboot @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# Copyright (c) 2018 Arista Networks, Inc. All rights reserved. +# Arista Networks, Inc. Confidential and Proprietary. + +# Reboot script for 7050QX-32S + +from __future__ import print_function +import sys +import mmap, os +import subprocess +from struct import pack, unpack + +class MmapResource( object ): + """Resource implementation for a directly-mapped memory region.""" + + def __init__( self, path ): + try: + fd = os.open( path, os.O_RDWR ) + except EnvironmentError: + print( "FAIL can not open scd memory-map resource file" ) + print( "FAIL are you running on the proper platform?" ) + sys.exit( 1 ) + try: + size = os.fstat( fd ).st_size + except EnvironmentError: + print( "FAIL can not fstat scd memory-map resource file" ) + print( "FAIL are you running on the proper platform?" ) + sys.exit( 1 ) + try: + self.mmap_ = mmap.mmap( fd, size, mmap.MAP_SHARED, + mmap.PROT_READ | mmap.PROT_WRITE ) + except EnvironmentError: + print( "FAIL can not map scd memory-map file" ) + print( "FAIL are you running on the proper platform?" ) + sys.exit( 1 ) + finally: + try: + # Note that closing the file descriptor has no effect on the memory map + os.close( fd ) + except EnvironmentError: + print( "FAIL failed to close scd memory-map file" ) + sys.exit( 1 ) + + def read32( self, addr ): + return unpack( ' + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + psu_location = ["R", "L"] + status = 0 + try: + with open(self.psu_path + self.psu_oper_status.format(psu_location[index - 1]), 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + psu_location = ["R", "L"] + status = 0 + try: + with open(self.psu_path + self.psu_presence.format(psu_location[index - 1]), 'r') as psu_prs: + status = int(psu_prs.read()) + except IOError: + return False + + return status == 1 diff --git a/device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py new file mode 100644 index 000000000000..5e7d287ef543 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python + +try: + 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 = 1 + PORT_END = 52 + port_to_i2c_mapping = { + 1: None, + 2: None, + 3: None, + 4: None, + 5: None, + 6: None, + 7: None, + 8: None, + 9: None, + 10: None, + 11: None, + 12: None, + 13: None, + 14: None, + 15: None, + 16: None, + 17: None, + 18: None, + 19: None, + 20: None, + 21: None, + 22: None, + 23: None, + 24: None, + 25: None, + 26: None, + 27: None, + 28: None, + 29: None, + 30: None, + 31: None, + 32: None, + 33: None, + 34: None, + 35: None, + 36: None, + 37: None, + 38: None, + 39: None, + 40: None, + 41: None, + 42: None, + 43: None, + 44: None, + 45: None, + 46: None, + 47: None, + 48: None, + 49: 15, + 50: 14, + 51: 17, + 52: 16 + } + _port_to_eeprom_mapping = {} + _sfp_port = range(49, PORT_END + 1) + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return [] + + @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): + 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): + sfp_modabs_path = '/sys/devices/platform/e1031.smc/SFP/sfp_modabs' + + if port_num not in self._sfp_port: + return False + + status = 1 + try: + with open(sfp_modabs_path, 'r') as port_status: + status = int(port_status.read(), 16) + status = (status >> (port_num - 49)) & 1 + except IOError: + return False + + return status == 0 + + 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 + + def get_transceiver_change_event(self, timeout=0): + modabs_interrupt_path = '/sys/devices/platform/e1031.smc/SFP/modabs_int' + ports_evt = {} + try: + with open(modabs_interrupt_path, 'r') as port_changes: + changes = int(port_changes.read(), 16) + for port_num in self._sfp_port: + change = (changes >> ( port_num - 49)) & 1 + if change == 1: + ports_evt[str(port_num)] = str(self.get_presence(port_num)) + except IOError: + return False, {} + return True, ports_evt diff --git a/device/celestica/x86_64-cel_e1031-r0/sensors.conf b/device/celestica/x86_64-cel_e1031-r0/sensors.conf new file mode 100644 index 000000000000..25c6047137b6 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sensors.conf @@ -0,0 +1,33 @@ +# libsensors configuration file for Celestica E1031. +# The i2c bus portion is omit because adapter name +# changes every time when system boot up. + +bus "i2c-3" "i2c-0-mux (chan_id 1)" +bus "i2c-11" "i2c-8-mux (chan_id 1)" + +chip "max6697-i2c-3-1a" + label temp1 "CPU board temperature sensor : 1" + label temp2 "CPU board temperature sensor : 2" + label temp3 "CPU board temperature sensor : 3" + ignore temp4 + ignore temp5 + ignore temp6 + ignore temp7 + +chip "max6697-i2c-11-1a" + label temp1 "Main board temperature sensor : 1" + label temp2 "Main board temperature sensor : 2" + label temp3 "Main board temperature sensor : 3" + label temp4 "Main board temperature sensor : 4" + label temp5 "Main board temperature sensor : 5" + ignore temp6 + ignore temp7 + + +chip "emc2305-i2c-*-4d" + ignore fan3 + ignore fan5 + label fan4 "Fan 1 :" + label fan2 "Fan 2 :" + label fan1 "Fan 3 :" + diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/port_config.ini b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/port_config.ini new file mode 100644 index 000000000000..7f977a26e1f3 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/port_config.ini @@ -0,0 +1,113 @@ +# name lanes alias index speed +Ethernet0 65 Eth1/1 1 10000 +Ethernet1 66 Eth1/2 1 10000 +Ethernet2 67 Eth1/3 1 10000 +Ethernet3 68 Eth1/4 1 10000 +Ethernet4 69 Eth2/1 2 10000 +Ethernet5 70 Eth2/2 2 10000 +Ethernet6 71 Eth2/3 2 10000 +Ethernet7 72 Eth2/4 2 10000 +Ethernet8 73 Eth3/1 3 10000 +Ethernet9 74 Eth3/2 3 10000 +Ethernet10 75 Eth3/3 3 10000 +Ethernet11 76 Eth3/4 3 10000 +Ethernet12 77 Eth4/1 4 10000 +Ethernet13 78 Eth4/2 4 10000 +Ethernet14 79 Eth4/3 4 10000 +Ethernet15 80 Eth4/4 4 10000 +Ethernet16 33 Eth5/1 5 10000 +Ethernet17 34 Eth5/2 5 10000 +Ethernet18 35 Eth5/3 5 10000 +Ethernet19 36 Eth5/4 5 10000 +Ethernet20 37 Eth6/1 6 10000 +Ethernet21 38 Eth6/2 6 10000 +Ethernet22 39 Eth6/3 6 10000 +Ethernet23 40 Eth6/4 6 10000 +Ethernet24 41 Eth7/1 7 10000 +Ethernet25 42 Eth7/2 7 10000 +Ethernet26 43 Eth7/3 7 10000 +Ethernet27 44 Eth7/4 7 10000 +Ethernet28 45 Eth8/1 8 10000 +Ethernet29 46 Eth8/2 8 10000 +Ethernet30 47 Eth8/3 8 10000 +Ethernet31 48 Eth8/4 8 10000 +Ethernet32 49 Eth9/1 9 10000 +Ethernet33 50 Eth9/2 9 10000 +Ethernet34 51 Eth9/3 9 10000 +Ethernet35 52 Eth9/4 9 10000 +Ethernet36 53 Eth10/1 10 10000 +Ethernet37 54 Eth10/2 10 10000 +Ethernet38 55 Eth10/3 10 10000 +Ethernet39 56 Eth10/4 10 10000 +Ethernet40 57 Eth11/1 11 10000 +Ethernet41 58 Eth11/2 11 10000 +Ethernet42 59 Eth11/3 11 10000 +Ethernet43 60 Eth11/4 11 10000 +Ethernet44 61 Eth12/1 12 10000 +Ethernet45 62 Eth12/2 12 10000 +Ethernet46 63 Eth12/3 12 10000 +Ethernet47 64 Eth12/4 12 10000 +Ethernet48 81 Eth13/1 13 10000 +Ethernet49 82 Eth13/2 13 10000 +Ethernet50 83 Eth13/3 13 10000 +Ethernet51 84 Eth13/4 13 10000 +Ethernet52 85 Eth14/1 14 10000 +Ethernet53 86 Eth14/2 14 10000 +Ethernet54 87 Eth14/3 14 10000 +Ethernet55 88 Eth14/4 14 10000 +Ethernet56 89 Eth15/1 15 10000 +Ethernet57 90 Eth15/2 15 10000 +Ethernet58 91 Eth15/3 15 10000 +Ethernet59 92 Eth15/4 15 10000 +Ethernet60 93 Eth16/1 16 10000 +Ethernet61 94 Eth16/2 16 10000 +Ethernet62 95 Eth16/3 16 10000 +Ethernet63 96 Eth16/4 16 10000 +Ethernet64 97 Eth17/1 17 10000 +Ethernet65 98 Eth17/2 17 10000 +Ethernet66 99 Eth17/3 17 10000 +Ethernet67 100 Eth17/4 17 10000 +Ethernet68 101 Eth18/1 18 10000 +Ethernet69 102 Eth18/2 18 10000 +Ethernet70 103 Eth18/3 18 10000 +Ethernet71 104 Eth18/4 18 10000 +Ethernet72 105 Eth19/1 19 10000 +Ethernet73 106 Eth19/2 19 10000 +Ethernet74 107 Eth19/3 19 10000 +Ethernet75 108 Eth19/4 19 10000 +Ethernet76 109 Eth20/1 20 10000 +Ethernet77 110 Eth20/2 20 10000 +Ethernet78 111 Eth20/3 20 10000 +Ethernet79 112 Eth20/4 20 10000 +Ethernet80 1 Eth21/1 21 10000 +Ethernet81 2 Eth21/2 21 10000 +Ethernet82 3 Eth21/3 21 10000 +Ethernet83 4 Eth21/4 21 10000 +Ethernet84 5 Eth22/1 22 10000 +Ethernet85 6 Eth22/2 22 10000 +Ethernet86 7 Eth22/3 22 10000 +Ethernet87 8 Eth22/4 22 10000 +Ethernet88 9 Eth23/1 23 10000 +Ethernet89 10 Eth23/2 23 10000 +Ethernet90 11 Eth23/3 23 10000 +Ethernet91 12 Eth23/4 23 10000 +Ethernet92 13 Eth24/1 24 10000 +Ethernet93 14 Eth24/2 24 10000 +Ethernet94 15 Eth24/3 25 10000 +Ethernet95 16 Eth24/4 25 10000 +Ethernet96 17,18 Eth25/1 26 50000 +Ethernet98 19,20 Eth25/2 26 50000 +Ethernet100 21,22 Eth26/1 27 50000 +Ethernet102 23,24 Eth26/2 27 50000 +Ethernet104 25,26 Eth27/1 28 50000 +Ethernet106 27,28 Eth27/2 28 50000 +Ethernet108 29,30 Eth28/1 29 50000 +Ethernet110 31,32 Eth28/2 29 50000 +Ethernet112 113,114 Eth29/1 30 50000 +Ethernet114 115,116 Eth29/2 30 50000 +Ethernet116 117,118 Eth30/1 31 50000 +Ethernet118 119,120 Eth30/2 31 50000 +Ethernet120 121,122 Eth31/1 32 50000 +Ethernet122 123,124 Eth31/2 32 50000 +Ethernet124 125,126 Eth32/1 32 50000 +Ethernet126 127,128 Eth32/2 32 50000 \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/sai.profile b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/sai.profile new file mode 100644 index 000000000000..4618972dbba9 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-seastone-dx010-96x10G-16x50G.config.bcm diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/th-seastone-dx010-96x10G-16x50G.config.bcm b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/th-seastone-dx010-96x10G-16x50G.config.bcm new file mode 100644 index 000000000000..b62320f7c50b --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/th-seastone-dx010-96x10G-16x50G.config.bcm @@ -0,0 +1,927 @@ +# Define default OS / SAL +os=unix + +# all XPORTs to XE ports +#pbmp_xport_xe=0x1fffffffe +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +pbmp_oversubscribe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe + +# Mode control to select L2 Table DMA mode aka L2MODE_POLL (0) or +# L2MOD_FIFO mechanism aka L2MODE_FIFO (1) for L2 table change notification. +l2xmsg_mode=1 + +# Memory table size configs +l2_mem_entries=8192 +l3_mem_entries=8192 +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +mmu_lossless=0 + +################################################################################### +# Celestica Customize for SeaStone +################################################################################### + +#ext mdio frequency to 495/0x80/2(1.933Mhz) or 415/0x80/2(1.62MHz) +# default is 40 +# Set external MDIO freq to 6.19MHz (495MHz) or 5.19MHz (415MHz) +#* target_freq is core_clock_freq * DIVIDEND / DIVISOR / 2 +# +rate_ext_mdio_divisor=0x80 + +# use internal rom boot +phy_ext_rom_boot=0 + +#fpem_mem_entries=32768 +oversubscribe_mode=1 +#pbmp_xport_xe=0x3fd000000ff4000003fc000001fe + +dport_map_enable=1 + +dport_map_port_68=1 +dport_map_port_69=2 +dport_map_port_70=3 +dport_map_port_71=4 + +dport_map_port_72=5 +dport_map_port_73=6 +dport_map_port_74=7 +dport_map_port_75=8 + +dport_map_port_76=9 +dport_map_port_77=10 +dport_map_port_78=11 +dport_map_port_79=12 + +dport_map_port_80=13 +dport_map_port_81=14 +dport_map_port_82=15 +dport_map_port_83=16 + +dport_map_port_34=17 +dport_map_port_35=18 +dport_map_port_36=19 +dport_map_port_37=20 + +dport_map_port_38=21 +dport_map_port_39=22 +dport_map_port_40=23 +dport_map_port_41=24 + +dport_map_port_42=25 +dport_map_port_43=26 +dport_map_port_44=27 +dport_map_port_45=28 + +dport_map_port_46=29 +dport_map_port_47=30 +dport_map_port_48=31 +dport_map_port_49=32 + +dport_map_port_50=33 +dport_map_port_51=34 +dport_map_port_52=35 +dport_map_port_53=36 + +dport_map_port_54=37 +dport_map_port_55=38 +dport_map_port_56=39 +dport_map_port_57=40 + +dport_map_port_58=41 +dport_map_port_59=42 +dport_map_port_60=43 +dport_map_port_61=44 + +dport_map_port_62=45 +dport_map_port_63=46 +dport_map_port_64=47 +dport_map_port_65=48 + +dport_map_port_84=49 +dport_map_port_85=50 +dport_map_port_86=51 +dport_map_port_87=52 + +dport_map_port_88=53 +dport_map_port_89=54 +dport_map_port_90=55 +dport_map_port_91=56 + +dport_map_port_92=57 +dport_map_port_93=58 +dport_map_port_94=59 +dport_map_port_95=60 + +dport_map_port_96=61 +dport_map_port_97=62 +dport_map_port_98=63 +dport_map_port_99=64 + +dport_map_port_102=65 +dport_map_port_103=66 +dport_map_port_104=67 +dport_map_port_105=68 + +dport_map_port_106=69 +dport_map_port_107=70 +dport_map_port_108=71 +dport_map_port_109=72 + +dport_map_port_110=73 +dport_map_port_111=74 +dport_map_port_112=75 +dport_map_port_113=76 + +dport_map_port_114=77 +dport_map_port_115=78 +dport_map_port_116=79 +dport_map_port_117=80 + +dport_map_port_1=81 +dport_map_port_2=82 +dport_map_port_3=83 +dport_map_port_4=84 + +dport_map_port_5=85 +dport_map_port_6=86 +dport_map_port_7=87 +dport_map_port_8=88 + +dport_map_port_9=89 +dport_map_port_10=90 +dport_map_port_11=91 +dport_map_port_12=92 + +dport_map_port_13=93 +dport_map_port_14=94 +dport_map_port_15=95 +dport_map_port_16=96 + + +dport_map_port_17=97 +dport_map_port_18=98 + +dport_map_port_21=101 +dport_map_port_22=102 + +dport_map_port_25=105 +dport_map_port_26=106 + +dport_map_port_29=109 +dport_map_port_30=110 + +dport_map_port_118=113 +dport_map_port_119=114 + +dport_map_port_122=117 +dport_map_port_123=118 + +dport_map_port_126=121 +dport_map_port_127=122 + +dport_map_port_130=125 +dport_map_port_131=126 + + +# port mapping +portmap_68=65:10 +portmap_69=66:10 +portmap_70=67:10 +portmap_71=68:10 + +portmap_72=69:10 +portmap_73=70:10 +portmap_74=71:10 +portmap_75=72:10 + +portmap_76=73:10 +portmap_77=74:10 +portmap_78=75:10 +portmap_79=76:10 + +portmap_80=77:10 +portmap_81=78:10 +portmap_82=79:10 +portmap_83=80:10 + +portmap_34=33:10 +portmap_35=34:10 +portmap_36=35:10 +portmap_37=36:10 + +portmap_38=37:10 +portmap_39=38:10 +portmap_40=39:10 +portmap_41=40:10 + +portmap_42=41:10 +portmap_43=42:10 +portmap_44=43:10 +portmap_45=44:10 + +portmap_46=45:10 +portmap_47=46:10 +portmap_48=47:10 +portmap_49=48:10 + +portmap_50=49:10 +portmap_51=50:10 +portmap_52=51:10 +portmap_53=52:10 + +portmap_54=53:10 +portmap_55=54:10 +portmap_56=55:10 +portmap_57=56:10 + +portmap_58=57:10 +portmap_59=58:10 +portmap_60=59:10 +portmap_61=60:10 + +portmap_62=61:10 +portmap_63=62:10 +portmap_64=63:10 +portmap_65=64:10 + +portmap_84=81:10 +portmap_85=82:10 +portmap_86=83:10 +portmap_87=84:10 + +portmap_88=85:10 +portmap_89=86:10 +portmap_90=87:10 +portmap_91=88:10 + +portmap_92=89:10 +portmap_93=90:10 +portmap_94=91:10 +portmap_95=92:10 + +portmap_96=93:10 +portmap_97=94:10 +portmap_98=95:10 +portmap_99=96:10 + +portmap_102=97:10 +portmap_103=98:10 +portmap_104=99:10 +portmap_105=100:10 + +portmap_106=101:10 +portmap_107=102:10 +portmap_108=103:10 +portmap_109=104:10 + +portmap_110=105:10 +portmap_111=106:10 +portmap_112=107:10 +portmap_113=108:10 + +portmap_114=109:10 +portmap_115=110:10 +portmap_116=111:10 +portmap_117=112:10 + +portmap_1=1:10 +portmap_2=2:10 +portmap_3=3:10 +portmap_4=4:10 + +portmap_5=5:10 +portmap_6=6:10 +portmap_7=7:10 +portmap_8=8:10 + +portmap_9=9:10 +portmap_10=10:10 +portmap_11=11:10 +portmap_12=12:10 + +portmap_13=13:10 +portmap_14=14:10 +portmap_15=15:10 +portmap_16=16:10 + + +portmap_17=17:50:2 +portmap_18=19:50:2 + +portmap_21=21:50:2 +portmap_22=23:50:2 + +portmap_25=25:50:2 +portmap_26=27:50:2 + +portmap_29=29:50:2 +portmap_30=31:50:2 + +portmap_118=113:50:2 +portmap_119=115:50:2 + +portmap_122=117:50:2 +portmap_123=119:50:2 + +portmap_126=121:50:2 +portmap_127=123:50:2 + +portmap_130=125:50:2 +portmap_131=127:50:2 + +#portmap_66=129:10 +#portmap_100=131:10 + +#WC16 +xgxs_tx_lane_map_68=0x3201 +xgxs_rx_lane_map_68=0x2310 +xgxs_tx_lane_map_69=0x3201 +xgxs_rx_lane_map_69=0x2310 +xgxs_tx_lane_map_70=0x3201 +xgxs_rx_lane_map_70=0x2310 +xgxs_tx_lane_map_71=0x3201 +xgxs_rx_lane_map_71=0x2310 + + +#WC17 +xgxs_tx_lane_map_72=0x3201 +xgxs_rx_lane_map_72=0x2301 +xgxs_tx_lane_map_73=0x3201 +xgxs_rx_lane_map_73=0x2301 +xgxs_tx_lane_map_74=0x3201 +xgxs_rx_lane_map_74=0x2301 +xgxs_tx_lane_map_75=0x3201 +xgxs_rx_lane_map_75=0x2301 + +#WC18 +xgxs_tx_lane_map_76=0x0132 +xgxs_rx_lane_map_76=0x0123 +xgxs_tx_lane_map_77=0x0132 +xgxs_rx_lane_map_77=0x0123 +xgxs_tx_lane_map_78=0x0132 +xgxs_rx_lane_map_78=0x0123 +xgxs_tx_lane_map_79=0x0132 +xgxs_rx_lane_map_79=0x0123 + +#WC19 +xgxs_tx_lane_map_80=0x2031 +xgxs_rx_lane_map_80=0x1320 +xgxs_tx_lane_map_81=0x2031 +xgxs_rx_lane_map_81=0x1320 +xgxs_tx_lane_map_82=0x2031 +xgxs_rx_lane_map_82=0x1320 +xgxs_tx_lane_map_83=0x2031 +xgxs_rx_lane_map_83=0x1320 + +#WC8 +#xgxs_tx_lane_map_34=0x3021 +#xgxs_rx_lane_map_34=0x0213 +#xgxs_tx_lane_map_35=0x3021 +#xgxs_rx_lane_map_35=0x0213 +#xgxs_tx_lane_map_36=0x3021 +#xgxs_rx_lane_map_36=0x0213 +#xgxs_tx_lane_map_37=0x3021 +#xgxs_rx_lane_map_37=0x0213 + +xgxs_tx_lane_map_34=0x3021 +xgxs_rx_lane_map_34=0x0213 +xgxs_tx_lane_map_35=0x3021 +xgxs_rx_lane_map_35=0x0213 +xgxs_tx_lane_map_36=0x3021 +xgxs_rx_lane_map_36=0x0213 +xgxs_tx_lane_map_37=0x3021 +xgxs_rx_lane_map_37=0x0213 + +#WC9 +xgxs_tx_lane_map_38=0x3210 +xgxs_rx_lane_map_38=0x1023 +xgxs_tx_lane_map_39=0x3210 +xgxs_rx_lane_map_39=0x1023 +xgxs_tx_lane_map_40=0x3210 +xgxs_rx_lane_map_40=0x1023 +xgxs_tx_lane_map_41=0x3210 +xgxs_rx_lane_map_41=0x1023 + +#WC10 +xgxs_tx_lane_map_42=0x2310 +xgxs_rx_lane_map_42=0x3210 +xgxs_tx_lane_map_43=0x2310 +xgxs_rx_lane_map_43=0x3210 +xgxs_tx_lane_map_44=0x2310 +xgxs_rx_lane_map_44=0x3210 +xgxs_tx_lane_map_45=0x2310 +xgxs_rx_lane_map_45=0x3210 + +#WC11 +xgxs_tx_lane_map_46=0x1032 +xgxs_rx_lane_map_46=0x1302 +xgxs_tx_lane_map_47=0x1032 +xgxs_rx_lane_map_47=0x1302 +xgxs_tx_lane_map_48=0x1032 +xgxs_rx_lane_map_48=0x1302 +xgxs_tx_lane_map_49=0x1032 +xgxs_rx_lane_map_49=0x1302 + +#WC12 +xgxs_tx_lane_map_50=0x3201 +xgxs_rx_lane_map_50=0x0213 +xgxs_tx_lane_map_51=0x3201 +xgxs_rx_lane_map_51=0x0213 +xgxs_tx_lane_map_52=0x3201 +xgxs_rx_lane_map_52=0x0213 +xgxs_tx_lane_map_53=0x3201 +xgxs_rx_lane_map_53=0x0213 + + +#WC13 +xgxs_tx_lane_map_54=0x2301 +xgxs_rx_lane_map_54=0x2310 +xgxs_tx_lane_map_55=0x2301 +xgxs_rx_lane_map_55=0x2310 +xgxs_tx_lane_map_56=0x2301 +xgxs_rx_lane_map_56=0x2310 +xgxs_tx_lane_map_57=0x2301 +xgxs_rx_lane_map_57=0x2310 + +#WC14 +xgxs_tx_lane_map_58=0x3201 +xgxs_rx_lane_map_58=0x0213 +xgxs_tx_lane_map_59=0x3201 +xgxs_rx_lane_map_59=0x0213 +xgxs_tx_lane_map_60=0x3201 +xgxs_rx_lane_map_60=0x0213 +xgxs_tx_lane_map_61=0x3201 +xgxs_rx_lane_map_61=0x0213 + +#WC15 +xgxs_tx_lane_map_62=0x1302 +xgxs_rx_lane_map_62=0x2310 +xgxs_tx_lane_map_63=0x1302 +xgxs_rx_lane_map_63=0x2310 +xgxs_tx_lane_map_64=0x1302 +xgxs_rx_lane_map_64=0x2310 +xgxs_tx_lane_map_65=0x1302 +xgxs_rx_lane_map_65=0x2310 + +#WC20 +xgxs_tx_lane_map_84=0x0213 +xgxs_rx_lane_map_84=0x2301 +xgxs_tx_lane_map_85=0x0213 +xgxs_rx_lane_map_85=0x2301 +xgxs_tx_lane_map_86=0x0213 +xgxs_rx_lane_map_86=0x2301 +xgxs_tx_lane_map_87=0x0213 +xgxs_rx_lane_map_87=0x2301 + +#WC21 +xgxs_tx_lane_map_88=0x0132 +xgxs_rx_lane_map_88=0x3210 +xgxs_tx_lane_map_89=0x0132 +xgxs_rx_lane_map_89=0x3210 +xgxs_tx_lane_map_90=0x0132 +xgxs_rx_lane_map_90=0x3210 +xgxs_tx_lane_map_91=0x0132 +xgxs_rx_lane_map_91=0x3210 + +#WC22 +xgxs_tx_lane_map_92=0x0132 +xgxs_rx_lane_map_92=0x2031 +xgxs_tx_lane_map_93=0x0132 +xgxs_rx_lane_map_93=0x2031 +xgxs_tx_lane_map_94=0x0132 +xgxs_rx_lane_map_94=0x2031 +xgxs_tx_lane_map_95=0x0132 +xgxs_rx_lane_map_95=0x2031 + +#WC23 +xgxs_tx_lane_map_96=0x2031 +xgxs_rx_lane_map_96=0x3201 +xgxs_tx_lane_map_97=0x2031 +xgxs_rx_lane_map_97=0x3201 +xgxs_tx_lane_map_98=0x2031 +xgxs_rx_lane_map_98=0x3201 +xgxs_tx_lane_map_99=0x2031 +xgxs_rx_lane_map_99=0x3201 + +#WC24 +xgxs_tx_lane_map_102=0x0132 +xgxs_rx_lane_map_102=0x2301 +xgxs_tx_lane_map_103=0x0132 +xgxs_rx_lane_map_103=0x2301 +xgxs_tx_lane_map_104=0x0132 +xgxs_rx_lane_map_104=0x2301 +xgxs_tx_lane_map_105=0x0132 +xgxs_rx_lane_map_105=0x2301 + +#WC25 +xgxs_tx_lane_map_106=0x0132 +xgxs_rx_lane_map_106=0x3201 +xgxs_tx_lane_map_107=0x0132 +xgxs_rx_lane_map_107=0x3201 +xgxs_tx_lane_map_108=0x0132 +xgxs_rx_lane_map_108=0x3201 +xgxs_tx_lane_map_109=0x0132 +xgxs_rx_lane_map_109=0x3201 + +#WC26 +xgxs_tx_lane_map_110=0x0132 +xgxs_rx_lane_map_110=0x2031 +xgxs_tx_lane_map_111=0x0132 +xgxs_rx_lane_map_111=0x2031 +xgxs_tx_lane_map_112=0x0132 +xgxs_rx_lane_map_112=0x2031 +xgxs_tx_lane_map_113=0x0132 +xgxs_rx_lane_map_113=0x2031 + +#WC27 +xgxs_tx_lane_map_114=0x2031 +xgxs_rx_lane_map_114=0x2301 +xgxs_tx_lane_map_115=0x2031 +xgxs_rx_lane_map_115=0x2301 +xgxs_tx_lane_map_116=0x2031 +xgxs_rx_lane_map_116=0x2301 +xgxs_tx_lane_map_117=0x2031 +xgxs_rx_lane_map_117=0x2301 + + +#WC0 +xgxs_tx_lane_map_1=0x3210 +xgxs_rx_lane_map_1=0x3120 +xgxs_tx_lane_map_2=0x3210 +xgxs_rx_lane_map_2=0x3120 +xgxs_tx_lane_map_3=0x3210 +xgxs_rx_lane_map_3=0x3120 +xgxs_tx_lane_map_4=0x3210 +xgxs_rx_lane_map_4=0x3120 + +#WC1 +xgxs_tx_lane_map_5=0x0132 +xgxs_rx_lane_map_5=0x1023 +xgxs_tx_lane_map_6=0x0132 +xgxs_rx_lane_map_6=0x1023 +xgxs_tx_lane_map_7=0x0132 +xgxs_rx_lane_map_7=0x1023 +xgxs_tx_lane_map_8=0x0132 +xgxs_rx_lane_map_8=0x1023 + +#WC2 +xgxs_tx_lane_map_9=0x3201 +xgxs_rx_lane_map_9=0x3120 +xgxs_tx_lane_map_10=0x3201 +xgxs_rx_lane_map_10=0x3120 +xgxs_tx_lane_map_11=0x3201 +xgxs_rx_lane_map_11=0x3120 +xgxs_tx_lane_map_12=0x3201 +xgxs_rx_lane_map_12=0x3120 + +#WC3 +xgxs_tx_lane_map_13=0x2031 +xgxs_rx_lane_map_13=0x1032 +xgxs_tx_lane_map_14=0x2031 +xgxs_rx_lane_map_14=0x1032 +xgxs_tx_lane_map_15=0x2031 +xgxs_rx_lane_map_15=0x1032 +xgxs_tx_lane_map_16=0x2031 +xgxs_rx_lane_map_16=0x1032 + +#WC4 +xgxs_tx_lane_map_17=0x2310 +xgxs_rx_lane_map_17=0x3210 +xgxs_tx_lane_map_18=0x2310 +xgxs_rx_lane_map_18=0x3210 + +#WC5 +xgxs_tx_lane_map_21=0x2301 +xgxs_rx_lane_map_21=0x3120 +xgxs_tx_lane_map_22=0x2301 +xgxs_rx_lane_map_22=0x3120 + +#WC6 +xgxs_tx_lane_map_25=0x3201 +xgxs_rx_lane_map_25=0x0213 +xgxs_tx_lane_map_26=0x3201 +xgxs_rx_lane_map_26=0x0213 + +#WC7 +xgxs_tx_lane_map_29=0x1302 +xgxs_rx_lane_map_29=0x1023 +xgxs_tx_lane_map_30=0x1302 +xgxs_rx_lane_map_30=0x1023 + +#WC28 +xgxs_tx_lane_map_118=0x1320 +xgxs_rx_lane_map_118=0x1302 +xgxs_tx_lane_map_119=0x1320 +xgxs_rx_lane_map_119=0x1302 + +#WC29 +xgxs_tx_lane_map_122=0x1032 +xgxs_rx_lane_map_122=0x1023 +xgxs_tx_lane_map_123=0x1032 +xgxs_rx_lane_map_123=0x1023 + +#WC30 +xgxs_tx_lane_map_126=0x3120 +xgxs_rx_lane_map_126=0x3120 +xgxs_tx_lane_map_127=0x3120 +xgxs_rx_lane_map_127=0x3120 + +#WC31 +xgxs_tx_lane_map_130=0x1302 +xgxs_rx_lane_map_130=0x2310 +xgxs_tx_lane_map_131=0x1302 +xgxs_rx_lane_map_131=0x2310 + + + + +#PN + +#WC16 +phy_xaui_tx_polarity_flip_68=0x0000 +phy_xaui_rx_polarity_flip_68=0x0000 +phy_xaui_tx_polarity_flip_69=0x0000 +phy_xaui_rx_polarity_flip_69=0x0000 +phy_xaui_tx_polarity_flip_70=0x0000 +phy_xaui_rx_polarity_flip_70=0x0000 +phy_xaui_tx_polarity_flip_71=0x0000 +phy_xaui_rx_polarity_flip_71=0x0000 + +#WC17 +phy_xaui_tx_polarity_flip_72=0x0001 +phy_xaui_rx_polarity_flip_72=0x0000 +phy_xaui_tx_polarity_flip_73=0x0000 +phy_xaui_rx_polarity_flip_73=0x0001 +phy_xaui_tx_polarity_flip_74=0x0001 +phy_xaui_rx_polarity_flip_74=0x0000 +phy_xaui_tx_polarity_flip_75=0x0001 +phy_xaui_rx_polarity_flip_75=0x0000 + +#WC18 +phy_xaui_tx_polarity_flip_76=0x0001 +phy_xaui_rx_polarity_flip_76=0x0000 +phy_xaui_tx_polarity_flip_77=0x0001 +phy_xaui_rx_polarity_flip_77=0x0000 +phy_xaui_tx_polarity_flip_78=0x0001 +phy_xaui_rx_polarity_flip_78=0x0000 +phy_xaui_tx_polarity_flip_79=0x0001 +phy_xaui_rx_polarity_flip_79=0x0000 + +#WC19 +phy_xaui_tx_polarity_flip_80=0x0001 +phy_xaui_rx_polarity_flip_80=0x0001 +phy_xaui_tx_polarity_flip_81=0x0001 +phy_xaui_rx_polarity_flip_81=0x0001 +phy_xaui_tx_polarity_flip_82=0x0001 +phy_xaui_rx_polarity_flip_82=0x0001 +phy_xaui_tx_polarity_flip_83=0x0001 +phy_xaui_rx_polarity_flip_83=0x0001 + +#WC8 +phy_xaui_tx_polarity_flip_34=0x0000 +phy_xaui_rx_polarity_flip_34=0x0000 +phy_xaui_tx_polarity_flip_35=0x0001 +phy_xaui_rx_polarity_flip_35=0x0000 +phy_xaui_tx_polarity_flip_36=0x0001 +phy_xaui_rx_polarity_flip_36=0x0000 +phy_xaui_tx_polarity_flip_37=0x0001 +phy_xaui_rx_polarity_flip_37=0x0000 + +#WC9 +phy_xaui_tx_polarity_flip_38=0x0000 +phy_xaui_rx_polarity_flip_38=0x0000 +phy_xaui_tx_polarity_flip_39=0x0000 +phy_xaui_rx_polarity_flip_39=0x0000 +phy_xaui_tx_polarity_flip_40=0x0000 +phy_xaui_rx_polarity_flip_40=0x0000 +phy_xaui_tx_polarity_flip_41=0x0001 +phy_xaui_rx_polarity_flip_41=0x0000 + +#WC10 +phy_xaui_tx_polarity_flip_42=0x0001 +phy_xaui_rx_polarity_flip_42=0x0000 +phy_xaui_tx_polarity_flip_43=0x0000 +phy_xaui_rx_polarity_flip_43=0x0000 +phy_xaui_tx_polarity_flip_44=0x0001 +phy_xaui_rx_polarity_flip_44=0x0000 +phy_xaui_tx_polarity_flip_45=0x0001 +phy_xaui_rx_polarity_flip_45=0x0000 + +#WC11 +phy_xaui_tx_polarity_flip_46=0x0000 +phy_xaui_rx_polarity_flip_46=0x0000 +phy_xaui_tx_polarity_flip_47=0x0000 +phy_xaui_rx_polarity_flip_47=0x0000 +phy_xaui_tx_polarity_flip_48=0x0000 +phy_xaui_rx_polarity_flip_48=0x0000 +phy_xaui_tx_polarity_flip_49=0x0000 +phy_xaui_rx_polarity_flip_49=0x0000 + +#WC12 +phy_xaui_tx_polarity_flip_50=0x0000 +phy_xaui_rx_polarity_flip_50=0x0000 +phy_xaui_tx_polarity_flip_51=0x0001 +phy_xaui_rx_polarity_flip_51=0x0000 +phy_xaui_tx_polarity_flip_52=0x0000 +phy_xaui_rx_polarity_flip_52=0x0000 +phy_xaui_tx_polarity_flip_53=0x0000 +phy_xaui_rx_polarity_flip_53=0x0000 + +#WC13 +phy_xaui_tx_polarity_flip_54=0x0000 +phy_xaui_rx_polarity_flip_54=0x0000 +phy_xaui_tx_polarity_flip_55=0x0001 +phy_xaui_rx_polarity_flip_55=0x0000 +phy_xaui_tx_polarity_flip_56=0x0000 +phy_xaui_rx_polarity_flip_56=0x0000 +phy_xaui_tx_polarity_flip_57=0x0000 +phy_xaui_rx_polarity_flip_57=0x0000 + +#WC14 +phy_xaui_tx_polarity_flip_58=0x0000 +phy_xaui_rx_polarity_flip_58=0x0000 +phy_xaui_tx_polarity_flip_59=0x0000 +phy_xaui_rx_polarity_flip_59=0x0000 +phy_xaui_tx_polarity_flip_60=0x0000 +phy_xaui_rx_polarity_flip_60=0x0000 +phy_xaui_tx_polarity_flip_61=0x0000 +phy_xaui_rx_polarity_flip_61=0x0000 + +#WC15 +phy_xaui_tx_polarity_flip_62=0x0000 +phy_xaui_rx_polarity_flip_62=0x0001 +phy_xaui_tx_polarity_flip_63=0x0001 +phy_xaui_rx_polarity_flip_63=0x0001 +phy_xaui_tx_polarity_flip_64=0x0000 +phy_xaui_rx_polarity_flip_64=0x0001 +phy_xaui_tx_polarity_flip_65=0x0001 +phy_xaui_rx_polarity_flip_65=0x0001 + +#WC20 +phy_xaui_tx_polarity_flip_84=0x0001 +phy_xaui_rx_polarity_flip_84=0x0000 +phy_xaui_tx_polarity_flip_85=0x0001 +phy_xaui_rx_polarity_flip_85=0x0001 +phy_xaui_tx_polarity_flip_86=0x0001 +phy_xaui_rx_polarity_flip_86=0x0001 +phy_xaui_tx_polarity_flip_87=0x0000 +phy_xaui_rx_polarity_flip_87=0x0001 + +#WC21 +phy_xaui_tx_polarity_flip_88=0x0001 +phy_xaui_rx_polarity_flip_88=0x0001 +phy_xaui_tx_polarity_flip_89=0x0000 +phy_xaui_rx_polarity_flip_89=0x0000 +phy_xaui_tx_polarity_flip_90=0x0001 +phy_xaui_rx_polarity_flip_90=0x0001 +phy_xaui_tx_polarity_flip_91=0x0001 +phy_xaui_rx_polarity_flip_91=0x0001 + +#WC22 +phy_xaui_tx_polarity_flip_92=0x0001 +phy_xaui_rx_polarity_flip_92=0x0000 +phy_xaui_tx_polarity_flip_93=0x0001 +phy_xaui_rx_polarity_flip_93=0x0000 +phy_xaui_tx_polarity_flip_94=0x0001 +phy_xaui_rx_polarity_flip_94=0x0000 +phy_xaui_tx_polarity_flip_95=0x0001 +phy_xaui_rx_polarity_flip_95=0x0001 + +#WC23 +phy_xaui_tx_polarity_flip_96=0x0001 +phy_xaui_rx_polarity_flip_96=0x0000 +phy_xaui_tx_polarity_flip_97=0x0000 +phy_xaui_rx_polarity_flip_97=0x0000 +phy_xaui_tx_polarity_flip_98=0x0001 +phy_xaui_rx_polarity_flip_98=0x0000 +phy_xaui_tx_polarity_flip_99=0x0000 +phy_xaui_rx_polarity_flip_99=0x0000 + +#WC24 +phy_xaui_tx_polarity_flip_102=0x0000 +phy_xaui_rx_polarity_flip_102=0x0001 +phy_xaui_tx_polarity_flip_103=0x0000 +phy_xaui_rx_polarity_flip_103=0x0001 +phy_xaui_tx_polarity_flip_104=0x0000 +phy_xaui_rx_polarity_flip_104=0x0001 +phy_xaui_tx_polarity_flip_105=0x0000 +phy_xaui_rx_polarity_flip_105=0x0001 + +#WC25 +phy_xaui_tx_polarity_flip_106=0x0001 +phy_xaui_rx_polarity_flip_106=0x0000 +phy_xaui_tx_polarity_flip_107=0x0001 +phy_xaui_rx_polarity_flip_107=0x0000 +phy_xaui_tx_polarity_flip_108=0x0001 +phy_xaui_rx_polarity_flip_108=0x0000 +phy_xaui_tx_polarity_flip_109=0x0001 +phy_xaui_rx_polarity_flip_109=0x0000 + +#WC26 +phy_xaui_tx_polarity_flip_110=0x0001 +phy_xaui_rx_polarity_flip_110=0x0001 +phy_xaui_tx_polarity_flip_111=0x0001 +phy_xaui_rx_polarity_flip_111=0x0001 +phy_xaui_tx_polarity_flip_112=0x0001 +phy_xaui_rx_polarity_flip_112=0x0001 +phy_xaui_tx_polarity_flip_113=0x0001 +phy_xaui_rx_polarity_flip_113=0x0001 + +#WC27 +phy_xaui_tx_polarity_flip_114=0x0001 +phy_xaui_rx_polarity_flip_114=0x0001 +phy_xaui_tx_polarity_flip_115=0x0001 +phy_xaui_rx_polarity_flip_115=0x0001 +phy_xaui_tx_polarity_flip_116=0x0001 +phy_xaui_rx_polarity_flip_116=0x0001 +phy_xaui_tx_polarity_flip_117=0x0001 +phy_xaui_rx_polarity_flip_117=0x0000 + +#WC0 +phy_xaui_tx_polarity_flip_1=0x0001 +phy_xaui_rx_polarity_flip_1=0x0001 +phy_xaui_tx_polarity_flip_2=0x0001 +phy_xaui_rx_polarity_flip_2=0x0001 +phy_xaui_tx_polarity_flip_3=0x0000 +phy_xaui_rx_polarity_flip_3=0x0001 +phy_xaui_tx_polarity_flip_4=0x0000 +phy_xaui_rx_polarity_flip_4=0x0001 + +#WC1 +phy_xaui_tx_polarity_flip_5=0x0001 +phy_xaui_rx_polarity_flip_5=0x0000 +phy_xaui_tx_polarity_flip_6=0x0001 +phy_xaui_rx_polarity_flip_6=0x0000 +phy_xaui_tx_polarity_flip_7=0x0001 +phy_xaui_rx_polarity_flip_7=0x0000 +phy_xaui_tx_polarity_flip_8=0x0000 +phy_xaui_rx_polarity_flip_8=0x0000 + +#WC2 +phy_xaui_tx_polarity_flip_9=0x0000 +phy_xaui_rx_polarity_flip_9=0x0000 +phy_xaui_tx_polarity_flip_10=0x0001 +phy_xaui_rx_polarity_flip_10=0x0000 +phy_xaui_tx_polarity_flip_11=0x0000 +phy_xaui_rx_polarity_flip_11=0x0000 +phy_xaui_tx_polarity_flip_12=0x0000 +phy_xaui_rx_polarity_flip_12=0x0001 + +#WC3 +phy_xaui_tx_polarity_flip_13=0x0001 +phy_xaui_rx_polarity_flip_13=0x0000 +phy_xaui_tx_polarity_flip_14=0x0001 +phy_xaui_rx_polarity_flip_14=0x0000 +phy_xaui_tx_polarity_flip_15=0x0001 +phy_xaui_rx_polarity_flip_15=0x0000 +phy_xaui_tx_polarity_flip_16=0x0001 +phy_xaui_rx_polarity_flip_16=0x0000 + +#WC4 +phy_xaui_tx_polarity_flip_17=0x0003 +phy_xaui_rx_polarity_flip_17=0x0000 +phy_xaui_tx_polarity_flip_18=0x0001 +phy_xaui_rx_polarity_flip_18=0x0000 + +#WC5 +phy_xaui_tx_polarity_flip_21=0x0000 +phy_xaui_rx_polarity_flip_21=0x0000 +phy_xaui_tx_polarity_flip_22=0x0000 +phy_xaui_rx_polarity_flip_22=0x0000 + +#WC6 +phy_xaui_tx_polarity_flip_25=0x0002 +phy_xaui_rx_polarity_flip_25=0x0001 +phy_xaui_tx_polarity_flip_26=0x0000 +phy_xaui_rx_polarity_flip_26=0x0001 + +#WC7 +phy_xaui_tx_polarity_flip_29=0x0002 +phy_xaui_rx_polarity_flip_29=0x0000 +phy_xaui_tx_polarity_flip_30=0x0000 +phy_xaui_rx_polarity_flip_30=0x0000 + +#WC28 +phy_xaui_tx_polarity_flip_118=0x0003 +phy_xaui_rx_polarity_flip_118=0x0003 +phy_xaui_tx_polarity_flip_119=0x0003 +phy_xaui_rx_polarity_flip_119=0x0003 + +#WC29 +phy_xaui_tx_polarity_flip_122=0x0000 +phy_xaui_rx_polarity_flip_122=0x0000 +phy_xaui_tx_polarity_flip_123=0x0001 +phy_xaui_rx_polarity_flip_123=0x0000 + +#WC30 +phy_xaui_tx_polarity_flip_126=0x0003 +phy_xaui_rx_polarity_flip_126=0x0000 +phy_xaui_tx_polarity_flip_127=0x0003 +phy_xaui_rx_polarity_flip_127=0x0000 + +#WC31 +phy_xaui_tx_polarity_flip_130=0x0002 +phy_xaui_rx_polarity_flip_130=0x0000 +phy_xaui_tx_polarity_flip_131=0x0001 +phy_xaui_rx_polarity_flip_131=0x0000 + diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/port_config.ini b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/port_config.ini new file mode 100644 index 000000000000..e1af29b0262f --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/port_config.ini @@ -0,0 +1,113 @@ +# name lanes alias index speed +Ethernet0 65 Eth1/1 0 25000 +Ethernet1 66 Eth1/2 0 25000 +Ethernet2 67 Eth1/3 0 25000 +Ethernet3 68 Eth1/4 0 25000 +Ethernet4 69 Eth2/1 1 25000 +Ethernet5 70 Eth2/2 1 25000 +Ethernet6 71 Eth2/3 1 25000 +Ethernet7 72 Eth2/4 1 25000 +Ethernet8 73 Eth3/1 2 25000 +Ethernet9 74 Eth3/2 2 25000 +Ethernet10 75 Eth3/3 2 25000 +Ethernet11 76 Eth3/4 2 25000 +Ethernet12 77 Eth4/1 3 25000 +Ethernet13 78 Eth4/2 3 25000 +Ethernet14 79 Eth4/3 3 25000 +Ethernet15 80 Eth4/4 3 25000 +Ethernet16 33 Eth5/1 4 25000 +Ethernet17 34 Eth5/2 4 25000 +Ethernet18 35 Eth5/3 4 25000 +Ethernet19 36 Eth5/4 4 25000 +Ethernet20 37 Eth6/1 5 25000 +Ethernet21 38 Eth6/2 5 25000 +Ethernet22 39 Eth6/3 5 25000 +Ethernet23 40 Eth6/4 5 25000 +Ethernet24 41 Eth7/1 6 25000 +Ethernet25 42 Eth7/2 6 25000 +Ethernet26 43 Eth7/3 6 25000 +Ethernet27 44 Eth7/4 6 25000 +Ethernet28 45 Eth8/1 7 25000 +Ethernet29 46 Eth8/2 7 25000 +Ethernet30 47 Eth8/3 7 25000 +Ethernet31 48 Eth8/4 7 25000 +Ethernet32 49 Eth9/1 8 25000 +Ethernet33 50 Eth9/2 8 25000 +Ethernet34 51 Eth9/3 8 25000 +Ethernet35 52 Eth9/4 8 25000 +Ethernet36 53 Eth10/1 9 25000 +Ethernet37 54 Eth10/2 9 25000 +Ethernet38 55 Eth10/3 9 25000 +Ethernet39 56 Eth10/4 9 25000 +Ethernet40 57 Eth11/1 10 25000 +Ethernet41 58 Eth11/2 10 25000 +Ethernet42 59 Eth11/3 10 25000 +Ethernet43 60 Eth11/4 10 25000 +Ethernet44 61 Eth12/1 11 25000 +Ethernet45 62 Eth12/2 11 25000 +Ethernet46 63 Eth12/3 11 25000 +Ethernet47 64 Eth12/4 11 25000 +Ethernet48 81 Eth13/1 12 25000 +Ethernet49 82 Eth13/2 12 25000 +Ethernet50 83 Eth13/3 12 25000 +Ethernet51 84 Eth13/4 12 25000 +Ethernet52 85 Eth14/1 13 25000 +Ethernet53 86 Eth14/2 13 25000 +Ethernet54 87 Eth14/3 13 25000 +Ethernet55 88 Eth14/4 13 25000 +Ethernet56 89 Eth15/1 14 25000 +Ethernet57 90 Eth15/2 14 25000 +Ethernet58 91 Eth15/3 14 25000 +Ethernet59 92 Eth15/4 14 25000 +Ethernet60 93 Eth16/1 15 25000 +Ethernet61 94 Eth16/2 15 25000 +Ethernet62 95 Eth16/3 15 25000 +Ethernet63 96 Eth16/4 15 25000 +Ethernet64 97 Eth17/1 16 25000 +Ethernet65 98 Eth17/2 16 25000 +Ethernet66 99 Eth17/3 16 25000 +Ethernet67 100 Eth17/4 16 25000 +Ethernet68 101 Eth18/1 17 25000 +Ethernet69 102 Eth18/2 17 25000 +Ethernet70 103 Eth18/3 17 25000 +Ethernet71 104 Eth18/4 17 25000 +Ethernet72 105 Eth19/1 18 25000 +Ethernet73 106 Eth19/2 18 25000 +Ethernet74 107 Eth19/3 18 25000 +Ethernet75 108 Eth19/4 18 25000 +Ethernet76 109 Eth20/1 19 25000 +Ethernet77 110 Eth20/2 19 25000 +Ethernet78 111 Eth20/3 19 25000 +Ethernet79 112 Eth20/4 19 25000 +Ethernet80 1 Eth21/1 20 25000 +Ethernet81 2 Eth21/2 20 25000 +Ethernet82 3 Eth21/3 20 25000 +Ethernet83 4 Eth21/4 20 25000 +Ethernet84 5 Eth22/1 21 25000 +Ethernet85 6 Eth22/2 21 25000 +Ethernet86 7 Eth22/3 21 25000 +Ethernet87 8 Eth22/4 21 25000 +Ethernet88 9 Eth23/1 22 25000 +Ethernet89 10 Eth23/2 22 25000 +Ethernet90 11 Eth23/3 22 25000 +Ethernet91 12 Eth23/4 22 25000 +Ethernet92 13 Eth24/1 23 25000 +Ethernet93 14 Eth24/2 23 25000 +Ethernet94 15 Eth24/3 23 25000 +Ethernet95 16 Eth24/4 23 25000 +Ethernet96 17,18 Eth25/1 24 50000 +Ethernet98 19,20 Eth25/2 24 50000 +Ethernet100 21,22 Eth26/1 25 50000 +Ethernet102 23,24 Eth26/2 25 50000 +Ethernet104 25,26 Eth27/1 26 50000 +Ethernet106 27,28 Eth27/2 26 50000 +Ethernet108 29,30 Eth28/1 27 50000 +Ethernet110 31,32 Eth28/2 27 50000 +Ethernet112 113,114 Eth29/1 28 50000 +Ethernet114 115,116 Eth29/2 28 50000 +Ethernet116 117,118 Eth30/1 29 50000 +Ethernet118 119,120 Eth30/2 29 50000 +Ethernet120 121,122 Eth31/1 30 50000 +Ethernet122 123,124 Eth31/2 30 50000 +Ethernet124 125,126 Eth32/1 31 50000 +Ethernet126 127,128 Eth32/2 31 50000 diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/sai.profile b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/sai.profile new file mode 100644 index 000000000000..053313a6574f --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-seastone-dx010-96x25G-16x50G.config.bcm diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/th-seastone-dx010-96x25G-16x50G.config.bcm b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/th-seastone-dx010-96x25G-16x50G.config.bcm new file mode 100644 index 000000000000..4e772d4eab4d --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/th-seastone-dx010-96x25G-16x50G.config.bcm @@ -0,0 +1,916 @@ +# Define default OS / SAL +os=unix + +# all XPORTs to XE ports +#pbmp_xport_xe=0x1fffffffe +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +pbmp_oversubscribe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe + +# Mode control to select L2 Table DMA mode aka L2MODE_POLL (0) or +# L2MOD_FIFO mechanism aka L2MODE_FIFO (1) for L2 table change notification. +l2xmsg_mode=1 + +# Memory table size configs, enable ALPM +l2_mem_entries=8192 +l3_mem_entries=8192 +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 + +#Use MMU lossy configuration +mmu_lossless=0 + +################################################################################### +# SeaStone customized configuration +################################################################################### + +#ext mdio frequency to 495/0x80/2(1.933Mhz) or 415/0x80/2(1.62MHz) +# default is 40 +# Set external MDIO freq to 6.19MHz (495MHz) or 5.19MHz (415MHz) +#* target_freq is core_clock_freq * DIVIDEND / DIVISOR / 2 +# +rate_ext_mdio_divisor=0x80 + +# use internal rom boot +phy_ext_rom_boot=0 + +oversubscribe_mode=1 + +# Map the physical ports to logical ports +dport_map_enable=1 + +dport_map_port_68=1 +dport_map_port_69=2 +dport_map_port_70=3 +dport_map_port_71=4 + +dport_map_port_72=5 +dport_map_port_73=6 +dport_map_port_74=7 +dport_map_port_75=8 + +dport_map_port_76=9 +dport_map_port_77=10 +dport_map_port_78=11 +dport_map_port_79=12 + +dport_map_port_80=13 +dport_map_port_81=14 +dport_map_port_82=15 +dport_map_port_83=16 + +dport_map_port_34=17 +dport_map_port_35=18 +dport_map_port_36=19 +dport_map_port_37=20 + +dport_map_port_38=21 +dport_map_port_39=22 +dport_map_port_40=23 +dport_map_port_41=24 + +dport_map_port_42=25 +dport_map_port_43=26 +dport_map_port_44=27 +dport_map_port_45=28 + +dport_map_port_46=29 +dport_map_port_47=30 +dport_map_port_48=31 +dport_map_port_49=32 + +dport_map_port_50=33 +dport_map_port_51=34 +dport_map_port_52=35 +dport_map_port_53=36 + +dport_map_port_54=37 +dport_map_port_55=38 +dport_map_port_56=39 +dport_map_port_57=40 + +dport_map_port_58=41 +dport_map_port_59=42 +dport_map_port_60=43 +dport_map_port_61=44 + +dport_map_port_62=45 +dport_map_port_63=46 +dport_map_port_64=47 +dport_map_port_65=48 + +dport_map_port_84=49 +dport_map_port_85=50 +dport_map_port_86=51 +dport_map_port_87=52 + +dport_map_port_88=53 +dport_map_port_89=54 +dport_map_port_90=55 +dport_map_port_91=56 + +dport_map_port_92=57 +dport_map_port_93=58 +dport_map_port_94=59 +dport_map_port_95=60 + +dport_map_port_96=61 +dport_map_port_97=62 +dport_map_port_98=63 +dport_map_port_99=64 + +dport_map_port_102=65 +dport_map_port_103=66 +dport_map_port_104=67 +dport_map_port_105=68 + +dport_map_port_106=69 +dport_map_port_107=70 +dport_map_port_108=71 +dport_map_port_109=72 + +dport_map_port_110=73 +dport_map_port_111=74 +dport_map_port_112=75 +dport_map_port_113=76 + +dport_map_port_114=77 +dport_map_port_115=78 +dport_map_port_116=79 +dport_map_port_117=80 + +dport_map_port_1=81 +dport_map_port_2=82 +dport_map_port_3=83 +dport_map_port_4=84 + +dport_map_port_5=85 +dport_map_port_6=86 +dport_map_port_7=87 +dport_map_port_8=88 + +dport_map_port_9=89 +dport_map_port_10=90 +dport_map_port_11=91 +dport_map_port_12=92 + +dport_map_port_13=93 +dport_map_port_14=94 +dport_map_port_15=95 +dport_map_port_16=96 + +dport_map_port_17=97 +dport_map_port_18=98 + +dport_map_port_21=101 +dport_map_port_22=102 + +dport_map_port_25=105 +dport_map_port_26=106 + +dport_map_port_29=109 +dport_map_port_30=110 + +dport_map_port_118=113 +dport_map_port_119=114 + +dport_map_port_122=117 +dport_map_port_123=118 + +dport_map_port_126=121 +dport_map_port_127=122 + +dport_map_port_130=125 +dport_map_port_131=126 + + +# port/lane mapping, 96x25G + 16x50G +portmap_68=65:25 +portmap_69=66:25 +portmap_70=67:25 +portmap_71=68:25 + +portmap_72=69:25 +portmap_73=70:25 +portmap_74=71:25 +portmap_75=72:25 + +portmap_76=73:25 +portmap_77=74:25 +portmap_78=75:25 +portmap_79=76:25 + +portmap_80=77:25 +portmap_81=78:25 +portmap_82=79:25 +portmap_83=80:25 + +portmap_34=33:25 +portmap_35=34:25 +portmap_36=35:25 +portmap_37=36:25 + +portmap_38=37:25 +portmap_39=38:25 +portmap_40=39:25 +portmap_41=40:25 + +portmap_42=41:25 +portmap_43=42:25 +portmap_44=43:25 +portmap_45=44:25 + +portmap_46=45:25 +portmap_47=46:25 +portmap_48=47:25 +portmap_49=48:25 + +portmap_50=49:25 +portmap_51=50:25 +portmap_52=51:25 +portmap_53=52:25 + +portmap_54=53:25 +portmap_55=54:25 +portmap_56=55:25 +portmap_57=56:25 + +portmap_58=57:25 +portmap_59=58:25 +portmap_60=59:25 +portmap_61=60:25 + +portmap_62=61:25 +portmap_63=62:25 +portmap_64=63:25 +portmap_65=64:25 + +portmap_84=81:25 +portmap_85=82:25 +portmap_86=83:25 +portmap_87=84:25 + +portmap_88=85:25 +portmap_89=86:25 +portmap_90=87:25 +portmap_91=88:25 + +portmap_92=89:25 +portmap_93=90:25 +portmap_94=91:25 +portmap_95=92:25 + +portmap_96=93:25 +portmap_97=94:25 +portmap_98=95:25 +portmap_99=96:25 + +portmap_102=97:25 +portmap_103=98:25 +portmap_104=99:25 +portmap_105=100:25 + +portmap_106=101:25 +portmap_107=102:25 +portmap_108=103:25 +portmap_109=104:25 + +portmap_110=105:25 +portmap_111=106:25 +portmap_112=107:25 +portmap_113=108:25 + +portmap_114=109:25 +portmap_115=110:25 +portmap_116=111:25 +portmap_117=112:25 + +portmap_1=1:25 +portmap_2=2:25 +portmap_3=3:25 +portmap_4=4:25 + +portmap_5=5:25 +portmap_6=6:25 +portmap_7=7:25 +portmap_8=8:25 + +portmap_9=9:25 +portmap_10=10:25 +portmap_11=11:25 +portmap_12=12:25 + +portmap_13=13:25 +portmap_14=14:25 +portmap_15=15:25 +portmap_16=16:25 + + +portmap_17=17:50:2 +portmap_18=19:50:2 + +portmap_21=21:50:2 +portmap_22=23:50:2 + +portmap_25=25:50:2 +portmap_26=27:50:2 + +portmap_29=29:50:2 +portmap_30=31:50:2 + +portmap_118=113:50:2 +portmap_119=115:50:2 + +portmap_122=117:50:2 +portmap_123=119:50:2 + +portmap_126=121:50:2 +portmap_127=123:50:2 + +portmap_130=125:50:2 +portmap_131=127:50:2 + +#portmap_66=129:10 +#portmap_100=131:10 + +#WC16 +xgxs_tx_lane_map_68=0x3201 +xgxs_rx_lane_map_68=0x2310 +xgxs_tx_lane_map_69=0x3201 +xgxs_rx_lane_map_69=0x2310 +xgxs_tx_lane_map_70=0x3201 +xgxs_rx_lane_map_70=0x2310 +xgxs_tx_lane_map_71=0x3201 +xgxs_rx_lane_map_71=0x2310 + + +#WC17 +xgxs_tx_lane_map_72=0x3201 +xgxs_rx_lane_map_72=0x2301 +xgxs_tx_lane_map_73=0x3201 +xgxs_rx_lane_map_73=0x2301 +xgxs_tx_lane_map_74=0x3201 +xgxs_rx_lane_map_74=0x2301 +xgxs_tx_lane_map_75=0x3201 +xgxs_rx_lane_map_75=0x2301 + +#WC18 +xgxs_tx_lane_map_76=0x0132 +xgxs_rx_lane_map_76=0x0123 +xgxs_tx_lane_map_77=0x0132 +xgxs_rx_lane_map_77=0x0123 +xgxs_tx_lane_map_78=0x0132 +xgxs_rx_lane_map_78=0x0123 +xgxs_tx_lane_map_79=0x0132 +xgxs_rx_lane_map_79=0x0123 + +#WC19 +xgxs_tx_lane_map_80=0x2031 +xgxs_rx_lane_map_80=0x1320 +xgxs_tx_lane_map_81=0x2031 +xgxs_rx_lane_map_81=0x1320 +xgxs_tx_lane_map_82=0x2031 +xgxs_rx_lane_map_82=0x1320 +xgxs_tx_lane_map_83=0x2031 +xgxs_rx_lane_map_83=0x1320 + +#WC8 +xgxs_tx_lane_map_34=0x3021 +xgxs_rx_lane_map_34=0x0213 +xgxs_tx_lane_map_35=0x3021 +xgxs_rx_lane_map_35=0x0213 +xgxs_tx_lane_map_36=0x3021 +xgxs_rx_lane_map_36=0x0213 +xgxs_tx_lane_map_37=0x3021 +xgxs_rx_lane_map_37=0x0213 + +#WC9 +xgxs_tx_lane_map_38=0x3210 +xgxs_rx_lane_map_38=0x1023 +xgxs_tx_lane_map_39=0x3210 +xgxs_rx_lane_map_39=0x1023 +xgxs_tx_lane_map_40=0x3210 +xgxs_rx_lane_map_40=0x1023 +xgxs_tx_lane_map_41=0x3210 +xgxs_rx_lane_map_41=0x1023 + +#WC10 +xgxs_tx_lane_map_42=0x2310 +xgxs_rx_lane_map_42=0x3210 +xgxs_tx_lane_map_43=0x2310 +xgxs_rx_lane_map_43=0x3210 +xgxs_tx_lane_map_44=0x2310 +xgxs_rx_lane_map_44=0x3210 +xgxs_tx_lane_map_45=0x2310 +xgxs_rx_lane_map_45=0x3210 + +#WC11 +xgxs_tx_lane_map_46=0x1032 +xgxs_rx_lane_map_46=0x1302 +xgxs_tx_lane_map_47=0x1032 +xgxs_rx_lane_map_47=0x1302 +xgxs_tx_lane_map_48=0x1032 +xgxs_rx_lane_map_48=0x1302 +xgxs_tx_lane_map_49=0x1032 +xgxs_rx_lane_map_49=0x1302 + +#WC12 +xgxs_tx_lane_map_50=0x3201 +xgxs_rx_lane_map_50=0x0213 +xgxs_tx_lane_map_51=0x3201 +xgxs_rx_lane_map_51=0x0213 +xgxs_tx_lane_map_52=0x3201 +xgxs_rx_lane_map_52=0x0213 +xgxs_tx_lane_map_53=0x3201 +xgxs_rx_lane_map_53=0x0213 + + +#WC13 +xgxs_tx_lane_map_54=0x2301 +xgxs_rx_lane_map_54=0x2310 +xgxs_tx_lane_map_55=0x2301 +xgxs_rx_lane_map_55=0x2310 +xgxs_tx_lane_map_56=0x2301 +xgxs_rx_lane_map_56=0x2310 +xgxs_tx_lane_map_57=0x2301 +xgxs_rx_lane_map_57=0x2310 + +#WC14 +xgxs_tx_lane_map_58=0x3201 +xgxs_rx_lane_map_58=0x0213 +xgxs_tx_lane_map_59=0x3201 +xgxs_rx_lane_map_59=0x0213 +xgxs_tx_lane_map_60=0x3201 +xgxs_rx_lane_map_60=0x0213 +xgxs_tx_lane_map_61=0x3201 +xgxs_rx_lane_map_61=0x0213 + +#WC15 +xgxs_tx_lane_map_62=0x1302 +xgxs_rx_lane_map_62=0x2310 +xgxs_tx_lane_map_63=0x1302 +xgxs_rx_lane_map_63=0x2310 +xgxs_tx_lane_map_64=0x1302 +xgxs_rx_lane_map_64=0x2310 +xgxs_tx_lane_map_65=0x1302 +xgxs_rx_lane_map_65=0x2310 + +#WC20 +xgxs_tx_lane_map_84=0x0213 +xgxs_rx_lane_map_84=0x2301 +xgxs_tx_lane_map_85=0x0213 +xgxs_rx_lane_map_85=0x2301 +xgxs_tx_lane_map_86=0x0213 +xgxs_rx_lane_map_86=0x2301 +xgxs_tx_lane_map_87=0x0213 +xgxs_rx_lane_map_87=0x2301 + +#WC21 +xgxs_tx_lane_map_88=0x0132 +xgxs_rx_lane_map_88=0x3210 +xgxs_tx_lane_map_89=0x0132 +xgxs_rx_lane_map_89=0x3210 +xgxs_tx_lane_map_90=0x0132 +xgxs_rx_lane_map_90=0x3210 +xgxs_tx_lane_map_91=0x0132 +xgxs_rx_lane_map_91=0x3210 + +#WC22 +xgxs_tx_lane_map_92=0x0132 +xgxs_rx_lane_map_92=0x2031 +xgxs_tx_lane_map_93=0x0132 +xgxs_rx_lane_map_93=0x2031 +xgxs_tx_lane_map_94=0x0132 +xgxs_rx_lane_map_94=0x2031 +xgxs_tx_lane_map_95=0x0132 +xgxs_rx_lane_map_95=0x2031 + +#WC23 +xgxs_tx_lane_map_96=0x2031 +xgxs_rx_lane_map_96=0x3201 +xgxs_tx_lane_map_97=0x2031 +xgxs_rx_lane_map_97=0x3201 +xgxs_tx_lane_map_98=0x2031 +xgxs_rx_lane_map_98=0x3201 +xgxs_tx_lane_map_99=0x2031 +xgxs_rx_lane_map_99=0x3201 + +#WC24 +xgxs_tx_lane_map_102=0x0132 +xgxs_rx_lane_map_102=0x2301 +xgxs_tx_lane_map_103=0x0132 +xgxs_rx_lane_map_103=0x2301 +xgxs_tx_lane_map_104=0x0132 +xgxs_rx_lane_map_104=0x2301 +xgxs_tx_lane_map_105=0x0132 +xgxs_rx_lane_map_105=0x2301 + +#WC25 +xgxs_tx_lane_map_106=0x0132 +xgxs_rx_lane_map_106=0x3201 +xgxs_tx_lane_map_107=0x0132 +xgxs_rx_lane_map_107=0x3201 +xgxs_tx_lane_map_108=0x0132 +xgxs_rx_lane_map_108=0x3201 +xgxs_tx_lane_map_109=0x0132 +xgxs_rx_lane_map_109=0x3201 + +#WC26 +xgxs_tx_lane_map_110=0x0132 +xgxs_rx_lane_map_110=0x2031 +xgxs_tx_lane_map_111=0x0132 +xgxs_rx_lane_map_111=0x2031 +xgxs_tx_lane_map_112=0x0132 +xgxs_rx_lane_map_112=0x2031 +xgxs_tx_lane_map_113=0x0132 +xgxs_rx_lane_map_113=0x2031 + +#WC27 +xgxs_tx_lane_map_114=0x2031 +xgxs_rx_lane_map_114=0x2301 +xgxs_tx_lane_map_115=0x2031 +xgxs_rx_lane_map_115=0x2301 +xgxs_tx_lane_map_116=0x2031 +xgxs_rx_lane_map_116=0x2301 +xgxs_tx_lane_map_117=0x2031 +xgxs_rx_lane_map_117=0x2301 + + +#WC0 +xgxs_tx_lane_map_1=0x3210 +xgxs_rx_lane_map_1=0x3120 +xgxs_tx_lane_map_2=0x3210 +xgxs_rx_lane_map_2=0x3120 +xgxs_tx_lane_map_3=0x3210 +xgxs_rx_lane_map_3=0x3120 +xgxs_tx_lane_map_4=0x3210 +xgxs_rx_lane_map_4=0x3120 + +#WC1 +xgxs_tx_lane_map_5=0x0132 +xgxs_rx_lane_map_5=0x1023 +xgxs_tx_lane_map_6=0x0132 +xgxs_rx_lane_map_6=0x1023 +xgxs_tx_lane_map_7=0x0132 +xgxs_rx_lane_map_7=0x1023 +xgxs_tx_lane_map_8=0x0132 +xgxs_rx_lane_map_8=0x1023 + +#WC2 +xgxs_tx_lane_map_9=0x3201 +xgxs_rx_lane_map_9=0x3120 +xgxs_tx_lane_map_10=0x3201 +xgxs_rx_lane_map_10=0x3120 +xgxs_tx_lane_map_11=0x3201 +xgxs_rx_lane_map_11=0x3120 +xgxs_tx_lane_map_12=0x3201 +xgxs_rx_lane_map_12=0x3120 + +#WC3 +xgxs_tx_lane_map_13=0x2031 +xgxs_rx_lane_map_13=0x1032 +xgxs_tx_lane_map_14=0x2031 +xgxs_rx_lane_map_14=0x1032 +xgxs_tx_lane_map_15=0x2031 +xgxs_rx_lane_map_15=0x1032 +xgxs_tx_lane_map_16=0x2031 +xgxs_rx_lane_map_16=0x1032 + +#WC4 +xgxs_tx_lane_map_17=0x2310 +xgxs_rx_lane_map_17=0x3210 +xgxs_tx_lane_map_18=0x2310 +xgxs_rx_lane_map_18=0x3210 + +#WC5 +xgxs_tx_lane_map_21=0x2301 +xgxs_rx_lane_map_21=0x3120 +xgxs_tx_lane_map_22=0x2301 +xgxs_rx_lane_map_22=0x3120 + +#WC6 +xgxs_tx_lane_map_25=0x3201 +xgxs_rx_lane_map_25=0x0213 +xgxs_tx_lane_map_26=0x3201 +xgxs_rx_lane_map_26=0x0213 + +#WC7 +xgxs_tx_lane_map_29=0x1302 +xgxs_rx_lane_map_29=0x1023 +xgxs_tx_lane_map_30=0x1302 +xgxs_rx_lane_map_30=0x1023 + +#WC28 +xgxs_tx_lane_map_118=0x1320 +xgxs_rx_lane_map_118=0x1302 +xgxs_tx_lane_map_119=0x1320 +xgxs_rx_lane_map_119=0x1302 + +#WC29 +xgxs_tx_lane_map_122=0x1032 +xgxs_rx_lane_map_122=0x1023 +xgxs_tx_lane_map_123=0x1032 +xgxs_rx_lane_map_123=0x1023 + +#WC30 +xgxs_tx_lane_map_126=0x3120 +xgxs_rx_lane_map_126=0x3120 +xgxs_tx_lane_map_127=0x3120 +xgxs_rx_lane_map_127=0x3120 + +#WC31 +xgxs_tx_lane_map_130=0x1302 +xgxs_rx_lane_map_130=0x2310 +xgxs_tx_lane_map_131=0x1302 +xgxs_rx_lane_map_131=0x2310 + + +#Polarity flip settings + +#WC16 +phy_xaui_tx_polarity_flip_68=0x0000 +phy_xaui_rx_polarity_flip_68=0x0000 +phy_xaui_tx_polarity_flip_69=0x0000 +phy_xaui_rx_polarity_flip_69=0x0000 +phy_xaui_tx_polarity_flip_70=0x0000 +phy_xaui_rx_polarity_flip_70=0x0000 +phy_xaui_tx_polarity_flip_71=0x0000 +phy_xaui_rx_polarity_flip_71=0x0000 + +#WC17 +phy_xaui_tx_polarity_flip_72=0x0001 +phy_xaui_rx_polarity_flip_72=0x0000 +phy_xaui_tx_polarity_flip_73=0x0000 +phy_xaui_rx_polarity_flip_73=0x0001 +phy_xaui_tx_polarity_flip_74=0x0001 +phy_xaui_rx_polarity_flip_74=0x0000 +phy_xaui_tx_polarity_flip_75=0x0001 +phy_xaui_rx_polarity_flip_75=0x0000 + +#WC18 +phy_xaui_tx_polarity_flip_76=0x0001 +phy_xaui_rx_polarity_flip_76=0x0000 +phy_xaui_tx_polarity_flip_77=0x0001 +phy_xaui_rx_polarity_flip_77=0x0000 +phy_xaui_tx_polarity_flip_78=0x0001 +phy_xaui_rx_polarity_flip_78=0x0000 +phy_xaui_tx_polarity_flip_79=0x0001 +phy_xaui_rx_polarity_flip_79=0x0000 + +#WC19 +phy_xaui_tx_polarity_flip_80=0x0001 +phy_xaui_rx_polarity_flip_80=0x0001 +phy_xaui_tx_polarity_flip_81=0x0001 +phy_xaui_rx_polarity_flip_81=0x0001 +phy_xaui_tx_polarity_flip_82=0x0001 +phy_xaui_rx_polarity_flip_82=0x0001 +phy_xaui_tx_polarity_flip_83=0x0001 +phy_xaui_rx_polarity_flip_83=0x0001 + +#WC8 +phy_xaui_tx_polarity_flip_34=0x0000 +phy_xaui_rx_polarity_flip_34=0x0000 +phy_xaui_tx_polarity_flip_35=0x0001 +phy_xaui_rx_polarity_flip_35=0x0000 +phy_xaui_tx_polarity_flip_36=0x0001 +phy_xaui_rx_polarity_flip_36=0x0000 +phy_xaui_tx_polarity_flip_37=0x0001 +phy_xaui_rx_polarity_flip_37=0x0000 + +#WC9 +phy_xaui_tx_polarity_flip_38=0x0000 +phy_xaui_rx_polarity_flip_38=0x0000 +phy_xaui_tx_polarity_flip_39=0x0000 +phy_xaui_rx_polarity_flip_39=0x0000 +phy_xaui_tx_polarity_flip_40=0x0000 +phy_xaui_rx_polarity_flip_40=0x0000 +phy_xaui_tx_polarity_flip_41=0x0001 +phy_xaui_rx_polarity_flip_41=0x0000 + +#WC10 +phy_xaui_tx_polarity_flip_42=0x0001 +phy_xaui_rx_polarity_flip_42=0x0000 +phy_xaui_tx_polarity_flip_43=0x0000 +phy_xaui_rx_polarity_flip_43=0x0000 +phy_xaui_tx_polarity_flip_44=0x0001 +phy_xaui_rx_polarity_flip_44=0x0000 +phy_xaui_tx_polarity_flip_45=0x0001 +phy_xaui_rx_polarity_flip_45=0x0000 + +#WC11 +phy_xaui_tx_polarity_flip_46=0x0000 +phy_xaui_rx_polarity_flip_46=0x0000 +phy_xaui_tx_polarity_flip_47=0x0000 +phy_xaui_rx_polarity_flip_47=0x0000 +phy_xaui_tx_polarity_flip_48=0x0000 +phy_xaui_rx_polarity_flip_48=0x0000 +phy_xaui_tx_polarity_flip_49=0x0000 +phy_xaui_rx_polarity_flip_49=0x0000 + +#WC12 +phy_xaui_tx_polarity_flip_50=0x0000 +phy_xaui_rx_polarity_flip_50=0x0000 +phy_xaui_tx_polarity_flip_51=0x0001 +phy_xaui_rx_polarity_flip_51=0x0000 +phy_xaui_tx_polarity_flip_52=0x0000 +phy_xaui_rx_polarity_flip_52=0x0000 +phy_xaui_tx_polarity_flip_53=0x0000 +phy_xaui_rx_polarity_flip_53=0x0000 + +#WC13 +phy_xaui_tx_polarity_flip_54=0x0000 +phy_xaui_rx_polarity_flip_54=0x0000 +phy_xaui_tx_polarity_flip_55=0x0001 +phy_xaui_rx_polarity_flip_55=0x0000 +phy_xaui_tx_polarity_flip_56=0x0000 +phy_xaui_rx_polarity_flip_56=0x0000 +phy_xaui_tx_polarity_flip_57=0x0000 +phy_xaui_rx_polarity_flip_57=0x0000 + +#WC14 +phy_xaui_tx_polarity_flip_58=0x0000 +phy_xaui_rx_polarity_flip_58=0x0000 +phy_xaui_tx_polarity_flip_59=0x0000 +phy_xaui_rx_polarity_flip_59=0x0000 +phy_xaui_tx_polarity_flip_60=0x0000 +phy_xaui_rx_polarity_flip_60=0x0000 +phy_xaui_tx_polarity_flip_61=0x0000 +phy_xaui_rx_polarity_flip_61=0x0000 + +#WC15 +phy_xaui_tx_polarity_flip_62=0x0000 +phy_xaui_rx_polarity_flip_62=0x0001 +phy_xaui_tx_polarity_flip_63=0x0001 +phy_xaui_rx_polarity_flip_63=0x0001 +phy_xaui_tx_polarity_flip_64=0x0000 +phy_xaui_rx_polarity_flip_64=0x0001 +phy_xaui_tx_polarity_flip_65=0x0001 +phy_xaui_rx_polarity_flip_65=0x0001 + +#WC20 +phy_xaui_tx_polarity_flip_84=0x0001 +phy_xaui_rx_polarity_flip_84=0x0000 +phy_xaui_tx_polarity_flip_85=0x0001 +phy_xaui_rx_polarity_flip_85=0x0001 +phy_xaui_tx_polarity_flip_86=0x0001 +phy_xaui_rx_polarity_flip_86=0x0001 +phy_xaui_tx_polarity_flip_87=0x0000 +phy_xaui_rx_polarity_flip_87=0x0001 + +#WC21 +phy_xaui_tx_polarity_flip_88=0x0001 +phy_xaui_rx_polarity_flip_88=0x0001 +phy_xaui_tx_polarity_flip_89=0x0000 +phy_xaui_rx_polarity_flip_89=0x0000 +phy_xaui_tx_polarity_flip_90=0x0001 +phy_xaui_rx_polarity_flip_90=0x0001 +phy_xaui_tx_polarity_flip_91=0x0001 +phy_xaui_rx_polarity_flip_91=0x0001 + +#WC22 +phy_xaui_tx_polarity_flip_92=0x0001 +phy_xaui_rx_polarity_flip_92=0x0000 +phy_xaui_tx_polarity_flip_93=0x0001 +phy_xaui_rx_polarity_flip_93=0x0000 +phy_xaui_tx_polarity_flip_94=0x0001 +phy_xaui_rx_polarity_flip_94=0x0000 +phy_xaui_tx_polarity_flip_95=0x0001 +phy_xaui_rx_polarity_flip_95=0x0001 + +#WC23 +phy_xaui_tx_polarity_flip_96=0x0001 +phy_xaui_rx_polarity_flip_96=0x0000 +phy_xaui_tx_polarity_flip_97=0x0000 +phy_xaui_rx_polarity_flip_97=0x0000 +phy_xaui_tx_polarity_flip_98=0x0001 +phy_xaui_rx_polarity_flip_98=0x0000 +phy_xaui_tx_polarity_flip_99=0x0000 +phy_xaui_rx_polarity_flip_99=0x0000 + +#WC24 +phy_xaui_tx_polarity_flip_102=0x0000 +phy_xaui_rx_polarity_flip_102=0x0001 +phy_xaui_tx_polarity_flip_103=0x0000 +phy_xaui_rx_polarity_flip_103=0x0001 +phy_xaui_tx_polarity_flip_104=0x0000 +phy_xaui_rx_polarity_flip_104=0x0001 +phy_xaui_tx_polarity_flip_105=0x0000 +phy_xaui_rx_polarity_flip_105=0x0001 + +#WC25 +phy_xaui_tx_polarity_flip_106=0x0001 +phy_xaui_rx_polarity_flip_106=0x0000 +phy_xaui_tx_polarity_flip_107=0x0001 +phy_xaui_rx_polarity_flip_107=0x0000 +phy_xaui_tx_polarity_flip_108=0x0001 +phy_xaui_rx_polarity_flip_108=0x0000 +phy_xaui_tx_polarity_flip_109=0x0001 +phy_xaui_rx_polarity_flip_109=0x0000 + +#WC26 +phy_xaui_tx_polarity_flip_110=0x0001 +phy_xaui_rx_polarity_flip_110=0x0001 +phy_xaui_tx_polarity_flip_111=0x0001 +phy_xaui_rx_polarity_flip_111=0x0001 +phy_xaui_tx_polarity_flip_112=0x0001 +phy_xaui_rx_polarity_flip_112=0x0001 +phy_xaui_tx_polarity_flip_113=0x0001 +phy_xaui_rx_polarity_flip_113=0x0001 + +#WC27 +phy_xaui_tx_polarity_flip_114=0x0001 +phy_xaui_rx_polarity_flip_114=0x0001 +phy_xaui_tx_polarity_flip_115=0x0001 +phy_xaui_rx_polarity_flip_115=0x0001 +phy_xaui_tx_polarity_flip_116=0x0001 +phy_xaui_rx_polarity_flip_116=0x0001 +phy_xaui_tx_polarity_flip_117=0x0001 +phy_xaui_rx_polarity_flip_117=0x0000 + +#WC0 +phy_xaui_tx_polarity_flip_1=0x0001 +phy_xaui_rx_polarity_flip_1=0x0001 +phy_xaui_tx_polarity_flip_2=0x0001 +phy_xaui_rx_polarity_flip_2=0x0001 +phy_xaui_tx_polarity_flip_3=0x0000 +phy_xaui_rx_polarity_flip_3=0x0001 +phy_xaui_tx_polarity_flip_4=0x0000 +phy_xaui_rx_polarity_flip_4=0x0001 + +#WC1 +phy_xaui_tx_polarity_flip_5=0x0001 +phy_xaui_rx_polarity_flip_5=0x0000 +phy_xaui_tx_polarity_flip_6=0x0001 +phy_xaui_rx_polarity_flip_6=0x0000 +phy_xaui_tx_polarity_flip_7=0x0001 +phy_xaui_rx_polarity_flip_7=0x0000 +phy_xaui_tx_polarity_flip_8=0x0000 +phy_xaui_rx_polarity_flip_8=0x0000 + +#WC2 +phy_xaui_tx_polarity_flip_9=0x0000 +phy_xaui_rx_polarity_flip_9=0x0000 +phy_xaui_tx_polarity_flip_10=0x0001 +phy_xaui_rx_polarity_flip_10=0x0000 +phy_xaui_tx_polarity_flip_11=0x0000 +phy_xaui_rx_polarity_flip_11=0x0000 +phy_xaui_tx_polarity_flip_12=0x0000 +phy_xaui_rx_polarity_flip_12=0x0001 + +#WC3 +phy_xaui_tx_polarity_flip_13=0x0001 +phy_xaui_rx_polarity_flip_13=0x0000 +phy_xaui_tx_polarity_flip_14=0x0001 +phy_xaui_rx_polarity_flip_14=0x0000 +phy_xaui_tx_polarity_flip_15=0x0001 +phy_xaui_rx_polarity_flip_15=0x0000 +phy_xaui_tx_polarity_flip_16=0x0001 +phy_xaui_rx_polarity_flip_16=0x0000 + +#WC4 +phy_xaui_tx_polarity_flip_17=0x0003 +phy_xaui_rx_polarity_flip_17=0x0000 +phy_xaui_tx_polarity_flip_18=0x0001 +phy_xaui_rx_polarity_flip_18=0x0000 + +#WC5 +phy_xaui_tx_polarity_flip_21=0x0000 +phy_xaui_rx_polarity_flip_21=0x0000 +phy_xaui_tx_polarity_flip_22=0x0000 +phy_xaui_rx_polarity_flip_22=0x0000 + +#WC6 +phy_xaui_tx_polarity_flip_25=0x0002 +phy_xaui_rx_polarity_flip_25=0x0001 +phy_xaui_tx_polarity_flip_26=0x0000 +phy_xaui_rx_polarity_flip_26=0x0001 + +#WC7 +phy_xaui_tx_polarity_flip_29=0x0002 +phy_xaui_rx_polarity_flip_29=0x0000 +phy_xaui_tx_polarity_flip_30=0x0000 +phy_xaui_rx_polarity_flip_30=0x0000 + +#WC28 +phy_xaui_tx_polarity_flip_118=0x0003 +phy_xaui_rx_polarity_flip_118=0x0003 +phy_xaui_tx_polarity_flip_119=0x0003 +phy_xaui_rx_polarity_flip_119=0x0003 + +#WC29 +phy_xaui_tx_polarity_flip_122=0x0000 +phy_xaui_rx_polarity_flip_122=0x0000 +phy_xaui_tx_polarity_flip_123=0x0001 +phy_xaui_rx_polarity_flip_123=0x0000 + +#WC30 +phy_xaui_tx_polarity_flip_126=0x0003 +phy_xaui_rx_polarity_flip_126=0x0000 +phy_xaui_tx_polarity_flip_127=0x0003 +phy_xaui_rx_polarity_flip_127=0x0000 + +#WC31 +phy_xaui_tx_polarity_flip_130=0x0002 +phy_xaui_rx_polarity_flip_130=0x0000 +phy_xaui_tx_polarity_flip_131=0x0001 +phy_xaui_rx_polarity_flip_131=0x0000 + diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/port_config.ini b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/port_config.ini new file mode 100644 index 000000000000..bed33e9ed0f5 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index speed +Ethernet0 65,66 Eth1/1 1 50000 +Ethernet2 67,68 Eth1/2 1 50000 +Ethernet4 69,70 Eth2/1 2 50000 +Ethernet6 71,72 Eth2/2 2 50000 +Ethernet8 73,74 Eth3/1 3 50000 +Ethernet10 75,76 Eth3/2 3 50000 +Ethernet12 77,78 Eth4/1 4 50000 +Ethernet14 79,80 Eth4/2 4 50000 +Ethernet16 33,34 Eth5/1 5 50000 +Ethernet18 35,36 Eth5/2 5 50000 +Ethernet20 37,38 Eth6/1 6 50000 +Ethernet22 39,40 Eth6/2 6 50000 +Ethernet24 41,42 Eth7/1 7 50000 +Ethernet26 43,44 Eth7/2 7 50000 +Ethernet28 45,46 Eth8/1 8 50000 +Ethernet30 47,48 Eth8/2 8 50000 +Ethernet32 49,50 Eth9/1 9 50000 +Ethernet34 51,52 Eth9/2 9 50000 +Ethernet36 53,54 Eth10/1 10 50000 +Ethernet38 55,56 Eth10/2 10 50000 +Ethernet40 57,58 Eth11/1 11 50000 +Ethernet42 59,60 Eth11/2 11 50000 +Ethernet44 61,62 Eth12/1 12 50000 +Ethernet46 63,64 Eth12/2 12 50000 +Ethernet48 81,82 Eth13/1 13 50000 +Ethernet50 83,84 Eth13/2 13 50000 +Ethernet52 85,86 Eth14/1 14 50000 +Ethernet54 87,88 Eth14/2 14 50000 +Ethernet56 89,90 Eth15/1 15 50000 +Ethernet58 91,92 Eth15/2 15 50000 +Ethernet60 93,94 Eth16/1 16 50000 +Ethernet62 95,96 Eth16/2 16 50000 +Ethernet64 97,98 Eth17/1 17 50000 +Ethernet66 99,100 Eth17/2 17 50000 +Ethernet68 101,102 Eth18/1 18 50000 +Ethernet70 103,104 Eth18/2 18 50000 +Ethernet72 105,106 Eth19/1 19 50000 +Ethernet74 107,108 Eth19/2 19 50000 +Ethernet76 109,110 Eth20/1 20 50000 +Ethernet78 111,112 Eth20/2 20 50000 +Ethernet80 1,2 Eth21/1 21 50000 +Ethernet82 3,4 Eth21/2 21 50000 +Ethernet84 5,6 Eth22/1 22 50000 +Ethernet86 7,8 Eth22/2 22 50000 +Ethernet88 9,10 Eth23/1 23 50000 +Ethernet90 11,12 Eth23/2 23 50000 +Ethernet92 13,14 Eth24/1 24 50000 +Ethernet94 15,16 Eth24/2 24 50000 +Ethernet96 17,18 Eth25/1 25 50000 +Ethernet98 19,20 Eth25/2 25 50000 +Ethernet100 21,22 Eth26/1 26 50000 +Ethernet102 23,24 Eth26/2 26 50000 +Ethernet104 25,26 Eth27/1 27 50000 +Ethernet106 27,28 Eth27/2 27 50000 +Ethernet108 29,30 Eth28/1 28 50000 +Ethernet110 31,32 Eth28/2 28 50000 +Ethernet112 113,114 Eth29/1 29 50000 +Ethernet114 115,116 Eth29/2 29 50000 +Ethernet116 117,118 Eth30/1 30 50000 +Ethernet118 119,120 Eth30/2 30 50000 +Ethernet120 121,122 Eth31/1 31 50000 +Ethernet122 123,124 Eth31/2 31 50000 +Ethernet124 125,126 Eth32/1 32 50000 +Ethernet126 127,128 Eth32/2 32 50000 \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/sai.profile b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/sai.profile new file mode 100644 index 000000000000..075fdfde2229 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-seastone-dx010-64x50G.config.bcm diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/th-seastone-dx010-64x50G.config.bcm b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/th-seastone-dx010-64x50G.config.bcm new file mode 100644 index 000000000000..07814e52ac4a --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/th-seastone-dx010-64x50G.config.bcm @@ -0,0 +1,621 @@ +# Define default OS / SAL +os=unix + +# all XPORTs to XE ports +#pbmp_xport_xe=0x1fffffffe +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +pbmp_oversubscribe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe + +# Mode control to select L2 Table DMA mode aka L2MODE_POLL (0) or +# L2MOD_FIFO mechanism aka L2MODE_FIFO (1) for L2 table change notification. +l2xmsg_mode=1 + +# Memory table size configs +l2_mem_entries=8192 +l3_mem_entries=8192 +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +mmu_lossless=0 + +################################################################################### +# Celestica Customize for SeaStone +################################################################################### + +#ext mdio frequency to 495/0x80/2(1.933Mhz) or 415/0x80/2(1.62MHz) +# default is 40 +# Set external MDIO freq to 6.19MHz (495MHz) or 5.19MHz (415MHz) +#* target_freq is core_clock_freq * DIVIDEND / DIVISOR / 2 +# +rate_ext_mdio_divisor=0x80 + +# use internal rom boot +phy_ext_rom_boot=0 + +#fpem_mem_entries=32768 +oversubscribe_mode=1 +#pbmp_xport_xe=0x3fd000000ff4000003fc000001fe + +dport_map_enable=1 +dport_map_port_68=1 +dport_map_port_69=2 + +dport_map_port_72=5 +dport_map_port_73=6 + +dport_map_port_76=9 +dport_map_port_77=10 + +dport_map_port_80=13 +dport_map_port_81=14 + +dport_map_port_34=17 +dport_map_port_35=18 + +dport_map_port_38=21 +dport_map_port_39=22 + +dport_map_port_42=25 +dport_map_port_43=26 + +dport_map_port_46=29 +dport_map_port_47=30 + +dport_map_port_50=33 +dport_map_port_51=34 + +dport_map_port_54=37 +dport_map_port_55=38 + +dport_map_port_58=41 +dport_map_port_59=42 + +dport_map_port_62=45 +dport_map_port_63=46 + +dport_map_port_84=49 +dport_map_port_85=50 + +dport_map_port_88=53 +dport_map_port_89=54 + +dport_map_port_92=57 +dport_map_port_93=58 + +dport_map_port_96=61 +dport_map_port_97=62 + +dport_map_port_102=65 +dport_map_port_103=66 + +dport_map_port_106=69 +dport_map_port_107=70 + +dport_map_port_110=73 +dport_map_port_111=74 + +dport_map_port_114=77 +dport_map_port_115=78 + +dport_map_port_1=81 +dport_map_port_2=82 + +dport_map_port_5=85 +dport_map_port_6=86 + +dport_map_port_9=89 +dport_map_port_10=90 + +dport_map_port_13=93 +dport_map_port_14=94 + +dport_map_port_17=97 +dport_map_port_18=98 + +dport_map_port_21=101 +dport_map_port_22=102 + +dport_map_port_25=105 +dport_map_port_26=106 + +dport_map_port_29=109 +dport_map_port_30=110 + +dport_map_port_118=113 +dport_map_port_119=114 + +dport_map_port_122=117 +dport_map_port_123=118 + +dport_map_port_126=121 +dport_map_port_127=122 + +dport_map_port_130=125 +dport_map_port_131=126 + + +# port mapping +portmap_68=65:50:2 +portmap_69=67:50:2 + +portmap_72=69:50:2 +portmap_73=71:50:2 + +portmap_76=73:50:2 +portmap_77=75:50:2 + +portmap_80=77:50:2 +portmap_81=79:50:2 + +portmap_34=33:50:2 +portmap_35=35:50:2 + +portmap_38=37:50:2 +portmap_39=39:50:2 + +portmap_42=41:50:2 +portmap_43=43:50:2 + +portmap_46=45:50:2 +portmap_47=47:50:2 + +portmap_50=49:50:2 +portmap_51=51:50:2 + +portmap_54=53:50:2 +portmap_55=55:50:2 + +portmap_58=57:50:2 +portmap_59=59:50:2 + +portmap_62=61:50:2 +portmap_63=63:50:2 + +portmap_84=81:50:2 +portmap_85=83:50:2 + +portmap_88=85:50:2 +portmap_89=87:50:2 + +portmap_92=89:50:2 +portmap_93=91:50:2 + +portmap_96=93:50:2 +portmap_97=95:50:2 + +portmap_102=97:50:2 +portmap_103=99:50:2 + +portmap_106=101:50:2 +portmap_107=103:50:2 + +portmap_110=105:50:2 +portmap_111=107:50:2 + +portmap_114=109:50:2 +portmap_115=111:50:2 + +portmap_1=1:50:2 +portmap_2=3:50:2 + +portmap_5=5:50:2 +portmap_6=7:50:2 + +portmap_9=9:50:2 +portmap_10=11:50:2 + +portmap_13=13:50:2 +portmap_14=15:50:2 + +portmap_17=17:50:2 +portmap_18=19:50:2 + +portmap_21=21:50:2 +portmap_22=23:50:2 + +portmap_25=25:50:2 +portmap_26=27:50:2 + +portmap_29=29:50:2 +portmap_30=31:50:2 + +portmap_118=113:50:2 +portmap_119=115:50:2 + +portmap_122=117:50:2 +portmap_123=119:50:2 + +portmap_126=121:50:2 +portmap_127=123:50:2 + +portmap_130=125:50:2 +portmap_131=127:50:2 + + +#WC16 +xgxs_tx_lane_map_68=0x3201 +xgxs_rx_lane_map_68=0x2310 +xgxs_tx_lane_map_69=0x3201 +xgxs_rx_lane_map_69=0x2310 + + +#WC17 +xgxs_tx_lane_map_72=0x3201 +xgxs_rx_lane_map_72=0x2301 +xgxs_tx_lane_map_73=0x3201 +xgxs_rx_lane_map_73=0x2301 + +#WC18 +xgxs_tx_lane_map_76=0x0132 +xgxs_rx_lane_map_76=0x0123 +xgxs_tx_lane_map_77=0x0132 +xgxs_rx_lane_map_77=0x0123 + +#WC19 +xgxs_tx_lane_map_80=0x2031 +xgxs_rx_lane_map_80=0x1320 +xgxs_tx_lane_map_81=0x2031 +xgxs_rx_lane_map_81=0x1320 + +#WC8 +xgxs_tx_lane_map_34=0x3021 +xgxs_rx_lane_map_34=0x0213 +xgxs_tx_lane_map_35=0x3021 +xgxs_rx_lane_map_35=0x0213 + +#WC9 +xgxs_tx_lane_map_38=0x3210 +xgxs_rx_lane_map_38=0x1023 +xgxs_tx_lane_map_39=0x3210 +xgxs_rx_lane_map_39=0x1023 + +#WC10 +xgxs_tx_lane_map_42=0x2310 +xgxs_rx_lane_map_42=0x3210 +xgxs_tx_lane_map_43=0x2310 +xgxs_rx_lane_map_43=0x3210 + +#WC11 +xgxs_tx_lane_map_46=0x1032 +xgxs_rx_lane_map_46=0x1302 +xgxs_tx_lane_map_47=0x1032 +xgxs_rx_lane_map_47=0x1302 + +#WC12 +xgxs_tx_lane_map_50=0x3201 +xgxs_rx_lane_map_50=0x0213 +xgxs_tx_lane_map_51=0x3201 +xgxs_rx_lane_map_51=0x0213 + + +#WC13 +xgxs_tx_lane_map_54=0x2301 +xgxs_rx_lane_map_54=0x2310 +xgxs_tx_lane_map_55=0x2301 +xgxs_rx_lane_map_55=0x2310 + +#WC14 +xgxs_tx_lane_map_58=0x3201 +xgxs_rx_lane_map_58=0x0213 +xgxs_tx_lane_map_59=0x3201 +xgxs_rx_lane_map_59=0x0213 + +#WC15 +xgxs_tx_lane_map_62=0x1302 +xgxs_rx_lane_map_62=0x2310 +xgxs_tx_lane_map_63=0x1302 +xgxs_rx_lane_map_63=0x2310 + +#WC20 +xgxs_tx_lane_map_84=0x0213 +xgxs_rx_lane_map_84=0x2301 +xgxs_tx_lane_map_85=0x0213 +xgxs_rx_lane_map_85=0x2301 + +#WC21 +xgxs_tx_lane_map_88=0x0132 +xgxs_rx_lane_map_88=0x3210 +xgxs_tx_lane_map_89=0x0132 +xgxs_rx_lane_map_89=0x3210 + +#WC22 +xgxs_tx_lane_map_92=0x0132 +xgxs_rx_lane_map_92=0x2031 +xgxs_tx_lane_map_93=0x0132 +xgxs_rx_lane_map_93=0x2031 + +#WC23 +xgxs_tx_lane_map_96=0x2031 +xgxs_rx_lane_map_96=0x3201 +xgxs_tx_lane_map_97=0x2031 +xgxs_rx_lane_map_97=0x3201 + +#WC24 +xgxs_tx_lane_map_102=0x0132 +xgxs_rx_lane_map_102=0x2301 +xgxs_tx_lane_map_103=0x0132 +xgxs_rx_lane_map_103=0x2301 + +#WC25 +xgxs_tx_lane_map_106=0x0132 +xgxs_rx_lane_map_106=0x3201 +xgxs_tx_lane_map_107=0x0132 +xgxs_rx_lane_map_107=0x3201 + +#WC26 +xgxs_tx_lane_map_110=0x0132 +xgxs_rx_lane_map_110=0x2031 +xgxs_tx_lane_map_111=0x0132 +xgxs_rx_lane_map_111=0x2031 + +#WC27 +xgxs_tx_lane_map_114=0x2031 +xgxs_rx_lane_map_114=0x2301 +xgxs_tx_lane_map_115=0x2031 +xgxs_rx_lane_map_115=0x2301 + + +#WC0 +xgxs_tx_lane_map_1=0x3210 +xgxs_rx_lane_map_1=0x3120 +xgxs_tx_lane_map_2=0x3210 +xgxs_rx_lane_map_2=0x3120 + +#WC1 +xgxs_tx_lane_map_5=0x0132 +xgxs_rx_lane_map_5=0x1023 +xgxs_tx_lane_map_6=0x0132 +xgxs_rx_lane_map_6=0x1023 + +#WC2 +xgxs_tx_lane_map_9=0x3201 +xgxs_rx_lane_map_9=0x3120 +xgxs_tx_lane_map_10=0x3201 +xgxs_rx_lane_map_10=0x3120 + +#WC3 +xgxs_tx_lane_map_13=0x2031 +xgxs_rx_lane_map_13=0x1032 +xgxs_tx_lane_map_14=0x2031 +xgxs_rx_lane_map_14=0x1032 + +#WC4 +xgxs_tx_lane_map_17=0x2310 +xgxs_rx_lane_map_17=0x3210 +xgxs_tx_lane_map_18=0x2310 +xgxs_rx_lane_map_18=0x3210 + +#WC5 +xgxs_tx_lane_map_21=0x2301 +xgxs_rx_lane_map_21=0x3120 +xgxs_tx_lane_map_22=0x2301 +xgxs_rx_lane_map_22=0x3120 + +#WC6 +xgxs_tx_lane_map_25=0x3201 +xgxs_rx_lane_map_25=0x0213 +xgxs_tx_lane_map_26=0x3201 +xgxs_rx_lane_map_26=0x0213 + +#WC7 +xgxs_tx_lane_map_29=0x1302 +xgxs_rx_lane_map_29=0x1023 +xgxs_tx_lane_map_30=0x1302 +xgxs_rx_lane_map_30=0x1023 + +#WC28 +xgxs_tx_lane_map_118=0x1320 +xgxs_rx_lane_map_118=0x1302 +xgxs_tx_lane_map_119=0x1320 +xgxs_rx_lane_map_119=0x1302 + +#WC29 +xgxs_tx_lane_map_122=0x1032 +xgxs_rx_lane_map_122=0x1023 +xgxs_tx_lane_map_123=0x1032 +xgxs_rx_lane_map_123=0x1023 + +#WC30 +xgxs_tx_lane_map_126=0x3120 +xgxs_rx_lane_map_126=0x3120 +xgxs_tx_lane_map_127=0x3120 +xgxs_rx_lane_map_127=0x3120 + +#WC31 +xgxs_tx_lane_map_130=0x1302 +xgxs_rx_lane_map_130=0x2310 +xgxs_tx_lane_map_131=0x1302 +xgxs_rx_lane_map_131=0x2310 + +#PN + +#WC16 +phy_xaui_tx_polarity_flip_68=0x0000 +phy_xaui_rx_polarity_flip_68=0x0000 +phy_xaui_tx_polarity_flip_69=0x0000 +phy_xaui_rx_polarity_flip_69=0x0000 + +#WC17 +phy_xaui_tx_polarity_flip_72=0x0001 +phy_xaui_rx_polarity_flip_72=0x0002 +phy_xaui_tx_polarity_flip_73=0x0003 +phy_xaui_rx_polarity_flip_73=0x0000 + +#WC18 +phy_xaui_tx_polarity_flip_76=0x0003 +phy_xaui_rx_polarity_flip_76=0x0000 +phy_xaui_tx_polarity_flip_77=0x0003 +phy_xaui_rx_polarity_flip_77=0x0000 + +#WC19 +phy_xaui_tx_polarity_flip_80=0x0003 +phy_xaui_rx_polarity_flip_80=0x0003 +phy_xaui_tx_polarity_flip_81=0x0003 +phy_xaui_rx_polarity_flip_81=0x0003 + +#WC8 +phy_xaui_tx_polarity_flip_34=0x0002 +phy_xaui_rx_polarity_flip_34=0x0000 +phy_xaui_tx_polarity_flip_35=0x0003 +phy_xaui_rx_polarity_flip_35=0x0000 + +#WC9 +phy_xaui_tx_polarity_flip_38=0x0000 +phy_xaui_rx_polarity_flip_38=0x0000 +phy_xaui_tx_polarity_flip_39=0x0002 +phy_xaui_rx_polarity_flip_39=0x0000 + +#WC10 +phy_xaui_tx_polarity_flip_42=0x0001 +phy_xaui_rx_polarity_flip_42=0x0000 +phy_xaui_tx_polarity_flip_43=0x0003 +phy_xaui_rx_polarity_flip_43=0x0000 + +#WC11 +phy_xaui_tx_polarity_flip_46=0x0000 +phy_xaui_rx_polarity_flip_46=0x0000 +phy_xaui_tx_polarity_flip_47=0x0000 +phy_xaui_rx_polarity_flip_47=0x0000 + +#WC12 +phy_xaui_tx_polarity_flip_50=0x0002 +phy_xaui_rx_polarity_flip_50=0x0000 +phy_xaui_tx_polarity_flip_51=0x0000 +phy_xaui_rx_polarity_flip_51=0x0000 + +#WC13 +phy_xaui_tx_polarity_flip_54=0x0002 +phy_xaui_rx_polarity_flip_54=0x0000 +phy_xaui_tx_polarity_flip_55=0x0000 +phy_xaui_rx_polarity_flip_55=0x0000 + +#WC14 +phy_xaui_tx_polarity_flip_58=0x0000 +phy_xaui_rx_polarity_flip_58=0x0000 +phy_xaui_tx_polarity_flip_59=0x0000 +phy_xaui_rx_polarity_flip_59=0x0000 + +#WC15 +phy_xaui_tx_polarity_flip_62=0x0002 +phy_xaui_rx_polarity_flip_62=0x0003 +phy_xaui_tx_polarity_flip_63=0x0002 +phy_xaui_rx_polarity_flip_63=0x0003 + +#WC20 +phy_xaui_tx_polarity_flip_84=0x0003 +phy_xaui_rx_polarity_flip_84=0x0002 +phy_xaui_tx_polarity_flip_85=0x0001 +phy_xaui_rx_polarity_flip_85=0x0003 + +#WC21 +phy_xaui_tx_polarity_flip_88=0x0001 +phy_xaui_rx_polarity_flip_88=0x0001 +phy_xaui_tx_polarity_flip_89=0x0003 +phy_xaui_rx_polarity_flip_89=0x0003 + +#WC22 +phy_xaui_tx_polarity_flip_92=0x0003 +phy_xaui_rx_polarity_flip_92=0x0000 +phy_xaui_tx_polarity_flip_93=0x0003 +phy_xaui_rx_polarity_flip_93=0x0002 + +#WC23 +phy_xaui_tx_polarity_flip_96=0x0001 +phy_xaui_rx_polarity_flip_96=0x0000 +phy_xaui_tx_polarity_flip_97=0x0001 +phy_xaui_rx_polarity_flip_97=0x0000 + +#WC24 +phy_xaui_tx_polarity_flip_102=0x0000 +phy_xaui_rx_polarity_flip_102=0x0003 +phy_xaui_tx_polarity_flip_103=0x0000 +phy_xaui_rx_polarity_flip_103=0x0003 + +#WC25 +phy_xaui_tx_polarity_flip_106=0x0003 +phy_xaui_rx_polarity_flip_106=0x0000 +phy_xaui_tx_polarity_flip_107=0x0003 +phy_xaui_rx_polarity_flip_107=0x0000 + +#WC26 +phy_xaui_tx_polarity_flip_110=0x0003 +phy_xaui_rx_polarity_flip_110=0x0003 +phy_xaui_tx_polarity_flip_111=0x0003 +phy_xaui_rx_polarity_flip_111=0x0003 + +#WC27 +phy_xaui_tx_polarity_flip_114=0x0003 +phy_xaui_rx_polarity_flip_114=0x0003 +phy_xaui_tx_polarity_flip_115=0x0003 +phy_xaui_rx_polarity_flip_115=0x0001 + +#WC0 +phy_xaui_tx_polarity_flip_1=0x0003 +phy_xaui_rx_polarity_flip_1=0x0003 +phy_xaui_tx_polarity_flip_2=0x0000 +phy_xaui_rx_polarity_flip_2=0x0003 + +#WC1 +phy_xaui_tx_polarity_flip_5=0x0003 +phy_xaui_rx_polarity_flip_5=0x0000 +phy_xaui_tx_polarity_flip_6=0x0001 +phy_xaui_rx_polarity_flip_6=0x0000 + +#WC2 +phy_xaui_tx_polarity_flip_9=0x0002 +phy_xaui_rx_polarity_flip_9=0x0000 +phy_xaui_tx_polarity_flip_10=0x0000 +phy_xaui_rx_polarity_flip_10=0x0002 + +#WC3 +phy_xaui_tx_polarity_flip_13=0x0003 +phy_xaui_rx_polarity_flip_13=0x0000 +phy_xaui_tx_polarity_flip_14=0x0003 +phy_xaui_rx_polarity_flip_14=0x0000 + +#WC4 +phy_xaui_tx_polarity_flip_17=0x0003 +phy_xaui_rx_polarity_flip_17=0x0000 +phy_xaui_tx_polarity_flip_18=0x0001 +phy_xaui_rx_polarity_flip_18=0x0000 + +#WC5 +phy_xaui_tx_polarity_flip_21=0x0000 +phy_xaui_rx_polarity_flip_21=0x0000 +phy_xaui_tx_polarity_flip_22=0x0000 +phy_xaui_rx_polarity_flip_22=0x0000 + +#WC6 +phy_xaui_tx_polarity_flip_25=0x0002 +phy_xaui_rx_polarity_flip_25=0x0001 +phy_xaui_tx_polarity_flip_26=0x0000 +phy_xaui_rx_polarity_flip_26=0x0001 + +#WC7 +phy_xaui_tx_polarity_flip_29=0x0002 +phy_xaui_rx_polarity_flip_29=0x0000 +phy_xaui_tx_polarity_flip_30=0x0000 +phy_xaui_rx_polarity_flip_30=0x0000 + +#WC28 +phy_xaui_tx_polarity_flip_118=0x0003 +phy_xaui_rx_polarity_flip_118=0x0003 +phy_xaui_tx_polarity_flip_119=0x0003 +phy_xaui_rx_polarity_flip_119=0x0003 + +#WC29 +phy_xaui_tx_polarity_flip_122=0x0000 +phy_xaui_rx_polarity_flip_122=0x0000 +phy_xaui_tx_polarity_flip_123=0x0001 +phy_xaui_rx_polarity_flip_123=0x0000 + +#WC30 +phy_xaui_tx_polarity_flip_126=0x0003 +phy_xaui_rx_polarity_flip_126=0x0000 +phy_xaui_tx_polarity_flip_127=0x0003 +phy_xaui_rx_polarity_flip_127=0x0000 + +#WC31 +phy_xaui_tx_polarity_flip_130=0x0002 +phy_xaui_rx_polarity_flip_130=0x0000 +phy_xaui_tx_polarity_flip_131=0x0001 +phy_xaui_rx_polarity_flip_131=0x0000 diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/port_config.ini b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/port_config.ini new file mode 100644 index 000000000000..91d2f91d41cc --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 65,66,67,68 Eth1 1 100000 +Ethernet4 69,70,71,72 Eth2 2 100000 +Ethernet8 73,74,75,76 Eth3 3 100000 +Ethernet12 77,78,79,80 Eth4 4 100000 +Ethernet16 33,34,35,36 Eth5 5 100000 +Ethernet20 37,38,39,40 Eth6 6 100000 +Ethernet24 41,42,43,44 Eth7 7 100000 +Ethernet28 45,46,47,48 Eth8 8 100000 +Ethernet32 49,50,51,52 Eth9 9 100000 +Ethernet36 53,54,55,56 Eth10 10 100000 +Ethernet40 57,58,59,60 Eth11 11 100000 +Ethernet44 61,62,63,64 Eth12 12 100000 +Ethernet48 81,82,83,84 Eth13 13 100000 +Ethernet52 85,86,87,88 Eth14 14 100000 +Ethernet56 89,90,91,92 Eth15 15 100000 +Ethernet60 93,94,95,96 Eth16 16 100000 +Ethernet64 97,98,99,100 Eth17 17 100000 +Ethernet68 101,102,103,104 Eth18 18 100000 +Ethernet72 105,106,107,108 Eth19 19 100000 +Ethernet76 109,110,111,112 Eth20 20 100000 +Ethernet80 1,2,3,4 Eth21 21 100000 +Ethernet84 5,6,7,8 Eth22 22 100000 +Ethernet88 9,10,11,12 Eth23 23 100000 +Ethernet92 13,14,15,16 Eth24 24 100000 +Ethernet96 17,18,19,20 Eth25 25 100000 +Ethernet100 21,22,23,24 Eth26 26 100000 +Ethernet104 25,26,27,28 Eth27 27 100000 +Ethernet108 29,30,31,32 Eth28 28 100000 +Ethernet112 113,114,115,116 Eth29 29 100000 +Ethernet116 117,118,119,120 Eth30 30 100000 +Ethernet120 121,122,123,124 Eth31 31 100000 +Ethernet124 125,126,127,128 Eth32 32 100000 \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/sai.profile b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/sai.profile new file mode 100644 index 000000000000..072467af3e9a --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-seastone-dx010-32x100G.config.bcm diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/th-seastone-dx010-32x100G.config.bcm b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/th-seastone-dx010-32x100G.config.bcm new file mode 100644 index 000000000000..c8f3523189e3 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/th-seastone-dx010-32x100G.config.bcm @@ -0,0 +1,374 @@ +# Define default OS / SAL +os=unix + +# all XPORTs to XE ports +#pbmp_xport_xe=0x1fffffffe +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +pbmp_oversubscribe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe + +# Mode control to select L2 Table DMA mode aka L2MODE_POLL (0) or +# L2MOD_FIFO mechanism aka L2MODE_FIFO (1) for L2 table change notification. +l2xmsg_mode=1 + +# Memory table size configs +l2_mem_entries=8192 +l3_mem_entries=8192 +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +mmu_lossless=0 + +################################################################################### +# Celestica Customize for SeaStone +################################################################################### + +#ext mdio frequency to 495/0x80/2(1.933Mhz) or 415/0x80/2(1.62MHz) +# default is 40 +# Set external MDIO freq to 6.19MHz (495MHz) or 5.19MHz (415MHz) +#* target_freq is core_clock_freq * DIVIDEND / DIVISOR / 2 +# +rate_ext_mdio_divisor=0x80 + +# use internal rom boot +phy_ext_rom_boot=0 + +#fpem_mem_entries=32768 +oversubscribe_mode=1 +#pbmp_xport_xe=0x3fd000000ff4000003fc000001fe + + +dport_map_enable=1 + +dport_map_port_68=1 +dport_map_port_72=5 +dport_map_port_76=9 +dport_map_port_80=13 +dport_map_port_34=17 +dport_map_port_38=21 +dport_map_port_42=25 +dport_map_port_46=29 +dport_map_port_50=33 +dport_map_port_54=37 +dport_map_port_58=41 +dport_map_port_62=45 +dport_map_port_84=49 +dport_map_port_88=53 +dport_map_port_92=57 +dport_map_port_96=61 +dport_map_port_102=65 +dport_map_port_106=69 +dport_map_port_110=73 +dport_map_port_114=77 +dport_map_port_1=81 +dport_map_port_5=85 +dport_map_port_9=89 +dport_map_port_13=93 +dport_map_port_17=97 +dport_map_port_21=101 +dport_map_port_25=105 +dport_map_port_29=109 +dport_map_port_118=113 +dport_map_port_122=117 +dport_map_port_126=121 +dport_map_port_130=125 + + +# port mapping +portmap_68=65:100:4 +portmap_72=69:100:4 +portmap_76=73:100:4 +portmap_80=77:100:4 +portmap_34=33:100:4 +portmap_38=37:100:4 +portmap_42=41:100:4 +portmap_46=45:100:4 +portmap_50=49:100:4 +portmap_54=53:100:4 +portmap_58=57:100:4 +portmap_62=61:100:4 +portmap_84=81:100:4 +portmap_88=85:100:4 +portmap_92=89:100:4 +portmap_96=93:100:4 +portmap_102=97:100:4 +portmap_106=101:100:4 +portmap_110=105:100:4 +portmap_114=109:100:4 +portmap_1=1:100:4 +portmap_5=5:100:4 +portmap_9=9:100:4 +portmap_13=13:100:4 +portmap_17=17:100:4 +portmap_21=21:100:4 +portmap_25=25:100:4 +portmap_29=29:100:4 +portmap_118=113:100:4 +portmap_122=117:100:4 +portmap_126=121:100:4 +portmap_130=125:100:4 +#portmap_66=129:10 +#portmap_100=131:10 + +#WC16 +xgxs_tx_lane_map_68=0x3201 +xgxs_rx_lane_map_68=0x2310 + + +#WC17 +xgxs_tx_lane_map_72=0x3201 +xgxs_rx_lane_map_72=0x2301 + +#WC18 +xgxs_tx_lane_map_76=0x0132 +xgxs_rx_lane_map_76=0x0123 + +#WC19 +xgxs_tx_lane_map_80=0x2031 +xgxs_rx_lane_map_80=0x1320 + +#WC8 +xgxs_tx_lane_map_34=0x3021 +xgxs_rx_lane_map_34=0x0213 + +#WC9 +xgxs_tx_lane_map_38=0x3210 +xgxs_rx_lane_map_38=0x1023 + +#WC10 +xgxs_tx_lane_map_42=0x2310 +xgxs_rx_lane_map_42=0x3210 + +#WC11 +xgxs_tx_lane_map_46=0x1032 +xgxs_rx_lane_map_46=0x1302 + +#WC12 +xgxs_tx_lane_map_50=0x3201 +xgxs_rx_lane_map_50=0x0213 + + +#WC13 +xgxs_tx_lane_map_54=0x2301 +xgxs_rx_lane_map_54=0x2310 + +#WC14 +xgxs_tx_lane_map_58=0x3201 +xgxs_rx_lane_map_58=0x0213 + +#WC15 +xgxs_tx_lane_map_62=0x1302 +xgxs_rx_lane_map_62=0x2310 + +#WC20 +xgxs_tx_lane_map_84=0x0213 +xgxs_rx_lane_map_84=0x2301 + +#WC21 +xgxs_tx_lane_map_88=0x0132 +xgxs_rx_lane_map_88=0x3210 + +#WC22 +xgxs_tx_lane_map_92=0x0132 +xgxs_rx_lane_map_92=0x2031 + +#WC23 +xgxs_tx_lane_map_96=0x2031 +xgxs_rx_lane_map_96=0x3201 + +#WC24 +xgxs_tx_lane_map_102=0x0132 +xgxs_rx_lane_map_102=0x2301 + +#WC25 +xgxs_tx_lane_map_106=0x0132 +xgxs_rx_lane_map_106=0x3201 + +#WC26 +xgxs_tx_lane_map_110=0x0132 +xgxs_rx_lane_map_110=0x2031 + +#WC27 +xgxs_tx_lane_map_114=0x2031 +xgxs_rx_lane_map_114=0x2301 + + +#WC0 +xgxs_tx_lane_map_1=0x3210 +xgxs_rx_lane_map_1=0x3120 + +#WC1 +xgxs_tx_lane_map_5=0x0132 +xgxs_rx_lane_map_5=0x1023 + +#WC2 +xgxs_tx_lane_map_9=0x3201 +xgxs_rx_lane_map_9=0x3120 + +#WC3 +xgxs_tx_lane_map_13=0x2031 +xgxs_rx_lane_map_13=0x1032 + +#WC4 +xgxs_tx_lane_map_17=0x2310 +xgxs_rx_lane_map_17=0x3210 + +#WC5 +xgxs_tx_lane_map_21=0x2301 +xgxs_rx_lane_map_21=0x3120 + +#WC6 +xgxs_tx_lane_map_25=0x3201 +xgxs_rx_lane_map_25=0x0213 + +#WC7 +xgxs_tx_lane_map_29=0x1302 +xgxs_rx_lane_map_29=0x1023 + +#WC28 +xgxs_tx_lane_map_118=0x1320 +xgxs_rx_lane_map_118=0x1302 + +#WC29 +xgxs_tx_lane_map_122=0x1032 +xgxs_rx_lane_map_122=0x1023 + +#WC30 +xgxs_tx_lane_map_126=0x3120 +xgxs_rx_lane_map_126=0x3120 + +#WC31 +xgxs_tx_lane_map_130=0x1302 +xgxs_rx_lane_map_130=0x2310 + +#PN + +#WC16 +phy_xaui_tx_polarity_flip_68=0x0000 +phy_xaui_rx_polarity_flip_68=0x0000 + +#WC17 +phy_xaui_tx_polarity_flip_72=0x000D +phy_xaui_rx_polarity_flip_72=0x0002 + + +#WC18 +phy_xaui_tx_polarity_flip_76=0x000F +phy_xaui_rx_polarity_flip_76=0x0000 + +#WC19 +phy_xaui_tx_polarity_flip_80=0x000F +phy_xaui_rx_polarity_flip_80=0x000F + + +#WC8 +phy_xaui_tx_polarity_flip_34=0x000E +phy_xaui_rx_polarity_flip_34=0x0000 + +#WC9 +phy_xaui_tx_polarity_flip_38=0x0008 +phy_xaui_rx_polarity_flip_38=0x0000 + +#WC10 +phy_xaui_tx_polarity_flip_42=0x000D +phy_xaui_rx_polarity_flip_42=0x0000 + +#WC11 +phy_xaui_tx_polarity_flip_46=0x0000 +phy_xaui_rx_polarity_flip_46=0x0000 + + +#WC12 +phy_xaui_tx_polarity_flip_50=0x0002 +phy_xaui_rx_polarity_flip_50=0x0000 + +#WC13 +phy_xaui_tx_polarity_flip_54=0x0002 +phy_xaui_rx_polarity_flip_54=0x0000 + +#WC14 +phy_xaui_tx_polarity_flip_58=0x0000 +phy_xaui_rx_polarity_flip_58=0x0000 + +#WC15 +phy_xaui_tx_polarity_flip_62=0x000A +phy_xaui_rx_polarity_flip_62=0x000F + + +#WC20 + phy_xaui_tx_polarity_flip_84=0x0007 + phy_xaui_rx_polarity_flip_84=0x000E + +#WC21 +phy_xaui_tx_polarity_flip_88=0x000D +phy_xaui_rx_polarity_flip_88=0x000D + +#WC22 +phy_xaui_tx_polarity_flip_92=0x000F +phy_xaui_rx_polarity_flip_92=0x0008 + +#WC23 +phy_xaui_tx_polarity_flip_96=0x0005 +phy_xaui_rx_polarity_flip_96=0x0000 + +#WC24 +phy_xaui_tx_polarity_flip_102=0x0000 +phy_xaui_rx_polarity_flip_102=0x000F + +#WC25 +phy_xaui_tx_polarity_flip_106=0x000F +phy_xaui_rx_polarity_flip_106=0x0000 + +#WC26 +phy_xaui_tx_polarity_flip_110=0x000F +phy_xaui_rx_polarity_flip_110=0x000F + +#WC27 +phy_xaui_tx_polarity_flip_114=0x000F +phy_xaui_rx_polarity_flip_114=0x0007 + +#WC0 +phy_xaui_tx_polarity_flip_1=0x0003 +phy_xaui_rx_polarity_flip_1=0x000F + +#WC1 +phy_xaui_tx_polarity_flip_5=0x0007 +phy_xaui_rx_polarity_flip_5=0x0000 + +#WC2 +phy_xaui_tx_polarity_flip_9=0x0002 +phy_xaui_rx_polarity_flip_9=0x0008 + +#WC3 +phy_xaui_tx_polarity_flip_13=0x000F +phy_xaui_rx_polarity_flip_13=0x0000 + +#WC4 +phy_xaui_tx_polarity_flip_17=0x0007 +phy_xaui_rx_polarity_flip_17=0x0000 + +#WC5 +phy_xaui_tx_polarity_flip_21=0x0000 +phy_xaui_rx_polarity_flip_21=0x0000 + +#WC6 +phy_xaui_tx_polarity_flip_25=0x0002 +phy_xaui_rx_polarity_flip_25=0x0005 + +#WC7 +phy_xaui_tx_polarity_flip_29=0x0002 +phy_xaui_rx_polarity_flip_29=0x0000 + +#WC28 +phy_xaui_tx_polarity_flip_118=0x000F +phy_xaui_rx_polarity_flip_118=0x000F + +#WC29 +phy_xaui_tx_polarity_flip_122=0x0004 +phy_xaui_rx_polarity_flip_122=0x0000 + +#WC30 +phy_xaui_tx_polarity_flip_126=0x000F +phy_xaui_rx_polarity_flip_126=0x0000 + +#WC31 +phy_xaui_tx_polarity_flip_130=0x0006 +phy_xaui_rx_polarity_flip_130=0x0000 diff --git a/device/celestica/x86_64-cel_seastone-r0/default_sku b/device/celestica/x86_64-cel_seastone-r0/default_sku new file mode 100644 index 000000000000..0c95475c8505 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/default_sku @@ -0,0 +1 @@ +Seastone-DX010 t1 diff --git a/device/celestica/x86_64-cel_seastone-r0/fancontrol b/device/celestica/x86_64-cel_seastone-r0/fancontrol new file mode 100644 index 000000000000..8d5cbccb9d00 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/fancontrol @@ -0,0 +1,12 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon6=devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-002e hwmon7=devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-004d +DEVNAME=hwmon6=emc2305 hwmon7=emc2305 +FCTEMPS=hwmon6/device/pwm1=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon6/device/pwm2=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon6/device/pwm3=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon6/device/pwm4=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon6/device/pwm5=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon7/device/pwm1=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon7/device/pwm2=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon7/device/pwm3=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon7/device/pwm4=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon7/device/pwm5=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input +FCFANS=hwmon7/device/pwm5=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-004d/pwm5 hwmon7/device/pwm4=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-004d/pwm4 hwmon7/device/pwm3=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-004d/pwm3 hwmon7/device/pwm2=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-004d/pwm2 hwmon7/device/pwm1=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-004d/pwm1 hwmon6/device/pwm5=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-002e/pwm5 hwmon6/device/pwm4=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-002e/pwm4 hwmon6/device/pwm3=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-002e/pwm3 hwmon6/device/pwm2=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-002e/pwm2 hwmon6/device/pwm1=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-002e/pwm1 +MINTEMP=hwmon6/device/pwm1=26 hwmon6/device/pwm2=26 hwmon6/device/pwm3=26 hwmon6/device/pwm4=26 hwmon6/device/pwm5=26 hwmon7/device/pwm1=26 hwmon7/device/pwm2=26 hwmon7/device/pwm3=26 hwmon7/device/pwm4=26 hwmon7/device/pwm5=26 +MAXTEMP=hwmon6/device/pwm1=45 hwmon6/device/pwm2=45 hwmon6/device/pwm3=45 hwmon6/device/pwm4=45 hwmon6/device/pwm5=45 hwmon7/device/pwm1=45 hwmon7/device/pwm2=45 hwmon7/device/pwm3=45 hwmon7/device/pwm4=45 hwmon7/device/pwm5=45 +MINSTART=hwmon6/device/pwm1=89 hwmon6/device/pwm2=89 hwmon6/device/pwm3=89 hwmon6/device/pwm4=89 hwmon6/device/pwm5=89 hwmon7/device/pwm1=89 hwmon7/device/pwm2=89 hwmon7/device/pwm3=89 hwmon7/device/pwm4=89 hwmon7/device/pwm5=89 +MINSTOP=hwmon6/device/pwm1=89 hwmon6/device/pwm2=89 hwmon6/device/pwm3=89 hwmon6/device/pwm4=89 hwmon6/device/pwm5=89 hwmon7/device/pwm1=89 hwmon7/device/pwm2=89 hwmon7/device/pwm3=89 hwmon7/device/pwm4=89 hwmon7/device/pwm5=89 +MINPWM=hwmon6/device/pwm1=89 hwmon6/device/pwm2=89 hwmon6/device/pwm3=89 hwmon6/device/pwm4=89 hwmon6/device/pwm5=89 hwmon7/device/pwm1=89 hwmon7/device/pwm2=89 hwmon7/device/pwm3=89 hwmon7/device/pwm4=89 hwmon7/device/pwm5=89 +MAXPWM=hwmon6/device/pwm1=255 hwmon6/device/pwm2=255 hwmon6/device/pwm3=255 hwmon6/device/pwm4=255 hwmon6/device/pwm5=255 hwmon7/device/pwm1=255 hwmon7/device/pwm2=255 hwmon7/device/pwm3=255 hwmon7/device/pwm4=255 hwmon7/device/pwm5=255 diff --git a/device/celestica/x86_64-cel_seastone-r0/installer.conf b/device/celestica/x86_64-cel_seastone-r0/installer.conf new file mode 100644 index 000000000000..924e0fb81963 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 diff --git a/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode0 b/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode0 new file mode 100755 index 000000000000..df26e4abd679 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode0 @@ -0,0 +1,13 @@ +02 20 28 67 72 12 30 80 D1 74 02 02 00 28 67 72 +12 20 80 D1 74 0D 02 30 28 67 72 02 31 28 67 72 +02 32 28 67 72 02 33 28 67 72 02 34 28 67 72 02 +35 28 67 72 02 36 28 67 72 02 37 28 67 72 02 38 +28 67 72 02 39 28 67 72 02 3A 28 67 72 02 3B 28 +67 72 02 3C 28 67 72 02 3D 28 67 72 02 3E 28 67 +72 02 3F 28 67 72 12 E0 85 05 D2 05 71 70 52 00 +3A 80 67 98 75 B0 77 78 67 9F 75 7E 77 8B 28 67 +A6 75 B6 16 E0 DA 04 74 B0 77 B6 28 67 A6 75 B3 +16 E0 DA 04 74 B0 77 B3 12 A0 F8 15 1A 00 57 12 +A0 F8 15 1A 01 57 28 32 00 32 01 B7 97 77 AF 57 +67 B9 57 67 C7 57 67 C0 57 32 0F 87 32 0F 87 57 +32 0F 87 32 0E 87 57 32 0E 87 32 0E 87 57 00 00 diff --git a/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode1 b/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode1 new file mode 100755 index 000000000000..df26e4abd679 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode1 @@ -0,0 +1,13 @@ +02 20 28 67 72 12 30 80 D1 74 02 02 00 28 67 72 +12 20 80 D1 74 0D 02 30 28 67 72 02 31 28 67 72 +02 32 28 67 72 02 33 28 67 72 02 34 28 67 72 02 +35 28 67 72 02 36 28 67 72 02 37 28 67 72 02 38 +28 67 72 02 39 28 67 72 02 3A 28 67 72 02 3B 28 +67 72 02 3C 28 67 72 02 3D 28 67 72 02 3E 28 67 +72 02 3F 28 67 72 12 E0 85 05 D2 05 71 70 52 00 +3A 80 67 98 75 B0 77 78 67 9F 75 7E 77 8B 28 67 +A6 75 B6 16 E0 DA 04 74 B0 77 B6 28 67 A6 75 B3 +16 E0 DA 04 74 B0 77 B3 12 A0 F8 15 1A 00 57 12 +A0 F8 15 1A 01 57 28 32 00 32 01 B7 97 77 AF 57 +67 B9 57 67 C7 57 67 C0 57 32 0F 87 32 0F 87 57 +32 0F 87 32 0E 87 57 32 0E 87 32 0E 87 57 00 00 diff --git a/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode2 b/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode2 new file mode 100755 index 000000000000..9e30d9d28fb6 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode2 @@ -0,0 +1,8 @@ +02 01 28 67 16 02 01 28 67 16 12 E0 85 05 D2 05 +71 14 52 00 3A 04 67 3C 75 54 77 1C 67 43 75 22 +77 2F 28 67 4A 75 57 16 E0 DA 04 74 54 77 57 28 +67 4A 75 57 16 E0 DA 04 74 54 77 57 12 A0 F8 15 +1A 00 57 12 A0 F8 15 1A 01 57 28 32 00 32 01 B7 +97 77 53 57 67 5D 57 67 6B 57 67 64 57 32 0F 87 +32 0F 87 57 32 0E 87 32 0F 87 57 32 0E 87 32 0E +87 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/device/celestica/x86_64-cel_seastone-r0/led_proc_init.soc b/device/celestica/x86_64-cel_seastone-r0/led_proc_init.soc new file mode 100755 index 000000000000..450533c0dc68 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/led_proc_init.soc @@ -0,0 +1,8 @@ +# Download LED code into LED processor and enable (if applicable). + +led 0 load /usr/share/sonic/platform/led-code/ledcode0; +led 0 auto on; led 0 start; +led 1 load /usr/share/sonic/platform/led-code/ledcode1; +led 1 auto on; led 1 start; +led 2 load /usr/share/sonic/platform/led-code/ledcode2; +led 2 auto on; led 2 start diff --git a/device/celestica/x86_64-cel_seastone-r0/plugins/eeprom.py b/device/celestica/x86_64-cel_seastone-r0/plugins/eeprom.py new file mode 100644 index 000000000000..29f01a07fc73 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica DX010 +# +# 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-12/12-0050/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) + diff --git a/device/celestica/x86_64-cel_seastone-r0/plugins/psuutil.py b/device/celestica/x86_64-cel_seastone-r0/plugins/psuutil.py new file mode 100644 index 000000000000..510c03a43ff1 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/plugins/psuutil.py @@ -0,0 +1,91 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + +import os + + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + # DX010 PSU pin mapping + self.psu = [ + {'base': self.get_gpio_base()}, + {'abs':27, 'power':22}, + {'abs':28, 'power':25} + ] + + def get_gpio_base(self): + sys_gpio_dir = "/sys/class/gpio" + for r in os.listdir(sys_gpio_dir): + if "gpiochip" in r: + return int(r[8:],10) + return 216 #Reserve + + + # Get a psu status and presence + def read_psu_statuses(self, pinnum): + sys_gpio_dir = "/sys/class/gpio" + gpio_base = self.psu[0]['base'] + + gpio_dir = sys_gpio_dir + '/gpio' + str(gpio_base+pinnum) + gpio_file = gpio_dir + "/value" + + try: + with open(gpio_file, 'r') as fd: + retval = fd.read() + except IOError: + raise IOError("Unable to open " + gpio_file + "file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + DX010_MAX_PSUS = 2 + return DX010_MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + psu_status = self.read_psu_statuses(self.psu[index]['power']) + psu_status = int(psu_status, 10) + # Check for PSU status + if (psu_status == 1): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_absence = self.read_psu_statuses(self.psu[index]['abs']) + psu_absence = (int(psu_absence, 10)) + # Check for PSU presence + if (psu_absence == 0): + status = 1 + + return status diff --git a/device/celestica/x86_64-cel_seastone-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_seastone-r0/plugins/sfputil.py new file mode 100644 index 000000000000..c361659b0f17 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/plugins/sfputil.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python +# +# 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 = 1 + PORT_END = 32 + PORTS_IN_BLOCK = 32 + + _port_to_eeprom_mapping = {} + + @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(self.PORT_START, 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): + if self.port_start == 1: + self.port_to_eeprom_mapping[x] = eeprom_path.format((x - 1) + 26) + else: + self.port_to_eeprom_mapping[x] = eeprom_path.format(x + 26) + 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/devices/platform/dx010_cpld/qsfp_modprs", "r") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + if self.port_start == 1: + bit_index = port_num - 1 + else: + bit_index = port_num + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # 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 + + try: + reg_file = open("/sys/devices/platform/dx010_cpld/qsfp_lpmode", "r") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + if self.port_start == 1: + bit_index = port_num - 1 + else: + bit_index = port_num + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # 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 + + try: + reg_file = open("/sys/devices/platform/dx010_cpld/qsfp_lpmode", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + if self.port_start == 1: + bit_index = port_num - 1 + else: + bit_index = port_num + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # 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).strip('L') + + 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 + + try: + reg_file = open("/sys/devices/platform/dx010_cpld/qsfp_reset", "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 the + # register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + if self.port_start == 1: + bit_index = port_num - 1 + else: + bit_index = port_num + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # 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).rstrip('L')) + 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: + reg_file = open("/sys/devices/platform/dx010_cpld/qsfp_reset", "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).rstrip('L')) + reg_file.close() + + return True + + def get_transceiver_change_event(self, timeout=0): + raise NotImplementedError diff --git a/device/celestica/x86_64-cel_seastone-r0/sensors.conf b/device/celestica/x86_64-cel_seastone-r0/sensors.conf new file mode 100644 index 000000000000..307587f687e5 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sensors.conf @@ -0,0 +1,78 @@ +# libsensors configuration file for Celestica DX010. +# The i2c bus portion is omit because adapter name +# changes every time when system boot up. + +chip "dps460-i2c-*-5a" + label temp1 "Power Supply 1 temp sensor 1" + label temp2 "Power Supply 1 temp sensor 2" + label temp3 "Power Supply 1 temp sensor 3" + ignore fan2 + ignore fan3 + ignore in2 + + set in1_max 240 + set in1_min 100 + set in1_crit 264 + set in1_lcrit 90 + set in3_max 12.6 + set in3_min 11.4 + set in3_crit 13.0 + set in3_lcrit 11.0 + +chip "dps460-i2c-*-5b" + label temp1 "Power Supply 2 temp sensor 1" + label temp2 "Power Supply 2 temp sensor 2" + label temp3 "Power Supply 2 temp sensor 3" + ignore fan2 + ignore fan3 + ignore in2 + + set in1_max 240 + set in1_min 100 + set in1_crit 264 + set in1_lcrit 90 + set in3_max 12.6 + set in3_min 11.4 + set in3_crit 13.0 + set in3_lcrit 11.0 + +# These sensors located on Main Switch Board. +chip "lm75b-i2c-*-48" + label temp1 "Front-panel temp sensor 1" + set temp1_max 43 + set temp1_max_hyst 28 + +chip "lm75b-i2c-*-49" + label temp1 "Front-panel temp sensor 2" + set temp1_max 43 + set temp1_max_hyst 28 + +chip "lm75b-i2c-*-4a" + label temp1 "ASIC temp sensor" + set temp1_max 43 + set temp1_max_hyst 28 + +# These sensors located on CPU Board. +chip "lm75b-i2c-*-48" + label temp1 "Rear-panel temp sensor 1" + set temp1_max 43 + set temp1_max_hyst 28 + +chip "lm75b-i2c-*-4e" + label temp1 "Rear-panel temp sensor 2" + set temp1_max 43 + set temp1_max_hyst 28 + +chip "emc2305-i2c-*-2e" + label fan2 "fan1" + label fan1 "fan2" + label fan4 "fan3" + label fan5 "fan4" + label fan3 "fan5" + +chip "emc2305-i2c-*-4d" + label fan2 "fan1" + label fan4 "fan2" + label fan5 "fan3" + label fan3 "fan4" + label fan1 "fan5" diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/buffers.json.j2 b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/buffers.json.j2 new file mode 100644 index 000000000000..08e21e428b6c --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/buffers.json.j2 @@ -0,0 +1,70 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# 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' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- 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 -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- 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 -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(1,default_ports_num+1) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + } +} + diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/pg_profile_lookup.ini b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/pg_profile_lookup.ini new file mode 100644 index 000000000000..a65244e69b5b --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/pg_profile_lookup.ini @@ -0,0 +1,21 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 1000 5m 34816 18432 16384 0 + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 1000 40m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 1000 300m 49152 18432 30720 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 + diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/port_config.ini b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/port_config.ini new file mode 100644 index 000000000000..78a1df9f051d --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias speed +Ethernet1 75 eth-0-1 1000 +Ethernet2 73 eth-0-2 1000 +Ethernet3 72 eth-0-3 1000 +Ethernet4 70 eth-0-4 1000 +Ethernet5 69 eth-0-5 1000 +Ethernet6 67 eth-0-6 1000 +Ethernet7 66 eth-0-7 1000 +Ethernet8 64 eth-0-8 1000 +Ethernet9 63 eth-0-9 1000 +Ethernet10 61 eth-0-10 1000 +Ethernet11 60 eth-0-11 1000 +Ethernet12 58 eth-0-12 1000 +Ethernet13 57 eth-0-13 10000 +Ethernet14 56 eth-0-14 10000 +Ethernet15 55 eth-0-15 10000 +Ethernet16 53 eth-0-16 10000 +Ethernet17 52 eth-0-17 10000 +Ethernet18 50 eth-0-18 10000 +Ethernet19 49 eth-0-19 10000 +Ethernet20 48 eth-0-20 10000 +Ethernet21 0 eth-0-21 10000 +Ethernet22 1 eth-0-22 10000 +Ethernet23 3 eth-0-23 10000 +Ethernet24 2 eth-0-24 10000 +Ethernet25 4 eth-0-25 10000 +Ethernet26 5 eth-0-26 10000 +Ethernet27 6 eth-0-27 10000 +Ethernet28 7 eth-0-28 10000 +Ethernet29 8 eth-0-29 10000 +Ethernet30 9 eth-0-30 10000 +Ethernet31 10 eth-0-31 10000 +Ethernet32 12 eth-0-32 10000 +Ethernet33 13 eth-0-33 10000 +Ethernet34 15 eth-0-34 10000 +Ethernet35 16 eth-0-35 10000 +Ethernet36 18 eth-0-36 10000 +Ethernet37 19 eth-0-37 10000 +Ethernet38 21 eth-0-38 10000 +Ethernet39 22 eth-0-39 10000 +Ethernet40 24 eth-0-40 10000 +Ethernet41 25 eth-0-41 10000 +Ethernet42 27 eth-0-42 10000 +Ethernet43 28 eth-0-43 10000 +Ethernet44 30 eth-0-44 10000 +Ethernet45 31 eth-0-45 10000 +Ethernet46 33 eth-0-46 10000 +Ethernet47 34 eth-0-47 10000 +Ethernet48 36 eth-0-48 10000 +Ethernet49 42,41,43,40 eth-0-49 40000 +Ethernet50 45,46,44,47 eth-0-50 40000 +Ethernet51 94,93,95,92 eth-0-51 100000 +Ethernet52 89,90,88,91 eth-0-52 100000 +Ethernet53 85,86,84,87 eth-0-53 100000 +Ethernet54 81,82,80,83 eth-0-54 100000 diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/qos.json.j2 b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/sai.profile b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/sai.profile new file mode 100644 index 000000000000..6139a61cf0cd --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/etc/centec/E582-48x2q4z-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E582-48x2q4z-datapath-cfg.txt diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/default_sku b/device/centec/x86_64-centec_e582_48x2q4z-r0/default_sku new file mode 100644 index 000000000000..89c83dc3d0e3 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/default_sku @@ -0,0 +1 @@ +E582-48x2q4z t1 diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/fancontrol b/device/centec/x86_64-centec_e582_48x2q4z-r0/fancontrol new file mode 100644 index 000000000000..5bcd0383896b --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/fancontrol @@ -0,0 +1,10 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/platform/coretemp.0 hwmon5=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-15/15-002f +DEVNAME=hwmon1=coretemp hwmon5=adt7470 +FCTEMPS=hwmon5/pwm4=hwmon1/temp1_input hwmon5/pwm3=hwmon1/temp1_input hwmon5/pwm2=hwmon1/temp1_input hwmon5/pwm1=hwmon1/temp1_input +FCFANS=hwmon5/pwm4=hwmon5/fan4_input hwmon5/pwm3=hwmon5/fan3_input hwmon5/pwm2=hwmon5/fan2_input hwmon5/pwm1=hwmon5/fan1_input +MINTEMP=hwmon5/pwm4=20 hwmon5/pwm3=20 hwmon5/pwm2=20 hwmon5/pwm1=20 +MAXTEMP=hwmon5/pwm4=60 hwmon5/pwm3=60 hwmon5/pwm2=60 hwmon5/pwm1=60 +MINSTART=hwmon5/pwm4=150 hwmon5/pwm3=150 hwmon5/pwm2=150 hwmon5/pwm1=150 +MINSTOP=hwmon5/pwm4=0 hwmon5/pwm3=0 hwmon5/pwm2=0 hwmon5/pwm1=100 diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/installer.conf b/device/centec/x86_64-centec_e582_48x2q4z-r0/installer.conf new file mode 100644 index 000000000000..7d60bf73d366 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=no" diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/eeprom.py b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/eeprom.py new file mode 100644 index 000000000000..3fd55c63d8b7 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/eeprom.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +############################################################################# +# Centec E582-48X6Q +# +# 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: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + import subprocess + from sonic_eeprom import eeprom_base + 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-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/led_control.py b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/led_control.py new file mode 100644 index 000000000000..4459096cb011 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/led_control.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python +# +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + from sonic_led.led_control_base import LedControlBase + import swsssdk + import threading + import os + import logging + import struct + import time + import syslog + from socket import * + from select import * +except ImportError, e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("centec-led") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + +class LedControl(LedControlBase): + """Platform specific LED control class""" + SONIC_PORT_NAME_PREFIX = "Ethernet" + LED_MODE_UP = [11, 1] + LED_MODE_DOWN = [7, 2] + + def _initSystemLed(self): + try: + with open(self.f_led.format("system"), 'w') as led_file: + led_file.write("5") + DBG_PRINT("init system led to normal") + with open(self.f_led.format("idn"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init idn led to off") + except IOError as e: + DBG_PRINT(str(e)) + + def _initPanelLed(self): + with open(self.f_led.format("port1"), 'r') as led_file: + shouldInit = (int(led_file.read()) == 0) + + if shouldInit == True: + for (port, ctlid, defmode) in self.led_mapping[1:59]: + data = struct.pack('=HHHBBH', 0, 7, 4, ctlid, defmode, port) + self.udpClient.sendto(data, ('localhost', 8101)) + + data = struct.pack('=HHHBB30B', 0, 3, 32, 30, 0, *[x[0] for x in self.led_mapping[21:51]]) + self.udpClient.sendto(data, ('localhost', 8101)) + data = struct.pack('=HHHBB28B', 0, 3, 30, 28, 1, *[x[0] for x in (self.led_mapping[1:21]+self.led_mapping[51:59])]) + self.udpClient.sendto(data, ('localhost', 8101)) + + data = struct.pack('=HHHB', 0, 5, 1, 1) + self.udpClient.sendto(data, ('localhost', 8101)) + + for idx in range(1, 55): + (port, ctlid, defmode) = self.led_mapping[idx] + with open(self.f_led.format("port{}".format(idx)), 'w') as led_file: + led_file.write(str(defmode)) + DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + + for idx in range(1, 55): + (port, ctlid, defmode) = self.led_mapping[idx] + with open(self.f_led.format("port{}".format(idx)), 'r') as led_file: + defmode = int(led_file.read()) + data = struct.pack('=HHHBBH', 0, 7, 4, ctlid, defmode, port) + self.udpClient.sendto(data, ('localhost', 8101)) + DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + + def _initDefaultConfig(self): + DBG_PRINT("start init led") + while True: + try: + r_sel = [self.udpClient] + echo_req = struct.pack('=HHH', 0, 1, 0) + self.udpClient.sendto(echo_req, ('localhost', 8101)) + result = select(r_sel, [], [], 1) + if self.udpClient in result[0]: + echo_rsp, srv_addr = self.udpClient.recvfrom(1024) + if echo_rsp: + break + DBG_PRINT("connect to sdk rpc server timeout, try again.") + except IOError as e: + DBG_PRINT(str(e)) + + DBG_PRINT("connect to sdk rpc server success.") + + self._initSystemLed() + self._initPanelLed() + + DBG_PRINT("init led done") + + + # Helper method to map SONiC port name to index + def _port_name_to_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + return port_idx + + def _port_state_to_mode(self, port_idx, state): + if state == "up": + return self.LED_MODE_UP[0] if (port_idx < 49) else self.LED_MODE_UP[1] + else: + return self.LED_MODE_DOWN[0] if (port_idx < 49) else self.LED_MODE_DOWN[1] + + def _port_led_mode_update(self, port_idx, ledMode): + with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: + led_file.write(str(ledMode)) + (port, ctlid) = (self.led_mapping[port_idx][0], self.led_mapping[port_idx][1]) + data = struct.pack('=HHHBBH', 0, 7, 4, ctlid, ledMode, port) + self.udpClient.sendto(data, ('localhost', 8101)) + + # Concrete implementation of port_link_state_change() method + def port_link_state_change(self, portname, state): + port_idx = self._port_name_to_index(portname) + ledMode = self._port_state_to_mode(port_idx, state) + with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: + saveMode = int(led_file.read()) + + if ledMode == saveMode: + return + + self._port_led_mode_update(port_idx, ledMode) + DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) + + # Constructor + def __init__(self): + # [macid, ctlid, defaultmode] + self.led_mapping = [(0, 0, 0)] # resv + self.led_mapping.extend([(27, 1, 7), (25, 1, 7), (24, 1, 7), (22, 1, 7), (21, 1, 7), (19, 1, 7), (18, 1, 7), (16, 1, 7)]) # panel port 1~8 + self.led_mapping.extend([(15, 1, 7), (13, 1, 7), (12, 1, 7), (10, 1, 7), (9, 1, 7), (8, 1, 7), (7, 1, 7), (5, 1, 7)]) # panel port 9~16 + self.led_mapping.extend([(4, 1, 7), (2, 1, 7), (1, 1, 7), (0, 1, 7), (0, 0, 7), (1, 0, 7), (3, 0, 7), (2, 0, 7)]) # panel port 17~24 + self.led_mapping.extend([(4, 0, 7), (5, 0, 7), (6, 0, 7), (7, 0, 7), (8, 0, 7), (9, 0, 7), (10, 0, 7), (12, 0, 7)]) # panel port 25~32 + self.led_mapping.extend([(13, 0, 7), (15, 0, 7), (16, 0, 7), (18, 0, 7), (19, 0, 7), (21, 0, 7), (22, 0, 7), (24, 0, 7)]) # panel port 33~40 + self.led_mapping.extend([(25, 0, 7), (27, 0, 7), (28, 0, 7), (30, 0, 7), (31, 0, 7), (33, 0, 7), (34, 0, 7), (48, 0, 7)]) # panel port 41~48 + self.led_mapping.extend([(36, 0, 2), (52, 0, 2), (52, 1, 2), (36, 1, 2), (48, 1, 2), (32, 1, 2)]) # panel port 49~54 + self.led_mapping.extend([(11, 1, 2), (11, 1, 2), (11, 1, 2), (11, 1, 2), (11, 1, 2), (11, 1, 2)]) + + self.f_led = "/sys/class/leds/{}/brightness" + + self.udpClient = socket(AF_INET, SOCK_DGRAM) + + self._initDefaultConfig() + diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/psuutil.py b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/psuutil.py new file mode 100644 index 000000000000..6505318ed948 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/psuutil.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/class/psu/psu{}/" + self.psu_presence = "psu_presence" + self.psu_oper_status = "psu_status" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_oper_status, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 0 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 0 diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/sfputil.py b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/sfputil.py new file mode 100644 index 000000000000..4d4b3f3e5558 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/sfputil.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python + +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + import logging + import struct + import syslog + from socket import * + from select import * + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + + +def DBG_PRINT(str): + print str + "\n" + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + SONIC_PORT_NAME_PREFIX = "Ethernet" + PORT_START = 1 + PORT_END = 54 + PORTS_IN_BLOCK = 54 + + @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(49, self.PORTS_IN_BLOCK + 1) + + @property + def port_to_eeprom_mapping(self): + return self.eeprom_mapping + + def is_logical_port(self, port_name): + return True + + def get_logical_to_physical(self, port_name): + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return None + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + + return [port_idx] + + def get_eeprom_data(self, port): + (ctlid, devid) = self.fiber_mapping[port] + offset = (128 if port in self.qsfp_ports else 0) + r_sel = [self.udpClient] + req = struct.pack('=HHHBBHIBBBBI', + 0, 9, 16, # lchip/msgtype/msglen + ctlid, # uint8 ctl_id + devid, # uint8 slave_dev_id + 0x50, # uint16 dev_addr + (1< self.port_end: + return False + try: + with open(self.f_sfp_present.format(port_num), 'r') as sfp_file: + return 1 == int(sfp_file.read()) + except IOError as e: + DBG_PRINT(str(e)) + + 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 + + return False + + 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 + + return False + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def get_transceiver_change_event(self, timeout=0): + return False, {} diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/buffers.json.j2 b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/buffers.json.j2 new file mode 100644 index 000000000000..08e21e428b6c --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/buffers.json.j2 @@ -0,0 +1,70 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# 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' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- 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 -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- 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 -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(1,default_ports_num+1) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + } +} + diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/pg_profile_lookup.ini b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/pg_profile_lookup.ini new file mode 100644 index 000000000000..a65244e69b5b --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/pg_profile_lookup.ini @@ -0,0 +1,21 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 1000 5m 34816 18432 16384 0 + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 1000 40m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 1000 300m 49152 18432 30720 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 + diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/port_config.ini b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/port_config.ini new file mode 100644 index 000000000000..efb24937cec1 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias speed +Ethernet1 4 eth-0-1 1000 +Ethernet2 5 eth-0-2 1000 +Ethernet3 6 eth-0-3 1000 +Ethernet4 8 eth-0-4 1000 +Ethernet5 9 eth-0-5 1000 +Ethernet6 10 eth-0-6 1000 +Ethernet7 12 eth-0-7 1000 +Ethernet8 13 eth-0-8 1000 +Ethernet9 14 eth-0-9 1000 +Ethernet10 16 eth-0-10 1000 +Ethernet11 17 eth-0-11 1000 +Ethernet12 18 eth-0-12 1000 +Ethernet13 20 eth-0-13 10000 +Ethernet14 21 eth-0-14 10000 +Ethernet15 22 eth-0-15 10000 +Ethernet16 24 eth-0-16 10000 +Ethernet17 25 eth-0-17 10000 +Ethernet18 26 eth-0-18 10000 +Ethernet19 28 eth-0-19 10000 +Ethernet20 30 eth-0-20 10000 +Ethernet21 31 eth-0-21 10000 +Ethernet22 32 eth-0-22 10000 +Ethernet23 34 eth-0-23 10000 +Ethernet24 35 eth-0-24 10000 +Ethernet25 36 eth-0-25 10000 +Ethernet26 37 eth-0-26 10000 +Ethernet27 39 eth-0-27 10000 +Ethernet28 40 eth-0-28 10000 +Ethernet29 41 eth-0-29 10000 +Ethernet30 43 eth-0-30 10000 +Ethernet31 47 eth-0-31 10000 +Ethernet32 46 eth-0-32 10000 +Ethernet33 45 eth-0-33 10000 +Ethernet34 44 eth-0-34 10000 +Ethernet35 92 eth-0-35 10000 +Ethernet36 93 eth-0-36 10000 +Ethernet37 94 eth-0-37 10000 +Ethernet38 95 eth-0-38 10000 +Ethernet39 90 eth-0-39 10000 +Ethernet40 89 eth-0-40 10000 +Ethernet41 88 eth-0-41 10000 +Ethernet42 87 eth-0-42 10000 +Ethernet43 86 eth-0-43 10000 +Ethernet44 85 eth-0-44 10000 +Ethernet45 84 eth-0-45 10000 +Ethernet46 82 eth-0-46 10000 +Ethernet47 81 eth-0-47 10000 +Ethernet48 80 eth-0-48 10000 +Ethernet49 77,78,76,79 eth-0-49 40000 +Ethernet50 73,74,72,75 eth-0-50 40000 +Ethernet51 70,71,69,68 eth-0-51 40000 +Ethernet52 61,63,60,62 eth-0-52 40000 +Ethernet53 59,57,58,56 eth-0-53 40000 +Ethernet54 53,55,54,52 eth-0-54 40000 diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/qos.json.j2 b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/sai.profile b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/sai.profile new file mode 100644 index 000000000000..c03fcf630c5a --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/etc/centec/E582-48x6q-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E582-48x6q-datapath-cfg.txt diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/default_sku b/device/centec/x86_64-centec_e582_48x6q-r0/default_sku new file mode 100644 index 000000000000..e0f7b24535b6 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/default_sku @@ -0,0 +1 @@ +E582-48x6q t1 diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/fancontrol b/device/centec/x86_64-centec_e582_48x6q-r0/fancontrol new file mode 100644 index 000000000000..5bcd0383896b --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/fancontrol @@ -0,0 +1,10 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/platform/coretemp.0 hwmon5=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-15/15-002f +DEVNAME=hwmon1=coretemp hwmon5=adt7470 +FCTEMPS=hwmon5/pwm4=hwmon1/temp1_input hwmon5/pwm3=hwmon1/temp1_input hwmon5/pwm2=hwmon1/temp1_input hwmon5/pwm1=hwmon1/temp1_input +FCFANS=hwmon5/pwm4=hwmon5/fan4_input hwmon5/pwm3=hwmon5/fan3_input hwmon5/pwm2=hwmon5/fan2_input hwmon5/pwm1=hwmon5/fan1_input +MINTEMP=hwmon5/pwm4=20 hwmon5/pwm3=20 hwmon5/pwm2=20 hwmon5/pwm1=20 +MAXTEMP=hwmon5/pwm4=60 hwmon5/pwm3=60 hwmon5/pwm2=60 hwmon5/pwm1=60 +MINSTART=hwmon5/pwm4=150 hwmon5/pwm3=150 hwmon5/pwm2=150 hwmon5/pwm1=150 +MINSTOP=hwmon5/pwm4=0 hwmon5/pwm3=0 hwmon5/pwm2=0 hwmon5/pwm1=100 diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/installer.conf b/device/centec/x86_64-centec_e582_48x6q-r0/installer.conf new file mode 100644 index 000000000000..7d60bf73d366 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=no" diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/plugins/eeprom.py b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/eeprom.py new file mode 100644 index 000000000000..3fd55c63d8b7 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/eeprom.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +############################################################################# +# Centec E582-48X6Q +# +# 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: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + import subprocess + from sonic_eeprom import eeprom_base + 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-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/plugins/led_control.py b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/led_control.py new file mode 100644 index 000000000000..d25bf6f8b473 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/led_control.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python +# +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + from sonic_led.led_control_base import LedControlBase + import swsssdk + import threading + import os + import logging + import struct + import time + import syslog + from socket import * + from select import * +except ImportError, e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("centec-led") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + +class LedControl(LedControlBase): + """Platform specific LED control class""" + SONIC_PORT_NAME_PREFIX = "Ethernet" + LED_MODE_UP = [11, 1] + LED_MODE_DOWN = [7, 2] + + def _initSystemLed(self): + try: + with open(self.f_led.format("system"), 'w') as led_file: + led_file.write("5") + DBG_PRINT("init system led to normal") + with open(self.f_led.format("idn"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init idn led to off") + except IOError as e: + DBG_PRINT(str(e)) + + def _initPanelLed(self): + with open(self.f_led.format("port1"), 'r') as led_file: + shouldInit = (int(led_file.read()) == 0) + + if shouldInit == True: + for (port, ctlid, defmode) in self.led_mapping[1:59]: + data = struct.pack('=HHHBBH', 0, 7, 4, ctlid, defmode, port) + self.udpClient.sendto(data, ('localhost', 8101)) + + data = struct.pack('=HHHBB34B', 0, 3, 36, 34, 0, *[x[0] for x in self.led_mapping[1:35]]) + self.udpClient.sendto(data, ('localhost', 8101)) + data = struct.pack('=HHHBB24B', 0, 3, 26, 24, 1, *[x[0] for x in self.led_mapping[35:59]]) + self.udpClient.sendto(data, ('localhost', 8101)) + + data = struct.pack('=HHHB', 0, 5, 1, 1) + self.udpClient.sendto(data, ('localhost', 8101)) + + for idx in range(1, 55): + (port, ctlid, defmode) = self.led_mapping[idx] + with open(self.f_led.format("port{}".format(idx)), 'w') as led_file: + led_file.write(str(defmode)) + DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + + for idx in range(1, 55): + (port, ctlid, defmode) = self.led_mapping[idx] + with open(self.f_led.format("port{}".format(idx)), 'r') as led_file: + defmode = int(led_file.read()) + data = struct.pack('=HHHBBH', 0, 7, 4, ctlid, defmode, port) + self.udpClient.sendto(data, ('localhost', 8101)) + DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + + def _initDefaultConfig(self): + DBG_PRINT("start init led") + while True: + try: + r_sel = [self.udpClient] + echo_req = struct.pack('=HHH', 0, 1, 0) + self.udpClient.sendto(echo_req, ('localhost', 8101)) + result = select(r_sel, [], [], 1) + if self.udpClient in result[0]: + echo_rsp, srv_addr = self.udpClient.recvfrom(1024) + if echo_rsp: + break + DBG_PRINT("connect to sdk rpc server timeout, try again.") + except IOError as e: + DBG_PRINT(str(e)) + + DBG_PRINT("connect to sdk rpc server success.") + + self._initSystemLed() + self._initPanelLed() + + DBG_PRINT("init led done") + + + # Helper method to map SONiC port name to index + def _port_name_to_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + return port_idx + + def _port_state_to_mode(self, port_idx, state): + if state == "up": + return self.LED_MODE_UP[0] if (port_idx < 49) else self.LED_MODE_UP[1] + else: + return self.LED_MODE_DOWN[0] if (port_idx < 49) else self.LED_MODE_DOWN[1] + + def _port_led_mode_update(self, port_idx, ledMode): + with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: + led_file.write(str(ledMode)) + (port, ctlid) = (self.led_mapping[port_idx][0], self.led_mapping[port_idx][1]) + data = struct.pack('=HHHBBH', 0, 7, 4, ctlid, ledMode, port) + self.udpClient.sendto(data, ('localhost', 8101)) + + # Concrete implementation of port_link_state_change() method + def port_link_state_change(self, portname, state): + port_idx = self._port_name_to_index(portname) + ledMode = self._port_state_to_mode(port_idx, state) + with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: + saveMode = int(led_file.read()) + + if ledMode == saveMode: + return + + self._port_led_mode_update(port_idx, ledMode) + DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) + + # Constructor + def __init__(self): + # [macid, ctlid, defaultmode] + self.led_mapping = [(0, 0, 0)] # resv + self.led_mapping.extend([(4, 0, 7), (5, 0, 7), (6, 0, 7), (8, 0, 7), (9, 0, 7), (10, 0, 7), (12, 0, 7), (13, 0, 7)]) # panel port 1~8 + self.led_mapping.extend([(14, 0, 7), (16, 0, 7), (17, 0, 7), (18, 0, 7), (20, 0, 7), (21, 0, 7), (22, 0, 7), (24, 0, 7)]) # panel port 9~16 + self.led_mapping.extend([(25, 0, 7), (26, 0, 7), (28, 0, 7), (30, 0, 7), (31, 0, 7), (32, 0, 7), (34, 0, 7), (35, 0, 7)]) # panel port 17~24 + self.led_mapping.extend([(48, 0, 7), (49, 0, 7), (51, 0, 7), (36, 0, 7), (37, 0, 7), (39, 0, 7), (55, 0, 7), (54, 0, 7)]) # panel port 25~32 + self.led_mapping.extend([(53, 0, 7), (52, 0, 7), (52, 1, 7), (53, 1, 7), (54, 1, 7), (55, 1, 7), (38, 1, 7), (37, 1, 7)]) # panel port 33~40 + self.led_mapping.extend([(36, 1, 7), (51, 1, 7), (50, 1, 7), (49, 1, 7), (48, 1, 7), (34, 1, 7), (33, 1, 7), (32, 1, 7)]) # panel port 41~48 + self.led_mapping.extend([(28, 1, 2), (24, 1, 2), (20, 1, 2), (12, 1, 2), (8, 1, 2), (4, 1, 2)]) # panel port 49~54 + self.led_mapping.extend([(0, 1, 2), (0, 1, 2), (0, 1, 2), (0, 1, 2), (0, 1, 2), (0, 1, 2)]) + + self.f_led = "/sys/class/leds/{}/brightness" + + self.udpClient = socket(AF_INET, SOCK_DGRAM) + + self._initDefaultConfig() + diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/plugins/psuutil.py b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/psuutil.py new file mode 100644 index 000000000000..6505318ed948 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/psuutil.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/class/psu/psu{}/" + self.psu_presence = "psu_presence" + self.psu_oper_status = "psu_status" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_oper_status, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 0 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 0 diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/plugins/sfputil.py b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/sfputil.py new file mode 100644 index 000000000000..8d1281492d6c --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/sfputil.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python + +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + import logging + import struct + import syslog + from socket import * + from select import * + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + + +def DBG_PRINT(str): + print str + "\n" + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + SONIC_PORT_NAME_PREFIX = "Ethernet" + PORT_START = 1 + PORT_END = 54 + PORTS_IN_BLOCK = 54 + + @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(49, self.PORTS_IN_BLOCK + 1) + + @property + def port_to_eeprom_mapping(self): + return self.eeprom_mapping + + def is_logical_port(self, port_name): + return True + + def get_logical_to_physical(self, port_name): + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return None + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + + return [port_idx] + + def get_eeprom_data(self, port): + (ctlid, devid) = self.fiber_mapping[port] + offset = (128 if port in self.qsfp_ports else 0) + r_sel = [self.udpClient] + req = struct.pack('=HHHBBHIBBBBI', + 0, 9, 16, # lchip/msgtype/msglen + ctlid, # uint8 ctl_id + devid, # uint8 slave_dev_id + 0x50, # uint16 dev_addr + (1< self.port_end: + return False + try: + with open(self.f_sfp_present.format(port_num), 'r') as sfp_file: + return 1 == int(sfp_file.read()) + except IOError as e: + DBG_PRINT(str(e)) + + 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 + + return False + + 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 + + return False + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def get_transceiver_change_event(self, timeout=0): + return False, {} diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/port_config.ini b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/port_config.ini new file mode 100644 index 000000000000..b9a831f22e8d --- /dev/null +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/port_config.ini @@ -0,0 +1,33 @@ +# name lanes +Ethernet0 1 +Ethernet4 2 +Ethernet8 3 +Ethernet12 4 +Ethernet16 5 +Ethernet20 6 +Ethernet24 7 +Ethernet28 8 +Ethernet32 9 +Ethernet36 10 +Ethernet40 11 +Ethernet44 12 +Ethernet48 13 +Ethernet52 14 +Ethernet56 15 +Ethernet60 16 +Ethernet64 17 +Ethernet68 18 +Ethernet72 19 +Ethernet76 20 +Ethernet80 21 +Ethernet84 22 +Ethernet88 23 +Ethernet92 24 +Ethernet96 25 +Ethernet100 26 +Ethernet104 27 +Ethernet108 28 +Ethernet112 29 +Ethernet116 30 +Ethernet120 31 +Ethernet124 32 diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/sai.profile b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/sai.profile new file mode 100644 index 000000000000..6a5af192a2b7 --- /dev/null +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/sai.profile @@ -0,0 +1 @@ +BOARD_CONFIG_FILE_PATH=/etc/centec/ES6428A-X48Q2H4.json diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/default_sku b/device/centec/x86_64-ew_es6220_x48q2h4-r0/default_sku new file mode 100644 index 000000000000..d10e1b46328c --- /dev/null +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/default_sku @@ -0,0 +1 @@ +ES6428A-X48Q2H4 t1 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q32 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q32 new file mode 120000 index 000000000000..175db8c15394 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q32 @@ -0,0 +1 @@ +Force10-S6000 \ No newline at end of file diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers.json.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers.json.j2 new file mode 100644 index 000000000000..b67cf577ab75 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers_defaults_t1.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..40d32ef316da --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers_defaults_t1.j2 @@ -0,0 +1,45 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7582515", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/pg_profile_lookup.ini b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/pg_profile_lookup.ini new file mode 100644 index 000000000000..135a598465ba --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/pg_profile_lookup.ini @@ -0,0 +1,11 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 40000 5m 41808 18432 40560 -3 2496 + 50000 5m 41808 18432 40560 -3 2496 + 100000 5m 41808 18432 40560 -3 2496 + 40000 40m 51376 18432 50128 -3 2496 + 50000 40m 51376 18432 50128 -3 2496 + 100000 40m 51376 18432 50128 -3 2496 + 40000 300m 51376 18432 50128 -3 2496 + 50000 300m 51376 18432 50128 -3 2496 + 100000 300m 51376 18432 50128 -3 2496 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/port_config.ini b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/port_config.ini new file mode 100644 index 000000000000..433700a5f37f --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias speed +Ethernet0 25,26,27,28 fortyGigE0/0 40000 +Ethernet4 29,30,31,32 fortyGigE0/4 40000 +Ethernet8 33,34,35,36 fortyGigE0/8 40000 +Ethernet12 37,38,39,40 fortyGigE0/12 40000 +Ethernet16 45,46,47,48 fortyGigE0/16 40000 +Ethernet20 41,42,43,44 fortyGigE0/20 40000 +Ethernet24 1,2,3,4 fortyGigE0/24 40000 +Ethernet28 5,6,7,8 fortyGigE0/28 40000 +Ethernet32 13,14,15,16 fortyGigE0/32 40000 +Ethernet36 9,10,11,12 fortyGigE0/36 40000 +Ethernet40 17,18,19,20 fortyGigE0/40 40000 +Ethernet44 21,22,23,24 fortyGigE0/44 40000 +Ethernet48 53,54,55,56 fortyGigE0/48 40000 +Ethernet52 49,50,51,52 fortyGigE0/52 40000 +Ethernet56 57,58,59,60 fortyGigE0/56 40000 +Ethernet60 61,62,63,64 fortyGigE0/60 40000 +Ethernet64 69,70,71,72 fortyGigE0/64 40000 +Ethernet68 65,66,67,68 fortyGigE0/68 40000 +Ethernet72 73,74,75,76 fortyGigE0/72 40000 +Ethernet76 77,78,79,80 fortyGigE0/76 40000 +Ethernet80 109,110,111,112 fortyGigE0/80 40000 +Ethernet84 105,106,107,108 fortyGigE0/84 40000 +Ethernet88 113,114,115,116 fortyGigE0/88 40000 +Ethernet92 117,118,119,120 fortyGigE0/92 40000 +Ethernet96 125,126,127,128 fortyGigE0/96 40000 +Ethernet100 121,122,123,124 fortyGigE0/100 40000 +Ethernet104 81,82,83,84 fortyGigE0/104 40000 +Ethernet108 85,86,87,88 fortyGigE0/108 40000 +Ethernet112 93,94,95,96 fortyGigE0/112 40000 +Ethernet116 89,90,91,92 fortyGigE0/116 40000 +Ethernet120 101,102,103,104 fortyGigE0/120 40000 +Ethernet124 97,98,99,100 fortyGigE0/124 40000 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/qos.json.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/sai.profile b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/sai.profile new file mode 100644 index 000000000000..52e2e289af60 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-s6000-32x40G.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/td2-s6000-32x40G.config.bcm b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/td2-s6000-32x40G.config.bcm new file mode 100644 index 000000000000..4c94db7107c7 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/td2-s6000-32x40G.config.bcm @@ -0,0 +1,646 @@ +# Old LPM only configuration +# l2_mem_entries=163840 +# l3_mem_entries=90112 +# l3_alpm_enable=0 +# ipv6_lpm_128b_enable=0 +# +# ALPM enable +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l2_mem_entries=32768 +l3_mem_entries=16384 + +# From old config file +os=unix +higig2_hdr_mode=1 + +# Parity +parity_correction=1 +parity_enable=1 +stat_if_parity_enable=0 + +# +bcm_num_cos=8 +bcm_stat_interval=2000000 +l2xmsg_hostbuf_size=8192 +l2xmsg_mode=1 +lls_num_l2uc=12 +max_vp_lags=0 +miim_intr_enable=0 +mmu_lossless=0 +module_64ports=0 +schan_intr_enable=0 +stable_size=0x2000000 +tdma_timeout_usec=5000000 + +pbmp_oversubscribe=0x000007fffffffffffffffffffffffffe +pbmp_xport_xe=0x000007fffffffffffffffffffffffffe + +# Ports configuration +# xe0 (40G) +portmap_1=25:40 +xgxs_rx_lane_map_1=0x213 +xgxs_tx_lane_map_1=0x2031 +phy_xaui_rx_polarity_flip_1=0xe +phy_xaui_tx_polarity_flip_1=0x2 +serdes_driver_current_lane0_xe0=0x5 +serdes_driver_current_lane1_xe0=0x5 +serdes_driver_current_lane2_xe0=0x5 +serdes_driver_current_lane3_xe0=0x5 +serdes_pre_driver_current_lane0_xe0=0x5 +serdes_pre_driver_current_lane1_xe0=0x5 +serdes_pre_driver_current_lane2_xe0=0x5 +serdes_pre_driver_current_lane3_xe0=0x5 +serdes_preemphasis_lane0_xe0=0xcad0 +serdes_preemphasis_lane1_xe0=0xc6e0 +serdes_preemphasis_lane2_xe0=0xc6e0 +serdes_preemphasis_lane3_xe0=0xd2b0 + +# xe1 (40G) +portmap_2=29:40 +xgxs_rx_lane_map_2=0x213 +xgxs_tx_lane_map_2=0x213 +phy_xaui_rx_polarity_flip_2=0xc +phy_xaui_tx_polarity_flip_2=0x9 +serdes_driver_current_lane0_xe1=0x6 +serdes_driver_current_lane1_xe1=0x7 +serdes_driver_current_lane2_xe1=0x6 +serdes_driver_current_lane3_xe1=0x6 +serdes_pre_driver_current_lane0_xe1=0x6 +serdes_pre_driver_current_lane1_xe1=0x7 +serdes_pre_driver_current_lane2_xe1=0x6 +serdes_pre_driver_current_lane3_xe1=0x6 +serdes_preemphasis_lane0_xe1=0xc2f0 +serdes_preemphasis_lane1_xe1=0xd2b0 +serdes_preemphasis_lane2_xe1=0xc6e0 +serdes_preemphasis_lane3_xe1=0xc2f0 + +# xe2 (40G) +portmap_3=33:40 +xgxs_rx_lane_map_3=0x213 +xgxs_tx_lane_map_3=0x132 +phy_xaui_rx_polarity_flip_3=0xe +phy_xaui_tx_polarity_flip_3=0x2 +serdes_driver_current_lane0_xe2=0x4 +serdes_driver_current_lane1_xe2=0x4 +serdes_driver_current_lane2_xe2=0x4 +serdes_driver_current_lane3_xe2=0x4 +serdes_pre_driver_current_lane0_xe2=0x4 +serdes_pre_driver_current_lane1_xe2=0x4 +serdes_pre_driver_current_lane2_xe2=0x4 +serdes_pre_driver_current_lane3_xe2=0x4 +serdes_preemphasis_lane0_xe2=0xc6e0 +serdes_preemphasis_lane1_xe2=0xc6e0 +serdes_preemphasis_lane2_xe2=0xc6e0 +serdes_preemphasis_lane3_xe2=0xc6e0 + +# xe3 (40G) +portmap_4=37:40 +xgxs_rx_lane_map_4=0x213 +xgxs_tx_lane_map_4=0x1203 +phy_xaui_rx_polarity_flip_4=0x3 +phy_xaui_tx_polarity_flip_4=0xe +serdes_driver_current_lane0_xe3=0x4 +serdes_driver_current_lane1_xe3=0x4 +serdes_driver_current_lane2_xe3=0x4 +serdes_driver_current_lane3_xe3=0x4 +serdes_pre_driver_current_lane0_xe3=0x4 +serdes_pre_driver_current_lane1_xe3=0x4 +serdes_pre_driver_current_lane2_xe3=0x4 +serdes_pre_driver_current_lane3_xe3=0x4 +serdes_preemphasis_lane0_xe3=0xcad0 +serdes_preemphasis_lane1_xe3=0xcad0 +serdes_preemphasis_lane2_xe3=0xc2f0 +serdes_preemphasis_lane3_xe3=0xc2f0 + +# xe4 (40G) +portmap_5=45:40 +xgxs_rx_lane_map_5=0x213 +xgxs_tx_lane_map_5=0x213 +phy_xaui_rx_polarity_flip_5=0xe +phy_xaui_tx_polarity_flip_5=0x8 +serdes_driver_current_lane0_xe4=0x4 +serdes_driver_current_lane1_xe4=0x4 +serdes_driver_current_lane2_xe4=0x4 +serdes_driver_current_lane3_xe4=0x4 +serdes_pre_driver_current_lane0_xe4=0x4 +serdes_pre_driver_current_lane1_xe4=0x4 +serdes_pre_driver_current_lane2_xe4=0x4 +serdes_pre_driver_current_lane3_xe4=0x4 +serdes_preemphasis_lane0_xe4=0xc2f0 +serdes_preemphasis_lane1_xe4=0xc2f0 +serdes_preemphasis_lane2_xe4=0xc2f0 +serdes_preemphasis_lane3_xe4=0xc2f0 + +# xe5 (40G) +portmap_6=41:40 +xgxs_rx_lane_map_6=0x213 +xgxs_tx_lane_map_6=0x3021 +phy_xaui_rx_polarity_flip_6=0x3 +phy_xaui_tx_polarity_flip_6=0xb +serdes_driver_current_lane0_xe5=0x4 +serdes_driver_current_lane1_xe5=0x4 +serdes_driver_current_lane2_xe5=0x4 +serdes_driver_current_lane3_xe5=0x4 +serdes_pre_driver_current_lane0_xe5=0x4 +serdes_pre_driver_current_lane1_xe5=0x4 +serdes_pre_driver_current_lane2_xe5=0x4 +serdes_pre_driver_current_lane3_xe5=0x4 +serdes_preemphasis_lane0_xe5=0xc6e0 +serdes_preemphasis_lane1_xe5=0xc2f0 +serdes_preemphasis_lane2_xe5=0xc2f0 +serdes_preemphasis_lane3_xe5=0xcad0 + +# xe6 (40G) +portmap_7=1:40 +xgxs_rx_lane_map_7=0x213 +xgxs_tx_lane_map_7=0x2031 +phy_xaui_rx_polarity_flip_7=0xe +phy_xaui_tx_polarity_flip_7=0xd +serdes_driver_current_lane0_xe6=0x5 +serdes_driver_current_lane1_xe6=0x5 +serdes_driver_current_lane2_xe6=0x5 +serdes_driver_current_lane3_xe6=0x5 +serdes_pre_driver_current_lane0_xe6=0x5 +serdes_pre_driver_current_lane1_xe6=0x5 +serdes_pre_driver_current_lane2_xe6=0x5 +serdes_pre_driver_current_lane3_xe6=0x5 +serdes_preemphasis_lane0_xe6=0xc6e0 +serdes_preemphasis_lane1_xe6=0xcad0 +serdes_preemphasis_lane2_xe6=0xc6e0 +serdes_preemphasis_lane3_xe6=0xcad0 + +# xe7 (40G) +portmap_8=5:40 +xgxs_rx_lane_map_8=0x213 +xgxs_tx_lane_map_8=0x1203 +phy_xaui_rx_polarity_flip_8=0xc +phy_xaui_tx_polarity_flip_8=0x1 +serdes_driver_current_lane0_xe7=0x4 +serdes_driver_current_lane1_xe7=0x4 +serdes_driver_current_lane2_xe7=0x4 +serdes_driver_current_lane3_xe7=0x4 +serdes_pre_driver_current_lane0_xe7=0x4 +serdes_pre_driver_current_lane1_xe7=0x4 +serdes_pre_driver_current_lane2_xe7=0x4 +serdes_pre_driver_current_lane3_xe7=0x4 +serdes_preemphasis_lane0_xe7=0xc6e0 +serdes_preemphasis_lane1_xe7=0xc6e0 +serdes_preemphasis_lane2_xe7=0xc6e0 +serdes_preemphasis_lane3_xe7=0xc6e0 + +# xe8 (40G) +portmap_9=13:40 +xgxs_rx_lane_map_9=0x213 +xgxs_tx_lane_map_9=0x132 +phy_xaui_rx_polarity_flip_9=0xe +phy_xaui_tx_polarity_flip_9=0x0 +serdes_driver_current_lane0_xe8=0x2 +serdes_driver_current_lane1_xe8=0x3 +serdes_driver_current_lane2_xe8=0x2 +serdes_driver_current_lane3_xe8=0x2 +serdes_pre_driver_current_lane0_xe8=0x2 +serdes_pre_driver_current_lane1_xe8=0x3 +serdes_pre_driver_current_lane2_xe8=0x2 +serdes_pre_driver_current_lane3_xe8=0x2 +serdes_preemphasis_lane0_xe8=0xb270 +serdes_preemphasis_lane1_xe8=0xbb10 +serdes_preemphasis_lane2_xe8=0xb720 +serdes_preemphasis_lane3_xe8=0xb720 + +# xe9 (40G) +portmap_10=9:40 +xgxs_rx_lane_map_10=0x3120 +xgxs_tx_lane_map_10=0x3021 +phy_xaui_rx_polarity_flip_10=0x0 +phy_xaui_tx_polarity_flip_10=0x4 +serdes_driver_current_lane0_xe9=0x3 +serdes_driver_current_lane1_xe9=0x3 +serdes_driver_current_lane2_xe9=0x3 +serdes_driver_current_lane3_xe9=0x3 +serdes_pre_driver_current_lane0_xe9=0x3 +serdes_pre_driver_current_lane1_xe9=0x3 +serdes_pre_driver_current_lane2_xe9=0x3 +serdes_pre_driver_current_lane3_xe9=0x3 +serdes_preemphasis_lane0_xe9=0xc2f0 +serdes_preemphasis_lane1_xe9=0xc6e0 +serdes_preemphasis_lane2_xe9=0xbf00 +serdes_preemphasis_lane3_xe9=0xc2f0 + +# xe10 (40G) +portmap_11=17:40 +xgxs_rx_lane_map_11=0x213 +xgxs_tx_lane_map_11=0x132 +phy_xaui_rx_polarity_flip_11=0xe +phy_xaui_tx_polarity_flip_11=0x0 +serdes_driver_current_lane0_xe10=0x2 +serdes_driver_current_lane1_xe10=0x2 +serdes_driver_current_lane2_xe10=0x2 +serdes_driver_current_lane3_xe10=0x2 +serdes_pre_driver_current_lane0_xe10=0x2 +serdes_pre_driver_current_lane1_xe10=0x2 +serdes_pre_driver_current_lane2_xe10=0x2 +serdes_pre_driver_current_lane3_xe10=0x2 +serdes_preemphasis_lane0_xe10=0xb330 +serdes_preemphasis_lane1_xe10=0xbb10 +serdes_preemphasis_lane2_xe10=0xbb10 +serdes_preemphasis_lane3_xe10=0xbb10 + +# xe11 (40G) +portmap_12=21:40 +xgxs_rx_lane_map_12=0x123 +xgxs_tx_lane_map_12=0x1203 +phy_xaui_rx_polarity_flip_12=0xc +phy_xaui_tx_polarity_flip_12=0xe +serdes_driver_current_lane0_xe11=0x2 +serdes_driver_current_lane1_xe11=0x2 +serdes_driver_current_lane2_xe11=0x2 +serdes_driver_current_lane3_xe11=0x2 +serdes_pre_driver_current_lane0_xe11=0x2 +serdes_pre_driver_current_lane1_xe11=0x2 +serdes_pre_driver_current_lane2_xe11=0x2 +serdes_pre_driver_current_lane3_xe11=0x2 +serdes_preemphasis_lane0_xe11=0xb330 +serdes_preemphasis_lane1_xe11=0xb330 +serdes_preemphasis_lane2_xe11=0xb330 +serdes_preemphasis_lane3_xe11=0xb330 + +# xe12 (40G) +portmap_13=53:40 +xgxs_rx_lane_map_13=0x213 +xgxs_tx_lane_map_13=0x231 +phy_xaui_rx_polarity_flip_13=0x1 +phy_xaui_tx_polarity_flip_13=0x0 +serdes_driver_current_lane0_xe12=0x2 +serdes_driver_current_lane1_xe12=0x2 +serdes_driver_current_lane2_xe12=0x2 +serdes_driver_current_lane3_xe12=0x2 +serdes_pre_driver_current_lane0_xe12=0x2 +serdes_pre_driver_current_lane1_xe12=0x2 +serdes_pre_driver_current_lane2_xe12=0x2 +serdes_pre_driver_current_lane3_xe12=0x2 +serdes_preemphasis_lane0_xe12=0xaf40 +serdes_preemphasis_lane1_xe12=0xaf40 +serdes_preemphasis_lane2_xe12=0xaf40 +serdes_preemphasis_lane3_xe12=0xaf40 + +# xe13 (40G) +portmap_14=49:40 +xgxs_rx_lane_map_14=0x1302 +xgxs_tx_lane_map_14=0x2031 +phy_xaui_rx_polarity_flip_14=0xb +phy_xaui_tx_polarity_flip_14=0x3 +serdes_driver_current_lane0_xe13=0x2 +serdes_driver_current_lane1_xe13=0x2 +serdes_driver_current_lane2_xe13=0x2 +serdes_driver_current_lane3_xe13=0x2 +serdes_pre_driver_current_lane0_xe13=0x2 +serdes_pre_driver_current_lane1_xe13=0x2 +serdes_pre_driver_current_lane2_xe13=0x2 +serdes_pre_driver_current_lane3_xe13=0x2 +serdes_preemphasis_lane0_xe13=0xa760 +serdes_preemphasis_lane1_xe13=0xa760 +serdes_preemphasis_lane2_xe13=0xa760 +serdes_preemphasis_lane3_xe13=0xa760 + +# xe14 (40G) +portmap_15=57:40 +xgxs_rx_lane_map_15=0x213 +xgxs_tx_lane_map_15=0x2031 +phy_xaui_rx_polarity_flip_15=0x1 +phy_xaui_tx_polarity_flip_15=0x0 +serdes_driver_current_lane0_xe14=0x1 +serdes_driver_current_lane1_xe14=0x1 +serdes_driver_current_lane2_xe14=0x1 +serdes_driver_current_lane3_xe14=0x1 +serdes_pre_driver_current_lane0_xe14=0x1 +serdes_pre_driver_current_lane1_xe14=0x1 +serdes_pre_driver_current_lane2_xe14=0x1 +serdes_pre_driver_current_lane3_xe14=0x1 +serdes_preemphasis_lane0_xe14=0xa760 +serdes_preemphasis_lane1_xe14=0xa760 +serdes_preemphasis_lane2_xe14=0xa760 +serdes_preemphasis_lane3_xe14=0xa760 + +# xe15 (40G) +portmap_16=61:40 +xgxs_rx_lane_map_16=0x132 +xgxs_tx_lane_map_16=0x213 +phy_xaui_rx_polarity_flip_16=0x0 +phy_xaui_tx_polarity_flip_16=0x0 +serdes_driver_current_lane0_xe15=0x2 +serdes_driver_current_lane1_xe15=0x2 +serdes_driver_current_lane2_xe15=0x2 +serdes_driver_current_lane3_xe15=0x2 +serdes_pre_driver_current_lane0_xe15=0x2 +serdes_pre_driver_current_lane1_xe15=0x2 +serdes_pre_driver_current_lane2_xe15=0x2 +serdes_pre_driver_current_lane3_xe15=0x2 +serdes_preemphasis_lane0_xe15=0xa760 +serdes_preemphasis_lane1_xe15=0xa760 +serdes_preemphasis_lane2_xe15=0xa760 +serdes_preemphasis_lane3_xe15=0xa760 + +# xe16 (40G) +portmap_17=69:40 +xgxs_rx_lane_map_17=0x213 +xgxs_tx_lane_map_17=0x2130 +phy_xaui_rx_polarity_flip_17=0x1 +phy_xaui_tx_polarity_flip_17=0xf +serdes_driver_current_lane0_xe16=0x1 +serdes_driver_current_lane1_xe16=0x1 +serdes_driver_current_lane2_xe16=0x1 +serdes_driver_current_lane3_xe16=0x1 +serdes_pre_driver_current_lane0_xe16=0x1 +serdes_pre_driver_current_lane1_xe16=0x1 +serdes_pre_driver_current_lane2_xe16=0x1 +serdes_pre_driver_current_lane3_xe16=0x1 +serdes_preemphasis_lane0_xe16=0xa760 +serdes_preemphasis_lane1_xe16=0xa760 +serdes_preemphasis_lane2_xe16=0xa760 +serdes_preemphasis_lane3_xe16=0xa760 + +# xe17 (40G) +portmap_18=65:40 +xgxs_rx_lane_map_18=0x132 +xgxs_tx_lane_map_18=0x2031 +phy_xaui_rx_polarity_flip_18=0x3 +phy_xaui_tx_polarity_flip_18=0x9 +serdes_driver_current_lane0_xe17=0x1 +serdes_driver_current_lane1_xe17=0x1 +serdes_driver_current_lane2_xe17=0x1 +serdes_driver_current_lane3_xe17=0x1 +serdes_pre_driver_current_lane0_xe17=0x1 +serdes_pre_driver_current_lane1_xe17=0x1 +serdes_pre_driver_current_lane2_xe17=0x1 +serdes_pre_driver_current_lane3_xe17=0x1 +serdes_preemphasis_lane0_xe17=0xa370 +serdes_preemphasis_lane1_xe17=0xa370 +serdes_preemphasis_lane2_xe17=0xa370 +serdes_preemphasis_lane3_xe17=0xa370 + +# xe18 (40G) +portmap_19=73:40 +xgxs_rx_lane_map_19=0x213 +xgxs_tx_lane_map_19=0x2031 +phy_xaui_rx_polarity_flip_19=0x1 +phy_xaui_tx_polarity_flip_19=0x0 +serdes_driver_current_lane0_xe18=0x2 +serdes_driver_current_lane1_xe18=0x2 +serdes_driver_current_lane2_xe18=0x2 +serdes_driver_current_lane3_xe18=0x2 +serdes_pre_driver_current_lane0_xe18=0x2 +serdes_pre_driver_current_lane1_xe18=0x2 +serdes_pre_driver_current_lane2_xe18=0x2 +serdes_pre_driver_current_lane3_xe18=0x2 +serdes_preemphasis_lane0_xe18=0xa760 +serdes_preemphasis_lane1_xe18=0xa760 +serdes_preemphasis_lane2_xe18=0xa760 +serdes_preemphasis_lane3_xe18=0xa760 + +# xe19 (40G) +portmap_20=77:40 +xgxs_rx_lane_map_20=0x123 +xgxs_tx_lane_map_20=0x1203 +phy_xaui_rx_polarity_flip_20=0x3 +phy_xaui_tx_polarity_flip_20=0xe +serdes_driver_current_lane0_xe19=0x2 +serdes_driver_current_lane1_xe19=0x2 +serdes_driver_current_lane2_xe19=0x2 +serdes_driver_current_lane3_xe19=0x2 +serdes_pre_driver_current_lane0_xe19=0x2 +serdes_pre_driver_current_lane1_xe19=0x2 +serdes_pre_driver_current_lane2_xe19=0x2 +serdes_pre_driver_current_lane3_xe19=0x2 +serdes_preemphasis_lane0_xe19=0xaf40 +serdes_preemphasis_lane1_xe19=0xaf40 +serdes_preemphasis_lane2_xe19=0xaf40 +serdes_preemphasis_lane3_xe19=0xaf40 + +# xe20 (40G) +portmap_21=109:40 +xgxs_rx_lane_map_21=0x132 +xgxs_tx_lane_map_21=0x132 +phy_xaui_rx_polarity_flip_21=0x8 +phy_xaui_tx_polarity_flip_21=0x0 +serdes_driver_current_lane0_xe20=0x1 +serdes_driver_current_lane1_xe20=0x1 +serdes_driver_current_lane2_xe20=0x1 +serdes_driver_current_lane3_xe20=0x2 +serdes_pre_driver_current_lane0_xe20=0x1 +serdes_pre_driver_current_lane1_xe20=0x1 +serdes_pre_driver_current_lane2_xe20=0x1 +serdes_pre_driver_current_lane3_xe20=0x2 +serdes_preemphasis_lane0_xe20=0xb330 +serdes_preemphasis_lane1_xe20=0xb330 +serdes_preemphasis_lane2_xe20=0xb330 +serdes_preemphasis_lane3_xe20=0xbff0 + +# xe21 (40G) +portmap_22=105:40 +xgxs_rx_lane_map_22=0x1320 +xgxs_tx_lane_map_22=0x3021 +phy_xaui_rx_polarity_flip_22=0xd +phy_xaui_tx_polarity_flip_22=0xb +serdes_driver_current_lane0_xe21=0x1 +serdes_driver_current_lane1_xe21=0x1 +serdes_driver_current_lane2_xe21=0x1 +serdes_driver_current_lane3_xe21=0x1 +serdes_pre_driver_current_lane0_xe21=0x1 +serdes_pre_driver_current_lane1_xe21=0x1 +serdes_pre_driver_current_lane2_xe21=0x1 +serdes_pre_driver_current_lane3_xe21=0x1 +serdes_preemphasis_lane0_xe21=0xb330 +serdes_preemphasis_lane1_xe21=0xb330 +serdes_preemphasis_lane2_xe21=0xb330 +serdes_preemphasis_lane3_xe21=0xb330 + +# xe22 (40G) +portmap_23=113:40 +xgxs_rx_lane_map_23=0x132 +xgxs_tx_lane_map_23=0x132 +phy_xaui_rx_polarity_flip_23=0x8 +phy_xaui_tx_polarity_flip_23=0x0 +serdes_driver_current_lane0_xe22=0x1 +serdes_driver_current_lane1_xe22=0x1 +serdes_driver_current_lane2_xe22=0x1 +serdes_driver_current_lane3_xe22=0x1 +serdes_pre_driver_current_lane0_xe22=0x1 +serdes_pre_driver_current_lane1_xe22=0x1 +serdes_pre_driver_current_lane2_xe22=0x1 +serdes_pre_driver_current_lane3_xe22=0x1 +serdes_preemphasis_lane0_xe22=0xbb10 +serdes_preemphasis_lane1_xe22=0xbb10 +serdes_preemphasis_lane2_xe22=0xbb10 +serdes_preemphasis_lane3_xe22=0xc2f0 + +# xe23 (40G) +portmap_24=117:40 +xgxs_rx_lane_map_24=0x231 +xgxs_tx_lane_map_24=0x1203 +phy_xaui_rx_polarity_flip_24=0x3 +phy_xaui_tx_polarity_flip_24=0xe +serdes_driver_current_lane0_xe23=0x3 +serdes_driver_current_lane1_xe23=0x5 +serdes_driver_current_lane2_xe23=0x3 +serdes_driver_current_lane3_xe23=0x3 +serdes_pre_driver_current_lane0_xe23=0x3 +serdes_pre_driver_current_lane1_xe23=0x5 +serdes_pre_driver_current_lane2_xe23=0x3 +serdes_pre_driver_current_lane3_xe23=0x3 +serdes_preemphasis_lane0_xe23=0xc6e0 +serdes_preemphasis_lane1_xe23=0xc6e0 +serdes_preemphasis_lane2_xe23=0xc6e0 +serdes_preemphasis_lane3_xe23=0xc6e0 + +# xe24 (40G) +portmap_25=125:40 +xgxs_rx_lane_map_25=0x132 +xgxs_tx_lane_map_25=0x132 +phy_xaui_rx_polarity_flip_25=0x8 +phy_xaui_tx_polarity_flip_25=0x0 +serdes_driver_current_lane0_xe24=0x4 +serdes_driver_current_lane1_xe24=0x4 +serdes_driver_current_lane2_xe24=0x4 +serdes_driver_current_lane3_xe24=0x4 +serdes_pre_driver_current_lane0_xe24=0x4 +serdes_pre_driver_current_lane1_xe24=0x4 +serdes_pre_driver_current_lane2_xe24=0x4 +serdes_pre_driver_current_lane3_xe24=0x4 +serdes_preemphasis_lane0_xe24=0xc6e0 +serdes_preemphasis_lane1_xe24=0xc6e0 +serdes_preemphasis_lane2_xe24=0xc6e0 +serdes_preemphasis_lane3_xe24=0xcec0 + +# xe25 (40G) +portmap_26=121:40 +xgxs_rx_lane_map_26=0x1320 +xgxs_tx_lane_map_26=0x3021 +phy_xaui_rx_polarity_flip_26=0xd +phy_xaui_tx_polarity_flip_26=0xb +serdes_driver_current_lane0_xe25=0x4 +serdes_driver_current_lane1_xe25=0x4 +serdes_driver_current_lane2_xe25=0x4 +serdes_driver_current_lane3_xe25=0x4 +serdes_pre_driver_current_lane0_xe25=0x4 +serdes_pre_driver_current_lane1_xe25=0x4 +serdes_pre_driver_current_lane2_xe25=0x4 +serdes_pre_driver_current_lane3_xe25=0x4 +serdes_preemphasis_lane0_xe25=0xc6e0 +serdes_preemphasis_lane1_xe25=0xc6e0 +serdes_preemphasis_lane2_xe25=0xc6e0 +serdes_preemphasis_lane3_xe25=0xc6e0 + +# xe26 (40G) +portmap_27=81:40 +xgxs_rx_lane_map_27=0x1320 +xgxs_tx_lane_map_27=0x2031 +phy_xaui_rx_polarity_flip_27=0x1 +phy_xaui_tx_polarity_flip_27=0x2 +serdes_driver_current_lane0_xe26=0x2 +serdes_driver_current_lane1_xe26=0x2 +serdes_driver_current_lane2_xe26=0x2 +serdes_driver_current_lane3_xe26=0x2 +serdes_pre_driver_current_lane0_xe26=0x2 +serdes_pre_driver_current_lane1_xe26=0x2 +serdes_pre_driver_current_lane2_xe26=0x2 +serdes_pre_driver_current_lane3_xe26=0x2 +serdes_preemphasis_lane0_xe26=0xbb10 +serdes_preemphasis_lane1_xe26=0xbb10 +serdes_preemphasis_lane2_xe26=0xbf00 +serdes_preemphasis_lane3_xe26=0xbb10 + +# xe27 (40G) +portmap_28=85:40 +xgxs_rx_lane_map_28=0x213 +xgxs_tx_lane_map_28=0x1203 +phy_xaui_rx_polarity_flip_28=0xc +phy_xaui_tx_polarity_flip_28=0xe +serdes_driver_current_lane0_xe27=0x4 +serdes_driver_current_lane1_xe27=0x5 +serdes_driver_current_lane2_xe27=0x4 +serdes_driver_current_lane3_xe27=0x5 +serdes_pre_driver_current_lane0_xe27=0x4 +serdes_pre_driver_current_lane1_xe27=0x5 +serdes_pre_driver_current_lane2_xe27=0x4 +serdes_pre_driver_current_lane3_xe27=0x5 +serdes_preemphasis_lane0_xe27=0xc2f0 +serdes_preemphasis_lane1_xe27=0xc6e0 +serdes_preemphasis_lane2_xe27=0xc6e0 +serdes_preemphasis_lane3_xe27=0xc6e0 + +# xe28 (40G) +portmap_29=93:40 +xgxs_rx_lane_map_29=0x1320 +xgxs_tx_lane_map_29=0x2031 +phy_xaui_rx_polarity_flip_29=0x1 +phy_xaui_tx_polarity_flip_29=0x2 +serdes_driver_current_lane0_xe28=0x4 +serdes_driver_current_lane1_xe28=0x4 +serdes_driver_current_lane2_xe28=0x4 +serdes_driver_current_lane3_xe28=0x4 +serdes_pre_driver_current_lane0_xe28=0x4 +serdes_pre_driver_current_lane1_xe28=0x4 +serdes_pre_driver_current_lane2_xe28=0x4 +serdes_pre_driver_current_lane3_xe28=0x4 +serdes_preemphasis_lane0_xe28=0xc2f0 +serdes_preemphasis_lane1_xe28=0xc2f0 +serdes_preemphasis_lane2_xe28=0xc2f0 +serdes_preemphasis_lane3_xe28=0xc2f0 + +# xe29 (40G) +portmap_30=89:40 +xgxs_rx_lane_map_30=0x1320 +xgxs_tx_lane_map_30=0x3021 +phy_xaui_rx_polarity_flip_30=0x2 +phy_xaui_tx_polarity_flip_30=0xb +serdes_driver_current_lane0_xe29=0x4 +serdes_driver_current_lane1_xe29=0x4 +serdes_driver_current_lane2_xe29=0x4 +serdes_driver_current_lane3_xe29=0x4 +serdes_pre_driver_current_lane0_xe29=0x4 +serdes_pre_driver_current_lane1_xe29=0x4 +serdes_pre_driver_current_lane2_xe29=0x4 +serdes_pre_driver_current_lane3_xe29=0x4 +serdes_preemphasis_lane0_xe29=0xcad0 +serdes_preemphasis_lane1_xe29=0xc6e0 +serdes_preemphasis_lane2_xe29=0xc6e0 +serdes_preemphasis_lane3_xe29=0xc6e0 + +# xe30 (40G) +portmap_31=101:40 +xgxs_rx_lane_map_31=0x1320 +xgxs_tx_lane_map_31=0x1203 +phy_xaui_rx_polarity_flip_31=0x1 +phy_xaui_tx_polarity_flip_31=0x6 +serdes_driver_current_lane0_xe30=0x6 +serdes_driver_current_lane1_xe30=0x6 +serdes_driver_current_lane2_xe30=0x6 +serdes_driver_current_lane3_xe30=0x7 +serdes_pre_driver_current_lane0_xe30=0x6 +serdes_pre_driver_current_lane1_xe30=0x6 +serdes_pre_driver_current_lane2_xe30=0x6 +serdes_pre_driver_current_lane3_xe30=0x7 +serdes_preemphasis_lane0_xe30=0xcec0 +serdes_preemphasis_lane1_xe30=0xcec0 +serdes_preemphasis_lane2_xe30=0xcad0 +serdes_preemphasis_lane3_xe30=0xc6e0 + +# xe31 (40G) +portmap_32=97:40 +xgxs_rx_lane_map_32=0x213 +xgxs_tx_lane_map_32=0x2031 +phy_xaui_rx_polarity_flip_32=0xc +phy_xaui_tx_polarity_flip_32=0x3 +serdes_driver_current_lane0_xe31=0x5 +serdes_driver_current_lane1_xe31=0x5 +serdes_driver_current_lane2_xe31=0x5 +serdes_driver_current_lane3_xe31=0x5 +serdes_pre_driver_current_lane0_xe31=0x5 +serdes_pre_driver_current_lane1_xe31=0x5 +serdes_pre_driver_current_lane2_xe31=0x5 +serdes_pre_driver_current_lane3_xe31=0x5 +serdes_preemphasis_lane0_xe31=0xcad0 +serdes_preemphasis_lane1_xe31=0xcad0 +serdes_preemphasis_lane2_xe31=0xcad0 +serdes_preemphasis_lane3_xe31=0xcad0 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/default_sku b/device/dell/x86_64-dell_s6000_s1220-r0/default_sku new file mode 100644 index 000000000000..493e1989b662 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/default_sku @@ -0,0 +1 @@ +Force10-S6000 t1 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/installer.conf b/device/dell/x86_64-dell_s6000_s1220-r0/installer.conf new file mode 100644 index 000000000000..107095cdad7c --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/installer.conf @@ -0,0 +1,27 @@ +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="processor.max_cstate=1 intel_idle.max_cstate=0" + +if [ "$install_env" = "onie" ]; then + +echo "Replace ONIE reboot with Dell reset commands" + +# set I2C GPIO mux +[ -d /sys/class/gpio/gpio1 ] || echo 1 > /sys/class/gpio/export +[ -d /sys/class/gpio/gpio2 ] || echo 2 > /sys/class/gpio/export +echo out > /sys/class/gpio/gpio1/direction +echo out > /sys/class/gpio/gpio2/direction +echo 0 > /sys/class/gpio/gpio1/value +echo 0 > /sys/class/gpio/gpio2/value + +# replace the original reboot binary with the following command +# sync flushes file system buffers +# i2cset command triggers a hard system reboot, required by ASIC to operate correctly +rm /sbin/reboot +cat <> /sbin/reboot +#!/bin/sh +sync +i2cset -y 0 0x31 1 0xfd +EOF + +chmod a+x /sbin/reboot + +fi diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/led_proc_init.soc b/device/dell/x86_64-dell_s6000_s1220-r0/led_proc_init.soc new file mode 100644 index 000000000000..ddda7bdb639a --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/led_proc_init.soc @@ -0,0 +1,43 @@ +# LED microprocessor initialization for Dell s6000 + +led 0 stop +led 0 prog 02 31 60 F7 02 01 28 60 F6 D6 F7 70 28 67 44 06 F6 06 F6 80 D2 35 74 06 86 F8 3A 40 67 80 67 44 06 F6 67 80 67 80 67 3C D2 32 70 1C D2 34 70 1C 67 44 06 F6 67 80 67 80 67 80 67 3C 06 F7 F2 01 60 F7 77 11 32 08 97 71 4C 77 80 57 67 61 32 00 32 01 B7 97 71 5C 95 75 74 85 77 7C 02 0A 50 77 56 06 F6 D2 17 75 6C 12 88 FE F6 57 06 F6 E2 17 12 D4 F8 57 16 F8 CA 05 74 80 77 7C 22 0E 87 57 22 0F 87 57 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0x31 REMAP_PORT_2=0 REMAP_PORT_1=0 REMAP_PORT_0=0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=0x32 REMAP_PORT_6=0 REMAP_PORT_5=0 REMAP_PORT_4=0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=0 REMAP_PORT_8=0 REMAP_PORT_11=0x34 REMAP_PORT_10=0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=0x33 REMAP_PORT_14=0 REMAP_PORT_13=0 REMAP_PORT_12=0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=0x16 REMAP_PORT_18=0x15 REMAP_PORT_17=0x18 REMAP_PORT_16=0x17 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=0x11 REMAP_PORT_22=0x12 REMAP_PORT_21=0x13 REMAP_PORT_20=0x14 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=9 REMAP_PORT_26=0xa REMAP_PORT_25=0xb REMAP_PORT_24=0xc +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0xe REMAP_PORT_30=0xd REMAP_PORT_29=0x10 REMAP_PORT_28=0xf +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=0x2e REMAP_PORT_34=0x2d REMAP_PORT_33=0x30 REMAP_PORT_32=0x2f +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=0x29 REMAP_PORT_38=0x2a REMAP_PORT_37=0x2b REMAP_PORT_36=0x2c +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=6 REMAP_PORT_42=5 REMAP_PORT_41=8 REMAP_PORT_40=7 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=1 REMAP_PORT_46=2 REMAP_PORT_45=3 REMAP_PORT_44=4 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=0x26 REMAP_PORT_50=0x25 REMAP_PORT_49=0x28 REMAP_PORT_48=0x27 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=0x21 REMAP_PORT_54=0x22 REMAP_PORT_53=0x23 REMAP_PORT_52=0x24 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=0x19 REMAP_PORT_58=0x1a REMAP_PORT_57=0x1b REMAP_PORT_56=0x1c +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0x1e REMAP_PORT_62=0x1d REMAP_PORT_61=0x20 REMAP_PORT_60=0x1f +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 02 31 60 F7 02 01 28 60 F6 D6 F7 70 28 67 44 06 F6 06 F6 80 D2 35 74 06 86 F8 3A 40 67 80 67 44 06 F6 67 80 67 80 67 3C D2 32 70 1C D2 34 70 1C 67 44 06 F6 67 80 67 80 67 80 67 3C 06 F7 F2 01 60 F7 77 11 32 08 97 71 4C 77 80 57 67 61 32 00 32 01 B7 97 71 5C 95 75 74 85 77 7C 02 0A 50 77 56 06 F6 D2 17 75 6C 12 88 FE F6 57 06 F6 E2 17 12 D4 F8 57 16 F8 CA 05 74 80 77 7C 22 0E 87 57 22 0F 87 57 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0x1e REMAP_PORT_2=0x1d REMAP_PORT_1=0x20 REMAP_PORT_0=0x1f +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=0x19 REMAP_PORT_6=0x1a REMAP_PORT_5=0x1b REMAP_PORT_4=0x1c +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=0x23 REMAP_PORT_8=0x24 REMAP_PORT_11=0x21 REMAP_PORT_10=0x22 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=0x26 REMAP_PORT_14=0x25 REMAP_PORT_13=0x28 REMAP_PORT_12=0x27 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=0x16 REMAP_PORT_18=0x15 REMAP_PORT_17=0x18 REMAP_PORT_16=0x17 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=0x11 REMAP_PORT_22=0x12 REMAP_PORT_21=0x13 REMAP_PORT_20=0x14 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=0x34 REMAP_PORT_26=0 REMAP_PORT_25=0 REMAP_PORT_24=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0x33 REMAP_PORT_30=0 REMAP_PORT_29=0 REMAP_PORT_28=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=0x2e REMAP_PORT_34=0x2d REMAP_PORT_33=0x30 REMAP_PORT_32=0x2f +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=0x29 REMAP_PORT_38=0x2a REMAP_PORT_37=0x2b REMAP_PORT_36=0x2c +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=0x31 REMAP_PORT_42=0 REMAP_PORT_41=0 REMAP_PORT_40=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=0x32 REMAP_PORT_46=0 REMAP_PORT_45=0 REMAP_PORT_44=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=9 REMAP_PORT_50=0xa REMAP_PORT_49=0xb REMAP_PORT_48=0xc +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=0xe REMAP_PORT_54=0xd REMAP_PORT_53=0x10 REMAP_PORT_52=0xf +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=6 REMAP_PORT_58=5 REMAP_PORT_57=8 REMAP_PORT_56=7 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=1 REMAP_PORT_62=2 REMAP_PORT_61=3 REMAP_PORT_60=4 +led 1 auto on +led 1 start diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/platform_reboot b/device/dell/x86_64-dell_s6000_s1220-r0/platform_reboot new file mode 100755 index 000000000000..875a52787752 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/platform_reboot @@ -0,0 +1,3 @@ +#!/bin/sh + +echo 1 > /sys/devices/platform/dell-s6000-cpld.0/power_reset diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/plugins/eeprom.py b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/eeprom.py new file mode 100644 index 000000000000..b326d24f6d44 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Dell S6000 +# +# 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-10/10-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/plugins/psuutil.py b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/psuutil.py new file mode 100644 index 000000000000..537605f3975b --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/psuutil.py @@ -0,0 +1,74 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def get_cpld_register(self, reg_name): + cpld_dir = "/sys/devices/platform/dell-s6000-cpld.0" + retval = 'ERR' + reg_file = cpld_dir +'/' + reg_name + if (not os.path.isfile(reg_file)): + return retval + + try: + with open(reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", reg_file, "file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + S6000_MAX_PSUS = 2 + return S6000_MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + psu_status = self.get_cpld_register('psu'+str(index - 1)+'_status') + if (psu_status != 'ERR'): + status = int(psu_status, 10) + + presence = self.get_psu_presence(index) + + return (status & presence) + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_presence = self.get_cpld_register('psu'+str(index - 1)+'_prs') + if (psu_presence != 'ERR'): + status = int(psu_presence, 10) + + return status diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/plugins/sfputil.py b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/sfputil.py new file mode 100644 index 000000000000..9275c4c9b6fb --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/sfputil.py @@ -0,0 +1,183 @@ +# 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 = 31 + PORTS_IN_BLOCK = 32 + + EEPROM_OFFSET = 20 + + _port_to_eeprom_mapping = {} + + @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 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): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET) + + 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/devices/platform/dell-s6000-cpld.0/qsfp_modprs") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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 + + try: + reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_lpmode") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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 + + try: + reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_lpmode", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/dell-s6000-cpld.0/qsfp_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 + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # 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: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "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 + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/sensors.conf b/device/dell/x86_64-dell_s6000_s1220-r0/sensors.conf new file mode 100644 index 000000000000..c87af11afacc --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/sensors.conf @@ -0,0 +1,36 @@ +# libsensors configuration file +# -------------------------------------------------- +# + +# tmp75-i2c-11-4c has sensors close to Networking ASIC. +# tmp75-i2c-11-4d has sensors close to NIC. +# tmp75-i2c-11-4e is an ambient temperature sensor. + +chip "tmp75-*" + set temp1_max 50 + set temp1_max_hyst 25 + +# emc1403-i2c-10-4d has following temperature sensors: +# temp1: CPU0 external Temp Sensor +# temp2: CPU1 external Temp Sensor +# temp3: CPU Internal DTS (Internal die, max of all die readings) + +chip "emc1403-*" + set temp1_crit 85 + set temp1_max 50 + set temp2_crit 85 + set temp2_max 50 + set temp3_crit 85 + set temp3_max 50 + +chip "max6620-i2c-*-2a" + ignore fan3 + ignore fan4 + +chip "jc42-*" + set temp1_max 50 + set temp1_crit 85 + +chip "dni_dps460-*" + set temp1_max 50 + set temp2_max 50 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/Force10-S6100/buffers.json.j2 b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers_defaults_t0.j2 b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..e337f676b650 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers_defaults_t0.j2 @@ -0,0 +1,47 @@ + +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11213696", + "type": "ingress", + "mode": "dynamic", + "xoff": "3855488" + }, + "egress_lossy_pool": { + "size": "9532224", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"3995680" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers_defaults_t1.j2 b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..c7c98bfe4299 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers_defaults_t1.j2 @@ -0,0 +1,47 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10443264", + "type": "ingress", + "mode": "dynamic", + "xoff": "4625920" + }, + "egress_lossy_pool": { + "size": "8877440", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"3995680" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/pg_profile_lookup.ini b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/pg_profile_lookup.ini new file mode 100644 index 000000000000..570454c8d5b2 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -3 2288 + 25000 5m 1248 2288 53248 -3 2288 + 40000 5m 1248 2288 66560 -3 2288 + 50000 5m 1248 2288 79872 -3 2288 + 100000 5m 1248 2288 165568 -3 2288 + 10000 40m 1248 2288 37024 -3 2288 + 25000 40m 1248 2288 56160 -3 2288 + 40000 40m 1248 2288 71552 -3 2288 + 50000 40m 1248 2288 85696 -3 2288 + 100000 40m 1248 2288 177632 -3 2288 + 10000 300m 1248 2288 46176 -3 2288 + 25000 300m 1248 2288 79040 -3 2288 + 40000 300m 1248 2288 108160 -3 2288 + 50000 300m 1248 2288 131456 -3 2288 + 100000 300m 1248 2288 268736 -3 2288 diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/port_config.ini b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/port_config.ini new file mode 100644 index 000000000000..1922a3e04b5a --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index speed +Ethernet0 101,102 fortyGigE1/1/1 0 40000 +Ethernet1 103,104 fortyGigE1/1/2 1 40000 +Ethernet2 97,98 fortyGigE1/1/3 2 40000 +Ethernet3 99,100 fortyGigE1/1/4 3 40000 +Ethernet4 69,70 fortyGigE1/1/5 4 40000 +Ethernet5 71,72 fortyGigE1/1/6 5 40000 +Ethernet6 65,66 fortyGigE1/1/7 6 40000 +Ethernet7 67,68 fortyGigE1/1/8 7 40000 +Ethernet8 53,54 fortyGigE1/1/9 8 40000 +Ethernet9 55,56 fortyGigE1/1/10 9 40000 +Ethernet10 49,50 fortyGigE1/1/11 10 40000 +Ethernet11 51,52 fortyGigE1/1/12 11 40000 +Ethernet12 21,22 fortyGigE1/1/13 12 40000 +Ethernet13 23,24 fortyGigE1/1/14 13 40000 +Ethernet14 17,18 fortyGigE1/1/15 14 40000 +Ethernet15 19,20 fortyGigE1/1/16 15 40000 +Ethernet16 25,26 fortyGigE1/2/1 16 40000 +Ethernet17 27,28 fortyGigE1/2/2 17 40000 +Ethernet18 29,30 fortyGigE1/2/3 18 40000 +Ethernet19 31,32 fortyGigE1/2/4 19 40000 +Ethernet20 57,58 fortyGigE1/2/5 20 40000 +Ethernet21 59,60 fortyGigE1/2/6 21 40000 +Ethernet22 61,62 fortyGigE1/2/7 22 40000 +Ethernet23 63,64 fortyGigE1/2/8 23 40000 +Ethernet24 73,74 fortyGigE1/2/9 24 40000 +Ethernet25 75,76 fortyGigE1/2/10 25 40000 +Ethernet26 77,78 fortyGigE1/2/11 26 40000 +Ethernet27 79,80 fortyGigE1/2/12 27 40000 +Ethernet28 105,106 fortyGigE1/2/13 28 40000 +Ethernet29 107,108 fortyGigE1/2/14 29 40000 +Ethernet30 109,110 fortyGigE1/2/15 30 40000 +Ethernet31 111,112 fortyGigE1/2/16 31 40000 +Ethernet32 13,14 fortyGigE1/3/1 32 40000 +Ethernet33 15,16 fortyGigE1/3/2 33 40000 +Ethernet34 9,10 fortyGigE1/3/3 34 40000 +Ethernet35 11,12 fortyGigE1/3/4 35 40000 +Ethernet36 125,126 fortyGigE1/3/5 36 40000 +Ethernet37 127,128 fortyGigE1/3/6 37 40000 +Ethernet38 121,122 fortyGigE1/3/7 38 40000 +Ethernet39 123,124 fortyGigE1/3/8 39 40000 +Ethernet40 93,94 fortyGigE1/3/9 40 40000 +Ethernet41 95,96 fortyGigE1/3/10 41 40000 +Ethernet42 89,90 fortyGigE1/3/11 42 40000 +Ethernet43 91,92 fortyGigE1/3/12 43 40000 +Ethernet44 45,46 fortyGigE1/3/13 44 40000 +Ethernet45 47,48 fortyGigE1/3/14 45 40000 +Ethernet46 41,42 fortyGigE1/3/15 46 40000 +Ethernet47 43,44 fortyGigE1/3/16 47 40000 +Ethernet48 113,114 fortyGigE1/4/1 48 40000 +Ethernet49 115,116 fortyGigE1/4/2 49 40000 +Ethernet50 117,118 fortyGigE1/4/3 50 40000 +Ethernet51 119,120 fortyGigE1/4/4 51 40000 +Ethernet52 1,2 fortyGigE1/4/5 52 40000 +Ethernet53 3,4 fortyGigE1/4/6 53 40000 +Ethernet54 5,6 fortyGigE1/4/7 54 40000 +Ethernet55 7,8 fortyGigE1/4/8 55 40000 +Ethernet56 33,34 fortyGigE1/4/9 56 40000 +Ethernet57 35,36 fortyGigE1/4/10 57 40000 +Ethernet58 37,38 fortyGigE1/4/11 58 40000 +Ethernet59 39,40 fortyGigE1/4/12 59 40000 +Ethernet60 81,82 fortyGigE1/4/13 60 40000 +Ethernet61 83,84 fortyGigE1/4/14 61 40000 +Ethernet62 85,86 fortyGigE1/4/15 62 40000 +Ethernet63 87,88 fortyGigE1/4/16 63 40000 diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/qos.json.j2 b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/sai.profile.j2 b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/sai.profile.j2 new file mode 100644 index 000000000000..df3cbb558294 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/sai.profile.j2 @@ -0,0 +1,13 @@ +{# Get sai.profile based on switch_role #} +{%- if DEVICE_METADATA is defined -%} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] -%} +{%- if switch_role.lower() == 'torrouter' %} +{% set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-s6100-64x40G-t0.config.bcm' -%} +{%- else %} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-s6100-64x40G-t1.config.bcm' -%} +{%- endif %} +{%- else %} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-s6100-64x40G-t1.config.bcm' -%} +{%- endif %} +{# Write the contents of sai_ profile_filename to sai.profile file #} +{{ sai_profile_contents }} diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/th-s6100-64x40G-t0.config.bcm b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/th-s6100-64x40G-t0.config.bcm new file mode 100644 index 000000000000..5132d448c91d --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/th-s6100-64x40G-t0.config.bcm @@ -0,0 +1,415 @@ +#TH S6100 64x40 +l3_alpm_enable=2 +pfc_deadlock_seq_control=1 +bcm_stat_interval=2000000 +bcm_num_cos=8 +switch_bypass_mode=0 +mmu_lossless=0 +lpm_scaling_enable=0 +lpm_ipv6_128b_reserved=0 +ipv6_lpm_128b_enable=1 +l2xmsg_mode=1 +oversubscribe_mode=1 + +phy_gearbox_enable=1 +phy_84752=1 +phy_ext_rom_boot=0 +rate_ext_mdio_divisor=0x80 + +serdes_fiber_pref_xe=0 +serdes_if_type_xe=14 + +fpem_mem_entries=32768 + +os=unix + +parity_correction=1 +parity_enable=1 + +port_phy_addr_66=0x176 +port_phy_addr_100=0x177 +xgxs_tx_lane_map_104=0x3210 +xgxs_rx_lane_map_104=0x0312 +phy_xaui_tx_polarity_flip_104=0x0 +phy_xaui_rx_polarity_flip_104=0x0 +port_phy_addr_104=0x1e +port_phy_addr_105=0x1e +dport_map_port_104=1 +dport_map_port_105=2 +xgxs_tx_lane_map_102=0x1032 +xgxs_rx_lane_map_102=0x0132 +phy_xaui_tx_polarity_flip_102=0x3 +phy_xaui_rx_polarity_flip_102=0x3 +phy_xaui_tx_polarity_flip_103=0x3 +phy_xaui_rx_polarity_flip_103=0x3 +port_phy_addr_102=0x1f +port_phy_addr_103=0x1f +dport_map_port_102=3 +dport_map_port_103=4 +xgxs_tx_lane_map_70=0x0123 +xgxs_rx_lane_map_70=0x3201 +phy_xaui_tx_polarity_flip_70=0x3 +phy_xaui_rx_polarity_flip_70=0x3 +phy_xaui_tx_polarity_flip_71=0x3 +phy_xaui_rx_polarity_flip_71=0x3 +port_phy_addr_70=0xE +port_phy_addr_71=0xE +dport_map_port_70=5 +dport_map_port_71=6 +xgxs_tx_lane_map_68=0x2301 +xgxs_rx_lane_map_68=0x1023 +phy_xaui_tx_polarity_flip_68=0x0 +phy_xaui_rx_polarity_flip_68=0x2 +phy_xaui_tx_polarity_flip_69=0x0 +phy_xaui_rx_polarity_flip_69=0x3 +port_phy_addr_68=0xF +port_phy_addr_69=0xF +dport_map_port_68=7 +dport_map_port_69=8 +xgxs_tx_lane_map_44=0x0123 +xgxs_rx_lane_map_44=0x3201 +phy_xaui_tx_polarity_flip_44=0x3 +phy_xaui_rx_polarity_flip_44=0x3 +phy_xaui_tx_polarity_flip_45=0x3 +phy_xaui_rx_polarity_flip_45=0x3 +port_phy_addr_44=0x3e +port_phy_addr_45=0x3e +dport_map_port_44=9 +dport_map_port_45=10 +xgxs_tx_lane_map_42=0x1032 +xgxs_rx_lane_map_42=0x2310 +phy_xaui_tx_polarity_flip_42=0x0 +phy_xaui_rx_polarity_flip_42=0x0 +phy_xaui_tx_polarity_flip_43=0x3 +phy_xaui_rx_polarity_flip_43=0x0 +port_phy_addr_42=0x3f +port_phy_addr_43=0x3f +dport_map_port_42=11 +dport_map_port_43=12 +xgxs_tx_lane_map_11=0x0123 +xgxs_rx_lane_map_11=0x3201 +phy_xaui_tx_polarity_flip_11=0x3 +phy_xaui_rx_polarity_flip_11=0x0 +phy_xaui_tx_polarity_flip_12=0x3 +phy_xaui_rx_polarity_flip_12=0x0 +port_phy_addr_11=0x2E +port_phy_addr_12=0x2E +dport_map_port_11=13 +dport_map_port_12=14 +xgxs_tx_lane_map_9=0x2310 +xgxs_rx_lane_map_9=0x1023 +phy_xaui_tx_polarity_flip_9=0x0 +phy_xaui_rx_polarity_flip_9=0x0 +phy_xaui_tx_polarity_flip_10=0x0 +phy_xaui_rx_polarity_flip_10=0x0 +port_phy_addr_9=0x2F +port_phy_addr_10=0x2F +dport_map_port_9=15 +dport_map_port_10=16 +xgxs_tx_lane_map_13=0x0123 +xgxs_rx_lane_map_13=0x0132 +phy_xaui_tx_polarity_flip_13=0x3 +phy_xaui_rx_polarity_flip_13=0x3 +phy_xaui_tx_polarity_flip_14=0x3 +phy_xaui_rx_polarity_flip_14=0x3 +port_phy_addr_13=0x11e +port_phy_addr_14=0x11e +dport_map_port_13=17 +dport_map_port_14=18 +xgxs_tx_lane_map_15=0x2301 +xgxs_rx_lane_map_15=0x2310 +phy_xaui_tx_polarity_flip_15=0x0 +phy_xaui_rx_polarity_flip_15=0x0 +port_phy_addr_15=0x11f +port_phy_addr_16=0x11f +dport_map_port_15=19 +dport_map_port_16=20 +xgxs_tx_lane_map_46=0x3210 +xgxs_rx_lane_map_46=0x0132 +phy_xaui_tx_polarity_flip_46=0x3 +phy_xaui_rx_polarity_flip_46=0x3 +phy_xaui_tx_polarity_flip_47=0x3 +phy_xaui_rx_polarity_flip_47=0x3 +port_phy_addr_46=0x10e +port_phy_addr_47=0x10e +dport_map_port_46=21 +dport_map_port_47=22 +xgxs_tx_lane_map_48=0x2301 +xgxs_rx_lane_map_48=0x1023 +phy_xaui_tx_polarity_flip_48=0x0 +phy_xaui_rx_polarity_flip_48=0x1 +port_phy_addr_48=0x10F +port_phy_addr_49=0x10F +dport_map_port_48=23 +dport_map_port_49=24 +xgxs_tx_lane_map_72=0x3210 +xgxs_rx_lane_map_72=0x0132 +phy_xaui_tx_polarity_flip_72=0x3 +phy_xaui_rx_polarity_flip_72=0x0 +phy_xaui_tx_polarity_flip_73=0x3 +phy_xaui_rx_polarity_flip_73=0x0 +port_phy_addr_72=0x13e +port_phy_addr_73=0x13e +dport_map_port_72=25 +dport_map_port_73=26 +xgxs_tx_lane_map_74=0x1320 +xgxs_rx_lane_map_74=0x2013 +phy_xaui_tx_polarity_flip_74=0x0 +phy_xaui_rx_polarity_flip_74=0x0 +phy_xaui_tx_polarity_flip_75=0x3 +phy_xaui_rx_polarity_flip_75=0x0 +port_phy_addr_74=0x13f +port_phy_addr_75=0x13f +dport_map_port_74=27 +dport_map_port_75=28 +xgxs_tx_lane_map_106=0x3210 +xgxs_rx_lane_map_106=0x2310 +phy_xaui_tx_polarity_flip_106=0x0 +phy_xaui_rx_polarity_flip_106=0x3 +phy_xaui_tx_polarity_flip_107=0x0 +phy_xaui_rx_polarity_flip_107=0x3 +port_phy_addr_106=0x12e +port_phy_addr_107=0x12e +dport_map_port_106=29 +dport_map_port_107=30 +xgxs_tx_lane_map_108=0x1032 +xgxs_rx_lane_map_108=0x0132 +phy_xaui_tx_polarity_flip_108=0x3 +phy_xaui_rx_polarity_flip_108=0x3 +phy_xaui_tx_polarity_flip_109=0x3 +phy_xaui_rx_polarity_flip_109=0x3 +port_phy_addr_108=0x12f +port_phy_addr_109=0x12f +dport_map_port_108=31 +dport_map_port_109=32 +port_phy_addr_7=0x5e +port_phy_addr_8=0x5e +xgxs_tx_lane_map_7=0x3210 +xgxs_rx_lane_map_7=0x0132 +phy_xaui_tx_polarity_flip_7=0x3 +phy_xaui_rx_polarity_flip_7=0x1 +phy_xaui_tx_polarity_flip_8=0x3 +phy_xaui_rx_polarity_flip_8=0x3 +dport_map_port_7=33 +dport_map_port_8=34 +port_phy_addr_5=0x5f +port_phy_addr_6=0x5f +xgxs_tx_lane_map_5=0x2301 +xgxs_rx_lane_map_5=0x1023 +phy_xaui_tx_polarity_flip_5=0x0 +phy_xaui_rx_polarity_flip_5=0x0 +phy_xaui_tx_polarity_flip_6=0x0 +phy_xaui_tx_polarity_flip_6=0x0 +dport_map_port_5=35 +dport_map_port_6=36 +port_phy_addr_116=0x4e +port_phy_addr_117=0x4e +phy_xaui_tx_polarity_flip_116=0x0 +phy_xaui_rx_polarity_flip_116=0x1 +phy_xaui_tx_polarity_flip_117=0x3 +phy_xaui_rx_polarity_flip_117=0x3 +xgxs_tx_lane_map_116=0x0123 +xgxs_rx_lane_map_116=0x3201 +dport_map_port_116=37 +dport_map_port_117=38 +port_phy_addr_114=0x4f +port_phy_addr_115=0x4f +phy_xaui_tx_polarity_flip_114=0x0 +phy_xaui_rx_polarity_flip_114=0x0 +phy_xaui_tx_polarity_flip_115=0x1 +phy_xaui_rx_polarity_flip_115=0x0 +xgxs_tx_lane_map_114=0x2301 +xgxs_rx_lane_map_114=0x1023 +dport_map_port_114=39 +dport_map_port_115=40 +port_phy_addr_82=0x7e +port_phy_addr_83=0x7e +xgxs_tx_lane_map_82=0x3210 +xgxs_rx_lane_map_82=0x2310 +phy_xaui_tx_polarity_flip_82=0x0 +phy_xaui_rx_polarity_flip_82=0x0 +dport_map_port_82=41 +dport_map_port_83=42 +port_phy_addr_80=0x7f +port_phy_addr_81=0x7f +xgxs_tx_lane_map_80=0x1032 +xgxs_rx_lane_map_80=0x0132 +phy_xaui_tx_polarity_flip_80=0x3 +phy_xaui_rx_polarity_flip_80=0x3 +phy_xaui_tx_polarity_flip_81=0x0 +phy_xaui_rx_polarity_flip_81=0x3 +dport_map_port_80=43 +dport_map_port_81=44 +xgxs_tx_lane_map_40=0x0123 +xgxs_rx_lane_map_40=0x0132 +port_phy_addr_40=0x6e +port_phy_addr_41=0x6e +phy_xaui_tx_polarity_flip_40=0x3 +phy_xaui_rx_polarity_flip_40=0x0 +phy_xaui_tx_polarity_flip_41=0x3 +phy_xaui_rx_polarity_flip_41=0x0 +dport_map_port_40=45 +dport_map_port_41=46 +port_phy_addr_38=0x6f +port_phy_addr_39=0x6f +phy_xaui_tx_polarity_flip_38=0x0 +phy_xaui_rx_polarity_flip_38=0x0 +xgxs_tx_lane_map_38=0x2301 +xgxs_rx_lane_map_38=0x2310 +dport_map_port_38=47 +dport_map_port_39=48 +xgxs_tx_lane_map_110=0x2013 +xgxs_rx_lane_map_110=0x3102 +phy_xaui_tx_polarity_flip_110=0x3 +phy_xaui_rx_polarity_flip_110=0x3 +phy_xaui_tx_polarity_flip_111=0x3 +phy_xaui_rx_polarity_flip_111=0x3 +port_phy_addr_110=0x15e +port_phy_addr_111=0x15e +dport_map_port_110=49 +dport_map_port_111=50 +xgxs_tx_lane_map_112=0x1032 +xgxs_rx_lane_map_112=0x2310 +phy_xaui_tx_polarity_flip_112=0x3 +phy_xaui_rx_polarity_flip_112=0x3 +phy_xaui_tx_polarity_flip_113=0x3 +phy_xaui_rx_polarity_flip_113=0x3 +port_phy_addr_112=0x15f +port_phy_addr_113=0x15f +dport_map_port_112=51 +dport_map_port_113=52 +port_phy_addr_1=0x14e +port_phy_addr_2=0x14e +xgxs_tx_lane_map_1=0x0123 +xgxs_rx_lane_map_1=0x3201 +phy_xaui_tx_polarity_flip_1=0x3 +phy_xaui_rx_polarity_flip_1=0x3 +phy_xaui_tx_polarity_flip_2=0x3 +phy_xaui_rx_polarity_flip_2=0x3 +dport_map_port_1=53 +dport_map_port_2=54 +xgxs_tx_lane_map_3=0x1023 +xgxs_rx_lane_map_3=0x2310 +port_phy_addr_3=0x14f +port_phy_addr_4=0x14f +phy_xaui_tx_polarity_flip_3=0x3 +phy_xaui_rx_polarity_flip_3=0x0 +phy_xaui_tx_polarity_flip_4=0x3 +phy_xaui_rx_polarity_flip_4=0x3 +dport_map_port_3=55 +dport_map_port_4=56 +port_phy_addr_34=0x17e +port_phy_addr_35=0x17e +xgxs_tx_lane_map_34=0x0123 +xgxs_rx_lane_map_34=0x0132 +phy_xaui_tx_polarity_flip_34=0x3 +phy_xaui_rx_polarity_flip_34=0x0 +phy_xaui_tx_polarity_flip_35=0x3 +phy_xaui_rx_polarity_flip_35=0x0 +dport_map_port_34=57 +dport_map_port_35=58 +port_phy_addr_36=0x17f +port_phy_addr_37=0x17f +xgxs_tx_lane_map_36=0x2301 +xgxs_rx_lane_map_36=0x2310 +phy_xaui_tx_polarity_flip_36=0x0 +phy_xaui_rx_polarity_flip_36=0x3 +phy_xaui_tx_polarity_flip_37=0x3 +phy_xaui_rx_polarity_flip_37=0x3 +dport_map_port_36=59 +dport_map_port_37=60 +port_phy_addr_76=0x16e +port_phy_addr_77=0x16e +xgxs_tx_lane_map_76=0x3210 +xgxs_rx_lane_map_76=0x2310 +phy_xaui_tx_polarity_flip_76=0x0 +phy_xaui_rx_polarity_flip_76=0x3 +phy_xaui_tx_polarity_flip_77=0x0 +phy_xaui_rx_polarity_flip_77=0x3 +dport_map_port_76=61 +dport_map_port_77=62 +port_phy_addr_78=0x16f +port_phy_addr_79=0x16f +xgxs_tx_lane_map_78=0x1032 +xgxs_rx_lane_map_78=0x0132 +phy_xaui_tx_polarity_flip_78=0x3 +phy_xaui_rx_polarity_flip_78=0x3 +phy_xaui_tx_polarity_flip_79=0x3 +phy_xaui_rx_polarity_flip_79=0x3 +dport_map_port_78=63 +dport_map_port_79=64 +pbmp_xport_xe=0x3fffd0000ffff40003fffc0001fffe +portmap_66=129:10 +portmap_100=131:10 +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 +portmap_1=1:40:2 +portmap_2=3:40:2 +portmap_3=5:40:2 +portmap_4=7:40:2 +portmap_5=9:40:2 +portmap_6=11:40:2 +portmap_7=13:40:2 +portmap_8=15:40:2 +portmap_9=17:40:2 +portmap_10=19:40:2 +portmap_11=21:40:2 +portmap_12=23:40:2 +portmap_13=25:40:2 +portmap_14=27:40:2 +portmap_15=29:40:2 +portmap_16=31:40:2 +portmap_34=33:40:2 +portmap_35=35:40:2 +portmap_36=37:40:2 +portmap_37=39:40:2 +portmap_38=41:40:2 +portmap_39=43:40:2 +portmap_40=45:40:2 +portmap_41=47:40:2 +portmap_42=49:40:2 +portmap_43=51:40:2 +portmap_44=53:40:2 +portmap_45=55:40:2 +portmap_46=57:40:2 +portmap_47=59:40:2 +portmap_48=61:40:2 +portmap_49=63:40:2 +portmap_68=65:40:2 +portmap_69=67:40:2 +portmap_70=69:40:2 +portmap_71=71:40:2 +portmap_72=73:40:2 +portmap_73=75:40:2 +portmap_74=77:40:2 +portmap_75=79:40:2 +portmap_76=81:40:2 +portmap_77=83:40:2 +portmap_78=85:40:2 +portmap_79=87:40:2 +portmap_80=89:40:2 +portmap_81=91:40:2 +portmap_82=93:40:2 +portmap_83=95:40:2 +portmap_102=97:40:2 +portmap_103=99:40:2 +portmap_104=101:40:2 +portmap_105=103:40:2 +portmap_106=105:40:2 +portmap_107=107:40:2 +portmap_108=109:40:2 +portmap_109=111:40:2 +portmap_110=113:40:2 +portmap_111=115:40:2 +portmap_112=117:40:2 +portmap_113=119:40:2 +portmap_114=121:40:2 +portmap_115=123:40:2 +portmap_116=125:40:2 +portmap_117=127:40:2 +dport_map_port_66=65 +dport_map_port_100=66 + +mmu_init_config="MSFT-TH-Tier0" diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/th-s6100-64x40G-t1.config.bcm b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/th-s6100-64x40G-t1.config.bcm new file mode 100644 index 000000000000..b6a4e6076a34 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/th-s6100-64x40G-t1.config.bcm @@ -0,0 +1,415 @@ +#TH S6100 64x40 +l3_alpm_enable=2 +pfc_deadlock_seq_control=1 +bcm_stat_interval=2000000 +bcm_num_cos=8 +switch_bypass_mode=0 +mmu_lossless=0 +lpm_scaling_enable=0 +lpm_ipv6_128b_reserved=0 +ipv6_lpm_128b_enable=1 +l2xmsg_mode=1 +oversubscribe_mode=1 + +phy_gearbox_enable=1 +phy_84752=1 +phy_ext_rom_boot=0 +rate_ext_mdio_divisor=0x80 + +serdes_fiber_pref_xe=0 +serdes_if_type_xe=14 + +fpem_mem_entries=32768 + +os=unix + +parity_correction=1 +parity_enable=1 + +port_phy_addr_66=0x176 +port_phy_addr_100=0x177 +xgxs_tx_lane_map_104=0x3210 +xgxs_rx_lane_map_104=0x0312 +phy_xaui_tx_polarity_flip_104=0x0 +phy_xaui_rx_polarity_flip_104=0x0 +port_phy_addr_104=0x1e +port_phy_addr_105=0x1e +dport_map_port_104=1 +dport_map_port_105=2 +xgxs_tx_lane_map_102=0x1032 +xgxs_rx_lane_map_102=0x0132 +phy_xaui_tx_polarity_flip_102=0x3 +phy_xaui_rx_polarity_flip_102=0x3 +phy_xaui_tx_polarity_flip_103=0x3 +phy_xaui_rx_polarity_flip_103=0x3 +port_phy_addr_102=0x1f +port_phy_addr_103=0x1f +dport_map_port_102=3 +dport_map_port_103=4 +xgxs_tx_lane_map_70=0x0123 +xgxs_rx_lane_map_70=0x3201 +phy_xaui_tx_polarity_flip_70=0x3 +phy_xaui_rx_polarity_flip_70=0x3 +phy_xaui_tx_polarity_flip_71=0x3 +phy_xaui_rx_polarity_flip_71=0x3 +port_phy_addr_70=0xE +port_phy_addr_71=0xE +dport_map_port_70=5 +dport_map_port_71=6 +xgxs_tx_lane_map_68=0x2301 +xgxs_rx_lane_map_68=0x1023 +phy_xaui_tx_polarity_flip_68=0x0 +phy_xaui_rx_polarity_flip_68=0x2 +phy_xaui_tx_polarity_flip_69=0x0 +phy_xaui_rx_polarity_flip_69=0x3 +port_phy_addr_68=0xF +port_phy_addr_69=0xF +dport_map_port_68=7 +dport_map_port_69=8 +xgxs_tx_lane_map_44=0x0123 +xgxs_rx_lane_map_44=0x3201 +phy_xaui_tx_polarity_flip_44=0x3 +phy_xaui_rx_polarity_flip_44=0x3 +phy_xaui_tx_polarity_flip_45=0x3 +phy_xaui_rx_polarity_flip_45=0x3 +port_phy_addr_44=0x3e +port_phy_addr_45=0x3e +dport_map_port_44=9 +dport_map_port_45=10 +xgxs_tx_lane_map_42=0x1032 +xgxs_rx_lane_map_42=0x2310 +phy_xaui_tx_polarity_flip_42=0x0 +phy_xaui_rx_polarity_flip_42=0x0 +phy_xaui_tx_polarity_flip_43=0x3 +phy_xaui_rx_polarity_flip_43=0x0 +port_phy_addr_42=0x3f +port_phy_addr_43=0x3f +dport_map_port_42=11 +dport_map_port_43=12 +xgxs_tx_lane_map_11=0x0123 +xgxs_rx_lane_map_11=0x3201 +phy_xaui_tx_polarity_flip_11=0x3 +phy_xaui_rx_polarity_flip_11=0x0 +phy_xaui_tx_polarity_flip_12=0x3 +phy_xaui_rx_polarity_flip_12=0x0 +port_phy_addr_11=0x2E +port_phy_addr_12=0x2E +dport_map_port_11=13 +dport_map_port_12=14 +xgxs_tx_lane_map_9=0x2310 +xgxs_rx_lane_map_9=0x1023 +phy_xaui_tx_polarity_flip_9=0x0 +phy_xaui_rx_polarity_flip_9=0x0 +phy_xaui_tx_polarity_flip_10=0x0 +phy_xaui_rx_polarity_flip_10=0x0 +port_phy_addr_9=0x2F +port_phy_addr_10=0x2F +dport_map_port_9=15 +dport_map_port_10=16 +xgxs_tx_lane_map_13=0x0123 +xgxs_rx_lane_map_13=0x0132 +phy_xaui_tx_polarity_flip_13=0x3 +phy_xaui_rx_polarity_flip_13=0x3 +phy_xaui_tx_polarity_flip_14=0x3 +phy_xaui_rx_polarity_flip_14=0x3 +port_phy_addr_13=0x11e +port_phy_addr_14=0x11e +dport_map_port_13=17 +dport_map_port_14=18 +xgxs_tx_lane_map_15=0x2301 +xgxs_rx_lane_map_15=0x2310 +phy_xaui_tx_polarity_flip_15=0x0 +phy_xaui_rx_polarity_flip_15=0x0 +port_phy_addr_15=0x11f +port_phy_addr_16=0x11f +dport_map_port_15=19 +dport_map_port_16=20 +xgxs_tx_lane_map_46=0x3210 +xgxs_rx_lane_map_46=0x0132 +phy_xaui_tx_polarity_flip_46=0x3 +phy_xaui_rx_polarity_flip_46=0x3 +phy_xaui_tx_polarity_flip_47=0x3 +phy_xaui_rx_polarity_flip_47=0x3 +port_phy_addr_46=0x10e +port_phy_addr_47=0x10e +dport_map_port_46=21 +dport_map_port_47=22 +xgxs_tx_lane_map_48=0x2301 +xgxs_rx_lane_map_48=0x1023 +phy_xaui_tx_polarity_flip_48=0x0 +phy_xaui_rx_polarity_flip_48=0x1 +port_phy_addr_48=0x10F +port_phy_addr_49=0x10F +dport_map_port_48=23 +dport_map_port_49=24 +xgxs_tx_lane_map_72=0x3210 +xgxs_rx_lane_map_72=0x0132 +phy_xaui_tx_polarity_flip_72=0x3 +phy_xaui_rx_polarity_flip_72=0x0 +phy_xaui_tx_polarity_flip_73=0x3 +phy_xaui_rx_polarity_flip_73=0x0 +port_phy_addr_72=0x13e +port_phy_addr_73=0x13e +dport_map_port_72=25 +dport_map_port_73=26 +xgxs_tx_lane_map_74=0x1320 +xgxs_rx_lane_map_74=0x2013 +phy_xaui_tx_polarity_flip_74=0x0 +phy_xaui_rx_polarity_flip_74=0x0 +phy_xaui_tx_polarity_flip_75=0x3 +phy_xaui_rx_polarity_flip_75=0x0 +port_phy_addr_74=0x13f +port_phy_addr_75=0x13f +dport_map_port_74=27 +dport_map_port_75=28 +xgxs_tx_lane_map_106=0x3210 +xgxs_rx_lane_map_106=0x2310 +phy_xaui_tx_polarity_flip_106=0x0 +phy_xaui_rx_polarity_flip_106=0x3 +phy_xaui_tx_polarity_flip_107=0x0 +phy_xaui_rx_polarity_flip_107=0x3 +port_phy_addr_106=0x12e +port_phy_addr_107=0x12e +dport_map_port_106=29 +dport_map_port_107=30 +xgxs_tx_lane_map_108=0x1032 +xgxs_rx_lane_map_108=0x0132 +phy_xaui_tx_polarity_flip_108=0x3 +phy_xaui_rx_polarity_flip_108=0x3 +phy_xaui_tx_polarity_flip_109=0x3 +phy_xaui_rx_polarity_flip_109=0x3 +port_phy_addr_108=0x12f +port_phy_addr_109=0x12f +dport_map_port_108=31 +dport_map_port_109=32 +port_phy_addr_7=0x5e +port_phy_addr_8=0x5e +xgxs_tx_lane_map_7=0x3210 +xgxs_rx_lane_map_7=0x0132 +phy_xaui_tx_polarity_flip_7=0x3 +phy_xaui_rx_polarity_flip_7=0x1 +phy_xaui_tx_polarity_flip_8=0x3 +phy_xaui_rx_polarity_flip_8=0x3 +dport_map_port_7=33 +dport_map_port_8=34 +port_phy_addr_5=0x5f +port_phy_addr_6=0x5f +xgxs_tx_lane_map_5=0x2301 +xgxs_rx_lane_map_5=0x1023 +phy_xaui_tx_polarity_flip_5=0x0 +phy_xaui_rx_polarity_flip_5=0x0 +phy_xaui_tx_polarity_flip_6=0x0 +phy_xaui_tx_polarity_flip_6=0x0 +dport_map_port_5=35 +dport_map_port_6=36 +port_phy_addr_116=0x4e +port_phy_addr_117=0x4e +phy_xaui_tx_polarity_flip_116=0x0 +phy_xaui_rx_polarity_flip_116=0x1 +phy_xaui_tx_polarity_flip_117=0x3 +phy_xaui_rx_polarity_flip_117=0x3 +xgxs_tx_lane_map_116=0x0123 +xgxs_rx_lane_map_116=0x3201 +dport_map_port_116=37 +dport_map_port_117=38 +port_phy_addr_114=0x4f +port_phy_addr_115=0x4f +phy_xaui_tx_polarity_flip_114=0x0 +phy_xaui_rx_polarity_flip_114=0x0 +phy_xaui_tx_polarity_flip_115=0x1 +phy_xaui_rx_polarity_flip_115=0x0 +xgxs_tx_lane_map_114=0x2301 +xgxs_rx_lane_map_114=0x1023 +dport_map_port_114=39 +dport_map_port_115=40 +port_phy_addr_82=0x7e +port_phy_addr_83=0x7e +xgxs_tx_lane_map_82=0x3210 +xgxs_rx_lane_map_82=0x2310 +phy_xaui_tx_polarity_flip_82=0x0 +phy_xaui_rx_polarity_flip_82=0x0 +dport_map_port_82=41 +dport_map_port_83=42 +port_phy_addr_80=0x7f +port_phy_addr_81=0x7f +xgxs_tx_lane_map_80=0x1032 +xgxs_rx_lane_map_80=0x0132 +phy_xaui_tx_polarity_flip_80=0x3 +phy_xaui_rx_polarity_flip_80=0x3 +phy_xaui_tx_polarity_flip_81=0x0 +phy_xaui_rx_polarity_flip_81=0x3 +dport_map_port_80=43 +dport_map_port_81=44 +xgxs_tx_lane_map_40=0x0123 +xgxs_rx_lane_map_40=0x0132 +port_phy_addr_40=0x6e +port_phy_addr_41=0x6e +phy_xaui_tx_polarity_flip_40=0x3 +phy_xaui_rx_polarity_flip_40=0x0 +phy_xaui_tx_polarity_flip_41=0x3 +phy_xaui_rx_polarity_flip_41=0x0 +dport_map_port_40=45 +dport_map_port_41=46 +port_phy_addr_38=0x6f +port_phy_addr_39=0x6f +phy_xaui_tx_polarity_flip_38=0x0 +phy_xaui_rx_polarity_flip_38=0x0 +xgxs_tx_lane_map_38=0x2301 +xgxs_rx_lane_map_38=0x2310 +dport_map_port_38=47 +dport_map_port_39=48 +xgxs_tx_lane_map_110=0x2013 +xgxs_rx_lane_map_110=0x3102 +phy_xaui_tx_polarity_flip_110=0x3 +phy_xaui_rx_polarity_flip_110=0x3 +phy_xaui_tx_polarity_flip_111=0x3 +phy_xaui_rx_polarity_flip_111=0x3 +port_phy_addr_110=0x15e +port_phy_addr_111=0x15e +dport_map_port_110=49 +dport_map_port_111=50 +xgxs_tx_lane_map_112=0x1032 +xgxs_rx_lane_map_112=0x2310 +phy_xaui_tx_polarity_flip_112=0x3 +phy_xaui_rx_polarity_flip_112=0x3 +phy_xaui_tx_polarity_flip_113=0x3 +phy_xaui_rx_polarity_flip_113=0x3 +port_phy_addr_112=0x15f +port_phy_addr_113=0x15f +dport_map_port_112=51 +dport_map_port_113=52 +port_phy_addr_1=0x14e +port_phy_addr_2=0x14e +xgxs_tx_lane_map_1=0x0123 +xgxs_rx_lane_map_1=0x3201 +phy_xaui_tx_polarity_flip_1=0x3 +phy_xaui_rx_polarity_flip_1=0x3 +phy_xaui_tx_polarity_flip_2=0x3 +phy_xaui_rx_polarity_flip_2=0x3 +dport_map_port_1=53 +dport_map_port_2=54 +xgxs_tx_lane_map_3=0x1023 +xgxs_rx_lane_map_3=0x2310 +port_phy_addr_3=0x14f +port_phy_addr_4=0x14f +phy_xaui_tx_polarity_flip_3=0x3 +phy_xaui_rx_polarity_flip_3=0x0 +phy_xaui_tx_polarity_flip_4=0x3 +phy_xaui_rx_polarity_flip_4=0x3 +dport_map_port_3=55 +dport_map_port_4=56 +port_phy_addr_34=0x17e +port_phy_addr_35=0x17e +xgxs_tx_lane_map_34=0x0123 +xgxs_rx_lane_map_34=0x0132 +phy_xaui_tx_polarity_flip_34=0x3 +phy_xaui_rx_polarity_flip_34=0x0 +phy_xaui_tx_polarity_flip_35=0x3 +phy_xaui_rx_polarity_flip_35=0x0 +dport_map_port_34=57 +dport_map_port_35=58 +port_phy_addr_36=0x17f +port_phy_addr_37=0x17f +xgxs_tx_lane_map_36=0x2301 +xgxs_rx_lane_map_36=0x2310 +phy_xaui_tx_polarity_flip_36=0x0 +phy_xaui_rx_polarity_flip_36=0x3 +phy_xaui_tx_polarity_flip_37=0x3 +phy_xaui_rx_polarity_flip_37=0x3 +dport_map_port_36=59 +dport_map_port_37=60 +port_phy_addr_76=0x16e +port_phy_addr_77=0x16e +xgxs_tx_lane_map_76=0x3210 +xgxs_rx_lane_map_76=0x2310 +phy_xaui_tx_polarity_flip_76=0x0 +phy_xaui_rx_polarity_flip_76=0x3 +phy_xaui_tx_polarity_flip_77=0x0 +phy_xaui_rx_polarity_flip_77=0x3 +dport_map_port_76=61 +dport_map_port_77=62 +port_phy_addr_78=0x16f +port_phy_addr_79=0x16f +xgxs_tx_lane_map_78=0x1032 +xgxs_rx_lane_map_78=0x0132 +phy_xaui_tx_polarity_flip_78=0x3 +phy_xaui_rx_polarity_flip_78=0x3 +phy_xaui_tx_polarity_flip_79=0x3 +phy_xaui_rx_polarity_flip_79=0x3 +dport_map_port_78=63 +dport_map_port_79=64 +pbmp_xport_xe=0x3fffd0000ffff40003fffc0001fffe +portmap_66=129:10 +portmap_100=131:10 +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 +portmap_1=1:40:2 +portmap_2=3:40:2 +portmap_3=5:40:2 +portmap_4=7:40:2 +portmap_5=9:40:2 +portmap_6=11:40:2 +portmap_7=13:40:2 +portmap_8=15:40:2 +portmap_9=17:40:2 +portmap_10=19:40:2 +portmap_11=21:40:2 +portmap_12=23:40:2 +portmap_13=25:40:2 +portmap_14=27:40:2 +portmap_15=29:40:2 +portmap_16=31:40:2 +portmap_34=33:40:2 +portmap_35=35:40:2 +portmap_36=37:40:2 +portmap_37=39:40:2 +portmap_38=41:40:2 +portmap_39=43:40:2 +portmap_40=45:40:2 +portmap_41=47:40:2 +portmap_42=49:40:2 +portmap_43=51:40:2 +portmap_44=53:40:2 +portmap_45=55:40:2 +portmap_46=57:40:2 +portmap_47=59:40:2 +portmap_48=61:40:2 +portmap_49=63:40:2 +portmap_68=65:40:2 +portmap_69=67:40:2 +portmap_70=69:40:2 +portmap_71=71:40:2 +portmap_72=73:40:2 +portmap_73=75:40:2 +portmap_74=77:40:2 +portmap_75=79:40:2 +portmap_76=81:40:2 +portmap_77=83:40:2 +portmap_78=85:40:2 +portmap_79=87:40:2 +portmap_80=89:40:2 +portmap_81=91:40:2 +portmap_82=93:40:2 +portmap_83=95:40:2 +portmap_102=97:40:2 +portmap_103=99:40:2 +portmap_104=101:40:2 +portmap_105=103:40:2 +portmap_106=105:40:2 +portmap_107=107:40:2 +portmap_108=109:40:2 +portmap_109=111:40:2 +portmap_110=113:40:2 +portmap_111=115:40:2 +portmap_112=117:40:2 +portmap_113=119:40:2 +portmap_114=121:40:2 +portmap_115=123:40:2 +portmap_116=125:40:2 +portmap_117=127:40:2 +dport_map_port_66=65 +dport_map_port_100=66 + +mmu_init_config="MSFT-TH-Tier1" diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/default_sku b/device/dell/x86_64-dell_s6100_c2538-r0/default_sku new file mode 100644 index 000000000000..0ab292005678 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/default_sku @@ -0,0 +1 @@ +Force10-S6100 t1 diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/installer.conf b/device/dell/x86_64-dell_s6100_c2538-r0/installer.conf new file mode 100644 index 000000000000..0a9a3a639eb2 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="module_blacklist=gpio_ich" diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/led_proc_init.soc b/device/dell/x86_64-dell_s6100_c2538-r0/led_proc_init.soc new file mode 100644 index 000000000000..a4a44f15bcf1 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/led_proc_init.soc @@ -0,0 +1,13 @@ +# LED microprocessor initialization for Dell S6100 + +led 0 stop +led 0 prog 02 00 60 FE 2E FE 67 2C 86 FE 67 5B 67 5B 67 5B 86 FE 2E FE 67 2C 86 FE 86 FE 06 FE D2 40 71 04 12 FF 85 05 D2 05 71 2A 52 00 3A A0 32 08 97 71 33 77 5B 32 00 32 01 B7 97 75 42 12 BC FE FE 02 0A 50 12 BC FE FE 95 75 4C 85 77 54 16 FF DA 02 71 5B 77 54 22 0E 87 22 0E 87 57 22 0F 87 22 0F 87 57 22 0F 87 22 0E 87 57 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 02 00 60 FE 2E FE 67 2C 86 FE 67 5B 67 5B 67 5B 86 FE 2E FE 67 2C 86 FE 86 FE 06 FE D2 40 71 04 12 FF 85 05 D2 05 71 2A 52 00 3A A0 32 08 97 71 33 77 5B 32 00 32 01 B7 97 75 42 12 BC FE FE 02 0A 50 12 BC FE FE 95 75 4C 85 77 54 16 FF DA 02 71 5B 77 54 22 0E 87 22 0E 87 57 22 0F 87 22 0F 87 57 22 0F 87 22 0E 87 57 +led 1 auto on +led 1 start + +led 2 stop diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/plugins/eeprom.py b/device/dell/x86_64-dell_s6100_c2538-r0/plugins/eeprom.py new file mode 100644 index 000000000000..7265b90efb1f --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/plugins/eeprom.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python + +############################################################################# +# Dell S6100 +# +# 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-2/2-0050/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) + + def serial_number_str(self, e): + """Return service tag instead of serial number""" + + (is_valid, results) = self.get_tlv_field(e, self._TLV_CODE_SERVICE_TAG) + if is_valid == False: + return "Bad service tag" + + # 'results' is a list containing 3 elements, type (int), length (int), + # and value (string) of the requested TLV + return results[2] diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/plugins/psuutil.py b/device/dell/x86_64-dell_s6100_c2538-r0/plugins/psuutil.py new file mode 100644 index 000000000000..2f3673801526 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/plugins/psuutil.py @@ -0,0 +1,82 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" +HWMON_NODE = os.listdir(HWMON_DIR)[0] + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + # Get a mailbox register + def get_pmc_register(self, reg_name): + mailbox_dir = HWMON_DIR + HWMON_NODE + retval = 'ERR' + mb_reg_file = mailbox_dir+'/' + reg_name + if (not os.path.isfile(mb_reg_file)): + logging.error(mb_reg_file, "not found !") + return retval + + try: + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", mb_reg_file, "file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + S6100_MAX_PSUS = 2 + return S6100_MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + psu_status = self.get_pmc_register('psu'+str(index)+'_presence') + if (psu_status != 'ERR'): + psu_status = int(psu_status, 16) + # Check for PSU statuse + if (~psu_status & 0b1000) or (psu_status & 0b0100): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_presence = self.get_pmc_register('psu'+str(index)+'_presence') + if (psu_presence != 'ERR'): + psu_presence = int(psu_presence, 16) + # Check for PSU presence + if (~psu_presence & 0b1): + status = 1 + + return status 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 new file mode 100644 index 000000000000..04723b109a55 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/plugins/sfputil.py @@ -0,0 +1,607 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# +# +-i2c----+--------+ +# | 6 | 7 | +# | +-------------+ | +# | |IOM1 | IOM3 | | +# | |IOM2 | IOM4 | | +# | +-------------+ | +# | 8 | 9 | +# +--------+--------+ + + +try: + import time + import os + import logging + import select + 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/" + OIR_FD_PATH = "/sys/devices/platform/dell_ich.0/sci_int_gpio_sus6" + + oir_fd = -1 + epoll = -1 + + @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" + + self.oir_fd = open(self.OIR_FD_PATH, "r") + self.epoll = select.epoll() + if self.oir_fd != -1: + self.epoll.register(self.oir_fd.fileno(), select.EPOLLIN) + + SfpUtilBase.__init__(self) + + def __del__(self): + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + + 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 + + # 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 + + def get_register(self, reg_file): + retval = 'ERR' + + if (not os.path.isfile(reg_file)): + print reg_file, 'not found !' + return retval + + try: + with open(reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", reg_file, "file !") + + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + + def check_interrupts(self, port_dict): + retval = 0 + is_port_dict_updated = False + + # Read the QSFP ABS interrupt & status registers + cpld2_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_int") + cpld2_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_sta") + cpld3_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_int") + cpld3_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_sta") + cpld4_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_int") + cpld4_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_sta") + cpld5_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-17/17-003e/qsfp_abs_int") + cpld5_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-17/17-003e/qsfp_abs_sta") + + if (cpld2_abs_int == 'ERR' or cpld2_abs_sta == 'ERR' or + cpld3_abs_int == 'ERR' or cpld3_abs_sta == 'ERR' or + cpld4_abs_int == 'ERR' or cpld4_abs_sta == 'ERR' or + cpld5_abs_int == 'ERR' or cpld5_abs_sta == 'ERR'): + return -1 + + # If IOM is not present, interrupt will return 'read error' + # Handle the scenario gracefully + if (cpld2_abs_int == 'read error'): + cpld2_abs_int = "0x0" + cpld2_abs_sta = "0x0" + if (cpld3_abs_int == 'read error'): + cpld3_abs_int = "0x0" + cpld3_abs_sta = "0x0" + if (cpld4_abs_int == 'read error'): + cpld4_abs_int = "0x0" + cpld4_abs_sta = "0x0" + if (cpld5_abs_int == 'read error'): + cpld5_abs_int = "0x0" + cpld5_abs_sta = "0x0" + + cpld2_abs_int = int(cpld2_abs_int, 16) + cpld2_abs_sta = int(cpld2_abs_sta, 16) + cpld3_abs_int = int(cpld3_abs_int, 16) + cpld3_abs_sta = int(cpld3_abs_sta, 16) + cpld4_abs_int = int(cpld4_abs_int, 16) + cpld4_abs_sta = int(cpld4_abs_sta, 16) + cpld5_abs_int = int(cpld5_abs_int, 16) + cpld5_abs_sta = int(cpld5_abs_sta, 16) + + # Make it contiguous + interrupt_reg = (cpld2_abs_int & 0xffff) | \ + ((cpld4_abs_int & 0xffff) << 16) | \ + ((cpld3_abs_int & 0xffff) << 32) | \ + ((cpld5_abs_int & 0xffff) << 48) + status_reg = (cpld2_abs_sta & 0xffff) | \ + ((cpld4_abs_sta & 0xffff) << 16) | \ + ((cpld3_abs_sta & 0xffff) << 32) | \ + ((cpld5_abs_sta & 0xffff) << 48) + + port = self.port_start + while port <= self.port_end: + if interrupt_reg & (1 << port): + # update only if atleast one port has generated + # interrupt + is_port_dict_updated = True + if status_reg & (1 << port): + # status reg 1 => optics is removed + port_dict[port] = '0' + else: + # status reg 0 => optics is inserted + port_dict[port] = '1' + port += 1 + return retval, is_port_dict_updated + + def get_transceiver_change_event(self, timeout=0): + port_dict = {} + try: + # We get notified when there is an SCI interrupt from GPIO SUS6 + # Check for missed interrupts by invoking self.check_interrupts + # it will update the port_dict. + # Then poll for new xcvr insertion/removal and + # call self.check_interrupts again and return + retval, is_port_dict_updated = self.check_interrupts(port_dict) + if ((retval == 0) and (is_port_dict_updated is True)): + return True, port_dict + + # Block until an xcvr is inserted or removed with timeout = -1 + events = self.epoll.poll( + timeout=timeout if timeout != 0 else -1) + if events: + # check interrupts and return the port_dict + retval, is_port_dict_updated = \ + self.check_interrupts(port_dict) + if (retval != 0): + return False, {} + return True, port_dict + except: + return False, {} + + return False, {} + diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/sensors.conf b/device/dell/x86_64-dell_s6100_c2538-r0/sensors.conf new file mode 100644 index 000000000000..43fa7357c177 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/sensors.conf @@ -0,0 +1,9 @@ +chip "SMF_S6100_ON-isa-0000" +label power1 "PSU1 Input Power" +label power2 "PSU1 Output Power" +label power3 "PSU2 Input Power" +label power4 "PSU2 Output Power" +label temp14 "PSU1 Temp" +label temp15 "PSU1 Temp" +ignore temp12 +ignore temp13 diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/buffers.json.j2 b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/buffers_defaults_t1.j2 b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..5c654ab9e8a1 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/buffers_defaults_t1.j2 @@ -0,0 +1,47 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,32) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx*4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10443264", + "type": "ingress", + "mode": "dynamic", + "xoff": "4625920" + }, + "egress_lossy_pool": { + "size": "8877440", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"3995680" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/pg_profile_lookup.ini b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/pg_profile_lookup.ini new file mode 100644 index 000000000000..aedda37a8878 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -3 2288 + 25000 5m 1248 2288 53248 -3 2288 + 40000 5m 1248 2288 66560 -3 2288 + 50000 5m 1248 2288 90272 -3 2288 + 100000 5m 1248 2288 165568 -3 2288 + 10000 40m 1248 2288 37024 -3 2288 + 25000 40m 1248 2288 53248 -3 2288 + 40000 40m 1248 2288 71552 -3 2288 + 50000 40m 1248 2288 96096 -3 2288 + 100000 40m 1248 2288 177632 -3 2288 + 10000 300m 1248 2288 46176 -3 2288 + 25000 300m 1248 2288 79040 -3 2288 + 40000 300m 1248 2288 108160 -3 2288 + 50000 300m 1248 2288 141856 -3 2288 + 100000 300m 1248 2288 268736 -3 2288 diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/port_config.ini b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/port_config.ini new file mode 100644 index 000000000000..e000f29bef38 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 49,50,51,52 hundredGigE1/1 +Ethernet4 53,54,55,56 hundredGigE1/2 +Ethernet8 57,58,59,60 hundredGigE1/3 +Ethernet12 61,62,63,64 hundredGigE1/4 +Ethernet16 65,66,67,68 hundredGigE1/5 +Ethernet20 69,70,71,72 hundredGigE1/6 +Ethernet24 73,74,75,76 hundredGigE1/7 +Ethernet28 77,78,79,80 hundredGigE1/8 +Ethernet32 37,38,39,40 hundredGigE1/9 +Ethernet36 33,34,35,36 hundredGigE1/10 +Ethernet40 45,46,47,48 hundredGigE1/11 +Ethernet44 41,42,43,44 hundredGigE1/12 +Ethernet48 81,82,83,84 hundredGigE1/13 +Ethernet52 85,86,87,88 hundredGigE1/14 +Ethernet56 89,90,91,92 hundredGigE1/15 +Ethernet60 93,94,95,96 hundredGigE1/16 +Ethernet64 97,98,99,100 hundredGigE1/17 +Ethernet68 101,102,103,104 hundredGigE1/18 +Ethernet72 105,106,107,108 hundredGigE1/19 +Ethernet76 109,110,111,112 hundredGigE1/20 +Ethernet80 21,22,23,24 hundredGigE1/21 +Ethernet84 17,18,19,20 hundredGigE1/22 +Ethernet88 29,30,31,32 hundredGigE1/23 +Ethernet92 25,26,27,28 hundredGigE1/24 +Ethernet96 117,118,119,120 hundredGigE1/25 +Ethernet100 113,114,115,116 hundredGigE1/26 +Ethernet104 125,126,127,128 hundredGigE1/27 +Ethernet108 121,122,123,124 hundredGigE1/28 +Ethernet112 5,6,7,8 hundredGigE1/29 +Ethernet116 1,2,3,4 hundredGigE1/30 +Ethernet120 13,14,15,16 hundredGigE1/31 +Ethernet124 9,10,11,12 hundredGigE1/32 diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/qos.json.j2 b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/sai.profile b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/sai.profile new file mode 100644 index 000000000000..a690c3ff8b94 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-z9100-32x100G.config.bcm diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/th-z9100-32x100G.config.bcm b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/th-z9100-32x100G.config.bcm new file mode 100644 index 000000000000..25aefca2dafa --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/th-z9100-32x100G.config.bcm @@ -0,0 +1,232 @@ +#TH Z9100 32x100 + +l3_alpm_enable=2 +pfc_deadlock_seq_control=1 +bcm_stat_interval=2000000 +bcm_num_cos=8 +switch_bypass_mode=0 +mmu_lossless=0 +lpm_scaling_enable=0 +lpm_scaling_enable=0 +lpm_ipv6_128b_reserved=0 +ipv6_lpm_128b_enable=1 +l2xmsg_mode=1 +oversubscribe_mode=1 +os=unix + +pbmp_oversubscribe=0x3fd000000ff4000003fc000001fe +pbmp_xport_xe=0x3fd000000ff4000003fc000001fe + +serdes_if_type_xe=14 +serdes_if_type_ce=14 + +#Parity +parity_correction=1 +parity_enable=1 + +#Port configuration +portmap_38=49:100 +portmap_39=53:100 +portmap_40=57:100 +portmap_41=61:100 +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_35=37:100 +portmap_34=33:100 +portmap_37=45:100 +portmap_36=41:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_6=21:100 +portmap_5=17:100 +portmap_8=29:100 +portmap_7=25:100 +portmap_107=117:100 +portmap_106=113:100 +portmap_109=125:100 +portmap_108=121:100 +portmap_2=5:100 +portmap_1=1:100 +portmap_4=13:100 +portmap_3=9:100 +portmap_66=129:10 +portmap_100=131:10 +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +xgxs_tx_lane_map_ce0=0x0132 +xgxs_tx_lane_map_ce1=0x2301 +xgxs_tx_lane_map_ce2=0x0123 +xgxs_tx_lane_map_ce3=0x3201 +xgxs_tx_lane_map_ce4=0x3210 +xgxs_tx_lane_map_ce5=0x2301 +xgxs_tx_lane_map_ce6=0x0123 +xgxs_tx_lane_map_ce7=0x1320 +xgxs_tx_lane_map_ce8=0x1032 +xgxs_tx_lane_map_ce9=0x2031 +xgxs_tx_lane_map_ce10=0x1023 +xgxs_tx_lane_map_ce11=0x0132 +xgxs_tx_lane_map_ce12=0x0213 +xgxs_tx_lane_map_ce13=0x1032 +xgxs_tx_lane_map_ce14=0x0132 +xgxs_tx_lane_map_ce15=0x0123 +xgxs_tx_lane_map_ce16=0x0123 +xgxs_tx_lane_map_ce17=0x0123 +xgxs_tx_lane_map_ce18=0x1032 +xgxs_tx_lane_map_ce19=0x0123 +xgxs_tx_lane_map_ce20=0x2301 +xgxs_tx_lane_map_ce21=0x3102 +xgxs_tx_lane_map_ce22=0x1023 +xgxs_tx_lane_map_ce23=0x2130 +xgxs_tx_lane_map_ce24=0x2310 +xgxs_tx_lane_map_ce25=0x2013 +xgxs_tx_lane_map_ce26=0x0132 +xgxs_tx_lane_map_ce27=0x0123 +xgxs_tx_lane_map_ce28=0x0213 +xgxs_tx_lane_map_ce29=0x0123 +xgxs_tx_lane_map_ce30=0x2301 +xgxs_tx_lane_map_ce31=0x0123 + +xgxs_rx_lane_map_ce0=0x1023 +xgxs_rx_lane_map_ce1=0x1302 +xgxs_rx_lane_map_ce2=0x1203 +xgxs_rx_lane_map_ce3=0x1302 +xgxs_rx_lane_map_ce4=0x3201 +xgxs_rx_lane_map_ce5=0x1302 +xgxs_rx_lane_map_ce6=0x1203 +xgxs_rx_lane_map_ce7=0x2301 +xgxs_rx_lane_map_ce8=0x0312 +xgxs_rx_lane_map_ce9=0x1302 +xgxs_rx_lane_map_ce10=0x2103 +xgxs_rx_lane_map_ce11=0x3210 +xgxs_rx_lane_map_ce12=0x2301 +xgxs_rx_lane_map_ce13=0x0213 +xgxs_rx_lane_map_ce14=0x3210 +xgxs_rx_lane_map_ce15=0x3210 +xgxs_rx_lane_map_ce16=0x3201 +xgxs_rx_lane_map_ce17=0x0213 +xgxs_rx_lane_map_ce18=0x3210 +xgxs_rx_lane_map_ce19=0x3210 +xgxs_rx_lane_map_ce20=0x3102 +xgxs_rx_lane_map_ce21=0x2103 +xgxs_rx_lane_map_ce22=0x2301 +xgxs_rx_lane_map_ce23=0x2310 +xgxs_rx_lane_map_ce24=0x3201 +xgxs_rx_lane_map_ce25=0x0123 +xgxs_rx_lane_map_ce26=0x1023 +xgxs_rx_lane_map_ce27=0x0213 +xgxs_rx_lane_map_ce28=0x1203 +xgxs_rx_lane_map_ce29=0x0213 +xgxs_rx_lane_map_ce30=0x3201 +xgxs_rx_lane_map_ce31=0x0213 + +phy_xaui_tx_polarity_flip_ce0=0xe +phy_xaui_tx_polarity_flip_ce1=0x2 +phy_xaui_tx_polarity_flip_ce2=0xa +phy_xaui_tx_polarity_flip_ce3=0xb +phy_xaui_tx_polarity_flip_ce4=0x2 +phy_xaui_tx_polarity_flip_ce5=0x0 +phy_xaui_tx_polarity_flip_ce6=0x0 +phy_xaui_tx_polarity_flip_ce7=0xa +phy_xaui_tx_polarity_flip_ce8=0x0 +phy_xaui_tx_polarity_flip_ce9=0xb +phy_xaui_tx_polarity_flip_ce10=0xe +phy_xaui_tx_polarity_flip_ce11=0x6 +phy_xaui_tx_polarity_flip_ce12=0x6 +phy_xaui_tx_polarity_flip_ce13=0xf +phy_xaui_tx_polarity_flip_ce14=0x5 +phy_xaui_tx_polarity_flip_ce15=0x8 +phy_xaui_tx_polarity_flip_ce16=0xf +phy_xaui_tx_polarity_flip_ce17=0xf +phy_xaui_tx_polarity_flip_ce18=0xf +phy_xaui_tx_polarity_flip_ce19=0xf +phy_xaui_tx_polarity_flip_ce20=0xf +phy_xaui_tx_polarity_flip_ce21=0xf +phy_xaui_tx_polarity_flip_ce22=0xb +phy_xaui_tx_polarity_flip_ce23=0xa +phy_xaui_tx_polarity_flip_ce24=0xf +phy_xaui_tx_polarity_flip_ce25=0x0 +phy_xaui_tx_polarity_flip_ce26=0xb +phy_xaui_tx_polarity_flip_ce27=0x7 +phy_xaui_tx_polarity_flip_ce28=0x8 +phy_xaui_tx_polarity_flip_ce29=0x3 +phy_xaui_tx_polarity_flip_ce30=0xc +phy_xaui_tx_polarity_flip_ce31=0x3 + +phy_xaui_rx_polarity_flip_ce0=0xc +phy_xaui_rx_polarity_flip_ce1=0xd +phy_xaui_rx_polarity_flip_ce2=0x2 +phy_xaui_rx_polarity_flip_ce3=0xf +phy_xaui_rx_polarity_flip_ce4=0xc +phy_xaui_rx_polarity_flip_ce5=0x2 +phy_xaui_rx_polarity_flip_ce6=0x2 +phy_xaui_rx_polarity_flip_ce7=0xd +phy_xaui_rx_polarity_flip_ce8=0xd +phy_xaui_rx_polarity_flip_ce9=0xa +phy_xaui_rx_polarity_flip_ce10=0x7 +phy_xaui_rx_polarity_flip_ce11=0xf +phy_xaui_rx_polarity_flip_ce12=0xf +phy_xaui_rx_polarity_flip_ce13=0xd +phy_xaui_rx_polarity_flip_ce14=0x4 +phy_xaui_rx_polarity_flip_ce15=0xb +phy_xaui_rx_polarity_flip_ce16=0x2 +phy_xaui_rx_polarity_flip_ce17=0xd +phy_xaui_rx_polarity_flip_ce18=0xf +phy_xaui_rx_polarity_flip_ce19=0x0 +phy_xaui_rx_polarity_flip_ce20=0x0 +phy_xaui_rx_polarity_flip_ce21=0x5 +phy_xaui_rx_polarity_flip_ce22=0x0 +phy_xaui_rx_polarity_flip_ce23=0x2 +phy_xaui_rx_polarity_flip_ce24=0xc +phy_xaui_rx_polarity_flip_ce25=0x8 +phy_xaui_rx_polarity_flip_ce26=0x4 +phy_xaui_rx_polarity_flip_ce27=0x7 +phy_xaui_rx_polarity_flip_ce28=0x7 +phy_xaui_rx_polarity_flip_ce29=0x9 +phy_xaui_rx_polarity_flip_ce30=0xc +phy_xaui_rx_polarity_flip_ce31=0x8 + +dport_map_port_38=1 +dport_map_port_39=2 +dport_map_port_40=3 +dport_map_port_41=4 +dport_map_port_68=5 +dport_map_port_69=6 +dport_map_port_70=7 +dport_map_port_71=8 +dport_map_port_35=9 +dport_map_port_34=10 +dport_map_port_37=11 +dport_map_port_36=12 +dport_map_port_72=13 +dport_map_port_73=14 +dport_map_port_74=15 +dport_map_port_75=16 +dport_map_port_102=17 +dport_map_port_103=18 +dport_map_port_104=19 +dport_map_port_105=20 +dport_map_port_6=21 +dport_map_port_5=22 +dport_map_port_8=23 +dport_map_port_7=24 +dport_map_port_107=25 +dport_map_port_106=26 +dport_map_port_109=27 +dport_map_port_108=28 +dport_map_port_2=29 +dport_map_port_1=30 +dport_map_port_4=31 +dport_map_port_3=32 + +mmu_init_config="MSFT-TH-Tier1" diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/buffers.json.j2 b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/buffers_defaults_t0.j2 b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..4bd35b354c8a --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/buffers_defaults_t0.j2 @@ -0,0 +1,61 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,6) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(10,26) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(30,32) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(6,10) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(26,30) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11213696", + "type": "ingress", + "mode": "dynamic", + "xoff": "3855488" + }, + "egress_lossy_pool": { + "size": "9532224", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"3995680" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/pg_profile_lookup.ini b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/pg_profile_lookup.ini new file mode 100644 index 000000000000..aedda37a8878 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -3 2288 + 25000 5m 1248 2288 53248 -3 2288 + 40000 5m 1248 2288 66560 -3 2288 + 50000 5m 1248 2288 90272 -3 2288 + 100000 5m 1248 2288 165568 -3 2288 + 10000 40m 1248 2288 37024 -3 2288 + 25000 40m 1248 2288 53248 -3 2288 + 40000 40m 1248 2288 71552 -3 2288 + 50000 40m 1248 2288 96096 -3 2288 + 100000 40m 1248 2288 177632 -3 2288 + 10000 300m 1248 2288 46176 -3 2288 + 25000 300m 1248 2288 79040 -3 2288 + 40000 300m 1248 2288 108160 -3 2288 + 50000 300m 1248 2288 141856 -3 2288 + 100000 300m 1248 2288 268736 -3 2288 diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/port_config.ini b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/port_config.ini new file mode 100644 index 000000000000..c1a086764854 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 49,50 fiftyGigE1/1/1 1 50000 +Ethernet2 51,52 fiftyGigE1/1/2 1 50000 +Ethernet4 53,54 fiftyGigE1/2/1 2 50000 +Ethernet6 55,56 fiftyGigE1/2/2 2 50000 +Ethernet8 57,58 fiftyGigE1/3/1 3 50000 +Ethernet10 59,60 fiftyGigE1/3/2 3 50000 +Ethernet12 61,62 fiftyGigE1/4/1 4 50000 +Ethernet14 63,64 fiftyGigE1/4/2 4 50000 +Ethernet16 65,66 fiftyGigE1/5/1 5 50000 +Ethernet18 67,68 fiftyGigE1/5/2 5 50000 +Ethernet20 69,70 fiftyGigE1/6/1 6 50000 +Ethernet22 71,72 fiftyGigE1/6/2 6 50000 +Ethernet24 73,74,75,76 hundredGigE1/7 7 100000 +Ethernet28 77,78,79,80 hundredGigE1/8 8 100000 +Ethernet32 37,38,39,40 hundredGigE1/9 9 100000 +Ethernet36 33,34,35,36 hundredGigE1/10 10 100000 +Ethernet40 45,46 fiftyGigE1/11/1 11 50000 +Ethernet42 47,48 fiftyGigE1/11/2 11 50000 +Ethernet44 41,42 fiftyGigE1/12/1 12 50000 +Ethernet46 43,44 fiftyGigE1/12/2 12 50000 +Ethernet48 81,82 fiftyGigE1/13/1 13 50000 +Ethernet50 83,84 fiftyGigE1/13/2 13 50000 +Ethernet52 85,86 fiftyGigE1/14/1 14 50000 +Ethernet54 87,88 fiftyGigE1/14/2 14 50000 +Ethernet56 89,90 fiftyGigE1/15/1 15 50000 +Ethernet58 91,92 fiftyGigE1/15/2 15 50000 +Ethernet60 93,94 fiftyGigE1/16/1 16 50000 +Ethernet62 95,96 fiftyGigE1/16/2 16 50000 +Ethernet64 97,98 fiftyGigE1/17/1 17 50000 +Ethernet66 99,100 fiftyGigE1/17/2 17 50000 +Ethernet68 101,102 fiftyGigE1/18/1 18 50000 +Ethernet70 103,104 fiftyGigE1/18/2 18 50000 +Ethernet72 105,106 fiftyGigE1/19/1 19 50000 +Ethernet74 107,108 fiftyGigE1/19/2 19 50000 +Ethernet76 109,110 fiftyGigE1/20/1 20 50000 +Ethernet78 111,112 fiftyGigE1/20/2 20 50000 +Ethernet80 21,22 fiftyGigE1/21/1 21 50000 +Ethernet82 23,24 fiftyGigE1/21/2 21 50000 +Ethernet84 17,18 fiftyGigE1/22/1 22 50000 +Ethernet86 19,20 fiftyGigE1/22/2 22 50000 +Ethernet88 29,30 fiftyGigE1/23/1 23 50000 +Ethernet90 31,32 fiftyGigE1/23/2 23 50000 +Ethernet92 25,26 fiftyGigE1/24/1 24 50000 +Ethernet94 27,28 fiftyGigE1/24/2 24 50000 +Ethernet96 117,118 fiftyGigE1/25/1 25 50000 +Ethernet98 119,120 fiftyGigE1/25/2 25 50000 +Ethernet100 113,114 fiftyGigE1/26/1 26 50000 +Ethernet102 115,116 fiftyGigE1/26/2 26 50000 +Ethernet104 125,126,127,128 hundredGigE1/27 27 100000 +Ethernet108 121,122,123,124 hundredGigE1/28 28 100000 +Ethernet112 5,6,7,8 hundredGigE1/29 29 100000 +Ethernet116 1,2,3,4 hundredGigE1/30 30 100000 +Ethernet120 13,14 fiftyGigE1/31/1 31 50000 +Ethernet122 15,16 fiftyGigE1/31/2 31 50000 +Ethernet124 9,10 fiftyGigE1/32/1 32 50000 +Ethernet126 11,12 fiftyGigE1/32/2 32 50000 diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/qos.json.j2 b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/sai.profile b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/sai.profile new file mode 100644 index 000000000000..182624c19bd4 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-z9100-8x100G-48x50G.config.bcm diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/th-z9100-8x100G-48x50G.config.bcm b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/th-z9100-8x100G-48x50G.config.bcm new file mode 100644 index 000000000000..5dddf7d2a2d4 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/th-z9100-8x100G-48x50G.config.bcm @@ -0,0 +1,380 @@ +#TH Z9100 T0 + +l3_alpm_enable=2 +pfc_deadlock_seq_control=1 +bcm_stat_interval=2000000 +bcm_num_cos=8 +switch_bypass_mode=0 +mmu_lossless=0 +lpm_scaling_enable=0 +lpm_scaling_enable=0 +lpm_ipv6_128b_reserved=0 +ipv6_lpm_128b_enable=1 +l2xmsg_mode=1 +oversubscribe_mode=1 +os=unix + +pbmp_oversubscribe=0x3fffffffdffffffff7fffffffdfffffffe +pbmp_xport_xe=0x3fffffffdffffffff7fffffffdfffffffe + +serdes_if_type_xe=14 +serdes_if_type_ce=14 + +#Parity +parity_correction=1 +parity_enable=1 + +#Port configuration +dport_map_port_100.0=130 +dport_map_port_10.0=126 +dport_map_port_1.0=117 +dport_map_port_102.0=65 +dport_map_port_103.0=66 +dport_map_port_106.0=69 +dport_map_port_107.0=70 +dport_map_port_110.0=73 +dport_map_port_111.0=74 +dport_map_port_114.0=77 +dport_map_port_115.0=78 +dport_map_port_118.0=101 +dport_map_port_119.0=102 +dport_map_port_122.0=97 +dport_map_port_123.0=98 +dport_map_port_126.0=109 +dport_map_port_130.0=105 +dport_map_port_13.0=121 +dport_map_port_14.0=122 +dport_map_port_17.0=85 +dport_map_port_18.0=86 +dport_map_port_21.0=81 +dport_map_port_22.0=82 +dport_map_port_25.0=93 +dport_map_port_26.0=94 +dport_map_port_29.0=89 +dport_map_port_30.0=90 +dport_map_port_34.0=37 +dport_map_port_38.0=33 +dport_map_port_42.0=45 +dport_map_port_43.0=46 +dport_map_port_46.0=41 +dport_map_port_47.0=42 +dport_map_port_50.0=1 +dport_map_port_5.0=113 +dport_map_port_51.0=2 +dport_map_port_54.0=5 +dport_map_port_55.0=6 +dport_map_port_58.0=9 +dport_map_port_59.0=10 +dport_map_port_62.0=13 +dport_map_port_63.0=14 +dport_map_port_66.0=129 +dport_map_port_68.0=17 +dport_map_port_69.0=18 +dport_map_port_72.0=21 +dport_map_port_73.0=22 +dport_map_port_76.0=25 +dport_map_port_80.0=29 +dport_map_port_84.0=49 +dport_map_port_85.0=50 +dport_map_port_88.0=53 +dport_map_port_89.0=54 +dport_map_port_9.0=125 +dport_map_port_92.0=57 +dport_map_port_93.0=58 +dport_map_port_96.0=61 +dport_map_port_97.0=62 + +phy_xaui_rx_polarity_flip_100.0=0xf +phy_xaui_rx_polarity_flip_10.0=0x2 +phy_xaui_rx_polarity_flip_1.0=0x9 +phy_xaui_rx_polarity_flip_102.0=0x2 +phy_xaui_rx_polarity_flip_103.0=0x0 +phy_xaui_rx_polarity_flip_106.0=0x1 +phy_xaui_rx_polarity_flip_107.0=0x3 +phy_xaui_rx_polarity_flip_110.0=0x3 +phy_xaui_rx_polarity_flip_111.0=0x3 +phy_xaui_rx_polarity_flip_114.0=0x0 +phy_xaui_rx_polarity_flip_115.0=0x0 +phy_xaui_rx_polarity_flip_118.0=0x0 +phy_xaui_rx_polarity_flip_119.0=0x2 +phy_xaui_rx_polarity_flip_122.0=0x0 +phy_xaui_rx_polarity_flip_123.0=0x3 +phy_xaui_rx_polarity_flip_126.0=0x7 +phy_xaui_rx_polarity_flip_130.0=0x4 +phy_xaui_rx_polarity_flip_13.0=0x0 +phy_xaui_rx_polarity_flip_14.0=0x3 +phy_xaui_rx_polarity_flip_17.0=0x1 +phy_xaui_rx_polarity_flip_18.0=0x1 +phy_xaui_rx_polarity_flip_21.0=0x0 +phy_xaui_rx_polarity_flip_22.0=0x0 +phy_xaui_rx_polarity_flip_25.0=0x2 +phy_xaui_rx_polarity_flip_26.0=0x0 +phy_xaui_rx_polarity_flip_29.0=0x0 +phy_xaui_rx_polarity_flip_30.0=0x0 +phy_xaui_rx_polarity_flip_34.0=0xa +phy_xaui_rx_polarity_flip_38.0=0xd +phy_xaui_rx_polarity_flip_42.0=0x3 +phy_xaui_rx_polarity_flip_43.0=0x3 +phy_xaui_rx_polarity_flip_46.0=0x3 +phy_xaui_rx_polarity_flip_47.0=0x1 +phy_xaui_rx_polarity_flip_50.0=0x0 +phy_xaui_rx_polarity_flip_5.0=0x7 +phy_xaui_rx_polarity_flip_51.0=0x3 +phy_xaui_rx_polarity_flip_54.0=0x1 +phy_xaui_rx_polarity_flip_55.0=0x3 +phy_xaui_rx_polarity_flip_58.0=0x2 +phy_xaui_rx_polarity_flip_59.0=0x0 +phy_xaui_rx_polarity_flip_62.0=0x3 +phy_xaui_rx_polarity_flip_63.0=0x3 +phy_xaui_rx_polarity_flip_66.0=0xf +phy_xaui_rx_polarity_flip_68.0=0x0 +phy_xaui_rx_polarity_flip_69.0=0x3 +phy_xaui_rx_polarity_flip_72.0=0x2 +phy_xaui_rx_polarity_flip_73.0=0x0 +phy_xaui_rx_polarity_flip_76.0=0x2 +phy_xaui_rx_polarity_flip_80.0=0xd +phy_xaui_rx_polarity_flip_84.0=0x3 +phy_xaui_rx_polarity_flip_85.0=0x3 +phy_xaui_rx_polarity_flip_88.0=0x1 +phy_xaui_rx_polarity_flip_89.0=0x3 +phy_xaui_rx_polarity_flip_9.0=0x0 +phy_xaui_rx_polarity_flip_92.0=0x0 +phy_xaui_rx_polarity_flip_93.0=0x1 +phy_xaui_rx_polarity_flip_96.0=0x3 +phy_xaui_rx_polarity_flip_97.0=0x2 + +phy_xaui_tx_polarity_flip_100.0=0x6 +phy_xaui_tx_polarity_flip_10.0=0x0 +phy_xaui_tx_polarity_flip_1.0=0x3 +phy_xaui_tx_polarity_flip_102.0=0x3 +phy_xaui_tx_polarity_flip_103.0=0x3 +phy_xaui_tx_polarity_flip_106.0=0x3 +phy_xaui_tx_polarity_flip_107.0=0x3 +phy_xaui_tx_polarity_flip_110.0=0x3 +phy_xaui_tx_polarity_flip_111.0=0x3 +phy_xaui_tx_polarity_flip_114.0=0x3 +phy_xaui_tx_polarity_flip_115.0=0x3 +phy_xaui_tx_polarity_flip_118.0=0x0 +phy_xaui_tx_polarity_flip_119.0=0x0 +phy_xaui_tx_polarity_flip_122.0=0x3 +phy_xaui_tx_polarity_flip_123.0=0x3 +phy_xaui_tx_polarity_flip_126.0=0x7 +phy_xaui_tx_polarity_flip_130.0=0xb +phy_xaui_tx_polarity_flip_13.0=0x0 +phy_xaui_tx_polarity_flip_14.0=0x3 +phy_xaui_tx_polarity_flip_17.0=0x3 +phy_xaui_tx_polarity_flip_18.0=0x3 +phy_xaui_tx_polarity_flip_21.0=0x3 +phy_xaui_tx_polarity_flip_22.0=0x3 +phy_xaui_tx_polarity_flip_25.0=0x2 +phy_xaui_tx_polarity_flip_26.0=0x2 +phy_xaui_tx_polarity_flip_29.0=0x3 +phy_xaui_tx_polarity_flip_30.0=0x2 +phy_xaui_tx_polarity_flip_34.0=0xb +phy_xaui_tx_polarity_flip_38.0=0x0 +phy_xaui_tx_polarity_flip_42.0=0x2 +phy_xaui_tx_polarity_flip_43.0=0x1 +phy_xaui_tx_polarity_flip_46.0=0x2 +phy_xaui_tx_polarity_flip_47.0=0x3 +phy_xaui_tx_polarity_flip_50.0=0x2 +phy_xaui_tx_polarity_flip_5.0=0x8 +phy_xaui_tx_polarity_flip_51.0=0x3 +phy_xaui_tx_polarity_flip_54.0=0x2 +phy_xaui_tx_polarity_flip_55.0=0x0 +phy_xaui_tx_polarity_flip_58.0=0x2 +phy_xaui_tx_polarity_flip_59.0=0x2 +phy_xaui_tx_polarity_flip_62.0=0x3 +phy_xaui_tx_polarity_flip_63.0=0x2 +phy_xaui_tx_polarity_flip_66.0=0x6 +phy_xaui_tx_polarity_flip_68.0=0x2 +phy_xaui_tx_polarity_flip_69.0=0x0 +phy_xaui_tx_polarity_flip_72.0=0x0 +phy_xaui_tx_polarity_flip_73.0=0x0 +phy_xaui_tx_polarity_flip_76.0=0x0 +phy_xaui_tx_polarity_flip_80.0=0xa +phy_xaui_tx_polarity_flip_84.0=0x2 +phy_xaui_tx_polarity_flip_85.0=0x1 +phy_xaui_tx_polarity_flip_88.0=0x3 +phy_xaui_tx_polarity_flip_89.0=0x3 +phy_xaui_tx_polarity_flip_9.0=0x3 +phy_xaui_tx_polarity_flip_92.0=0x1 +phy_xaui_tx_polarity_flip_93.0=0x1 +phy_xaui_tx_polarity_flip_96.0=0x0 +phy_xaui_tx_polarity_flip_97.0=0x2 + +portmap_100.0=131:10 +portmap_10.0=11:50:2 +portmap_1.0=1:100 +portmap_102.0=97:50:2 +portmap_103.0=99:50:2 +portmap_106.0=101:50:2 +portmap_107.0=103:50:2 +portmap_110.0=105:50:2 +portmap_111.0=107:50:2 +portmap_114.0=109:50:2 +portmap_115.0=111:50:2 +portmap_118.0=113:50:2 +portmap_119.0=115:50:2 +portmap_122.0=117:50:2 +portmap_123.0=119:50:2 +portmap_126.0=121:100 +portmap_130.0=125:100 +portmap_13.0=13:50:2 +portmap_14.0=15:50:2 +portmap_17.0=17:50:2 +portmap_18.0=19:50:2 +portmap_21.0=21:50:2 +portmap_22.0=23:50:2 +portmap_25.0=25:50:2 +portmap_26.0=27:50:2 +portmap_29.0=29:50:2 +portmap_30.0=31:50:2 +portmap_34.0=33:100 +portmap_38.0=37:100 +portmap_42.0=41:50:2 +portmap_43.0=43:50:2 +portmap_46.0=45:50:2 +portmap_47.0=47:50:2 +portmap_50.0=49:50:2 +portmap_5.0=5:100 +portmap_51.0=51:50:2 +portmap_54.0=53:50:2 +portmap_55.0=55:50:2 +portmap_58.0=57:50:2 +portmap_59.0=59:50:2 +portmap_62.0=61:50:2 +portmap_63.0=63:50:2 +portmap_66.0=129:10 +portmap_68.0=65:50:2 +portmap_69.0=67:50:2 +portmap_72.0=69:50:2 +portmap_73.0=71:50:2 +portmap_76.0=73:100 +portmap_80.0=77:100 +portmap_84.0=81:50:2 +portmap_85.0=83:50:2 +portmap_88.0=85:50:2 +portmap_89.0=87:50:2 +portmap_9.0=9:50:2 +portmap_92.0=89:50:2 +portmap_93.0=91:50:2 +portmap_96.0=93:50:2 +portmap_97.0=95:50:2 + +xgxs_rx_lane_map_100.0=0x3210 +xgxs_rx_lane_map_10.0=0x213 +xgxs_rx_lane_map_1.0=0x213 +xgxs_rx_lane_map_102.0=0x3201 +xgxs_rx_lane_map_103.0=0x3201 +xgxs_rx_lane_map_106.0=0x213 +xgxs_rx_lane_map_107.0=0x213 +xgxs_rx_lane_map_110.0=0x3210 +xgxs_rx_lane_map_111.0=0x3210 +xgxs_rx_lane_map_114.0=0x3210 +xgxs_rx_lane_map_115.0=0x3210 +xgxs_rx_lane_map_118.0=0x123 +xgxs_rx_lane_map_119.0=0x123 +xgxs_rx_lane_map_122.0=0x3201 +xgxs_rx_lane_map_123.0=0x3201 +xgxs_rx_lane_map_126.0=0x213 +xgxs_rx_lane_map_130.0=0x1023 +xgxs_rx_lane_map_13.0=0x3201 +xgxs_rx_lane_map_14.0=0x3201 +xgxs_rx_lane_map_17.0=0x2103 +xgxs_rx_lane_map_18.0=0x2103 +xgxs_rx_lane_map_21.0=0x3102 +xgxs_rx_lane_map_22.0=0x3102 +xgxs_rx_lane_map_25.0=0x2310 +xgxs_rx_lane_map_26.0=0x2310 +xgxs_rx_lane_map_29.0=0x2301 +xgxs_rx_lane_map_30.0=0x2301 +xgxs_rx_lane_map_34.0=0x1302 +xgxs_rx_lane_map_38.0=0x312 +xgxs_rx_lane_map_42.0=0x3210 +xgxs_rx_lane_map_43.0=0x3210 +xgxs_rx_lane_map_46.0=0x2103 +xgxs_rx_lane_map_47.0=0x2103 +xgxs_rx_lane_map_50.0=0x1023 +xgxs_rx_lane_map_5.0=0x1203 +xgxs_rx_lane_map_51.0=0x1023 +xgxs_rx_lane_map_54.0=0x1302 +xgxs_rx_lane_map_55.0=0x1302 +xgxs_rx_lane_map_58.0=0x1203 +xgxs_rx_lane_map_59.0=0x1203 +xgxs_rx_lane_map_62.0=0x1302 +xgxs_rx_lane_map_63.0=0x1302 +xgxs_rx_lane_map_66.0=0x3210 +xgxs_rx_lane_map_68.0=0x3201 +xgxs_rx_lane_map_69.0=0x3201 +xgxs_rx_lane_map_72.0=0x1302 +xgxs_rx_lane_map_73.0=0x1302 +xgxs_rx_lane_map_76.0=0x1203 +xgxs_rx_lane_map_80.0=0x2301 +xgxs_rx_lane_map_84.0=0x2301 +xgxs_rx_lane_map_85.0=0x2301 +xgxs_rx_lane_map_88.0=0x213 +xgxs_rx_lane_map_89.0=0x213 +xgxs_rx_lane_map_9.0=0x213 +xgxs_rx_lane_map_92.0=0x3210 +xgxs_rx_lane_map_93.0=0x3210 +xgxs_rx_lane_map_96.0=0x3210 +xgxs_rx_lane_map_97.0=0x3210 +xgxs_tx_lane_map_100.0=0x132 +xgxs_tx_lane_map_10.0=0x123 +xgxs_tx_lane_map_1.0=0x123 +xgxs_tx_lane_map_102.0=0x123 +xgxs_tx_lane_map_103.0=0x123 +xgxs_tx_lane_map_106.0=0x123 +xgxs_tx_lane_map_107.0=0x123 +xgxs_tx_lane_map_110.0=0x132 +xgxs_tx_lane_map_111.0=0x132 +xgxs_tx_lane_map_114.0=0x123 +xgxs_tx_lane_map_115.0=0x123 +xgxs_tx_lane_map_118.0=0x2013 +xgxs_tx_lane_map_119.0=0x2013 +xgxs_tx_lane_map_122.0=0x2310 +xgxs_tx_lane_map_123.0=0x2310 +xgxs_tx_lane_map_126.0=0x123 +xgxs_tx_lane_map_130.0=0x132 +xgxs_tx_lane_map_13.0=0x2301 +xgxs_tx_lane_map_14.0=0x2301 +xgxs_tx_lane_map_17.0=0x3102 +xgxs_tx_lane_map_18.0=0x3102 +xgxs_tx_lane_map_21.0=0x132 +xgxs_tx_lane_map_22.0=0x132 +xgxs_tx_lane_map_25.0=0x2130 +xgxs_tx_lane_map_26.0=0x2130 +xgxs_tx_lane_map_29.0=0x1023 +xgxs_tx_lane_map_30.0=0x1023 +xgxs_tx_lane_map_34.0=0x2031 +xgxs_tx_lane_map_38.0=0x1032 +xgxs_tx_lane_map_42.0=0x132 +xgxs_tx_lane_map_43.0=0x132 +xgxs_tx_lane_map_46.0=0x1023 +xgxs_tx_lane_map_47.0=0x1023 +xgxs_tx_lane_map_50.0=0x132 +xgxs_tx_lane_map_5.0=0x213 +xgxs_tx_lane_map_51.0=0x132 +xgxs_tx_lane_map_54.0=0x2301 +xgxs_tx_lane_map_55.0=0x2301 +xgxs_tx_lane_map_58.0=0x123 +xgxs_tx_lane_map_59.0=0x123 +xgxs_tx_lane_map_62.0=0x3201 +xgxs_tx_lane_map_63.0=0x3201 +xgxs_tx_lane_map_66.0=0x132 +xgxs_tx_lane_map_68.0=0x3210 +xgxs_tx_lane_map_69.0=0x3210 +xgxs_tx_lane_map_72.0=0x2301 +xgxs_tx_lane_map_73.0=0x2301 +xgxs_tx_lane_map_76.0=0x123 +xgxs_tx_lane_map_80.0=0x1320 +xgxs_tx_lane_map_84.0=0x213 +xgxs_tx_lane_map_85.0=0x213 +xgxs_tx_lane_map_88.0=0x1032 +xgxs_tx_lane_map_89.0=0x1032 +xgxs_tx_lane_map_9.0=0x123 +xgxs_tx_lane_map_92.0=0x132 +xgxs_tx_lane_map_93.0=0x132 +xgxs_tx_lane_map_96.0=0x123 +xgxs_tx_lane_map_97.0=0x123 +mmu_init_config="MSFT-TH-Tier0" diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/default_sku b/device/dell/x86_64-dell_z9100_c2538-r0/default_sku new file mode 100644 index 000000000000..e09260239e96 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/default_sku @@ -0,0 +1 @@ +Force10-Z9100-C32 t1 diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/installer.conf b/device/dell/x86_64-dell_z9100_c2538-r0/installer.conf new file mode 100644 index 000000000000..0a9a3a639eb2 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="module_blacklist=gpio_ich" diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/plugins/eeprom.py b/device/dell/x86_64-dell_z9100_c2538-r0/plugins/eeprom.py new file mode 100644 index 000000000000..8d1d13f4b7cc --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Dell Z9100 +# +# 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-2/2-0050/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/plugins/psuutil.py b/device/dell/x86_64-dell_z9100_c2538-r0/plugins/psuutil.py new file mode 100644 index 000000000000..f96fac6f46cf --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/plugins/psuutil.py @@ -0,0 +1,82 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" +HWMON_NODE = os.listdir(HWMON_DIR)[0] + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + # Get a mailbox register + def get_pmc_register(self, reg_name): + mailbox_dir = HWMON_DIR + HWMON_NODE + retval = 'ERR' + mb_reg_file = mailbox_dir+'/' + reg_name + if (not os.path.isfile(mb_reg_file)): + logging.error(mb_reg_file, "not found !") + return retval + + try: + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", mb_reg_file, "file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + Z9100_MAX_PSUS = 2 + return Z9100_MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + psu_status = self.get_pmc_register('psu'+str(index)+'_presence') + if (psu_status != 'ERR'): + psu_status = int(psu_status, 16) + # Check for PSU statuse + if (~psu_status & 0b1000) or (psu_status & 0b0100): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_presence = self.get_pmc_register('psu'+str(index)+'_presence') + if (psu_presence != 'ERR'): + psu_presence = int(psu_presence, 16) + # Check for PSU presence + if (~psu_presence & 0b1): + status = 1 + + return status 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 new file mode 100644 index 000000000000..b31a44ca1539 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/plugins/sfputil.py @@ -0,0 +1,452 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import os + import logging + import time + import select + 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/" + OIR_FD_PATH = "/sys/devices/platform/dell_ich.0/sci_int_gpio_sus6" + + oir_fd = -1 + epoll = -1 + _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]) + + self.oir_fd = open(self.OIR_FD_PATH, "r") + self.epoll = select.epoll() + if self.oir_fd != -1: + self.epoll.register(self.oir_fd.fileno(), select.EPOLLIN) + + SfpUtilBase.__init__(self) + + def __del__(self): + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + + 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 + + def get_register(self, reg_file): + retval = 'ERR' + + if (not os.path.isfile(reg_file)): + print reg_file, 'not found !' + return retval + + try: + with open(reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", reg_file, "file !") + + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + + def check_interrupts(self, port_dict): + retval = 0 + is_port_dict_updated = False + # Read the QSFP ABS interrupt & status registers + cpld2_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_int") + cpld2_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_sta") + cpld3_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_int") + cpld3_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_sta") + cpld4_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_int") + cpld4_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_sta") + + if (cpld2_abs_int == 'ERR' or cpld2_abs_sta == 'ERR' or + cpld3_abs_int == 'ERR' or cpld3_abs_sta == 'ERR' or + cpld4_abs_int == 'ERR' or cpld4_abs_sta == 'ERR'): + return -1 + + cpld2_abs_int = int(cpld2_abs_int, 16) + cpld2_abs_sta = int(cpld2_abs_sta, 16) + cpld3_abs_int = int(cpld3_abs_int, 16) + cpld3_abs_sta = int(cpld3_abs_sta, 16) + cpld4_abs_int = int(cpld4_abs_int, 16) + cpld4_abs_sta = int(cpld4_abs_sta, 16) + + # Make it contiguous (discard reserved bits) + interrupt_reg = (cpld2_abs_int & 0xfff) |\ + ((cpld3_abs_int & 0x3ff) << 12) |\ + ((cpld4_abs_int & 0x3ff) << 22) + status_reg = (cpld2_abs_sta & 0xfff) |\ + ((cpld3_abs_sta & 0x3ff) << 12) |\ + ((cpld4_abs_sta & 0x3ff) << 22) + + port = self.port_start + while port <= self.port_end: + if interrupt_reg & (1 << port): + # update only if atleast one port has generated + # interrupt + is_port_dict_updated = True + if status_reg & (1 << port): + # status reg 1 => optics is removed + port_dict[port] = '0' + else: + # status reg 0 => optics is inserted + port_dict[port] = '1' + port += 1 + return retval, is_port_dict_updated + + def get_transceiver_change_event(self, timeout=0): + port_dict = {} + try: + # We get notified when there is an SCI interrupt from GPIO SUS6 + # Check for missed interrupts by invoking self.check_interrupts + # it will update the port_dict. + # Then poll for new xcvr insertion/removal and + # call self.check_interrupts again and return + retval, is_port_dict_updated = self.check_interrupts(port_dict) + if ((retval == 0) and (is_port_dict_updated is True)): + return True, port_dict + + # Block until an xcvr is inserted or removed with timeout = -1 + events = self.epoll.poll( + timeout=timeout if timeout != 0 else -1) + if events: + # check interrupts and return the port_dict + retval, is_port_dict_updated = \ + self.check_interrupts(port_dict) + if (retval != 0): + return False, {} + return True, port_dict + except: + return False, {} + return False, {} + diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/sensors.conf b/device/dell/x86_64-dell_z9100_c2538-r0/sensors.conf new file mode 100644 index 000000000000..31a656fcf0b3 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/sensors.conf @@ -0,0 +1,12 @@ +chip "SMF_Z9100_ON-isa-0000" +label power1 "PSU1 Input Power" +label power2 "PSU1 Output Power" +label power3 "PSU2 Input Power" +label power4 "PSU2 Output Power" +label temp14 "PSU1 Temp" +label temp15 "PSU1 Temp" +ignore temp12 +ignore temp13 +ignore temp5 +ignore temp7 +ignore temp8 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f/port_config.ini b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f/port_config.ini new file mode 100644 index 000000000000..2ae02b21b49c --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index +Ethernet0 49,50,51,52 hundredGigE1/1 0 +Ethernet4 53,54,55,56 hundredGigE1/2 1 +Ethernet8 65,66,67,68 hundredGigE1/3 2 +Ethernet12 69,70,71,72 hundredGigE1/4 3 +Ethernet16 81,82,83,84 hundredGigE1/5 4 +Ethernet20 85,86,87,88 hundredGigE1/6 5 +Ethernet24 97,98,99,100 hundredGigE1/7 6 +Ethernet28 101,102,103,104 hundredGigE1/8 7 +Ethernet32 1,2,3,4 hundredGigE1/9 8 +Ethernet36 5,6,7,8 hundredGigE1/10 9 +Ethernet40 17,18,19,20 hundredGigE1/11 10 +Ethernet44 21,22,23,24 hundredGigE1/12 11 +Ethernet48 33,34,35,36 hundredGigE1/13 12 +Ethernet52 37,38,39,40 hundredGigE1/14 13 +Ethernet56 113,114,115,116 hundredGigE1/15 14 +Ethernet60 117,118,119,120 hundredGigE1/16 15 +Ethernet64 133,134,135,136 hundredGigE1/17 16 +Ethernet68 129,130,131,132 hundredGigE1/18 17 +Ethernet72 213,214,215,216 hundredGigE1/19 18 +Ethernet76 209,210,211,212 hundredGigE1/20 19 +Ethernet80 229,230,231,232 hundredGigE1/21 20 +Ethernet84 225,226,227,228 hundredGigE1/22 21 +Ethernet88 245,246,247,248 hundredGigE1/23 22 +Ethernet92 241,242,243,244 hundredGigE1/24 23 +Ethernet96 149,150,151,152 hundredGigE1/25 24 +Ethernet100 145,146,147,148 hundredGigE1/26 25 +Ethernet104 165,166,167,168 hundredGigE1/27 26 +Ethernet108 161,162,163,164 hundredGigE1/28 27 +Ethernet112 181,182,183,184 hundredGigE1/29 28 +Ethernet116 177,178,179,180 hundredGigE1/30 29 +Ethernet120 197,198,199,200 hundredGigE1/31 30 +Ethernet124 193,194,195,196 hundredGigE1/32 31 +Ethernet128 61,62,63,64 hundredGigE1/33 32 +Ethernet132 57,58,59,60 hundredGigE1/34 33 +Ethernet136 77,78,79,80 hundredGigE1/35 34 +Ethernet140 73,74,75,76 hundredGigE1/36 35 +Ethernet144 93,94,95,96 hundredGigE1/37 36 +Ethernet148 89,90,91,92 hundredGigE1/38 37 +Ethernet152 109,110,111,112 hundredGigE1/39 38 +Ethernet156 105,106,107,108 hundredGigE1/40 39 +Ethernet160 13,14,15,16 hundredGigE1/41 40 +Ethernet164 9,10,11,12 hundredGigE1/42 41 +Ethernet168 29,30,31,32 hundredGigE1/43 42 +Ethernet172 25,26,27,28 hundredGigE1/44 43 +Ethernet176 45,46,47,48 hundredGigE1/45 44 +Ethernet180 41,42,43,44 hundredGigE1/46 45 +Ethernet184 125,126,127,128 hundredGigE1/47 46 +Ethernet188 121,122,123,124 hundredGigE1/48 47 +Ethernet192 137,138,139,140 hundredGigE1/49 48 +Ethernet196 141,142,143,144 hundredGigE1/50 49 +Ethernet200 217,218,219,220 hundredGigE1/51 50 +Ethernet204 221,222,223,224 hundredGigE1/52 51 +Ethernet208 233,234,235,236 hundredGigE1/53 52 +Ethernet212 237,238,239,240 hundredGigE1/54 53 +Ethernet216 249,250,251,252 hundredGigE1/55 54 +Ethernet220 253,254,255,256 hundredGigE1/56 55 +Ethernet224 153,154,155,156 hundredGigE1/57 56 +Ethernet228 157,158,159,160 hundredGigE1/58 57 +Ethernet232 169,170,171,172 hundredGigE1/59 58 +Ethernet236 173,174,175,176 hundredGigE1/60 59 +Ethernet240 185,186,187,188 hundredGigE1/61 60 +Ethernet244 189,190,191,192 hundredGigE1/62 61 +Ethernet248 201,202,203,204 hundredGigE1/63 62 +Ethernet252 205,206,207,208 hundredGigE1/64 63 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f/sai.profile b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f/sai.profile new file mode 100644 index 000000000000..0a4fed041752 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-z9264f-64x100G.config.bcm diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f/th2-z9264f-64x100G.config.bcm b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f/th2-z9264f-64x100G.config.bcm new file mode 100644 index 000000000000..fdd3b3fc076d --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f/th2-z9264f-64x100G.config.bcm @@ -0,0 +1,1005 @@ +#TH2 Z9264F 64x100G +os=unix +core_clock_frequency=1700 +dpp_clock_ratio=2:3 +pbmp_xport_xe=0x3FFFD0000FFFF40003FFFC0001FFFE +oversubscribe_mode=1 +fpem_mem_entries=65536 +l2xmsg_mode=1 + +l3_alpm_enable=2 +bcm_num_cos=8 +switch_bypass_mode=0 +mmu_lossless=0 +lpm_scaling_enable=0 +lpm_ipv6_128b_reserved=0 +ipv6_lpm_128b_enable=1 + +parity_correction=1 +parity_enable=1 + +dport_map_enable=1 + +dport_map_enable=1 +dport_map_port_13=1 +dport_map_port_14=2 +dport_map_port_34=3 +dport_map_port_35=4 +dport_map_port_38=5 +dport_map_port_39=6 +dport_map_port_42=7 +dport_map_port_43=8 +dport_map_port_1=9 +dport_map_port_2=10 +dport_map_port_5=11 +dport_map_port_6=12 +dport_map_port_9=13 +dport_map_port_10=14 +dport_map_port_46=15 +dport_map_port_47=16 + +dport_map_port_69=17 +dport_map_port_68=18 +dport_map_port_107=19 +dport_map_port_106=20 +dport_map_port_111=21 +dport_map_port_110=22 +dport_map_port_115=23 +dport_map_port_114=24 +dport_map_port_73=25 +dport_map_port_72=26 +dport_map_port_77=27 +dport_map_port_76=28 +dport_map_port_81=29 +dport_map_port_80=30 +dport_map_port_103=31 +dport_map_port_102=32 + +dport_map_port_16=33 +dport_map_port_15=34 +dport_map_port_37=35 +dport_map_port_36=36 +dport_map_port_41=37 +dport_map_port_40=38 +dport_map_port_45=39 +dport_map_port_44=40 +dport_map_port_4=41 +dport_map_port_3=42 +dport_map_port_8=43 +dport_map_port_7=44 +dport_map_port_12=45 +dport_map_port_11=46 +dport_map_port_49=47 +dport_map_port_48=48 + +dport_map_port_70=49 +dport_map_port_71=50 +dport_map_port_108=51 +dport_map_port_109=52 +dport_map_port_112=53 +dport_map_port_113=54 +dport_map_port_116=55 +dport_map_port_117=56 +dport_map_port_74=57 +dport_map_port_75=58 +dport_map_port_78=59 +dport_map_port_79=60 +dport_map_port_82=61 +dport_map_port_83=62 +dport_map_port_104=63 +dport_map_port_105=64 + +# +# Tile-0 FC0~FC15 +# +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_6=21:100 +portmap_7=25:100 +portmap_8=29:100 +portmap_9=33:100 +portmap_10=37:100 +portmap_11=41:100 +portmap_12=45:100 +portmap_13=49:100 +portmap_14=53:100 +portmap_15=57:100 +portmap_16=61:100 + +# TX polarity +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 + +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 + +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 + +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x1 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 + +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_tx_polarity_flip_physical{18.0}=0x0 +phy_chain_tx_polarity_flip_physical{19.0}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 + +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x1 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_tx_polarity_flip_physical{24.0}=0x1 + +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 + +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x1 + +phy_chain_tx_polarity_flip_physical{33.0}=0x1 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x1 +phy_chain_tx_polarity_flip_physical{36.0}=0x1 + +phy_chain_tx_polarity_flip_physical{37.0}=0x0 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 + +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x1 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 + +phy_chain_tx_polarity_flip_physical{45.0}=0x0 +phy_chain_tx_polarity_flip_physical{46.0}=0x0 +phy_chain_tx_polarity_flip_physical{47.0}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x1 + +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 + +phy_chain_tx_polarity_flip_physical{53.0}=0x0 +phy_chain_tx_polarity_flip_physical{54.0}=0x0 +phy_chain_tx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x1 + +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_tx_polarity_flip_physical{58.0}=0x1 +phy_chain_tx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 + +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x0 +phy_chain_tx_polarity_flip_physical{64.0}=0x1 + +# RX polarity +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 + +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 + +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 + +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 + +phy_chain_rx_polarity_flip_physical{17.0}=0x0 +phy_chain_rx_polarity_flip_physical{18.0}=0x1 +phy_chain_rx_polarity_flip_physical{19.0}=0x1 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 + +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 + +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x1 + +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 + +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_rx_polarity_flip_physical{34.0}=0x0 +phy_chain_rx_polarity_flip_physical{35.0}=0x1 +phy_chain_rx_polarity_flip_physical{36.0}=0x1 + +phy_chain_rx_polarity_flip_physical{37.0}=0x1 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x1 + +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 + +phy_chain_rx_polarity_flip_physical{45.0}=0x1 +phy_chain_rx_polarity_flip_physical{46.0}=0x1 +phy_chain_rx_polarity_flip_physical{47.0}=0x0 +phy_chain_rx_polarity_flip_physical{48.0}=0x1 + +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +phy_chain_rx_polarity_flip_physical{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 + +phy_chain_rx_polarity_flip_physical{53.0}=0x1 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{56.0}=0x1 + +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 + +phy_chain_rx_polarity_flip_physical{61.0}=0x1 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x0 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 + +# TX lane swap +phy_chain_tx_lane_map_physical{1.0}=0x3120 +phy_chain_tx_lane_map_physical{5.0}=0x2130 +phy_chain_tx_lane_map_physical{9.0}=0x0213 +phy_chain_tx_lane_map_physical{13.0}=0x3021 + +phy_chain_tx_lane_map_physical{17.0}=0x3201 +phy_chain_tx_lane_map_physical{21.0}=0x3210 +phy_chain_tx_lane_map_physical{25.0}=0x1023 +phy_chain_tx_lane_map_physical{29.0}=0x0231 + +phy_chain_tx_lane_map_physical{33.0}=0x3210 +phy_chain_tx_lane_map_physical{37.0}=0x3120 +phy_chain_tx_lane_map_physical{41.0}=0x2031 +phy_chain_tx_lane_map_physical{45.0}=0x2130 + +phy_chain_tx_lane_map_physical{49.0}=0x2130 +phy_chain_tx_lane_map_physical{53.0}=0x3012 +phy_chain_tx_lane_map_physical{57.0}=0x2031 +phy_chain_tx_lane_map_physical{61.0}=0x0231 + +# RX lane swap +phy_chain_rx_lane_map_physical{1.0}=0x1320 +phy_chain_rx_lane_map_physical{5.0}=0x0213 +phy_chain_rx_lane_map_physical{9.0}=0x2301 +phy_chain_rx_lane_map_physical{13.0}=0x0321 + +phy_chain_rx_lane_map_physical{17.0}=0x2031 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_rx_lane_map_physical{25.0}=0x2310 +phy_chain_rx_lane_map_physical{29.0}=0x2013 + +phy_chain_rx_lane_map_physical{33.0}=0x2103 +phy_chain_rx_lane_map_physical{37.0}=0x0132 +phy_chain_rx_lane_map_physical{41.0}=0x2031 +phy_chain_rx_lane_map_physical{45.0}=0x1032 + +phy_chain_rx_lane_map_physical{49.0}=0x3201 +phy_chain_rx_lane_map_physical{53.0}=0x0132 +phy_chain_rx_lane_map_physical{57.0}=0x2031 +phy_chain_rx_lane_map_physical{61.0}=0x1032 + +# +# Tile-1 FC16~FC31 +# +portmap_34=65:100 +portmap_35=69:100 +portmap_36=73:100 +portmap_37=77:100 +portmap_38=81:100 +portmap_39=85:100 +portmap_40=89:100 +portmap_41=93:100 +portmap_42=97:100 +portmap_43=101:100 +portmap_44=105:100 +portmap_45=109:100 +portmap_46=113:100 +portmap_47=117:100 +portmap_48=121:100 +portmap_49=125:100 + +#TX polarity +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_tx_polarity_flip_physical{66.0}=0x1 +phy_chain_tx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 + +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_tx_polarity_flip_physical{70.0}=0x0 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +phy_chain_tx_polarity_flip_physical{72.0}=0x1 + +phy_chain_tx_polarity_flip_physical{73.0}=0x0 +phy_chain_tx_polarity_flip_physical{74.0}=0x1 +phy_chain_tx_polarity_flip_physical{75.0}=0x1 +phy_chain_tx_polarity_flip_physical{76.0}=0x0 + +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x1 +phy_chain_tx_polarity_flip_physical{80.0}=0x1 + +phy_chain_tx_polarity_flip_physical{81.0}=0x1 +phy_chain_tx_polarity_flip_physical{82.0}=0x1 +phy_chain_tx_polarity_flip_physical{83.0}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 + +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 + +phy_chain_tx_polarity_flip_physical{89.0}=0x0 +phy_chain_tx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 + +phy_chain_tx_polarity_flip_physical{93.0}=0x1 +phy_chain_tx_polarity_flip_physical{94.0}=0x1 +phy_chain_tx_polarity_flip_physical{95.0}=0x1 +phy_chain_tx_polarity_flip_physical{96.0}=0x1 + +phy_chain_tx_polarity_flip_physical{97.0}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 + +phy_chain_tx_polarity_flip_physical{101.0}=0x1 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +phy_chain_tx_polarity_flip_physical{103.0}=0x1 +phy_chain_tx_polarity_flip_physical{104.0}=0x0 + +phy_chain_tx_polarity_flip_physical{105.0}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_tx_polarity_flip_physical{107.0}=0x0 +phy_chain_tx_polarity_flip_physical{108.0}=0x0 + +phy_chain_tx_polarity_flip_physical{109.0}=0x0 +phy_chain_tx_polarity_flip_physical{110.0}=0x1 +phy_chain_tx_polarity_flip_physical{111.0}=0x0 +phy_chain_tx_polarity_flip_physical{112.0}=0x0 + +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +phy_chain_tx_polarity_flip_physical{114.0}=0x0 +phy_chain_tx_polarity_flip_physical{115.0}=0x0 +phy_chain_tx_polarity_flip_physical{116.0}=0x0 + +phy_chain_tx_polarity_flip_physical{117.0}=0x0 +phy_chain_tx_polarity_flip_physical{118.0}=0x1 +phy_chain_tx_polarity_flip_physical{119.0}=0x0 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 + +phy_chain_tx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +phy_chain_tx_polarity_flip_physical{124.0}=0x0 + +phy_chain_tx_polarity_flip_physical{125.0}=0x1 +phy_chain_tx_polarity_flip_physical{126.0}=0x1 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 + +#RX polarity +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_rx_polarity_flip_physical{68.0}=0x1 + +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x1 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 + +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{74.0}=0x1 +phy_chain_rx_polarity_flip_physical{75.0}=0x1 +phy_chain_rx_polarity_flip_physical{76.0}=0x0 + +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x1 + +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x0 +phy_chain_rx_polarity_flip_physical{84.0}=0x1 + +phy_chain_rx_polarity_flip_physical{85.0}=0x0 +phy_chain_rx_polarity_flip_physical{86.0}=0x0 +phy_chain_rx_polarity_flip_physical{87.0}=0x1 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 + +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x1 +phy_chain_rx_polarity_flip_physical{91.0}=0x1 +phy_chain_rx_polarity_flip_physical{92.0}=0x0 + +phy_chain_rx_polarity_flip_physical{93.0}=0x0 +phy_chain_rx_polarity_flip_physical{94.0}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x0 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 + +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x1 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 + +phy_chain_rx_polarity_flip_physical{101.0}=0x0 +phy_chain_rx_polarity_flip_physical{102.0}=0x0 +phy_chain_rx_polarity_flip_physical{103.0}=0x1 +phy_chain_rx_polarity_flip_physical{104.0}=0x1 + +phy_chain_rx_polarity_flip_physical{105.0}=0x1 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 + +phy_chain_rx_polarity_flip_physical{109.0}=0x0 +phy_chain_rx_polarity_flip_physical{110.0}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x1 +phy_chain_rx_polarity_flip_physical{112.0}=0x1 + +phy_chain_rx_polarity_flip_physical{113.0}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x1 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 + +phy_chain_rx_polarity_flip_physical{117.0}=0x1 +phy_chain_rx_polarity_flip_physical{118.0}=0x0 +phy_chain_rx_polarity_flip_physical{119.0}=0x1 +phy_chain_rx_polarity_flip_physical{120.0}=0x0 + +phy_chain_rx_polarity_flip_physical{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{122.0}=0x1 +phy_chain_rx_polarity_flip_physical{123.0}=0x0 +phy_chain_rx_polarity_flip_physical{124.0}=0x0 + +phy_chain_rx_polarity_flip_physical{125.0}=0x0 +phy_chain_rx_polarity_flip_physical{126.0}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x1 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{65.0}=0x2130 +phy_chain_tx_lane_map_physical{69.0}=0x3012 +phy_chain_tx_lane_map_physical{73.0}=0x2031 +phy_chain_tx_lane_map_physical{77.0}=0x0231 + +phy_chain_tx_lane_map_physical{81.0}=0x2130 +phy_chain_tx_lane_map_physical{85.0}=0x1032 +phy_chain_tx_lane_map_physical{89.0}=0x2031 +phy_chain_tx_lane_map_physical{93.0}=0x0231 + +phy_chain_tx_lane_map_physical{97.0}=0x0123 +phy_chain_tx_lane_map_physical{101.0}=0x1320 +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_tx_lane_map_physical{109.0}=0x0213 + +phy_chain_tx_lane_map_physical{113.0}=0x0123 +phy_chain_tx_lane_map_physical{117.0}=0x1023 +phy_chain_tx_lane_map_physical{121.0}=0x2130 +phy_chain_tx_lane_map_physical{125.0}=0x1302 + +# RX lane swap +phy_chain_rx_lane_map_physical{65.0}=0x2103 +phy_chain_rx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{73.0}=0x2031 +phy_chain_rx_lane_map_physical{77.0}=0x1032 + +phy_chain_rx_lane_map_physical{81.0}=0x2103 +phy_chain_rx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_rx_lane_map_physical{93.0}=0x1032 + +phy_chain_rx_lane_map_physical{97.0}=0x1023 +phy_chain_rx_lane_map_physical{101.0}=0x3120 +phy_chain_rx_lane_map_physical{105.0}=0x1023 +phy_chain_rx_lane_map_physical{109.0}=0x0231 + +phy_chain_rx_lane_map_physical{113.0}=0x1320 +phy_chain_rx_lane_map_physical{117.0}=0x3102 +phy_chain_rx_lane_map_physical{121.0}=0x0213 +phy_chain_rx_lane_map_physical{125.0}=0x0231 + +# +# Tile-2 FC32~FC47 +# +# port 66 is the first management port +portmap_66=257:10 +# port 67 is the second loopback port +#portmap_67=261:10 +portmap_68=129:100 +portmap_69=133:100 +portmap_70=137:100 +portmap_71=141:100 +portmap_72=145:100 +portmap_73=149:100 +portmap_74=153:100 +portmap_75=157:100 +portmap_76=161:100 +portmap_77=165:100 +portmap_78=169:100 +portmap_79=173:100 +portmap_80=177:100 +portmap_81=181:100 +portmap_82=185:100 +portmap_83=189:100 + +# TX polarity +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +phy_chain_tx_polarity_flip_physical{130.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x1 + +phy_chain_tx_polarity_flip_physical{133.0}=0x0 +phy_chain_tx_polarity_flip_physical{134.0}=0x0 +phy_chain_tx_polarity_flip_physical{135.0}=0x1 +phy_chain_tx_polarity_flip_physical{136.0}=0x1 + +phy_chain_tx_polarity_flip_physical{137.0}=0x1 +phy_chain_tx_polarity_flip_physical{138.0}=0x0 +phy_chain_tx_polarity_flip_physical{139.0}=0x1 +phy_chain_tx_polarity_flip_physical{140.0}=0x0 + +phy_chain_tx_polarity_flip_physical{141.0}=0x1 +phy_chain_tx_polarity_flip_physical{142.0}=0x0 +phy_chain_tx_polarity_flip_physical{143.0}=0x1 +phy_chain_tx_polarity_flip_physical{144.0}=0x1 + +phy_chain_tx_polarity_flip_physical{145.0}=0x1 +phy_chain_tx_polarity_flip_physical{146.0}=0x0 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x1 + +phy_chain_tx_polarity_flip_physical{149.0}=0x0 +phy_chain_tx_polarity_flip_physical{150.0}=0x1 +phy_chain_tx_polarity_flip_physical{151.0}=0x1 +phy_chain_tx_polarity_flip_physical{152.0}=0x1 + +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x1 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 + +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x0 +phy_chain_tx_polarity_flip_physical{159.0}=0x1 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 + +phy_chain_tx_polarity_flip_physical{161.0}=0x1 +phy_chain_tx_polarity_flip_physical{162.0}=0x0 +phy_chain_tx_polarity_flip_physical{163.0}=0x0 +phy_chain_tx_polarity_flip_physical{164.0}=0x1 + +phy_chain_tx_polarity_flip_physical{165.0}=0x1 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x0 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 + +phy_chain_tx_polarity_flip_physical{169.0}=0x0 +phy_chain_tx_polarity_flip_physical{170.0}=0x0 +phy_chain_tx_polarity_flip_physical{171.0}=0x0 +phy_chain_tx_polarity_flip_physical{172.0}=0x0 + +phy_chain_tx_polarity_flip_physical{173.0}=0x0 +phy_chain_tx_polarity_flip_physical{174.0}=0x1 +phy_chain_tx_polarity_flip_physical{175.0}=0x0 +phy_chain_tx_polarity_flip_physical{176.0}=0x1 + +phy_chain_tx_polarity_flip_physical{177.0}=0x0 +phy_chain_tx_polarity_flip_physical{178.0}=0x0 +phy_chain_tx_polarity_flip_physical{179.0}=0x0 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 + +phy_chain_tx_polarity_flip_physical{181.0}=0x1 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x0 + +phy_chain_tx_polarity_flip_physical{185.0}=0x0 +phy_chain_tx_polarity_flip_physical{186.0}=0x0 +phy_chain_tx_polarity_flip_physical{187.0}=0x0 +phy_chain_tx_polarity_flip_physical{188.0}=0x0 + +phy_chain_tx_polarity_flip_physical{189.0}=0x1 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x1 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 + +# RX polarity +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 + +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x1 +phy_chain_rx_polarity_flip_physical{135.0}=0x1 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 + +phy_chain_rx_polarity_flip_physical{137.0}=0x1 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{140.0}=0x1 + +phy_chain_rx_polarity_flip_physical{141.0}=0x0 +phy_chain_rx_polarity_flip_physical{142.0}=0x0 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x1 + +phy_chain_rx_polarity_flip_physical{145.0}=0x0 +phy_chain_rx_polarity_flip_physical{146.0}=0x0 +phy_chain_rx_polarity_flip_physical{147.0}=0x1 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 + +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x1 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 + +phy_chain_rx_polarity_flip_physical{153.0}=0x0 +phy_chain_rx_polarity_flip_physical{154.0}=0x1 +phy_chain_rx_polarity_flip_physical{155.0}=0x0 +phy_chain_rx_polarity_flip_physical{156.0}=0x0 + +phy_chain_rx_polarity_flip_physical{157.0}=0x1 +phy_chain_rx_polarity_flip_physical{158.0}=0x1 +phy_chain_rx_polarity_flip_physical{159.0}=0x0 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 + +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x1 + +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x1 +phy_chain_rx_polarity_flip_physical{167.0}=0x1 +phy_chain_rx_polarity_flip_physical{168.0}=0x0 + +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x1 + +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x1 +phy_chain_rx_polarity_flip_physical{175.0}=0x0 +phy_chain_rx_polarity_flip_physical{176.0}=0x0 + +phy_chain_rx_polarity_flip_physical{177.0}=0x1 +phy_chain_rx_polarity_flip_physical{178.0}=0x0 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x1 + +phy_chain_rx_polarity_flip_physical{181.0}=0x0 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x0 +phy_chain_rx_polarity_flip_physical{184.0}=0x1 + +phy_chain_rx_polarity_flip_physical{185.0}=0x1 +phy_chain_rx_polarity_flip_physical{186.0}=0x0 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 + +phy_chain_rx_polarity_flip_physical{189.0}=0x1 +phy_chain_rx_polarity_flip_physical{190.0}=0x1 +phy_chain_rx_polarity_flip_physical{191.0}=0x0 +phy_chain_rx_polarity_flip_physical{192.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{129.0}=0x0312 +phy_chain_tx_lane_map_physical{133.0}=0x3120 +phy_chain_tx_lane_map_physical{137.0}=0x1203 +phy_chain_tx_lane_map_physical{141.0}=0x0132 + +phy_chain_tx_lane_map_physical{145.0}=0x0312 +phy_chain_tx_lane_map_physical{149.0}=0x2310 +phy_chain_tx_lane_map_physical{153.0}=0x1032 +phy_chain_tx_lane_map_physical{157.0}=0x3120 + +phy_chain_tx_lane_map_physical{161.0}=0x1023 +phy_chain_tx_lane_map_physical{165.0}=0x1203 +phy_chain_tx_lane_map_physical{169.0}=0x0213 +phy_chain_tx_lane_map_physical{173.0}=0x0123 + +phy_chain_tx_lane_map_physical{177.0}=0x2031 +phy_chain_tx_lane_map_physical{181.0}=0x1203 +phy_chain_tx_lane_map_physical{185.0}=0x0213 +phy_chain_tx_lane_map_physical{189.0}=0x3210 + +# RX lane swap +phy_chain_rx_lane_map_physical{129.0}=0x0321 +phy_chain_rx_lane_map_physical{133.0}=0x0312 +phy_chain_rx_lane_map_physical{137.0}=0x2103 +phy_chain_rx_lane_map_physical{141.0}=0x0231 + +phy_chain_rx_lane_map_physical{145.0}=0x0321 +phy_chain_rx_lane_map_physical{149.0}=0x0312 +phy_chain_rx_lane_map_physical{153.0}=0x3120 +phy_chain_rx_lane_map_physical{157.0}=0x2103 + +phy_chain_rx_lane_map_physical{161.0}=0x1032 +phy_chain_rx_lane_map_physical{165.0}=0x2031 +phy_chain_rx_lane_map_physical{169.0}=0x0132 +phy_chain_rx_lane_map_physical{173.0}=0x2103 + +phy_chain_rx_lane_map_physical{177.0}=0x1032 +phy_chain_rx_lane_map_physical{181.0}=0x1230 +phy_chain_rx_lane_map_physical{185.0}=0x0321 +phy_chain_rx_lane_map_physical{189.0}=0x3201 + +# +# Tile-3 FC48~FC63 +# portmap_0=x:xx // cpu port (not required, but included for illustration purposes) +# +# port 100 is the second management port +portmap_100=259:10 +# port 101 is the third loopback port +#portmap_101=262:10 +portmap_102=193:100 +portmap_103=197:100 +portmap_104=201:100 +portmap_105=205:100 +portmap_106=209:100 +portmap_107=213:100 +portmap_108=217:100 +portmap_109=221:100 +portmap_110=225:100 +portmap_111=229:100 +portmap_112=233:100 +portmap_113=237:100 +portmap_114=241:100 +portmap_115=245:100 +portmap_116=249:100 +portmap_117=253:100 +# port 135 is the fourth loopback port +portmap_135=263:10 + +# TX polarity +phy_chain_tx_polarity_flip_physical{193.0}=0x0 +phy_chain_tx_polarity_flip_physical{194.0}=0x0 +phy_chain_tx_polarity_flip_physical{195.0}=0x0 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 + +phy_chain_tx_polarity_flip_physical{197.0}=0x1 +phy_chain_tx_polarity_flip_physical{198.0}=0x0 +phy_chain_tx_polarity_flip_physical{199.0}=0x1 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 + +phy_chain_tx_polarity_flip_physical{201.0}=0x0 +phy_chain_tx_polarity_flip_physical{202.0}=0x0 +phy_chain_tx_polarity_flip_physical{203.0}=0x0 +phy_chain_tx_polarity_flip_physical{204.0}=0x0 + +phy_chain_tx_polarity_flip_physical{205.0}=0x1 +phy_chain_tx_polarity_flip_physical{206.0}=0x0 +phy_chain_tx_polarity_flip_physical{207.0}=0x1 +phy_chain_tx_polarity_flip_physical{208.0}=0x0 + +phy_chain_tx_polarity_flip_physical{209.0}=0x1 +phy_chain_tx_polarity_flip_physical{210.0}=0x0 +phy_chain_tx_polarity_flip_physical{211.0}=0x0 +phy_chain_tx_polarity_flip_physical{212.0}=0x1 + +phy_chain_tx_polarity_flip_physical{213.0}=0x1 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x0 + +phy_chain_tx_polarity_flip_physical{217.0}=0x0 +phy_chain_tx_polarity_flip_physical{218.0}=0x0 +phy_chain_tx_polarity_flip_physical{219.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x0 + +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x1 +phy_chain_tx_polarity_flip_physical{223.0}=0x1 +phy_chain_tx_polarity_flip_physical{224.0}=0x0 + +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x1 +phy_chain_tx_polarity_flip_physical{227.0}=0x0 +phy_chain_tx_polarity_flip_physical{228.0}=0x0 + +phy_chain_tx_polarity_flip_physical{229.0}=0x1 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x1 +phy_chain_tx_polarity_flip_physical{232.0}=0x1 + +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x1 +phy_chain_tx_polarity_flip_physical{236.0}=0x1 + +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 + +phy_chain_tx_polarity_flip_physical{241.0}=0x0 +phy_chain_tx_polarity_flip_physical{242.0}=0x1 +phy_chain_tx_polarity_flip_physical{243.0}=0x0 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 + +phy_chain_tx_polarity_flip_physical{245.0}=0x1 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x0 +phy_chain_tx_polarity_flip_physical{248.0}=0x0 + +phy_chain_tx_polarity_flip_physical{249.0}=0x0 +phy_chain_tx_polarity_flip_physical{250.0}=0x0 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x0 + +phy_chain_tx_polarity_flip_physical{253.0}=0x1 +phy_chain_tx_polarity_flip_physical{254.0}=0x0 +phy_chain_tx_polarity_flip_physical{255.0}=0x0 +phy_chain_tx_polarity_flip_physical{256.0}=0x0 + +# RX polarity +phy_chain_rx_polarity_flip_physical{193.0}=0x1 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x0 +phy_chain_rx_polarity_flip_physical{196.0}=0x1 + +phy_chain_rx_polarity_flip_physical{197.0}=0x1 +phy_chain_rx_polarity_flip_physical{198.0}=0x1 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x1 + +phy_chain_rx_polarity_flip_physical{201.0}=0x1 +phy_chain_rx_polarity_flip_physical{202.0}=0x0 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x1 + +phy_chain_rx_polarity_flip_physical{205.0}=0x1 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x0 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 + +phy_chain_rx_polarity_flip_physical{209.0}=0x1 +phy_chain_rx_polarity_flip_physical{210.0}=0x1 +phy_chain_rx_polarity_flip_physical{211.0}=0x0 +phy_chain_rx_polarity_flip_physical{212.0}=0x1 + +phy_chain_rx_polarity_flip_physical{213.0}=0x0 +phy_chain_rx_polarity_flip_physical{214.0}=0x1 +phy_chain_rx_polarity_flip_physical{215.0}=0x1 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 + +phy_chain_rx_polarity_flip_physical{217.0}=0x1 +phy_chain_rx_polarity_flip_physical{218.0}=0x0 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{220.0}=0x1 + +phy_chain_rx_polarity_flip_physical{221.0}=0x1 +phy_chain_rx_polarity_flip_physical{222.0}=0x1 +phy_chain_rx_polarity_flip_physical{223.0}=0x0 +phy_chain_rx_polarity_flip_physical{224.0}=0x0 + +phy_chain_rx_polarity_flip_physical{225.0}=0x1 +phy_chain_rx_polarity_flip_physical{226.0}=0x1 +phy_chain_rx_polarity_flip_physical{227.0}=0x1 +phy_chain_rx_polarity_flip_physical{228.0}=0x0 + +phy_chain_rx_polarity_flip_physical{229.0}=0x1 +phy_chain_rx_polarity_flip_physical{230.0}=0x0 +phy_chain_rx_polarity_flip_physical{231.0}=0x0 +phy_chain_rx_polarity_flip_physical{232.0}=0x1 + +phy_chain_rx_polarity_flip_physical{233.0}=0x1 +phy_chain_rx_polarity_flip_physical{234.0}=0x1 +phy_chain_rx_polarity_flip_physical{235.0}=0x1 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 + +phy_chain_rx_polarity_flip_physical{237.0}=0x0 +phy_chain_rx_polarity_flip_physical{238.0}=0x1 +phy_chain_rx_polarity_flip_physical{239.0}=0x0 +phy_chain_rx_polarity_flip_physical{240.0}=0x0 + +phy_chain_rx_polarity_flip_physical{241.0}=0x0 +phy_chain_rx_polarity_flip_physical{242.0}=0x1 +phy_chain_rx_polarity_flip_physical{243.0}=0x0 +phy_chain_rx_polarity_flip_physical{244.0}=0x1 + +phy_chain_rx_polarity_flip_physical{245.0}=0x1 +phy_chain_rx_polarity_flip_physical{246.0}=0x0 +phy_chain_rx_polarity_flip_physical{247.0}=0x0 +phy_chain_rx_polarity_flip_physical{248.0}=0x1 + +phy_chain_rx_polarity_flip_physical{249.0}=0x0 +phy_chain_rx_polarity_flip_physical{250.0}=0x0 +phy_chain_rx_polarity_flip_physical{251.0}=0x1 +phy_chain_rx_polarity_flip_physical{252.0}=0x0 + +phy_chain_rx_polarity_flip_physical{253.0}=0x1 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x0 +phy_chain_rx_polarity_flip_physical{256.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{193.0}=0x2031 +phy_chain_tx_lane_map_physical{197.0}=0x1203 +phy_chain_tx_lane_map_physical{201.0}=0x0213 +phy_chain_tx_lane_map_physical{205.0}=0x3210 + +phy_chain_tx_lane_map_physical{209.0}=0x1023 +phy_chain_tx_lane_map_physical{213.0}=0x1203 +phy_chain_tx_lane_map_physical{217.0}=0x0213 +phy_chain_tx_lane_map_physical{221.0}=0x3102 + +phy_chain_tx_lane_map_physical{225.0}=0x2031 +phy_chain_tx_lane_map_physical{229.0}=0x1023 +phy_chain_tx_lane_map_physical{233.0}=0x1320 +phy_chain_tx_lane_map_physical{237.0}=0x2013 + +phy_chain_tx_lane_map_physical{241.0}=0x1023 +phy_chain_tx_lane_map_physical{245.0}=0x1203 +phy_chain_tx_lane_map_physical{249.0}=0x3120 +phy_chain_tx_lane_map_physical{253.0}=0x3210 + +# RX lane swap +phy_chain_rx_lane_map_physical{193.0}=0x1032 +phy_chain_rx_lane_map_physical{197.0}=0x1230 +phy_chain_rx_lane_map_physical{201.0}=0x0321 +phy_chain_rx_lane_map_physical{205.0}=0x3201 + +phy_chain_rx_lane_map_physical{209.0}=0x3201 +phy_chain_rx_lane_map_physical{213.0}=0x2031 +phy_chain_rx_lane_map_physical{217.0}=0x0321 +phy_chain_rx_lane_map_physical{221.0}=0x3201 + +phy_chain_rx_lane_map_physical{225.0}=0x2103 +phy_chain_rx_lane_map_physical{229.0}=0x2310 +phy_chain_rx_lane_map_physical{233.0}=0x0213 +phy_chain_rx_lane_map_physical{237.0}=0x1032 + +phy_chain_rx_lane_map_physical{241.0}=0x0321 +phy_chain_rx_lane_map_physical{245.0}=0x2301 +phy_chain_rx_lane_map_physical{249.0}=0x2103 +phy_chain_rx_lane_map_physical{253.0}=0x2013 + +physical_ports=64 +logical_ports=136 +uplink_ports=2 +dport_map_port_66=65 +dport_map_port_100=66 + +module_64ports=1 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/default_sku b/device/dell/x86_64-dellemc_z9264f_c3538-r0/default_sku new file mode 100644 index 000000000000..206373c042de --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/default_sku @@ -0,0 +1 @@ +DellEMC-Z9264f t1 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/installer.conf b/device/dell/x86_64-dellemc_z9264f_c3538-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/led_proc_init.soc b/device/dell/x86_64-dellemc_z9264f_c3538-r0/led_proc_init.soc new file mode 100644 index 000000000000..d38282b6508e --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/led_proc_init.soc @@ -0,0 +1,111 @@ +# LED microprocessor initialization for DellEMC-Z9264f + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=32 REMAP_PORT_2=33 REMAP_PORT_1=34 REMAP_PORT_0=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=36 REMAP_PORT_6=37 REMAP_PORT_5=38 REMAP_PORT_4=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=4 REMAP_PORT_10=5 REMAP_PORT_9=6 REMAP_PORT_8=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=0 REMAP_PORT_14=1 REMAP_PORT_13=2 REMAP_PORT_12=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=56 REMAP_PORT_18=57 REMAP_PORT_17=58 REMAP_PORT_16=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=60 REMAP_PORT_22=61 REMAP_PORT_21=62 REMAP_PORT_20=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=28 REMAP_PORT_26=29 REMAP_PORT_25=30 REMAP_PORT_24=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24 REMAP_PORT_30=25 REMAP_PORT_29=26 REMAP_PORT_28=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=48 REMAP_PORT_34=49 REMAP_PORT_33=50 REMAP_PORT_32=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=52 REMAP_PORT_38=53 REMAP_PORT_37=54 REMAP_PORT_36=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=20 REMAP_PORT_42=21 REMAP_PORT_41=22 REMAP_PORT_40=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=16 REMAP_PORT_46=17 REMAP_PORT_45=18 REMAP_PORT_44=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=40 REMAP_PORT_50=41 REMAP_PORT_49=42 REMAP_PORT_48=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=44 REMAP_PORT_54=45 REMAP_PORT_53=46 REMAP_PORT_52=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=12 REMAP_PORT_58=13 REMAP_PORT_57=14 REMAP_PORT_56=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=8 REMAP_PORT_62=9 REMAP_PORT_61=10 REMAP_PORT_60=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=38 REMAP_PORT_8=39 REMAP_PORT_11=36 REMAP_PORT_10=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=32 REMAP_PORT_14=33 REMAP_PORT_13=34 REMAP_PORT_12=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=8 REMAP_PORT_18=9 REMAP_PORT_17=10 REMAP_PORT_16=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=12 REMAP_PORT_22=13 REMAP_PORT_21=14 REMAP_PORT_20=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=44 REMAP_PORT_26=45 REMAP_PORT_25=46 REMAP_PORT_24=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=40 REMAP_PORT_30=41 REMAP_PORT_29=42 REMAP_PORT_28=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 REMAP_PORT_34=17 REMAP_PORT_33=18 REMAP_PORT_32=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 REMAP_PORT_38=21 REMAP_PORT_37=22 REMAP_PORT_36=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52 REMAP_PORT_42=53 REMAP_PORT_41=54 REMAP_PORT_40=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48 REMAP_PORT_46=49 REMAP_PORT_45=50 REMAP_PORT_44=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=24 REMAP_PORT_50=25 REMAP_PORT_49=26 REMAP_PORT_48=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=28 REMAP_PORT_54=29 REMAP_PORT_53=30 REMAP_PORT_52=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=60 REMAP_PORT_58=61 REMAP_PORT_57=62 REMAP_PORT_56=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56 REMAP_PORT_62=57 REMAP_PORT_61=58 REMAP_PORT_60=59 +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=60 REMAP_PORT_2=61 REMAP_PORT_1=62 REMAP_PORT_0=63 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=56 REMAP_PORT_6=57 REMAP_PORT_5=58 REMAP_PORT_4=59 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=24 REMAP_PORT_10=25 REMAP_PORT_9=26 REMAP_PORT_8=27 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=28 REMAP_PORT_14=29 REMAP_PORT_13=30 REMAP_PORT_12=31 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=52 REMAP_PORT_18=53 REMAP_PORT_17=54 REMAP_PORT_16=55 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=48 REMAP_PORT_22=49 REMAP_PORT_21=50 REMAP_PORT_20=51 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=16 REMAP_PORT_26=17 REMAP_PORT_25=18 REMAP_PORT_24=19 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=20 REMAP_PORT_30=21 REMAP_PORT_29=22 REMAP_PORT_28=23 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=44 REMAP_PORT_34=45 REMAP_PORT_33=46 REMAP_PORT_32=47 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=40 REMAP_PORT_38=41 REMAP_PORT_37=42 REMAP_PORT_36=43 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=8 REMAP_PORT_42=9 REMAP_PORT_41=10 REMAP_PORT_40=11 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=12 REMAP_PORT_46=13 REMAP_PORT_45=14 REMAP_PORT_44=15 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=36 REMAP_PORT_50=37 REMAP_PORT_49=38 REMAP_PORT_48=39 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=32 REMAP_PORT_54=33 REMAP_PORT_53=34 REMAP_PORT_52=35 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=0 REMAP_PORT_58=1 REMAP_PORT_57=2 REMAP_PORT_56=3 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=4 REMAP_PORT_62=5 REMAP_PORT_61=6 REMAP_PORT_60=7 +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28 REMAP_PORT_2=29 REMAP_PORT_1=30 REMAP_PORT_0=31 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24 REMAP_PORT_6=25 REMAP_PORT_5=26 REMAP_PORT_4=27 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 REMAP_PORT_10=57 REMAP_PORT_9=58 REMAP_PORT_8=59 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 REMAP_PORT_14=61 REMAP_PORT_13=62 REMAP_PORT_12=63 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=4 REMAP_PORT_18=5 REMAP_PORT_17=6 REMAP_PORT_16=7 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=0 REMAP_PORT_22=1 REMAP_PORT_21=2 REMAP_PORT_20=3 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=32 REMAP_PORT_26=33 REMAP_PORT_25=34 REMAP_PORT_24=35 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=36 REMAP_PORT_30=37 REMAP_PORT_29=38 REMAP_PORT_28=39 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=12 REMAP_PORT_34=13 REMAP_PORT_33=14 REMAP_PORT_32=15 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=8 REMAP_PORT_38=9 REMAP_PORT_37=10 REMAP_PORT_36=11 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40 REMAP_PORT_42=41 REMAP_PORT_41=42 REMAP_PORT_40=43 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44 REMAP_PORT_46=45 REMAP_PORT_45=46 REMAP_PORT_44=47 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=20 REMAP_PORT_50=21 REMAP_PORT_49=22 REMAP_PORT_48=23 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=16 REMAP_PORT_54=17 REMAP_PORT_53=18 REMAP_PORT_52=19 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=48 REMAP_PORT_58=49 REMAP_PORT_57=50 REMAP_PORT_56=51 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=52 REMAP_PORT_62=53 REMAP_PORT_61=54 REMAP_PORT_60=55 +m CMIC_LEDUP4_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=1 REMAP_PORT_1=0 + +led 0 stop +led 0 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 1 auto on +led 1 start + +led 2 stop +led 2 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 2 auto on +led 2 start + +led 3 stop +led 3 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 3 auto on +led 3 start diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/eeprom.py b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/eeprom.py new file mode 100644 index 000000000000..37ce00a0ca6c --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# DellEMC Z9264f +# +# 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/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/psuutil.py b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/psuutil.py new file mode 100644 index 000000000000..d3fe5cf64240 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/psuutil.py @@ -0,0 +1,97 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path +import logging +import commands + + +Z9264F_MAX_PSUS = 2 +IPMI_SENSOR_DATA = "ipmitool sdr list" +PSU_PRESENCE = "PSU{0}_state" +# Use this for older firmware +# PSU_PRESENCE="PSU{0}_prsnt" +ipmi_sdr_list = "" + + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + # Fetch a BMC register + def get_pmc_register(self, reg_name): + + status = 1 + global ipmi_sdr_list + ipmi_dev_node = "/dev/pmi0" + + ipmi_cmd = IPMI_SENSOR_DATA + status, ipmi_sdr_list = commands.getstatusoutput(ipmi_cmd) + + if status: + logging.error('Failed to execute:' + ipmi_sdr_list) + sys.exit(0) + + for item in ipmi_sdr_list.split("\n"): + if reg_name in item: + output = item.strip() + + if not output: + print('\nFailed to fetch: ' + reg_name + ' sensor ') + sys.exit(0) + + output = output.split('|')[1] + + logging.basicConfig(level=logging.DEBUG) + return output + + + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + Z9264F_MAX_PSUS = 2 + return Z9264F_MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + #Until psu_status is implemented this is hardcoded temporarily + + status = 1 + return status + + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_reg_name = PSU_PRESENCE.format(index) + psu_status = int(self.get_pmc_register(psu_reg_name),16) + if (psu_status != 'ERR'): + # Check for PSU presence + if (psu_status): + status = 1 + return status diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/sfputil.py new file mode 100644 index 000000000000..cbd723717afd --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/sfputil.py @@ -0,0 +1,200 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import struct + import sys + import getopt + import time + from sonic_sfp.sfputilbase import SfpUtilBase + from os import * + from mmap import * + +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 = 32 + + BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" + + _port_to_eeprom_mapping = {} + + @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 port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def pci_mem_read(self, mm, offset): + mm.seek(offset) + read_data_stream=mm.read(4) + reg_val=struct.unpack('I',read_data_stream) + mem_val = str(reg_val)[1:-2] + # print "reg_val read:%x"%reg_val + return mem_val + + def pci_mem_write(self, mm, offset, data): + mm.seek(offset) + # print "data to write:%x"%data + mm.write(struct.pack('I',data)) + + def pci_set_value(self, resource, val, offset): + fd=open(resource,O_RDWR) + mm=mmap(fd,0) + return self.pci_mem_write(mm,offset,val) + + def pci_get_value(self, resource, offset): + fd=open(resource,O_RDWR) + mm=mmap(fd,0) + return self.pci_mem_read(mm, offset) + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(0, self.port_end + 1): + port_num = x + 2 + self.port_to_eeprom_mapping[x] = eeprom_path.format( + port_num) + port_num = 0 + + 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 + + # Port offset starts with 0x4004 + port_offset = 16388 + ((port_num) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == "" ): + return False + + # Mask off 4th bit for presence + mask = (1 << 4) + + # 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 offset starts with 0x4000 + port_offset = 16384 + ((port_num) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == "" ): + return False + + # Mask off 4th bit for presence + mask = (1 << 6) + + # 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 offset starts with 0x4000 + port_offset = 16384 + ((port_num) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == "" ): + return False + + # Mask off 4th bit for presence + mask = (1 << 6) + + # 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 + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + 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 offset starts with 0x4000 + port_offset = 16384 + ((port_num) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == "" ): + return False + + # Mask off 4th bit for presence + mask = (1 << 6) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + # Sleep 1 second to allow it to settle + time.sleep(1) + + reg_value = reg_value | mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/port_config.ini b/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/port_config.ini new file mode 100644 index 000000000000..ace4228d861a --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias +Ethernet0 65 twentyfiveGigE1 +Ethernet4 66 twentyfiveGigE2 +Ethernet8 67 twentyfiveGigE3 +Ethernet12 68 twentyfiveGigE4 +Ethernet16 69 twentyfiveGigE5 +Ethernet20 70 twentyfiveGigE6 +Ethernet24 71 twentyfiveGigE7 +Ethernet28 72 twentyfiveGigE8 +Ethernet32 81 twentyfiveGigE9 +Ethernet36 82 twentyfiveGigE10 +Ethernet40 83 twentyfiveGigE11 +Ethernet44 84 twentyfiveGigE12 +Ethernet48 85 twentyfiveGigE13 +Ethernet52 86 twentyfiveGigE14 +Ethernet56 87 twentyfiveGigE15 +Ethernet60 88 twentyfiveGigE16 +Ethernet64 33 twentyfiveGigE17 +Ethernet68 34 twentyfiveGigE18 +Ethernet72 35 twentyfiveGigE19 +Ethernet76 36 twentyfiveGigE20 +Ethernet80 37 twentyfiveGigE21 +Ethernet84 38 twentyfiveGigE22 +Ethernet88 39 twentyfiveGigE23 +Ethernet92 40 twentyfiveGigE24 +Ethernet96 42 twentyfiveGigE25 +Ethernet100 41 twentyfiveGigE26 +Ethernet104 44 twentyfiveGigE27 +Ethernet108 43 twentyfiveGigE28 +Ethernet112 49 twentyfiveGigE29 +Ethernet116 50 twentyfiveGigE30 +Ethernet120 51 twentyfiveGigE31 +Ethernet124 52 twentyfiveGigE32 +Ethernet128 53 twentyfiveGigE33 +Ethernet132 54 twentyfiveGigE34 +Ethernet136 55 twentyfiveGigE35 +Ethernet140 56 twentyfiveGigE36 +Ethernet144 97 twentyfiveGigE37 +Ethernet148 98 twentyfiveGigE38 +Ethernet152 99 twentyfiveGigE39 +Ethernet156 100 twentyfiveGigE40 +Ethernet160 101 twentyfiveGigE41 +Ethernet164 102 twentyfiveGigE42 +Ethernet168 103 twentyfiveGigE43 +Ethernet172 104 twentyfiveGigE44 +Ethernet176 105 twentyfiveGigE45 +Ethernet180 106 twentyfiveGigE46 +Ethernet184 107 twentyfiveGigE47 +Ethernet188 108 twentyfiveGigE48 +Ethernet192 117,118,119,120 hundredGigE51 +Ethernet196 109,110,111,112 hundredGigE51 +Ethernet200 5,6,7,8 hundredGigE51 +Ethernet204 1,2,3,4 hundredGigE52 +Ethernet208 21,22,23,24 hundredGigE53 +Ethernet212 9,10,11,12 hundredGigE54 diff --git a/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/sai.profile b/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/sai.profile new file mode 100644 index 000000000000..094e2d2cda01 --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-ag5648-48x25G+6x100G.config.bcm diff --git a/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/th-ag5648-48x25G+6x100G.config.bcm b/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/th-ag5648-48x25G+6x100G.config.bcm new file mode 100644 index 000000000000..86afb258fd1b --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/th-ag5648-48x25G+6x100G.config.bcm @@ -0,0 +1,277 @@ +os=unix +schan_intr_enable=0 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +pbmp_oversubscribe=0x000fffc0000ffff0003ffffc0000001e +pbmp_xport_xe=0x000fffc0000ffff0003ffffc0000001e + +# Tile-0: 1, 5, 9, 21 +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=21:100 + +## TX lane swap +xgxs_tx_lane_map_1=0x0123 +xgxs_tx_lane_map_2=0x2301 +xgxs_tx_lane_map_3=0x0123 +xgxs_tx_lane_map_4=0x1302 + +## RX lane swap +xgxs_rx_lane_map_1=0x0123 +xgxs_rx_lane_map_2=0x2301 +xgxs_rx_lane_map_3=0x0123 +xgxs_rx_lane_map_4=0x2031 + +## TX polarity +phy_xaui_tx_polarity_flip_1=0x0 +phy_xaui_tx_polarity_flip_2=0xf +phy_xaui_tx_polarity_flip_3=0x0 +phy_xaui_tx_polarity_flip_4=0xf + +## RX polarity +phy_xaui_rx_polarity_flip_1=0x0 +phy_xaui_rx_polarity_flip_2=0xf +phy_xaui_rx_polarity_flip_3=0x0 +phy_xaui_rx_polarity_flip_4=0xf + + +# Tile-1: 8, 9, 11, 12, 13 +portmap_34=33:25 +portmap_35=34:25 +portmap_36=35:25 +portmap_37=36:25 +portmap_38=37:25 +portmap_39=38:25 +portmap_40=39:25 +portmap_41=40:25 +portmap_42=41:25 +portmap_43=42:25 +portmap_44=43:25 +portmap_45=44:25 +portmap_46=49:25 +portmap_47=50:25 +portmap_48=51:25 +portmap_49=52:25 +portmap_50=53:25 +portmap_51=54:25 +portmap_52=55:25 +portmap_53=56:25 + + +## TX lane swap +xgxs_tx_lane_map_34=0x3210 +xgxs_tx_lane_map_38=0x0123 +xgxs_tx_lane_map_42=0x2031 +xgxs_tx_lane_map_46=0x0123 +xgxs_tx_lane_map_50=0x0123 + +## RX lane swap +xgxs_rx_lane_map_34=0x2301 +xgxs_rx_lane_map_38=0x1032 +xgxs_rx_lane_map_42=0x0213 +xgxs_rx_lane_map_46=0x2301 +xgxs_rx_lane_map_50=0x2301 + + +## TX polarity +phy_xaui_tx_polarity_flip_34=0x0 +phy_xaui_tx_polarity_flip_35=0x1 +phy_xaui_tx_polarity_flip_36=0x0 +phy_xaui_tx_polarity_flip_37=0x1 + +phy_xaui_tx_polarity_flip_38=0x1 +phy_xaui_tx_polarity_flip_39=0x0 +phy_xaui_tx_polarity_flip_40=0x1 +phy_xaui_tx_polarity_flip_41=0x0 + +phy_xaui_tx_polarity_flip_42=0x1 +phy_xaui_tx_polarity_flip_43=0x0 +phy_xaui_tx_polarity_flip_44=0x1 +phy_xaui_tx_polarity_flip_45=0x0 + +phy_xaui_tx_polarity_flip_46=0x0 +phy_xaui_tx_polarity_flip_47=0x1 +phy_xaui_tx_polarity_flip_48=0x0 +phy_xaui_tx_polarity_flip_49=0x1 + +phy_xaui_tx_polarity_flip_50=0x0 +phy_xaui_tx_polarity_flip_51=0x1 +phy_xaui_tx_polarity_flip_52=0x0 +phy_xaui_tx_polarity_flip_53=0x1 + + +## RX polarity +phy_xaui_rx_polarity_flip_34=0x0 +phy_xaui_rx_polarity_flip_35=0x1 +phy_xaui_rx_polarity_flip_36=0x0 +phy_xaui_rx_polarity_flip_37=0x1 + +phy_xaui_rx_polarity_flip_38=0x1 +phy_xaui_rx_polarity_flip_39=0x0 +phy_xaui_rx_polarity_flip_40=0x1 +phy_xaui_rx_polarity_flip_41=0x0 + +phy_xaui_rx_polarity_flip_42=0x1 +phy_xaui_rx_polarity_flip_43=0x0 +phy_xaui_rx_polarity_flip_44=0x1 +phy_xaui_rx_polarity_flip_45=0x0 + +phy_xaui_rx_polarity_flip_46=0x0 +phy_xaui_rx_polarity_flip_47=0x1 +phy_xaui_rx_polarity_flip_48=0x0 +phy_xaui_rx_polarity_flip_49=0x1 + +phy_xaui_rx_polarity_flip_50=0x0 +phy_xaui_rx_polarity_flip_51=0x1 +phy_xaui_rx_polarity_flip_52=0x0 +phy_xaui_rx_polarity_flip_53=0x1 + + +# Tile-2: 16, 17, 20, 21 +portmap_68=65:25 +portmap_69=66:25 +portmap_70=67:25 +portmap_71=68:25 +portmap_72=69:25 +portmap_73=70:25 +portmap_74=71:25 +portmap_75=72:25 +portmap_76=81:25 +portmap_77=82:25 +portmap_78=83:25 +portmap_79=84:25 +portmap_80=85:25 +portmap_81=86:25 +portmap_82=87:25 +portmap_83=88:25 + + +## TX lane swap +xgxs_tx_lane_map_68=0x3210 +xgxs_tx_lane_map_72=0x0123 +xgxs_tx_lane_map_76=0x0123 +xgxs_tx_lane_map_80=0x3210 + +## RX lane swap +xgxs_rx_lane_map_68=0x1032 +xgxs_rx_lane_map_72=0x2301 +xgxs_rx_lane_map_76=0x0123 +xgxs_rx_lane_map_80=0x3210 + + +## TX polarity +phy_xaui_tx_polarity_flip_68=0x0 +phy_xaui_tx_polarity_flip_69=0x1 +phy_xaui_tx_polarity_flip_70=0x0 +phy_xaui_tx_polarity_flip_71=0x1 + +phy_xaui_tx_polarity_flip_72=0x0 +phy_xaui_tx_polarity_flip_73=0x1 +phy_xaui_tx_polarity_flip_74=0x0 +phy_xaui_tx_polarity_flip_75=0x1 + +phy_xaui_tx_polarity_flip_76=0x0 +phy_xaui_tx_polarity_flip_77=0x1 +phy_xaui_tx_polarity_flip_78=0x0 +phy_xaui_tx_polarity_flip_79=0x1 + +phy_xaui_tx_polarity_flip_80=0x1 +phy_xaui_tx_polarity_flip_81=0x0 +phy_xaui_tx_polarity_flip_82=0x1 +phy_xaui_tx_polarity_flip_83=0x0 + +## RX polarity +phy_xaui_rx_polarity_flip_68=0x0 +phy_xaui_rx_polarity_flip_69=0x1 +phy_xaui_rx_polarity_flip_70=0x0 +phy_xaui_rx_polarity_flip_71=0x1 + +phy_xaui_rx_polarity_flip_72=0x0 +phy_xaui_rx_polarity_flip_73=0x1 +phy_xaui_rx_polarity_flip_74=0x0 +phy_xaui_rx_polarity_flip_75=0x1 + +phy_xaui_rx_polarity_flip_76=0x0 +phy_xaui_rx_polarity_flip_77=0x1 +phy_xaui_rx_polarity_flip_78=0x0 +phy_xaui_rx_polarity_flip_79=0x1 + +phy_xaui_rx_polarity_flip_80=0x1 +phy_xaui_rx_polarity_flip_81=0x0 +phy_xaui_rx_polarity_flip_82=0x1 +phy_xaui_rx_polarity_flip_83=0x0 + + +# Tile-3: 24, 25, 26; 27, 29 +portmap_102=97:25 +portmap_103=98:25 +portmap_104=99:25 +portmap_105=100:25 +portmap_106=101:25 +portmap_107=102:25 +portmap_108=103:25 +portmap_109=104:25 +portmap_110=105:25 +portmap_111=106:25 +portmap_112=107:25 +portmap_113=108:25 +portmap_114=109:100 +portmap_115=117:100 + + +## TX lane swap +xgxs_tx_lane_map_102=0x0123 +xgxs_tx_lane_map_106=0x3210 +xgxs_tx_lane_map_110=0x0123 +xgxs_tx_lane_map_114=0x3120 +xgxs_tx_lane_map_115=0x2301 + +## RX lane swap +xgxs_rx_lane_map_102=0x0123 +xgxs_rx_lane_map_106=0x3210 +xgxs_rx_lane_map_110=0x0123 +xgxs_rx_lane_map_114=0x3120 +xgxs_rx_lane_map_115=0x2301 + +## TX polarity +phy_xaui_tx_polarity_flip_102=0 +phy_xaui_tx_polarity_flip_103=1 +phy_xaui_tx_polarity_flip_104=0 +phy_xaui_tx_polarity_flip_105=1 + +phy_xaui_tx_polarity_flip_106=1 +phy_xaui_tx_polarity_flip_107=0 +phy_xaui_tx_polarity_flip_108=1 +phy_xaui_tx_polarity_flip_109=0 + +phy_xaui_tx_polarity_flip_110=0 +phy_xaui_tx_polarity_flip_111=1 +phy_xaui_tx_polarity_flip_112=0 +phy_xaui_tx_polarity_flip_113=1 + +phy_xaui_tx_polarity_flip_114=0xf +phy_xaui_tx_polarity_flip_115=0xf + +## RX polarity +phy_xaui_rx_polarity_flip_102=0 +phy_xaui_rx_polarity_flip_103=1 +phy_xaui_rx_polarity_flip_104=0 +phy_xaui_rx_polarity_flip_105=1 + +phy_xaui_rx_polarity_flip_106=1 +phy_xaui_rx_polarity_flip_107=0 +phy_xaui_rx_polarity_flip_108=1 +phy_xaui_rx_polarity_flip_109=0 + +phy_xaui_rx_polarity_flip_110=0 +phy_xaui_rx_polarity_flip_111=1 +phy_xaui_rx_polarity_flip_112=0 +phy_xaui_rx_polarity_flip_113=1 + +phy_xaui_rx_polarity_flip_114=0xf +phy_xaui_rx_polarity_flip_115=0xf diff --git a/device/delta/x86_64-delta_ag5648-r0/default_sku b/device/delta/x86_64-delta_ag5648-r0/default_sku new file mode 100644 index 000000000000..c4ce98e35557 --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/default_sku @@ -0,0 +1 @@ +Delta-ag5648 t1 diff --git a/device/delta/x86_64-delta_ag5648-r0/fancontrol b/device/delta/x86_64-delta_ag5648-r0/fancontrol new file mode 100644 index 000000000000..2666ad97d9ce --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=10 +DEVPATH=hwmon1=/sys/bus/i2c/devices +DEVNAME=hwmon1=emc2305 +FCTEMPS=DEVPATH/2-004d/hwmon/hwmon*/temp1_input DEVPATH/3-0049/hwmon/hwmon*/temp1_input DEVPATH/3-004b/hwmon/hwmon*/temp1_input DEVPATH/3-004c/hwmon/hwmon*/temp1_input DEVPATH/3-004e/hwmon/hwmon*/temp1_input DEVPATH/3-004f/hwmon/hwmon*/temp1_input DEVPATH/6-0059/temp1_input DEVPATH/6-0058/temp1_input + +FCFANS=DEVPATH/3-004d/fan1_input DEVPATH/3-004d/fan2_input DEVPATH/3-004d/fan3_input DEVPATH/3-004d/fan4_input DEVPATH/5-004d/fan1_input DEVPATH/5-004d/fan2_input DEVPATH/5-004d/fan3_input DEVPATH/5-004d/fan4_input +MINTEMP=20 +MAXTEMP=60 +MINSTART=75 +MINSTOP=22 diff --git a/device/delta/x86_64-delta_ag5648-r0/fancontrol.service b/device/delta/x86_64-delta_ag5648-r0/fancontrol.service new file mode 100755 index 000000000000..ace4392f436d --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/fancontrol.service @@ -0,0 +1,262 @@ +#!/bin/bash +# +# Simple script implementing a temperature dependent fan speed control +# Supported Linux kernel versions: 2.6.5 and later +# +# Version 0.70 +# +# Usage: fancontrol.service [CONFIGFILE] +# +# Dependencies: +# bash, egrep, sed, cut, sleep, readlink, lm_sensors :) +# +# Please send any questions, comments or success stories to +# marius.reiner@hdev.de +# Thanks! +# +# For configuration instructions and warnings please see fancontrol.txt, which +# can be found in the doc/ directory or at the website mentioned above. +# +# +# Copyright 2003 Marius Reiner +# Copyright (C) 2007-2009 Jean Delvare +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# +# + +PIDFILE="/var/run/fancontrol.pid" + +#DEBUG=1 +MAX=255 + +function LoadConfig +{ + local fcvcount fcv + + echo "Loading configuration from $1 ..." + if [ ! -r "$1" ] + then + echo "Error: Can't read configuration file" >&2 + exit 1 + fi + + # grep configuration from file + INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g'` + DEVPATH=`egrep '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g'` + DEVNAME=`egrep '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g'` + FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g'` + MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g'` + MAXTEMP=`egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g'` + MINSTART=`egrep '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g'` + MINSTOP=`egrep '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g'` + HWMON=$( echo "$DEVPATH" | sed 's/=.*$//g') + FCDEVPATH=$( echo "$DEVPATH" | sed 's/^.*=//g') + FCMINTEMP=$MINTEMP + FCMAXTEMP=$MAXTEMP + FCMINSTART=$MINSTART + FCMINSTOP=$MINSTOP + + FCFANS=`egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g'` + + # Check whether all mandatory settings are set + if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]] + then + echo "Some mandatory settings missing, please check your config file!" >&2 + exit 1 + fi + if [ "$INTERVAL" -le 0 ] + then + echo "Error in configuration file:" >&2 + echo "INTERVAL must be at least 1" >&2 + exit 1 + fi + + # write settings to arrays for easier use and print them + echo "Common settings:" + + temp_string=$FCTEMPS + + let fcvcount=0 + for fcv in $FCTEMPS + do + fcvcount=$((fcvcount+1)) + AFCTEMP[$fcvcount]=$( echo "$temp_string" | cut -d" " -f $fcvcount ) + AFCTEMP[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/DEVPATH/\/sys\/bus\/i2c\/devices/g' ) + AFCTEMP_PATH[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/DEVPATH/\/sys\/bus\/i2c\/devices/g' ) + + #if [ $fcvcount -eq 5 ];then + #echo "0x00" > '/sys/bus/i2c/devices/6-0058/psu_select_member' + # AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} ) + #elif [ $fcvcount -eq 6 ];then + #echo "0x20" > '/sys/bus/i2c/devices/6-0058/psu_select_member' + # AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} ) + #else + # AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} ) + #fi + AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} ) + AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 )) + echo "AFCTEMP[$fcvcount]=${AFCTEMP[$fcvcount]} (Celsius)" + done + + fan_string=$FCFANS + fcvcount=0 + zero=0 + for fcv in $FCFANS + do + fcvcount=$((fcvcount+1)) + AFCFAN[$fcvcount]=$( echo "$fan_string" | cut -d" " -f $fcvcount ) + AFCFAN_PATH[$fcvcount]=$( echo "${AFCFAN[$fcvcount]}" | sed 's/DEVPATH/\/sys\/bus\/i2c\/devices/g' ) + AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_PATH[$fcvcount]}" | sed 's/DEVPATH/\/sys\/bus\/i2c\/devices/g' ) + AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_TARGET[$fcvcount]}" | sed 's/$/_percentage/g') + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + if [ "${AFCFAN[$fcvcount]}" == 960 ] + then + AFCFAN[$fcvcount]=$zero + fi + echo "AFCFAN[$fcvcount]=${AFCFAN[$fcvcount]} (rpm)" + done + echo "INTERVAL=$INTERVAL" + echo "DEVPATH=$FCDEVPATH" + echo "MINTEMP=$FCMINTEMP" + echo "MAXTEMP=$FCMAXTEMP" + echo "MINSTART=$FCMINSTART" + echo "MINSTOP=$FCMINSTOP" +} + +# Check that all referenced sysfs files exist +function CheckFiles +{ + local outdated=0 fcvcount tsen fan + if [ $outdated -eq 1 ] + then + echo >&2 + echo "At least one referenced file is missing. Either some required kernel" >&2 + echo "modules haven't been loaded, or your configuration file is outdated." >&2 + echo "In the latter case, you should run pwmconfig again." >&2 + fi + return $outdated +} + +LoadConfig $1 + +# Detect path to sensors +if [ ! -d $DIR ] +then + echo $0: 'No sensors found! (did you load the necessary modules?)' >&2 + exit 1 +fi +cd $DIR + +# Check for configuration change +if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ] +then + echo "Configuration is too old, please run pwmconfig again" >&2 + exit 1 +fi +if [ "$DIR" = "/" -a -n "$DEVPATH" ] +then + echo "Unneeded DEVPATH with absolute device paths" >&2 + exit 1 +fi +CheckFiles || exit 1 + +if [ -f "$PIDFILE" ] +then + echo "File $PIDFILE exists, is fancontrol already running?" >&2 + exit 1 +fi +echo $$ > "$PIDFILE" + + +# main function +function UpdateThermalSensors +{ + echo "" + TEMP_HIGHEST=0 + FAN_PERCENTAGE=0 + + for i in ${AFCTEMP_PATH[@]}; do + if (( $(cat $i) > $TEMP_HIGHEST )); then + TEMP_HIGHEST=$(cat $i); + fi; + done + TEMP_HIGHEST=$((TEMP_HIGHEST/1000)) + echo "The highest temperature of thermal sensors: $TEMP_HIGHEST C" + +} + +function UpdateFanSpeeds +{ + if [ $TEMP_HIGHEST -lt 51 ]; then #TEMP<=50 + FAN_PERCENTAGE=40 + elif [ $TEMP_HIGHEST -lt 56 -a $TEMP_HIGHEST -gt 50 ]; then #50 ${AFCFAN_TARGET[$fcvcount]} + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + + if [ "${AFCFAN[$fcvcount]}" == 960 ] + then + AFCFAN[$fcvcount]=$zero + fi + echo "AFCFAN[$fcvcount]=${AFCFAN[$fcvcount]} (rpm)" + done + + if [ $TEMP_HIGHEST -lt 51 ]; then #TEMP<=50 + FAN_ON_PSU_PERCENTAGE=50 + elif [ $TEMP_HIGHEST -lt 100 -a $TEMP_HIGHEST -gt 50 ]; then #50 '/sys/bus/i2c/devices/4-0058/psu_select_member' + echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/6-0059/fan1_set_percentage' + echo "PSU fan1 =$( cat '/sys/bus/i2c/devices/6-0059/fan1_input' ) (rpm)" + #Set speed to PSU_FAN2 + #echo "0x20" > '/sys/bus/i2c/devices/6-0058/psu_select_member' + echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/6-0058/fan1_set_percentage' + echo "PSU fan2 =$( cat '/sys/bus/i2c/devices/6-0058/fan1_input' ) (rpm)" + + rm -f "$PIDFILE" +} +# main loop calling the main function at specified intervals +while true +do + UpdateThermalSensors + UpdateFanSpeeds + echo "Sleep $INTERVAL seconds ..." + # Sleep while still handling signals + sleep $INTERVAL & + wait $! +done diff --git a/device/delta/x86_64-delta_ag5648-r0/installer.conf b/device/delta/x86_64-delta_ag5648-r0/installer.conf new file mode 100644 index 000000000000..fa2af8b7a007 --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_SPEED=115200 diff --git a/device/delta/x86_64-delta_ag5648-r0/led_proc_init.soc b/device/delta/x86_64-delta_ag5648-r0/led_proc_init.soc new file mode 100755 index 000000000000..a329017fbde8 --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/led_proc_init.soc @@ -0,0 +1,67 @@ +#AG5648 LED + +led 0 stop +led 0 prog \ + 02 00 60 E0 02 A0 60 E2 86 ED 02 00 60 E1 67 EF \ + 71 1F 2E E0 32 08 97 02 00 0E 02 60 E3 77 2A 2E \ + E0 32 08 97 02 00 0E 03 60 E3 2E E0 32 00 32 01 \ + B7 97 02 00 0E 00 12 E7 FE E1 50 67 EF 71 49 86 \ + E0 86 E1 06 E1 D2 04 74 2A 02 00 60 E1 12 E7 FE \ + E1 05 60 EC 12 E3 FE E1 05 0A 03 71 61 67 EB 77 \ + 63 67 CB 67 EF 71 76 12 E3 FE E1 05 0A 02 71 74 \ + 67 EB 77 76 67 CB 12 E3 FE E1 05 0A 01 71 87 67 \ + EB 67 EF 71 97 77 8D 67 CB 67 EF 71 97 86 E1 06 \ + E1 D2 04 74 4D 77 A5 06 E0 28 32 08 97 71 A3 67 \ + EB 77 A5 67 D7 06 E2 67 EF 71 B1 F2 04 60 E2 77 \ + B7 F2 01 60 E2 86 E0 06 E0 D2 24 74 0A 67 EB 67 \ + EB 67 EB 67 EB 67 EB 67 EB 3A 72 67 EF 71 E7 06 \ + EC D2 00 70 E7 77 DD 06 EC D2 00 70 EB 16 ED 99 \ + 99 1A 00 71 E7 77 EB 32 0F 87 57 32 0E 87 57 16 \ + E0 DA 0C 57 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog \ + 02 00 60 E0 02 A0 60 E2 86 E6 02 00 60 E1 2E E0 \ + 32 08 97 02 00 0E 03 60 E3 2E E0 32 00 32 01 B7 \ + 97 02 00 0E 00 12 E4 FE E1 50 12 E4 05 60 E5 12 \ + E3 05 0A 03 71 3A 67 83 77 3C 67 7F 12 E3 05 0A \ + 01 71 47 67 83 77 49 67 7F 06 E0 28 32 08 97 71 \ + 55 67 83 77 57 67 6F 06 E2 F2 01 60 E2 86 E0 06 \ + E0 D2 24 74 0A 67 83 67 83 67 83 67 83 3A 70 06 \ + E5 D2 00 70 83 16 E6 99 99 1A 00 71 7F 77 83 32 \ + 0F 87 57 32 0E 87 57 00 00 00 00 00 00 00 00 00 +led 1 auto on +led 1 start + +# LED0 port order remap +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=47 REMAP_PORT_1=47 REMAP_PORT_2=47 REMAP_PORT_3=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=47 REMAP_PORT_5=47 REMAP_PORT_6=47 REMAP_PORT_7=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=31 REMAP_PORT_9=30 REMAP_PORT_10=29 REMAP_PORT_11=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=47 REMAP_PORT_13=47 REMAP_PORT_14=47 REMAP_PORT_15=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 REMAP_PORT_17=47 REMAP_PORT_18=47 REMAP_PORT_19=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=35 REMAP_PORT_21=34 REMAP_PORT_22=33 REMAP_PORT_23=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=23 REMAP_PORT_25=22 REMAP_PORT_26=21 REMAP_PORT_27=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=27 REMAP_PORT_29=26 REMAP_PORT_30=25 REMAP_PORT_31=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=47 REMAP_PORT_33=47 REMAP_PORT_34=47 REMAP_PORT_35=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=15 REMAP_PORT_41=14 REMAP_PORT_42=13 REMAP_PORT_43=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=19 REMAP_PORT_49=18 REMAP_PORT_50=17 REMAP_PORT_51=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +# LED1 port order remap +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=19 REMAP_PORT_1=18 REMAP_PORT_2=17 REMAP_PORT_3=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=23 REMAP_PORT_5=22 REMAP_PORT_6=21 REMAP_PORT_7=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=26 REMAP_PORT_9=27 REMAP_PORT_10=24 REMAP_PORT_11=25 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=31 REMAP_PORT_17=30 REMAP_PORT_18=29 REMAP_PORT_19=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=35 REMAP_PORT_21=34 REMAP_PORT_22=33 REMAP_PORT_23=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=63 REMAP_PORT_25=63 REMAP_PORT_26=63 REMAP_PORT_27=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=63 REMAP_PORT_29=63 REMAP_PORT_30=63 REMAP_PORT_31=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=3 REMAP_PORT_33=2 REMAP_PORT_34=1 REMAP_PORT_35=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=7 REMAP_PORT_37=6 REMAP_PORT_38=5 REMAP_PORT_39=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=11 REMAP_PORT_49=10 REMAP_PORT_50=9 REMAP_PORT_51=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=15 REMAP_PORT_53=14 REMAP_PORT_54=13 REMAP_PORT_55=12 + diff --git a/device/delta/x86_64-delta_ag5648-r0/plugins/eeprom.py b/device/delta/x86_64-delta_ag5648-r0/plugins/eeprom.py new file mode 100644 index 000000000000..786e1fdc85e3 --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/plugins/eeprom.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# 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: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + _TLV_INFO_MAX_LEN = 256 + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-2/2-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/delta/x86_64-delta_ag5648-r0/plugins/psuutil.py b/device/delta/x86_64-delta_ag5648-r0/plugins/psuutil.py new file mode 100644 index 000000000000..0d17ff05681a --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/plugins/psuutil.py @@ -0,0 +1,56 @@ +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/6-00{}/" + self.psu_oper_status = "in1_input" + self.psu_presence = "i2cget -y 6 0x{} 0x00" + + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + if index is None: + return False + Base_bus_number = 57 + status = 0 + try: + with open(self.psu_path.format(index + Base_bus_number) + self.psu_oper_status, 'r') as power_status: + if int(power_status.read()) == 0 : + return False + else: + status = 1 + except IOError: + return False + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + Base_bus_number = 49 + status = 0 + try: + p = os.popen(self.psu_presence.format(index + Base_bus_number)+ "> /dev/null 2>&1") + if p.readline() != None: + status = 1 + p.close() + except IOError: + return False + return status == 1 + + diff --git a/device/delta/x86_64-delta_ag5648-r0/plugins/sfputil.py b/device/delta/x86_64-delta_ag5648-r0/plugins/sfputil.py new file mode 100644 index 000000000000..864977414251 --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/plugins/sfputil.py @@ -0,0 +1,211 @@ +# 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_START_QSFP = 48 + PORT_END = 53 + PORTS_IN_BLOCK = 54 + + EEPROM_OFFSET = 10 + + _port_to_eeprom_mapping = {} + + @property + def port_start(self): + return self.PORT_START + @property + def port_start_qsfp(self): + return self.PORT_START_QSFP + + @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): + if x > self.port_start_qsfp -1 and x < self.port_end + 1: + self.get_response(x) + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET) + SfpUtilBase.__init__(self) + + def get_response(self, port_num): + # Check for invalid port_num + if port_num < self.port_start_qsfp or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag5648-cpld.0/sfp_response", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # set the bit corresponding to our port + mask = (port_num + 1) % 8 - 1 + mask = 1 << mask + + # Convert our register value back to a hex string and write back + content = hex(mask) + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + 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/devices/platform/delta-ag5648-cpld.0/sfp_present") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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 + + try: + reg_file = open("/sys/devices/platform/delta-ag5648-cpld.0/sfp_lpmode") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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_qsfp or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag5648-cpld.0/sfp_lpmode", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/delta-ag5648-cpld.0/sfp_reset" + + # Check for invalid port_num + if port_num < self.port_start_qsfp 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 + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # 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: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "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 + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/delta/x86_64-delta_ag5648-r0/sensors.conf b/device/delta/x86_64-delta_ag5648-r0/sensors.conf new file mode 100644 index 000000000000..ff71a21a747d --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/sensors.conf @@ -0,0 +1,91 @@ +# libsensors configuration file for AG5648 +# ------------------------------------------------ +# + +bus "i2c-2" "i2c-1-mux (chan_id 0)" +bus "i2c-3" "i2c-1-mux (chan_id 1)" +bus "i2c-4" "i2c-1-mux (chan_id 2)" +bus "i2c-5" "i2c-1-mux (chan_id 3)" +bus "i2c-6" "i2c-1-mux (chan_id 4)" +bus "i2c-7" "i2c-1-mux (chan_id 5)" + +# tmp75-i2c-2-4d board sensor near Left of front vents. +# tmp75-i2c-3-49 board sensor near MAC. +# tmp75-i2c-3-4b board sensor near Middle of front vents. +# tmp75-i2c-3-4c board sensor near Right of front vents. +# tmp75-i2c-3-4e board sensor near DC fan. +# tmp75-i2c-3-4f board sensor near CPU. + +chip "tmp75-i2c-2-4d" + label temp1 "board sensor near Left of front vents" + set temp1_max 60 + set temp1_max_hyst 55 + +chip "tmp75-i2c-3-49" + label temp1 "board sensor near MAC" + set temp1_max 85 + set temp1_max_hyst 80 + +chip "tmp75-i2c-3-4b" + label temp1 "board sensor near Middle of front vents" + set temp1_max 70 + set temp1_max_hyst 65 + +chip "tmp75-i2c-3-4c" + label temp1 "board sensor near Right of front vents" + set temp1_max 65 + set temp1_max_hyst 60 + +chip "tmp75-i2c-3-4e" + label temp1 "board sensor near DC fan" + set temp1_max 60 + set temp1_max_hyst 55 + +chip "tmp75-i2c-3-4f" + label temp1 "board sensor near CPU" + set temp1_max 80 + set temp1_max_hyst 75 + +chip "emc2305-i2c-3-4d" + label fan1 "FANTRAY 1 REAR" + label fan2 "FANTRAY 2 REAR" + label fan3 "FANTRAY 3 REAR" + label fan4 "FANTRAY 4 REAR" + +chip "emc2305-i2c-5-4d" + label fan1 "FANTRAY 1 FRONT" + label fan2 "FANTRAY 2 FRONT" + label fan3 "FANTRAY 3 FRONT" + label fan4 "FANTRAY 4 FRONT" + +chip "ltc4215-i2c-3-40" + label in1 "PSU Hot-Swap voltage 1" + label in2 "PSU Hot-Swap voltage 2" + label power1 "PSU Hot-Swap power" + label curr1 "PSU Hot-Swap current" + +chip "ltc4215-i2c-3-42" + label in1 "PSU Hot-Swap voltage 1" + label in2 "PSU Hot-Swap voltage 2" + label power1 "PSU Hot-Swap power" + label curr1 "PSU Hot-Swap current" + +chip "dni_ag5648_psu-i2c-6-59" + label in1 "PSU voltage 1" + label in2 "PSU voltage 2" + label fan1 "PSU fan" + label temp1 "PSU temperature" + label power1 "PSU power1" + label power2 "PSU power2" + label curr1 "PSU current1" + label curr2 "PSU current2" + +chip "dni_ag5648_psu-i2c-6-58" + label in1 "PSU voltage 1" + label in2 "PSU voltage 2" + label fan1 "PSU fan" + label temp1 "PSU temperature" + label power1 "PSU power1" + label power2 "PSU power2" + label curr1 "PSU current1" + label curr2 "PSU current2" \ No newline at end of file diff --git a/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/port_config.ini b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/port_config.ini new file mode 100644 index 000000000000..4fb783847b0a --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 41,42,43,44 hundredGigE1/1 +Ethernet4 45,46,47,48 hundredGigE1/2 +Ethernet8 49,50,51,52 hundredGigE1/3 +Ethernet12 37,38,39,40 hundredGigE1/4 +Ethernet16 33,34,35,36 hundredGigE1/5 +Ethernet20 53,54,55,56 hundredGigE1/6 +Ethernet24 57,58,59,60 hundredGigE1/7 +Ethernet28 61,62,63,64 hundredGigE1/8 +Ethernet32 65,66,67,68 hundredGigE1/9 +Ethernet36 69,70,71,72 hundredGigE1/10 +Ethernet40 73,74,75,76 hundredGigE1/11 +Ethernet44 77,78,79,80 hundredGigE1/12 +Ethernet48 81,82,83,84 hundredGigE1/13 +Ethernet52 85,86,87,88 hundredGigE1/14 +Ethernet56 89,90,91,92 hundredGigE1/15 +Ethernet60 93,94,95,96 hundredGigE1/16 +Ethernet64 97,98,99,100 hundredGigE1/17 +Ethernet68 101,102,103,104 hundredGigE1/18 +Ethernet72 105,106,107,108 hundredGigE1/19 +Ethernet76 109,110,111,112 hundredGigE1/20 +Ethernet80 121,122,123,124 hundredGigE1/21 +Ethernet84 113,114,115,116 hundredGigE1/22 +Ethernet88 1,2,3,4 hundredGigE1/23 +Ethernet92 117,118,119,120 hundredGigE1/24 +Ethernet96 5,6,7,8 hundredGigE1/25 +Ethernet100 125,126,127,128 hundredGigE1/26 +Ethernet104 29,30,31,32 hundredGigE1/27 +Ethernet108 9,10,11,12 hundredGigE1/28 +Ethernet112 13,14,15,16 hundredGigE1/29 +Ethernet116 25,26,27,28 hundredGigE1/30 +Ethernet120 17,18,19,20 hundredGigE1/31 +Ethernet124 21,22,23,24 hundredGigE1/32 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/sai.profile b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/sai.profile new file mode 100644 index 000000000000..c77b2bf79a34 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-ag9032v1-32x100G.config.bcm diff --git a/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/th-ag9032v1-32x100G.config.bcm b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/th-ag9032v1-32x100G.config.bcm new file mode 100644 index 000000000000..a088c8f7a6be --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/th-ag9032v1-32x100G.config.bcm @@ -0,0 +1,523 @@ +os=unix +schan_intr_enable=0 +ctr_evict_enable=0 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +pbmp_oversubscribe=0x00003fc000000ff0000003fc000001fe +pbmp_xport_xe=0x00003fc000000ff0000003fc000001fe +port_phy_clause_1=45 +port_phy_clause_2=45 +port_phy_clause_3=45 +port_phy_clause_4=45 +port_phy_clause_5=45 +port_phy_clause_6=45 +port_phy_clause_7=45 +port_phy_clause_8=45 + +port_phy_clause_34=45 +port_phy_clause_35=45 +port_phy_clause_36=45 +port_phy_clause_37=45 +port_phy_clause_38=45 +port_phy_clause_39=45 +port_phy_clause_40=45 +port_phy_clause_41=45 + +port_phy_clause_68=45 +port_phy_clause_69=45 +port_phy_clause_70=45 +port_phy_clause_71=45 +port_phy_clause_72=45 +port_phy_clause_73=45 +port_phy_clause_74=45 +port_phy_clause_75=45 + +port_phy_clause_102=45 +port_phy_clause_103=45 +port_phy_clause_104=45 +port_phy_clause_105=45 +port_phy_clause_106=45 +port_phy_clause_107=45 +port_phy_clause_108=45 +port_phy_clause_109=45 + +port_phy_addr_1=0xff +port_phy_addr_2=0xff +port_phy_addr_3=0xff +port_phy_addr_4=0xff +port_phy_addr_5=0xff +port_phy_addr_6=0xff +port_phy_addr_7=0xff +port_phy_addr_8=0xff + +port_phy_addr_34=0xff +port_phy_addr_35=0xff +port_phy_addr_36=0xff +port_phy_addr_37=0xff +port_phy_addr_38=0xff +port_phy_addr_39=0xff +port_phy_addr_40=0xff +port_phy_addr_41=0xff + +port_phy_addr_68=0xff +port_phy_addr_69=0xff +port_phy_addr_70=0xff +port_phy_addr_71=0xff +port_phy_addr_72=0xff +port_phy_addr_73=0xff +port_phy_addr_74=0xff +port_phy_addr_75=0xff + +port_phy_addr_102=0xff +port_phy_addr_103=0xff +port_phy_addr_104=0xff +port_phy_addr_105=0xff +port_phy_addr_106=0xff +port_phy_addr_107=0xff +port_phy_addr_108=0xff +port_phy_addr_109=0xff + +# Tile-0 +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_6=21:100 +portmap_7=25:100 +portmap_8=29:100 + +# Tile-1 +portmap_34=33:100 +portmap_35=37:100 +portmap_36=41:100 +portmap_37=45:100 +portmap_38=49:100 +portmap_39=53:100 +portmap_40=57:100 +portmap_41=61:100 + +# Tile-2 +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 + +# Tile-3 +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_106=113:100 +portmap_107=117:100 +portmap_108=121:100 +portmap_109=125:100 + +dport_map_enable=1 +dport_map_indexed=1 +dport_map_direct=0 + +dport_map_port_36=1 +dport_map_port_37=2 +dport_map_port_38=3 +dport_map_port_35=4 +dport_map_port_34=5 +dport_map_port_39=6 +dport_map_port_40=7 +dport_map_port_41=8 + +dport_map_port_68=34 +dport_map_port_69=35 +dport_map_port_70=36 +dport_map_port_71=37 +dport_map_port_72=38 +dport_map_port_73=39 +dport_map_port_74=40 +dport_map_port_75=41 + +dport_map_port_102=68 +dport_map_port_103=69 +dport_map_port_104=70 +dport_map_port_105=71 +dport_map_port_108=72 +dport_map_port_106=73 +dport_map_port_1=74 +dport_map_port_107=75 + +dport_map_port_2=102 +dport_map_port_109=103 +dport_map_port_8=104 +dport_map_port_3=105 +dport_map_port_4=106 +dport_map_port_7=107 +dport_map_port_5=108 +dport_map_port_6=109 + +# Tile-0 FC0~FC7 +# TX polarity +phy_xaui_tx_polarity_flip_1=0xF +phy_xaui_tx_polarity_flip_2=0xF +phy_xaui_tx_polarity_flip_3=0x0 +phy_xaui_tx_polarity_flip_4=0x0 +phy_xaui_tx_polarity_flip_5=0x0 +phy_xaui_tx_polarity_flip_6=0x0 +phy_xaui_tx_polarity_flip_7=0xF +phy_xaui_tx_polarity_flip_8=0xF + +# RX polarity +phy_xaui_rx_polarity_flip_1=0xF +phy_xaui_rx_polarity_flip_2=0xF +phy_xaui_rx_polarity_flip_3=0x0 +phy_xaui_rx_polarity_flip_4=0x0 +phy_xaui_rx_polarity_flip_5=0x0 +phy_xaui_rx_polarity_flip_6=0x0 +phy_xaui_rx_polarity_flip_7=0xF +phy_xaui_rx_polarity_flip_8=0xF + +# TX lane swap +xgxs_tx_lane_map_1=0x1302 +xgxs_tx_lane_map_2=0x1302 +xgxs_tx_lane_map_3=0x0213 +xgxs_tx_lane_map_4=0x1302 +xgxs_tx_lane_map_5=0x1032 +xgxs_tx_lane_map_6=0x0213 +xgxs_tx_lane_map_7=0x3120 +xgxs_tx_lane_map_8=0x1302 + +# RX lane swap +xgxs_rx_lane_map_1=0x1302 +xgxs_rx_lane_map_2=0x1302 +xgxs_rx_lane_map_3=0x0213 +xgxs_rx_lane_map_4=0x1302 +xgxs_rx_lane_map_5=0x0123 +xgxs_rx_lane_map_6=0x1032 +xgxs_rx_lane_map_7=0x0213 +xgxs_rx_lane_map_8=0x2031 + +# Tile-1 FC8~FC15 +#TX polarity +phy_xaui_tx_polarity_flip_34=0x0 +phy_xaui_tx_polarity_flip_35=0x1 +phy_xaui_tx_polarity_flip_36=0x0 +phy_xaui_tx_polarity_flip_37=0x1 +phy_xaui_tx_polarity_flip_38=0xF +phy_xaui_tx_polarity_flip_39=0xE +phy_xaui_tx_polarity_flip_40=0x0 +phy_xaui_tx_polarity_flip_41=0xE + +#RX polarity +phy_xaui_rx_polarity_flip_34=0x0 +phy_xaui_rx_polarity_flip_35=0x0 +phy_xaui_rx_polarity_flip_36=0x0 +phy_xaui_rx_polarity_flip_37=0x2 +phy_xaui_rx_polarity_flip_38=0xF +phy_xaui_rx_polarity_flip_39=0xF +phy_xaui_rx_polarity_flip_40=0x0 +phy_xaui_rx_polarity_flip_41=0xF + +# TX lane swap +xgxs_tx_lane_map_34=0x0213 +xgxs_tx_lane_map_35=0x2031 +xgxs_tx_lane_map_36=0x0123 +xgxs_tx_lane_map_37=0x1032 +xgxs_tx_lane_map_38=0x0213 +xgxs_tx_lane_map_39=0x1302 +xgxs_tx_lane_map_40=0x0213 +xgxs_tx_lane_map_41=0x1302 + +# RX lane swap +xgxs_rx_lane_map_34=0x3120 +xgxs_rx_lane_map_35=0x2301 +xgxs_rx_lane_map_36=0x1032 +xgxs_rx_lane_map_37=0x0123 +xgxs_rx_lane_map_38=0x0213 +xgxs_rx_lane_map_39=0x1302 +xgxs_rx_lane_map_40=0x0213 +xgxs_rx_lane_map_41=0x1302 + +# Tile-2 FC16~FC23 +# TX polarity +phy_xaui_tx_polarity_flip_68=0x0 +phy_xaui_tx_polarity_flip_69=0xE +phy_xaui_tx_polarity_flip_70=0x0 +phy_xaui_tx_polarity_flip_71=0xE +phy_xaui_tx_polarity_flip_72=0xF +phy_xaui_tx_polarity_flip_73=0xE +phy_xaui_tx_polarity_flip_74=0xF +phy_xaui_tx_polarity_flip_75=0xE + +# RX polarity +phy_xaui_rx_polarity_flip_68=0x0 +phy_xaui_rx_polarity_flip_69=0xD +phy_xaui_rx_polarity_flip_70=0x0 +phy_xaui_rx_polarity_flip_71=0xF +phy_xaui_rx_polarity_flip_72=0xF +phy_xaui_rx_polarity_flip_73=0xF +phy_xaui_rx_polarity_flip_74=0xF +phy_xaui_rx_polarity_flip_75=0xF + +# TX lane swap +xgxs_tx_lane_map_68=0x3120 +xgxs_tx_lane_map_69=0x1302 +xgxs_tx_lane_map_70=0x0213 +xgxs_tx_lane_map_71=0x0123 +xgxs_tx_lane_map_72=0x0213 +xgxs_tx_lane_map_73=0x2031 +xgxs_tx_lane_map_74=0x0213 +xgxs_tx_lane_map_75=0x2031 + +# RX lane swap +xgxs_rx_lane_map_68=0x3120 +xgxs_rx_lane_map_69=0x1302 +xgxs_rx_lane_map_70=0x0213 +xgxs_rx_lane_map_71=0x2103 +xgxs_rx_lane_map_72=0x2031 +xgxs_rx_lane_map_73=0x0213 +xgxs_rx_lane_map_74=0x3210 +xgxs_rx_lane_map_75=0x0213 + +# Tile-3 +# portmap_0=x:xx // cpu port (not required, but included for illustration purposes) +# TX polarity +phy_xaui_tx_polarity_flip_102=0x0 +phy_xaui_tx_polarity_flip_103=0xF +phy_xaui_tx_polarity_flip_104=0x0 +phy_xaui_tx_polarity_flip_105=0x0 +phy_xaui_tx_polarity_flip_106=0x0 +phy_xaui_tx_polarity_flip_107=0x0 +phy_xaui_tx_polarity_flip_108=0xF +phy_xaui_tx_polarity_flip_109=0x0 + +# RX polarity +phy_xaui_rx_polarity_flip_102=0x0 +phy_xaui_rx_polarity_flip_103=0x2 +phy_xaui_rx_polarity_flip_104=0x0 +phy_xaui_rx_polarity_flip_105=0xF +phy_xaui_rx_polarity_flip_106=0x0 +phy_xaui_rx_polarity_flip_107=0x0 +phy_xaui_rx_polarity_flip_108=0xF +phy_xaui_rx_polarity_flip_109=0x2 + +# TX lane swap +xgxs_tx_lane_map_102=0x2031 +xgxs_tx_lane_map_103=0x0213 +xgxs_tx_lane_map_104=0x2031 +xgxs_tx_lane_map_105=0x0213 +xgxs_tx_lane_map_106=0x0123 +xgxs_tx_lane_map_107=0x0213 +xgxs_tx_lane_map_108=0x0312 +xgxs_tx_lane_map_109=0x3120 + +# RX lane swap +xgxs_rx_lane_map_102=0x0213 +xgxs_rx_lane_map_103=0x2031 +xgxs_rx_lane_map_104=0x0213 +xgxs_rx_lane_map_105=0x2031 +xgxs_rx_lane_map_106=0x0123 +xgxs_rx_lane_map_107=0x0213 +xgxs_rx_lane_map_108=0x1302 +xgxs_rx_lane_map_109=0x3120 + +#serdes_preemphasis_lane0_1=0x(post)(main)(pre) +#ce0 +serdes_preemphasis_lane0_36=0x3c320f +serdes_preemphasis_lane1_36=0x3c320f +serdes_preemphasis_lane2_36=0x3c320c +serdes_preemphasis_lane3_36=0x3c320c + +#ce1 +serdes_preemphasis_lane0_37=0x3c320f +serdes_preemphasis_lane1_37=0x3c320f +serdes_preemphasis_lane2_37=0x3c320c +serdes_preemphasis_lane3_37=0x37320c + +#ce2 +serdes_preemphasis_lane0_38=0x3c3206 +serdes_preemphasis_lane1_38=0x373206 +serdes_preemphasis_lane2_38=0x373206 +serdes_preemphasis_lane3_38=0x373206 + +#ce3 +serdes_preemphasis_lane0_35=0x3c3206 +serdes_preemphasis_lane1_35=0x3c3206 +serdes_preemphasis_lane2_35=0x3c3206 +serdes_preemphasis_lane3_35=0x3c3206 + +#ce4 +serdes_preemphasis_lane0_34=0x3c3206 +serdes_preemphasis_lane1_34=0x3c3206 +serdes_preemphasis_lane2_34=0x3c3206 +serdes_preemphasis_lane3_34=0x373206 + +#ce5 +serdes_preemphasis_lane0_39=0x323206 +serdes_preemphasis_lane1_39=0x323206 +serdes_preemphasis_lane2_39=0x323206 +serdes_preemphasis_lane3_39=0x323206 + +#ce6 +serdes_preemphasis_lane0_40=0x323206 +serdes_preemphasis_lane1_40=0x2D3206 +serdes_preemphasis_lane2_40=0x2D3206 +serdes_preemphasis_lane3_40=0x2D3206 + +#ce7 +serdes_preemphasis_lane0_41=0x2D3206 +serdes_preemphasis_lane1_41=0x2D3206 +serdes_preemphasis_lane2_41=0x2D3206 +serdes_preemphasis_lane3_41=0x2D3206 + +#ce8 +serdes_preemphasis_lane0_68=0x283206 +serdes_preemphasis_lane1_68=0x283206 +serdes_preemphasis_lane2_68=0x283206 +serdes_preemphasis_lane3_68=0x283206 + +#ce9 +serdes_preemphasis_lane0_69=0x283206 +serdes_preemphasis_lane1_69=0x283206 +serdes_preemphasis_lane2_69=0x283206 +serdes_preemphasis_lane3_69=0x283206 + +#ce10 +serdes_preemphasis_lane0_70=0x2D3206 +serdes_preemphasis_lane1_70=0x2D3206 +serdes_preemphasis_lane2_70=0x2D3206 +serdes_preemphasis_lane3_70=0x2D3206 + +#ce11 +serdes_preemphasis_lane0_71=0x2D3206 +serdes_preemphasis_lane1_71=0x2D3206 +serdes_preemphasis_lane2_71=0x2D3206 +serdes_preemphasis_lane3_71=0x2D3206 + +#ce12 +serdes_preemphasis_lane0_72=0x2D3203 +serdes_preemphasis_lane1_72=0x2D3206 +serdes_preemphasis_lane2_72=0x2D3206 +serdes_preemphasis_lane3_73=0x2D3206 + +#ce13 +serdes_preemphasis_lane0_73=0x2D3206 +serdes_preemphasis_lane1_73=0x283206 +serdes_preemphasis_lane2_73=0x283206 +serdes_preemphasis_lane3_73=0x283206 + +#ce14 +serdes_preemphasis_lane0_74=0x2D3203 +serdes_preemphasis_lane1_74=0x2D3203 +serdes_preemphasis_lane2_74=0x2D3203 +serdes_preemphasis_lane3_74=0x283206 + +#ce15 +serdes_preemphasis_lane0_75=0x2D3206 +serdes_preemphasis_lane1_75=0x283206 +serdes_preemphasis_lane2_75=0x283206 +serdes_preemphasis_lane3_75=0x283206 + +#ce16 +serdes_preemphasis_lane0_102=0x2D3206 +serdes_preemphasis_lane1_102=0x2D3206 +serdes_preemphasis_lane2_102=0x2D3206 +serdes_preemphasis_lane3_102=0x2D3206 + +#ce17 +serdes_preemphasis_lane0_103=0x2D3206 +serdes_preemphasis_lane1_103=0x283206 +serdes_preemphasis_lane2_103=0x283206 +serdes_preemphasis_lane3_103=0x283206 + +#ce18 +serdes_preemphasis_lane0_104=0x2D3206 +serdes_preemphasis_lane1_104=0x283206 +serdes_preemphasis_lane2_104=0x283206 +serdes_preemphasis_lane3_104=0x283206 + +#ce19 +serdes_preemphasis_lane0_105=0x2D3206 +serdes_preemphasis_lane1_105=0x2D3206 +serdes_preemphasis_lane2_105=0x2D3206 +serdes_preemphasis_lane3_105=0x2D3206 + +#ce20 +serdes_preemphasis_lane0_108=0x323206 +serdes_preemphasis_lane1_108=0x283206 +serdes_preemphasis_lane2_108=0x283206 +serdes_preemphasis_lane3_108=0x283206 + +#ce21 +serdes_preemphasis_lane0_106=0x2D3206 +serdes_preemphasis_lane1_106=0x283206 +serdes_preemphasis_lane2_106=0x283206 +serdes_preemphasis_lane3_106=0x283206 + +#ce22 +serdes_preemphasis_lane0_1=0x323206 +serdes_preemphasis_lane1_1=0x283206 +serdes_preemphasis_lane2_1=0x283206 +serdes_preemphasis_lane3_1=0x283206 + +#ce23 +serdes_preemphasis_lane0_107=0x323206 +serdes_preemphasis_lane1_107=0x283206 +serdes_preemphasis_lane2_107=0x283206 +serdes_preemphasis_lane3_107=0x283206 + +#ce24 +serdes_preemphasis_lane0_2=0x2D3206 +serdes_preemphasis_lane1_2=0x2D3206 +serdes_preemphasis_lane2_2=0x323206 +serdes_preemphasis_lane3_3=0x2D3206 + +#ce25 +serdes_preemphasis_lane0_109=0x323203 +serdes_preemphasis_lane1_109=0x2D3206 +serdes_preemphasis_lane2_109=0x2D3206 +serdes_preemphasis_lane3_109=0x2D3206 + +#ce26 +serdes_preemphasis_lane0_8=0x373206 +serdes_preemphasis_lane1_8=0x373206 +serdes_preemphasis_lane2_8=0x373206 +serdes_preemphasis_lane3_8=0x373206 + +#ce27 +serdes_preemphasis_lane0_3=0x323203 +serdes_preemphasis_lane1_3=0x323203 +serdes_preemphasis_lane2_3=0x323203 +serdes_preemphasis_lane3_3=0x323203 + +#ce28 +serdes_preemphasis_lane0_4=0x373203 +serdes_preemphasis_lane1_4=0x323203 +serdes_preemphasis_lane2_4=0x323203 +serdes_preemphasis_lane3_4=0x323205 + +#ce29 +serdes_preemphasis_lane0_7=0x3c3203 +serdes_preemphasis_lane1_7=0x3c3203 +serdes_preemphasis_lane2_7=0x3c3203 +serdes_preemphasis_lane3_7=0x3c3205 + +#ce30 +serdes_preemphasis_lane0_5=0x3c320f +serdes_preemphasis_lane1_5=0x3c320f +serdes_preemphasis_lane2_5=0x3c320c +serdes_preemphasis_lane3_5=0x2c320c + +#ce31 +serdes_preemphasis_lane0_6=0x3c320f +serdes_preemphasis_lane1_6=0x3c320f +serdes_preemphasis_lane2_6=0x2c320c +serdes_preemphasis_lane3_6=0x2c320c + + + diff --git a/device/delta/x86_64-delta_ag9032v1-r0/default_sku b/device/delta/x86_64-delta_ag9032v1-r0/default_sku new file mode 100644 index 000000000000..f175f53b323e --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/default_sku @@ -0,0 +1 @@ +Delta-ag9032v1 t1 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/fancontrol b/device/delta/x86_64-delta_ag9032v1-r0/fancontrol new file mode 100644 index 000000000000..4a1cde92478f --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=10 +DEVPATH=hwmon1=/sys/bus/i2c/devices +DEVNAME=hwmon1=emc2305 +FCTEMPS=hwmon1/2-004d/hwmon/hwmon*/temp1_input hwmon1/7-004c/hwmon/hwmon*/temp1_input hwmon1/7-004d/hwmon/hwmon*/temp1_input hwmon1/7-004e/hwmon/hwmon*/temp1_input hwmon1/30-004f/hwmon/hwmon*/temp1_input hwmon1/40-0058/temp1_input hwmon1/41-0058/temp1_input + +FCFANS=hwmon1/37-002c/fan1_input hwmon1/37-002c/fan2_input hwmon1/37-002c/fan3_input hwmon1/37-002c/fan4_input hwmon1/37-002c/fan5_input hwmon1/38-002d/fan1_input hwmon1/38-002d/fan2_input hwmon1/38-002d/fan3_input hwmon1/38-002d/fan4_input hwmon1/38-002d/fan5_input +MINTEMP=20 +MAXTEMP=60 +MINSTART=75 +MINSTOP=22 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/fancontrol.service b/device/delta/x86_64-delta_ag9032v1-r0/fancontrol.service new file mode 100755 index 000000000000..83f14245d1bd --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/fancontrol.service @@ -0,0 +1,289 @@ +#!/bin/bash +# +# Simple script implementing a temperature dependent fan speed control +# Supported Linux kernel versions: 2.6.5 and later +# +# Version 0.70 +# +# Usage: fancontrol [CONFIGFILE] +# +# Dependencies: +# bash, egrep, sed, cut, sleep, readlink, lm_sensors :) +# +# Please send any questions, comments or success stories to +# marius.reiner@hdev.de +# Thanks! +# +# For configuration instructions and warnings please see fancontrol.txt, which +# can be found in the doc/ directory or at the website mentioned above. +# +# +# Copyright 2003 Marius Reiner +# Copyright (C) 2007-2009 Jean Delvare +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# +# + +PIDFILE="/var/run/fancontrol.pid" + +#DEBUG=1 +MAX=255 + +function LoadConfig +{ + local fcvcount fcv + + echo "Loading configuration from $1 ..." + if [ ! -r "$1" ] + then + echo "Error: Can't read configuration file" >&2 + exit 1 + fi + + # grep configuration from file + INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g'` + DEVPATH=`egrep '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g'` + DEVNAME=`egrep '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g'` + FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g'` + MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g'` + MAXTEMP=`egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g'` + MINSTART=`egrep '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g'` + MINSTOP=`egrep '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g'` + HWMON=$( echo "$DEVPATH" | sed 's/=.*$//g') + FCDEVPATH=$( echo "$DEVPATH" | sed 's/^.*=//g') + FCMINTEMP=$MINTEMP + FCMAXTEMP=$MAXTEMP + FCMINSTART=$MINSTART + FCMINSTOP=$MINSTOP + AFCTEMP_1_LOWER=(00 39 36 41 46 55) + AFCTEMP_1_UPPER=(39 39 44 49 54 150) + AFCTEMP_2_LOWER=(00 61 65 69 73 82) + AFCTEMP_2_UPPER=(63 67 71 75 79 150) + AFCTEMP_3_LOWER=(00 51 55 59 63 71) + AFCTEMP_3_UPPER=(53 57 61 65 69 150) + AFCTEMP_4_LOWER=(00 46 50 54 58 65) + AFCTEMP_4_UPPER=(45 52 56 60 64 150) + AFCTEMP_5_LOWER=(00 46 50 54 58 65) + AFCTEMP_5_UPPER=(45 52 56 60 64 150) + + + FCFANS=`egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g'` + + # Check whether all mandatory settings are set + if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]] + then + echo "Some mandatory settings missing, please check your config file!" >&2 + exit 1 + fi + if [ "$INTERVAL" -le 0 ] + then + echo "Error in configuration file:" >&2 + echo "INTERVAL must be at least 1" >&2 + exit 1 + fi + + # write settings to arrays for easier use and print them + echo + echo "Common settings:" + + temp_string=$FCTEMPS + + let fcvcount=0 + for fcv in $FCTEMPS + do + fcvcount=$((fcvcount+1)) + AFCTEMP[$fcvcount]=$( echo "$temp_string" | cut -d" " -f $fcvcount ) + AFCTEMP[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCTEMP_PATH[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} ) + AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 )) + done + + fan_string=$FCFANS + fcvcount=0 + zero=0 + for fcv in $FCFANS + do + fcvcount=$((fcvcount+1)) + AFCFAN[$fcvcount]=$( echo "$fan_string" | cut -d" " -f $fcvcount ) + AFCFAN_PATH[$fcvcount]=$( echo "${AFCFAN[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_PATH[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_TARGET[$fcvcount]}" | sed 's/$/_percentage/g') + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + if [ "${AFCFAN[$fcvcount]}" == 960 ] + then + AFCFAN[$fcvcount]=$zero + fi + done +} + +# Check that all referenced sysfs files exist +function CheckFiles +{ + local outdated=0 fcvcount tsen fan + if [ $outdated -eq 1 ] + then + echo >&2 + echo "At least one referenced file is missing. Either some required kernel" >&2 + echo "modules haven't been loaded, or your configuration file is outdated." >&2 + echo "In the latter case, you should run pwmconfig again." >&2 + fi + return $outdated +} + +LoadConfig $1 + +# Detect path to sensors +if [ ! -d $DIR ] +then + echo $0: 'No sensors found! (did you load the necessary modules?)' >&2 + exit 1 +fi +cd $DIR + +# Check for configuration change +if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ] +then + echo "Configuration is too old, please run pwmconfig again" >&2 + exit 1 +fi +if [ "$DIR" = "/" -a -n "$DEVPATH" ] +then + echo "Unneeded DEVPATH with absolute device paths" >&2 + exit 1 +fi +CheckFiles || exit 1 + +if [ -f "$PIDFILE" ] +then + echo "File $PIDFILE exists, is fancontrol already running?" >&2 + exit 1 +fi +echo $$ > "$PIDFILE" + +# main function +function UpdateThermalSensors +{ + fcvcount=0 + for fcv in $FCTEMPS + do + fcvcount=$((fcvcount+1)) + AFCTEMP[$fcvcount]=$( cat ${AFCTEMP_PATH[$fcvcount]} ) + AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 )) + done +} + +function UpdateThermalLevel +{ + AFCTEMP_NUM=$((6-${AFCTEMP_LEVEL[$i]})) + AFCTEMP_UPPER_BUF=AFCTEMP_"$i"_UPPER["$AFCTEMP_NUM"] + AFCTEMP_LOWER_BUF=AFCTEMP_"$i"_LOWER["$AFCTEMP_NUM"] + + AFCTEMP_UPPER=${!AFCTEMP_UPPER_BUF} + AFCTEMP_LOWER=${!AFCTEMP_LOWER_BUF} + + + if (( ("${AFCTEMP[$i]}" <= "$AFCTEMP_UPPER") && ("${AFCTEMP[$i]}" >= "$AFCTEMP_LOWER") )) ; then + FLAG=2 + elif (( "${AFCTEMP[$i]}" > "$AFCTEMP_UPPER" )); then + AFCTEMP_LEVEL[$i]=$((${AFCTEMP_LEVEL[$i]} - 1)) + FLAG=1 + elif (( "${AFCTEMP[$i]}" < "$AFCTEMP_LOWER" )); then + AFCTEMP_LEVEL[$i]=$((${AFCTEMP_LEVEL[$i]} + 1)) + FLAG=1 + else + AFCTEMP_LEVEL[$i]=1 + FLAG=2 + fi +} + +function UpdateFanSpeeds +{ + #echo "num tmp lev F L H" + #Update level + for i in 1 2 3 4 5 + do + #echo "----------------------" + FLAG=0 + #FLAG=0 : initial flag + #FLAG=1 : update level + #FLAG=2 : final level + while [ $FLAG -ne 2 ] + do + UpdateThermalLevel + #echo " $i ${AFCTEMP[$i]} ${AFCTEMP_LEVEL[$i]} $FLAG $AFCTEMP_LOWER $AFCTEMP_UPPER " + done + done + + min=${AFCTEMP_LEVEL[0]} + for j in "${AFCTEMP_LEVEL[@]}"; do + (( j < min )) && min=$j + done + + if (($min == 1 || $min == 2)); then + FAN_PERCENTAGE=100 + elif (($min == 3)); then + FAN_PERCENTAGE=80 + elif (($min == 4)); then + FAN_PERCENTAGE=60 + elif (($min == 5)); then + FAN_PERCENTAGE=40 + elif (($min == 6)); then + FAN_PERCENTAGE=30 + else + FAN_PERCENTAGE=100 + fi + echo "The lowest level of thermal sensors: $min " + echo "Trying to set fan speed to $FAN_PERCENTAGE %" + #Set speed to fan1~fan10 + let fcvcount=0 + for fcv in $FCFANS + do + fcvcount=$(( fcvcount + 1 )) + echo $FAN_PERCENTAGE > ${AFCFAN_TARGET[$fcvcount]} + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + + if [ "${AFCFAN[$fcvcount]}" == 960 ] + then + AFCFAN[$fcvcount]=$zero + fi + echo "FAN fan$fcvcount = ${AFCFAN[$fcvcount]} (rpm)" + done + + FAN_ON_PSU_PERCENTAGE=$FAN_PERCENTAGE + #Set speed to PSU_FAN1 + echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/40-0058/fan1_set_percentage' + echo "PSU fan1 =$( cat '/sys/bus/i2c/devices/40-0058/fan1_input' ) (rpm)" + #Set speed to PSU_FAN2 + echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/41-0058/fan1_set_percentage' + echo "PSU fan2 =$( cat '/sys/bus/i2c/devices/41-0058/fan1_input' ) (rpm)" + + rm -f "$PIDFILE" +} + +# main loop calling the main function at specified intervals +AFCTEMP_LEVEL=(9 4 4 4 4 4) #inttial level +while true +do + UpdateThermalSensors + UpdateFanSpeeds + echo "Sleep $INTERVAL seconds ..." + echo + # Sleep while still handling signals + sleep $INTERVAL & + wait $! +done diff --git a/device/delta/x86_64-delta_ag9032v1-r0/installer.conf b/device/delta/x86_64-delta_ag9032v1-r0/installer.conf new file mode 100644 index 000000000000..fa2af8b7a007 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_SPEED=115200 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/led_proc_init.soc b/device/delta/x86_64-delta_ag9032v1-r0/led_proc_init.soc new file mode 100644 index 000000000000..7f6789e90123 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/led_proc_init.soc @@ -0,0 +1,45 @@ +s CMIC_LEDUP0_PROGRAM_RAM 0 +s CMIC_LEDUP1_PROGRAM_RAM 0 + +led 0 stop +led 0 prog 02 00 60 E0 86 ED 2E E0 32 08 97 02 00 0E 00 60 E3 2E E0 32 00 32 01 B7 97 02 00 0E 00 12 E7 50 86 E0 86 E0 86 E0 86 E0 16 E7 61 EB 06 E3 67 4E 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 06 E0 D2 40 74 06 3A C0 D2 01 74 66 06 EB D2 00 70 62 16 ED 99 99 1A 00 71 62 77 66 32 0F 87 57 32 0E 87 57 +led 0 auto on +led 0 start +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=15 REMAP_PORT_17=14 REMAP_PORT_18=13 REMAP_PORT_19=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 REMAP_PORT_21=10 REMAP_PORT_22=9 REMAP_PORT_23=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=7 REMAP_PORT_25=6 REMAP_PORT_26=5 REMAP_PORT_27=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=3 REMAP_PORT_29=2 REMAP_PORT_30=1 REMAP_PORT_31=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=62 REMAP_PORT_34=61 REMAP_PORT_35=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=59 REMAP_PORT_37=58 REMAP_PORT_38=57 REMAP_PORT_39=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=55 REMAP_PORT_41=54 REMAP_PORT_42=53 REMAP_PORT_43=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=51 REMAP_PORT_45=50 REMAP_PORT_46=49 REMAP_PORT_47=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=47 REMAP_PORT_49=46 REMAP_PORT_50=45 REMAP_PORT_51=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=43 REMAP_PORT_53=42 REMAP_PORT_54=41 REMAP_PORT_55=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=39 REMAP_PORT_57=38 REMAP_PORT_58=37 REMAP_PORT_59=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=35 REMAP_PORT_61=34 REMAP_PORT_62=33 REMAP_PORT_63=32 + +led 1 stop +led 1 prog 02 00 60 E0 86 ED 2E E0 32 08 97 02 00 0E 00 60 E3 2E E0 32 00 32 01 B7 97 02 00 0E 00 12 E7 50 86 E0 86 E0 86 E0 86 E0 16 E7 61 EB 06 E3 67 4E 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 06 E0 D2 40 74 06 3A C0 D2 01 74 66 06 EB D2 00 70 62 16 ED 99 99 1A 00 71 62 77 66 32 0F 87 57 32 0E 87 57 +led 1 auto on +led 1 start +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + diff --git a/device/delta/x86_64-delta_ag9032v1-r0/plugins/eeprom.py b/device/delta/x86_64-delta_ag9032v1-r0/plugins/eeprom.py new file mode 100644 index 000000000000..786e1fdc85e3 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/plugins/eeprom.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# 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: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + _TLV_INFO_MAX_LEN = 256 + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-2/2-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/delta/x86_64-delta_ag9032v1-r0/plugins/psuutil.py b/device/delta/x86_64-delta_ag9032v1-r0/plugins/psuutil.py new file mode 100644 index 000000000000..4b370d9a7443 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/plugins/psuutil.py @@ -0,0 +1,57 @@ +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/{}-0058/" + self.psu_oper_status = "in1_input" + self.psu_presence = "i2cget -y {} 0x50 0x00" + + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + if index is None: + return False + Base_bus_number = 39 + status = 0 + #index from 1, psu attribute bus from 40 + try: + with open(self.psu_path.format(index + Base_bus_number) + self.psu_oper_status, 'r') as power_status: + if int(power_status.read()) == 0 : + return False + else: + status = 1 + except IOError: + return False + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + Base_bus_number = 39 + status = 0 + try: + p = os.popen(self.psu_presence.format(index + Base_bus_number)+ "> /dev/null 2>&1") + if p.readline() != None: + status = 1 + p.close() + except IOError: + return False + return status == 1 + + diff --git a/device/delta/x86_64-delta_ag9032v1-r0/plugins/sfputil.py b/device/delta/x86_64-delta_ag9032v1-r0/plugins/sfputil.py new file mode 100644 index 000000000000..748e2b6643f4 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/plugins/sfputil.py @@ -0,0 +1,183 @@ +# 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 = 31 + PORTS_IN_BLOCK = 32 + + EEPROM_OFFSET = 50 + + _port_to_eeprom_mapping = {} + + @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 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): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET) + + 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/devices/platform/delta-ag9032v1-swpld.0/sfp_present") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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 + + try: + reg_file = open("/sys/devices/platform/delta-ag9032v1-swpld.0/sfp_lpmode") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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 + + try: + reg_file = open("/sys/devices/platform/delta-ag9032v1-swpld.0/sfp_lpmode", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/delta-ag9032v1-swpld.0/sfp_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 + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # 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: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "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 + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/delta/x86_64-delta_ag9032v1-r0/sensors.conf b/device/delta/x86_64-delta_ag9032v1-r0/sensors.conf new file mode 100644 index 000000000000..d3b2aea2a5af --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/sensors.conf @@ -0,0 +1,61 @@ +# libsensors configuration file for DCS-7060CX-32S +# ------------------------------------------------ +# + +bus "i2c-2" "i2c-1-mux (chan_id 0)" +bus "i2c-3" "i2c-1-mux (chan_id 1)" +bus "i2c-4" "i2c-1-mux (chan_id 2)" +bus "i2c-7" "i2c-1-mux (chan_id 5)" + + +# tmp75-i2c-2-4d CPU below side thermal sensor. +# tmp75-i2c-3-4f Wind thermal sensor. +# tmp75-i2c-7-4c MAC up side thermal sensor. +# tmp75-i2c-7-4d MAC down side thermal sensor. +# tmp75-i2c-7-4e Surroundings thermal sensor. + +chip "tmp75-i2c-2-4d" + label temp1 "CPU below side thermal sensor" + set temp1_max 60 + set temp1_max_hyst 55 + +chip "tmp75-i2c-*-4f" + label temp1 "Wind thermal sensor" + set temp1_max 65 + set temp1_max_hyst 60 +chip "tmp75-i2c-7-4c" + label temp1 "MAC up side thermal sensor" + set temp1_max 80 + set temp1_max_hyst 75 +chip "tmp75-i2c-7-4d" + label temp1 "MAC down side thermal sensor" + set temp1_max 75 + set temp1_max_hyst 70 +chip "tmp75-i2c-7-4e" + label temp1 "Surroundings thermal sensor" + set temp1_max 65 + set temp1_max_hyst 60 + + +chip "emc2305-i2c-3-2d" + label fan1 "FANTRAY 1 REAR" + label fan2 "FANTRAY 2 REAR" + label fan3 "FANTRAY 3 REAR" + label fan4 "FANTRAY 4 REAR" + label fan5 "FANTRAY 5 REAR" +chip "emc2305-i2c-3-2c" + label fan1 "FANTRAY 1 FRONT" + label fan2 "FANTRAY 2 FRONT" + label fan3 "FANTRAY 3 FRONT" + label fan4 "FANTRAY 4 FRONT" + label fan5 "FANTRAY 5 FRONT" +chip "pmbus-i2c-4-50" + label temp1 "Fan of power supply controller 1 sensor 1" + label temp2 "Fan of Power supply controller 1 sensor 2" + +chip "pmbus-i2c-4-40" + label temp1 "Power supply 1 hotspot sensor" + +chip "pmbus-i2c-4-40" + label temp1 "Power supply 2 hotspot sensor" + diff --git a/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/port_config.ini b/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/port_config.ini new file mode 100644 index 000000000000..be43857f82b1 --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias +Ethernet0 49,50,51,52 Ethernet1/1 +Ethernet4 53,54,55,56 Ethernet2/1 +Ethernet8 65,66,67,68 Ethernet3/1 +Ethernet12 69,70,71,72 Ethernet4/1 +Ethernet16 81,82,83,84 Ethernet5/1 +Ethernet20 85,86,87,88 Ethernet6/1 +Ethernet24 1,2,3,4 Ethernet7/1 +Ethernet28 101,102,103,104 Ethernet8/1 +Ethernet32 5,6,7,8 Ethernet9/1 +Ethernet36 17,18,19,20 Ethernet10/1 +Ethernet40 21,22,23,24 Ethernet11/1 +Ethernet44 33,34,35,36 Ethernet12/1 +Ethernet48 37,38,39,40 Ethernet13/1 +Ethernet52 97,98,99,100 Ethernet14/1 +Ethernet56 113,114,115,116 Ethernet15/1 +Ethernet60 117,118,119,120 Ethernet16/1 +Ethernet64 129,130,131,132 Ethernet17/1 +Ethernet68 133,134,135,136 Ethernet18/1 +Ethernet72 145,146,147,148 Ethernet19/1 +Ethernet76 209,210,211,212 Ethernet20/1 +Ethernet80 213,214,215,216 Ethernet21/1 +Ethernet84 225,226,227,228 Ethernet22/1 +Ethernet88 229,230,231,232 Ethernet23/1 +Ethernet92 241,242,243,244 Ethernet24/1 +Ethernet96 245,246,247,248 Ethernet25/1 +Ethernet100 157,158,159,160 Ethernet26/1 +Ethernet104 161,162,163,164 Ethernet27/1 +Ethernet108 165,166,167,168 Ethernet28/1 +Ethernet112 177,178,179,180 Ethernet29/1 +Ethernet116 181,182,183,184 Ethernet30/1 +Ethernet120 193,194,195,196 Ethernet31/1 +Ethernet124 197,198,199,200 Ethernet32/1 +Ethernet128 61,62,63,64 Ethernet33/1 +Ethernet132 57,58,59,60 Ethernet34/1 +Ethernet136 77,78,79,80 Ethernet35/1 +Ethernet140 73,74,75,76 Ethernet36/1 +Ethernet144 93,94,95,96 Ethernet37/1 +Ethernet148 89,90,91,92 Ethernet38/1 +Ethernet152 105,106,107,108 Ethernet39/1 +Ethernet156 9,10,11,12 Ethernet40/1 +Ethernet160 25,26,27,28 Ethernet41/1 +Ethernet164 13,14,15,16 Ethernet42/1 +Ethernet168 41,42,43,44 Ethernet43/1 +Ethernet172 29,30,31,32 Ethernet44/1 +Ethernet176 45,46,47,48 Ethernet45/1 +Ethernet180 109,110,111,112 Ethernet46/1 +Ethernet184 125,126,127,128 Ethernet47/1 +Ethernet188 121,122,123,124 Ethernet48/1 +Ethernet192 141,142,143,144 Ethernet49/1 +Ethernet196 137,138,139,140 Ethernet50/1 +Ethernet200 217,218,219,220 Ethernet51/1 +Ethernet204 149,150,151,152 Ethernet52/1 +Ethernet208 233,234,235,236 Ethernet53/1 +Ethernet212 221,222,223,224 Ethernet54/1 +Ethernet216 249,250,251,252 Ethernet55/1 +Ethernet220 237,238,239,240 Ethernet56/1 +Ethernet224 153,154,155,156 Ethernet57/1 +Ethernet228 253,254,255,256 Ethernet58/1 +Ethernet232 173,174,175,176 Ethernet59/1 +Ethernet236 169,170,171,172 Ethernet60/1 +Ethernet240 189,190,191,192 Ethernet61/1 +Ethernet244 185,186,187,188 Ethernet62/1 +Ethernet248 205,206,207,208 Ethernet63/1 +Ethernet252 201,202,203,204 Ethernet64/1 diff --git a/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/sai.profile b/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/sai.profile new file mode 100644 index 000000000000..21f013773e61 --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-ag9064-64x100G.config.bcm diff --git a/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/th2-ag9064-64x100G.config.bcm b/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/th2-ag9064-64x100G.config.bcm new file mode 100644 index 000000000000..859196d8e5c8 --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/th2-ag9064-64x100G.config.bcm @@ -0,0 +1,802 @@ +core_clock_frequency=1700 +dport_map_enable=1 +dport_map_port_102=31 +dport_map_port_103=32 +dport_map_port_104=64 +dport_map_port_105=63 +dport_map_port_106=20 +dport_map_port_107=21 +dport_map_port_108=51 +dport_map_port_109=54 +dport_map_port_10=13 +dport_map_port_110=22 +dport_map_port_111=23 +dport_map_port_112=53 +dport_map_port_113=56 +dport_map_port_114=24 +dport_map_port_115=25 +dport_map_port_116=55 +dport_map_port_117=58 +dport_map_port_11=43 +dport_map_port_12=45 +dport_map_port_13=1 +dport_map_port_14=2 +dport_map_port_15=34 +dport_map_port_16=33 +dport_map_port_1=7 +dport_map_port_2=9 +dport_map_port_34=3 +dport_map_port_35=4 +dport_map_port_36=36 +dport_map_port_37=35 +dport_map_port_38=5 +dport_map_port_39=6 +dport_map_port_3=40 +dport_map_port_40=38 +dport_map_port_41=37 +dport_map_port_42=14 +dport_map_port_43=8 +dport_map_port_44=39 +dport_map_port_45=46 +dport_map_port_46=15 +dport_map_port_47=16 +dport_map_port_48=48 +dport_map_port_49=47 +dport_map_port_4=42 +dport_map_port_5=10 +dport_map_port_68=17 +dport_map_port_69=18 +dport_map_port_6=11 +dport_map_port_70=50 +dport_map_port_71=49 +dport_map_port_72=19 +dport_map_port_73=52 +dport_map_port_74=57 +dport_map_port_75=26 +dport_map_port_76=27 +dport_map_port_77=28 +dport_map_port_78=60 +dport_map_port_79=59 +dport_map_port_7=41 +dport_map_port_80=29 +dport_map_port_81=30 +dport_map_port_82=62 +dport_map_port_83=61 +dport_map_port_8=44 +dport_map_port_9=12 +dpp_clock_ratio=2:3 +fpem_mem_entries=65536 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +mem_cache_enable=0 +os=unix +oversubscribe_mode=1 +parity_correction=0 +parity_enable=0 +pbmp_xport_xe=0x40003ffff0000ffffc0003fffe0001fffe +phy_chain_rx_lane_map_physical{1.0}=0x2130 +phy_chain_rx_lane_map_physical{101.0}=0x2310 +phy_chain_rx_lane_map_physical{105.0}=0x3021 +phy_chain_rx_lane_map_physical{109.0}=0x0213 +phy_chain_rx_lane_map_physical{113.0}=0x1302 +phy_chain_rx_lane_map_physical{117.0}=0x0312 +phy_chain_rx_lane_map_physical{121.0}=0x1203 +phy_chain_rx_lane_map_physical{125.0}=0x3021 +phy_chain_rx_lane_map_physical{129.0}=0x1302 +phy_chain_rx_lane_map_physical{13.0}=0x2310 +phy_chain_rx_lane_map_physical{133.0}=0x2310 +phy_chain_rx_lane_map_physical{137.0}=0x1023 +phy_chain_rx_lane_map_physical{141.0}=0x2031 +phy_chain_rx_lane_map_physical{145.0}=0x1032 +phy_chain_rx_lane_map_physical{149.0}=0x1203 +phy_chain_rx_lane_map_physical{153.0}=0x2310 +phy_chain_rx_lane_map_physical{157.0}=0x2013 +phy_chain_rx_lane_map_physical{161.0}=0x2103 +phy_chain_rx_lane_map_physical{165.0}=0x3012 +phy_chain_rx_lane_map_physical{169.0}=0x1320 +phy_chain_rx_lane_map_physical{17.0}=0x0213 +phy_chain_rx_lane_map_physical{173.0}=0x2301 +phy_chain_rx_lane_map_physical{177.0}=0x1032 +phy_chain_rx_lane_map_physical{181.0}=0x1032 +phy_chain_rx_lane_map_physical{185.0}=0x3210 +phy_chain_rx_lane_map_physical{189.0}=0x2103 +phy_chain_rx_lane_map_physical{193.0}=0x1032 +phy_chain_rx_lane_map_physical{197.0}=0x1032 +phy_chain_rx_lane_map_physical{201.0}=0x2301 +phy_chain_rx_lane_map_physical{205.0}=0x2301 +phy_chain_rx_lane_map_physical{209.0}=0x2103 +phy_chain_rx_lane_map_physical{21.0}=0x3120 +phy_chain_rx_lane_map_physical{213.0}=0x3201 +phy_chain_rx_lane_map_physical{217.0}=0x2301 +phy_chain_rx_lane_map_physical{221.0}=0x2301 +phy_chain_rx_lane_map_physical{225.0}=0x0123 +phy_chain_rx_lane_map_physical{229.0}=0x1302 +phy_chain_rx_lane_map_physical{233.0}=0x3120 +phy_chain_rx_lane_map_physical{237.0}=0x0123 +phy_chain_rx_lane_map_physical{241.0}=0x2310 +phy_chain_rx_lane_map_physical{245.0}=0x0312 +phy_chain_rx_lane_map_physical{249.0}=0x3021 +phy_chain_rx_lane_map_physical{25.0}=0x1203 +phy_chain_rx_lane_map_physical{253.0}=0x2013 +phy_chain_rx_lane_map_physical{29.0}=0x3012 +phy_chain_rx_lane_map_physical{33.0}=0x3210 +phy_chain_rx_lane_map_physical{37.0}=0x3210 +phy_chain_rx_lane_map_physical{41.0}=0x1230 +phy_chain_rx_lane_map_physical{45.0}=0x2013 +phy_chain_rx_lane_map_physical{49.0}=0x2301 +phy_chain_rx_lane_map_physical{5.0}=0x2031 +phy_chain_rx_lane_map_physical{53.0}=0x3210 +phy_chain_rx_lane_map_physical{57.0}=0x1203 +phy_chain_rx_lane_map_physical{61.0}=0x0231 +phy_chain_rx_lane_map_physical{65.0}=0x2301 +phy_chain_rx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{73.0}=0x2013 +phy_chain_rx_lane_map_physical{77.0}=0x3012 +phy_chain_rx_lane_map_physical{81.0}=0x2301 +phy_chain_rx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{89.0}=0x2013 +phy_chain_rx_lane_map_physical{9.0}=0x0312 +phy_chain_rx_lane_map_physical{93.0}=0x3012 +phy_chain_rx_lane_map_physical{97.0}=0x1320 +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{100.0}=0x0 +phy_chain_rx_polarity_flip_physical{101.0}=0x1 +phy_chain_rx_polarity_flip_physical{102.0}=0x1 +phy_chain_rx_polarity_flip_physical{103.0}=0x0 +phy_chain_rx_polarity_flip_physical{104.0}=0x0 +phy_chain_rx_polarity_flip_physical{105.0}=0x1 +phy_chain_rx_polarity_flip_physical{106.0}=0x1 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x0 +phy_chain_rx_polarity_flip_physical{109.0}=0x1 +phy_chain_rx_polarity_flip_physical{11.0}=0x1 +phy_chain_rx_polarity_flip_physical{110.0}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x1 +phy_chain_rx_polarity_flip_physical{112.0}=0x1 +phy_chain_rx_polarity_flip_physical{113.0}=0x1 +phy_chain_rx_polarity_flip_physical{114.0}=0x0 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 +phy_chain_rx_polarity_flip_physical{117.0}=0x0 +phy_chain_rx_polarity_flip_physical{118.0}=0x0 +phy_chain_rx_polarity_flip_physical{119.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 +phy_chain_rx_polarity_flip_physical{120.0}=0x1 +phy_chain_rx_polarity_flip_physical{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +phy_chain_rx_polarity_flip_physical{123.0}=0x1 +phy_chain_rx_polarity_flip_physical{124.0}=0x1 +phy_chain_rx_polarity_flip_physical{125.0}=0x1 +phy_chain_rx_polarity_flip_physical{126.0}=0x0 +phy_chain_rx_polarity_flip_physical{127.0}=0x1 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x1 +phy_chain_rx_polarity_flip_physical{131.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x1 +phy_chain_rx_polarity_flip_physical{135.0}=0x1 +phy_chain_rx_polarity_flip_physical{136.0}=0x1 +phy_chain_rx_polarity_flip_physical{137.0}=0x0 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{140.0}=0x0 +phy_chain_rx_polarity_flip_physical{141.0}=0x1 +phy_chain_rx_polarity_flip_physical{142.0}=0x1 +phy_chain_rx_polarity_flip_physical{143.0}=0x0 +phy_chain_rx_polarity_flip_physical{144.0}=0x0 +phy_chain_rx_polarity_flip_physical{145.0}=0x1 +phy_chain_rx_polarity_flip_physical{146.0}=0x1 +phy_chain_rx_polarity_flip_physical{147.0}=0x0 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x0 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x0 +phy_chain_rx_polarity_flip_physical{152.0}=0x1 +phy_chain_rx_polarity_flip_physical{153.0}=0x1 +phy_chain_rx_polarity_flip_physical{154.0}=0x1 +phy_chain_rx_polarity_flip_physical{155.0}=0x0 +phy_chain_rx_polarity_flip_physical{156.0}=0x0 +phy_chain_rx_polarity_flip_physical{157.0}=0x1 +phy_chain_rx_polarity_flip_physical{158.0}=0x0 +phy_chain_rx_polarity_flip_physical{159.0}=0x0 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 +phy_chain_rx_polarity_flip_physical{161.0}=0x0 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x1 +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x0 +phy_chain_rx_polarity_flip_physical{167.0}=0x0 +phy_chain_rx_polarity_flip_physical{168.0}=0x1 +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{17.0}=0x1 +phy_chain_rx_polarity_flip_physical{170.0}=0x0 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x1 +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x0 +phy_chain_rx_polarity_flip_physical{175.0}=0x1 +phy_chain_rx_polarity_flip_physical{176.0}=0x1 +phy_chain_rx_polarity_flip_physical{177.0}=0x1 +phy_chain_rx_polarity_flip_physical{178.0}=0x0 +phy_chain_rx_polarity_flip_physical{179.0}=0x1 +phy_chain_rx_polarity_flip_physical{18.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x1 +phy_chain_rx_polarity_flip_physical{181.0}=0x0 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x1 +phy_chain_rx_polarity_flip_physical{184.0}=0x0 +phy_chain_rx_polarity_flip_physical{185.0}=0x1 +phy_chain_rx_polarity_flip_physical{186.0}=0x1 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 +phy_chain_rx_polarity_flip_physical{189.0}=0x0 +phy_chain_rx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{190.0}=0x0 +phy_chain_rx_polarity_flip_physical{191.0}=0x0 +phy_chain_rx_polarity_flip_physical{192.0}=0x1 +phy_chain_rx_polarity_flip_physical{193.0}=0x1 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x1 +phy_chain_rx_polarity_flip_physical{196.0}=0x1 +phy_chain_rx_polarity_flip_physical{197.0}=0x0 +phy_chain_rx_polarity_flip_physical{198.0}=0x1 +phy_chain_rx_polarity_flip_physical{199.0}=0x1 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x0 +phy_chain_rx_polarity_flip_physical{201.0}=0x0 +phy_chain_rx_polarity_flip_physical{202.0}=0x1 +phy_chain_rx_polarity_flip_physical{203.0}=0x0 +phy_chain_rx_polarity_flip_physical{204.0}=0x1 +phy_chain_rx_polarity_flip_physical{205.0}=0x0 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x1 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 +phy_chain_rx_polarity_flip_physical{209.0}=0x0 +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{210.0}=0x1 +phy_chain_rx_polarity_flip_physical{211.0}=0x0 +phy_chain_rx_polarity_flip_physical{212.0}=0x1 +phy_chain_rx_polarity_flip_physical{213.0}=0x1 +phy_chain_rx_polarity_flip_physical{214.0}=0x1 +phy_chain_rx_polarity_flip_physical{215.0}=0x1 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 +phy_chain_rx_polarity_flip_physical{217.0}=0x0 +phy_chain_rx_polarity_flip_physical{218.0}=0x1 +phy_chain_rx_polarity_flip_physical{219.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{220.0}=0x0 +phy_chain_rx_polarity_flip_physical{221.0}=0x0 +phy_chain_rx_polarity_flip_physical{222.0}=0x0 +phy_chain_rx_polarity_flip_physical{223.0}=0x1 +phy_chain_rx_polarity_flip_physical{224.0}=0x1 +phy_chain_rx_polarity_flip_physical{225.0}=0x1 +phy_chain_rx_polarity_flip_physical{226.0}=0x1 +phy_chain_rx_polarity_flip_physical{227.0}=0x1 +phy_chain_rx_polarity_flip_physical{228.0}=0x1 +phy_chain_rx_polarity_flip_physical{229.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{230.0}=0x0 +phy_chain_rx_polarity_flip_physical{231.0}=0x1 +phy_chain_rx_polarity_flip_physical{232.0}=0x1 +phy_chain_rx_polarity_flip_physical{233.0}=0x1 +phy_chain_rx_polarity_flip_physical{234.0}=0x0 +phy_chain_rx_polarity_flip_physical{235.0}=0x1 +phy_chain_rx_polarity_flip_physical{236.0}=0x1 +phy_chain_rx_polarity_flip_physical{237.0}=0x1 +phy_chain_rx_polarity_flip_physical{238.0}=0x1 +phy_chain_rx_polarity_flip_physical{239.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x1 +phy_chain_rx_polarity_flip_physical{240.0}=0x0 +phy_chain_rx_polarity_flip_physical{241.0}=0x0 +phy_chain_rx_polarity_flip_physical{242.0}=0x1 +phy_chain_rx_polarity_flip_physical{243.0}=0x0 +phy_chain_rx_polarity_flip_physical{244.0}=0x0 +phy_chain_rx_polarity_flip_physical{245.0}=0x1 +phy_chain_rx_polarity_flip_physical{246.0}=0x0 +phy_chain_rx_polarity_flip_physical{247.0}=0x1 +phy_chain_rx_polarity_flip_physical{248.0}=0x1 +phy_chain_rx_polarity_flip_physical{249.0}=0x1 +phy_chain_rx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{250.0}=0x0 +phy_chain_rx_polarity_flip_physical{251.0}=0x1 +phy_chain_rx_polarity_flip_physical{252.0}=0x0 +phy_chain_rx_polarity_flip_physical{253.0}=0x1 +phy_chain_rx_polarity_flip_physical{254.0}=0x1 +phy_chain_rx_polarity_flip_physical{255.0}=0x0 +phy_chain_rx_polarity_flip_physical{256.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x1 +phy_chain_rx_polarity_flip_physical{36.0}=0x1 +phy_chain_rx_polarity_flip_physical{37.0}=0x0 +phy_chain_rx_polarity_flip_physical{38.0}=0x1 +phy_chain_rx_polarity_flip_physical{39.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_rx_polarity_flip_physical{40.0}=0x1 +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x0 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{46.0}=0x1 +phy_chain_rx_polarity_flip_physical{47.0}=0x1 +phy_chain_rx_polarity_flip_physical{48.0}=0x0 +phy_chain_rx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{54.0}=0x1 +phy_chain_rx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{56.0}=0x0 +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x1 +phy_chain_rx_polarity_flip_physical{63.0}=0x0 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x1 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_rx_polarity_flip_physical{68.0}=0x0 +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{76.0}=0x1 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x1 +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x0 +phy_chain_rx_polarity_flip_physical{84.0}=0x0 +phy_chain_rx_polarity_flip_physical{85.0}=0x0 +phy_chain_rx_polarity_flip_physical{86.0}=0x0 +phy_chain_rx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{91.0}=0x0 +phy_chain_rx_polarity_flip_physical{92.0}=0x1 +phy_chain_rx_polarity_flip_physical{93.0}=0x0 +phy_chain_rx_polarity_flip_physical{94.0}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x1 +phy_chain_rx_polarity_flip_physical{96.0}=0x1 +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_lane_map_physical{1.0}=0x2301 +phy_chain_tx_lane_map_physical{101.0}=0x2103 +phy_chain_tx_lane_map_physical{105.0}=0x2310 +phy_chain_tx_lane_map_physical{109.0}=0x2013 +phy_chain_tx_lane_map_physical{113.0}=0x0312 +phy_chain_tx_lane_map_physical{117.0}=0x1230 +phy_chain_tx_lane_map_physical{121.0}=0x1203 +phy_chain_tx_lane_map_physical{125.0}=0x1203 +phy_chain_tx_lane_map_physical{129.0}=0x1320 +phy_chain_tx_lane_map_physical{13.0}=0x0312 +phy_chain_tx_lane_map_physical{133.0}=0x3201 +phy_chain_tx_lane_map_physical{137.0}=0x2130 +phy_chain_tx_lane_map_physical{141.0}=0x1032 +phy_chain_tx_lane_map_physical{145.0}=0x1320 +phy_chain_tx_lane_map_physical{149.0}=0x0321 +phy_chain_tx_lane_map_physical{153.0}=0x1023 +phy_chain_tx_lane_map_physical{157.0}=0x3021 +phy_chain_tx_lane_map_physical{161.0}=0x0321 +phy_chain_tx_lane_map_physical{165.0}=0x2130 +phy_chain_tx_lane_map_physical{169.0}=0x1320 +phy_chain_tx_lane_map_physical{17.0}=0x0213 +phy_chain_tx_lane_map_physical{173.0}=0x2130 +phy_chain_tx_lane_map_physical{177.0}=0x0321 +phy_chain_tx_lane_map_physical{181.0}=0x2130 +phy_chain_tx_lane_map_physical{185.0}=0x0132 +phy_chain_tx_lane_map_physical{189.0}=0x1320 +phy_chain_tx_lane_map_physical{193.0}=0x3012 +phy_chain_tx_lane_map_physical{197.0}=0x2130 +phy_chain_tx_lane_map_physical{201.0}=0x1023 +phy_chain_tx_lane_map_physical{205.0}=0x1320 +phy_chain_tx_lane_map_physical{209.0}=0x0321 +phy_chain_tx_lane_map_physical{21.0}=0x2310 +phy_chain_tx_lane_map_physical{213.0}=0x2031 +phy_chain_tx_lane_map_physical{217.0}=0x1032 +phy_chain_tx_lane_map_physical{221.0}=0x3201 +phy_chain_tx_lane_map_physical{225.0}=0x0123 +phy_chain_tx_lane_map_physical{229.0}=0x0231 +phy_chain_tx_lane_map_physical{233.0}=0x1302 +phy_chain_tx_lane_map_physical{237.0}=0x3210 +phy_chain_tx_lane_map_physical{241.0}=0x0312 +phy_chain_tx_lane_map_physical{245.0}=0x2031 +phy_chain_tx_lane_map_physical{249.0}=0x3201 +phy_chain_tx_lane_map_physical{25.0}=0x0312 +phy_chain_tx_lane_map_physical{253.0}=0x3120 +phy_chain_tx_lane_map_physical{29.0}=0x1230 +phy_chain_tx_lane_map_physical{33.0}=0x3201 +phy_chain_tx_lane_map_physical{37.0}=0x3201 +phy_chain_tx_lane_map_physical{41.0}=0x3201 +phy_chain_tx_lane_map_physical{45.0}=0x2031 +phy_chain_tx_lane_map_physical{49.0}=0x0132 +phy_chain_tx_lane_map_physical{5.0}=0x2301 +phy_chain_tx_lane_map_physical{53.0}=0x3201 +phy_chain_tx_lane_map_physical{57.0}=0x3201 +phy_chain_tx_lane_map_physical{61.0}=0x2031 +phy_chain_tx_lane_map_physical{65.0}=0x0321 +phy_chain_tx_lane_map_physical{69.0}=0x3201 +phy_chain_tx_lane_map_physical{73.0}=0x3201 +phy_chain_tx_lane_map_physical{77.0}=0x1032 +phy_chain_tx_lane_map_physical{81.0}=0x0132 +phy_chain_tx_lane_map_physical{85.0}=0x1320 +phy_chain_tx_lane_map_physical{89.0}=0x3201 +phy_chain_tx_lane_map_physical{9.0}=0x2130 +phy_chain_tx_lane_map_physical{93.0}=0x0321 +phy_chain_tx_lane_map_physical{97.0}=0x1320 +phy_chain_tx_polarity_flip_physical{1.0}=0x1 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 +phy_chain_tx_polarity_flip_physical{101.0}=0x0 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +phy_chain_tx_polarity_flip_physical{103.0}=0x1 +phy_chain_tx_polarity_flip_physical{104.0}=0x0 +phy_chain_tx_polarity_flip_physical{105.0}=0x1 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_tx_polarity_flip_physical{107.0}=0x0 +phy_chain_tx_polarity_flip_physical{108.0}=0x0 +phy_chain_tx_polarity_flip_physical{109.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{110.0}=0x1 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +phy_chain_tx_polarity_flip_physical{112.0}=0x1 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +phy_chain_tx_polarity_flip_physical{114.0}=0x0 +phy_chain_tx_polarity_flip_physical{115.0}=0x1 +phy_chain_tx_polarity_flip_physical{116.0}=0x1 +phy_chain_tx_polarity_flip_physical{117.0}=0x1 +phy_chain_tx_polarity_flip_physical{118.0}=0x1 +phy_chain_tx_polarity_flip_physical{119.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +phy_chain_tx_polarity_flip_physical{121.0}=0x0 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_tx_polarity_flip_physical{123.0}=0x0 +phy_chain_tx_polarity_flip_physical{124.0}=0x0 +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x0 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 +phy_chain_tx_polarity_flip_physical{129.0}=0x0 +phy_chain_tx_polarity_flip_physical{13.0}=0x1 +phy_chain_tx_polarity_flip_physical{130.0}=0x1 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x1 +phy_chain_tx_polarity_flip_physical{133.0}=0x0 +phy_chain_tx_polarity_flip_physical{134.0}=0x0 +phy_chain_tx_polarity_flip_physical{135.0}=0x1 +phy_chain_tx_polarity_flip_physical{136.0}=0x0 +phy_chain_tx_polarity_flip_physical{137.0}=0x0 +phy_chain_tx_polarity_flip_physical{138.0}=0x1 +phy_chain_tx_polarity_flip_physical{139.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x1 +phy_chain_tx_polarity_flip_physical{140.0}=0x1 +phy_chain_tx_polarity_flip_physical{141.0}=0x1 +phy_chain_tx_polarity_flip_physical{142.0}=0x0 +phy_chain_tx_polarity_flip_physical{143.0}=0x1 +phy_chain_tx_polarity_flip_physical{144.0}=0x1 +phy_chain_tx_polarity_flip_physical{145.0}=0x1 +phy_chain_tx_polarity_flip_physical{146.0}=0x0 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x1 +phy_chain_tx_polarity_flip_physical{149.0}=0x1 +phy_chain_tx_polarity_flip_physical{15.0}=0x1 +phy_chain_tx_polarity_flip_physical{150.0}=0x0 +phy_chain_tx_polarity_flip_physical{151.0}=0x1 +phy_chain_tx_polarity_flip_physical{152.0}=0x1 +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x1 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 +phy_chain_tx_polarity_flip_physical{157.0}=0x1 +phy_chain_tx_polarity_flip_physical{158.0}=0x0 +phy_chain_tx_polarity_flip_physical{159.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 +phy_chain_tx_polarity_flip_physical{160.0}=0x1 +phy_chain_tx_polarity_flip_physical{161.0}=0x0 +phy_chain_tx_polarity_flip_physical{162.0}=0x0 +phy_chain_tx_polarity_flip_physical{163.0}=0x0 +phy_chain_tx_polarity_flip_physical{164.0}=0x1 +phy_chain_tx_polarity_flip_physical{165.0}=0x0 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x0 +phy_chain_tx_polarity_flip_physical{168.0}=0x1 +phy_chain_tx_polarity_flip_physical{169.0}=0x1 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_tx_polarity_flip_physical{170.0}=0x0 +phy_chain_tx_polarity_flip_physical{171.0}=0x1 +phy_chain_tx_polarity_flip_physical{172.0}=0x1 +phy_chain_tx_polarity_flip_physical{173.0}=0x1 +phy_chain_tx_polarity_flip_physical{174.0}=0x1 +phy_chain_tx_polarity_flip_physical{175.0}=0x1 +phy_chain_tx_polarity_flip_physical{176.0}=0x0 +phy_chain_tx_polarity_flip_physical{177.0}=0x0 +phy_chain_tx_polarity_flip_physical{178.0}=0x1 +phy_chain_tx_polarity_flip_physical{179.0}=0x0 +phy_chain_tx_polarity_flip_physical{18.0}=0x0 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 +phy_chain_tx_polarity_flip_physical{181.0}=0x0 +phy_chain_tx_polarity_flip_physical{182.0}=0x1 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x1 +phy_chain_tx_polarity_flip_physical{185.0}=0x1 +phy_chain_tx_polarity_flip_physical{186.0}=0x0 +phy_chain_tx_polarity_flip_physical{187.0}=0x1 +phy_chain_tx_polarity_flip_physical{188.0}=0x1 +phy_chain_tx_polarity_flip_physical{189.0}=0x1 +phy_chain_tx_polarity_flip_physical{19.0}=0x1 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x1 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 +phy_chain_tx_polarity_flip_physical{193.0}=0x0 +phy_chain_tx_polarity_flip_physical{194.0}=0x0 +phy_chain_tx_polarity_flip_physical{195.0}=0x1 +phy_chain_tx_polarity_flip_physical{196.0}=0x1 +phy_chain_tx_polarity_flip_physical{197.0}=0x0 +phy_chain_tx_polarity_flip_physical{198.0}=0x1 +phy_chain_tx_polarity_flip_physical{199.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 +phy_chain_tx_polarity_flip_physical{201.0}=0x0 +phy_chain_tx_polarity_flip_physical{202.0}=0x1 +phy_chain_tx_polarity_flip_physical{203.0}=0x1 +phy_chain_tx_polarity_flip_physical{204.0}=0x1 +phy_chain_tx_polarity_flip_physical{205.0}=0x0 +phy_chain_tx_polarity_flip_physical{206.0}=0x0 +phy_chain_tx_polarity_flip_physical{207.0}=0x1 +phy_chain_tx_polarity_flip_physical{208.0}=0x0 +phy_chain_tx_polarity_flip_physical{209.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x1 +phy_chain_tx_polarity_flip_physical{210.0}=0x0 +phy_chain_tx_polarity_flip_physical{211.0}=0x0 +phy_chain_tx_polarity_flip_physical{212.0}=0x1 +phy_chain_tx_polarity_flip_physical{213.0}=0x1 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x1 +phy_chain_tx_polarity_flip_physical{217.0}=0x1 +phy_chain_tx_polarity_flip_physical{218.0}=0x1 +phy_chain_tx_polarity_flip_physical{219.0}=0x1 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x0 +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x1 +phy_chain_tx_polarity_flip_physical{223.0}=0x1 +phy_chain_tx_polarity_flip_physical{224.0}=0x1 +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x0 +phy_chain_tx_polarity_flip_physical{227.0}=0x0 +phy_chain_tx_polarity_flip_physical{228.0}=0x1 +phy_chain_tx_polarity_flip_physical{229.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_tx_polarity_flip_physical{230.0}=0x0 +phy_chain_tx_polarity_flip_physical{231.0}=0x1 +phy_chain_tx_polarity_flip_physical{232.0}=0x0 +phy_chain_tx_polarity_flip_physical{233.0}=0x1 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x0 +phy_chain_tx_polarity_flip_physical{236.0}=0x0 +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x1 +phy_chain_tx_polarity_flip_physical{241.0}=0x1 +phy_chain_tx_polarity_flip_physical{242.0}=0x0 +phy_chain_tx_polarity_flip_physical{243.0}=0x1 +phy_chain_tx_polarity_flip_physical{244.0}=0x1 +phy_chain_tx_polarity_flip_physical{245.0}=0x1 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x0 +phy_chain_tx_polarity_flip_physical{248.0}=0x1 +phy_chain_tx_polarity_flip_physical{249.0}=0x1 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{250.0}=0x1 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x1 +phy_chain_tx_polarity_flip_physical{253.0}=0x1 +phy_chain_tx_polarity_flip_physical{254.0}=0x1 +phy_chain_tx_polarity_flip_physical{255.0}=0x0 +phy_chain_tx_polarity_flip_physical{256.0}=0x1 +phy_chain_tx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_tx_polarity_flip_physical{29.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x1 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x1 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x1 +phy_chain_tx_polarity_flip_physical{43.0}=0x1 +phy_chain_tx_polarity_flip_physical{44.0}=0x1 +phy_chain_tx_polarity_flip_physical{45.0}=0x0 +phy_chain_tx_polarity_flip_physical{46.0}=0x1 +phy_chain_tx_polarity_flip_physical{47.0}=0x1 +phy_chain_tx_polarity_flip_physical{48.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 +phy_chain_tx_polarity_flip_physical{53.0}=0x1 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x1 +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_tx_polarity_flip_physical{58.0}=0x1 +phy_chain_tx_polarity_flip_physical{59.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +phy_chain_tx_polarity_flip_physical{64.0}=0x0 +phy_chain_tx_polarity_flip_physical{65.0}=0x0 +phy_chain_tx_polarity_flip_physical{66.0}=0x1 +phy_chain_tx_polarity_flip_physical{67.0}=0x1 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x0 +phy_chain_tx_polarity_flip_physical{72.0}=0x1 +phy_chain_tx_polarity_flip_physical{73.0}=0x0 +phy_chain_tx_polarity_flip_physical{74.0}=0x1 +phy_chain_tx_polarity_flip_physical{75.0}=0x1 +phy_chain_tx_polarity_flip_physical{76.0}=0x0 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x0 +phy_chain_tx_polarity_flip_physical{79.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 +phy_chain_tx_polarity_flip_physical{80.0}=0x1 +phy_chain_tx_polarity_flip_physical{81.0}=0x1 +phy_chain_tx_polarity_flip_physical{82.0}=0x1 +phy_chain_tx_polarity_flip_physical{83.0}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +phy_chain_tx_polarity_flip_physical{89.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 +phy_chain_tx_polarity_flip_physical{93.0}=0x1 +phy_chain_tx_polarity_flip_physical{94.0}=0x0 +phy_chain_tx_polarity_flip_physical{95.0}=0x1 +phy_chain_tx_polarity_flip_physical{96.0}=0x0 +phy_chain_tx_polarity_flip_physical{97.0}=0x1 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x1 +portmap_100=259:10 +portmap_101=262:10 +portmap_102=193:100 +portmap_103=197:100 +portmap_104=201:100 +portmap_105=205:100 +portmap_106=209:100 +portmap_107=213:100 +portmap_108=217:100 +portmap_109=221:100 +portmap_10=37:100 +portmap_110=225:100 +portmap_111=229:100 +portmap_112=233:100 +portmap_113=237:100 +portmap_114=241:100 +portmap_115=245:100 +portmap_116=249:100 +portmap_117=253:100 +portmap_11=41:100 +portmap_12=45:100 +portmap_135=263:10 +portmap_13=49:100 +portmap_14=53:100 +portmap_15=57:100 +portmap_16=61:100 +portmap_1=1:100 +portmap_2=5:100 +portmap_33=260:10 +portmap_34=65:100 +portmap_35=69:100 +portmap_36=73:100 +portmap_37=77:100 +portmap_38=81:100 +portmap_39=85:100 +portmap_3=9:100 +portmap_40=89:100 +portmap_41=93:100 +portmap_42=97:100 +portmap_43=101:100 +portmap_44=105:100 +portmap_45=109:100 +portmap_46=113:100 +portmap_47=117:100 +portmap_48=121:100 +portmap_49=125:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_66=257:10 +portmap_67=261:10 +portmap_68=129:100 +portmap_69=133:100 +portmap_6=21:100 +portmap_70=137:100 +portmap_71=141:100 +portmap_72=145:100 +portmap_73=149:100 +portmap_74=153:100 +portmap_75=157:100 +portmap_76=161:100 +portmap_77=165:100 +portmap_78=169:100 +portmap_79=173:100 +portmap_7=25:100 +portmap_80=177:100 +portmap_81=181:100 +portmap_82=185:100 +portmap_83=189:100 +portmap_8=29:100 +portmap_9=33:100 + +lpm_scaling_enable=0 +bcm_num_cos=8 +bcm_stat_jumbo=9236 +ipv6_lpm_128b_enable=1 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +phy_an_allow_pll_change_hg=0 +robust_hash_disable_egress_vlan=1 +robust_hash_disable_mpls=1 +robust_hash_disable_vlan=1 +sram_scan_enable=0 +stable_size=0x5500000 +mmu_lossless=1 diff --git a/device/delta/x86_64-delta_ag9064-r0/default_sku b/device/delta/x86_64-delta_ag9064-r0/default_sku new file mode 100644 index 000000000000..5de7fcd3733a --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/default_sku @@ -0,0 +1 @@ +Delta-ag9064 t1 diff --git a/device/delta/x86_64-delta_ag9064-r0/installer.conf b/device/delta/x86_64-delta_ag9064-r0/installer.conf new file mode 100644 index 000000000000..fa2af8b7a007 --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_SPEED=115200 diff --git a/device/delta/x86_64-delta_ag9064-r0/led_proc_init.soc b/device/delta/x86_64-delta_ag9064-r0/led_proc_init.soc new file mode 100644 index 000000000000..2e6f394b1219 --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/led_proc_init.soc @@ -0,0 +1,63 @@ +led 0 stop +led 0 prog \ + 02 00 60 E0 02 A0 60 E2 86 ED 02 00 60 E1 2E E0 \ + 32 08 97 02 00 0E 05 60 E3 2E E0 32 00 32 01 B7 \ + 97 02 00 0E 00 12 E7 FE E1 50 86 E0 86 E1 06 E1 \ + D2 04 74 19 16 E7 61 EB 06 E3 12 05 67 92 06 E3 \ + 12 04 67 92 06 E3 12 03 67 92 16 E9 61 EB 06 E5 \ + 12 03 67 92 02 02 60 EC 02 00 60 E1 77 66 02 01 \ + 60 EC 02 00 60 E1 12 E7 FE E1 05 60 EB 12 E3 FE \ + E1 05 16 EC 67 92 86 E1 06 E1 D2 04 74 66 06 EC \ + D2 02 70 5E 06 E2 F2 04 60 E2 06 E0 D2 40 74 0A \ + 3A C0 09 75 A9 06 EB D2 00 70 A5 16 ED 99 99 1A \ + 00 71 A5 77 A9 32 0F 87 57 32 0E 87 57 00 00 00 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog \ + 02 00 60 E0 02 A0 60 E2 86 ED 02 00 60 E1 2E E0 \ + 32 08 97 02 00 0E 05 60 E3 2E E0 32 00 32 01 B7 \ + 97 02 00 0E 00 12 E7 FE E1 50 86 E0 86 E1 06 E1 \ + D2 04 74 19 16 E7 61 EB 06 E3 12 05 67 92 06 E3 \ + 12 04 67 92 06 E3 12 03 67 92 16 E9 61 EB 06 E5 \ + 12 03 67 92 02 02 60 EC 02 00 60 E1 77 66 02 01 \ + 60 EC 02 00 60 E1 12 E7 FE E1 05 60 EB 12 E3 FE \ + E1 05 16 EC 67 92 86 E1 06 E1 D2 04 74 66 06 EC \ + D2 02 70 5E 06 E2 F2 04 60 E2 06 E0 D2 40 74 0A \ + 3A C0 09 75 A9 06 EB D2 00 70 A5 16 ED 99 99 1A \ + 00 71 A5 77 A9 32 0F 87 57 32 0E 87 57 00 00 00 +led 1 auto on +led 1 start + +led 2 stop +led 2 prog \ + 02 00 60 E0 02 A0 60 E2 86 ED 02 00 60 E1 2E E0 \ + 32 08 97 02 00 0E 05 60 E3 2E E0 32 00 32 01 B7 \ + 97 02 00 0E 00 12 E7 FE E1 50 86 E0 86 E1 06 E1 \ + D2 04 74 19 16 E7 61 EB 06 E3 12 05 67 92 06 E3 \ + 12 04 67 92 06 E3 12 03 67 92 16 E9 61 EB 06 E5 \ + 12 03 67 92 02 02 60 EC 02 00 60 E1 77 66 02 01 \ + 60 EC 02 00 60 E1 12 E7 FE E1 05 60 EB 12 E3 FE \ + E1 05 16 EC 67 92 86 E1 06 E1 D2 04 74 66 06 EC \ + D2 02 70 5E 06 E2 F2 04 60 E2 06 E0 D2 40 74 0A \ + 3A C0 09 75 A9 06 EB D2 00 70 A5 16 ED 99 99 1A \ + 00 71 A5 77 A9 32 0F 87 57 32 0E 87 57 00 00 00 +led 2 auto on +led 2 start + +led 3 stop +led 3 prog \ + 02 00 60 E0 02 A0 60 E2 86 ED 02 00 60 E1 2E E0 \ + 32 08 97 02 00 0E 05 60 E3 2E E0 32 00 32 01 B7 \ + 97 02 00 0E 00 12 E7 FE E1 50 86 E0 86 E1 06 E1 \ + D2 04 74 19 16 E7 61 EB 06 E3 12 05 67 92 06 E3 \ + 12 04 67 92 06 E3 12 03 67 92 16 E9 61 EB 06 E5 \ + 12 03 67 92 02 02 60 EC 02 00 60 E1 77 66 02 01 \ + 60 EC 02 00 60 E1 12 E7 FE E1 05 60 EB 12 E3 FE \ + E1 05 16 EC 67 92 86 E1 06 E1 D2 04 74 66 06 EC \ + D2 02 70 5E 06 E2 F2 04 60 E2 06 E0 D2 40 74 0A \ + 3A C0 09 75 A9 06 EB D2 00 70 A5 16 ED 99 99 1A \ + 00 71 A5 77 A9 32 0F 87 57 32 0E 87 57 00 00 00 +led 3 auto on +led 3 start diff --git a/device/delta/x86_64-delta_ag9064-r0/plugins/eeprom.py b/device/delta/x86_64-delta_ag9064-r0/plugins/eeprom.py new file mode 100644 index 000000000000..e4048ed302de --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/plugins/eeprom.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# 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: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + _TLV_INFO_MAX_LEN = 256 + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/delta/x86_64-delta_ag9064-r0/plugins/sfputil.py b/device/delta/x86_64-delta_ag9064-r0/plugins/sfputil.py new file mode 100644 index 000000000000..4b33dd8b090f --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/plugins/sfputil.py @@ -0,0 +1,183 @@ +# 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 = 63 + PORTS_IN_BLOCK = 64 + + EEPROM_OFFSET = 20 + + _port_to_eeprom_mapping = {} + + @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 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): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET) + + 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/devices/platform/delta-ag9064-cpld.0/qsfp_present") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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 + + try: + reg_file = open("/sys/devices/platform/delta-ag9064-cpld.0/qsfp_lpmode") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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 + + try: + reg_file = open("/sys/devices/platform/delta-ag9064-cpld.0/qsfp_lpmode", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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).rstrip("L") or "0" + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/delta-ag9064-cpld.0/qsfp_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 + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # 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: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "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 + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/delta/x86_64-delta_ag9064-r0/sensors.conf b/device/delta/x86_64-delta_ag9064-r0/sensors.conf new file mode 100644 index 000000000000..1d8489248a51 --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/sensors.conf @@ -0,0 +1,14 @@ +# libsensors configuration file for DCS-7060CX-32S +# ------------------------------------------------ +# + +bus "i2c-1" "i2c-1-mux (chan_id 1)" + + +# tmp75-i2c-1-4d CPU below side thermal sensor. + +chip "tmp75-i2c-1-4d" + label temp1 "CPU below side thermal sensor" + set temp1_max 60 + set temp1_max_hyst 55 + diff --git a/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/helix4-et-6248brb-48x1G+2x10G.config.bcm b/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/helix4-et-6248brb-48x1G+2x10G.config.bcm new file mode 100644 index 000000000000..05d1c1e8820c --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/helix4-et-6248brb-48x1G+2x10G.config.bcm @@ -0,0 +1,158 @@ +# bcm56340 setting : +# Specifies the base port and phy index of a multi slice phy chip. +#phy_port_primary_and_offset_ value is 0xPPOO 0xPP is primary port number 0xOO is offset of the slice +# bcm56340 QG0 port setting +phy_port_primary_and_offset_1=0x0100 +phy_port_primary_and_offset_2=0x0101 +phy_port_primary_and_offset_3=0x0102 +phy_port_primary_and_offset_4=0x0103 +phy_port_primary_and_offset_5=0x0104 +phy_port_primary_and_offset_6=0x0105 +phy_port_primary_and_offset_7=0x0106 +phy_port_primary_and_offset_8=0x0107 + +# bcm56340 QG1 port setting +phy_port_primary_and_offset_9=0x0900 +phy_port_primary_and_offset_10=0x0901 +phy_port_primary_and_offset_11=0x0902 +phy_port_primary_and_offset_12=0x0903 +phy_port_primary_and_offset_13=0x0904 +phy_port_primary_and_offset_14=0x0905 +phy_port_primary_and_offset_15=0x0906 +phy_port_primary_and_offset_16=0x0907 + +# bcm56340 QG2 port setting +phy_port_primary_and_offset_17=0x1100 +phy_port_primary_and_offset_18=0x1101 +phy_port_primary_and_offset_19=0x1102 +phy_port_primary_and_offset_20=0x1103 +phy_port_primary_and_offset_21=0x1104 +phy_port_primary_and_offset_22=0x1105 +phy_port_primary_and_offset_23=0x1106 +phy_port_primary_and_offset_24=0x1107 + +# bcm56340 QG3 port setting +phy_port_primary_and_offset_25=0x1900 +phy_port_primary_and_offset_26=0x1901 +phy_port_primary_and_offset_27=0x1902 +phy_port_primary_and_offset_28=0x1903 +phy_port_primary_and_offset_29=0x1904 +phy_port_primary_and_offset_30=0x1905 +phy_port_primary_and_offset_31=0x1906 +phy_port_primary_and_offset_32=0x1907 + +# bcm56340 QG4 port setting +phy_port_primary_and_offset_33=0x2100 +phy_port_primary_and_offset_34=0x2101 +phy_port_primary_and_offset_35=0x2102 +phy_port_primary_and_offset_36=0x2103 +phy_port_primary_and_offset_37=0x2104 +phy_port_primary_and_offset_38=0x2105 +phy_port_primary_and_offset_39=0x2106 +phy_port_primary_and_offset_40=0x2107 + +# bcm56340 QG5 port setting +phy_port_primary_and_offset_41=0x2900 +phy_port_primary_and_offset_42=0x2901 +phy_port_primary_and_offset_43=0x2902 +phy_port_primary_and_offset_44=0x2903 +phy_port_primary_and_offset_45=0x2904 +phy_port_primary_and_offset_46=0x2905 +phy_port_primary_and_offset_47=0x2906 +phy_port_primary_and_offset_48=0x2907 + +# bcm56340 port group setting +bcm56340_4x10=1 +portgroup_0=1 +portgroup_1=1 +portgroup_2=1 +portgroup_3=1 +portgroup_4=1 +portgroup_5=1 +portgroup_6=1 +portgroup_7=1 +portgroup_8=1 +portgroup_9=1 +portgroup_10=1 +portgroup_11=1 +portgroup_12=1 + +# Port map +pbmp_xport_ge=0x0001FFFFFFFFFFFE +pbmp_xport_xe=0x3F000000000000 + +# phy addr setting for bcm54285-0 +port_phy_addr_1=0x1 +port_phy_addr_2=0x2 +port_phy_addr_3=0x3 +port_phy_addr_4=0x4 +port_phy_addr_5=0x5 +port_phy_addr_6=0x6 +port_phy_addr_7=0x7 +port_phy_addr_8=0x8 + +# phy addr setting for bcm54285-1 +port_phy_addr_9=0xa +port_phy_addr_10=0xb +port_phy_addr_11=0xc +port_phy_addr_12=0xd +port_phy_addr_13=0xe +port_phy_addr_14=0xf +port_phy_addr_15=0x10 +port_phy_addr_16=0x11 + +# phy addr setting for bcm54285-2 +port_phy_addr_17=0x13 +port_phy_addr_18=0x14 +port_phy_addr_19=0x15 +port_phy_addr_20=0x16 +port_phy_addr_21=0x17 +port_phy_addr_22=0x18 +port_phy_addr_23=0x19 +port_phy_addr_24=0x1a + +# phy addr setting for bcm54285-3 +port_phy_addr_25=0x21 +port_phy_addr_26=0x22 +port_phy_addr_27=0x23 +port_phy_addr_28=0x24 +port_phy_addr_29=0x25 +port_phy_addr_30=0x26 +port_phy_addr_31=0x27 +port_phy_addr_32=0x28 + +# phy addr setting for bcm54285-4 +port_phy_addr_33=0x2a +port_phy_addr_34=0x2b +port_phy_addr_35=0x2c +port_phy_addr_36=0x2d +port_phy_addr_37=0x2e +port_phy_addr_38=0x2f +port_phy_addr_39=0x30 +port_phy_addr_40=0x31 + +# phy addr setting for bcm54285-5 +port_phy_addr_41=0x33 +port_phy_addr_42=0x34 +port_phy_addr_43=0x35 +port_phy_addr_44=0x36 +port_phy_addr_45=0x37 +port_phy_addr_46=0x38 +port_phy_addr_47=0x39 +port_phy_addr_48=0x3a + +# phy addr setting for bcm84758 +port_phy_addr_50=0x40 +port_phy_addr_51=0x41 +port_phy_addr_52=0x42 +port_phy_addr_53=0x43 + +# Fiber prefer setting for bcm54285 +phy_automedium=1 +#phy_fiber_pref value is 1 +phy_ext_rom_boot=0 +phy_sgmii_autoneg_ge=1 + +os=unix +phy_null_port52=1 +phy_null_port53=1 diff --git a/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/port_config.ini b/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/port_config.ini new file mode 100755 index 000000000000..3747a5c4989d --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/port_config.ini @@ -0,0 +1,51 @@ +# name lanes alias index +Ethernet0 1 1000 0 +Ethernet1 2 1000 1 +Ethernet2 3 1000 2 +Ethernet3 4 1000 3 +Ethernet4 5 1000 4 +Ethernet5 6 1000 5 +Ethernet6 7 1000 6 +Ethernet7 8 1000 7 +Ethernet8 9 1000 8 +Ethernet9 10 1000 9 +Ethernet10 11 1000 10 +Ethernet11 12 1000 11 +Ethernet12 13 1000 12 +Ethernet13 14 1000 13 +Ethernet14 15 1000 14 +Ethernet15 16 1000 15 +Ethernet16 17 1000 16 +Ethernet17 18 1000 17 +Ethernet18 19 1000 18 +Ethernet19 20 1000 19 +Ethernet20 21 1000 20 +Ethernet21 22 1000 21 +Ethernet22 23 1000 22 +Ethernet23 24 1000 23 +Ethernet24 25 1000 24 +Ethernet25 26 1000 25 +Ethernet26 27 1000 26 +Ethernet27 28 1000 27 +Ethernet28 29 1000 28 +Ethernet29 30 1000 29 +Ethernet30 31 1000 30 +Ethernet31 32 1000 31 +Ethernet32 33 1000 32 +Ethernet33 34 1000 33 +Ethernet34 35 1000 34 +Ethernet35 36 1000 35 +Ethernet36 37 1000 36 +Ethernet37 38 1000 37 +Ethernet38 39 1000 38 +Ethernet39 40 1000 39 +Ethernet40 41 1000 40 +Ethernet41 42 1000 41 +Ethernet42 43 1000 42 +Ethernet43 44 1000 43 +Ethernet44 45 1000 44 +Ethernet45 46 1000 45 +Ethernet46 47 1000 46 +Ethernet47 48 1000 47 +Ethernet48 54 10000 48 +Ethernet49 53 10000 49 diff --git a/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/sai.profile b/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/sai.profile new file mode 100644 index 000000000000..726e1b6dc667 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/etc/bcm/helix4-et-6248brb-48x1G+2x10G.config.bcm diff --git a/device/delta/x86_64-delta_et-6248brb-r0/default_sku b/device/delta/x86_64-delta_et-6248brb-r0/default_sku new file mode 100644 index 000000000000..ce1cdf6e4c69 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/default_sku @@ -0,0 +1 @@ +Delta-et-6248brb t1 diff --git a/device/delta/x86_64-delta_et-6248brb-r0/fancontrol b/device/delta/x86_64-delta_et-6248brb-r0/fancontrol new file mode 100644 index 000000000000..0deef5b88ef8 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/fancontrol @@ -0,0 +1,12 @@ +INTERVAL=10 +DEVPATH=hwmon1=/sys/bus/i2c/devices +DEVNAME=hwmon1=adt7473 +FCTEMPS=hwmon1/0-0048/hwmon/hwmon*/temp1_input hwmon1/7-0049/hwmon/hwmon*/temp1_input hwmon1/8-004a/hwmon/hwmon*/temp1_input + +FCFANS=hwmon1/0-002e/fan1_input hwmon1/0-002e/fan2_input + +FCTARGETS=hwmon1/0-002e/pwm1 hwmon1/0-002e/pwm2 +MINTEMP=20 +MAXTEMP=60 +MINSTART=75 +MINSTOP=22 diff --git a/device/delta/x86_64-delta_et-6248brb-r0/fancontrol.service b/device/delta/x86_64-delta_et-6248brb-r0/fancontrol.service new file mode 100755 index 000000000000..3864d6d99663 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/fancontrol.service @@ -0,0 +1,279 @@ +#!/bin/bash +# +# Simple script implementing a temperature dependent fan speed control +# Supported Linux kernel versions: 2.6.5 and later +# +# Version 0.70 +# +# Usage: fancontrol [CONFIGFILE] +# +# Dependencies: +# bash, egrep, sed, cut, sleep, readlink, lm_sensors :) +# +# Please send any questions, comments or success stories to +# marius.reiner@hdev.de +# Thanks! +# +# For configuration instructions and warnings please see fancontrol.txt, which +# can be found in the doc/ directory or at the website mentioned above. +# +# +# Copyright 2003 Marius Reiner +# Copyright (C) 2007-2009 Jean Delvare +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# +# + +PIDFILE="/var/run/fancontrol.pid" + +#DEBUG=1 +MAX=255 + +function LoadConfig +{ + local fcvcount fcv + + echo "Loading configuration from $1 ..." + if [ ! -r "$1" ] + then + echo "Error: Can't read configuration file" >&2 + exit 1 + fi + + # grep configuration from file + INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g'` + DEVPATH=`egrep '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g'` + DEVNAME=`egrep '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g'` + FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g'` + MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g'` + MAXTEMP=`egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g'` + MINSTART=`egrep '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g'` + MINSTOP=`egrep '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g'` + HWMON=$( echo "$DEVPATH" | sed 's/=.*$//g') + FCDEVPATH=$( echo "$DEVPATH" | sed 's/^.*=//g') + FCMINTEMP=$MINTEMP + FCMAXTEMP=$MAXTEMP + FCMINSTART=$MINSTART + FCMINSTOP=$MINSTOP + AFCTEMP_1_LOWER=(00 39 36 41 46 55) + AFCTEMP_1_UPPER=(39 39 44 49 54 150) + AFCTEMP_2_LOWER=(00 61 65 69 73 82) + AFCTEMP_2_UPPER=(63 67 71 75 79 150) + AFCTEMP_3_LOWER=(00 51 55 59 63 71) + AFCTEMP_3_UPPER=(53 57 61 65 69 150) + + + FCFANS=`egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g'` + + FCTARGETS=`egrep '^FCTARGETS=.*$' $1 | sed -e 's/FCTARGETS=//g'` + + # Check whether all mandatory settings are set + if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]] + then + echo "Some mandatory settings missing, please check your config file!" >&2 + exit 1 + fi + if [ "$INTERVAL" -le 0 ] + then + echo "Error in configuration file:" >&2 + echo "INTERVAL must be at least 1" >&2 + exit 1 + fi + + # write settings to arrays for easier use and print them + echo + echo "Common settings:" + + temp_string=$FCTEMPS + + let fcvcount=0 + for fcv in $FCTEMPS + do + fcvcount=$((fcvcount+1)) + AFCTEMP[$fcvcount]=$( echo "$temp_string" | cut -d" " -f $fcvcount ) + AFCTEMP[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCTEMP_PATH[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} ) + AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 )) + done + + fan_string=$FCFANS + fcvcount=0 + for fcv in $FCFANS + do + fcvcount=$((fcvcount+1)) + AFCFAN[$fcvcount]=$( echo "$fan_string" | cut -d" " -f $fcvcount ) + AFCFAN_PATH[$fcvcount]=$( echo "${AFCFAN[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + done + + target_string=$FCTARGETS + fcvcount=0 + for fcv in $FCTARGETS + do + fcvcount=$((fcvcount+1)) + AFCTARGET[$fcvcount]=$( echo "$target_string" | cut -d" " -f $fcvcount ) + AFCFAN_TARGET[$fcvcount]=$( echo "${AFCTARGET[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + done + +} + +# Check that all referenced sysfs files exist +function CheckFiles +{ + local outdated=0 fcvcount tsen fan + if [ $outdated -eq 1 ] + then + echo >&2 + echo "At least one referenced file is missing. Either some required kernel" >&2 + echo "modules haven't been loaded, or your configuration file is outdated." >&2 + echo "In the latter case, you should run pwmconfig again." >&2 + fi + return $outdated +} + +LoadConfig $1 + +# Detect path to sensors +if [ ! -d $DIR ] +then + echo $0: 'No sensors found! (did you load the necessary modules?)' >&2 + exit 1 +fi +cd $DIR + +# Check for configuration change +if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ] +then + echo "Configuration is too old, please run pwmconfig again" >&2 + exit 1 +fi +if [ "$DIR" = "/" -a -n "$DEVPATH" ] +then + echo "Unneeded DEVPATH with absolute device paths" >&2 + exit 1 +fi +CheckFiles || exit 1 + +if [ -f "$PIDFILE" ] +then + echo "File $PIDFILE exists, is fancontrol already running?" >&2 + exit 1 +fi +echo $$ > "$PIDFILE" + +# main function +function UpdateThermalSensors +{ + fcvcount=0 + for fcv in $FCTEMPS + do + fcvcount=$((fcvcount+1)) + AFCTEMP[$fcvcount]=$( cat ${AFCTEMP_PATH[$fcvcount]} ) + AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 )) + done +} + +function UpdateThermalLevel +{ + AFCTEMP_NUM=$((6-${AFCTEMP_LEVEL[$i]})) + AFCTEMP_UPPER_BUF=AFCTEMP_"$i"_UPPER["$AFCTEMP_NUM"] + AFCTEMP_LOWER_BUF=AFCTEMP_"$i"_LOWER["$AFCTEMP_NUM"] + + AFCTEMP_UPPER=${!AFCTEMP_UPPER_BUF} + AFCTEMP_LOWER=${!AFCTEMP_LOWER_BUF} + + + if (( ("${AFCTEMP[$i]}" <= "$AFCTEMP_UPPER") && ("${AFCTEMP[$i]}" >= "$AFCTEMP_LOWER") )) ; then + FLAG=2 + elif (( "${AFCTEMP[$i]}" > "$AFCTEMP_UPPER" )); then + AFCTEMP_LEVEL[$i]=$((${AFCTEMP_LEVEL[$i]} - 1)) + FLAG=1 + elif (( "${AFCTEMP[$i]}" < "$AFCTEMP_LOWER" )); then + AFCTEMP_LEVEL[$i]=$((${AFCTEMP_LEVEL[$i]} + 1)) + FLAG=1 + else + AFCTEMP_LEVEL[$i]=1 + FLAG=2 + fi +} + +function UpdateFanSpeeds +{ + #echo "num tmp lev F L H" + #Update level + for i in 1 2 3 + do + #echo "----------------------" + FLAG=0 + #FLAG=0 : initial flag + #FLAG=1 : update level + #FLAG=2 : final level + while [ $FLAG -ne 2 ] + do + UpdateThermalLevel + #echo " $i ${AFCTEMP[$i]} ${AFCTEMP_LEVEL[$i]} $FLAG $AFCTEMP_LOWER $AFCTEMP_UPPER " + done + done + + min=${AFCTEMP_LEVEL[0]} + for j in "${AFCTEMP_LEVEL[@]}"; do + (( j < min )) && min=$j + done + + if (($min == 1 || $min == 2)); then + FAN_PERCENTAGE=100 + elif (($min == 3)); then + FAN_PERCENTAGE=80 + elif (($min == 4)); then + FAN_PERCENTAGE=60 + elif (($min == 5)); then + FAN_PERCENTAGE=40 + elif (($min == 6)); then + FAN_PERCENTAGE=30 + else + FAN_PERCENTAGE=100 + fi + echo "The lowest level of thermal sensors: $min " + echo "Trying to set fan speed to $FAN_PERCENTAGE %" + #Set speed to fan1~fan10 + FAN_PERCENTAGE=`expr $FAN_PERCENTAGE \* 255 / 100` + let fcvcount=0 + for fcv in $FCFANS + do + fcvcount=$(( fcvcount + 1 )) + echo $FAN_PERCENTAGE > ${AFCFAN_TARGET[$fcvcount]} + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + + echo "FAN fan$fcvcount = ${AFCFAN[$fcvcount]} (rpm)" + done + + rm -f "$PIDFILE" +} + +# main loop calling the main function at specified intervals +AFCTEMP_LEVEL=(9 4 4 4) #inttial level +while true +do + UpdateThermalSensors + UpdateFanSpeeds + echo "Sleep $INTERVAL seconds ..." + echo + # Sleep while still handling signals + sleep $INTERVAL & + wait $! +done diff --git a/device/delta/x86_64-delta_et-6248brb-r0/installer.conf b/device/delta/x86_64-delta_et-6248brb-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/delta/x86_64-delta_et-6248brb-r0/led_proc_init.soc b/device/delta/x86_64-delta_et-6248brb-r0/led_proc_init.soc new file mode 100644 index 000000000000..ebc8f238a332 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/led_proc_init.soc @@ -0,0 +1,46 @@ +#ET_6248BRB Port_Remap +# Vlan set and port enable +clear c +port ge en=1 +port hg en=1 + +# led0 port order remap +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=0 REMAP_PORT_1=1 REMAP_PORT_2=2 REMAP_PORT_3=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=4 REMAP_PORT_5=5 REMAP_PORT_6=6 REMAP_PORT_7=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=51 REMAP_PORT_9=50 REMAP_PORT_10=49 REMAP_PORT_11=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=47 REMAP_PORT_13=46 REMAP_PORT_14=45 REMAP_PORT_15=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=43 REMAP_PORT_17=42 REMAP_PORT_18=41 REMAP_PORT_19=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=39 REMAP_PORT_21=38 REMAP_PORT_22=37 REMAP_PORT_23=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=35 REMAP_PORT_25=34 REMAP_PORT_26=33 REMAP_PORT_27=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=27 REMAP_PORT_33=26 REMAP_PORT_34=25 REMAP_PORT_35=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 REMAP_PORT_37=22 REMAP_PORT_38=21 REMAP_PORT_39=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=19 REMAP_PORT_41=18 REMAP_PORT_42=17 REMAP_PORT_43=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=15 REMAP_PORT_45=14 REMAP_PORT_46=13 REMAP_PORT_47=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=11 REMAP_PORT_49=10 REMAP_PORT_50=9 REMAP_PORT_51=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=7 REMAP_PORT_53=6 REMAP_PORT_54=5 REMAP_PORT_55=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=3 REMAP_PORT_57=2 REMAP_PORT_58=1 REMAP_PORT_59=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=60 REMAP_PORT_61=61 REMAP_PORT_62=62 REMAP_PORT_63=63 + +echo "ET_6248BRB LED Port Remap: Done." + +#ET_6248BRB_LED + +#-------------------------------------------------------------------------------------------------- +#LED Auto link/up + +led stop +led prog '\ + 02 00 60 E0 02 A0 60 E2 86 E6 02 00 60 E1 06 E0\ + D2 30 75 28 02 00 2E E0 32 08 97 71 1F 77 44 2E\ + E0 32 04 97 71 3C 77 40 02 00 2E E0 32 08 97 71\ + 33 77 44 2E E0 32 03 97 71 3C 77 40 02 02 77 44\ + 02 04 77 44 60 E3 2E E0 32 00 32 01 B7 97 02 00\ + 0E 00 12 E4 FE E1 50 12 E4 05 60 E5 12 E3 05 0A\ + 02 71 67 67 9A 77 69 67 86 12 E3 05 0A 01 71 74\ + 67 9A 77 76 67 86 06 E2 F2 01 60 E2 86 E0 06 E0\ + D2 34 74 0A 3A 68 06 E5 D2 00 70 96 16 E6 99 99\ + 1A 00 71 96 77 9A 32 0F 87 57 32 0E 87 57 00 00\ +' +led auto on +led start diff --git a/device/delta/x86_64-delta_et-6248brb-r0/plugins/eeprom.py b/device/delta/x86_64-delta_et-6248brb-r0/plugins/eeprom.py new file mode 100644 index 000000000000..11c9285f47db --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/plugins/eeprom.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# 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: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + _TLV_INFO_MAX_LEN = 256 + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/devices/pci0000:00/0000:00:13.0/i2c-1/1-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/delta/x86_64-delta_et-6248brb-r0/plugins/psuutil.py b/device/delta/x86_64-delta_et-6248brb-r0/plugins/psuutil.py new file mode 100644 index 000000000000..99e8f1d17dd8 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/plugins/psuutil.py @@ -0,0 +1,55 @@ +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/devices/platform/delta-et6248brb-gpio.0/PSU/psu{}_pg" + self.psu_oper_status = "in1_input" + self.psu_presence = "/sys/devices/platform/delta-et6248brb-gpio.0/PSU/psu{}_pres" + + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + if index is None: + return False + + try: + reg_file = open(self.psu_path.format(index)) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + if int(reg_file.readline()) == 1: + return True + + return False + + def get_psu_presence(self, index): + if index is None: + return False + + try: + reg_file = open(self.psu_presence.format(index)) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + if int(reg_file.readline()) == 0: + return True + + return False diff --git a/device/delta/x86_64-delta_et-6248brb-r0/plugins/sfputil.py b/device/delta/x86_64-delta_et-6248brb-r0/plugins/sfputil.py new file mode 100644 index 000000000000..84a3bfc3dac0 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/plugins/sfputil.py @@ -0,0 +1,96 @@ +# 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 = 48 + PORT_END = 49 + PORTS_IN_BLOCK = 1 + + EEPROM_OFFSET = 44 + + _port_to_eeprom_mapping = {} + + @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) + + @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): + if x >= self.port_start and x <= self.port_end: + self._port_to_eeprom_mapping[x] = eeprom_path.format(x - self.EEPROM_OFFSET) + else: + self._port_to_eeprom_mapping[x] = eeprom_path.format(x - x) + + 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 + + presence_path = "/sys/devices/platform/delta-et6248brb-gpio.0/SFP/sfp_mod_p{}" + + try: + reg_file = open(presence_path.format(port_num - 47)) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + if int(reg_file.readline()) == 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 + + return False + + 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 + + return False + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/delta/x86_64-delta_et-6248brb-r0/sensors.conf b/device/delta/x86_64-delta_et-6248brb-r0/sensors.conf new file mode 100644 index 000000000000..d5da19ffecd0 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/sensors.conf @@ -0,0 +1,13 @@ +# libsensors configuration file for et-6248brb +# ------------------------------------------------ + +chip "tmp75-i2c-0-48" + label temp1 "0-0048 thermal sensor" +chip "tmp75-i2c-7-49" + label temp1 "7-0048 thermal sensor" +chip "tmp75-i2c-8-4a" + label temp1 "8-004a thermal sensor" + +chip "adt7473-i2c-0-2e" + label fan1 "FANTRAY 1" + label fan2 "FANTRAY 2" \ No newline at end of file diff --git a/device/embedway/x86_64-ew_es6220_x48q2h4-r0/default_sku b/device/embedway/x86_64-ew_es6220_x48q2h4-r0/default_sku new file mode 100644 index 000000000000..0f663505d7a4 --- /dev/null +++ b/device/embedway/x86_64-ew_es6220_x48q2h4-r0/default_sku @@ -0,0 +1 @@ +OSW1800-48x6q t1 diff --git a/device/embedway/x86_64-ew_es6220_x48q2h4-r0/installer.conf b/device/embedway/x86_64-ew_es6220_x48q2h4-r0/installer.conf new file mode 100644 index 000000000000..5e62742c11bf --- /dev/null +++ b/device/embedway/x86_64-ew_es6220_x48q2h4-r0/installer.conf @@ -0,0 +1 @@ +CONSOLE_SPEED=115200 diff --git a/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/port_config.ini b/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/port_config.ini new file mode 100644 index 000000000000..973e47589aaa --- /dev/null +++ b/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 117,118,119,120 +Ethernet4 113,114,115,116 +Ethernet8 125,126,127,128 +Ethernet12 121,122,123,124 +Ethernet16 5,6,7,8 +Ethernet20 1,2,3,4 +Ethernet24 13,14,15,16 +Ethernet28 9,10,11,12 +Ethernet32 21,22,23,24 +Ethernet36 17,18,19,20 +Ethernet40 29,30,31,32 +Ethernet44 25,26,27,28 +Ethernet48 37,38,39,40 +Ethernet52 33,34,35,36 +Ethernet56 45,46,47,48 +Ethernet60 41,42,43,44 +Ethernet64 53,54,55,56 +Ethernet68 49,50,51,52 +Ethernet72 61,62,63,64 +Ethernet76 57,58,59,60 +Ethernet80 69,70,71,72 +Ethernet84 65,66,67,68 +Ethernet88 77,78,79,80 +Ethernet92 73,74,75,76 +Ethernet96 85,86,87,88 +Ethernet100 81,82,83,84 +Ethernet104 93,94,95,96 +Ethernet108 89,90,91,92 +Ethernet112 101,102,103,104 +Ethernet116 97,98,99,100 +Ethernet120 109,110,111,112 +Ethernet124 105,106,107,108 diff --git a/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/sai.profile b/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/sai.profile new file mode 100644 index 000000000000..b5586b7ba24c --- /dev/null +++ b/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-wedge100-32x100G.config.bcm diff --git a/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/th-wedge100-32x100G.config.bcm b/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/th-wedge100-32x100G.config.bcm new file mode 100644 index 000000000000..afd1db4cbc02 --- /dev/null +++ b/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/th-wedge100-32x100G.config.bcm @@ -0,0 +1,433 @@ +ctr_evict_enable=0x0 +l2_mem_entries=0x8000 +l3_intf_vlan_split_egress=0x1 +l3_mem_entries=0x4000 +mdio_output_delay=0xb +mmu_lossless=0x0 +os=unix +oversubscribe_mode=0x1 +parity_enable=0x1 +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +phy_an_c37=0x3 +phy_an_c73=0x0 +portmap_1=5:100 +portmap_102=101:100 +portmap_106=97:100 +portmap_110=109:100 +portmap_114=105:100 +portmap_118=117:100 +portmap_122=113:100 +portmap_126=125:100 +portmap_13=9:100 +portmap_130=121:100 +portmap_17=21:100 +portmap_21=17:100 +portmap_25=29:100 +portmap_29=25:100 +portmap_34=37:100 +portmap_38=33:100 +portmap_42=45:100 +portmap_46=41:100 +portmap_5=1:100 +portmap_50=53:100 +portmap_54=49:100 +portmap_58=61:100 +portmap_62=57:100 +portmap_68=69:100 +portmap_72=65:100 +portmap_76=77:100 +portmap_80=73:100 +portmap_84=85:100 +portmap_88=81:100 +portmap_9=13:100 +portmap_92=93:100 +portmap_96=89:100 +rate_ext_mdio_divisor=0x65 +serdes_automedium=0x0 +serdes_fiber_pref=0x1 +serdes_firmware_mode_xe=0x2 +serdes_preemphasis_1=0x284008 +serdes_preemphasis_10=0x284008 +serdes_preemphasis_102=0x2c4004 +serdes_preemphasis_103=0x2c4004 +serdes_preemphasis_104=0x2c4004 +serdes_preemphasis_105=0x2c4004 +serdes_preemphasis_106=0x2c4004 +serdes_preemphasis_107=0x2c4004 +serdes_preemphasis_108=0x2c4004 +serdes_preemphasis_109=0x2c4004 +serdes_preemphasis_11=0x284008 +serdes_preemphasis_110=0x303c04 +serdes_preemphasis_111=0x303c04 +serdes_preemphasis_112=0x303c04 +serdes_preemphasis_113=0x303c04 +serdes_preemphasis_114=0x303c04 +serdes_preemphasis_115=0x303c04 +serdes_preemphasis_116=0x303c04 +serdes_preemphasis_117=0x303c04 +serdes_preemphasis_118=0x2c4004 +serdes_preemphasis_119=0x2c4004 +serdes_preemphasis_12=0x284008 +serdes_preemphasis_120=0x2c4004 +serdes_preemphasis_121=0x2c4004 +serdes_preemphasis_122=0x303c04 +serdes_preemphasis_123=0x303c04 +serdes_preemphasis_124=0x303c04 +serdes_preemphasis_125=0x303c04 +serdes_preemphasis_126=0x2c4004 +serdes_preemphasis_127=0x2c4004 +serdes_preemphasis_128=0x2c4004 +serdes_preemphasis_129=0x2c4004 +serdes_preemphasis_13=0x284008 +serdes_preemphasis_130=0x2c4004 +serdes_preemphasis_131=0x2c4004 +serdes_preemphasis_132=0x2c4004 +serdes_preemphasis_133=0x2c4004 +serdes_preemphasis_14=0x284008 +serdes_preemphasis_15=0x284008 +serdes_preemphasis_16=0x284008 +serdes_preemphasis_17=0x205000 +serdes_preemphasis_18=0x205000 +serdes_preemphasis_19=0x205000 +serdes_preemphasis_2=0x284008 +serdes_preemphasis_20=0x205000 +serdes_preemphasis_21=0x284800 +serdes_preemphasis_22=0x284800 +serdes_preemphasis_23=0x284800 +serdes_preemphasis_24=0x284800 +serdes_preemphasis_25=0x205000 +serdes_preemphasis_26=0x205000 +serdes_preemphasis_27=0x205000 +serdes_preemphasis_28=0x205000 +serdes_preemphasis_29=0x205000 +serdes_preemphasis_3=0x284008 +serdes_preemphasis_30=0x205000 +serdes_preemphasis_31=0x205000 +serdes_preemphasis_32=0x205000 +serdes_preemphasis_34=0x205000 +serdes_preemphasis_35=0x205000 +serdes_preemphasis_36=0x205000 +serdes_preemphasis_37=0x205000 +serdes_preemphasis_38=0x205000 +serdes_preemphasis_39=0x205000 +serdes_preemphasis_4=0x284008 +serdes_preemphasis_40=0x205000 +serdes_preemphasis_41=0x205000 +serdes_preemphasis_42=0x205000 +serdes_preemphasis_43=0x205000 +serdes_preemphasis_44=0x205000 +serdes_preemphasis_45=0x205000 +serdes_preemphasis_46=0x205000 +serdes_preemphasis_47=0x205000 +serdes_preemphasis_48=0x205000 +serdes_preemphasis_49=0x205000 +serdes_preemphasis_5=0x284008 +serdes_preemphasis_50=0x205000 +serdes_preemphasis_51=0x205000 +serdes_preemphasis_52=0x205000 +serdes_preemphasis_53=0x205000 +serdes_preemphasis_54=0x205000 +serdes_preemphasis_55=0x205000 +serdes_preemphasis_56=0x205000 +serdes_preemphasis_57=0x205000 +serdes_preemphasis_58=0x205000 +serdes_preemphasis_59=0x205000 +serdes_preemphasis_6=0x284008 +serdes_preemphasis_60=0x205000 +serdes_preemphasis_61=0x205000 +serdes_preemphasis_62=0x205000 +serdes_preemphasis_63=0x205000 +serdes_preemphasis_64=0x205000 +serdes_preemphasis_65=0x205000 +serdes_preemphasis_68=0x205000 +serdes_preemphasis_69=0x205000 +serdes_preemphasis_7=0x284008 +serdes_preemphasis_70=0x205000 +serdes_preemphasis_71=0x205000 +serdes_preemphasis_72=0x205000 +serdes_preemphasis_73=0x205000 +serdes_preemphasis_74=0x205000 +serdes_preemphasis_75=0x205000 +serdes_preemphasis_76=0x284800 +serdes_preemphasis_77=0x284800 +serdes_preemphasis_78=0x284800 +serdes_preemphasis_79=0x284800 +serdes_preemphasis_8=0x284008 +serdes_preemphasis_80=0x205000 +serdes_preemphasis_81=0x205000 +serdes_preemphasis_82=0x205000 +serdes_preemphasis_83=0x205000 +serdes_preemphasis_84=0x284800 +serdes_preemphasis_85=0x284800 +serdes_preemphasis_86=0x284800 +serdes_preemphasis_87=0x284800 +serdes_preemphasis_88=0x284800 +serdes_preemphasis_89=0x284800 +serdes_preemphasis_9=0x284008 +serdes_preemphasis_90=0x284800 +serdes_preemphasis_91=0x284800 +serdes_preemphasis_92=0x284800 +serdes_preemphasis_93=0x284800 +serdes_preemphasis_94=0x284800 +serdes_preemphasis_95=0x284800 +serdes_preemphasis_96=0x284800 +serdes_preemphasis_97=0x284800 +serdes_preemphasis_98=0x284800 +serdes_preemphasis_99=0x284800 +stable_size=0x6000000 +xgxs_rx_lane_map_1=0x3210 +xgxs_rx_lane_map_10=0x3210 +xgxs_rx_lane_map_102=0x123 +xgxs_rx_lane_map_103=0x123 +xgxs_rx_lane_map_104=0x123 +xgxs_rx_lane_map_105=0x123 +xgxs_rx_lane_map_106=0x3210 +xgxs_rx_lane_map_107=0x3210 +xgxs_rx_lane_map_108=0x3210 +xgxs_rx_lane_map_109=0x3210 +xgxs_rx_lane_map_11=0x3210 +xgxs_rx_lane_map_110=0x1032 +xgxs_rx_lane_map_111=0x1032 +xgxs_rx_lane_map_112=0x1032 +xgxs_rx_lane_map_113=0x1032 +xgxs_rx_lane_map_114=0x3210 +xgxs_rx_lane_map_115=0x3210 +xgxs_rx_lane_map_116=0x3210 +xgxs_rx_lane_map_117=0x3210 +xgxs_rx_lane_map_118=0x2301 +xgxs_rx_lane_map_119=0x2301 +xgxs_rx_lane_map_12=0x3210 +xgxs_rx_lane_map_120=0x2301 +xgxs_rx_lane_map_121=0x2301 +xgxs_rx_lane_map_122=0x3210 +xgxs_rx_lane_map_123=0x3210 +xgxs_rx_lane_map_124=0x3210 +xgxs_rx_lane_map_125=0x3210 +xgxs_rx_lane_map_126=0x1032 +xgxs_rx_lane_map_127=0x1032 +xgxs_rx_lane_map_128=0x1032 +xgxs_rx_lane_map_129=0x1032 +xgxs_rx_lane_map_13=0x3210 +xgxs_rx_lane_map_130=0x3210 +xgxs_rx_lane_map_131=0x3210 +xgxs_rx_lane_map_132=0x3210 +xgxs_rx_lane_map_133=0x3210 +xgxs_rx_lane_map_14=0x3210 +xgxs_rx_lane_map_15=0x3210 +xgxs_rx_lane_map_16=0x3210 +xgxs_rx_lane_map_17=0x2301 +xgxs_rx_lane_map_18=0x2301 +xgxs_rx_lane_map_19=0x2301 +xgxs_rx_lane_map_2=0x3210 +xgxs_rx_lane_map_20=0x2301 +xgxs_rx_lane_map_21=0x1032 +xgxs_rx_lane_map_22=0x1032 +xgxs_rx_lane_map_23=0x1032 +xgxs_rx_lane_map_24=0x1032 +xgxs_rx_lane_map_25=0x3210 +xgxs_rx_lane_map_26=0x3210 +xgxs_rx_lane_map_27=0x3210 +xgxs_rx_lane_map_28=0x3210 +xgxs_rx_lane_map_29=0x1032 +xgxs_rx_lane_map_3=0x3210 +xgxs_rx_lane_map_30=0x1032 +xgxs_rx_lane_map_31=0x1032 +xgxs_rx_lane_map_32=0x1032 +xgxs_rx_lane_map_34=0x2301 +xgxs_rx_lane_map_35=0x2301 +xgxs_rx_lane_map_36=0x2301 +xgxs_rx_lane_map_37=0x2301 +xgxs_rx_lane_map_38=0x1032 +xgxs_rx_lane_map_39=0x1032 +xgxs_rx_lane_map_4=0x3210 +xgxs_rx_lane_map_40=0x1032 +xgxs_rx_lane_map_41=0x1032 +xgxs_rx_lane_map_42=0x3210 +xgxs_rx_lane_map_43=0x3210 +xgxs_rx_lane_map_44=0x3210 +xgxs_rx_lane_map_45=0x3210 +xgxs_rx_lane_map_46=0x1032 +xgxs_rx_lane_map_47=0x1032 +xgxs_rx_lane_map_48=0x1032 +xgxs_rx_lane_map_49=0x1032 +xgxs_rx_lane_map_5=0x3210 +xgxs_rx_lane_map_50=0x1032 +xgxs_rx_lane_map_51=0x1032 +xgxs_rx_lane_map_52=0x1032 +xgxs_rx_lane_map_53=0x1032 +xgxs_rx_lane_map_54=0x1032 +xgxs_rx_lane_map_55=0x1032 +xgxs_rx_lane_map_56=0x1032 +xgxs_rx_lane_map_57=0x1032 +xgxs_rx_lane_map_58=0x1032 +xgxs_rx_lane_map_59=0x1032 +xgxs_rx_lane_map_6=0x3210 +xgxs_rx_lane_map_60=0x1032 +xgxs_rx_lane_map_61=0x1032 +xgxs_rx_lane_map_62=0x1032 +xgxs_rx_lane_map_63=0x1032 +xgxs_rx_lane_map_64=0x1032 +xgxs_rx_lane_map_65=0x1032 +xgxs_rx_lane_map_68=0x1032 +xgxs_rx_lane_map_69=0x1032 +xgxs_rx_lane_map_7=0x3210 +xgxs_rx_lane_map_70=0x1032 +xgxs_rx_lane_map_71=0x1032 +xgxs_rx_lane_map_72=0x3210 +xgxs_rx_lane_map_73=0x3210 +xgxs_rx_lane_map_74=0x3210 +xgxs_rx_lane_map_75=0x3210 +xgxs_rx_lane_map_76=0x213 +xgxs_rx_lane_map_77=0x213 +xgxs_rx_lane_map_78=0x213 +xgxs_rx_lane_map_79=0x213 +xgxs_rx_lane_map_8=0x3210 +xgxs_rx_lane_map_80=0x1032 +xgxs_rx_lane_map_81=0x1032 +xgxs_rx_lane_map_82=0x1032 +xgxs_rx_lane_map_83=0x1032 +xgxs_rx_lane_map_84=0x123 +xgxs_rx_lane_map_85=0x123 +xgxs_rx_lane_map_86=0x123 +xgxs_rx_lane_map_87=0x123 +xgxs_rx_lane_map_88=0x3210 +xgxs_rx_lane_map_89=0x3210 +xgxs_rx_lane_map_9=0x3210 +xgxs_rx_lane_map_90=0x3210 +xgxs_rx_lane_map_91=0x3210 +xgxs_rx_lane_map_92=0x1032 +xgxs_rx_lane_map_93=0x1032 +xgxs_rx_lane_map_94=0x1032 +xgxs_rx_lane_map_95=0x1032 +xgxs_rx_lane_map_96=0x3210 +xgxs_rx_lane_map_97=0x3210 +xgxs_rx_lane_map_98=0x3210 +xgxs_rx_lane_map_99=0x3210 +xgxs_tx_lane_map_1=0x3210 +xgxs_tx_lane_map_10=0x3210 +xgxs_tx_lane_map_102=0x3210 +xgxs_tx_lane_map_103=0x3210 +xgxs_tx_lane_map_104=0x3210 +xgxs_tx_lane_map_105=0x3210 +xgxs_tx_lane_map_106=0x1032 +xgxs_tx_lane_map_107=0x1032 +xgxs_tx_lane_map_108=0x1032 +xgxs_tx_lane_map_109=0x1032 +xgxs_tx_lane_map_11=0x3210 +xgxs_tx_lane_map_110=0x3210 +xgxs_tx_lane_map_111=0x3210 +xgxs_tx_lane_map_112=0x3210 +xgxs_tx_lane_map_113=0x3210 +xgxs_tx_lane_map_114=0x1032 +xgxs_tx_lane_map_115=0x1032 +xgxs_tx_lane_map_116=0x1032 +xgxs_tx_lane_map_117=0x1032 +xgxs_tx_lane_map_118=0x3210 +xgxs_tx_lane_map_119=0x3210 +xgxs_tx_lane_map_12=0x3210 +xgxs_tx_lane_map_120=0x3210 +xgxs_tx_lane_map_121=0x3210 +xgxs_tx_lane_map_122=0x1032 +xgxs_tx_lane_map_123=0x1032 +xgxs_tx_lane_map_124=0x1032 +xgxs_tx_lane_map_125=0x1032 +xgxs_tx_lane_map_126=0x1032 +xgxs_tx_lane_map_127=0x1032 +xgxs_tx_lane_map_128=0x1032 +xgxs_tx_lane_map_129=0x1032 +xgxs_tx_lane_map_13=0x3210 +xgxs_tx_lane_map_130=0x3210 +xgxs_tx_lane_map_131=0x3210 +xgxs_tx_lane_map_132=0x3210 +xgxs_tx_lane_map_133=0x3210 +xgxs_tx_lane_map_14=0x3210 +xgxs_tx_lane_map_15=0x3210 +xgxs_tx_lane_map_16=0x3210 +xgxs_tx_lane_map_17=0x1032 +xgxs_tx_lane_map_18=0x1032 +xgxs_tx_lane_map_19=0x1032 +xgxs_tx_lane_map_2=0x3210 +xgxs_tx_lane_map_20=0x1032 +xgxs_tx_lane_map_21=0x3210 +xgxs_tx_lane_map_22=0x3210 +xgxs_tx_lane_map_23=0x3210 +xgxs_tx_lane_map_24=0x3210 +xgxs_tx_lane_map_25=0x1032 +xgxs_tx_lane_map_26=0x1032 +xgxs_tx_lane_map_27=0x1032 +xgxs_tx_lane_map_28=0x1032 +xgxs_tx_lane_map_29=0x3210 +xgxs_tx_lane_map_3=0x3210 +xgxs_tx_lane_map_30=0x3210 +xgxs_tx_lane_map_31=0x3210 +xgxs_tx_lane_map_32=0x3210 +xgxs_tx_lane_map_34=0x1032 +xgxs_tx_lane_map_35=0x1032 +xgxs_tx_lane_map_36=0x1032 +xgxs_tx_lane_map_37=0x1032 +xgxs_tx_lane_map_38=0x3210 +xgxs_tx_lane_map_39=0x3210 +xgxs_tx_lane_map_4=0x3210 +xgxs_tx_lane_map_40=0x3210 +xgxs_tx_lane_map_41=0x3210 +xgxs_tx_lane_map_42=0x1032 +xgxs_tx_lane_map_43=0x1032 +xgxs_tx_lane_map_44=0x1032 +xgxs_tx_lane_map_45=0x1032 +xgxs_tx_lane_map_46=0x3210 +xgxs_tx_lane_map_47=0x3210 +xgxs_tx_lane_map_48=0x3210 +xgxs_tx_lane_map_49=0x3210 +xgxs_tx_lane_map_5=0x3210 +xgxs_tx_lane_map_50=0x1032 +xgxs_tx_lane_map_51=0x1032 +xgxs_tx_lane_map_52=0x1032 +xgxs_tx_lane_map_53=0x1032 +xgxs_tx_lane_map_54=0x1032 +xgxs_tx_lane_map_55=0x1032 +xgxs_tx_lane_map_56=0x1032 +xgxs_tx_lane_map_57=0x1032 +xgxs_tx_lane_map_58=0x1032 +xgxs_tx_lane_map_59=0x1032 +xgxs_tx_lane_map_6=0x3210 +xgxs_tx_lane_map_60=0x1032 +xgxs_tx_lane_map_61=0x1032 +xgxs_tx_lane_map_62=0x1032 +xgxs_tx_lane_map_63=0x1032 +xgxs_tx_lane_map_64=0x1032 +xgxs_tx_lane_map_65=0x1032 +xgxs_tx_lane_map_68=0x1032 +xgxs_tx_lane_map_69=0x1032 +xgxs_tx_lane_map_7=0x3210 +xgxs_tx_lane_map_70=0x1032 +xgxs_tx_lane_map_71=0x1032 +xgxs_tx_lane_map_72=0x3210 +xgxs_tx_lane_map_73=0x3210 +xgxs_tx_lane_map_74=0x3210 +xgxs_tx_lane_map_75=0x3210 +xgxs_tx_lane_map_76=0x3210 +xgxs_tx_lane_map_77=0x3210 +xgxs_tx_lane_map_78=0x3210 +xgxs_tx_lane_map_79=0x3210 +xgxs_tx_lane_map_8=0x3210 +xgxs_tx_lane_map_80=0x1032 +xgxs_tx_lane_map_81=0x1032 +xgxs_tx_lane_map_82=0x1032 +xgxs_tx_lane_map_83=0x1032 +xgxs_tx_lane_map_84=0x3210 +xgxs_tx_lane_map_85=0x3210 +xgxs_tx_lane_map_86=0x3210 +xgxs_tx_lane_map_87=0x3210 +xgxs_tx_lane_map_88=0x1032 +xgxs_tx_lane_map_89=0x1032 +xgxs_tx_lane_map_9=0x3210 +xgxs_tx_lane_map_90=0x1032 +xgxs_tx_lane_map_91=0x1032 +xgxs_tx_lane_map_92=0x3210 +xgxs_tx_lane_map_93=0x3210 +xgxs_tx_lane_map_94=0x3210 +xgxs_tx_lane_map_95=0x3210 +xgxs_tx_lane_map_96=0x1032 +xgxs_tx_lane_map_97=0x1032 +xgxs_tx_lane_map_98=0x1032 +xgxs_tx_lane_map_99=0x1032 diff --git a/device/facebook/x86_64-facebook_wedge100-r0/default_sku b/device/facebook/x86_64-facebook_wedge100-r0/default_sku new file mode 100644 index 000000000000..e8fafcb709da --- /dev/null +++ b/device/facebook/x86_64-facebook_wedge100-r0/default_sku @@ -0,0 +1 @@ +Facebook-W100-C32 t1 diff --git a/device/facebook/x86_64-facebook_wedge100-r0/installer.conf b/device/facebook/x86_64-facebook_wedge100-r0/installer.conf new file mode 100644 index 000000000000..3714ff053bb0 --- /dev/null +++ b/device/facebook/x86_64-facebook_wedge100-r0/installer.conf @@ -0,0 +1 @@ +CONSOLE_SPEED=57600 diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/port_config.ini b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/port_config.ini new file mode 100644 index 000000000000..bf87e1402ab1 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 37,38,39,40 Ethernet1/1 0 +Ethernet4 33,34,35,36 Ethernet2/1 1 +Ethernet8 45,46,47,48 Ethernet3/1 2 +Ethernet12 41,42,43,44 Ethernet4/1 3 +Ethernet16 53,54,55,56 Ethernet5/1 4 +Ethernet20 49,50,51,52 Ethernet6/1 5 +Ethernet24 61,62,63,64 Ethernet7/1 6 +Ethernet28 57,58,59,60 Ethernet8/1 7 +Ethernet32 69,70,71,72 Ethernet9/1 8 +Ethernet36 65,66,67,68 Ethernet10/1 9 +Ethernet40 77,78,79,80 Ethernet11/1 10 +Ethernet44 73,74,75,76 Ethernet12/1 11 +Ethernet48 85,86,87,88 Ethernet13/1 12 +Ethernet52 81,82,83,84 Ethernet14/1 13 +Ethernet56 93,94,95,96 Ethernet15/1 14 +Ethernet60 89,90,91,92 Ethernet16/1 15 +Ethernet64 101,102,103,104 Ethernet17/1 16 +Ethernet68 97,98,99,100 Ethernet18/1 17 +Ethernet72 109,110,111,112 Ethernet19/1 18 +Ethernet76 105,106,107,108 Ethernet20/1 19 +Ethernet80 117,118,119,120 Ethernet21/1 20 +Ethernet84 113,114,115,116 Ethernet22/1 21 +Ethernet88 125,126,127,128 Ethernet23/1 22 +Ethernet92 121,122,123,124 Ethernet24/1 23 +Ethernet96 5,6,7,8 Ethernet25/1 24 +Ethernet100 1,2,3,4 Ethernet26/1 25 +Ethernet104 13,14,15,16 Ethernet27/1 26 +Ethernet108 9,10,11,12 Ethernet28/1 27 +Ethernet112 21,22,23,24 Ethernet29/1 28 +Ethernet116 17,18,19,20 Ethernet30/1 29 +Ethernet120 29,30,31,32 Ethernet31/1 30 +Ethernet124 25,26,27,28 Ethernet32/1 31 diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/sai.profile b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/sai.profile new file mode 100644 index 000000000000..42315ee4ea6a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-s8810-32x40G.config.bcm diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/td2-s8810-32x40G.config.bcm b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/td2-s8810-32x40G.config.bcm new file mode 100644 index 000000000000..894f60345a73 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/td2-s8810-32x40G.config.bcm @@ -0,0 +1,473 @@ +#2017/09/12 +os=unix + +module_64ports=0 +schan_intr_enable=0 +stable_size=0x2000000 + +pbmp_xport_xe=0x000007fffffffffffffffffffffffffe +pbmp_oversubscribe=0x000007fffffffffffffffffffffffffe + +# ALPM enable +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l2_mem_entries=32768 +l3_mem_entries=16384 + +l2xmsg_mode=1 +mmu_lossless=0 + +#Parity +parity_correction=1 +parity_enable=1 + +portmap_1=37:40 +portmap_2=33:40 +portmap_3=45:40 +portmap_4=41:40 +portmap_5=53:40 +portmap_6=49:40 +portmap_7=61:40 +portmap_8=57:40 +portmap_9=69:40 +portmap_10=65:40 +portmap_11=77:40 +portmap_12=73:40 +portmap_13=85:40 +portmap_14=81:40 +portmap_15=93:40 +portmap_16=89:40 +portmap_17=101:40 +portmap_18=97:40 +portmap_19=109:40 +portmap_20=105:40 +portmap_21=117:40 +portmap_22=113:40 +portmap_23=125:40 +portmap_24=121:40 +portmap_25=5:40 +portmap_26=1:40 +portmap_27=13:40 +portmap_28=9:40 +portmap_29=21:40 +portmap_30=17:40 +portmap_31=29:40 +portmap_32=25:40 + +serdes_driver_current_lane0_xe0=0x6 +serdes_driver_current_lane1_xe0=0x6 +serdes_driver_current_lane2_xe0=0x6 +serdes_driver_current_lane3_xe0=0x7 +serdes_pre_driver_current_lane0_xe0=0x6 +serdes_pre_driver_current_lane1_xe0=0x6 +serdes_pre_driver_current_lane2_xe0=0x6 +serdes_pre_driver_current_lane3_xe0=0x7 +serdes_preemphasis_lane0_xe0=0xc2f0 +serdes_preemphasis_lane1_xe0=0xcf20 +serdes_preemphasis_lane2_xe0=0xc2f0 +serdes_preemphasis_lane3_xe0=0xc2f0 + +serdes_driver_current_lane0_xe1=0x8 +serdes_driver_current_lane1_xe1=0x8 +serdes_driver_current_lane2_xe1=0x8 +serdes_driver_current_lane3_xe1=0x8 +serdes_pre_driver_current_lane0_xe1=0x8 +serdes_pre_driver_current_lane1_xe1=0x8 +serdes_pre_driver_current_lane2_xe1=0x8 +serdes_pre_driver_current_lane3_xe1=0x8 +serdes_preemphasis_lane0_xe1=0xc6e0 +serdes_preemphasis_lane1_xe1=0xc6e0 +serdes_preemphasis_lane2_xe1=0xc6e0 +serdes_preemphasis_lane3_xe1=0xc6e0 + +serdes_driver_current_lane0_xe2=0x5 +serdes_driver_current_lane1_xe2=0x3 +serdes_driver_current_lane2_xe2=0x3 +serdes_driver_current_lane3_xe2=0x3 +serdes_pre_driver_current_lane0_xe2=0x5 +serdes_pre_driver_current_lane1_xe2=0x3 +serdes_pre_driver_current_lane2_xe2=0x3 +serdes_pre_driver_current_lane3_xe2=0x3 +serdes_preemphasis_lane0_xe2=0x9b90 +serdes_preemphasis_lane1_xe2=0x9f80 +serdes_preemphasis_lane2_xe2=0x9b90 +serdes_preemphasis_lane3_xe2=0x9b90 + +serdes_driver_current_lane0_xe3=0x5 +serdes_driver_current_lane1_xe3=0x5 +serdes_driver_current_lane2_xe3=0x5 +serdes_driver_current_lane3_xe3=0x5 +serdes_pre_driver_current_lane0_xe3=0x5 +serdes_pre_driver_current_lane1_xe3=0x5 +serdes_pre_driver_current_lane2_xe3=0x5 +serdes_pre_driver_current_lane3_xe3=0x5 +serdes_preemphasis_lane0_xe3=0x9b90 +serdes_preemphasis_lane1_xe3=0x9b90 +serdes_preemphasis_lane2_xe3=0x9b90 +serdes_preemphasis_lane3_xe3=0x9b90 + +serdes_driver_current_lane0_xe4=0x3 +serdes_driver_current_lane1_xe4=0x3 +serdes_driver_current_lane2_xe4=0x3 +serdes_driver_current_lane3_xe4=0x3 +serdes_pre_driver_current_lane0_xe4=0x3 +serdes_pre_driver_current_lane1_xe4=0x3 +serdes_pre_driver_current_lane2_xe4=0x3 +serdes_pre_driver_current_lane3_xe4=0x3 +serdes_preemphasis_lane0_xe4=0x93b0 +serdes_preemphasis_lane1_xe4=0x97a0 +serdes_preemphasis_lane2_xe4=0x9b90 +serdes_preemphasis_lane3_xe4=0x9b90 + +serdes_driver_current_lane0_xe5=0x3 +serdes_driver_current_lane1_xe5=0x3 +serdes_driver_current_lane2_xe5=0x3 +serdes_driver_current_lane3_xe5=0x3 +serdes_pre_driver_current_lane0_xe5=0x3 +serdes_pre_driver_current_lane1_xe5=0x3 +serdes_pre_driver_current_lane2_xe5=0x3 +serdes_pre_driver_current_lane3_xe5=0x3 +serdes_preemphasis_lane0_xe5=0x9b90 +serdes_preemphasis_lane1_xe5=0x9b90 +serdes_preemphasis_lane2_xe5=0x9b90 +serdes_preemphasis_lane3_xe5=0x9b90 + +serdes_driver_current_lane0_xe6=0x1 +serdes_driver_current_lane1_xe6=0x1 +serdes_driver_current_lane2_xe6=0x1 +serdes_driver_current_lane3_xe6=0x1 +serdes_pre_driver_current_lane0_xe6=0x1 +serdes_pre_driver_current_lane1_xe6=0x1 +serdes_pre_driver_current_lane2_xe6=0x1 +serdes_pre_driver_current_lane3_xe6=0x1 +serdes_preemphasis_lane0_xe6=0xa760 +serdes_preemphasis_lane1_xe6=0xc2f0 +serdes_preemphasis_lane2_xe6=0xa760 +serdes_preemphasis_lane3_xe6=0xa760 + +serdes_driver_current_lane0_xe7=0x1 +serdes_driver_current_lane1_xe7=0x1 +serdes_driver_current_lane2_xe7=0x1 +serdes_driver_current_lane3_xe7=0x1 +serdes_pre_driver_current_lane0_xe7=0x0 +serdes_pre_driver_current_lane1_xe7=0x0 +serdes_pre_driver_current_lane2_xe7=0x0 +serdes_pre_driver_current_lane3_xe7=0x0 +serdes_preemphasis_lane0_xe7=0xa760 +serdes_preemphasis_lane1_xe7=0xa760 +serdes_preemphasis_lane2_xe7=0xa760 +serdes_preemphasis_lane3_xe7=0xa760 + +serdes_driver_current_lane0_xe8=0x1 +serdes_driver_current_lane1_xe8=0x1 +serdes_driver_current_lane2_xe8=0x1 +serdes_driver_current_lane3_xe8=0x0 +serdes_pre_driver_current_lane0_xe8=0x0 +serdes_pre_driver_current_lane1_xe8=0x0 +serdes_pre_driver_current_lane2_xe8=0x0 +serdes_pre_driver_current_lane3_xe8=0x0 +serdes_preemphasis_lane0_xe8=0xa760 +serdes_preemphasis_lane1_xe8=0xa760 +serdes_preemphasis_lane2_xe8=0xa760 +serdes_preemphasis_lane3_xe8=0xa760 + +serdes_driver_current_lane0_xe9=0x1 +serdes_driver_current_lane1_xe9=0x1 +serdes_driver_current_lane2_xe9=0x1 +serdes_driver_current_lane3_xe9=0x1 +serdes_pre_driver_current_lane0_xe9=0x0 +serdes_pre_driver_current_lane1_xe9=0x0 +serdes_pre_driver_current_lane2_xe9=0x0 +serdes_pre_driver_current_lane3_xe9=0x0 +serdes_preemphasis_lane0_xe9=0xa760 +serdes_preemphasis_lane1_xe9=0xa760 +serdes_preemphasis_lane2_xe9=0xa760 +serdes_preemphasis_lane3_xe9=0xa760 + +serdes_driver_current_lane0_xe10=0x1 +serdes_driver_current_lane1_xe10=0x1 +serdes_driver_current_lane2_xe10=0x1 +serdes_driver_current_lane3_xe10=0x1 +serdes_pre_driver_current_lane0_xe10=0x0 +serdes_pre_driver_current_lane1_xe10=0x0 +serdes_pre_driver_current_lane2_xe10=0x0 +serdes_pre_driver_current_lane3_xe10=0x0 +serdes_preemphasis_lane0_xe10=0xa760 +serdes_preemphasis_lane1_xe10=0xa760 +serdes_preemphasis_lane2_xe10=0xa760 +serdes_preemphasis_lane3_xe10=0xa760 + +serdes_driver_current_lane0_xe11=0x1 +serdes_driver_current_lane1_xe11=0x1 +serdes_driver_current_lane2_xe11=0x1 +serdes_driver_current_lane3_xe11=0x1 +serdes_pre_driver_current_lane0_xe11=0x1 +serdes_pre_driver_current_lane1_xe11=0x0 +serdes_pre_driver_current_lane2_xe11=0x1 +serdes_pre_driver_current_lane3_xe11=0x0 +serdes_preemphasis_lane0_xe11=0xa760 +serdes_preemphasis_lane1_xe11=0xa760 +serdes_preemphasis_lane2_xe11=0xa760 +serdes_preemphasis_lane3_xe11=0xa760 + +serdes_driver_current_lane0_xe12=0x1 +serdes_driver_current_lane1_xe12=0x1 +serdes_driver_current_lane2_xe12=0x1 +serdes_driver_current_lane3_xe12=0x1 +serdes_pre_driver_current_lane0_xe12=0x0 +serdes_pre_driver_current_lane1_xe12=0x0 +serdes_pre_driver_current_lane2_xe12=0x0 +serdes_pre_driver_current_lane3_xe12=0x0 +serdes_preemphasis_lane0_xe12=0xa760 +serdes_preemphasis_lane1_xe12=0xa760 +serdes_preemphasis_lane2_xe12=0xa760 +serdes_preemphasis_lane3_xe12=0xa760 + +serdes_driver_current_lane0_xe13=0x1 +serdes_driver_current_lane1_xe13=0x1 +serdes_driver_current_lane2_xe13=0x1 +serdes_driver_current_lane3_xe13=0x1 +serdes_pre_driver_current_lane0_xe13=0x1 +serdes_pre_driver_current_lane1_xe13=0x1 +serdes_pre_driver_current_lane2_xe13=0x1 +serdes_pre_driver_current_lane3_xe13=0x0 +serdes_preemphasis_lane0_xe13=0xa760 +serdes_preemphasis_lane1_xe13=0xa760 +serdes_preemphasis_lane2_xe13=0xa760 +serdes_preemphasis_lane3_xe13=0xa760 + +serdes_driver_current_lane0_xe14=0x3 +serdes_driver_current_lane1_xe14=0x3 +serdes_driver_current_lane2_xe14=0x3 +serdes_driver_current_lane3_xe14=0x3 +serdes_pre_driver_current_lane0_xe14=0x3 +serdes_pre_driver_current_lane1_xe14=0x3 +serdes_pre_driver_current_lane2_xe14=0x3 +serdes_pre_driver_current_lane3_xe14=0x3 +serdes_preemphasis_lane0_xe14=0xaf40 +serdes_preemphasis_lane1_xe14=0xab50 +serdes_preemphasis_lane2_xe14=0xaf40 +serdes_preemphasis_lane3_xe14=0xaf40 + +serdes_driver_current_lane0_xe15=0x3 +serdes_driver_current_lane1_xe15=0x3 +serdes_driver_current_lane2_xe15=0x3 +serdes_driver_current_lane3_xe15=0x3 +serdes_pre_driver_current_lane0_xe15=0x3 +serdes_pre_driver_current_lane1_xe15=0x3 +serdes_pre_driver_current_lane2_xe15=0x3 +serdes_pre_driver_current_lane3_xe15=0x3 +serdes_preemphasis_lane0_xe15=0xaf40 +serdes_preemphasis_lane1_xe15=0xaf40 +serdes_preemphasis_lane2_xe15=0xab50 +serdes_preemphasis_lane3_xe15=0xab50 + +serdes_driver_current_lane0_xe16=0x0 +serdes_driver_current_lane1_xe16=0x1 +serdes_driver_current_lane2_xe16=0x1 +serdes_driver_current_lane3_xe16=0x1 +serdes_pre_driver_current_lane0_xe16=0x0 +serdes_pre_driver_current_lane1_xe16=0x1 +serdes_pre_driver_current_lane2_xe16=0x1 +serdes_pre_driver_current_lane3_xe16=0x1 +serdes_preemphasis_lane0_xe16=0xa760 +serdes_preemphasis_lane1_xe16=0xa760 +serdes_preemphasis_lane2_xe16=0xa760 +serdes_preemphasis_lane3_xe16=0xa760 + +serdes_driver_current_lane0_xe17=0x1 +serdes_driver_current_lane1_xe17=0x0 +serdes_driver_current_lane2_xe17=0x1 +serdes_driver_current_lane3_xe17=0x1 +serdes_pre_driver_current_lane0_xe17=0x1 +serdes_pre_driver_current_lane1_xe17=0x0 +serdes_pre_driver_current_lane2_xe17=0x1 +serdes_pre_driver_current_lane3_xe17=0x1 +serdes_preemphasis_lane0_xe17=0xa760 +serdes_preemphasis_lane1_xe17=0x9b90 +serdes_preemphasis_lane2_xe17=0xa760 +serdes_preemphasis_lane3_xe17=0xa760 + +serdes_driver_current_lane0_xe18=0x1 +serdes_driver_current_lane1_xe18=0x1 +serdes_driver_current_lane2_xe18=0x1 +serdes_driver_current_lane3_xe18=0x1 +serdes_pre_driver_current_lane0_xe18=0x1 +serdes_pre_driver_current_lane1_xe18=0x1 +serdes_pre_driver_current_lane2_xe18=0x1 +serdes_pre_driver_current_lane3_xe18=0x1 +serdes_preemphasis_lane0_xe18=0xa760 +serdes_preemphasis_lane1_xe18=0xa760 +serdes_preemphasis_lane2_xe18=0xa760 +serdes_preemphasis_lane3_xe18=0xa760 + +serdes_driver_current_lane0_xe19=0x1 +serdes_driver_current_lane1_xe19=0x1 +serdes_driver_current_lane2_xe19=0x1 +serdes_driver_current_lane3_xe19=0x1 +serdes_pre_driver_current_lane0_xe19=0x1 +serdes_pre_driver_current_lane1_xe19=0x1 +serdes_pre_driver_current_lane2_xe19=0x0 +serdes_pre_driver_current_lane3_xe19=0x1 +serdes_preemphasis_lane0_xe19=0xa760 +serdes_preemphasis_lane1_xe19=0xa760 +serdes_preemphasis_lane2_xe19=0xa760 +serdes_preemphasis_lane3_xe19=0xa760 + +serdes_driver_current_lane0_xe20=0x1 +serdes_driver_current_lane1_xe20=0x2 +serdes_driver_current_lane2_xe20=0x1 +serdes_driver_current_lane3_xe20=0x1 +serdes_pre_driver_current_lane0_xe20=0x0 +serdes_pre_driver_current_lane1_xe20=0x2 +serdes_pre_driver_current_lane2_xe20=0x1 +serdes_pre_driver_current_lane3_xe20=0x1 +serdes_preemphasis_lane0_xe20=0xa760 +serdes_preemphasis_lane1_xe20=0xa670 +serdes_preemphasis_lane2_xe20=0xa760 +serdes_preemphasis_lane3_xe20=0xa760 + +serdes_driver_current_lane0_xe21=0x1 +serdes_driver_current_lane1_xe21=0x1 +serdes_driver_current_lane2_xe21=0x0 +serdes_driver_current_lane3_xe21=0x1 +serdes_pre_driver_current_lane0_xe21=0x0 +serdes_pre_driver_current_lane1_xe21=0x1 +serdes_pre_driver_current_lane2_xe21=0x0 +serdes_pre_driver_current_lane3_xe21=0x1 +serdes_preemphasis_lane0_xe21=0xa760 +serdes_preemphasis_lane1_xe21=0xa670 +serdes_preemphasis_lane2_xe21=0xa760 +serdes_preemphasis_lane3_xe21=0xa760 + +serdes_driver_current_lane0_xe22=0x1 +serdes_driver_current_lane1_xe22=0x4 +serdes_driver_current_lane2_xe22=0x2 +serdes_driver_current_lane3_xe22=0x2 +serdes_pre_driver_current_lane0_xe22=0x1 +serdes_pre_driver_current_lane1_xe22=0x4 +serdes_pre_driver_current_lane2_xe22=0x2 +serdes_pre_driver_current_lane3_xe22=0x2 +serdes_preemphasis_lane0_xe22=0xa760 +serdes_preemphasis_lane1_xe22=0x97a0 +serdes_preemphasis_lane2_xe22=0xa670 +serdes_preemphasis_lane3_xe22=0xa760 + +serdes_driver_current_lane0_xe23=0x3 +serdes_driver_current_lane1_xe23=0x3 +serdes_driver_current_lane2_xe23=0x1 +serdes_driver_current_lane3_xe23=0x1 +serdes_pre_driver_current_lane0_xe23=0x3 +serdes_pre_driver_current_lane1_xe23=0x3 +serdes_pre_driver_current_lane2_xe23=0x1 +serdes_pre_driver_current_lane3_xe23=0x1 +serdes_preemphasis_lane0_xe23=0xa760 +serdes_preemphasis_lane1_xe23=0x9b90 +serdes_preemphasis_lane2_xe23=0xab50 +serdes_preemphasis_lane3_xe23=0xa760 + +serdes_driver_current_lane0_xe24=0x1 +serdes_driver_current_lane1_xe24=0x4 +serdes_driver_current_lane2_xe24=0x4 +serdes_driver_current_lane3_xe24=0x3 +serdes_pre_driver_current_lane0_xe24=0x1 +serdes_pre_driver_current_lane1_xe24=0x4 +serdes_pre_driver_current_lane2_xe24=0x4 +serdes_pre_driver_current_lane3_xe24=0x3 +serdes_preemphasis_lane0_xe24=0xa760 +serdes_preemphasis_lane1_xe24=0x93b0 +serdes_preemphasis_lane2_xe24=0x9b90 +serdes_preemphasis_lane3_xe24=0xa760 + +serdes_driver_current_lane0_xe25=0x4 +serdes_driver_current_lane1_xe25=0x3 +serdes_driver_current_lane2_xe25=0x3 +serdes_driver_current_lane3_xe25=0x1 +serdes_pre_driver_current_lane0_xe25=0x4 +serdes_pre_driver_current_lane1_xe25=0x3 +serdes_pre_driver_current_lane2_xe25=0x3 +serdes_pre_driver_current_lane3_xe25=0x1 +serdes_preemphasis_lane0_xe25=0x93b0 +serdes_preemphasis_lane1_xe25=0x9b90 +serdes_preemphasis_lane2_xe25=0x9b90 +serdes_preemphasis_lane3_xe25=0xa760 + +serdes_driver_current_lane0_xe26=0x4 +serdes_driver_current_lane1_xe26=0x4 +serdes_driver_current_lane2_xe26=0x4 +serdes_driver_current_lane3_xe26=0x4 +serdes_pre_driver_current_lane0_xe26=0x4 +serdes_pre_driver_current_lane1_xe26=0x4 +serdes_pre_driver_current_lane2_xe26=0x4 +serdes_pre_driver_current_lane3_xe26=0x4 +serdes_preemphasis_lane0_xe26=0x9b90 +serdes_preemphasis_lane1_xe26=0x97a0 +serdes_preemphasis_lane2_xe26=0x9b90 +serdes_preemphasis_lane3_xe26=0x97a0 + +serdes_driver_current_lane0_xe27=0x4 +serdes_driver_current_lane1_xe27=0x3 +serdes_driver_current_lane2_xe27=0x3 +serdes_driver_current_lane3_xe27=0x3 +serdes_pre_driver_current_lane0_xe27=0x4 +serdes_pre_driver_current_lane1_xe27=0x3 +serdes_pre_driver_current_lane2_xe27=0x3 +serdes_pre_driver_current_lane3_xe27=0x3 +serdes_preemphasis_lane0_xe27=0x9b90 +serdes_preemphasis_lane1_xe27=0x9b90 +serdes_preemphasis_lane2_xe27=0x9b90 +serdes_preemphasis_lane3_xe27=0x9b90 + +serdes_driver_current_lane0_xe28=0x5 +serdes_driver_current_lane1_xe28=0x5 +serdes_driver_current_lane2_xe28=0x6 +serdes_driver_current_lane3_xe28=0x6 +serdes_pre_driver_current_lane0_xe28=0x5 +serdes_pre_driver_current_lane1_xe28=0x5 +serdes_pre_driver_current_lane2_xe28=0x6 +serdes_pre_driver_current_lane3_xe28=0x6 +serdes_preemphasis_lane0_xe28=0xbf00 +serdes_preemphasis_lane1_xe28=0xbf00 +serdes_preemphasis_lane2_xe28=0xbf00 +serdes_preemphasis_lane3_xe28=0xbf00 + +serdes_driver_current_lane0_xe29=0x7 +serdes_driver_current_lane1_xe29=0x6 +serdes_driver_current_lane2_xe29=0x6 +serdes_driver_current_lane3_xe29=0x6 +serdes_pre_driver_current_lane0_xe29=0x7 +serdes_pre_driver_current_lane1_xe29=0x6 +serdes_pre_driver_current_lane2_xe29=0x6 +serdes_pre_driver_current_lane3_xe29=0x6 +serdes_preemphasis_lane0_xe29=0xbb10 +serdes_preemphasis_lane1_xe29=0xbb10 +serdes_preemphasis_lane2_xe29=0xbb10 +serdes_preemphasis_lane3_xe29=0xbb10 + +serdes_driver_current_lane0_xe30=0x7 +serdes_driver_current_lane1_xe30=0x7 +serdes_driver_current_lane2_xe30=0x7 +serdes_driver_current_lane3_xe30=0x7 +serdes_pre_driver_current_lane0_xe30=0x7 +serdes_pre_driver_current_lane1_xe30=0x7 +serdes_pre_driver_current_lane2_xe30=0x7 +serdes_pre_driver_current_lane3_xe30=0x7 +serdes_preemphasis_lane0_xe30=0xc2f0 +serdes_preemphasis_lane1_xe30=0xc2f0 +serdes_preemphasis_lane2_xe30=0xc2f0 +serdes_preemphasis_lane3_xe30=0xc2f0 + +serdes_driver_current_lane0_xe31=0x7 +serdes_driver_current_lane1_xe31=0x7 +serdes_driver_current_lane2_xe31=0x7 +serdes_driver_current_lane3_xe31=0x7 +serdes_pre_driver_current_lane0_xe31=0x7 +serdes_pre_driver_current_lane1_xe31=0x7 +serdes_pre_driver_current_lane2_xe31=0x7 +serdes_pre_driver_current_lane3_xe31=0x7 +serdes_preemphasis_lane0_xe31=0xc2f0 +serdes_preemphasis_lane1_xe31=0xc2f0 +serdes_preemphasis_lane2_xe31=0xc2f0 +serdes_preemphasis_lane3_xe31=0xc2f0 + +serdes_if_type_xe=14 diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/default_sku new file mode 100644 index 000000000000..fe68cd87d182 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S8810-32Q t1 diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/fancontrol new file mode 100644 index 000000000000..8c378371a9a2 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/fancontrol @@ -0,0 +1,11 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/0-002f +DEVNAME=hwmon1=w83795adg +FCTEMPS=hwmon1/device/pwm2=hwmon1/device/temp2_input hwmon1/device/pwm1=hwmon1/device/temp2_input +FCFANS=hwmon1/device/pwm2=hwmon1/device/fan8_input hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan6_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm1=hwmon1/device/fan4_input hwmon1/device/pwm1=hwmon1/device/fan3_input hwmon1/device/pwm1=hwmon1/device/fan2_input hwmon1/device/pwm1=hwmon1/device/fan1_input +MINTEMP=hwmon1/device/pwm2=20 hwmon1/device/pwm1=20 +MAXTEMP=hwmon1/device/pwm2=60 hwmon1/device/pwm1=60 +MINSTART=hwmon1/device/pwm2=75 hwmon1/device/pwm1=75 +MINSTOP=hwmon1/device/pwm2=22 hwmon1/device/pwm1=22 + diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/led_proc_init.soc b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/led_proc_init.soc new file mode 100644 index 000000000000..8c1a18f6236b --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/led_proc_init.soc @@ -0,0 +1,45 @@ +#processor initialization for Ingrasys S8810-32Q + +led 0 stop +led 0 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=48 REMAP_PORT_2=49 REMAP_PORT_1=50 REMAP_PORT_0=51 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=52 REMAP_PORT_6=53 REMAP_PORT_5=54 REMAP_PORT_4=55 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 REMAP_PORT_10=57 REMAP_PORT_9=58 REMAP_PORT_8=59 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 REMAP_PORT_14=61 REMAP_PORT_13=62 REMAP_PORT_12=63 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=44 REMAP_PORT_18=45 REMAP_PORT_17=46 REMAP_PORT_16=47 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=40 REMAP_PORT_22=41 REMAP_PORT_21=42 REMAP_PORT_20=43 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 REMAP_PORT_26=37 REMAP_PORT_25=38 REMAP_PORT_24=39 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 REMAP_PORT_30=33 REMAP_PORT_29=34 REMAP_PORT_28=35 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 REMAP_PORT_34=17 REMAP_PORT_33=18 REMAP_PORT_32=19 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 REMAP_PORT_38=21 REMAP_PORT_37=22 REMAP_PORT_36=23 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=24 REMAP_PORT_42=25 REMAP_PORT_41=26 REMAP_PORT_40=27 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=28 REMAP_PORT_46=29 REMAP_PORT_45=30 REMAP_PORT_44=31 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=12 REMAP_PORT_50=13 REMAP_PORT_49=14 REMAP_PORT_48=15 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=8 REMAP_PORT_54=9 REMAP_PORT_53=10 REMAP_PORT_52=11 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 REMAP_PORT_58=5 REMAP_PORT_57=6 REMAP_PORT_56=7 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 REMAP_PORT_62=1 REMAP_PORT_61=2 REMAP_PORT_60=3 + +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=48 REMAP_PORT_2=49 REMAP_PORT_1=50 REMAP_PORT_0=51 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=52 REMAP_PORT_6=53 REMAP_PORT_5=54 REMAP_PORT_4=55 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 REMAP_PORT_10=57 REMAP_PORT_9=58 REMAP_PORT_8=59 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 REMAP_PORT_14=61 REMAP_PORT_13=62 REMAP_PORT_12=63 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=44 REMAP_PORT_18=45 REMAP_PORT_17=46 REMAP_PORT_16=47 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=40 REMAP_PORT_22=41 REMAP_PORT_21=42 REMAP_PORT_20=43 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 REMAP_PORT_26=37 REMAP_PORT_25=38 REMAP_PORT_24=39 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 REMAP_PORT_30=33 REMAP_PORT_29=34 REMAP_PORT_28=35 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 REMAP_PORT_34=17 REMAP_PORT_33=18 REMAP_PORT_32=19 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 REMAP_PORT_38=21 REMAP_PORT_37=22 REMAP_PORT_36=23 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=24 REMAP_PORT_42=25 REMAP_PORT_41=26 REMAP_PORT_40=27 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=28 REMAP_PORT_46=29 REMAP_PORT_45=30 REMAP_PORT_44=31 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=12 REMAP_PORT_50=13 REMAP_PORT_49=14 REMAP_PORT_48=15 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=8 REMAP_PORT_54=9 REMAP_PORT_53=10 REMAP_PORT_52=11 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 REMAP_PORT_58=5 REMAP_PORT_57=6 REMAP_PORT_56=7 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 REMAP_PORT_62=1 REMAP_PORT_61=2 REMAP_PORT_60=3 + +led 1 auto on +led 1 start diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/eeprom.py new file mode 100644 index 000000000000..4f919ccd7273 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +############################################################################# +# Ingrasys S8810-32Q +# +# 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): + i2c_bus = "12" + i2c_addr = "0056" + self.eeprom_path = "/sys/class/i2c-adapter/i2c-" + i2c_bus + "/" + i2c_bus + "-" + i2c_addr + "/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/psuutil.py new file mode 100644 index 000000000000..7e69360b0402 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/psuutil.py @@ -0,0 +1,92 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/i2c-3/3-0051", + "/sys/bus/i2c/devices/i2c-4/4-0051"] + + def __init__(self): + PsuBase.__init__(self) + + + # Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + attr_file = 'psu_pg' + attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU status + if (attr_value == 1): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_absent = 0 + attr_file ='psu_abs' + attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU presence + if (attr_value == 0): + status = 1 + + return status + diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/sfputil.py new file mode 100644 index 000000000000..8d195f644e18 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/sfputil.py @@ -0,0 +1,183 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +import os + +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 = 31 + PORTS_IN_BLOCK = 32 + + EEPROM_OFFSET = 18 + + ABS_GPIO_BASE = 224 + #INT_GPIO_BASE = 192 + LP_GPIO_BASE = 160 + RST_GPIO_BASE = 128 + GPIO_OFFSET = 0 + + BASE_DIR_PATH = "/sys/class/gpio/gpio{0}/direction" + BASE_VAL_PATH = "/sys/class/gpio/gpio{0}/value" + + _port_to_eeprom_mapping = {} + + @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 port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def set_gpio_offset(self): + sys_gpio_dir = "/sys/class/gpio" + self.GPIO_OFFSET = 0 + gpiochip_no = 0 + for d in os.listdir(sys_gpio_dir): + if "gpiochip" in d: + try: + gpiochip_no = int(d[8:],10) + except ValueError as e: + print "Error: %s" % str(e) + if gpiochip_no > 255: + self.GPIO_OFFSET=256 + return True + return True + + def update_gpio_base(self): + self.ABS_GPIO_BASE = 224 + self.GPIO_OFFSET + self.LP_GPIO_BASE = 160 + self.GPIO_OFFSET + self.RST_GPIO_BASE = 128 + self.GPIO_OFFSET + return True + + def __init__(self): + # Update abs, lpmode, and reset gpio base + self.set_gpio_offset() + self.update_gpio_base() + + # 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): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET) + + 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: + abs_device_file = self.BASE_VAL_PATH.format( + port_num + self.ABS_GPIO_BASE) + val_file = open(abs_device_file) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + + # content is a string, either "0" or "1" + if content == "1": + 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: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + port_num + self.LP_GPIO_BASE) + val_file = open(lpmode_val_device_file) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + 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: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + port_num + self.LP_GPIO_BASE) + val_file = open(lpmode_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("1" if lpmode is True else "0") + val_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 + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + port_num + self.RST_GPIO_BASE) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("1") + val_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + port_num + self.RST_GPIO_BASE) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("0") + val_file.close() + + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/sensors.conf new file mode 100644 index 000000000000..8332fbdf9086 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/sensors.conf @@ -0,0 +1,47 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + label temp1 "DIMM Temp" + set temp1_max 50 + set temp1_crit 85 + +chip "w83795adg-*" + label in0 "ROV" + set in0_min 1.025 * 0.98 + set in0_max 1.025 * 1.02 + ignore in1 + ignore in2 + label in3 "1.0V" + set in3_min 1 * 0.97 + set in3_max 1 * 1.03 + label in4 "1.8V" + set in4_min 1.8 * 0.95 + set in4_max 1.8 * 1.05 + ignore in5 + label in6 "5.0V" + compute in6 (4)*@, @/(4) + set in6_min 5 * 0.95 + set in6_max 5 * 1.05 + ignore in7 + label in12 "3.3V" + compute in6 (2)*@, @/(2) + set in12_min 3.3 * 0.97 + set in12_max 3.3 * 1.03 + ignore in14 + ignore in15 + ignore in16 + label fan1 "FANTRAY 1-A" + label fan2 "FANTRAY 1-B" + label fan3 "FANTRAY 2-A" + label fan4 "FANTRAY 2-B" + label fan5 "FANTRAY 3-A" + label fan6 "FANTRAY 3-B" + label fan7 "FANTRAY 4-A" + label fan8 "FANTRAY 4-B" + label temp1 "MAC Temp" + label temp2 "SFP+ Port 1 Temp" + label temp3 "SFP+ Port 8 Temp" + ignore temp4 + ignore intrusion0 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/port_config.ini b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/port_config.ini new file mode 100644 index 000000000000..079bb63455f2 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias index +Ethernet0 1 Ethernet1/1 0 +Ethernet1 2 Ethernet2/1 1 +Ethernet2 3 Ethernet3/1 2 +Ethernet3 4 Ethernet4/1 3 +Ethernet4 5 Ethernet5/1 4 +Ethernet5 6 Ethernet6/1 5 +Ethernet6 7 Ethernet7/1 6 +Ethernet7 8 Ethernet8/1 7 +Ethernet8 9 Ethernet9/1 8 +Ethernet9 10 Ethernet10/1 9 +Ethernet10 11 Ethernet11/1 10 +Ethernet11 12 Ethernet12/1 11 +Ethernet12 21 Ethernet13/1 12 +Ethernet13 22 Ethernet14/1 13 +Ethernet14 23 Ethernet15/1 14 +Ethernet15 24 Ethernet16/1 15 +Ethernet16 33 Ethernet17/1 16 +Ethernet17 34 Ethernet18/1 17 +Ethernet18 35 Ethernet19/1 18 +Ethernet19 36 Ethernet20/1 19 +Ethernet20 37 Ethernet21/1 20 +Ethernet21 38 Ethernet22/1 21 +Ethernet22 39 Ethernet23/1 22 +Ethernet23 40 Ethernet24/1 23 +Ethernet24 41 Ethernet25/1 24 +Ethernet25 42 Ethernet26/1 25 +Ethernet26 43 Ethernet27/1 26 +Ethernet27 44 Ethernet28/1 27 +Ethernet28 49 Ethernet29/1 28 +Ethernet29 50 Ethernet30/1 29 +Ethernet30 51 Ethernet31/1 30 +Ethernet31 52 Ethernet32/1 31 +Ethernet32 53 Ethernet33/1 32 +Ethernet33 54 Ethernet34/1 33 +Ethernet34 55 Ethernet35/1 34 +Ethernet35 56 Ethernet36/1 35 +Ethernet36 65 Ethernet37/1 36 +Ethernet37 66 Ethernet38/1 37 +Ethernet38 67 Ethernet39/1 38 +Ethernet39 68 Ethernet40/1 39 +Ethernet40 69 Ethernet41/1 40 +Ethernet41 70 Ethernet42/1 41 +Ethernet42 71 Ethernet43/1 42 +Ethernet43 72 Ethernet44/1 43 +Ethernet44 81 Ethernet45/1 44 +Ethernet45 82 Ethernet46/1 45 +Ethernet46 83 Ethernet47/1 46 +Ethernet47 84 Ethernet48/1 47 +Ethernet48 85,86,87,88 Ethernet52/1 48 +Ethernet52 97,98,99,100 Ethernet56/1 49 +Ethernet56 101,102,103,104 Ethernet60/1 50 +Ethernet60 105,106,107,108 Ethernet64/1 51 +Ethernet64 109,110,111,112 Ethernet68/1 52 +Ethernet68 117,118,119,120 Ethernet69/1 53 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/sai.profile b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/sai.profile new file mode 100644 index 000000000000..29db3ecd1624 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-s8900-48x25G+6x100G.config.bcm diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/th-s8900-48x25G+6x100G.config.bcm b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/th-s8900-48x25G+6x100G.config.bcm new file mode 100644 index 000000000000..4485a77af2d6 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/th-s8900-48x25G+6x100G.config.bcm @@ -0,0 +1,340 @@ +#2018/03/31 + +os=unix + +oversubscribe_mode=1 +pbmp_xport_xe=0x7f00001fff4003ffffc0001fffe + +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l3_mem_entries=40960 +l2_mem_entries=40960 + +l2xmsg_mode=1 +mmu_lossless=0 + +#Parity +parity_correction=1 +parity_enable=1 + +#PIPE0 +portmap_1=1:25 +portmap_2=2:25 +portmap_3=3:25 +portmap_4=4:25 +portmap_5=5:25 +portmap_6=6:25 +portmap_7=7:25 +portmap_8=8:25 +portmap_9=9:25 +portmap_10=10:25 +portmap_11=11:25 +portmap_12=12:25 +portmap_13=21:25 +portmap_14=22:25 +portmap_15=23:25 +portmap_16=24:25 + +#PIPE1 +portmap_34=33:25 +portmap_35=34:25 +portmap_36=35:25 +portmap_37=36:25 +portmap_38=37:25 +portmap_39=38:25 +portmap_40=39:25 +portmap_41=40:25 +portmap_42=41:25 +portmap_43=42:25 +portmap_44=43:25 +portmap_45=44:25 +portmap_46=49:25 +portmap_47=50:25 +portmap_48=51:25 +portmap_49=52:25 +portmap_50=53:25 +portmap_51=54:25 +portmap_52=55:25 +portmap_53=56:25 + +#PIPE2 +portmap_68=65:25 +portmap_69=66:25 +portmap_70=67:25 +portmap_71=68:25 +portmap_72=69:25 +portmap_73=70:25 +portmap_74=71:25 +portmap_75=72:25 +portmap_76=81:25 +portmap_77=82:25 +portmap_78=83:25 +portmap_79=84:25 +portmap_80=85:100 + +#PIPE3 +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_106=117:100 + + +portmap_66=129:10 +portmap_100=131:10 +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +serdes_driver_current_xe0=0xF +serdes_preemphasis_xe0=0x3E3200 +serdes_if_type_xe0=14 + +serdes_driver_current_xe1=0xF +serdes_preemphasis_xe1=0x3A3600 +serdes_if_type_xe1=14 + +serdes_driver_current_xe2=0xF +serdes_preemphasis_xe2=0x3A3600 +serdes_if_type_xe2=14 + +serdes_driver_current_xe3=0xF +serdes_preemphasis_xe3=0x383800 +serdes_if_type_xe3=14 + +serdes_driver_current_xe4=0xF +serdes_preemphasis_xe4=0x373900 +serdes_if_type_xe4=14 + +serdes_driver_current_xe5=0xF +serdes_preemphasis_xe5=0x2E4200 +serdes_if_type_xe5=14 + +serdes_driver_current_xe6=0xF +serdes_preemphasis_xe6=0x333D00 +serdes_if_type_xe6=14 + +serdes_driver_current_xe7=0xC +serdes_preemphasis_xe7=0x304000 +serdes_if_type_xe7=14 + +serdes_driver_current_xe8=0xE +serdes_preemphasis_xe8=0x2F4300 +serdes_if_type_xe8=14 + +serdes_driver_current_xe9=0xC +serdes_preemphasis_xe9=0x2D4300 +serdes_if_type_xe9=14 + +serdes_driver_current_xe10=0xC +serdes_preemphasis_xe10=0x2C4400 +serdes_if_type_xe10=14 + +serdes_driver_current_xe11=0xC +serdes_preemphasis_xe11=0x2D4300 +serdes_if_type_xe11=14 + +serdes_driver_current_xe12=0xC +serdes_preemphasis_xe12=0x294700 +serdes_if_type_xe12=14 + +serdes_driver_current_xe13=0xC +serdes_preemphasis_xe13=0x284800 +serdes_if_type_xe13=14 + +serdes_driver_current_xe14=0xA +serdes_preemphasis_xe14=0x294700 +serdes_if_type_xe14=14 + +serdes_driver_current_xe15=0xF +serdes_preemphasis_xe15=0x294700 +serdes_if_type_xe15=14 + +serdes_driver_current_xe16=0x9 +serdes_preemphasis_xe16=0x185800 +serdes_if_type_xe16=14 + +serdes_driver_current_xe17=0x9 +serdes_preemphasis_xe17=0x1D5300 +serdes_if_type_xe17=14 + +serdes_driver_current_xe18=0x9 +serdes_preemphasis_xe18=0x1C5400 +serdes_if_type_xe18=14 + +serdes_driver_current_xe19=0x9 +serdes_preemphasis_xe19=0x1C5400 +serdes_if_type_xe19=14 + +serdes_driver_current_xe20=0x9 +serdes_preemphasis_xe20=0x1C5400 +serdes_if_type_xe20=14 + +serdes_driver_current_xe21=0x9 +serdes_preemphasis_xe21=0x1C5400 +serdes_if_type_xe21=14 + +serdes_driver_current_xe22=0x9 +serdes_preemphasis_xe22=0x1C5400 +serdes_if_type_xe22=14 + +serdes_driver_current_xe23=0x9 +serdes_preemphasis_xe23=0x1C5400 +serdes_if_type_xe23=14 + +serdes_driver_current_xe24=0x8 +serdes_preemphasis_xe24=0x1C5400 +serdes_if_type_xe24=14 + +serdes_driver_current_xe25=0x8 +serdes_preemphasis_xe25=0x1C5400 +serdes_if_type_xe25=14 + +serdes_driver_current_xe26=0x8 +serdes_preemphasis_xe26=0x185800 +serdes_if_type_xe26=14 + +serdes_driver_current_xe27=0x8 +serdes_preemphasis_xe27=0x185800 +serdes_if_type_xe27=14 + +serdes_driver_current_xe28=0x8 +serdes_preemphasis_xe28=0x145C00 +serdes_if_type_xe28=14 + +serdes_driver_current_xe29=0x8 +serdes_preemphasis_xe29=0x195700 +serdes_if_type_xe29=14 + +serdes_driver_current_xe30=0x8 +serdes_preemphasis_xe30=0x195700 +serdes_if_type_xe30=14 + +serdes_driver_current_xe31=0x8 +serdes_preemphasis_xe31=0x195700 +serdes_if_type_xe31=14 + +serdes_driver_current_xe32=0xC +serdes_preemphasis_xe32=0x195700 +serdes_if_type_xe32=14 + +serdes_driver_current_xe33=0x9 +serdes_preemphasis_xe33=0x205000 +serdes_if_type_xe33=14 + +serdes_driver_current_xe34=0xC +serdes_preemphasis_xe34=0x214F00 +serdes_if_type_xe34=14 + +serdes_driver_current_xe35=0xC +serdes_preemphasis_xe35=0x244C00 +serdes_if_type_xe35=14 + +serdes_driver_current_xe36=0xC +serdes_preemphasis_xe36=0x244C00 +serdes_if_type_xe36=14 + +serdes_driver_current_xe37=0xC +serdes_preemphasis_xe37=0x244C00 +serdes_if_type_xe37=14 + +serdes_driver_current_xe38=0xC +serdes_preemphasis_xe38=0x244C00 +serdes_if_type_xe38=14 + +serdes_driver_current_xe39=0xC +serdes_preemphasis_xe39=0x244C00 +serdes_if_type_xe39=14 + +serdes_driver_current_xe40=0xD +serdes_preemphasis_xe40=0x284800 +serdes_if_type_xe40=14 + +serdes_driver_current_xe41=0xC +serdes_preemphasis_xe41=0x284800 +serdes_if_type_xe41=14 + +serdes_driver_current_xe42=0xE +serdes_preemphasis_xe42=0x294700 +serdes_if_type_xe42=14 + +serdes_driver_current_xe43=0xE +serdes_preemphasis_xe43=0x294700 +serdes_if_type_xe43=14 + +serdes_driver_current_xe44=0xE +serdes_preemphasis_xe44=0x294700 +serdes_if_type_xe44=14 + +serdes_driver_current_xe45=0xF +serdes_preemphasis_xe45=0x284800 +serdes_if_type_xe45=14 + +serdes_driver_current_xe46=0xF +serdes_preemphasis_xe46=0x284800 +serdes_if_type_xe46=14 + +serdes_driver_current_xe47=0xF +serdes_preemphasis_xe47=0x304000 +serdes_if_type_xe47=14 + +serdes_driver_current_lane0_ce0=0xC +serdes_driver_current_lane1_ce0=0xC +serdes_driver_current_lane2_ce0=0xF +serdes_driver_current_lane3_ce0=0xC +serdes_preemphasis_lane0_ce0=0x284800 +serdes_preemphasis_lane1_ce0=0x294100 +serdes_preemphasis_lane2_ce0=0x294100 +serdes_preemphasis_lane3_ce0=0x294100 +serdes_if_type_ce0=14 + +serdes_driver_current_lane0_ce1=0xC +serdes_driver_current_lane1_ce1=0xF +serdes_driver_current_lane2_ce1=0xC +serdes_driver_current_lane3_ce1=0xC +serdes_preemphasis_lane0_ce1=0x284200 +serdes_preemphasis_lane1_ce1=0x3A3600 +serdes_preemphasis_lane2_ce1=0x2C4400 +serdes_preemphasis_lane3_ce1=0x2C4400 +serdes_if_type_ce1=14 + +serdes_driver_current_lane0_ce2=0xC +serdes_driver_current_lane1_ce2=0xC +serdes_driver_current_lane2_ce2=0xC +serdes_driver_current_lane3_ce2=0xC +serdes_preemphasis_lane0_ce2=0x2F4100 +serdes_preemphasis_lane1_ce2=0x383800 +serdes_preemphasis_lane2_ce2=0x2F4100 +serdes_preemphasis_lane3_ce2=0x304000 +serdes_if_type_ce2=14 + +serdes_driver_current_lane0_ce3=0xC +serdes_driver_current_lane1_ce3=0xF +serdes_driver_current_lane2_ce3=0xC +serdes_driver_current_lane3_ce3=0xA +serdes_preemphasis_lane0_ce3=0x304000 +serdes_preemphasis_lane1_ce3=0x3F3100 +serdes_preemphasis_lane2_ce3=0x313F00 +serdes_preemphasis_lane3_ce3=0x304000 +serdes_if_type_ce3=14 + +serdes_driver_current_lane0_ce4=0xC +serdes_driver_current_lane1_ce4=0xF +serdes_driver_current_lane2_ce4=0xC +serdes_driver_current_lane3_ce4=0xC +serdes_preemphasis_lane0_ce4=0x304000 +serdes_preemphasis_lane1_ce4=0x313F00 +serdes_preemphasis_lane2_ce4=0x2F4100 +serdes_preemphasis_lane3_ce4=0x2E4200 +serdes_if_type_ce4=14 + +serdes_driver_current_lane0_ce5=0xE +serdes_driver_current_lane1_ce5=0xF +serdes_driver_current_lane2_ce5=0xF +serdes_driver_current_lane3_ce5=0xF +serdes_preemphasis_lane0_ce5=0x304000 +serdes_preemphasis_lane1_ce5=0x3F3100 +serdes_preemphasis_lane2_ce5=0x383800 +serdes_preemphasis_lane3_ce5=0x3F3100 +serdes_if_type_ce5=14 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/default_sku new file mode 100644 index 000000000000..ba80569555d1 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S8900-54XC t1 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/fancontrol new file mode 100644 index 000000000000..e1f88f6b79c5 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/fancontrol @@ -0,0 +1,10 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/0-002f +DEVNAME=hwmon1=w83795adg +FCTEMPS=hwmon1/device/pwm2=hwmon1/device/temp2_input hwmon1/device/pwm1=hwmon1/device/temp2_input +FCFANS=hwmon1/device/pwm2=hwmon1/device/fan8_input hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan6_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm1=hwmon1/device/fan4_input hwmon1/device/pwm1=hwmon1/device/fan3_input hwmon1/device/pwm1=hwmon1/device/fan2_input hwmon1/device/pwm1=hwmon1/device/fan1_input +MINTEMP=hwmon1/device/pwm2=20 hwmon1/device/pwm1=20 +MAXTEMP=hwmon1/device/pwm2=60 hwmon1/device/pwm1=60 +MINSTART=hwmon1/device/pwm2=75 hwmon1/device/pwm1=75 +MINSTOP=hwmon1/device/pwm2=22 hwmon1/device/pwm1=22 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/led_proc_init.soc b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/led_proc_init.soc new file mode 100644 index 000000000000..8eef1389abc8 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/led_proc_init.soc @@ -0,0 +1,43 @@ +# LED microprocessor initialization for Ingrasys S8900-54XC + +led 0 stop +led 0 prog 12 00 61 F1 12 10 61 F2 12 01 61 F3 12 01 61 F4 67 28 12 10 61 F1 12 05 61 F2 12 04 61 F3 12 04 61 F4 67 28 86 F0 77 86 96 F2 2E F1 67 3D 67 51 16 F3 FE F1 61 F1 12 00 DE F2 74 28 57 2E F1 32 00 32 01 B7 97 75 4C 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 6A 77 5A 06 FE D2 01 70 62 77 78 06 F0 C2 08 74 6A 77 78 16 F4 91 22 0E 87 22 0E 87 DA 00 74 6C 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 7A 57 02 48 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=36 REMAP_PORT_2=37 REMAP_PORT_1=38 REMAP_PORT_0=39 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=40 REMAP_PORT_6=41 REMAP_PORT_5=42 REMAP_PORT_4=43 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=12 REMAP_PORT_10=13 REMAP_PORT_9=14 REMAP_PORT_8=15 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=44 REMAP_PORT_14=45 REMAP_PORT_13=46 REMAP_PORT_12=47 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=48 REMAP_PORT_18=49 REMAP_PORT_17=50 REMAP_PORT_16=51 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=8 REMAP_PORT_22=9 REMAP_PORT_21=10 REMAP_PORT_20=11 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=4 REMAP_PORT_26=5 REMAP_PORT_25=6 REMAP_PORT_24=7 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0 REMAP_PORT_30=1 REMAP_PORT_29=2 REMAP_PORT_28=3 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=52 REMAP_PORT_34=53 REMAP_PORT_33=54 REMAP_PORT_32=55 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=56 REMAP_PORT_38=57 REMAP_PORT_37=58 REMAP_PORT_36=59 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=32 REMAP_PORT_42=33 REMAP_PORT_41=34 REMAP_PORT_40=35 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=59 REMAP_PORT_46=60 REMAP_PORT_45=61 REMAP_PORT_44=62 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=28 REMAP_PORT_50=29 REMAP_PORT_49=30 REMAP_PORT_48=31 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=24 REMAP_PORT_54=25 REMAP_PORT_53=26 REMAP_PORT_52=27 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=20 REMAP_PORT_58=21 REMAP_PORT_57=22 REMAP_PORT_56=23 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=16 REMAP_PORT_62=17 REMAP_PORT_61=18 REMAP_PORT_60=19 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 12 00 61 F1 12 20 61 F2 12 01 61 F3 12 01 61 F4 67 28 12 20 61 F1 12 01 61 F2 12 04 61 F3 12 04 61 F4 67 28 86 F0 77 86 96 F2 2E F1 67 3D 67 51 16 F3 FE F1 61 F1 12 00 DE F2 74 28 57 2E F1 32 00 32 01 B7 97 75 4C 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 6A 77 5A 06 FE D2 01 70 62 77 78 06 F0 C2 08 74 6A 77 78 16 F4 91 22 0E 87 22 0E 87 DA 00 74 6C 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 7A 57 02 48 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=8 REMAP_PORT_10=9 REMAP_PORT_9=10 REMAP_PORT_8=11 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=36 REMAP_PORT_14=37 REMAP_PORT_13=38 REMAP_PORT_12=39 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=12 REMAP_PORT_18=13 REMAP_PORT_17=14 REMAP_PORT_16=15 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=16 REMAP_PORT_22=17 REMAP_PORT_21=18 REMAP_PORT_20=19 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=40 REMAP_PORT_26=41 REMAP_PORT_25=42 REMAP_PORT_24=43 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=44 REMAP_PORT_30=45 REMAP_PORT_29=46 REMAP_PORT_28=47 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=20 REMAP_PORT_34=21 REMAP_PORT_33=22 REMAP_PORT_32=23 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=24 REMAP_PORT_38=25 REMAP_PORT_37=26 REMAP_PORT_36=27 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=48 REMAP_PORT_42=49 REMAP_PORT_41=50 REMAP_PORT_40=51 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=52 REMAP_PORT_46=53 REMAP_PORT_45=54 REMAP_PORT_44=55 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=28 REMAP_PORT_50=29 REMAP_PORT_49=30 REMAP_PORT_48=31 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=32 REMAP_PORT_54=33 REMAP_PORT_53=34 REMAP_PORT_52=35 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=56 REMAP_PORT_58=57 REMAP_PORT_57=58 REMAP_PORT_56=59 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=60 REMAP_PORT_62=61 REMAP_PORT_61=62 REMAP_PORT_60=63 +led 1 auto on +led 1 start diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/eeprom.py new file mode 100644 index 000000000000..414ff38221bf --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Dell Z9100 +# +# 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-17/17-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/psuutil.py new file mode 100644 index 000000000000..4f226c69fff3 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/psuutil.py @@ -0,0 +1,92 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_CPLD_DIR = "/sys/bus/i2c/devices/0-0033" + + def __init__(self): + PsuBase.__init__(self) + + + # Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + mask = [ 0x08, 0x10 ] + attr_file = 'cpld_pw_good' + attr_path = self.PSU_CPLD_DIR +'/'+ attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU status + if (attr_value & mask[index-1]): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + mask = [ 0x01, 0x02 ] + attr_file ='cpld_pw_abs' + attr_path = self.PSU_CPLD_DIR +'/'+ attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU presence + if (~attr_value & mask[index-1]): + status = 1 + + return status + diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/sfputil.py new file mode 100644 index 000000000000..586e6e189743 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/sfputil.py @@ -0,0 +1,321 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +import os + +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 + QSFP_PORT_START = 48 + PORTS_IN_BLOCK = 54 + GPIO_OFFSET = 0 + + BASE_DIR_PATH = "/sys/class/gpio/gpio{0}/direction" + BASE_VAL_PATH = "/sys/class/gpio/gpio{0}/value" + + _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: 30, + 13: 31, + 14: 32, + 15: 33, + 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, + 32: 50, + 33: 51, + 34: 52, + 35: 53, + 36: 54, + 37: 55, + 38: 56, + 39: 57, + 40: 58, + 41: 59, + 42: 60, + 43: 61, + 44: 62, + 45: 63, + 46: 64, + 47: 65, + 48: 66, + 49: 67, + 50: 68, + 51: 69, + 52: 70, + 53: 71 + } + + abs_to_gpio_mapping = {} + lpmode_to_gpio_mapping = {} + reset_to_gpio_mapping = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def port_end(self): + return self.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 set_gpio_offset(self): + sys_gpio_dir = "/sys/class/gpio" + self.GPIO_OFFSET = 0 + gpiochip_no = 0 + for d in os.listdir(sys_gpio_dir): + if "gpiochip" in d: + try: + gpiochip_no = int(d[8:],10) + except ValueError as e: + print "Error: %s" % str(e) + if gpiochip_no > 255: + self.GPIO_OFFSET=256 + return True + return True + + def init_abs_to_gpio_mapping(self): + self.abs_to_gpio_mapping = { + 0: 192+self.GPIO_OFFSET, + 1: 193+self.GPIO_OFFSET, + 2: 194+self.GPIO_OFFSET, + 3: 195+self.GPIO_OFFSET, + 4: 196+self.GPIO_OFFSET, + 5: 197+self.GPIO_OFFSET, + 6: 198+self.GPIO_OFFSET, + 7: 199+self.GPIO_OFFSET, + 8: 200+self.GPIO_OFFSET, + 9: 201+self.GPIO_OFFSET, + 10: 202+self.GPIO_OFFSET, + 11: 203+self.GPIO_OFFSET, + 12: 204+self.GPIO_OFFSET, + 13: 205+self.GPIO_OFFSET, + 14: 206+self.GPIO_OFFSET, + 15: 207+self.GPIO_OFFSET, + 16: 176+self.GPIO_OFFSET, + 17: 177+self.GPIO_OFFSET, + 18: 178+self.GPIO_OFFSET, + 19: 179+self.GPIO_OFFSET, + 20: 180+self.GPIO_OFFSET, + 21: 181+self.GPIO_OFFSET, + 22: 182+self.GPIO_OFFSET, + 23: 183+self.GPIO_OFFSET, + 24: 184+self.GPIO_OFFSET, + 25: 185+self.GPIO_OFFSET, + 26: 186+self.GPIO_OFFSET, + 27: 187+self.GPIO_OFFSET, + 28: 188+self.GPIO_OFFSET, + 29: 189+self.GPIO_OFFSET, + 30: 190+self.GPIO_OFFSET, + 31: 191+self.GPIO_OFFSET, + 32: 160+self.GPIO_OFFSET, + 33: 161+self.GPIO_OFFSET, + 34: 162+self.GPIO_OFFSET, + 35: 163+self.GPIO_OFFSET, + 36: 164+self.GPIO_OFFSET, + 37: 165+self.GPIO_OFFSET, + 38: 166+self.GPIO_OFFSET, + 39: 167+self.GPIO_OFFSET, + 40: 168+self.GPIO_OFFSET, + 41: 169+self.GPIO_OFFSET, + 42: 170+self.GPIO_OFFSET, + 43: 171+self.GPIO_OFFSET, + 44: 172+self.GPIO_OFFSET, + 45: 173+self.GPIO_OFFSET, + 46: 174+self.GPIO_OFFSET, + 47: 175+self.GPIO_OFFSET, + 48: 240+self.GPIO_OFFSET, + 49: 241+self.GPIO_OFFSET, + 50: 242+self.GPIO_OFFSET, + 51: 243+self.GPIO_OFFSET, + 52: 244+self.GPIO_OFFSET, + 53: 245+self.GPIO_OFFSET + } + return True + + def init_lpmode_to_gpio_mapping(self): + self.lpmode_to_gpio_mapping = { + 48: 224+self.GPIO_OFFSET, + 49: 225+self.GPIO_OFFSET, + 50: 226+self.GPIO_OFFSET, + 51: 227+self.GPIO_OFFSET, + 52: 228+self.GPIO_OFFSET, + 53: 229+self.GPIO_OFFSET + } + return True + + def init_reset_to_gpio_mapping(self): + self.reset_to_gpio_mapping = { + 48: 208+self.GPIO_OFFSET, + 49: 209+self.GPIO_OFFSET, + 50: 210+self.GPIO_OFFSET, + 51: 211+self.GPIO_OFFSET, + 52: 212+self.GPIO_OFFSET, + 53: 213+self.GPIO_OFFSET + } + return True + + def __init__(self): + # Init abs, lpmode, and reset to gpio mapping + self.set_gpio_offset() + self.init_abs_to_gpio_mapping() + self.init_lpmode_to_gpio_mapping() + self.init_reset_to_gpio_mapping() + + # 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): + 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: + abs_device_file = self.BASE_VAL_PATH.format( + self.abs_to_gpio_mapping[port_num]) + val_file = open(abs_device_file) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.port_end: + return False + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.port_end: + return False + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("1" if lpmode is True else "0") + val_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.port_end: + print "Error: unable to reset non-QSFP module: port %s" % str(port_num) + return False + + try: + print "port %s" % str(port_num) + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("1") + val_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("0") + val_file.close() + + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/sensors.conf new file mode 100644 index 000000000000..88a474a06742 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/sensors.conf @@ -0,0 +1,39 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + label temp1 "DIMM Temp" + set temp1_max 50 + set temp1_crit 85 + +chip "w83795adg-*" + label in0 "1.0V" + label in1 "1.0V_ROV" + label in2 "1.25V" + label in3 "1.8V" + ignore in4 + ignore in5 + ignore in6 + ignore in7 + label in12 "+3.3V" + ignore in14 + ignore in15 + ignore in16 + label fan1 "FANTRAY 1-A" + label fan2 "FANTRAY 1-B" + label fan3 "FANTRAY 2-A" + label fan4 "FANTRAY 2-B" + label fan5 "FANTRAY 3-A" + label fan6 "FANTRAY 3-B" + label fan7 "FANTRAY 4-A" + label fan8 "FANTRAY 4-B" + label temp1 "Front MAC Temp" + set temp1_max 70 + set temp1_crit 80 + label temp2 "Rear MAC Temp" + set temp1_max 70 + set temp1_crit 80 + ignore temp3 + ignore temp4 + ignore intrusion0 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/port_config.ini b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/port_config.ini new file mode 100644 index 000000000000..385056e6e8f0 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index +Ethernet0 17 Ethernet1/1 0 +Ethernet1 18 Ethernet2/1 1 +Ethernet2 19 Ethernet3/1 2 +Ethernet3 20 Ethernet4/1 3 +Ethernet4 24 Ethernet5/1 4 +Ethernet5 23 Ethernet6/1 5 +Ethernet6 22 Ethernet7/1 6 +Ethernet7 21 Ethernet8/1 7 +Ethernet8 28 Ethernet9/1 8 +Ethernet9 27 Ethernet10/1 9 +Ethernet10 26 Ethernet11/1 10 +Ethernet11 25 Ethernet12/1 11 +Ethernet12 32 Ethernet13/1 12 +Ethernet13 31 Ethernet14/1 13 +Ethernet14 30 Ethernet15/1 14 +Ethernet15 29 Ethernet16/1 15 +Ethernet16 1 Ethernet17/1 16 +Ethernet17 2 Ethernet18/1 17 +Ethernet18 3 Ethernet19/1 18 +Ethernet19 4 Ethernet20/1 19 +Ethernet20 8 Ethernet21/1 20 +Ethernet21 7 Ethernet22/1 21 +Ethernet22 6 Ethernet23/1 22 +Ethernet23 5 Ethernet24/1 23 +Ethernet24 12 Ethernet25/1 24 +Ethernet25 11 Ethernet26/1 25 +Ethernet26 10 Ethernet27/1 26 +Ethernet27 9 Ethernet28/1 27 +Ethernet28 13 Ethernet29/1 28 +Ethernet29 14 Ethernet30/1 29 +Ethernet30 15 Ethernet31/1 30 +Ethernet31 16 Ethernet32/1 31 +Ethernet32 33 Ethernet33/1 32 +Ethernet33 34 Ethernet34/1 33 +Ethernet34 35 Ethernet35/1 34 +Ethernet35 36 Ethernet36/1 35 +Ethernet36 38 Ethernet37/1 36 +Ethernet37 39 Ethernet38/1 37 +Ethernet38 40 Ethernet39/1 38 +Ethernet39 37 Ethernet40/1 39 +Ethernet40 41 Ethernet41/1 40 +Ethernet41 42 Ethernet42/1 41 +Ethernet42 43 Ethernet43/1 42 +Ethernet43 44 Ethernet44/1 43 +Ethernet44 48 Ethernet45/1 44 +Ethernet45 45 Ethernet46/1 45 +Ethernet46 46 Ethernet47/1 46 +Ethernet47 47 Ethernet48/1 47 +Ethernet48 49,50,51,52 Ethernet49/1 48 +Ethernet52 53,54,55,56 Ethernet50/1 49 +Ethernet56 57,58,59,60 Ethernet51/1 50 +Ethernet60 61,62,63,64 Ethernet52/1 51 +Ethernet64 65,66,67,68 Ethernet53/1 52 +Ethernet68 69,70,71,72 Ethernet54/1 53 +Ethernet72 73,74,75,76 Ethernet55/1 54 +Ethernet76 77,78,79,80 Ethernet56/1 55 +Ethernet80 81,82,83,84 Ethernet57/1 56 +Ethernet84 85,86,87,88 Ethernet58/1 57 +Ethernet88 89,90,91,92 Ethernet59/1 58 +Ethernet92 93,94,95,96 Ethernet60/1 59 +Ethernet96 97,98,99,100 Ethernet61/1 60 +Ethernet100 101,102,103,104 Ethernet62/1 61 +Ethernet104 105,106,107,108 Ethernet63/1 62 +Ethernet108 109,110,111,112 Ethernet64/1 63 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/sai.profile b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/sai.profile new file mode 100644 index 000000000000..77a0e3efa431 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-s8900-48x25G+16x100G.config.bcm diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/th-s8900-48x25G+16x100G.config.bcm b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/th-s8900-48x25G+16x100G.config.bcm new file mode 100644 index 000000000000..f30d4ea6dd34 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/th-s8900-48x25G+16x100G.config.bcm @@ -0,0 +1,448 @@ +#2018/03/31 + +os=unix + +oversubscribe_mode=1 +pbmp_xport_xe=0x3c000000ff0003ffffdfffffffe + +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l3_mem_entries=40960 +l2_mem_entries=40960 + +l2xmsg_mode=1 +mmu_lossless=0 + +#Parity +parity_correction=1 +parity_enable=1 + +#PIPE0 +portmap_1=17:25 +portmap_2=18:25 +portmap_3=19:25 +portmap_4=20:25 +portmap_5=24:25 +portmap_6=23:25 +portmap_7=22:25 +portmap_8=21:25 +portmap_9=28:25 +portmap_10=27:25 +portmap_11=26:25 +portmap_12=25:25 +portmap_13=32:25 +portmap_14=31:25 +portmap_15=30:25 +portmap_16=29:25 +portmap_17=1:25 +portmap_18=2:25 +portmap_19=3:25 +portmap_20=4:25 +portmap_21=8:25 +portmap_22=7:25 +portmap_23=6:25 +portmap_24=5:25 +portmap_25=12:25 +portmap_26=11:25 +portmap_27=10:25 +portmap_28=9:25 +portmap_29=13:25 +portmap_30=14:25 +portmap_31=15:25 +portmap_32=16:25 + +#PIPE1 +portmap_34=33:25 +portmap_35=34:25 +portmap_36=35:25 +portmap_37=36:25 +portmap_38=38:25 +portmap_39=39:25 +portmap_40=40:25 +portmap_41=37:25 +portmap_42=41:25 +portmap_43=42:25 +portmap_44=43:25 +portmap_45=44:25 +portmap_46=48:25 +portmap_47=45:25 +portmap_48=46:25 +portmap_49=47:25 +portmap_50=49:100 +portmap_51=53:100 +portmap_52=57:100 +portmap_53=61:100 + +#PIPE2 +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 + +#PIPE3 +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 + + +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +serdes_driver_current_xe0=0xf +serdes_preemphasis_xe0=0x003c14 +serdes_if_type_xe0=14 + +serdes_driver_current_xe1=0xf +serdes_preemphasis_xe1=0x003c1c +serdes_if_type_xe1=14 + +serdes_driver_current_xe2=0xf +serdes_preemphasis_xe2=0x003c08 +serdes_if_type_xe2=14 + +serdes_driver_current_xe3=0xf +serdes_preemphasis_xe3=0x003c08 +serdes_if_type_xe3=14 + +serdes_driver_current_xe4=0xf +serdes_preemphasis_xe4=0x003c08 +serdes_if_type_xe4=14 + +serdes_driver_current_xe5=0xf +serdes_preemphasis_xe5=0x003c10 +serdes_if_type_xe5=14 + +serdes_driver_current_xe6=0xf +serdes_preemphasis_xe6=0x083c08 +serdes_if_type_xe6=14 + +serdes_driver_current_xe7=0xf +serdes_preemphasis_xe7=0x043c10 +serdes_if_type_xe7=14 + +serdes_driver_current_xe8=0x9 +serdes_preemphasis_xe8=0x003c08 +serdes_if_type_xe8=14 + +serdes_driver_current_xe9=0x9 +serdes_preemphasis_xe9=0x003c08 +serdes_if_type_xe9=14 + +serdes_driver_current_xe10=0x9 +serdes_preemphasis_xe10=0x003c08 +serdes_if_type_xe10=14 + +serdes_driver_current_xe11=0x9 +serdes_preemphasis_xe11=0x003c08 +serdes_if_type_xe11=14 + +serdes_driver_current_xe12=0x9 +serdes_preemphasis_xe12=0x2c4408 +serdes_if_type_xe12=14 + +serdes_driver_current_xe13=0x9 +serdes_preemphasis_xe13=0x003c08 +serdes_if_type_xe13=14 + +serdes_driver_current_xe14=0x9 +serdes_preemphasis_xe14=0x003c08 +serdes_if_type_xe14=14 + +serdes_driver_current_xe15=0x9 +serdes_preemphasis_xe15=0x003c08 +serdes_if_type_xe15=14 + +serdes_driver_current_xe16=0xb +serdes_preemphasis_xe16=0x0c3c08 +serdes_if_type_xe16=14 + +serdes_driver_current_xe17=0xb +serdes_preemphasis_xe17=0x0c3c10 +serdes_if_type_xe17=14 + +serdes_driver_current_xe18=0xa +serdes_preemphasis_xe18=0x083c08 +serdes_if_type_xe18=14 + +serdes_driver_current_xe19=0x9 +serdes_preemphasis_xe19=0x0c3c10 +serdes_if_type_xe19=14 + +serdes_driver_current_xe20=0xc +serdes_preemphasis_xe20=0x043c08 +serdes_if_type_xe20=14 + +serdes_driver_current_xe21=0x9 +serdes_preemphasis_xe21=0x083c08 +serdes_if_type_xe21=14 + +serdes_driver_current_xe22=0xc +serdes_preemphasis_xe22=0x083c08 +serdes_if_type_xe22=14 + +serdes_driver_current_xe23=0xa +serdes_preemphasis_xe23=0x083c10 +serdes_if_type_xe23=14 + +serdes_driver_current_xe24=0x9 +serdes_preemphasis_xe24=0x083c08 +serdes_if_type_xe24=14 + +serdes_driver_current_xe25=0x9 +serdes_preemphasis_xe25=0x043c08 +serdes_if_type_xe25=14 + +serdes_driver_current_xe26=0x9 +serdes_preemphasis_xe26=0x003c08 +serdes_if_type_xe26=14 + +serdes_driver_current_xe27=0xc +serdes_preemphasis_xe27=0x083c08 +serdes_if_type_xe27=14 + +serdes_driver_current_xe28=0xa +serdes_preemphasis_xe28=0x003c10 +serdes_if_type_xe28=14 + +serdes_driver_current_xe29=0x9 +serdes_preemphasis_xe29=0x043c10 +serdes_if_type_xe29=14 + +serdes_driver_current_xe30=0x9 +serdes_preemphasis_xe30=0x003c14 +serdes_if_type_xe30=14 + +serdes_driver_current_xe31=0xa +serdes_preemphasis_xe31=0x003c14 +serdes_if_type_xe31=14 + +serdes_driver_current_xe32=0x9 +serdes_preemphasis_xe32=0x003c08 +serdes_if_type_xe32=14 + +serdes_driver_current_xe33=0x7 +serdes_preemphasis_xe33=0x003c08 +serdes_if_type_xe33=14 + +serdes_driver_current_xe34=0x9 +serdes_preemphasis_xe34=0x003c08 +serdes_if_type_xe34=14 + +serdes_driver_current_xe35=0x9 +serdes_preemphasis_xe35=0x003c08 +serdes_if_type_xe35=14 + +serdes_driver_current_xe36=0x9 +serdes_preemphasis_xe36=0x003c08 +serdes_if_type_xe36=14 + +serdes_driver_current_xe37=0x9 +serdes_preemphasis_xe37=0x003c0c +serdes_if_type_xe37=14 + +serdes_driver_current_xe38=0x9 +serdes_preemphasis_xe38=0x003c08 +serdes_if_type_xe38=14 + +serdes_driver_current_xe39=0x9 +serdes_preemphasis_xe39=0x003c08 +serdes_if_type_xe39=14 + +serdes_driver_current_xe40=0xa +serdes_preemphasis_xe40=0x003c10 +serdes_if_type_xe40=14 + +serdes_driver_current_xe41=0x9 +serdes_preemphasis_xe41=0x003c10 +serdes_if_type_xe41=14 + +serdes_driver_current_xe42=0xc +serdes_preemphasis_xe42=0x083c08 +serdes_if_type_xe42=14 + +serdes_driver_current_xe43=0xa +serdes_preemphasis_xe43=0x003c10 +serdes_if_type_xe43=14 + +serdes_driver_current_xe44=0xa +serdes_preemphasis_xe44=0x003c08 +serdes_if_type_xe44=14 + +serdes_driver_current_xe45=0x9 +serdes_preemphasis_xe45=0x003c10 +serdes_if_type_xe45=14 + +serdes_driver_current_xe46=0x9 +serdes_preemphasis_xe46=0x043c08 +serdes_if_type_xe46=14 + +serdes_driver_current_xe47=0xa +serdes_preemphasis_xe47=0x003c08 +serdes_if_type_xe47=14 + +serdes_driver_current_lane0_ce0=0x9 +serdes_driver_current_lane1_ce0=0xf +serdes_driver_current_lane2_ce0=0x9 +serdes_driver_current_lane3_ce0=0x9 +serdes_preemphasis_lane0_ce0=0x003c08 +serdes_preemphasis_lane1_ce0=0x003c08 +serdes_preemphasis_lane2_ce0=0x003c08 +serdes_preemphasis_lane3_ce0=0x003c08 +serdes_if_type_ce0=14 + +serdes_driver_current_lane0_ce1=0x9 +serdes_driver_current_lane1_ce1=0x9 +serdes_driver_current_lane2_ce1=0x9 +serdes_driver_current_lane3_ce1=0xe +serdes_preemphasis_lane0_ce1=0x003c08 +serdes_preemphasis_lane1_ce1=0x003c08 +serdes_preemphasis_lane2_ce1=0x003c08 +serdes_preemphasis_lane3_ce1=0x003c08 +serdes_if_type_ce1=14 + +serdes_driver_current_lane0_ce2=0x9 +serdes_driver_current_lane1_ce2=0xf +serdes_driver_current_lane2_ce2=0x9 +serdes_driver_current_lane3_ce2=0xd +serdes_preemphasis_lane0_ce2=0x003c08 +serdes_preemphasis_lane1_ce2=0x003c08 +serdes_preemphasis_lane2_ce2=0x003c08 +serdes_preemphasis_lane3_ce2=0x003c08 +serdes_if_type_ce2=14 + +serdes_driver_current_lane0_ce3=0x9 +serdes_driver_current_lane1_ce3=0xd +serdes_driver_current_lane2_ce3=0x9 +serdes_driver_current_lane3_ce3=0xd +serdes_preemphasis_lane0_ce3=0x003c08 +serdes_preemphasis_lane1_ce3=0x003c08 +serdes_preemphasis_lane2_ce3=0x003c08 +serdes_preemphasis_lane3_ce3=0x003c08 +serdes_if_type_ce3=14 + +serdes_driver_current_lane0_ce4=0x9 +serdes_driver_current_lane1_ce4=0x9 +serdes_driver_current_lane2_ce4=0x9 +serdes_driver_current_lane3_ce4=0xd +serdes_preemphasis_lane0_ce4=0x003c08 +serdes_preemphasis_lane1_ce4=0x003c08 +serdes_preemphasis_lane2_ce4=0x003c08 +serdes_preemphasis_lane3_ce4=0x003c08 +serdes_if_type_ce4=14 + +serdes_driver_current_lane0_ce5=0x9 +serdes_driver_current_lane1_ce5=0xf +serdes_driver_current_lane2_ce5=0x9 +serdes_driver_current_lane3_ce5=0x9 +serdes_preemphasis_lane0_ce5=0x003c08 +serdes_preemphasis_lane1_ce5=0x003c08 +serdes_preemphasis_lane2_ce5=0x003c08 +serdes_preemphasis_lane3_ce5=0x003c08 +serdes_if_type_ce5=14 + +serdes_driver_current_lane0_ce6=0x9 +serdes_driver_current_lane1_ce6=0x9 +serdes_driver_current_lane2_ce6=0x9 +serdes_driver_current_lane3_ce6=0xe +serdes_preemphasis_lane0_ce6=0x003c08 +serdes_preemphasis_lane1_ce6=0x003c08 +serdes_preemphasis_lane2_ce6=0x003c08 +serdes_preemphasis_lane3_ce6=0x003c08 +serdes_if_type_ce6=14 + +serdes_driver_current_lane0_ce7=0x9 +serdes_driver_current_lane1_ce7=0xa +serdes_driver_current_lane2_ce7=0x9 +serdes_driver_current_lane3_ce7=0Xe +serdes_preemphasis_lane0_ce7=0x003c08 +serdes_preemphasis_lane1_ce7=0x003c08 +serdes_preemphasis_lane2_ce7=0x003c08 +serdes_preemphasis_lane3_ce7=0x003c08 +serdes_if_type_ce7=14 + +serdes_driver_current_lane0_ce8=0xf +serdes_driver_current_lane1_ce8=0xf +serdes_driver_current_lane2_ce8=0xf +serdes_driver_current_lane3_ce8=0xf +serdes_preemphasis_lane0_ce8=0x043c08 +serdes_preemphasis_lane1_ce8=0x003c08 +serdes_preemphasis_lane2_ce8=0x043c08 +serdes_preemphasis_lane3_ce8=0x003c08 +serdes_if_type_ce8=14 + +serdes_driver_current_lane0_ce9=0xf +serdes_driver_current_lane1_ce9=0xf +serdes_driver_current_lane2_ce9=0xf +serdes_driver_current_lane3_ce9=0xf +serdes_preemphasis_lane0_ce9=0x043c08 +serdes_preemphasis_lane1_ce9=0x043c08 +serdes_preemphasis_lane2_ce9=0x043c08 +serdes_preemphasis_lane3_ce9=0x043c08 +serdes_if_type_ce9=14 + +serdes_driver_current_lane0_ce10=0xf +serdes_driver_current_lane1_ce10=0xf +serdes_driver_current_lane2_ce10=0xf +serdes_driver_current_lane3_ce10=0xf +serdes_preemphasis_lane0_ce10=0x043c08 +serdes_preemphasis_lane1_ce10=0x083c10 +serdes_preemphasis_lane2_ce10=0x043c08 +serdes_preemphasis_lane3_ce10=0x043c08 +serdes_if_type_ce10=14 + +serdes_driver_current_lane0_ce11=0xf +serdes_driver_current_lane1_ce11=0xf +serdes_driver_current_lane2_ce11=0xf +serdes_driver_current_lane3_ce11=0xf +serdes_preemphasis_lane0_ce11=0x083c08 +serdes_preemphasis_lane1_ce11=0x043c08 +serdes_preemphasis_lane2_ce11=0X043c08 +serdes_preemphasis_lane3_ce11=0X043c08 +serdes_if_type_ce11=14 + +serdes_driver_current_lane0_ce12=0xf +serdes_driver_current_lane1_ce12=0xf +serdes_driver_current_lane2_ce12=0xf +serdes_driver_current_lane3_ce12=0xf +serdes_preemphasis_lane0_ce12=0x0c3c08 +serdes_preemphasis_lane1_ce12=0x083c08 +serdes_preemphasis_lane2_ce12=0x0c3c08 +serdes_preemphasis_lane3_ce12=0x083c08 +serdes_if_type_ce12=14 + +serdes_driver_current_lane0_ce13=0xf +serdes_driver_current_lane1_ce13=0xf +serdes_driver_current_lane2_ce13=0xf +serdes_driver_current_lane3_ce13=0xf +serdes_preemphasis_lane0_ce13=0x083c08 +serdes_preemphasis_lane1_ce13=0x0c3c08 +serdes_preemphasis_lane2_ce13=0x083c08 +serdes_preemphasis_lane3_ce13=0x0c3c08 +serdes_if_type_ce13=14 + +serdes_driver_current_lane0_ce14=0xf +serdes_driver_current_lane1_ce14=0xf +serdes_driver_current_lane2_ce14=0xf +serdes_driver_current_lane3_ce14=0xf +serdes_preemphasis_lane0_ce14=0x103c10 +serdes_preemphasis_lane1_ce14=0x0c3c08 +serdes_preemphasis_lane2_ce14=0x0c3c08 +serdes_preemphasis_lane3_ce14=0x0c3c08 +serdes_if_type_ce14=14 + +serdes_driver_current_lane0_ce15=0xf +serdes_driver_current_lane1_ce15=0xf +serdes_driver_current_lane2_ce15=0xf +serdes_driver_current_lane3_ce15=0xf +serdes_preemphasis_lane0_ce15=0x143c08 +serdes_preemphasis_lane1_ce15=0x103c08 +serdes_preemphasis_lane2_ce15=0x103c08 +serdes_preemphasis_lane3_ce15=0x103c08 +serdes_if_type_ce15=14 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/default_sku new file mode 100644 index 000000000000..3002ec5856f3 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S8900-64XC t1 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/fancontrol new file mode 100644 index 000000000000..4819fe113172 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/fancontrol @@ -0,0 +1,10 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/0-002f +DEVNAME=hwmon1=w83795adg +FCTEMPS=hwmon1/device/pwm1=hwmon1/device/temp2_input hwmon1/device/pwm2=hwmon1/device/temp2_input +FCFANS=hwmon1/device/pwm2=hwmon1/device/fan10_input hwmon1/device/pwm2=hwmon1/device/fan9_input hwmon1/device/pwm2=hwmon1/device/fan8_input hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan6_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm1=hwmon1/device/fan4_input hwmon1/device/pwm1=hwmon1/device/fan3_input hwmon1/device/pwm1=hwmon1/device/fan2_input hwmon1/device/pwm1=hwmon1/device/fan1_input +MINTEMP=hwmon1/device/pwm1=20 hwmon1/device/pwm2=20 +MAXTEMP=hwmon1/device/pwm1=60 hwmon1/device/pwm2=60 +MINSTART=hwmon1/device/pwm1=150 hwmon1/device/pwm2=150 +MINSTOP=hwmon1/device/pwm1=0 hwmon1/device/pwm2=0 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/led_proc_init.soc b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/led_proc_init.soc new file mode 100644 index 000000000000..6a1f4f2c1ea6 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/led_proc_init.soc @@ -0,0 +1,43 @@ +# LED microprocessor initialization for Ingrasys S8900-64XC + +led 0 stop +led 0 prog 12 00 61 F1 12 20 61 F2 12 01 61 F3 12 01 61 F4 67 28 12 20 61 F1 12 04 61 F2 12 04 61 F3 12 01 61 F4 67 28 86 F0 77 86 96 F2 2E F1 67 3D 67 51 16 F3 FE F1 61 F1 12 00 DE F2 74 28 57 2E F1 32 00 32 01 B7 97 75 4C 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 6A 77 5A 06 FE D2 01 70 62 77 78 06 F0 C2 08 74 6A 77 78 16 F4 91 22 0E 87 22 0E 87 DA 00 74 6C 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 7A 57 02 48 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28 REMAP_PORT_2=29 REMAP_PORT_1=30 REMAP_PORT_0=31 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24 REMAP_PORT_6=25 REMAP_PORT_5=26 REMAP_PORT_4=27 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=20 REMAP_PORT_10=21 REMAP_PORT_9=22 REMAP_PORT_8=19 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=16 REMAP_PORT_14=17 REMAP_PORT_13=18 REMAP_PORT_12=23 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=12 REMAP_PORT_18=13 REMAP_PORT_17=14 REMAP_PORT_16=15 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=8 REMAP_PORT_22=9 REMAP_PORT_21=10 REMAP_PORT_20=11 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=4 REMAP_PORT_26=5 REMAP_PORT_25=6 REMAP_PORT_24=7 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0 REMAP_PORT_30=1 REMAP_PORT_29=2 REMAP_PORT_28=3 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=60 REMAP_PORT_34=61 REMAP_PORT_33=62 REMAP_PORT_32=63 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=56 REMAP_PORT_38=57 REMAP_PORT_37=58 REMAP_PORT_36=59 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52 REMAP_PORT_42=53 REMAP_PORT_41=54 REMAP_PORT_40=55 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48 REMAP_PORT_46=49 REMAP_PORT_45=50 REMAP_PORT_44=51 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=44 REMAP_PORT_50=45 REMAP_PORT_49=46 REMAP_PORT_48=47 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=40 REMAP_PORT_54=41 REMAP_PORT_53=42 REMAP_PORT_52=43 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=36 REMAP_PORT_58=37 REMAP_PORT_57=38 REMAP_PORT_56=39 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=32 REMAP_PORT_62=33 REMAP_PORT_61=34 REMAP_PORT_60=35 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 12 00 61 F1 12 10 61 F2 12 01 61 F3 12 01 61 F4 67 28 12 10 61 F1 12 0C 61 F2 12 04 61 F3 12 01 61 F4 67 28 86 F0 77 86 96 F2 2E F1 67 3D 67 51 16 F3 FE F1 61 F1 12 00 DE F2 74 28 57 2E F1 32 00 32 01 B7 97 75 4C 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 6A 77 5A 06 FE D2 01 70 62 77 78 06 F0 C2 08 74 6A 77 78 16 F4 91 22 0E 87 22 0E 87 DA 00 74 6C 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 7A 57 02 38 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=8 REMAP_PORT_10=9 REMAP_PORT_9=10 REMAP_PORT_8=11 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=12 REMAP_PORT_14=13 REMAP_PORT_13=14 REMAP_PORT_12=15 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=16 REMAP_PORT_18=17 REMAP_PORT_17=18 REMAP_PORT_16=19 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=20 REMAP_PORT_22=21 REMAP_PORT_21=22 REMAP_PORT_20=23 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=24 REMAP_PORT_26=25 REMAP_PORT_25=26 REMAP_PORT_24=27 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=28 REMAP_PORT_30=29 REMAP_PORT_29=30 REMAP_PORT_28=31 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=32 REMAP_PORT_34=33 REMAP_PORT_33=34 REMAP_PORT_32=35 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=36 REMAP_PORT_38=37 REMAP_PORT_37=38 REMAP_PORT_36=39 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40 REMAP_PORT_42=41 REMAP_PORT_41=42 REMAP_PORT_40=43 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44 REMAP_PORT_46=45 REMAP_PORT_45=46 REMAP_PORT_44=47 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=48 REMAP_PORT_50=49 REMAP_PORT_49=50 REMAP_PORT_48=51 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=52 REMAP_PORT_54=53 REMAP_PORT_53=54 REMAP_PORT_52=55 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=56 REMAP_PORT_58=57 REMAP_PORT_57=58 REMAP_PORT_56=59 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=60 REMAP_PORT_62=61 REMAP_PORT_61=62 REMAP_PORT_60=63 +led 1 auto on +led 1 start diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/eeprom.py new file mode 100644 index 000000000000..1b8de3f16bca --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Ingrasys S8900-64XC +# +# 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-7/7-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/psuutil.py new file mode 100644 index 000000000000..3af5423daebd --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/psuutil.py @@ -0,0 +1,92 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_CPLD_DIR = "/sys/bus/i2c/devices/0-0033" + + def __init__(self): + PsuBase.__init__(self) + + + # Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + mask = [ 0x04, 0x08 ] + attr_file = 'cpld_pw_good' + attr_path = self.PSU_CPLD_DIR +'/'+ attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU status + if (attr_value & mask[index-1]): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + mask = [ 0x01, 0x02 ] + attr_file ='cpld_pw_abs' + attr_path = self.PSU_CPLD_DIR +'/'+ attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU presence + if (~attr_value & mask[index-1]): + status = 1 + + return status + diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/sfputil.py new file mode 100644 index 000000000000..26355bf441e6 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/sfputil.py @@ -0,0 +1,264 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import subprocess + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +i2c_set = 'i2cset' +i2c_get = 'i2cget' +cpld_addr = '0x33' +mux_reg = '0x4A' + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 0 + PORT_END = 63 + QSFP_PORT_START = 48 + PORTS_IN_BLOCK = 64 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: [2,1], + 1: [2,2], + 2: [2,3], + 3: [2,4], + 4: [2,5], + 5: [2,6], + 6: [2,7], + 7: [2,8], + 8: [2,9], + 9: [2,10], + 10: [2,11], + 11: [2,12], + 12: [2,13], + 13: [2,14], + 14: [2,15], + 15: [2,16], + 16: [2,17], + 17: [2,18], + 18: [2,19], + 19: [2,20], + 20: [2,21], + 21: [2,22], + 22: [2,23], + 23: [2,24], + 24: [3,25], + 25: [3,26], + 26: [3,27], + 27: [3,28], + 28: [3,29], + 29: [3,30], + 30: [3,31], + 31: [3,32], + 32: [3,33], + 33: [3,34], + 34: [3,35], + 35: [3,36], + 36: [3,37], + 37: [3,38], + 38: [3,39], + 39: [3,40], + 40: [3,41], + 41: [3,42], + 42: [3,43], + 43: [3,44], + 44: [3,45], + 45: [3,46], + 46: [3,47], + 47: [3,48], + 48: [4,49], + 49: [4,50], + 50: [4,51], + 51: [4,52], + 52: [4,53], + 53: [4,54], + 54: [4,55], + 55: [4,56], + 56: [4,57], + 57: [4,58], + 58: [4,59], + 59: [4,60], + 60: [4,61], + 61: [4,62], + 62: [4,63], + 63: [4,64] + } + + @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(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + def __init__(self): + + sfp_eeprom_path = '/sys/bus/i2c/devices/{0[0]}-0050/sfp{0[1]}' + qsfp_eeprom_path = '/sys/bus/i2c/devices/{0[0]}-0050/qsfp{0[1]}' + for x in range(self.port_start, self.qsfp_port_start): + port_eeprom_path = sfp_eeprom_path.format(self.port_to_i2c_mapping[x]) + self.port_to_eeprom_mapping[x] = port_eeprom_path + for x in range(self.qsfp_port_start, self.port_end + 1): + port_eeprom_path = qsfp_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/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_modprs") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # content is a string, either "0" or "1" + 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.qsfp_port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_lpmode") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (port_num - self.qsfp_port_start) ) + + # 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.qsfp_port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_lpmode", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (port_num - self.qsfp_port_start) ) + + # 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): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_reset" + + # Check for invalid port_num + if port_num < self.qsfp_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 + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (port_num - self.qsfp_port_start)) + + # 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: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "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 + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/sensors.conf new file mode 100644 index 000000000000..374bd3a64f04 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/sensors.conf @@ -0,0 +1,55 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + label temp1 "DIMM Temp" + set temp1_max 50 + set temp1_crit 85 + +chip "w83795adg-*" + label in0 "1.0V" + label in1 "1.0V_ROV" + label in2 "1.25V" + label in3 "1.8V" + ignore in4 + ignore in5 + ignore in6 + ignore in7 + label in12 "+3.3V" + ignore in14 + ignore in15 + ignore in16 + label fan1 "FANTRAY 1-A" + label fan2 "FANTRAY 1-B" + label fan3 "FANTRAY 2-A" + label fan4 "FANTRAY 2-B" + label fan5 "FANTRAY 3-A" + label fan6 "FANTRAY 3-B" + label fan7 "FANTRAY 4-A" + label fan8 "FANTRAY 4-B" + label fan9 "FANTRAY 5-A" + label fan10 "FANTRAY 5-B" + label temp1 "Front MAC Temp" + set temp1_max 60 + set temp1_crit 65 + label temp2 "Rear MAC Temp" + set temp2_max 60 + set temp2_crit 65 + label temp3 "Near Port 15" + set temp3_max 50 + set temp3_crit 70 + label temp4 "Near Port 56" + set temp4_max 50 + set temp4_crit 70 + ignore intrusion0 + +bus "i2c-5" "i2c-1-switch (chan_id 3)" +chip "tmp75-i2c-*-48" + label temp1 "FAN Temp1" + set temp1_max 50 + set temp1_crit 70 +chip "tmp75-i2c-*-49" + label temp1 "FAN Temp2" + set temp1_max 50 + set temp1_crit 70 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/port_config.ini b/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/port_config.ini new file mode 100644 index 000000000000..ab0202011576 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 5,6,7,8 Ethernet1/1 0 +Ethernet4 1,2,3,4 Ethernet2/1 1 +Ethernet8 13,14,15,16 Ethernet3/1 2 +Ethernet12 9,10,11,12 Ethernet4/1 3 +Ethernet16 21,22,23,24 Ethernet5/1 4 +Ethernet20 17,18,19,20 Ethernet6/1 5 +Ethernet24 29,30,31,32 Ethernet7/1 6 +Ethernet28 25,26,27,28 Ethernet8/1 7 +Ethernet32 37,38,39,40 Ethernet9/1 8 +Ethernet36 33,34,35,36 Ethernet10/1 9 +Ethernet40 45,46,47,48 Ethernet11/1 10 +Ethernet44 41,42,43,44 Ethernet12/1 11 +Ethernet48 53,54,55,56 Ethernet13/1 12 +Ethernet52 49,50,51,52 Ethernet14/1 13 +Ethernet56 61,62,63,64 Ethernet15/1 14 +Ethernet60 57,58,59,60 Ethernet16/1 15 +Ethernet64 69,70,71,72 Ethernet17/1 16 +Ethernet68 65,66,67,68 Ethernet18/1 17 +Ethernet72 77,78,79,80 Ethernet19/1 18 +Ethernet76 73,74,75,76 Ethernet20/1 19 +Ethernet80 85,86,87,88 Ethernet21/1 20 +Ethernet84 81,82,83,84 Ethernet22/1 21 +Ethernet88 93,94,95,96 Ethernet23/1 22 +Ethernet92 89,90,91,92 Ethernet24/1 23 +Ethernet96 101,102,103,104 Ethernet25/1 24 +Ethernet100 97,98,99,100 Ethernet26/1 25 +Ethernet104 109,110,111,112 Ethernet27/1 26 +Ethernet108 105,106,107,108 Ethernet28/1 27 +Ethernet112 117,118,119,120 Ethernet29/1 28 +Ethernet116 113,114,115,116 Ethernet30/1 29 +Ethernet120 125,126,127,128 Ethernet31/1 30 +Ethernet124 121,122,123,124 Ethernet32/1 31 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/sai.profile b/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/sai.profile new file mode 100644 index 000000000000..14a36af5f554 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-s9100-32x100G.config.bcm diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/th-s9100-32x100G.config.bcm b/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/th-s9100-32x100G.config.bcm new file mode 100644 index 000000000000..46b8799efef2 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/th-s9100-32x100G.config.bcm @@ -0,0 +1,357 @@ +#2017/09/12 + +os=unix + +oversubscribe_mode=1 +pbmp_xport_xe=0x3fc000000ff0000003fc000001fe + +#ALPM enable +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l3_mem_entries=40960 +l2_mem_entries=40960 + +l2xmsg_mode=1 +mmu_lossless=0 + +#Parity +parity_correction=1 +parity_enable=1 + +#PIPE0 +portmap_1=5:100 +portmap_2=1:100 +portmap_3=13:100 +portmap_4=9:100 +portmap_5=21:100 +portmap_6=17:100 +portmap_7=29:100 +portmap_8=25:100 + +#PIPE1 +portmap_34=37:100 +portmap_35=33:100 +portmap_36=45:100 +portmap_37=41:100 +portmap_38=53:100 +portmap_39=49:100 +portmap_40=61:100 +portmap_41=57:100 + +#PIPE2 +portmap_68=69:100 +portmap_69=65:100 +portmap_70=77:100 +portmap_71=73:100 +portmap_72=85:100 +portmap_73=81:100 +portmap_74=93:100 +portmap_75=89:100 + +#PIPE3 +portmap_102=101:100 +portmap_103=97:100 +portmap_104=109:100 +portmap_105=105:100 +portmap_106=117:100 +portmap_107=113:100 +portmap_108=125:100 +portmap_109=121:100 + +#portmap_66=129:10 +#portmap_100=131:10 +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +serdes_driver_current_lane0_ce0=0xF +serdes_driver_current_lane1_ce0=0xF +serdes_driver_current_lane2_ce0=0xF +serdes_driver_current_lane3_ce0=0xF +serdes_preemphasis_lane0_ce0=0x153C1F +serdes_preemphasis_lane1_ce0=0x20341C +serdes_preemphasis_lane2_ce0=0x153C1F +serdes_preemphasis_lane3_ce0=0x243418 + +serdes_driver_current_lane0_ce1=0xF +serdes_driver_current_lane1_ce1=0xF +serdes_driver_current_lane2_ce1=0xF +serdes_driver_current_lane3_ce1=0xF +serdes_preemphasis_lane0_ce1=0x153C1F +serdes_preemphasis_lane1_ce1=0x20341C +serdes_preemphasis_lane2_ce1=0x153C1F +serdes_preemphasis_lane3_ce1=0x20341C + +serdes_driver_current_lane0_ce2=0xF +serdes_driver_current_lane1_ce2=0xD +serdes_driver_current_lane2_ce2=0xF +serdes_driver_current_lane3_ce2=0xD +serdes_preemphasis_lane0_ce2=0x153C1F +serdes_preemphasis_lane1_ce2=0x243418 +serdes_preemphasis_lane2_ce2=0x153C1F +serdes_preemphasis_lane3_ce2=0x203C14 + +serdes_driver_current_lane0_ce3=0xF +serdes_driver_current_lane1_ce3=0xD +serdes_driver_current_lane2_ce3=0xF +serdes_driver_current_lane3_ce3=0xD +serdes_preemphasis_lane0_ce3=0x153C1F +serdes_preemphasis_lane1_ce3=0x203C14 +serdes_preemphasis_lane2_ce3=0x153C1F +serdes_preemphasis_lane3_ce3=0x243418 + +serdes_driver_current_lane0_ce4=0xF +serdes_driver_current_lane1_ce4=0xB +serdes_driver_current_lane2_ce4=0xF +serdes_driver_current_lane3_ce4=0xA +serdes_preemphasis_lane0_ce4=0x153C1F +serdes_preemphasis_lane1_ce4=0x333D00 +serdes_preemphasis_lane2_ce4=0x153C1F +serdes_preemphasis_lane3_ce4=0x304000 + +serdes_driver_current_lane0_ce5=0xF +serdes_driver_current_lane1_ce5=0xB +serdes_driver_current_lane2_ce5=0xF +serdes_driver_current_lane3_ce5=0xA +serdes_preemphasis_lane0_ce5=0x153C1F +serdes_preemphasis_lane1_ce5=0x304000 +serdes_preemphasis_lane2_ce5=0x153C1F +serdes_preemphasis_lane3_ce5=0x304000 + +serdes_driver_current_lane0_ce6=0xF +serdes_driver_current_lane1_ce6=0xC +serdes_driver_current_lane2_ce6=0xF +serdes_driver_current_lane3_ce6=0xA +serdes_preemphasis_lane0_ce6=0x153C1F +serdes_preemphasis_lane1_ce6=0x363A00 +serdes_preemphasis_lane2_ce6=0x153C1F +serdes_preemphasis_lane3_ce6=0x304000 + +serdes_driver_current_lane0_ce7=0xF +serdes_driver_current_lane1_ce7=0x8 +serdes_driver_current_lane2_ce7=0xF +serdes_driver_current_lane3_ce7=0x8 +serdes_preemphasis_lane0_ce7=0x153C1F +serdes_preemphasis_lane1_ce7=0x304000 +serdes_preemphasis_lane2_ce7=0x153C1F +serdes_preemphasis_lane3_ce7=0x304000 + +serdes_driver_current_lane0_ce8=0x8 +serdes_driver_current_lane1_ce8=0x9 +serdes_driver_current_lane2_ce8=0x8 +serdes_driver_current_lane3_ce8=0x8 +serdes_preemphasis_lane0_ce8=0x254B00 +serdes_preemphasis_lane1_ce8=0x2C4400 +serdes_preemphasis_lane2_ce8=0x254B00 +serdes_preemphasis_lane3_ce8=0x254B00 + +serdes_driver_current_lane0_ce9=0x8 +serdes_driver_current_lane1_ce9=0x9 +serdes_driver_current_lane2_ce9=0x8 +serdes_driver_current_lane3_ce9=0x8 +serdes_preemphasis_lane0_ce9=0x254B00 +serdes_preemphasis_lane1_ce9=0x2B4500 +serdes_preemphasis_lane2_ce9=0x254B00 +serdes_preemphasis_lane3_ce9=0x254B00 + +serdes_driver_current_lane0_ce10=0x8 +serdes_driver_current_lane1_ce10=0x7 +serdes_driver_current_lane2_ce10=0x8 +serdes_driver_current_lane3_ce10=0x8 +serdes_preemphasis_lane0_ce10=0x254B00 +serdes_preemphasis_lane1_ce10=0x2B4500 +serdes_preemphasis_lane2_ce10=0x254B00 +serdes_preemphasis_lane3_ce10=0x254B00 + +serdes_driver_current_lane0_ce11=0x8 +serdes_driver_current_lane1_ce11=0x8 +serdes_driver_current_lane2_ce11=0x8 +serdes_driver_current_lane3_ce11=0x8 +serdes_preemphasis_lane0_ce11=0x254B00 +serdes_preemphasis_lane1_ce11=0x2C4400 +serdes_preemphasis_lane2_ce11=0x254B00 +serdes_preemphasis_lane3_ce11=0x254B00 + +serdes_driver_current_lane0_ce12=0x8 +serdes_driver_current_lane1_ce12=0x5 +serdes_driver_current_lane2_ce12=0x8 +serdes_driver_current_lane3_ce12=0x8 +serdes_preemphasis_lane0_ce12=0x254B00 +serdes_preemphasis_lane1_ce12=0x254B00 +serdes_preemphasis_lane2_ce12=0x254B00 +serdes_preemphasis_lane3_ce12=0x254B00 + +serdes_driver_current_lane0_ce13=0x8 +serdes_driver_current_lane1_ce13=0x8 +serdes_driver_current_lane2_ce13=0x8 +serdes_driver_current_lane3_ce13=0x8 +serdes_preemphasis_lane0_ce13=0x254B00 +serdes_preemphasis_lane1_ce13=0x254B00 +serdes_preemphasis_lane2_ce13=0x254B00 +serdes_preemphasis_lane3_ce13=0x254B00 + +serdes_driver_current_lane0_ce14=0x7 +serdes_driver_current_lane1_ce14=0x7 +serdes_driver_current_lane2_ce14=0x7 +serdes_driver_current_lane3_ce14=0x7 +serdes_preemphasis_lane0_ce14=0x254B00 +serdes_preemphasis_lane1_ce14=0x254B00 +serdes_preemphasis_lane2_ce14=0x254B00 +serdes_preemphasis_lane3_ce14=0x254B00 + +serdes_driver_current_lane0_ce15=0x7 +serdes_driver_current_lane1_ce15=0x5 +serdes_driver_current_lane2_ce15=0x7 +serdes_driver_current_lane3_ce15=0x7 +serdes_preemphasis_lane0_ce15=0x254B00 +serdes_preemphasis_lane1_ce15=0x254B00 +serdes_preemphasis_lane2_ce15=0x254B00 +serdes_preemphasis_lane3_ce15=0x254B00 + +serdes_driver_current_lane0_ce16=0x4 +serdes_driver_current_lane1_ce16=0x4 +serdes_driver_current_lane2_ce16=0x4 +serdes_driver_current_lane3_ce16=0x4 +serdes_preemphasis_lane0_ce16=0x274900 +serdes_preemphasis_lane1_ce16=0x274900 +serdes_preemphasis_lane2_ce16=0x274900 +serdes_preemphasis_lane3_ce16=0x274900 + +serdes_driver_current_lane0_ce17=0x8 +serdes_driver_current_lane1_ce17=0xF +serdes_driver_current_lane2_ce17=0xF +serdes_driver_current_lane3_ce17=0xF +serdes_preemphasis_lane0_ce17=0x254B00 +serdes_preemphasis_lane1_ce17=0x304000 +serdes_preemphasis_lane2_ce17=0x304000 +serdes_preemphasis_lane3_ce17=0x304000 + +serdes_driver_current_lane0_ce18=0x2 +serdes_driver_current_lane1_ce18=0x2 +serdes_driver_current_lane2_ce18=0x2 +serdes_driver_current_lane3_ce18=0x2 +serdes_preemphasis_lane0_ce18=0x205000 +serdes_preemphasis_lane1_ce18=0x205000 +serdes_preemphasis_lane2_ce18=0x205000 +serdes_preemphasis_lane3_ce18=0x205000 + +serdes_driver_current_lane0_ce19=0x2 +serdes_driver_current_lane1_ce19=0x2 +serdes_driver_current_lane2_ce19=0x2 +serdes_driver_current_lane3_ce19=0x2 +serdes_preemphasis_lane0_ce19=0x205000 +serdes_preemphasis_lane1_ce19=0x205000 +serdes_preemphasis_lane2_ce19=0x205000 +serdes_preemphasis_lane3_ce19=0x205000 + +serdes_driver_current_lane0_ce20=0x2 +serdes_driver_current_lane1_ce20=0x2 +serdes_driver_current_lane2_ce20=0x2 +serdes_driver_current_lane3_ce20=0x2 +serdes_preemphasis_lane0_ce20=0x205000 +serdes_preemphasis_lane1_ce20=0x205000 +serdes_preemphasis_lane2_ce20=0x205000 +serdes_preemphasis_lane3_ce20=0x205000 + +serdes_driver_current_lane0_ce21=0x4 +serdes_driver_current_lane1_ce21=0x2 +serdes_driver_current_lane2_ce21=0x2 +serdes_driver_current_lane3_ce21=0x2 +serdes_preemphasis_lane0_ce21=0x175900 +serdes_preemphasis_lane1_ce21=0x175900 +serdes_preemphasis_lane2_ce21=0x205000 +serdes_preemphasis_lane3_ce21=0x205000 + +serdes_driver_current_lane0_ce22=0x7 +serdes_driver_current_lane1_ce22=0x7 +serdes_driver_current_lane2_ce22=0x7 +serdes_driver_current_lane3_ce22=0x7 +serdes_preemphasis_lane0_ce22=0x254B00 +serdes_preemphasis_lane1_ce22=0x254B00 +serdes_preemphasis_lane2_ce22=0x254B00 +serdes_preemphasis_lane3_ce22=0x254B00 + +serdes_driver_current_lane0_ce23=0x7 +serdes_driver_current_lane1_ce23=0x7 +serdes_driver_current_lane2_ce23=0x7 +serdes_driver_current_lane3_ce23=0x7 +serdes_preemphasis_lane0_ce23=0x254B00 +serdes_preemphasis_lane1_ce23=0x254B00 +serdes_preemphasis_lane2_ce23=0x254B00 +serdes_preemphasis_lane3_ce23=0x254B00 + +serdes_driver_current_lane0_ce24=0xF +serdes_driver_current_lane1_ce24=0x8 +serdes_driver_current_lane2_ce24=0xF +serdes_driver_current_lane3_ce24=0x4 +serdes_preemphasis_lane0_ce24=0x153C1F +serdes_preemphasis_lane1_ce24=0x294700 +serdes_preemphasis_lane2_ce24=0x153C1F +serdes_preemphasis_lane3_ce24=0x294700 + +serdes_driver_current_lane0_ce25=0xF +serdes_driver_current_lane1_ce25=0x8 +serdes_driver_current_lane2_ce25=0xF +serdes_driver_current_lane3_ce25=0x4 +serdes_preemphasis_lane0_ce25=0x153C1F +serdes_preemphasis_lane1_ce25=0x294700 +serdes_preemphasis_lane2_ce25=0x153C1F +serdes_preemphasis_lane3_ce25=0x294700 + +serdes_driver_current_lane0_ce26=0xF +serdes_driver_current_lane1_ce26=0xA +serdes_driver_current_lane2_ce26=0xF +serdes_driver_current_lane3_ce26=0x9 +serdes_preemphasis_lane0_ce26=0x153C1F +serdes_preemphasis_lane1_ce26=0x304000 +serdes_preemphasis_lane2_ce26=0x153C1F +serdes_preemphasis_lane3_ce26=0x304000 + +serdes_driver_current_lane0_ce27=0xF +serdes_driver_current_lane1_ce27=0x9 +serdes_driver_current_lane2_ce27=0xF +serdes_driver_current_lane3_ce27=0x9 +serdes_preemphasis_lane0_ce27=0x153C1F +serdes_preemphasis_lane1_ce27=0x304000 +serdes_preemphasis_lane2_ce27=0x153C1F +serdes_preemphasis_lane3_ce27=0x304000 + +serdes_driver_current_lane0_ce28=0xF +serdes_driver_current_lane1_ce28=0xC +serdes_driver_current_lane2_ce28=0xF +serdes_driver_current_lane3_ce28=0xC +serdes_preemphasis_lane0_ce28=0x153C1F +serdes_preemphasis_lane1_ce28=0x183C10 +serdes_preemphasis_lane2_ce28=0x153C1F +serdes_preemphasis_lane3_ce28=0x1C3C10 + +serdes_driver_current_lane0_ce29=0xF +serdes_driver_current_lane1_ce29=0xC +serdes_driver_current_lane2_ce29=0xF +serdes_driver_current_lane3_ce29=0xC +serdes_preemphasis_lane0_ce29=0x153C1F +serdes_preemphasis_lane1_ce29=0x203C10 +serdes_preemphasis_lane2_ce29=0x153C1F +serdes_preemphasis_lane3_ce29=0x203C10 + +serdes_driver_current_lane0_ce30=0xF +serdes_driver_current_lane1_ce30=0xC +serdes_driver_current_lane2_ce30=0xF +serdes_driver_current_lane3_ce30=0xC +serdes_preemphasis_lane0_ce30=0x153C1F +serdes_preemphasis_lane1_ce30=0x243C10 +serdes_preemphasis_lane2_ce30=0x153C1F +serdes_preemphasis_lane3_ce30=0x243C08 + +serdes_driver_current_lane0_ce31=0xF +serdes_driver_current_lane1_ce31=0xC +serdes_driver_current_lane2_ce31=0xF +serdes_driver_current_lane3_ce31=0xE +serdes_preemphasis_lane0_ce31=0x153C1F +serdes_preemphasis_lane1_ce31=0x243C10 +serdes_preemphasis_lane2_ce31=0x153C1F +serdes_preemphasis_lane3_ce31=0x203C14 + +serdes_if_type_xe=14 +serdes_if_type_ce=14 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s9100-r0/default_sku new file mode 100644 index 000000000000..1a78c849d5e5 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S9100-C32 t1 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s9100-r0/fancontrol new file mode 100644 index 000000000000..e1f88f6b79c5 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/fancontrol @@ -0,0 +1,10 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/0-002f +DEVNAME=hwmon1=w83795adg +FCTEMPS=hwmon1/device/pwm2=hwmon1/device/temp2_input hwmon1/device/pwm1=hwmon1/device/temp2_input +FCFANS=hwmon1/device/pwm2=hwmon1/device/fan8_input hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan6_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm1=hwmon1/device/fan4_input hwmon1/device/pwm1=hwmon1/device/fan3_input hwmon1/device/pwm1=hwmon1/device/fan2_input hwmon1/device/pwm1=hwmon1/device/fan1_input +MINTEMP=hwmon1/device/pwm2=20 hwmon1/device/pwm1=20 +MAXTEMP=hwmon1/device/pwm2=60 hwmon1/device/pwm1=60 +MINSTART=hwmon1/device/pwm2=75 hwmon1/device/pwm1=75 +MINSTOP=hwmon1/device/pwm2=22 hwmon1/device/pwm1=22 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s9100-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/led_proc_init.soc b/device/ingrasys/x86_64-ingrasys_s9100-r0/led_proc_init.soc new file mode 100644 index 000000000000..492d3b897851 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/led_proc_init.soc @@ -0,0 +1,43 @@ +# LED microprocessor initialization for Ingrasys S9100-32X + +led 0 stop +led 0 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28 REMAP_PORT_2=29 REMAP_PORT_1=30 REMAP_PORT_0=31 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24 REMAP_PORT_6=25 REMAP_PORT_5=26 REMAP_PORT_4=27 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=20 REMAP_PORT_10=21 REMAP_PORT_9=22 REMAP_PORT_8=23 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=16 REMAP_PORT_14=17 REMAP_PORT_13=18 REMAP_PORT_12=19 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=12 REMAP_PORT_18=13 REMAP_PORT_17=14 REMAP_PORT_16=15 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=8 REMAP_PORT_22=9 REMAP_PORT_21=10 REMAP_PORT_20=11 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=4 REMAP_PORT_26=5 REMAP_PORT_25=6 REMAP_PORT_24=7 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0 REMAP_PORT_30=1 REMAP_PORT_29=2 REMAP_PORT_28=3 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=60 REMAP_PORT_34=61 REMAP_PORT_33=62 REMAP_PORT_32=63 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=56 REMAP_PORT_38=57 REMAP_PORT_37=58 REMAP_PORT_36=59 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52 REMAP_PORT_42=53 REMAP_PORT_41=54 REMAP_PORT_40=55 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48 REMAP_PORT_46=49 REMAP_PORT_45=50 REMAP_PORT_44=51 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=44 REMAP_PORT_50=45 REMAP_PORT_49=46 REMAP_PORT_48=47 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=40 REMAP_PORT_54=41 REMAP_PORT_53=42 REMAP_PORT_52=43 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=36 REMAP_PORT_58=37 REMAP_PORT_57=38 REMAP_PORT_56=39 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=32 REMAP_PORT_62=33 REMAP_PORT_61=34 REMAP_PORT_60=35 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=8 REMAP_PORT_10=9 REMAP_PORT_9=10 REMAP_PORT_8=11 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=12 REMAP_PORT_14=13 REMAP_PORT_13=14 REMAP_PORT_12=15 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=16 REMAP_PORT_18=17 REMAP_PORT_17=18 REMAP_PORT_16=19 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=20 REMAP_PORT_22=21 REMAP_PORT_21=22 REMAP_PORT_20=23 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=24 REMAP_PORT_26=25 REMAP_PORT_25=26 REMAP_PORT_24=27 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=28 REMAP_PORT_30=29 REMAP_PORT_29=30 REMAP_PORT_28=31 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=32 REMAP_PORT_34=33 REMAP_PORT_33=34 REMAP_PORT_32=35 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=36 REMAP_PORT_38=37 REMAP_PORT_37=38 REMAP_PORT_36=39 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40 REMAP_PORT_42=41 REMAP_PORT_41=42 REMAP_PORT_40=43 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44 REMAP_PORT_46=45 REMAP_PORT_45=46 REMAP_PORT_44=47 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=48 REMAP_PORT_50=49 REMAP_PORT_49=50 REMAP_PORT_48=51 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=52 REMAP_PORT_54=53 REMAP_PORT_53=54 REMAP_PORT_52=55 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=56 REMAP_PORT_58=57 REMAP_PORT_57=58 REMAP_PORT_56=59 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=60 REMAP_PORT_62=61 REMAP_PORT_61=62 REMAP_PORT_60=63 +led 1 auto on +led 1 start diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/eeprom.py new file mode 100644 index 000000000000..83bf65a389bd --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Ingrasys S9100 +# +# 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-9/9-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/psuutil.py new file mode 100644 index 000000000000..4f226c69fff3 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/psuutil.py @@ -0,0 +1,92 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_CPLD_DIR = "/sys/bus/i2c/devices/0-0033" + + def __init__(self): + PsuBase.__init__(self) + + + # Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + mask = [ 0x08, 0x10 ] + attr_file = 'cpld_pw_good' + attr_path = self.PSU_CPLD_DIR +'/'+ attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU status + if (attr_value & mask[index-1]): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + mask = [ 0x01, 0x02 ] + attr_file ='cpld_pw_abs' + attr_path = self.PSU_CPLD_DIR +'/'+ attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU presence + if (~attr_value & mask[index-1]): + status = 1 + + return status + diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/sfputil.py new file mode 100644 index 000000000000..849bd13d94d3 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/sfputil.py @@ -0,0 +1,324 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +import os + +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 = 31 + PORTS_IN_BLOCK = 32 + GPIO_OFFSET = 0 + + BASE_DIR_PATH = "/sys/class/gpio/gpio{0}/direction" + BASE_VAL_PATH = "/sys/class/gpio/gpio{0}/value" + + _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 + } + + abs_to_gpio_mapping = {} + lpmode_to_gpio_mapping = {} + reset_to_gpio_mapping = {} + + @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 port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def set_gpio_offset(self): + sys_gpio_dir = "/sys/class/gpio" + self.GPIO_OFFSET = 0 + gpiochip_no = 0 + for d in os.listdir(sys_gpio_dir): + if "gpiochip" in d: + try: + gpiochip_no = int(d[8:],10) + except ValueError as e: + print "Error: %s" % str(e) + if gpiochip_no > 255: + self.GPIO_OFFSET=256 + return True + return True + + def init_abs_to_gpio_mapping(self): + self.abs_to_gpio_mapping = { + 0: 241+self.GPIO_OFFSET, + 1: 240+self.GPIO_OFFSET, + 2: 243+self.GPIO_OFFSET, + 3: 242+self.GPIO_OFFSET, + 4: 245+self.GPIO_OFFSET, + 5: 244+self.GPIO_OFFSET, + 6: 247+self.GPIO_OFFSET, + 7: 246+self.GPIO_OFFSET, + 8: 249+self.GPIO_OFFSET, + 9: 248+self.GPIO_OFFSET, + 10: 251+self.GPIO_OFFSET, + 11: 250+self.GPIO_OFFSET, + 12: 253+self.GPIO_OFFSET, + 13: 252+self.GPIO_OFFSET, + 14: 255+self.GPIO_OFFSET, + 15: 254+self.GPIO_OFFSET, + 16: 225+self.GPIO_OFFSET, + 17: 224+self.GPIO_OFFSET, + 18: 227+self.GPIO_OFFSET, + 19: 226+self.GPIO_OFFSET, + 20: 229+self.GPIO_OFFSET, + 21: 228+self.GPIO_OFFSET, + 22: 231+self.GPIO_OFFSET, + 23: 230+self.GPIO_OFFSET, + 24: 233+self.GPIO_OFFSET, + 25: 232+self.GPIO_OFFSET, + 26: 235+self.GPIO_OFFSET, + 27: 234+self.GPIO_OFFSET, + 28: 237+self.GPIO_OFFSET, + 29: 236+self.GPIO_OFFSET, + 30: 239+self.GPIO_OFFSET, + 31: 238+self.GPIO_OFFSET + } + return True + + def init_lpmode_to_gpio_mapping(self): + self.lpmode_to_gpio_mapping = { + 0: 177+self.GPIO_OFFSET, + 1: 176+self.GPIO_OFFSET, + 2: 179+self.GPIO_OFFSET, + 3: 178+self.GPIO_OFFSET, + 4: 181+self.GPIO_OFFSET, + 5: 180+self.GPIO_OFFSET, + 6: 183+self.GPIO_OFFSET, + 7: 182+self.GPIO_OFFSET, + 8: 185+self.GPIO_OFFSET, + 9: 184+self.GPIO_OFFSET, + 10: 187+self.GPIO_OFFSET, + 11: 186+self.GPIO_OFFSET, + 12: 189+self.GPIO_OFFSET, + 13: 188+self.GPIO_OFFSET, + 14: 191+self.GPIO_OFFSET, + 15: 190+self.GPIO_OFFSET, + 16: 161+self.GPIO_OFFSET, + 17: 160+self.GPIO_OFFSET, + 18: 163+self.GPIO_OFFSET, + 19: 162+self.GPIO_OFFSET, + 20: 165+self.GPIO_OFFSET, + 21: 164+self.GPIO_OFFSET, + 22: 167+self.GPIO_OFFSET, + 23: 166+self.GPIO_OFFSET, + 24: 169+self.GPIO_OFFSET, + 25: 168+self.GPIO_OFFSET, + 26: 171+self.GPIO_OFFSET, + 27: 170+self.GPIO_OFFSET, + 28: 173+self.GPIO_OFFSET, + 29: 172+self.GPIO_OFFSET, + 30: 175+self.GPIO_OFFSET, + 31: 174+self.GPIO_OFFSET + } + return True + + def init_reset_to_gpio_mapping(self): + self.reset_to_gpio_mapping = { + 0: 145+self.GPIO_OFFSET, + 1: 144+self.GPIO_OFFSET, + 2: 147+self.GPIO_OFFSET, + 3: 146+self.GPIO_OFFSET, + 4: 149+self.GPIO_OFFSET, + 5: 148+self.GPIO_OFFSET, + 6: 151+self.GPIO_OFFSET, + 7: 150+self.GPIO_OFFSET, + 8: 153+self.GPIO_OFFSET, + 9: 152+self.GPIO_OFFSET, + 10: 155+self.GPIO_OFFSET, + 11: 154+self.GPIO_OFFSET, + 12: 157+self.GPIO_OFFSET, + 13: 156+self.GPIO_OFFSET, + 14: 159+self.GPIO_OFFSET, + 15: 158+self.GPIO_OFFSET, + 16: 129+self.GPIO_OFFSET, + 17: 128+self.GPIO_OFFSET, + 18: 131+self.GPIO_OFFSET, + 19: 130+self.GPIO_OFFSET, + 20: 133+self.GPIO_OFFSET, + 21: 132+self.GPIO_OFFSET, + 22: 135+self.GPIO_OFFSET, + 23: 134+self.GPIO_OFFSET, + 24: 137+self.GPIO_OFFSET, + 25: 136+self.GPIO_OFFSET, + 26: 139+self.GPIO_OFFSET, + 27: 138+self.GPIO_OFFSET, + 28: 141+self.GPIO_OFFSET, + 29: 140+self.GPIO_OFFSET, + 30: 143+self.GPIO_OFFSET, + 31: 142+self.GPIO_OFFSET + } + return True + + def __init__(self): + # Init abs, lpmode, and reset to gpio mapping + self.set_gpio_offset() + self.init_abs_to_gpio_mapping() + self.init_lpmode_to_gpio_mapping() + self.init_reset_to_gpio_mapping() + + # 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): + 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: + abs_device_file = self.BASE_VAL_PATH.format( + self.abs_to_gpio_mapping[port_num]) + val_file = open(abs_device_file) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + 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: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + 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: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("1" if lpmode is True else "0") + val_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 + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("1") + val_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("0") + val_file.close() + + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s9100-r0/sensors.conf new file mode 100644 index 000000000000..5535db7e7eb4 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/sensors.conf @@ -0,0 +1,49 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + label temp1 "DIMM Temp" + set temp1_max 50 + set temp1_crit 85 + +chip "w83795adg-*" + label in0 "1.0V" + set in0_min 1.00 * 0.97 + set in0_max 1.00 * 1.03 + label in1 "1.0V_ROV" + set in1_min 1.00 * 0.98 + set in1_max 1.00 * 1.02 + label in2 "1.25V" + set in2_min 1.25 * 0.97 + set in2_max 1.25 * 1.03 + label in3 "1.8V" + set in3_min 1.80 * 0.97 + set in3_max 1.80 * 1.03 + ignore in4 + ignore in5 + ignore in6 + ignore in7 + label in12 "+3.3V" + set in12_min 3.30 * 0.97 + set in12_max 3.30 * 1.03 + ignore in14 + ignore in15 + ignore in16 + label fan1 "FANTRAY 1-A" + label fan2 "FANTRAY 1-B" + label fan3 "FANTRAY 2-A" + label fan4 "FANTRAY 2-B" + label fan5 "FANTRAY 3-A" + label fan6 "FANTRAY 3-B" + label fan7 "FANTRAY 4-A" + label fan8 "FANTRAY 4-B" + label temp1 "Front MAC Temp" + set temp1_max 70 + set temp1_crit 80 + label temp2 "Rear MAC Temp" + set temp2_max 70 + set temp2_crit 80 + ignore temp3 + ignore temp4 + ignore intrusion0 diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers.json.j2 b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers.json.j2 new file mode 100644 index 000000000000..9354b7ec5b59 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers_defaults_t0.j2 b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..b008aa892bc1 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers_defaults_t0.j2 @@ -0,0 +1,69 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20971328' %} +{% set ingress_lossy_pool_size = '20971328' %} +{% set egress_lossless_pool_size = '20971328' %} +{% set egress_lossy_pool_size = '20971328' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0, 32) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx*4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xon":"78400", + "xoff":"132160", + "size":"3584", + "static_th":"82880" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"3584", + "dynamic_th":"-1" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"3584", + "dynamic_th":"-4" + } + }, +{%- endmacro %} + +{# the typo of generate_pg_profils dued to buffers_config.j2 #} +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + } +{%- endmacro %} + +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + } +{%- endmacro %} \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers_defaults_t1.j2 b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..b008aa892bc1 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers_defaults_t1.j2 @@ -0,0 +1,69 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20971328' %} +{% set ingress_lossy_pool_size = '20971328' %} +{% set egress_lossless_pool_size = '20971328' %} +{% set egress_lossy_pool_size = '20971328' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0, 32) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx*4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xon":"78400", + "xoff":"132160", + "size":"3584", + "static_th":"82880" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"3584", + "dynamic_th":"-1" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"3584", + "dynamic_th":"-4" + } + }, +{%- endmacro %} + +{# the typo of generate_pg_profils dued to buffers_config.j2 #} +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + } +{%- endmacro %} + +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + } +{%- endmacro %} \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/pg_profile_lookup.ini b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/pg_profile_lookup.ini new file mode 100644 index 000000000000..d98b0eca6d19 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 3584 32256 59136 36736 + 25000 5m 3584 41216 68096 45696 + 40000 5m 3584 47488 74368 51968 + 50000 5m 3584 52864 79744 57344 + 100000 5m 3584 78400 132160 82880 + 10000 40m 3584 32256 59136 36736 + 25000 40m 3584 41216 68096 45696 + 40000 40m 3584 47488 74368 51968 + 50000 40m 3584 52864 79744 57344 + 100000 40m 3584 78400 132160 82880 + 10000 300m 3584 32256 65856 36736 + 25000 300m 3584 41216 84672 45696 + 40000 300m 3584 47488 101024 51968 + 50000 300m 3584 52864 113120 57344 + 100000 300m 3584 78400 198688 82880 \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/port_config.ini b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/port_config.ini new file mode 100644 index 000000000000..bb26684cb7da --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 0,1,2,3 Ethernet1/1 0 +Ethernet4 4,5,6,7 Ethernet2/1 1 +Ethernet8 8,9,10,11 Ethernet3/1 2 +Ethernet12 12,13,14,15 Ethernet4/1 3 +Ethernet16 16,17,18,19 Ethernet5/1 4 +Ethernet20 20,21,22,23 Ethernet6/1 5 +Ethernet24 24,25,26,27 Ethernet7/1 6 +Ethernet28 28,29,30,31 Ethernet8/1 7 +Ethernet32 32,33,34,35 Ethernet9/1 8 +Ethernet36 36,37,38,39 Ethernet10/1 9 +Ethernet40 40,41,42,43 Ethernet11/1 10 +Ethernet44 44,45,46,47 Ethernet12/1 11 +Ethernet48 48,49,50,51 Ethernet13/1 12 +Ethernet52 52,53,54,55 Ethernet14/1 13 +Ethernet56 56,57,58,59 Ethernet15/1 14 +Ethernet60 60,61,62,63 Ethernet16/1 15 +Ethernet64 64,65,66,67 Ethernet17/1 16 +Ethernet68 68,69,70,71 Ethernet18/1 17 +Ethernet72 72,73,74,75 Ethernet19/1 18 +Ethernet76 76,77,78,79 Ethernet20/1 19 +Ethernet80 80,81,82,83 Ethernet21/1 20 +Ethernet84 84,85,86,87 Ethernet22/1 21 +Ethernet88 88,89,90,91 Ethernet23/1 22 +Ethernet92 92,93,94,95 Ethernet24/1 23 +Ethernet96 96,97,98,99 Ethernet25/1 24 +Ethernet100 100,101,102,103 Ethernet26/1 25 +Ethernet104 104,105,106,107 Ethernet27/1 26 +Ethernet108 108,109,110,111 Ethernet28/1 27 +Ethernet112 112,113,114,115 Ethernet29/1 28 +Ethernet116 116,117,118,119 Ethernet30/1 29 +Ethernet120 120,121,122,123 Ethernet31/1 30 +Ethernet124 124,125,126,127 Ethernet32/1 31 diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/port_config.nps b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/port_config.nps new file mode 100644 index 000000000000..49068859b25c --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/port_config.nps @@ -0,0 +1,352 @@ +init start stage unit=0 low-level +init set port-map unit=0 port=0 eth-macro=0 lane=0 max-speed=100g active=true +init set port-map unit=0 port=1 eth-macro=1 lane=0 max-speed=100g active=true +init set port-map unit=0 port=2 eth-macro=2 lane=0 max-speed=100g active=true +init set port-map unit=0 port=3 eth-macro=3 lane=0 max-speed=100g active=true +init set port-map unit=0 port=4 eth-macro=4 lane=0 max-speed=100g active=true +init set port-map unit=0 port=5 eth-macro=5 lane=0 max-speed=100g active=true +init set port-map unit=0 port=6 eth-macro=6 lane=0 max-speed=100g active=true +init set port-map unit=0 port=7 eth-macro=7 lane=0 max-speed=100g active=true +init set port-map unit=0 port=8 eth-macro=8 lane=0 max-speed=100g active=true +init set port-map unit=0 port=9 eth-macro=9 lane=0 max-speed=100g active=true +init set port-map unit=0 port=10 eth-macro=10 lane=0 max-speed=100g active=true +init set port-map unit=0 port=11 eth-macro=11 lane=0 max-speed=100g active=true +init set port-map unit=0 port=12 eth-macro=12 lane=0 max-speed=100g active=true +init set port-map unit=0 port=13 eth-macro=13 lane=0 max-speed=100g active=true +init set port-map unit=0 port=14 eth-macro=14 lane=0 max-speed=100g active=true +init set port-map unit=0 port=15 eth-macro=15 lane=0 max-speed=100g active=true +init set port-map unit=0 port=16 eth-macro=16 lane=0 max-speed=100g active=true +init set port-map unit=0 port=17 eth-macro=17 lane=0 max-speed=100g active=true +init set port-map unit=0 port=18 eth-macro=18 lane=0 max-speed=100g active=true +init set port-map unit=0 port=19 eth-macro=19 lane=0 max-speed=100g active=true +init set port-map unit=0 port=20 eth-macro=20 lane=0 max-speed=100g active=true +init set port-map unit=0 port=21 eth-macro=21 lane=0 max-speed=100g active=true +init set port-map unit=0 port=22 eth-macro=22 lane=0 max-speed=100g active=true +init set port-map unit=0 port=23 eth-macro=23 lane=0 max-speed=100g active=true +init set port-map unit=0 port=24 eth-macro=24 lane=0 max-speed=100g active=true +init set port-map unit=0 port=25 eth-macro=25 lane=0 max-speed=100g active=true +init set port-map unit=0 port=26 eth-macro=26 lane=0 max-speed=100g active=true +init set port-map unit=0 port=27 eth-macro=27 lane=0 max-speed=100g active=true +init set port-map unit=0 port=28 eth-macro=28 lane=0 max-speed=100g active=true +init set port-map unit=0 port=29 eth-macro=29 lane=0 max-speed=100g active=true +init set port-map unit=0 port=30 eth-macro=30 lane=0 max-speed=100g active=true +init set port-map unit=0 port=31 eth-macro=31 lane=0 max-speed=100g active=true +init set port-map unit=0 port=129 eth-macro=0 lane=1 max-speed=10g active=true guarantee=true cpi=true +init set port-map unit=0 port=130 eth-macro=0 lane=0 max-speed=10g active=true guarantee=true cpi=true init-done=true +init start stage unit=0 task-rsrc +init start stage unit=0 module +init start stage unit=0 task +phy set lane-swap unit=0 portlist=0 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=1 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=2 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=3 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=4 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=5 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=6 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=7 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=8 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=9 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=10 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=11 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=12 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=13 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=14 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=15 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=16 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=17 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=18 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=19 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=20 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=21 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=22 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=23 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=24 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=25 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=26 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=27 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=28 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=29 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=30 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=31 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=129 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=130 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=0 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=1 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=2 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=3 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=4 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=5 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=6 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=7 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=8 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=9 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=10 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=11 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=12 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=13 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=14 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=15 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=16 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=17 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=18 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=19 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=20 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=21 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=22 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=23 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=24 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=25 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=26 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=27 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=28 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=29 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=30 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=31 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=129 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=130 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=0 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=1 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=2 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=3 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=4 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=5 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=6 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=7 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=8 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=9 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=10 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=11 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=12 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=13 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=14 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=15 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=16 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=17 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=18 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=19 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=20 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=21 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=22 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=23 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=24 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=25 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=26 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=27 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=28 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=29 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=30 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=31 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=129 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=130 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=0 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=1 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=2 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=3 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=4 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=5 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=6 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=7 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=8 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=9 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=10 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=11 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=12 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=13 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=14 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=15 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=16 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=17 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=18 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=19 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=20 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=21 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=22 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=23 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=24 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=25 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=26 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=27 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=28 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=29 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=30 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=31 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=129 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=130 lane-cnt=1 property=rx data=0x0 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=4 property=cn1 data=0x01.01.01.01 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=4 property=c0 data=0x1A.1A.1A.1A +phy set pre-emphasis unit=0 portlist=0 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=4 property=c0 data=0x1A.1A.1A.1A +phy set pre-emphasis unit=0 portlist=1 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=4 property=cn1 data=0x01.01.01.01 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=2 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=3 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=4 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=5 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=4 property=c2 data=0x03.03.03.03 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=6 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=7 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=8 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=9 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=10 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=4 property=cn1 data=0x01.01.01.01 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=11 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=12 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=13 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=4 property=c0 data=0x1D.1D.1D.1D +phy set pre-emphasis unit=0 portlist=14 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=15 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=16 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=17 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=18 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=19 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=20 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=21 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=22 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=23 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=24 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=25 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=26 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=27 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=28 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=4 property=c0 data=0x1A.1A.1A.1A +phy set pre-emphasis unit=0 portlist=29 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=4 property=cn1 data=0x01.01.01.01 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=4 property=c0 data=0x1A.1A.1A.1A +phy set pre-emphasis unit=0 portlist=30 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=4 property=c2 data=0x01.01.01.01 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=4 property=cn1 data=0x03.03.03.03 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c2 data=0x01 +phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=cn1 data=0x01 +phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c0 data=0x02 +phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c1 data=0x03 +phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=c2 data=0x01 +phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=cn1 data=0x01 +phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=c0 data=0x02 +phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=c1 data=0x03 +phy set mdio portlist=0 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=1 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=2 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=3 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=4 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=5 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=6 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=7 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=8 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=9 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=10 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=11 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=12 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=13 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=14 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=15 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=16 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=17 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=18 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=19 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=20 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=21 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=22 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=23 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=24 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=25 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=26 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=27 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=28 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=29 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=30 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=31 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=129 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=130 devad=0x1E addr=0x2 data=0x0000 +port set property unit=0 portlist=0-31 speed=100g +port set property unit=0 portlist=129-130 speed=10g +port set property unit=0 portlist=0-31 medium-type=sr4 +port set property unit=0 portlist=129-130 medium-type=kr +port set property unit=0 portlist=0-31 fec=disable +port set adver unit=0 portlist=129-130 speed-10g-kr +port set property unit=0 portlist=129-130 an=enable +port set property unit=0 portlist=0-31,129-130 admin=enable diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/qos.json.j2 b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/qos.json.j2 new file mode 100644 index 000000000000..42eef17c362b --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/qos.json.j2 @@ -0,0 +1,136 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "1", + "1": "0", + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "1", + "1": "0", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"1", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + }, + "WRED_PROFILE": { + "AZURE_LOSSY" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"516096", + "red_min_threshold":"516096", + "yellow_max_threshold":"516096", + "yellow_min_threshold":"516096", + "green_max_threshold": "184128", + "green_min_threshold": "184128" + }, + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"516096", + "red_min_threshold":"516096", + "yellow_max_threshold":"516096", + "yellow_min_threshold":"516096", + "green_max_threshold": "184128", + "green_min_threshold": "184128" + } + }, + "QUEUE": { + } +} diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/sai.profile b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/sai.profile new file mode 100644 index 000000000000..880f47910ac1 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/led_proc_init.nps +SAI_DSH_CONFIG_FILE=/usr/share/sonic/hwsku/port_config.nps diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/default_sku new file mode 100644 index 000000000000..2464f73308e3 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S9130-32X t1 diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/fancontrol new file mode 100644 index 000000000000..5ed165966b93 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/fancontrol @@ -0,0 +1,12 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon5=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-8/8-002f +DEVNAME=hwmon5=w83795adg +FCTEMPS=hwmon5/device/pwm2=hwmon1/temp1_input hwmon5/device/pwm1=hwmon1/temp1_input +FCFANS=hwmon5/device/pwm2=hwmon5/device/fan8_input hwmon5/device/pwm2=hwmon5/device/fan7_input hwmon5/device/pwm2=hwmon5/device/fan6_input hwmon5/device/pwm2=hwmon5/device/fan5_input hwmon5/device/pwm1=hwmon5/device/fan4_input hwmon5/device/pwm1=hwmon5/device/fan3_input hwmon5/device/pwm1=hwmon5/device/fan2_input hwmon5/device/pwm1=hwmon5/device/fan1_input +# TODO: check the temp value with HW after board ready +MINTEMP=hwmon5/device/pwm2=20 hwmon5/device/pwm1=20 +MAXTEMP=hwmon5/device/pwm2=60 hwmon5/device/pwm1=60 +MINSTART=hwmon5/device/pwm2=75 hwmon5/device/pwm1=75 +MINSTOP=hwmon5/device/pwm2=22 hwmon5/device/pwm1=22 + diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/led_proc_init.nps b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/led_proc_init.nps new file mode 100644 index 000000000000..d1695e36b59a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/led_proc_init.nps @@ -0,0 +1,9 @@ +#unit NPS_CFG_TYPE_XXX param0 param1 value +#---- ---------------- ------ ------ ----- +0 NPS_CFG_TYPE_USE_UNIT_PORT 0 0 1 +0 NPS_CFG_TYPE_LED_CFG 0 0 1 +0 NPS_CFG_TYPE_CPI_PORT_MODE 129 0 1 +0 NPS_CFG_TYPE_CPI_PORT_MODE 130 0 1 +0 NPS_CFG_TYPE_USER_BUF_CTRL 0 0 1 +0 NPS_CFG_TYPE_HASH_L2_FDB_REGION_ENTRY_NUM 0 0 49152 +0 NPS_CFG_TYPE_HASH_L3_WITH_IPV6_PREFIX_64_REGION_ENTRY_NUM 0 0 32768 diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..71ce941f1abb --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Ingrasys S9130-32X +# +# 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-0051/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..4a029c15b1a6 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/psuutil.py @@ -0,0 +1,92 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/i2c-10/10-0050", + "/sys/bus/i2c/devices/i2c-9/9-0050"] + + def __init__(self): + PsuBase.__init__(self) + + + # Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + attr_file = 'psu_pg' + attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU status + if (attr_value == 1): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_absent = 0 + attr_file ='psu_abs' + attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU presence + if (attr_value == 0): + status = 1 + + return status + diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..4827ad3bfa80 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/sfputil.py @@ -0,0 +1,220 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +import os + +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 = 31 + PORTS_IN_BLOCK = 32 + EEPROM_OFFSET = 21 + ABS_GPIO_BASE_0_15 = 240 + ABS_GPIO_BASE_16_31 = 224 + LP_MODE_GPIO_BASE_0_15 = 176 + LP_MODE_GPIO_BASE_16_31 = 160 + RST_GPIO_BASE_0_15 = 144 + RST_GPIO_BASE_16_31 = 128 + GPIO_OFFSET = 0 + + GPIO_VAL_PATH = "/sys/class/gpio/gpio{0}/value" + + _port_to_eeprom_mapping = {} + + @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 port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def set_gpio_offset(self): + sys_gpio_dir = "/sys/class/gpio" + self.GPIO_OFFSET = 0 + gpiochip_no = 0 + for d in os.listdir(sys_gpio_dir): + if "gpiochip" in d: + try: + gpiochip_no = int(d[8:],10) + except ValueError as e: + print "Error: %s" % str(e) + if gpiochip_no > 255: + self.GPIO_OFFSET=256 + return True + return True + + def update_gpio_base(self): + self.ABS_GPIO_BASE_0_15 = 240 + self.GPIO_OFFSET + self.ABS_GPIO_BASE_16_31 = 224 + self.GPIO_OFFSET + self.LP_MODE_GPIO_BASE_0_15 = 176 + self.GPIO_OFFSET + self.LP_MODE_GPIO_BASE_16_31 = 160 + self.GPIO_OFFSET + self.RST_GPIO_BASE_0_15 = 144 + self.GPIO_OFFSET + self.RST_GPIO_BASE_16_31 = 128 + self.GPIO_OFFSET + return True + + def __init__(self): + # Update abs, lpmode, and reset gpio base + self.set_gpio_offset() + self.update_gpio_base() + + # 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): + port_eeprom_path = eeprom_path.format(x + self.EEPROM_OFFSET) + 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 + + # open corrsponding gpio file + try: + if port_num <= 15: + gpio_base = self.ABS_GPIO_BASE_0_15 + else : + gpio_base = self.ABS_GPIO_BASE_16_31 + gpio_index = gpio_base + (port_num % 16) + gpio_file_path = self.GPIO_VAL_PATH.format(gpio_index) + gpio_file = open(gpio_file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # content is a string containing the gpio value + gpio_val = int(gpio_file.readline().rstrip()) + gpio_file.close() + + # the gpio pin is ACTIVE_LOW but reversed + if gpio_val == 0: + return False + + return True + + 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 + + # open corrsponding gpio file + try: + if port_num <= 15: + gpio_base = self.LP_MODE_GPIO_BASE_0_15 + else : + gpio_base = self.LP_MODE_GPIO_BASE_16_31 + gpio_index = gpio_base + (port_num % 16) + gpio_file_path = self.GPIO_VAL_PATH.format(gpio_index) + gpio_file = open(gpio_file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # content is a string containing the gpio value + gpio_val = int(gpio_file.readline().rstrip()) + gpio_file.close() + + if gpio_val == 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 + + # open corrsponding gpio file + try: + if port_num <= 15: + gpio_base = self.LP_MODE_GPIO_BASE_0_15 + else : + gpio_base = self.LP_MODE_GPIO_BASE_16_31 + gpio_index = gpio_base + (port_num % 16) + gpio_file_path = self.GPIO_VAL_PATH.format(gpio_index) + gpio_file = open(gpio_file_path, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # the gpio pin is ACTIVE_HIGH + if lpmode is True: + gpio_val = "1" + else: + gpio_val = "0" + + # write value to gpio + gpio_file.seek(0) + gpio_file.write(gpio_val) + gpio_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 + + # open corrsponding gpio file + try: + if port_num <= 15: + gpio_base = self.RST_GPIO_BASE_0_15 + else : + gpio_base = self.RST_GPIO_BASE_16_31 + gpio_index = gpio_base + (port_num % 16) + gpio_file_path = self.GPIO_VAL_PATH.format(gpio_index) + gpio_file = open(gpio_file_path, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # set the gpio to take port into reset + # the gpio pin is ACTIVE_LOW but reversed + gpio_val = "1" + # write value to gpio + gpio_file.seek(0) + gpio_file.write(gpio_val) + gpio_file.close() + + # Sleep 1 second to let it settle + time.sleep(1) + + # open corrsponding gpio file + try: + gpio_file = open(gpio_file_path, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # set gpio back low to take port out of reset + # the gpio pin is ACTIVE_LOW but reversed + gpio_val = "0" + # write value to gpio + gpio_file.seek(0) + gpio_file.write(gpio_val) + gpio_file.close() + + return True + + def get_transceiver_change_event(self, timeout=0): + raise NotImplementedError diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/sensors.conf new file mode 100644 index 000000000000..9b55f73af2af --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/sensors.conf @@ -0,0 +1,69 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + +bus "i2c-8" "i2c-mux-0 (chan_id 7)" +chip "w83795adg-*" + label in0 "0.9V" + set in0_max 0.945 + set in0_min 0.855 + label in1 "VDD_CORE" + set in1_max 0.945 + set in1_min 0.855 + label in2 "1.2V" + set in2_max 1.26 + set in2_min 1.14 + label in3 "1.8V" + set in3_max 1.89 + set in3_min 1.71 + label in4 "1.01V" + set in4_max 1.0605 + set in4_min 0.9595 + ignore in5 + ignore in6 + ignore in7 + ignore in11 + label in12 "3.3VDD" + set in12_max 3.465 + set in12_min 3.135 + # in12 and in13 are the same source + ignore in13 + label fan1 "FANTRAY 1-A" + label fan2 "FANTRAY 1-B" + label fan3 "FANTRAY 2-A" + label fan4 "FANTRAY 2-B" + label fan5 "FANTRAY 3-A" + label fan6 "FANTRAY 3-B" + label fan7 "FANTRAY 4-A" + label fan8 "FANTRAY 4-B" + ignore temp1 + ignore temp2 + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore intrusion0 + +chip "tmp75-i2c-*-4A" + label temp1 "BMC board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-0" "i2c-main" +chip "tmp75-i2c-*-4F" + label temp1 "x86 CPU board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-12" "i2c-mux-1 (chan_id 3)" +chip "tmp75-i2c-*-4C" + label temp1 "rear MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +chip "tmp75-i2c-*-49" + label temp1 "front MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/port_config.ini b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/port_config.ini new file mode 100644 index 000000000000..8b25c1333a67 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias speed autoneg fec index +Ethernet0 0,1,2,3 Ethernet0 100000 0 none 0 +Ethernet4 4,5,6,7 Ethernet4 100000 0 none 1 +Ethernet8 8,9,10,11 Ethernet8 100000 0 none 2 +Ethernet12 12,13,14,15 Ethernet12 100000 0 none 3 +Ethernet16 16,17,18,19 Ethernet16 100000 0 none 4 +Ethernet20 20,21,22,23 Ethernet20 100000 0 none 5 +Ethernet24 24,25,26,27 Ethernet24 100000 0 none 6 +Ethernet28 28,29,30,31 Ethernet28 100000 0 none 7 +Ethernet32 32,33,34,35 Ethernet32 100000 0 none 8 +Ethernet36 36,37,38,39 Ethernet36 100000 0 none 9 +Ethernet40 40,41,42,43 Ethernet40 100000 0 none 10 +Ethernet44 44,45,46,47 Ethernet44 100000 0 none 11 +Ethernet48 48,49,50,51 Ethernet48 100000 0 none 12 +Ethernet52 52,53,54,55 Ethernet52 100000 0 none 13 +Ethernet56 56,57,58,59 Ethernet56 100000 0 none 14 +Ethernet60 60,61,62,63 Ethernet60 100000 0 none 15 +Ethernet64 64,65,66,67 Ethernet64 100000 0 none 16 +Ethernet68 68,69,70,71 Ethernet68 100000 0 none 17 +Ethernet72 72,73,74,75 Ethernet72 100000 0 none 18 +Ethernet76 76,77,78,79 Ethernet76 100000 0 none 19 +Ethernet80 80,81,82,83 Ethernet80 100000 0 none 20 +Ethernet84 84,85,86,87 Ethernet84 100000 0 none 21 +Ethernet88 88,89,90,91 Ethernet88 100000 0 none 22 +Ethernet92 92,93,94,95 Ethernet92 100000 0 none 23 +Ethernet96 96,97,98,99 Ethernet96 100000 0 none 24 +Ethernet100 100,101,102,103 Ethernet100 100000 0 none 25 +Ethernet104 104,105,106,107 Ethernet104 100000 0 none 26 +Ethernet108 108,109,110,111 Ethernet108 100000 0 none 27 +Ethernet112 112,113,114,115 Ethernet112 100000 0 none 28 +Ethernet116 116,117,118,119 Ethernet116 100000 0 none 29 +Ethernet120 120,121,122,123 Ethernet120 100000 0 none 30 +Ethernet124 124,125,126,127 Ethernet124 100000 0 none 31 diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/switch-sai.conf b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/switch-sai.conf new file mode 100644 index 000000000000..4f316bb9e5af --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/switch-sai.conf @@ -0,0 +1,33 @@ +{ + "chip_list": [ + { + "id": "asic-0", + "chip_family": "Tofino", + "instance": 0, + "pcie_sysfs_prefix": "/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0", + "pcie_domain": 0, + "pcie_bus": 5, + "pcie_fn": 0, + "pcie_dev": 0, + "pcie_int_mode": 1, + "sds_fw_path": "share/tofino_sds_fw/avago/firmware" + } + ], + "instance": 0, + "p4_program_list": [ + { + "id": "pgm-0", + "instance": 0, + "path": "switch", + "program-name": "switch", + "pd": "lib/tofinopd/switch/libpd.so", + "pd-thrift": "lib/tofinopd/switch/libpdthrift.so", + "table-config": "share/tofinopd/switch/context.json", + "tofino-bin": "share/tofinopd/switch/tofino.bin", + "switchapi": "lib/libswitchapi.so", + "switchsai": "lib/libswitchsai.so", + "agent0": "lib/platform/x86_64-ingrasys_s9180_32x-r0/libpltfm_mgr.so", + "switchapi_port_add": false + } + ] +} diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/default_sku new file mode 100644 index 000000000000..984f54a96e23 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S9180-32X t1 diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/fancontrol new file mode 100644 index 000000000000..dc303afac034 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/fancontrol @@ -0,0 +1,12 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-56/56-002f +DEVNAME=hwmon1=w83795adg +FCTEMPS=hwmon1/device/pwm2=hwmon2/temp2_input hwmon1/device/pwm1=hwmon2/temp2_input +FCFANS=hwmon1/device/pwm2=hwmon1/device/fan8_input hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan6_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm1=hwmon1/device/fan4_input hwmon1/device/pwm1=hwmon1/device/fan3_input hwmon1/device/pwm1=hwmon1/device/fan2_input hwmon1/device/pwm1=hwmon1/device/fan1_input +# TODO: check the temp value with HW after board ready +MINTEMP=hwmon1/device/pwm2=20 hwmon1/device/pwm1=20 +MAXTEMP=hwmon1/device/pwm2=60 hwmon1/device/pwm1=60 +MINSTART=hwmon1/device/pwm2=75 hwmon1/device/pwm1=75 +MINSTOP=hwmon1/device/pwm2=22 hwmon1/device/pwm1=22 + diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..d1270eeffbf6 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Ingrasys S9180-32X +# +# 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-0055/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..25cdfb031882 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/psuutil.py @@ -0,0 +1,107 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + GPIO_OFFSET = 0 + SYS_GPIO_DIR = "/sys/class/gpio/" + + def set_gpio_offset(self): + sys_gpio_dir = "/sys/class/gpio" + self.GPIO_OFFSET = 0 + gpiochip_no = 0 + for d in os.listdir(sys_gpio_dir): + if "gpiochip" in d: + try: + gpiochip_no = int(d[8:],10) + except ValueError as e: + print "Error: %s" % str(e) + if gpiochip_no > 255: + self.GPIO_OFFSET=256 + return True + return True + + def __init__(self): + self.set_gpio_offset() + PsuBase.__init__(self) + + + # Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + gpio_path = [ 'gpio'+str(99+self.GPIO_OFFSET)+'/value', 'gpio'+str(96+self.GPIO_OFFSET)+'/value' ] + attr_path = self.SYS_GPIO_DIR + gpio_path[index-1] + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 10) + # Check for PSU status + if (attr_value == 1): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + gpio_path = [ 'gpio'+str(100+self.GPIO_OFFSET)+'/value', 'gpio'+str(97+self.GPIO_OFFSET)+'/value' ] + attr_path = self.SYS_GPIO_DIR + gpio_path[index-1] + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 10) + # Check for PSU status + if (attr_value == 1): + status = 1 + + return status + diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..00c5e10e0b0d --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/sfputil.py @@ -0,0 +1,332 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +import os + +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 = 33 + SFP_PORT_START = 32 + PORTS_IN_BLOCK = 34 + GPIO_OFFSET = 0 + + BASE_DIR_PATH = "/sys/class/gpio/gpio{0}/direction" + BASE_VAL_PATH = "/sys/class/gpio/gpio{0}/value" + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: 10, + 1: 9, + 2: 12, + 3: 11, + 4: 14, + 5: 13, + 6: 16, + 7: 15, + 8: 18, + 9: 17, + 10: 20, + 11: 19, + 12: 22, + 13: 21, + 14: 24, + 15: 23, + 16: 26, + 17: 25, + 18: 28, + 19: 27, + 20: 30, + 21: 29, + 22: 32, + 23: 31, + 24: 34, + 25: 33, + 26: 36, + 27: 35, + 28: 38, + 29: 37, + 30: 40, + 31: 39, + 32: 45, + 33: 46 + } + + abs_to_gpio_mapping = {} + lpmode_to_gpio_mapping = {} + reset_to_gpio_mapping = {} + + @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 port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + @property + def sfp_port_start(self): + return self.SFP_PORT_START + + def set_gpio_offset(self): + sys_gpio_dir = "/sys/class/gpio" + self.GPIO_OFFSET = 0 + gpiochip_no = 0 + for d in os.listdir(sys_gpio_dir): + if "gpiochip" in d: + try: + gpiochip_no = int(d[8:],10) + except ValueError as e: + print "Error: %s" % str(e) + if gpiochip_no > 255: + self.GPIO_OFFSET=256 + return True + return True + + def init_abs_to_gpio_mapping(self): + self.abs_to_gpio_mapping = { + 0: 241+self.GPIO_OFFSET, + 1: 240+self.GPIO_OFFSET, + 2: 243+self.GPIO_OFFSET, + 3: 242+self.GPIO_OFFSET, + 4: 245+self.GPIO_OFFSET, + 5: 244+self.GPIO_OFFSET, + 6: 247+self.GPIO_OFFSET, + 7: 246+self.GPIO_OFFSET, + 8: 249+self.GPIO_OFFSET, + 9: 248+self.GPIO_OFFSET, + 10: 251+self.GPIO_OFFSET, + 11: 250+self.GPIO_OFFSET, + 12: 253+self.GPIO_OFFSET, + 13: 252+self.GPIO_OFFSET, + 14: 255+self.GPIO_OFFSET, + 15: 254+self.GPIO_OFFSET, + 16: 225+self.GPIO_OFFSET, + 17: 224+self.GPIO_OFFSET, + 18: 227+self.GPIO_OFFSET, + 19: 226+self.GPIO_OFFSET, + 20: 229+self.GPIO_OFFSET, + 21: 228+self.GPIO_OFFSET, + 22: 231+self.GPIO_OFFSET, + 23: 230+self.GPIO_OFFSET, + 24: 233+self.GPIO_OFFSET, + 25: 232+self.GPIO_OFFSET, + 26: 235+self.GPIO_OFFSET, + 27: 234+self.GPIO_OFFSET, + 28: 237+self.GPIO_OFFSET, + 29: 236+self.GPIO_OFFSET, + 30: 239+self.GPIO_OFFSET, + 31: 238+self.GPIO_OFFSET, + 32: 177+self.GPIO_OFFSET, + 33: 176+self.GPIO_OFFSET + } + return True + + def init_lpmode_to_gpio_mapping(self): + self.lpmode_to_gpio_mapping = { + 0: 161+self.GPIO_OFFSET, + 1: 160+self.GPIO_OFFSET, + 2: 163+self.GPIO_OFFSET, + 3: 162+self.GPIO_OFFSET, + 4: 165+self.GPIO_OFFSET, + 5: 164+self.GPIO_OFFSET, + 6: 167+self.GPIO_OFFSET, + 7: 166+self.GPIO_OFFSET, + 8: 169+self.GPIO_OFFSET, + 9: 168+self.GPIO_OFFSET, + 10: 171+self.GPIO_OFFSET, + 11: 170+self.GPIO_OFFSET, + 12: 173+self.GPIO_OFFSET, + 13: 172+self.GPIO_OFFSET, + 14: 175+self.GPIO_OFFSET, + 15: 174+self.GPIO_OFFSET, + 16: 145+self.GPIO_OFFSET, + 17: 144+self.GPIO_OFFSET, + 18: 147+self.GPIO_OFFSET, + 19: 146+self.GPIO_OFFSET, + 20: 149+self.GPIO_OFFSET, + 21: 148+self.GPIO_OFFSET, + 22: 151+self.GPIO_OFFSET, + 23: 150+self.GPIO_OFFSET, + 24: 153+self.GPIO_OFFSET, + 25: 152+self.GPIO_OFFSET, + 26: 155+self.GPIO_OFFSET, + 27: 154+self.GPIO_OFFSET, + 28: 157+self.GPIO_OFFSET, + 29: 156+self.GPIO_OFFSET, + 30: 159+self.GPIO_OFFSET, + 31: 158+self.GPIO_OFFSET + } + return True + + def init_reset_to_gpio_mapping(self): + self.reset_to_gpio_mapping = { + 0: 129+self.GPIO_OFFSET, + 1: 128+self.GPIO_OFFSET, + 2: 131+self.GPIO_OFFSET, + 3: 130+self.GPIO_OFFSET, + 4: 133+self.GPIO_OFFSET, + 5: 132+self.GPIO_OFFSET, + 6: 135+self.GPIO_OFFSET, + 7: 134+self.GPIO_OFFSET, + 8: 137+self.GPIO_OFFSET, + 9: 136+self.GPIO_OFFSET, + 10: 139+self.GPIO_OFFSET, + 11: 138+self.GPIO_OFFSET, + 12: 141+self.GPIO_OFFSET, + 13: 140+self.GPIO_OFFSET, + 14: 143+self.GPIO_OFFSET, + 15: 142+self.GPIO_OFFSET, + 16: 113+self.GPIO_OFFSET, + 17: 112+self.GPIO_OFFSET, + 18: 115+self.GPIO_OFFSET, + 19: 114+self.GPIO_OFFSET, + 20: 117+self.GPIO_OFFSET, + 21: 116+self.GPIO_OFFSET, + 22: 119+self.GPIO_OFFSET, + 23: 118+self.GPIO_OFFSET, + 24: 121+self.GPIO_OFFSET, + 25: 120+self.GPIO_OFFSET, + 26: 123+self.GPIO_OFFSET, + 27: 122+self.GPIO_OFFSET, + 28: 125+self.GPIO_OFFSET, + 29: 124+self.GPIO_OFFSET, + 30: 127+self.GPIO_OFFSET, + 31: 126+self.GPIO_OFFSET + } + return True + + def __init__(self): + # Init abs, lpmode, and reset to gpio mapping + self.set_gpio_offset() + self.init_abs_to_gpio_mapping() + self.init_lpmode_to_gpio_mapping() + self.init_reset_to_gpio_mapping() + + # 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): + 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: + abs_device_file = self.BASE_VAL_PATH.format( + self.abs_to_gpio_mapping[port_num]) + val_file = open(abs_device_file) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + 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.sfp_port_start: # TBD + return False + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.sfp_port_start: # TBD + return False + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("1" if lpmode is True else "0") + val_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.sfp_port_start: # TBD + return False + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("1") + val_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("0") + val_file.close() + + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/sensors.conf new file mode 100644 index 000000000000..eb991d771d15 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/sensors.conf @@ -0,0 +1,76 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + label temp1 "DIMM Temp" + set temp1_max 50 + set temp1_crit 85 + +bus "i2c-0" "I2C I801" +chip "tmp75-i2c-*-4f" + label temp1 "CPU Board Temp" + set temp1_max 50 + +bus "i2c-41" "i2c-7-switch (chan_id 0)" +chip "tmp75-i2c-*-48" + label temp1 "Near PSU1" + set temp1_max 50 +chip "tmp75-i2c-*-4a" + label temp1 "Rear MAC" + set temp1_max 50 +chip "tmp75-i2c-*-4b" + label temp1 "Near Port 32" + set temp1_max 50 +chip "tmp75-i2c-*-4d" + label temp1 "Near PSU2" + set temp1_max 50 +chip "lm86-i2c-*-4c" + label temp1 "Front MAC" + label temp2 "ASIC Core Temp" + set temp1_min 20 + set temp1_max 65 + set temp1_crit 70 + set temp2_min 20 + set temp2_max 70 + set temp2_crit 80 + +bus "i2c-56" "i2c-0-mux (chan_id 7)" +chip "w83795adg-*" + label in0 "0.9V" + set in0_max 0.927 + set in0_min 0.873 + label in1 "VDD" + set in1_max 0.962 + set in1_min 0.717 + ignore in2 + ignore in3 + ignore in4 + ignore in5 + ignore in6 + ignore in7 + label in12 "2.5V" + #compute in12 (2*4*@)/10, @-(2*4*@/10) + compute in12 @/(1+(3/10)), @*(1+(3/10)) + set in12_max 2.625 + set in12_min 2.375 + # in12 and in13 are the same source + ignore in13 + ignore in14 + ignore in15 + ignore in16 + label fan1 "FANTRAY 1-A" + label fan2 "FANTRAY 1-B" + label fan3 "FANTRAY 2-A" + label fan4 "FANTRAY 2-B" + label fan5 "FANTRAY 3-A" + label fan6 "FANTRAY 3-B" + label fan7 "FANTRAY 4-A" + label fan8 "FANTRAY 4-B" + ignore temp1 + ignore temp2 + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore intrusion0 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/port_config.ini b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/port_config.ini new file mode 100644 index 000000000000..c1d2642fab8e --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index +Ethernet0 49,50,51,52 Ethernet1/1 0 +Ethernet4 53,54,55,56 Ethernet2/1 1 +Ethernet8 65,66,67,68 Ethernet3/1 2 +Ethernet12 69,70,71,72 Ethernet4/1 3 +Ethernet16 81,82,83,84 Ethernet5/1 4 +Ethernet20 85,86,87,88 Ethernet6/1 5 +Ethernet24 1,2,3,4 Ethernet7/1 6 +Ethernet28 5,6,7,8 Ethernet8/1 7 +Ethernet32 17,18,19,20 Ethernet9/1 8 +Ethernet36 21,22,23,24 Ethernet10/1 9 +Ethernet40 33,34,35,36 Ethernet11/1 10 +Ethernet44 37,38,39,40 Ethernet12/1 11 +Ethernet48 97,98,99,100 Ethernet13/1 12 +Ethernet52 101,102,103,104 Ethernet14/1 13 +Ethernet56 113,114,115,116 Ethernet15/1 14 +Ethernet60 117,118,119,120 Ethernet16/1 15 +Ethernet64 129,130,131,132 Ethernet17/1 16 +Ethernet68 133,134,135,136 Ethernet18/1 17 +Ethernet72 145,146,147,148 Ethernet19/1 18 +Ethernet76 149,150,151,152 Ethernet20/1 19 +Ethernet80 209,210,211,212 Ethernet21/1 20 +Ethernet84 213,214,215,216 Ethernet22/1 21 +Ethernet88 225,226,227,228 Ethernet23/1 22 +Ethernet92 229,230,231,232 Ethernet24/1 23 +Ethernet96 241,242,243,244 Ethernet25/1 24 +Ethernet100 245,246,247,248 Ethernet26/1 25 +Ethernet104 161,162,163,164 Ethernet27/1 26 +Ethernet108 165,166,167,168 Ethernet28/1 27 +Ethernet112 177,178,179,180 Ethernet29/1 28 +Ethernet116 181,182,183,184 Ethernet30/1 29 +Ethernet120 193,194,195,196 Ethernet31/1 30 +Ethernet124 197,198,199,200 Ethernet32/1 31 +Ethernet128 57,58,59,60 Ethernet33/1 32 +Ethernet132 61,62,63,64 Ethernet34/1 33 +Ethernet136 73,74,75,76 Ethernet35/1 34 +Ethernet140 77,78,79,80 Ethernet36/1 35 +Ethernet144 89,90,91,92 Ethernet37/1 36 +Ethernet148 93,94,95,96 Ethernet38/1 37 +Ethernet152 9,10,11,12 Ethernet39/1 38 +Ethernet156 13,14,15,16 Ethernet40/1 39 +Ethernet160 25,26,27,28 Ethernet41/1 40 +Ethernet164 29,30,31,32 Ethernet42/1 41 +Ethernet168 41,42,43,44 Ethernet43/1 42 +Ethernet172 45,46,47,48 Ethernet44/1 43 +Ethernet176 105,106,107,108 Ethernet45/1 44 +Ethernet180 109,110,111,112 Ethernet46/1 45 +Ethernet184 121,122,123,124 Ethernet47/1 46 +Ethernet188 125,126,127,128 Ethernet48/1 47 +Ethernet192 137,138,139,140 Ethernet49/1 48 +Ethernet196 141,142,143,144 Ethernet50/1 49 +Ethernet200 153,154,155,156 Ethernet51/1 50 +Ethernet204 157,158,159,160 Ethernet52/1 51 +Ethernet208 217,218,219,220 Ethernet53/1 52 +Ethernet212 221,222,223,224 Ethernet54/1 53 +Ethernet216 233,234,235,236 Ethernet55/1 54 +Ethernet220 237,238,239,240 Ethernet56/1 55 +Ethernet224 249,250,251,252 Ethernet57/1 56 +Ethernet228 253,254,255,256 Ethernet58/1 57 +Ethernet232 169,170,171,172 Ethernet59/1 58 +Ethernet236 173,174,175,176 Ethernet60/1 59 +Ethernet240 185,186,187,188 Ethernet61/1 60 +Ethernet244 189,190,191,192 Ethernet62/1 61 +Ethernet248 201,202,203,204 Ethernet63/1 62 +Ethernet252 205,206,207,208 Ethernet64/1 63 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/sai.profile b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/sai.profile new file mode 100644 index 000000000000..5404ca338ffd --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-s9200-64x100G.config.bcm diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/th2-s9200-64x100G.config.bcm b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/th2-s9200-64x100G.config.bcm new file mode 100644 index 000000000000..b143fb425b92 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/th2-s9200-64x100G.config.bcm @@ -0,0 +1,873 @@ +#2018/3/6 + +os=unix + +oversubscribe_mode=1 +pbmp_xport_xe=0x3fffd0000ffff40003fffc0001fffe + +#ALPM enable +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l3_mem_entries=40960 +l2_mem_entries=40960 + +#Parity +parity_correction=1 +parity_enable=1 + +l2xmsg_mode=1 +mmu_lossless=0 + +# core_clock_frequency can be 1125, 850, 765, 672, 645 or 545 +#core_clock_frequency=1125 + + +#PIPE-0 +#FC 0 +portmap_1=1:100 +phy_chain_tx_polarity_flip_physical{1.0}=0 +phy_chain_tx_polarity_flip_physical{2.0}=1 +phy_chain_tx_polarity_flip_physical{3.0}=0 +phy_chain_tx_polarity_flip_physical{4.0}=0 +phy_chain_rx_polarity_flip_physical{1.0}=1 +phy_chain_rx_polarity_flip_physical{2.0}=1 +phy_chain_rx_polarity_flip_physical{3.0}=0 +phy_chain_rx_polarity_flip_physical{4.0}=1 +phy_chain_tx_lane_map_physical{1.0}=0x3210 +phy_chain_rx_lane_map_physical{1.0}=0x0312 + +#FC 1 +portmap_2=5:100 +phy_chain_tx_polarity_flip_physical{5.0}=1 +phy_chain_tx_polarity_flip_physical{6.0}=1 +phy_chain_tx_polarity_flip_physical{7.0}=0 +phy_chain_tx_polarity_flip_physical{8.0}=0 +phy_chain_rx_polarity_flip_physical{5.0}=1 +phy_chain_rx_polarity_flip_physical{6.0}=0 +phy_chain_rx_polarity_flip_physical{7.0}=1 +phy_chain_rx_polarity_flip_physical{8.0}=1 +phy_chain_tx_lane_map_physical{5.0}=0x1023 +phy_chain_rx_lane_map_physical{5.0}=0x2103 + +#FC 2 +portmap_3=9:100 +phy_chain_tx_polarity_flip_physical{9.0}=0 +phy_chain_tx_polarity_flip_physical{10.0}=0 +phy_chain_tx_polarity_flip_physical{11.0}=1 +phy_chain_tx_polarity_flip_physical{12.0}=1 +phy_chain_rx_polarity_flip_physical{9.0}=1 +phy_chain_rx_polarity_flip_physical{10.0}=1 +phy_chain_rx_polarity_flip_physical{11.0}=0 +phy_chain_rx_polarity_flip_physical{12.0}=1 +phy_chain_tx_lane_map_physical{9.0}=0x3201 +phy_chain_rx_lane_map_physical{9.0}=0x1320 + +#FC 3 +portmap_4=13:100 +phy_chain_tx_polarity_flip_physical{13.0}=0 +phy_chain_tx_polarity_flip_physical{14.0}=0 +phy_chain_tx_polarity_flip_physical{15.0}=0 +phy_chain_tx_polarity_flip_physical{16.0}=1 +phy_chain_rx_polarity_flip_physical{13.0}=0 +phy_chain_rx_polarity_flip_physical{14.0}=0 +phy_chain_rx_polarity_flip_physical{15.0}=0 +phy_chain_rx_polarity_flip_physical{16.0}=0 +phy_chain_tx_lane_map_physical{13.0}=0x2013 +phy_chain_rx_lane_map_physical{13.0}=0x2310 + +#FC 4 +portmap_5=17:100 +phy_chain_tx_polarity_flip_physical{17.0}=1 +phy_chain_tx_polarity_flip_physical{18.0}=0 +phy_chain_tx_polarity_flip_physical{19.0}=0 +phy_chain_tx_polarity_flip_physical{20.0}=0 +phy_chain_rx_polarity_flip_physical{17.0}=0 +phy_chain_rx_polarity_flip_physical{18.0}=1 +phy_chain_rx_polarity_flip_physical{19.0}=1 +phy_chain_rx_polarity_flip_physical{20.0}=1 +phy_chain_tx_lane_map_physical{17.0}=0x0213 +phy_chain_rx_lane_map_physical{17.0}=0x0132 + +#FC 5 +portmap_6=21:100 +phy_chain_tx_polarity_flip_physical{21.0}=1 +phy_chain_tx_polarity_flip_physical{22.0}=1 +phy_chain_tx_polarity_flip_physical{23.0}=0 +phy_chain_tx_polarity_flip_physical{24.0}=0 +phy_chain_rx_polarity_flip_physical{21.0}=1 +phy_chain_rx_polarity_flip_physical{22.0}=0 +phy_chain_rx_polarity_flip_physical{23.0}=0 +phy_chain_rx_polarity_flip_physical{24.0}=1 +phy_chain_tx_lane_map_physical{21.0}=0x3021 +phy_chain_rx_lane_map_physical{21.0}=0x0312 + +#FC 6 +portmap_7=25:100 +phy_chain_tx_polarity_flip_physical{25.0}=0 +phy_chain_tx_polarity_flip_physical{26.0}=0 +phy_chain_tx_polarity_flip_physical{27.0}=0 +phy_chain_tx_polarity_flip_physical{28.0}=0 +phy_chain_rx_polarity_flip_physical{25.0}=0 +phy_chain_rx_polarity_flip_physical{26.0}=0 +phy_chain_rx_polarity_flip_physical{27.0}=0 +phy_chain_rx_polarity_flip_physical{28.0}=0 +phy_chain_tx_lane_map_physical{25.0}=0x2310 +phy_chain_rx_lane_map_physical{25.0}=0x1302 + +#FC 7 +portmap_8=29:100 +phy_chain_tx_polarity_flip_physical{29.0}=0 +phy_chain_tx_polarity_flip_physical{30.0}=0 +phy_chain_tx_polarity_flip_physical{31.0}=0 +phy_chain_tx_polarity_flip_physical{32.0}=1 +phy_chain_rx_polarity_flip_physical{29.0}=0 +phy_chain_rx_polarity_flip_physical{30.0}=0 +phy_chain_rx_polarity_flip_physical{31.0}=1 +phy_chain_rx_polarity_flip_physical{32.0}=0 +phy_chain_tx_lane_map_physical{29.0}=0x2031 +phy_chain_rx_lane_map_physical{29.0}=0x2310 + +#FC 8 +portmap_9=33:100 +phy_chain_tx_polarity_flip_physical{33.0}=1 +phy_chain_tx_polarity_flip_physical{34.0}=1 +phy_chain_tx_polarity_flip_physical{35.0}=0 +phy_chain_tx_polarity_flip_physical{36.0}=1 +phy_chain_rx_polarity_flip_physical{33.0}=1 +phy_chain_rx_polarity_flip_physical{34.0}=0 +phy_chain_rx_polarity_flip_physical{35.0}=0 +phy_chain_rx_polarity_flip_physical{36.0}=0 +phy_chain_tx_lane_map_physical{33.0}=0x3120 +phy_chain_rx_lane_map_physical{33.0}=0x2130 + +#FC 9 +portmap_10=37:100 +phy_chain_tx_polarity_flip_physical{37.0}=1 +phy_chain_tx_polarity_flip_physical{38.0}=1 +phy_chain_tx_polarity_flip_physical{39.0}=1 +phy_chain_tx_polarity_flip_physical{40.0}=1 +phy_chain_rx_polarity_flip_physical{37.0}=0 +phy_chain_rx_polarity_flip_physical{38.0}=1 +phy_chain_rx_polarity_flip_physical{39.0}=0 +phy_chain_rx_polarity_flip_physical{40.0}=0 +phy_chain_tx_lane_map_physical{37.0}=0x0123 +phy_chain_rx_lane_map_physical{37.0}=0x1230 + +#FC 10 +portmap_11=41:100 +phy_chain_tx_polarity_flip_physical{41.0}=1 +phy_chain_tx_polarity_flip_physical{42.0}=1 +phy_chain_tx_polarity_flip_physical{43.0}=0 +phy_chain_tx_polarity_flip_physical{44.0}=0 +phy_chain_rx_polarity_flip_physical{41.0}=1 +phy_chain_rx_polarity_flip_physical{42.0}=0 +phy_chain_rx_polarity_flip_physical{43.0}=0 +phy_chain_rx_polarity_flip_physical{44.0}=0 +phy_chain_tx_lane_map_physical{41.0}=0x3021 +phy_chain_rx_lane_map_physical{41.0}=0x1230 + +#FC 11 +portmap_12=45:100 +phy_chain_tx_polarity_flip_physical{45.0}=0 +phy_chain_tx_polarity_flip_physical{46.0}=1 +phy_chain_tx_polarity_flip_physical{47.0}=1 +phy_chain_tx_polarity_flip_physical{48.0}=1 +phy_chain_rx_polarity_flip_physical{45.0}=0 +phy_chain_rx_polarity_flip_physical{46.0}=1 +phy_chain_rx_polarity_flip_physical{47.0}=1 +phy_chain_rx_polarity_flip_physical{48.0}=1 +phy_chain_tx_lane_map_physical{45.0}=0x0123 +phy_chain_rx_lane_map_physical{45.0}=0x0213 + +#FC 12 +portmap_13=49:100 +phy_chain_tx_polarity_flip_physical{49.0}=1 +phy_chain_tx_polarity_flip_physical{50.0}=0 +phy_chain_tx_polarity_flip_physical{51.0}=1 +phy_chain_tx_polarity_flip_physical{52.0}=0 +phy_chain_rx_polarity_flip_physical{49.0}=1 +phy_chain_rx_polarity_flip_physical{50.0}=1 +phy_chain_rx_polarity_flip_physical{51.0}=1 +phy_chain_rx_polarity_flip_physical{52.0}=0 +phy_chain_tx_lane_map_physical{49.0}=0x0213 +phy_chain_rx_lane_map_physical{49.0}=0x0123 + +#FC 13 +portmap_14=53:100 +phy_chain_tx_polarity_flip_physical{53.0}=1 +phy_chain_tx_polarity_flip_physical{54.0}=1 +phy_chain_tx_polarity_flip_physical{55.0}=0 +phy_chain_tx_polarity_flip_physical{56.0}=1 +phy_chain_rx_polarity_flip_physical{53.0}=0 +phy_chain_rx_polarity_flip_physical{54.0}=1 +phy_chain_rx_polarity_flip_physical{55.0}=1 +phy_chain_rx_polarity_flip_physical{56.0}=1 +phy_chain_tx_lane_map_physical{53.0}=0x2031 +phy_chain_rx_lane_map_physical{53.0}=0x0132 + +#FC 14 +portmap_15=57:100 +phy_chain_tx_polarity_flip_physical{57.0}=1 +phy_chain_tx_polarity_flip_physical{58.0}=0 +phy_chain_tx_polarity_flip_physical{59.0}=0 +phy_chain_tx_polarity_flip_physical{60.0}=0 +phy_chain_rx_polarity_flip_physical{57.0}=0 +phy_chain_rx_polarity_flip_physical{58.0}=0 +phy_chain_rx_polarity_flip_physical{59.0}=0 +phy_chain_rx_polarity_flip_physical{60.0}=0 +phy_chain_tx_lane_map_physical{57.0}=0x3021 +phy_chain_rx_lane_map_physical{57.0}=0x2103 + +#FC 15 +portmap_16=61:100 +phy_chain_tx_polarity_flip_physical{61.0}=0 +phy_chain_tx_polarity_flip_physical{62.0}=0 +phy_chain_tx_polarity_flip_physical{63.0}=0 +phy_chain_tx_polarity_flip_physical{64.0}=1 +phy_chain_rx_polarity_flip_physical{61.0}=0 +phy_chain_rx_polarity_flip_physical{62.0}=1 +phy_chain_rx_polarity_flip_physical{63.0}=1 +phy_chain_rx_polarity_flip_physical{64.0}=1 +phy_chain_tx_lane_map_physical{61.0}=0x0132 +phy_chain_rx_lane_map_physical{61.0}=0x1320 + +#PIPE-1 +#FC 16 +portmap_34=65:100 +phy_chain_tx_polarity_flip_physical{65.0}=1 +phy_chain_tx_polarity_flip_physical{66.0}=1 +phy_chain_tx_polarity_flip_physical{67.0}=1 +phy_chain_tx_polarity_flip_physical{68.0}=1 +phy_chain_rx_polarity_flip_physical{65.0}=0 +phy_chain_rx_polarity_flip_physical{66.0}=0 +phy_chain_rx_polarity_flip_physical{67.0}=1 +phy_chain_rx_polarity_flip_physical{68.0}=0 +phy_chain_tx_lane_map_physical{65.0}=0x2031 +phy_chain_rx_lane_map_physical{65.0}=0x2031 + +#FC 17 +portmap_35=69:100 +phy_chain_tx_polarity_flip_physical{69.0}=1 +phy_chain_tx_polarity_flip_physical{70.0}=0 +phy_chain_tx_polarity_flip_physical{71.0}=0 +phy_chain_tx_polarity_flip_physical{72.0}=1 +phy_chain_rx_polarity_flip_physical{69.0}=1 +phy_chain_rx_polarity_flip_physical{70.0}=0 +phy_chain_rx_polarity_flip_physical{71.0}=0 +phy_chain_rx_polarity_flip_physical{72.0}=1 +phy_chain_tx_lane_map_physical{69.0}=0x2031 +phy_chain_rx_lane_map_physical{69.0}=0x3201 + +#FC 18 +portmap_36=73:100 +phy_chain_tx_polarity_flip_physical{73.0}=0 +phy_chain_tx_polarity_flip_physical{74.0}=0 +phy_chain_tx_polarity_flip_physical{75.0}=1 +phy_chain_tx_polarity_flip_physical{76.0}=0 +phy_chain_rx_polarity_flip_physical{73.0}=1 +phy_chain_rx_polarity_flip_physical{74.0}=1 +phy_chain_rx_polarity_flip_physical{75.0}=0 +phy_chain_rx_polarity_flip_physical{76.0}=0 +phy_chain_tx_lane_map_physical{73.0}=0x3120 +phy_chain_rx_lane_map_physical{73.0}=0x3201 + +#FC 19 +portmap_37=77:100 +phy_chain_tx_polarity_flip_physical{77.0}=1 +phy_chain_tx_polarity_flip_physical{78.0}=0 +phy_chain_tx_polarity_flip_physical{79.0}=1 +phy_chain_tx_polarity_flip_physical{80.0}=0 +phy_chain_rx_polarity_flip_physical{77.0}=1 +phy_chain_rx_polarity_flip_physical{78.0}=0 +phy_chain_rx_polarity_flip_physical{79.0}=1 +phy_chain_rx_polarity_flip_physical{80.0}=0 +phy_chain_tx_lane_map_physical{77.0}=0x0132 +phy_chain_rx_lane_map_physical{77.0}=0x1032 + +#FC 20 +portmap_38=81:100 +phy_chain_tx_polarity_flip_physical{81.0}=1 +phy_chain_tx_polarity_flip_physical{82.0}=0 +phy_chain_tx_polarity_flip_physical{83.0}=1 +phy_chain_tx_polarity_flip_physical{84.0}=0 +phy_chain_rx_polarity_flip_physical{81.0}=0 +phy_chain_rx_polarity_flip_physical{82.0}=1 +phy_chain_rx_polarity_flip_physical{83.0}=1 +phy_chain_rx_polarity_flip_physical{84.0}=1 +phy_chain_tx_lane_map_physical{81.0}=0x0213 +phy_chain_rx_lane_map_physical{81.0}=0x1203 + +#FC 21 +portmap_39=85:100 +phy_chain_tx_polarity_flip_physical{85.0}=1 +phy_chain_tx_polarity_flip_physical{86.0}=1 +phy_chain_tx_polarity_flip_physical{87.0}=0 +phy_chain_tx_polarity_flip_physical{88.0}=0 +phy_chain_rx_polarity_flip_physical{85.0}=0 +phy_chain_rx_polarity_flip_physical{86.0}=1 +phy_chain_rx_polarity_flip_physical{87.0}=0 +phy_chain_rx_polarity_flip_physical{88.0}=1 +phy_chain_tx_lane_map_physical{85.0}=0x3021 +phy_chain_rx_lane_map_physical{85.0}=0x1230 + +#FC 22 +portmap_40=89:100 +phy_chain_tx_polarity_flip_physical{89.0}=1 +phy_chain_tx_polarity_flip_physical{90.0}=0 +phy_chain_tx_polarity_flip_physical{91.0}=0 +phy_chain_tx_polarity_flip_physical{92.0}=0 +phy_chain_rx_polarity_flip_physical{89.0}=1 +phy_chain_rx_polarity_flip_physical{90.0}=1 +phy_chain_rx_polarity_flip_physical{91.0}=0 +phy_chain_rx_polarity_flip_physical{92.0}=0 +phy_chain_tx_lane_map_physical{89.0}=0x3021 +phy_chain_rx_lane_map_physical{89.0}=0x3201 + +#FC 23 +portmap_41=93:100 +phy_chain_tx_polarity_flip_physical{93.0}=0 +phy_chain_tx_polarity_flip_physical{94.0}=0 +phy_chain_tx_polarity_flip_physical{95.0}=1 +phy_chain_tx_polarity_flip_physical{96.0}=0 +phy_chain_rx_polarity_flip_physical{93.0}=1 +phy_chain_rx_polarity_flip_physical{94.0}=0 +phy_chain_rx_polarity_flip_physical{95.0}=1 +phy_chain_rx_polarity_flip_physical{96.0}=0 +phy_chain_tx_lane_map_physical{93.0}=0x1023 +phy_chain_rx_lane_map_physical{93.0}=0x1032 + +#FC 24 +portmap_42=97:100 +phy_chain_tx_polarity_flip_physical{97.0}=0 +phy_chain_tx_polarity_flip_physical{98.0}=1 +phy_chain_tx_polarity_flip_physical{99.0}=1 +phy_chain_tx_polarity_flip_physical{100.0}=0 +phy_chain_rx_polarity_flip_physical{97.0}=0 +phy_chain_rx_polarity_flip_physical{98.0}=0 +phy_chain_rx_polarity_flip_physical{99.0}=0 +phy_chain_rx_polarity_flip_physical{100.0}=1 +phy_chain_tx_lane_map_physical{97.0}=0x0132 +phy_chain_rx_lane_map_physical{97.0}=0x1320 + +#FC 25 +portmap_43=101:100 +phy_chain_tx_polarity_flip_physical{101.0}=0 +phy_chain_tx_polarity_flip_physical{102.0}=1 +phy_chain_tx_polarity_flip_physical{103.0}=1 +phy_chain_tx_polarity_flip_physical{104.0}=1 +phy_chain_rx_polarity_flip_physical{101.0}=1 +phy_chain_rx_polarity_flip_physical{102.0}=1 +phy_chain_rx_polarity_flip_physical{103.0}=1 +phy_chain_rx_polarity_flip_physical{104.0}=1 +phy_chain_tx_lane_map_physical{101.0}=0x1023 +phy_chain_rx_lane_map_physical{101.0}=0x3120 + +#FC 26 +portmap_44=105:100 +phy_chain_tx_polarity_flip_physical{105.0}=1 +phy_chain_tx_polarity_flip_physical{106.0}=0 +phy_chain_tx_polarity_flip_physical{107.0}=1 +phy_chain_tx_polarity_flip_physical{108.0}=1 +phy_chain_rx_polarity_flip_physical{105.0}=1 +phy_chain_rx_polarity_flip_physical{106.0}=1 +phy_chain_rx_polarity_flip_physical{107.0}=0 +phy_chain_rx_polarity_flip_physical{108.0}=0 +phy_chain_tx_lane_map_physical{105.0}=0x2103 +phy_chain_rx_lane_map_physical{105.0}=0x1203 + +#FC 27 +portmap_45=109:100 +phy_chain_tx_polarity_flip_physical{109.0}=1 +phy_chain_tx_polarity_flip_physical{110.0}=1 +phy_chain_tx_polarity_flip_physical{111.0}=0 +phy_chain_tx_polarity_flip_physical{112.0}=1 +phy_chain_rx_polarity_flip_physical{109.0}=0 +phy_chain_rx_polarity_flip_physical{110.0}=0 +phy_chain_rx_polarity_flip_physical{111.0}=1 +phy_chain_rx_polarity_flip_physical{112.0}=0 +phy_chain_tx_lane_map_physical{109.0}=0x3201 +phy_chain_rx_lane_map_physical{109.0}=0x0123 + +#FC 28 +portmap_46=113:100 +phy_chain_tx_polarity_flip_physical{113.0}=0 +phy_chain_tx_polarity_flip_physical{114.0}=1 +phy_chain_tx_polarity_flip_physical{115.0}=1 +phy_chain_tx_polarity_flip_physical{116.0}=0 +phy_chain_rx_polarity_flip_physical{113.0}=1 +phy_chain_rx_polarity_flip_physical{114.0}=0 +phy_chain_rx_polarity_flip_physical{115.0}=0 +phy_chain_rx_polarity_flip_physical{116.0}=1 +phy_chain_tx_lane_map_physical{113.0}=0x3012 +phy_chain_rx_lane_map_physical{113.0}=0x1302 + +#FC 29 +portmap_47=117:100 +phy_chain_tx_polarity_flip_physical{117.0}=1 +phy_chain_tx_polarity_flip_physical{118.0}=1 +phy_chain_tx_polarity_flip_physical{119.0}=0 +phy_chain_tx_polarity_flip_physical{120.0}=0 +phy_chain_rx_polarity_flip_physical{117.0}=1 +phy_chain_rx_polarity_flip_physical{118.0}=0 +phy_chain_rx_polarity_flip_physical{119.0}=0 +phy_chain_rx_polarity_flip_physical{120.0}=1 +phy_chain_tx_lane_map_physical{117.0}=0x0312 +phy_chain_rx_lane_map_physical{117.0}=0x0132 + +#FC 30 +portmap_48=121:100 +phy_chain_tx_polarity_flip_physical{121.0}=1 +phy_chain_tx_polarity_flip_physical{122.0}=0 +phy_chain_tx_polarity_flip_physical{123.0}=0 +phy_chain_tx_polarity_flip_physical{124.0}=0 +phy_chain_rx_polarity_flip_physical{121.0}=1 +phy_chain_rx_polarity_flip_physical{122.0}=1 +phy_chain_rx_polarity_flip_physical{123.0}=0 +phy_chain_rx_polarity_flip_physical{124.0}=0 +phy_chain_tx_lane_map_physical{121.0}=0x1023 +phy_chain_rx_lane_map_physical{121.0}=0x1203 + +#FC 31 +portmap_49=125:100 +phy_chain_tx_polarity_flip_physical{125.0}=0 +phy_chain_tx_polarity_flip_physical{126.0}=1 +phy_chain_tx_polarity_flip_physical{127.0}=0 +phy_chain_tx_polarity_flip_physical{128.0}=1 +phy_chain_rx_polarity_flip_physical{125.0}=0 +phy_chain_rx_polarity_flip_physical{126.0}=0 +phy_chain_rx_polarity_flip_physical{127.0}=1 +phy_chain_rx_polarity_flip_physical{128.0}=0 +phy_chain_tx_lane_map_physical{125.0}=0x1320 +phy_chain_rx_lane_map_physical{125.0}=0x2103 + +#PIPE-2 +#FC 32 +portmap_68=129:100 +phy_chain_tx_polarity_flip_physical{129.0}=0 +phy_chain_tx_polarity_flip_physical{130.0}=1 +phy_chain_tx_polarity_flip_physical{131.0}=1 +phy_chain_tx_polarity_flip_physical{132.0}=0 +phy_chain_rx_polarity_flip_physical{129.0}=0 +phy_chain_rx_polarity_flip_physical{130.0}=1 +phy_chain_rx_polarity_flip_physical{131.0}=1 +phy_chain_rx_polarity_flip_physical{132.0}=1 +phy_chain_tx_lane_map_physical{129.0}=0x0321 +phy_chain_rx_lane_map_physical{129.0}=0x2310 + +#FC 33 +portmap_69=133:100 +phy_chain_tx_polarity_flip_physical{133.0}=1 +phy_chain_tx_polarity_flip_physical{134.0}=0 +phy_chain_tx_polarity_flip_physical{135.0}=0 +phy_chain_tx_polarity_flip_physical{136.0}=1 +phy_chain_rx_polarity_flip_physical{133.0}=1 +phy_chain_rx_polarity_flip_physical{134.0}=0 +phy_chain_rx_polarity_flip_physical{135.0}=0 +phy_chain_rx_polarity_flip_physical{136.0}=1 +phy_chain_tx_lane_map_physical{133.0}=0x2013 +phy_chain_rx_lane_map_physical{133.0}=0x1203 + +#FC 34 +portmap_70=137:100 +phy_chain_tx_polarity_flip_physical{137.0}=0 +phy_chain_tx_polarity_flip_physical{138.0}=1 +phy_chain_tx_polarity_flip_physical{139.0}=0 +phy_chain_tx_polarity_flip_physical{140.0}=0 +phy_chain_rx_polarity_flip_physical{137.0}=0 +phy_chain_rx_polarity_flip_physical{138.0}=1 +phy_chain_rx_polarity_flip_physical{139.0}=1 +phy_chain_rx_polarity_flip_physical{140.0}=0 +phy_chain_tx_lane_map_physical{137.0}=0x2301 +phy_chain_rx_lane_map_physical{137.0}=0x0213 + +#FC 35 +portmap_71=141:100 +phy_chain_tx_polarity_flip_physical{141.0}=0 +phy_chain_tx_polarity_flip_physical{142.0}=1 +phy_chain_tx_polarity_flip_physical{143.0}=0 +phy_chain_tx_polarity_flip_physical{144.0}=1 +phy_chain_rx_polarity_flip_physical{141.0}=0 +phy_chain_rx_polarity_flip_physical{142.0}=0 +phy_chain_rx_polarity_flip_physical{143.0}=0 +phy_chain_rx_polarity_flip_physical{144.0}=1 +phy_chain_tx_lane_map_physical{141.0}=0x2013 +phy_chain_rx_lane_map_physical{141.0}=0x2310 + +#FC 36 +portmap_72=145:100 +phy_chain_tx_polarity_flip_physical{145.0}=1 +phy_chain_tx_polarity_flip_physical{146.0}=0 +phy_chain_tx_polarity_flip_physical{147.0}=1 +phy_chain_tx_polarity_flip_physical{148.0}=0 +phy_chain_rx_polarity_flip_physical{145.0}=1 +phy_chain_rx_polarity_flip_physical{146.0}=0 +phy_chain_rx_polarity_flip_physical{147.0}=0 +phy_chain_rx_polarity_flip_physical{148.0}=1 +phy_chain_tx_lane_map_physical{145.0}=0x2310 +phy_chain_rx_lane_map_physical{145.0}=0x0231 + +#FC 37 +portmap_73=149:100 +phy_chain_tx_polarity_flip_physical{149.0}=1 +phy_chain_tx_polarity_flip_physical{150.0}=1 +phy_chain_tx_polarity_flip_physical{151.0}=0 +phy_chain_tx_polarity_flip_physical{152.0}=0 +phy_chain_rx_polarity_flip_physical{149.0}=1 +phy_chain_rx_polarity_flip_physical{150.0}=0 +phy_chain_rx_polarity_flip_physical{151.0}=0 +phy_chain_rx_polarity_flip_physical{152.0}=1 +phy_chain_tx_lane_map_physical{149.0}=0x3021 +phy_chain_rx_lane_map_physical{149.0}=0x1203 + +#FC 38 +portmap_74=153:100 +phy_chain_tx_polarity_flip_physical{153.0}=1 +phy_chain_tx_polarity_flip_physical{154.0}=0 +phy_chain_tx_polarity_flip_physical{155.0}=1 +phy_chain_tx_polarity_flip_physical{156.0}=1 +phy_chain_rx_polarity_flip_physical{153.0}=0 +phy_chain_rx_polarity_flip_physical{154.0}=0 +phy_chain_rx_polarity_flip_physical{155.0}=0 +phy_chain_rx_polarity_flip_physical{156.0}=0 +phy_chain_tx_lane_map_physical{153.0}=0x1230 +phy_chain_rx_lane_map_physical{153.0}=0x3120 + +#FC 39 +portmap_75=157:100 +phy_chain_tx_polarity_flip_physical{157.0}=1 +phy_chain_tx_polarity_flip_physical{158.0}=1 +phy_chain_tx_polarity_flip_physical{159.0}=1 +phy_chain_tx_polarity_flip_physical{160.0}=0 +phy_chain_rx_polarity_flip_physical{157.0}=0 +phy_chain_rx_polarity_flip_physical{158.0}=0 +phy_chain_rx_polarity_flip_physical{159.0}=1 +phy_chain_rx_polarity_flip_physical{160.0}=0 +phy_chain_tx_lane_map_physical{157.0}=0x3210 +phy_chain_rx_lane_map_physical{157.0}=0x3210 + +#FC 40 +portmap_76=161:100 +phy_chain_tx_polarity_flip_physical{161.0}=1 +phy_chain_tx_polarity_flip_physical{162.0}=1 +phy_chain_tx_polarity_flip_physical{163.0}=0 +phy_chain_tx_polarity_flip_physical{164.0}=1 +phy_chain_rx_polarity_flip_physical{161.0}=1 +phy_chain_rx_polarity_flip_physical{162.0}=1 +phy_chain_rx_polarity_flip_physical{163.0}=1 +phy_chain_rx_polarity_flip_physical{164.0}=1 +phy_chain_tx_lane_map_physical{161.0}=0x2031 +phy_chain_rx_lane_map_physical{161.0}=0x1032 + +#FC 41 +portmap_77=165:100 +phy_chain_tx_polarity_flip_physical{165.0}=0 +phy_chain_tx_polarity_flip_physical{166.0}=0 +phy_chain_tx_polarity_flip_physical{167.0}=1 +phy_chain_tx_polarity_flip_physical{168.0}=1 +phy_chain_rx_polarity_flip_physical{165.0}=0 +phy_chain_rx_polarity_flip_physical{166.0}=1 +phy_chain_rx_polarity_flip_physical{167.0}=0 +phy_chain_rx_polarity_flip_physical{168.0}=1 +phy_chain_tx_lane_map_physical{165.0}=0x2310 +phy_chain_rx_lane_map_physical{165.0}=0x1230 + +#FC 42 +portmap_78=169:100 +phy_chain_tx_polarity_flip_physical{169.0}=1 +phy_chain_tx_polarity_flip_physical{170.0}=0 +phy_chain_tx_polarity_flip_physical{171.0}=1 +phy_chain_tx_polarity_flip_physical{172.0}=0 +phy_chain_rx_polarity_flip_physical{169.0}=0 +phy_chain_rx_polarity_flip_physical{170.0}=0 +phy_chain_rx_polarity_flip_physical{171.0}=0 +phy_chain_rx_polarity_flip_physical{172.0}=0 +phy_chain_tx_lane_map_physical{169.0}=0x1302 +phy_chain_rx_lane_map_physical{169.0}=0x3210 + +#FC 43 +portmap_79=173:100 +phy_chain_tx_polarity_flip_physical{173.0}=1 +phy_chain_tx_polarity_flip_physical{174.0}=0 +phy_chain_tx_polarity_flip_physical{175.0}=0 +phy_chain_tx_polarity_flip_physical{176.0}=0 +phy_chain_rx_polarity_flip_physical{173.0}=0 +phy_chain_rx_polarity_flip_physical{174.0}=1 +phy_chain_rx_polarity_flip_physical{175.0}=0 +phy_chain_rx_polarity_flip_physical{176.0}=1 +phy_chain_tx_lane_map_physical{173.0}=0x0312 +phy_chain_rx_lane_map_physical{173.0}=0x3210 + +#FC 44 +portmap_80=177:100 +phy_chain_tx_polarity_flip_physical{177.0}=0 +phy_chain_tx_polarity_flip_physical{178.0}=1 +phy_chain_tx_polarity_flip_physical{179.0}=0 +phy_chain_tx_polarity_flip_physical{180.0}=1 +phy_chain_rx_polarity_flip_physical{177.0}=1 +phy_chain_rx_polarity_flip_physical{178.0}=1 +phy_chain_rx_polarity_flip_physical{179.0}=0 +phy_chain_rx_polarity_flip_physical{180.0}=1 +phy_chain_tx_lane_map_physical{177.0}=0x2031 +phy_chain_rx_lane_map_physical{177.0}=0x1302 + +#FC 45 +portmap_81=181:100 +phy_chain_tx_polarity_flip_physical{181.0}=0 +phy_chain_tx_polarity_flip_physical{182.0}=0 +phy_chain_tx_polarity_flip_physical{183.0}=0 +phy_chain_tx_polarity_flip_physical{184.0}=0 +phy_chain_rx_polarity_flip_physical{181.0}=0 +phy_chain_rx_polarity_flip_physical{182.0}=1 +phy_chain_rx_polarity_flip_physical{183.0}=0 +phy_chain_rx_polarity_flip_physical{184.0}=1 +phy_chain_tx_lane_map_physical{181.0}=0x1023 +phy_chain_rx_lane_map_physical{181.0}=0x2301 + +#FC 46 +portmap_82=185:100 +phy_chain_tx_polarity_flip_physical{185.0}=0 +phy_chain_tx_polarity_flip_physical{186.0}=0 +phy_chain_tx_polarity_flip_physical{187.0}=1 +phy_chain_tx_polarity_flip_physical{188.0}=0 +phy_chain_rx_polarity_flip_physical{185.0}=0 +phy_chain_rx_polarity_flip_physical{186.0}=0 +phy_chain_rx_polarity_flip_physical{187.0}=0 +phy_chain_rx_polarity_flip_physical{188.0}=0 +phy_chain_tx_lane_map_physical{185.0}=0x1320 +phy_chain_rx_lane_map_physical{185.0}=0x3210 + +#FC 47 +portmap_83=189:100 +phy_chain_tx_polarity_flip_physical{189.0}=1 +phy_chain_tx_polarity_flip_physical{190.0}=1 +phy_chain_tx_polarity_flip_physical{191.0}=0 +phy_chain_tx_polarity_flip_physical{192.0}=1 +phy_chain_rx_polarity_flip_physical{189.0}=0 +phy_chain_rx_polarity_flip_physical{190.0}=1 +phy_chain_rx_polarity_flip_physical{191.0}=0 +phy_chain_rx_polarity_flip_physical{192.0}=1 +phy_chain_tx_lane_map_physical{189.0}=0x3021 +phy_chain_rx_lane_map_physical{189.0}=0x3210 + +#PIPE-3 +#FC 48 +portmap_102=193:100 +phy_chain_tx_polarity_flip_physical{193.0}=1 +phy_chain_tx_polarity_flip_physical{194.0}=0 +phy_chain_tx_polarity_flip_physical{195.0}=1 +phy_chain_tx_polarity_flip_physical{196.0}=0 +phy_chain_rx_polarity_flip_physical{193.0}=1 +phy_chain_rx_polarity_flip_physical{194.0}=1 +phy_chain_rx_polarity_flip_physical{195.0}=0 +phy_chain_rx_polarity_flip_physical{196.0}=1 +phy_chain_tx_lane_map_physical{193.0}=0x3021 +phy_chain_rx_lane_map_physical{193.0}=0x1302 + +#FC 49 +portmap_103=197:100 +phy_chain_tx_polarity_flip_physical{197.0}=1 +phy_chain_tx_polarity_flip_physical{198.0}=0 +phy_chain_tx_polarity_flip_physical{199.0}=0 +phy_chain_tx_polarity_flip_physical{200.0}=1 +phy_chain_rx_polarity_flip_physical{197.0}=0 +phy_chain_rx_polarity_flip_physical{198.0}=1 +phy_chain_rx_polarity_flip_physical{199.0}=0 +phy_chain_rx_polarity_flip_physical{200.0}=1 +phy_chain_tx_lane_map_physical{197.0}=0x0132 +phy_chain_rx_lane_map_physical{197.0}=0x2301 + +#FC 50 +portmap_104=201:100 +phy_chain_tx_polarity_flip_physical{201.0}=1 +phy_chain_tx_polarity_flip_physical{202.0}=0 +phy_chain_tx_polarity_flip_physical{203.0}=1 +phy_chain_tx_polarity_flip_physical{204.0}=1 +phy_chain_rx_polarity_flip_physical{201.0}=0 +phy_chain_rx_polarity_flip_physical{202.0}=0 +phy_chain_rx_polarity_flip_physical{203.0}=0 +phy_chain_rx_polarity_flip_physical{204.0}=0 +phy_chain_tx_lane_map_physical{201.0}=0x2301 +phy_chain_rx_lane_map_physical{201.0}=0x1230 + +#FC 51 +portmap_105=205:100 +phy_chain_tx_polarity_flip_physical{205.0}=1 +phy_chain_tx_polarity_flip_physical{206.0}=1 +phy_chain_tx_polarity_flip_physical{207.0}=0 +phy_chain_tx_polarity_flip_physical{208.0}=0 +phy_chain_rx_polarity_flip_physical{205.0}=0 +phy_chain_rx_polarity_flip_physical{206.0}=0 +phy_chain_rx_polarity_flip_physical{207.0}=0 +phy_chain_rx_polarity_flip_physical{208.0}=1 +phy_chain_tx_lane_map_physical{205.0}=0x3021 +phy_chain_rx_lane_map_physical{205.0}=0x2130 + +#FC 52 +portmap_106=209:100 +phy_chain_tx_polarity_flip_physical{209.0}=1 +phy_chain_tx_polarity_flip_physical{210.0}=1 +phy_chain_tx_polarity_flip_physical{211.0}=0 +phy_chain_tx_polarity_flip_physical{212.0}=1 +phy_chain_rx_polarity_flip_physical{209.0}=0 +phy_chain_rx_polarity_flip_physical{210.0}=0 +phy_chain_rx_polarity_flip_physical{211.0}=1 +phy_chain_rx_polarity_flip_physical{212.0}=1 +phy_chain_tx_lane_map_physical{209.0}=0x2031 +phy_chain_rx_lane_map_physical{209.0}=0x3021 + +#FC 53 +portmap_107=213:100 +phy_chain_tx_polarity_flip_physical{213.0}=0 +phy_chain_tx_polarity_flip_physical{214.0}=1 +phy_chain_tx_polarity_flip_physical{215.0}=1 +phy_chain_tx_polarity_flip_physical{216.0}=0 +phy_chain_rx_polarity_flip_physical{213.0}=0 +phy_chain_rx_polarity_flip_physical{214.0}=1 +phy_chain_rx_polarity_flip_physical{215.0}=0 +phy_chain_rx_polarity_flip_physical{216.0}=1 +phy_chain_tx_lane_map_physical{213.0}=0x1302 +phy_chain_rx_lane_map_physical{213.0}=0x1032 + +#FC 54 +portmap_108=217:100 +phy_chain_tx_polarity_flip_physical{217.0}=1 +phy_chain_tx_polarity_flip_physical{218.0}=0 +phy_chain_tx_polarity_flip_physical{219.0}=1 +phy_chain_tx_polarity_flip_physical{220.0}=1 +phy_chain_rx_polarity_flip_physical{217.0}=0 +phy_chain_rx_polarity_flip_physical{218.0}=0 +phy_chain_rx_polarity_flip_physical{219.0}=0 +phy_chain_rx_polarity_flip_physical{220.0}=0 +phy_chain_tx_lane_map_physical{217.0}=0x2301 +phy_chain_rx_lane_map_physical{217.0}=0x1230 + +#FC 55 +portmap_109=221:100 +phy_chain_tx_polarity_flip_physical{221.0}=0 +phy_chain_tx_polarity_flip_physical{222.0}=0 +phy_chain_tx_polarity_flip_physical{223.0}=0 +phy_chain_tx_polarity_flip_physical{224.0}=0 +phy_chain_rx_polarity_flip_physical{221.0}=0 +phy_chain_rx_polarity_flip_physical{222.0}=1 +phy_chain_rx_polarity_flip_physical{223.0}=0 +phy_chain_rx_polarity_flip_physical{224.0}=1 +phy_chain_tx_lane_map_physical{221.0}=0x3210 +phy_chain_rx_lane_map_physical{221.0}=0x2310 + +#FC 56 +portmap_110=225:100 +phy_chain_tx_polarity_flip_physical{225.0}=0 +phy_chain_tx_polarity_flip_physical{226.0}=0 +phy_chain_tx_polarity_flip_physical{227.0}=1 +phy_chain_tx_polarity_flip_physical{228.0}=0 +phy_chain_rx_polarity_flip_physical{225.0}=0 +phy_chain_rx_polarity_flip_physical{226.0}=1 +phy_chain_rx_polarity_flip_physical{227.0}=1 +phy_chain_rx_polarity_flip_physical{228.0}=1 +phy_chain_tx_lane_map_physical{225.0}=0x3120 +phy_chain_rx_lane_map_physical{225.0}=0x3021 + +#FC 57 +portmap_111=229:100 +phy_chain_tx_polarity_flip_physical{229.0}=0 +phy_chain_tx_polarity_flip_physical{230.0}=0 +phy_chain_tx_polarity_flip_physical{231.0}=1 +phy_chain_tx_polarity_flip_physical{232.0}=0 +phy_chain_rx_polarity_flip_physical{229.0}=0 +phy_chain_rx_polarity_flip_physical{230.0}=0 +phy_chain_rx_polarity_flip_physical{231.0}=1 +phy_chain_rx_polarity_flip_physical{232.0}=1 +phy_chain_tx_lane_map_physical{229.0}=0x0231 +phy_chain_rx_lane_map_physical{229.0}=0x2031 + +#FC 58 +portmap_112=233:100 +phy_chain_tx_polarity_flip_physical{233.0}=1 +phy_chain_tx_polarity_flip_physical{234.0}=0 +phy_chain_tx_polarity_flip_physical{235.0}=0 +phy_chain_tx_polarity_flip_physical{236.0}=0 +phy_chain_rx_polarity_flip_physical{233.0}=0 +phy_chain_rx_polarity_flip_physical{234.0}=0 +phy_chain_rx_polarity_flip_physical{235.0}=1 +phy_chain_rx_polarity_flip_physical{236.0}=1 +phy_chain_tx_lane_map_physical{233.0}=0x1023 +phy_chain_rx_lane_map_physical{233.0}=0x1203 + +#FC 59 +portmap_113=237:100 +phy_chain_tx_polarity_flip_physical{237.0}=0 +phy_chain_tx_polarity_flip_physical{238.0}=0 +phy_chain_tx_polarity_flip_physical{239.0}=1 +phy_chain_tx_polarity_flip_physical{240.0}=0 +phy_chain_rx_polarity_flip_physical{237.0}=1 +phy_chain_rx_polarity_flip_physical{238.0}=0 +phy_chain_rx_polarity_flip_physical{239.0}=0 +phy_chain_rx_polarity_flip_physical{240.0}=0 +phy_chain_tx_lane_map_physical{237.0}=0x2013 +phy_chain_rx_lane_map_physical{237.0}=0x0213 + +#FC 60 +portmap_114=241:100 +phy_chain_tx_polarity_flip_physical{241.0}=0 +phy_chain_tx_polarity_flip_physical{242.0}=1 +phy_chain_tx_polarity_flip_physical{243.0}=0 +phy_chain_tx_polarity_flip_physical{244.0}=0 +phy_chain_rx_polarity_flip_physical{241.0}=0 +phy_chain_rx_polarity_flip_physical{242.0}=0 +phy_chain_rx_polarity_flip_physical{243.0}=0 +phy_chain_rx_polarity_flip_physical{244.0}=0 +phy_chain_tx_lane_map_physical{241.0}=0x1032 +phy_chain_rx_lane_map_physical{241.0}=0x2310 + +#FC 61 +portmap_115=245:100 +phy_chain_tx_polarity_flip_physical{245.0}=1 +phy_chain_tx_polarity_flip_physical{246.0}=0 +phy_chain_tx_polarity_flip_physical{247.0}=0 +phy_chain_tx_polarity_flip_physical{248.0}=1 +phy_chain_rx_polarity_flip_physical{245.0}=1 +phy_chain_rx_polarity_flip_physical{246.0}=1 +phy_chain_rx_polarity_flip_physical{247.0}=0 +phy_chain_rx_polarity_flip_physical{248.0}=1 +phy_chain_tx_lane_map_physical{245.0}=0x1302 +phy_chain_rx_lane_map_physical{245.0}=0x1302 + +#FC 62 +portmap_116=249:100 +phy_chain_tx_polarity_flip_physical{249.0}=0 +phy_chain_tx_polarity_flip_physical{250.0}=1 +phy_chain_tx_polarity_flip_physical{251.0}=0 +phy_chain_tx_polarity_flip_physical{252.0}=0 +phy_chain_rx_polarity_flip_physical{249.0}=1 +phy_chain_rx_polarity_flip_physical{250.0}=1 +phy_chain_rx_polarity_flip_physical{251.0}=0 +phy_chain_rx_polarity_flip_physical{252.0}=0 +phy_chain_tx_lane_map_physical{249.0}=0x1032 +phy_chain_rx_lane_map_physical{249.0}=0x1203 + +#FC 63 +portmap_117=253:100 +phy_chain_tx_polarity_flip_physical{253.0}=0 +phy_chain_tx_polarity_flip_physical{254.0}=0 +phy_chain_tx_polarity_flip_physical{255.0}=0 +phy_chain_tx_polarity_flip_physical{256.0}=1 +phy_chain_rx_polarity_flip_physical{253.0}=0 +phy_chain_rx_polarity_flip_physical{254.0}=1 +phy_chain_rx_polarity_flip_physical{255.0}=1 +phy_chain_rx_polarity_flip_physical{256.0}=0 +phy_chain_tx_lane_map_physical{253.0}=0x3210 +phy_chain_rx_lane_map_physical{253.0}=0x2103 + + + +#MGMT +portmap_66=257:10 +portmap_100=259:10 +#phy_chain_tx_lane_map_physical{257.0}=0x0123 +#phy_chain_rx_lane_map_physical{257.0}=0x0123 + +#LPBK +portmap_33=260:10 +portmap_67=261:10 +portmap_101=262:10 +portmap_135=263:10 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/default_sku new file mode 100644 index 000000000000..30331b0d9fc0 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S9200-64X t1 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/fancontrol new file mode 100644 index 000000000000..489ebeaee95d --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +DEVPATH=hwmon5=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-002f hwmon2=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-7/7-004d +DEVNAME=hwmon5=w83795adg +FCTEMPS=hwmon5/device/pwm2=hwmon2/temp1_input +FCFANS=hwmon5/device/pwm2=hwmon5/device/fan7_input hwmon5/device/pwm2=hwmon5/device/fan5_input hwmon5/device/pwm2=hwmon5/device/fan3_input hwmon5/device/pwm2=hwmon5/device/fan1_input +MINTEMP=hwmon5/device/pwm2=20 +MAXTEMP=hwmon5/device/pwm2=60 +MINSTART=hwmon5/device/pwm2=75 +MINSTOP=hwmon5/device/pwm2=22 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/led_proc_init.soc b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/led_proc_init.soc new file mode 100644 index 000000000000..774923ff868d --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/led_proc_init.soc @@ -0,0 +1,111 @@ +#processor initialization for Ingrasys S9200-64X + +led 0 stop +led 0 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0F 87 22 0E 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=56 REMAP_PORT_2=57 REMAP_PORT_1=58 REMAP_PORT_0=59 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=60 REMAP_PORT_6=61 REMAP_PORT_5=62 REMAP_PORT_4=63 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=52 REMAP_PORT_10=53 REMAP_PORT_9=54 REMAP_PORT_8=55 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=48 REMAP_PORT_14=49 REMAP_PORT_13=50 REMAP_PORT_12=51 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=40 REMAP_PORT_18=41 REMAP_PORT_17=42 REMAP_PORT_16=43 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=44 REMAP_PORT_22=45 REMAP_PORT_21=46 REMAP_PORT_20=47 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 REMAP_PORT_26=37 REMAP_PORT_25=38 REMAP_PORT_24=39 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 REMAP_PORT_30=33 REMAP_PORT_29=34 REMAP_PORT_28=35 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=24 REMAP_PORT_34=25 REMAP_PORT_33=26 REMAP_PORT_32=27 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=28 REMAP_PORT_38=29 REMAP_PORT_37=30 REMAP_PORT_36=31 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=20 REMAP_PORT_42=21 REMAP_PORT_41=22 REMAP_PORT_40=23 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=16 REMAP_PORT_46=17 REMAP_PORT_45=18 REMAP_PORT_44=19 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=8 REMAP_PORT_50=9 REMAP_PORT_49=10 REMAP_PORT_48=11 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=12 REMAP_PORT_54=13 REMAP_PORT_53=14 REMAP_PORT_52=15 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 REMAP_PORT_58=5 REMAP_PORT_57=6 REMAP_PORT_56=7 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 REMAP_PORT_62=1 REMAP_PORT_61=2 REMAP_PORT_60=3 + +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0F 87 22 0E 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=12 REMAP_PORT_10=13 REMAP_PORT_9=14 REMAP_PORT_8=15 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=8 REMAP_PORT_14=9 REMAP_PORT_13=10 REMAP_PORT_12=11 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=16 REMAP_PORT_18=17 REMAP_PORT_17=18 REMAP_PORT_16=19 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=20 REMAP_PORT_22=21 REMAP_PORT_21=22 REMAP_PORT_20=23 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=28 REMAP_PORT_26=29 REMAP_PORT_25=30 REMAP_PORT_24=31 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24 REMAP_PORT_30=25 REMAP_PORT_29=26 REMAP_PORT_28=27 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=32 REMAP_PORT_34=33 REMAP_PORT_33=34 REMAP_PORT_32=35 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=36 REMAP_PORT_38=37 REMAP_PORT_37=38 REMAP_PORT_36=39 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=44 REMAP_PORT_42=45 REMAP_PORT_41=46 REMAP_PORT_40=47 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=40 REMAP_PORT_46=41 REMAP_PORT_45=42 REMAP_PORT_44=43 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=48 REMAP_PORT_50=49 REMAP_PORT_49=50 REMAP_PORT_48=51 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=52 REMAP_PORT_54=53 REMAP_PORT_53=54 REMAP_PORT_52=55 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=60 REMAP_PORT_58=61 REMAP_PORT_57=62 REMAP_PORT_56=63 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56 REMAP_PORT_62=57 REMAP_PORT_61=58 REMAP_PORT_60=59 + +led 1 auto on +led 1 start + +led 2 stop +led 2 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0F 87 22 0E 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=56 REMAP_PORT_2=57 REMAP_PORT_1=58 REMAP_PORT_0=59 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=60 REMAP_PORT_6=61 REMAP_PORT_5=62 REMAP_PORT_4=63 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=52 REMAP_PORT_10=53 REMAP_PORT_9=54 REMAP_PORT_8=55 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=48 REMAP_PORT_14=49 REMAP_PORT_13=50 REMAP_PORT_12=51 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=40 REMAP_PORT_18=41 REMAP_PORT_17=42 REMAP_PORT_16=43 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=44 REMAP_PORT_22=45 REMAP_PORT_21=46 REMAP_PORT_20=47 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 REMAP_PORT_26=37 REMAP_PORT_25=38 REMAP_PORT_24=39 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 REMAP_PORT_30=33 REMAP_PORT_29=34 REMAP_PORT_28=35 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=24 REMAP_PORT_34=25 REMAP_PORT_33=26 REMAP_PORT_32=27 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=28 REMAP_PORT_38=29 REMAP_PORT_37=30 REMAP_PORT_36=31 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=20 REMAP_PORT_42=21 REMAP_PORT_41=22 REMAP_PORT_40=23 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=16 REMAP_PORT_46=17 REMAP_PORT_45=18 REMAP_PORT_44=19 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=8 REMAP_PORT_50=9 REMAP_PORT_49=10 REMAP_PORT_48=11 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=12 REMAP_PORT_54=13 REMAP_PORT_53=14 REMAP_PORT_52=15 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 REMAP_PORT_58=5 REMAP_PORT_57=6 REMAP_PORT_56=7 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 REMAP_PORT_62=1 REMAP_PORT_61=2 REMAP_PORT_60=3 + +led 2 auto on +led 2 start + +led 3 stop +led 3 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0F 87 22 0E 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=12 REMAP_PORT_10=13 REMAP_PORT_9=14 REMAP_PORT_8=15 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=8 REMAP_PORT_14=9 REMAP_PORT_13=10 REMAP_PORT_12=11 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=16 REMAP_PORT_18=17 REMAP_PORT_17=18 REMAP_PORT_16=19 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=20 REMAP_PORT_22=21 REMAP_PORT_21=22 REMAP_PORT_20=23 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=28 REMAP_PORT_26=29 REMAP_PORT_25=30 REMAP_PORT_24=31 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24 REMAP_PORT_30=25 REMAP_PORT_29=26 REMAP_PORT_28=27 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=32 REMAP_PORT_34=33 REMAP_PORT_33=34 REMAP_PORT_32=35 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=36 REMAP_PORT_38=37 REMAP_PORT_37=38 REMAP_PORT_36=39 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=44 REMAP_PORT_42=45 REMAP_PORT_41=46 REMAP_PORT_40=47 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=40 REMAP_PORT_46=41 REMAP_PORT_45=42 REMAP_PORT_44=43 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=48 REMAP_PORT_50=49 REMAP_PORT_49=50 REMAP_PORT_48=51 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=52 REMAP_PORT_54=53 REMAP_PORT_53=54 REMAP_PORT_52=55 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=60 REMAP_PORT_58=61 REMAP_PORT_57=62 REMAP_PORT_56=63 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56 REMAP_PORT_62=57 REMAP_PORT_61=58 REMAP_PORT_60=59 + +led 3 auto on +led 3 start + +led 4 stop +led 4 prog 12 00 61 F1 12 40 61 F2 12 01 61 F3 12 01 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0F 87 22 0E 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=62 REMAP_PORT_2=0 REMAP_PORT_1=63 REMAP_PORT_0=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=0 REMAP_PORT_6=0 REMAP_PORT_5=0 REMAP_PORT_4=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=0 REMAP_PORT_10=0 REMAP_PORT_9=0 REMAP_PORT_8=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=0 REMAP_PORT_14=0 REMAP_PORT_13=0 REMAP_PORT_12=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=0 REMAP_PORT_18=0 REMAP_PORT_17=0 REMAP_PORT_16=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=0 REMAP_PORT_22=0 REMAP_PORT_21=0 REMAP_PORT_20=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=0 REMAP_PORT_26=0 REMAP_PORT_25=0 REMAP_PORT_24=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0 REMAP_PORT_30=0 REMAP_PORT_29=0 REMAP_PORT_28=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=0 REMAP_PORT_34=0 REMAP_PORT_33=0 REMAP_PORT_32=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=0 REMAP_PORT_38=0 REMAP_PORT_37=0 REMAP_PORT_36=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=0 REMAP_PORT_42=0 REMAP_PORT_41=0 REMAP_PORT_40=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=0 REMAP_PORT_46=0 REMAP_PORT_45=0 REMAP_PORT_44=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=0 REMAP_PORT_50=0 REMAP_PORT_49=0 REMAP_PORT_48=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=0 REMAP_PORT_54=0 REMAP_PORT_53=0 REMAP_PORT_52=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=0 REMAP_PORT_58=0 REMAP_PORT_57=0 REMAP_PORT_56=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 REMAP_PORT_62=0 REMAP_PORT_61=0 REMAP_PORT_60=0 + +led 4 auto on +led 4 start diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..64ddb99554b0 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +############################################################################# +# Ingrasys S9200-64X +# +# 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): + i2c_bus = "0" + i2c_addr = "0051" + self.eeprom_path = "/sys/class/i2c-adapter/i2c-" + i2c_bus + "/" + i2c_bus + "-" + i2c_addr + "/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..cc996057e09e --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/psuutil.py @@ -0,0 +1,92 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/i2c-18/18-0050", + "/sys/bus/i2c/devices/i2c-17/17-0050"] + + def __init__(self): + PsuBase.__init__(self) + + + # Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + attr_file = 'psu_pg' + attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU status + if (attr_value == 1): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_absent = 0 + attr_file ='psu_abs' + attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU presence + if (attr_value == 0): + status = 1 + + return status + diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..584b0e9716b8 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/sfputil.py @@ -0,0 +1,268 @@ +# 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 = 63 + PORTS_IN_BLOCK = 64 + + EEPROM_OFFSET = 29 + + _port_to_eeprom_mapping = {} + + _logic_to_phy_port_mapping = { + 0: 0, + 1: 1, + 2: 4, + 3: 5, + 4: 8, + 5: 9, + 6: 12, + 7: 13, + 8: 16, + 9: 17, + 10: 20, + 11: 21, + 12: 24, + 13: 25, + 14: 28, + 15: 29, + 16: 32, + 17: 33, + 18: 36, + 19: 37, + 20: 40, + 21: 41, + 22: 44, + 23: 45, + 24: 48, + 25: 49, + 26: 52, + 27: 53, + 28: 56, + 29: 57, + 30: 60, + 31: 61, + 32: 2, + 33: 3, + 34: 6, + 35: 7, + 36: 10, + 37: 11, + 38: 14, + 39: 15, + 40: 18, + 41: 19, + 42: 22, + 43: 23, + 44: 26, + 45: 27, + 46: 30, + 47: 31, + 48: 34, + 49: 35, + 50: 38, + 51: 39, + 52: 42, + 53: 43, + 54: 46, + 55: 47, + 56: 50, + 57: 51, + 58: 54, + 59: 55, + 60: 58, + 61: 59, + 62: 62, + 63: 63 + } + + @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 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): + phy_port = self._logic_to_phy_port_mapping[x] + self._port_to_eeprom_mapping[x] = eeprom_path.format(phy_port + self.EEPROM_OFFSET) + + 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 + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + try: + reg_file = open("/sys/devices/platform/ingrasys-s9200-cpld.0/qsfp_modprs") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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 + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + try: + reg_file = open("/sys/devices/platform/ingrasys-s9200-cpld.0/qsfp_lpmode") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 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 + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + try: + reg_file = open("/sys/devices/platform/ingrasys-s9200-cpld.0/qsfp_lpmode", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + + # content is a string containing the hex representation of the register + reg_value = int(content, 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 = format(reg_value, 'x') + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/ingrasys-s9200-cpld.0/qsfp_reset" + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + 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 + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # 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 + content = format(reg_value, 'x') + + reg_file.seek(0) + reg_file.write(content) + 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: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_value | mask + content = format(reg_value, 'x') + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/sensors.conf new file mode 100644 index 000000000000..25ab494e1f87 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/sensors.conf @@ -0,0 +1,80 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + label temp1 "DIMM Temp" + set temp1_max 50 + set temp1_crit 85 + +chip "w83795adg-*" + ignore in0 + label in1 "P0V9" + set in1_min 0.84 * 0.97 + set in1_max 0.96 * 1.03 + ignore in2 + label in3 "P1V8" + set in3_min 1.8 * 0.97 + set in3_max 1.8 * 1.03 + label in4 "P1V0" + set in4_min 1.0 * 0.97 + set in4_max 1.0 * 1.03 + label in5 "P0V8" + set in5_min 0.831 * 0.97 + set in5_max 0.831 * 1.03 + ignore in6 + ignore in7 + ignore in8 + ignore in9 + ignore in10 + ignore in11 + ignore in12 + ignore in13 + ignore in14 + ignore in15 + ignore in16 + ignore in17 + ignore in18 + ignore in19 + label fan1 "FANTRAY 1" + ignore fan2 + label fan3 "FANTRAY 2" + ignore fan4 + label fan5 "FANTRAY 3" + ignore fan6 + label fan7 "FANTRAY 4" + ignore fan8 + ignore temp1 + ignore temp2 + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore intrusion0 + +chip "tmp75-i2c-*-4A" + label temp1 "BMC Board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +chip "tmp75-i2c-*-4F" + label temp1 "x86 CPU Board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-6" "i2c-0-mux (chan_id 5)" +chip "lm75-i2c-6-4E" + label temp1 "MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +chip "lm75-i2c-6-4D" + label temp1 "REAR MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-7" "i2c-0-mux (chan_id 6)" +chip "lm75-i2c-7-4D" + label temp1 "Front MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers.json.j2 b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers.json.j2 new file mode 100644 index 000000000000..9354b7ec5b59 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers_defaults_t0.j2 b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..82194b2c3188 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers_defaults_t0.j2 @@ -0,0 +1,69 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20971328' %} +{% set ingress_lossy_pool_size = '20971328' %} +{% set egress_lossless_pool_size = '20971328' %} +{% set egress_lossy_pool_size = '20971328' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0, 64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx*4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xon":"78400", + "xoff":"132160", + "size":"3584", + "static_th":"82880" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"3584", + "dynamic_th":"-1" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"3584", + "dynamic_th":"-4" + } + }, +{%- endmacro %} + +{# the typo of generate_pg_profils dued to buffers_config.j2 #} +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + } +{%- endmacro %} + +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + } +{%- endmacro %} \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers_defaults_t1.j2 b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..82194b2c3188 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers_defaults_t1.j2 @@ -0,0 +1,69 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20971328' %} +{% set ingress_lossy_pool_size = '20971328' %} +{% set egress_lossless_pool_size = '20971328' %} +{% set egress_lossy_pool_size = '20971328' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0, 64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx*4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xon":"78400", + "xoff":"132160", + "size":"3584", + "static_th":"82880" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"3584", + "dynamic_th":"-1" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"3584", + "dynamic_th":"-4" + } + }, +{%- endmacro %} + +{# the typo of generate_pg_profils dued to buffers_config.j2 #} +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + } +{%- endmacro %} + +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + } +{%- endmacro %} \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/pg_profile_lookup.ini b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/pg_profile_lookup.ini new file mode 100644 index 000000000000..d98b0eca6d19 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 3584 32256 59136 36736 + 25000 5m 3584 41216 68096 45696 + 40000 5m 3584 47488 74368 51968 + 50000 5m 3584 52864 79744 57344 + 100000 5m 3584 78400 132160 82880 + 10000 40m 3584 32256 59136 36736 + 25000 40m 3584 41216 68096 45696 + 40000 40m 3584 47488 74368 51968 + 50000 40m 3584 52864 79744 57344 + 100000 40m 3584 78400 132160 82880 + 10000 300m 3584 32256 65856 36736 + 25000 300m 3584 41216 84672 45696 + 40000 300m 3584 47488 101024 51968 + 50000 300m 3584 52864 113120 57344 + 100000 300m 3584 78400 198688 82880 \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/port_config.ini b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/port_config.ini new file mode 100644 index 000000000000..d57c1f350186 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index +Ethernet0 0,1,2,3 Ethernet1/1 0 +Ethernet4 4,5,6,7 Ethernet2/1 1 +Ethernet8 20,21,22,23 Ethernet3/1 2 +Ethernet12 16,17,18,19 Ethernet4/1 3 +Ethernet16 36,37,38,39 Ethernet5/1 4 +Ethernet20 32,33,34,35 Ethernet6/1 5 +Ethernet24 52,53,54,55 Ethernet7/1 6 +Ethernet28 48,49,50,51 Ethernet8/1 7 +Ethernet32 68,69,70,71 Ethernet9/1 8 +Ethernet36 64,65,66,67 Ethernet10/1 9 +Ethernet40 84,85,86,87 Ethernet11/1 10 +Ethernet44 80,81,82,83 Ethernet12/1 11 +Ethernet48 100,101,102,103 Ethernet13/1 12 +Ethernet52 96,97,98,99 Ethernet14/1 13 +Ethernet56 116,117,118,119 Ethernet15/1 14 +Ethernet60 112,113,114,115 Ethernet16/1 15 +Ethernet64 132,133,134,135 Ethernet17/1 16 +Ethernet68 128,129,130,131 Ethernet18/1 17 +Ethernet72 148,149,150,151 Ethernet19/1 18 +Ethernet76 144,145,146,147 Ethernet20/1 19 +Ethernet80 164,165,166,167 Ethernet21/1 20 +Ethernet84 160,161,162,163 Ethernet22/1 21 +Ethernet88 180,181,182,183 Ethernet23/1 22 +Ethernet92 176,177,178,179 Ethernet24/1 23 +Ethernet96 196,197,198,199 Ethernet25/1 24 +Ethernet100 192,193,194,195 Ethernet26/1 25 +Ethernet104 212,213,214,215 Ethernet27/1 26 +Ethernet108 208,209,210,211 Ethernet28/1 27 +Ethernet112 228,229,230,231 Ethernet29/1 28 +Ethernet116 224,225,226,227 Ethernet30/1 29 +Ethernet120 244,245,246,247 Ethernet31/1 30 +Ethernet124 240,241,242,243 Ethernet32/1 31 +Ethernet128 12,13,14,15 Ethernet33/1 32 +Ethernet132 8,9,10,11 Ethernet34/1 33 +Ethernet136 28,29,30,31 Ethernet35/1 34 +Ethernet140 24,25,26,27 Ethernet36/1 35 +Ethernet144 44,45,46,47 Ethernet37/1 36 +Ethernet148 40,41,42,43 Ethernet38/1 37 +Ethernet152 60,61,62,63 Ethernet39/1 38 +Ethernet156 56,57,58,59 Ethernet40/1 39 +Ethernet160 76,77,78,79 Ethernet41/1 40 +Ethernet164 72,73,74,75 Ethernet42/1 41 +Ethernet168 92,93,94,95 Ethernet43/1 42 +Ethernet172 88,89,90,91 Ethernet44/1 43 +Ethernet176 108,109,110,111 Ethernet45/1 44 +Ethernet180 104,105,106,107 Ethernet46/1 45 +Ethernet184 124,125,126,127 Ethernet47/1 46 +Ethernet188 120,121,122,123 Ethernet48/1 47 +Ethernet192 140,141,142,143 Ethernet49/1 48 +Ethernet196 136,137,138,139 Ethernet50/1 49 +Ethernet200 156,157,158,159 Ethernet51/1 50 +Ethernet204 152,153,154,155 Ethernet52/1 51 +Ethernet208 172,173,174,175 Ethernet53/1 52 +Ethernet212 168,169,170,171 Ethernet54/1 53 +Ethernet216 188,189,190,191 Ethernet55/1 54 +Ethernet220 184,185,186,187 Ethernet56/1 55 +Ethernet224 204,205,206,207 Ethernet57/1 56 +Ethernet228 200,201,202,203 Ethernet58/1 57 +Ethernet232 220,221,222,223 Ethernet59/1 58 +Ethernet236 216,217,218,219 Ethernet60/1 59 +Ethernet240 236,237,238,239 Ethernet61/1 60 +Ethernet244 232,233,234,235 Ethernet62/1 61 +Ethernet248 248,249,250,251 Ethernet63/1 62 +Ethernet252 252,253,254,255 Ethernet64/1 63 \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/port_config.nps b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/port_config.nps new file mode 100644 index 000000000000..0e14b9ced3fe --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/port_config.nps @@ -0,0 +1,681 @@ +init start stage low-level +init set port-map port=0 eth-macro=0 lane=0 max-speed=100g active=true +init set port-map port=1 eth-macro=1 lane=0 max-speed=100g active=true +init set port-map port=2 eth-macro=5 lane=0 max-speed=100g active=true +init set port-map port=3 eth-macro=4 lane=0 max-speed=100g active=true +init set port-map port=4 eth-macro=9 lane=0 max-speed=100g active=true +init set port-map port=5 eth-macro=8 lane=0 max-speed=100g active=true +init set port-map port=6 eth-macro=13 lane=0 max-speed=100g active=true +init set port-map port=7 eth-macro=12 lane=0 max-speed=100g active=true +init set port-map port=8 eth-macro=17 lane=0 max-speed=100g active=true +init set port-map port=9 eth-macro=16 lane=0 max-speed=100g active=true +init set port-map port=10 eth-macro=21 lane=0 max-speed=100g active=true +init set port-map port=11 eth-macro=20 lane=0 max-speed=100g active=true +init set port-map port=12 eth-macro=25 lane=0 max-speed=100g active=true +init set port-map port=13 eth-macro=24 lane=0 max-speed=100g active=true +init set port-map port=14 eth-macro=29 lane=0 max-speed=100g active=true +init set port-map port=15 eth-macro=28 lane=0 max-speed=100g active=true +init set port-map port=16 eth-macro=33 lane=0 max-speed=100g active=true +init set port-map port=17 eth-macro=32 lane=0 max-speed=100g active=true +init set port-map port=18 eth-macro=37 lane=0 max-speed=100g active=true +init set port-map port=19 eth-macro=36 lane=0 max-speed=100g active=true +init set port-map port=20 eth-macro=41 lane=0 max-speed=100g active=true +init set port-map port=21 eth-macro=40 lane=0 max-speed=100g active=true +init set port-map port=22 eth-macro=45 lane=0 max-speed=100g active=true +init set port-map port=23 eth-macro=44 lane=0 max-speed=100g active=true +init set port-map port=24 eth-macro=49 lane=0 max-speed=100g active=true +init set port-map port=25 eth-macro=48 lane=0 max-speed=100g active=true +init set port-map port=26 eth-macro=53 lane=0 max-speed=100g active=true +init set port-map port=27 eth-macro=52 lane=0 max-speed=100g active=true +init set port-map port=28 eth-macro=57 lane=0 max-speed=100g active=true +init set port-map port=29 eth-macro=56 lane=0 max-speed=100g active=true +init set port-map port=30 eth-macro=61 lane=0 max-speed=100g active=true +init set port-map port=31 eth-macro=60 lane=0 max-speed=100g active=true +init set port-map port=32 eth-macro=3 lane=0 max-speed=100g active=true +init set port-map port=33 eth-macro=2 lane=0 max-speed=100g active=true +init set port-map port=34 eth-macro=7 lane=0 max-speed=100g active=true +init set port-map port=35 eth-macro=6 lane=0 max-speed=100g active=true +init set port-map port=36 eth-macro=11 lane=0 max-speed=100g active=true +init set port-map port=37 eth-macro=10 lane=0 max-speed=100g active=true +init set port-map port=38 eth-macro=15 lane=0 max-speed=100g active=true +init set port-map port=39 eth-macro=14 lane=0 max-speed=100g active=true +init set port-map port=40 eth-macro=19 lane=0 max-speed=100g active=true +init set port-map port=41 eth-macro=18 lane=0 max-speed=100g active=true +init set port-map port=42 eth-macro=23 lane=0 max-speed=100g active=true +init set port-map port=43 eth-macro=22 lane=0 max-speed=100g active=true +init set port-map port=44 eth-macro=27 lane=0 max-speed=100g active=true +init set port-map port=45 eth-macro=26 lane=0 max-speed=100g active=true +init set port-map port=46 eth-macro=31 lane=0 max-speed=100g active=true +init set port-map port=47 eth-macro=30 lane=0 max-speed=100g active=true +init set port-map port=48 eth-macro=35 lane=0 max-speed=100g active=true +init set port-map port=49 eth-macro=34 lane=0 max-speed=100g active=true +init set port-map port=50 eth-macro=39 lane=0 max-speed=100g active=true +init set port-map port=51 eth-macro=38 lane=0 max-speed=100g active=true +init set port-map port=52 eth-macro=43 lane=0 max-speed=100g active=true +init set port-map port=53 eth-macro=42 lane=0 max-speed=100g active=true +init set port-map port=54 eth-macro=47 lane=0 max-speed=100g active=true +init set port-map port=55 eth-macro=46 lane=0 max-speed=100g active=true +init set port-map port=56 eth-macro=51 lane=0 max-speed=100g active=true +init set port-map port=57 eth-macro=50 lane=0 max-speed=100g active=true +init set port-map port=58 eth-macro=55 lane=0 max-speed=100g active=true +init set port-map port=59 eth-macro=54 lane=0 max-speed=100g active=true +init set port-map port=60 eth-macro=59 lane=0 max-speed=100g active=true +init set port-map port=61 eth-macro=58 lane=0 max-speed=100g active=true +init set port-map port=62 eth-macro=62 lane=0 max-speed=100g active=true +init set port-map port=63 eth-macro=63 lane=0 max-speed=100g active=true +init set port-map port=129 eth-macro=0 lane=1 max-speed=10g active=true guarantee=true cpi=true +init set port-map port=130 eth-macro=0 lane=0 max-speed=10g active=true guarantee=true cpi=true init-done=true + +init start stage task-rsrc +init start stage module +init start stage task + +phy set lane-swap portlist=0 lane-cnt=4 property=tx data=0x3.2.0.1 +phy set lane-swap portlist=1 lane-cnt=4 property=tx data=0x2.1.3.0 +phy set lane-swap portlist=2 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=3 lane-cnt=4 property=tx data=0x2.3.0.1 +phy set lane-swap portlist=4 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=5 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=6 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=7 lane-cnt=4 property=tx data=0x1.0.2.3 +phy set lane-swap portlist=8 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=9 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=10 lane-cnt=4 property=tx data=0x0.3.2.1 +phy set lane-swap portlist=11 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=12 lane-cnt=4 property=tx data=0x3.2.0.1 +phy set lane-swap portlist=13 lane-cnt=4 property=tx data=0x3.2.1.0 +phy set lane-swap portlist=14 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=15 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=16 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=17 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=18 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=19 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=20 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=21 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=22 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=23 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=24 lane-cnt=4 property=tx data=0x0.3.2.1 +phy set lane-swap portlist=25 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=26 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=27 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=28 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=29 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=30 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=31 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=32 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=33 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=34 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=35 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=36 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=37 lane-cnt=4 property=tx data=0x3.1.0.2 +phy set lane-swap portlist=38 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=39 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=40 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=41 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=42 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=43 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=44 lane-cnt=4 property=tx data=0x3.2.1.0 +phy set lane-swap portlist=45 lane-cnt=4 property=tx data=0x3.2.1.0 +phy set lane-swap portlist=46 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=47 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=48 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=49 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=50 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=51 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=52 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=53 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=54 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=55 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=56 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=57 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=58 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=59 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=60 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=61 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=62 lane-cnt=4 property=tx data=0x1.0.2.3 +phy set lane-swap portlist=63 lane-cnt=4 property=tx data=0x3.1.0.2 +phy set lane-swap portlist=129 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=130 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=0 lane-cnt=4 property=rx data=0x2.0.3.1 +phy set lane-swap portlist=1 lane-cnt=4 property=rx data=0x1.3.0.2 +phy set lane-swap portlist=2 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=3 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=4 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=5 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=6 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=7 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=8 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=9 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=10 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=11 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=12 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set lane-swap portlist=13 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set lane-swap portlist=14 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=15 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=16 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=17 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=18 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=19 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=20 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=21 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=22 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=23 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=24 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=25 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=26 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=27 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=28 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=29 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=30 lane-cnt=4 property=rx data=0x0.2.1.3 +phy set lane-swap portlist=31 lane-cnt=4 property=rx data=0x0.2.1.3 +phy set lane-swap portlist=32 lane-cnt=4 property=rx data=0x0.2.1.3 +phy set lane-swap portlist=33 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=34 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=35 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=36 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=37 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=38 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=39 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=40 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=41 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=42 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=43 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=44 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set lane-swap portlist=45 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set lane-swap portlist=46 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=47 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=48 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=49 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=50 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=51 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=52 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=53 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=54 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=55 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=56 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=57 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=58 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=59 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=60 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=61 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=62 lane-cnt=4 property=rx data=0x1.3.0.2 +phy set lane-swap portlist=63 lane-cnt=4 property=rx data=0x3.1.2.0 +phy set lane-swap portlist=129 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=130 lane-cnt=1 property=rx data=0x0 + +phy set polarity-rev portlist=0 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=1 lane-cnt=4 property=tx data=0x0.1.0.0 +phy set polarity-rev portlist=2 lane-cnt=4 property=tx data=0x1.0.0.1 +phy set polarity-rev portlist=3 lane-cnt=4 property=tx data=0x1.1.1.1 +phy set polarity-rev portlist=4 lane-cnt=4 property=tx data=0x0.1.0.1 +phy set polarity-rev portlist=5 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=6 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=7 lane-cnt=4 property=tx data=0x1.0.0.0 +phy set polarity-rev portlist=8 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=9 lane-cnt=4 property=tx data=0x0.1.0.0 +phy set polarity-rev portlist=10 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=11 lane-cnt=4 property=tx data=0x0.1.0.0 +phy set polarity-rev portlist=12 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=13 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=14 lane-cnt=4 property=tx data=0x1.0.0.0 +phy set polarity-rev portlist=15 lane-cnt=4 property=tx data=0x0.1.0.0 +phy set polarity-rev portlist=16 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=17 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=18 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=19 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=20 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=21 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=22 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=23 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=24 lane-cnt=4 property=tx data=0x0.0.1.0 +phy set polarity-rev portlist=25 lane-cnt=4 property=tx data=0x1.0.0.1 +phy set polarity-rev portlist=26 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=27 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=28 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=29 lane-cnt=4 property=tx data=0x0.1.0.0 +phy set polarity-rev portlist=30 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=31 lane-cnt=4 property=tx data=0x0.0.1.0 +phy set polarity-rev portlist=32 lane-cnt=4 property=tx data=0x0.1.1.1 +phy set polarity-rev portlist=33 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=34 lane-cnt=4 property=tx data=0x0.1.1.1 +phy set polarity-rev portlist=35 lane-cnt=4 property=tx data=0x1.0.0.0 +phy set polarity-rev portlist=36 lane-cnt=4 property=tx data=0x0.0.1.1 +phy set polarity-rev portlist=37 lane-cnt=4 property=tx data=0x0.0.0.1 +phy set polarity-rev portlist=38 lane-cnt=4 property=tx data=0x0.1.1.0 +phy set polarity-rev portlist=39 lane-cnt=4 property=tx data=0x1.0.1.0 +phy set polarity-rev portlist=40 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=41 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=42 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=43 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=44 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=45 lane-cnt=4 property=tx data=0x0.0.1.0 +phy set polarity-rev portlist=46 lane-cnt=4 property=tx data=0x0.0.0.1 +phy set polarity-rev portlist=47 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=48 lane-cnt=4 property=tx data=0x0.0.1.1 +phy set polarity-rev portlist=49 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=50 lane-cnt=4 property=tx data=0x0.0.1.1 +phy set polarity-rev portlist=51 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=52 lane-cnt=4 property=tx data=0x0.0.1.1 +phy set polarity-rev portlist=53 lane-cnt=4 property=tx data=0x0.0.1.0 +phy set polarity-rev portlist=54 lane-cnt=4 property=tx data=0x0.0.1.1 +phy set polarity-rev portlist=55 lane-cnt=4 property=tx data=0x0.0.1.1 +phy set polarity-rev portlist=56 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=57 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=58 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=59 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=60 lane-cnt=4 property=tx data=0x0.1.0.1 +phy set polarity-rev portlist=61 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=62 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=63 lane-cnt=4 property=tx data=0x0.0.1.0 +phy set polarity-rev portlist=129 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=130 lane-cnt=1 property=tx data=0x0 + +phy set polarity-rev portlist=0 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=1 lane-cnt=4 property=rx data=0x1.0.0.0 +phy set polarity-rev portlist=2 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=3 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=4 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=5 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=6 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=7 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=8 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=9 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=10 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=11 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=12 lane-cnt=4 property=rx data=0x1.0.0.0 +phy set polarity-rev portlist=13 lane-cnt=4 property=rx data=0x0.0.1.0 +phy set polarity-rev portlist=14 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=15 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=16 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=17 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=18 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=19 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=20 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=21 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=22 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=23 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=24 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=25 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=26 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=27 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=28 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=29 lane-cnt=4 property=rx data=0x1.0.1.0 +phy set polarity-rev portlist=30 lane-cnt=4 property=rx data=0x0.0.1.0 +phy set polarity-rev portlist=31 lane-cnt=4 property=rx data=0x1.1.0.0 +phy set polarity-rev portlist=32 lane-cnt=4 property=rx data=0x0.1.1.1 +phy set polarity-rev portlist=33 lane-cnt=4 property=rx data=0x1.1.1.0 +phy set polarity-rev portlist=34 lane-cnt=4 property=rx data=0x0.0.1.1 +phy set polarity-rev portlist=35 lane-cnt=4 property=rx data=0x0.0.1.0 +phy set polarity-rev portlist=36 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=37 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=38 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=39 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=40 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=41 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=42 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=43 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=44 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=45 lane-cnt=4 property=rx data=0x0.1.0.1 +phy set polarity-rev portlist=46 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=47 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=48 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=49 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=50 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=51 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=52 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=53 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=54 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=55 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=56 lane-cnt=4 property=rx data=0x0.1.0.0 +phy set polarity-rev portlist=57 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=58 lane-cnt=4 property=rx data=0x0.1.0.0 +phy set polarity-rev portlist=59 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=60 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=61 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=62 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=63 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=129 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=130 lane-cnt=1 property=rx data=0x0 + +phy set pre-emphasis portlist=0 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=0 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=0 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=0 lane-cnt=4 property=c0 data=0x19.19.18.19 +phy set pre-emphasis portlist=1 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=1 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=1 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=1 lane-cnt=4 property=c0 data=0x19.18.19.19 +phy set pre-emphasis portlist=2 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=2 lane-cnt=4 property=c1 data=0x08.08.09.09 +phy set pre-emphasis portlist=2 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=2 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=3 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=3 lane-cnt=4 property=c1 data=0x08.08.09.08 +phy set pre-emphasis portlist=3 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=3 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=4 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=4 lane-cnt=4 property=c1 data=0x06.07.07.08 +phy set pre-emphasis portlist=4 lane-cnt=4 property=cn1 data=0x03.02.02.02 +phy set pre-emphasis portlist=4 lane-cnt=4 property=c0 data=0x19.19.18.19 +phy set pre-emphasis portlist=5 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=5 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis portlist=5 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=5 lane-cnt=4 property=c0 data=0x19.19.18.18 +phy set pre-emphasis portlist=6 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=6 lane-cnt=4 property=c1 data=0x06.06.06.07 +phy set pre-emphasis portlist=6 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=6 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=7 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=7 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=7 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=7 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=8 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=8 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=8 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=8 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=9 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=9 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=9 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=9 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=10 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=10 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=10 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=10 lane-cnt=4 property=c0 data=0x16.17.17.17 +phy set pre-emphasis portlist=11 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=11 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=11 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=11 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=12 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=12 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=12 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=12 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=13 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=13 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=13 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=13 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=14 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=14 lane-cnt=4 property=c1 data=0x04.05.04.05 +phy set pre-emphasis portlist=14 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=14 lane-cnt=4 property=c0 data=0x18.17.18.17 +phy set pre-emphasis portlist=15 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=15 lane-cnt=4 property=c1 data=0x06.05.06.06 +phy set pre-emphasis portlist=15 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=15 lane-cnt=4 property=c0 data=0x16.17.16.16 +phy set pre-emphasis portlist=16 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=16 lane-cnt=4 property=c1 data=0x05.06.06.06 +phy set pre-emphasis portlist=16 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=16 lane-cnt=4 property=c0 data=0x17.18.18.16 +phy set pre-emphasis portlist=17 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=17 lane-cnt=4 property=c1 data=0x04.04.04.04 +phy set pre-emphasis portlist=17 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=17 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=18 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=18 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=18 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=18 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=19 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=19 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=19 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=19 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=20 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=20 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=20 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=20 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=21 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=21 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=21 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=21 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=22 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=22 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=22 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=22 lane-cnt=4 property=c0 data=0x17.17.18.17 +phy set pre-emphasis portlist=23 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=23 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=23 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=23 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=24 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=24 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis portlist=24 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=24 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=25 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=25 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis portlist=25 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=25 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=26 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=26 lane-cnt=4 property=c1 data=0x08.08.07.07 +phy set pre-emphasis portlist=26 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=26 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=27 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=27 lane-cnt=4 property=c1 data=0x08.08.08.08 +phy set pre-emphasis portlist=27 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=27 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=28 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=28 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=28 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=28 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=29 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=29 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=29 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=29 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=30 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=30 lane-cnt=4 property=c1 data=0x08.09.09.09 +phy set pre-emphasis portlist=30 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=30 lane-cnt=4 property=c0 data=0x18.19.19.19 +phy set pre-emphasis portlist=31 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=31 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=31 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=31 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=32 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=32 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=32 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=32 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=33 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=33 lane-cnt=4 property=c1 data=0x08.09.09.09 +phy set pre-emphasis portlist=33 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=33 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=34 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=34 lane-cnt=4 property=c1 data=0x08.07.08.08 +phy set pre-emphasis portlist=34 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=34 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=35 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=35 lane-cnt=4 property=c1 data=0x08.08.07.08 +phy set pre-emphasis portlist=35 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=35 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=36 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=36 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis portlist=36 lane-cnt=4 property=cn1 data=0x01.02.02.02 +phy set pre-emphasis portlist=36 lane-cnt=4 property=c0 data=0x19.18.18.18 +phy set pre-emphasis portlist=37 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=37 lane-cnt=4 property=c1 data=0x06.06.06.07 +phy set pre-emphasis portlist=37 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=37 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=38 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=38 lane-cnt=4 property=c1 data=0x06.06.05.06 +phy set pre-emphasis portlist=38 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=38 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=39 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=39 lane-cnt=4 property=c1 data=0x06.07.06.06 +phy set pre-emphasis portlist=39 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=39 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=40 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=40 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=40 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=40 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=41 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=41 lane-cnt=4 property=c1 data=0x05.06.05.05 +phy set pre-emphasis portlist=41 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=41 lane-cnt=4 property=c0 data=0x16.17.18.18 +phy set pre-emphasis portlist=42 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=42 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=42 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=42 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=43 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=43 lane-cnt=4 property=c1 data=0x06.05.05.05 +phy set pre-emphasis portlist=43 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=43 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=44 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=44 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=44 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=44 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=45 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=45 lane-cnt=4 property=c1 data=0x05.05.04.05 +phy set pre-emphasis portlist=45 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=45 lane-cnt=4 property=c0 data=0x17.17.18.17 +phy set pre-emphasis portlist=46 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=46 lane-cnt=4 property=c1 data=0x05.05.06.06 +phy set pre-emphasis portlist=46 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=46 lane-cnt=4 property=c0 data=0x17.17.16.16 +phy set pre-emphasis portlist=47 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=47 lane-cnt=4 property=c1 data=0x05.05.06.06 +phy set pre-emphasis portlist=47 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=47 lane-cnt=4 property=c0 data=0x17.17.16.16 +phy set pre-emphasis portlist=48 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=48 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=48 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=48 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=49 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=49 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=49 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=49 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=50 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=50 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=50 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=50 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=51 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=51 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=51 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=51 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=52 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=52 lane-cnt=4 property=c1 data=0x06.06.05.05 +phy set pre-emphasis portlist=52 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=52 lane-cnt=4 property=c0 data=0x16.17.17.17 +phy set pre-emphasis portlist=53 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=53 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=53 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=53 lane-cnt=4 property=c0 data=0x16.17.17.17 +phy set pre-emphasis portlist=54 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=54 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=54 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=54 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=55 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=55 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=55 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=55 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=56 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=56 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis portlist=56 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=56 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=57 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=57 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis portlist=57 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=57 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=58 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=58 lane-cnt=4 property=c1 data=0x08.08.08.08 +phy set pre-emphasis portlist=58 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=58 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=59 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=59 lane-cnt=4 property=c1 data=0x08.08.08.08 +phy set pre-emphasis portlist=59 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=59 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=60 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=60 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=60 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=60 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=61 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=61 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=61 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=61 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=62 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=62 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=62 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=62 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=63 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=63 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=63 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=63 lane-cnt=4 property=c0 data=0x19.19.19.19 + +phy set pre-emphasis portlist=129 lane-cnt=1 property=c2 data=0x01 +phy set pre-emphasis portlist=129 lane-cnt=1 property=cn1 data=0x01 +phy set pre-emphasis portlist=129 lane-cnt=1 property=c0 data=0x02 +phy set pre-emphasis portlist=129 lane-cnt=1 property=c1 data=0x03 +phy set pre-emphasis portlist=130 lane-cnt=1 property=c2 data=0x01 +phy set pre-emphasis portlist=130 lane-cnt=1 property=cn1 data=0x01 +phy set pre-emphasis portlist=130 lane-cnt=1 property=c0 data=0x02 +phy set pre-emphasis portlist=130 lane-cnt=1 property=c1 data=0x03 + +phy set mdio portlist=0 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=1 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=2 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=3 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=4 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=5 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=6 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=7 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=8 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=9 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=10 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=11 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=12 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=13 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=14 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=15 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=16 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=17 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=18 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=19 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=20 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=21 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=22 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=23 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=24 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=25 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=26 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=27 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=28 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=29 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=30 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=31 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=32 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=33 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=34 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=35 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=36 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=37 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=38 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=39 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=40 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=41 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=42 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=43 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=44 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=45 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=46 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=47 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=48 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=49 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=50 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=51 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=52 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=53 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=54 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=55 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=56 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=57 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=58 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=59 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=60 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=61 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=62 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=63 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=129 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=130 devad=0x1E addr=0x2 data=0x0000 + +port set property portlist=0-63 speed=100g +port set property portlist=129-130 speed=10g +port set property portlist=0-63 medium-type=sr4 +port set property portlist=129-130 medium-type=kr +port set property portlist=0-63 fec=disable +port set adver portlist=129-130 speed-10g-kr +port set property portlist=129-130 an=enable + +port set property portlist=0-63,129-130 admin=enable diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/qos.json.j2 b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/qos.json.j2 new file mode 100644 index 000000000000..42eef17c362b --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/qos.json.j2 @@ -0,0 +1,136 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "1", + "1": "0", + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "1", + "1": "0", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"1", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + }, + "WRED_PROFILE": { + "AZURE_LOSSY" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"516096", + "red_min_threshold":"516096", + "yellow_max_threshold":"516096", + "yellow_min_threshold":"516096", + "green_max_threshold": "184128", + "green_min_threshold": "184128" + }, + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"516096", + "red_min_threshold":"516096", + "yellow_max_threshold":"516096", + "yellow_min_threshold":"516096", + "green_max_threshold": "184128", + "green_min_threshold": "184128" + } + }, + "QUEUE": { + } +} diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/sai.profile b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/sai.profile new file mode 100644 index 000000000000..880f47910ac1 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/led_proc_init.nps +SAI_DSH_CONFIG_FILE=/usr/share/sonic/hwsku/port_config.nps diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/default_sku new file mode 100644 index 000000000000..46ddac21550c --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S9230-64X t1 diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/fancontrol new file mode 100644 index 000000000000..86b4e636375f --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +DEVPATH=hwmon7=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-002f hwmon4=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-7/7-004e +DEVNAME=hwmon7=w83795adg +FCTEMPS=hwmon7/device/pwm2=hwmon4/temp1_input +FCFANS=hwmon7/device/pwm2=hwmon7/device/fan7_input hwmon7/device/pwm2=hwmon7/device/fan5_input hwmon7/device/pwm2=hwmon7/device/fan3_input hwmon7/device/pwm2=hwmon7/device/fan1_input +MINTEMP=hwmon7/device/pwm2=20 +MAXTEMP=hwmon7/device/pwm2=60 +MINSTART=hwmon7/device/pwm2=75 +MINSTOP=hwmon7/device/pwm2=22 diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/led_proc_init.nps b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/led_proc_init.nps new file mode 100644 index 000000000000..717d3303f172 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/led_proc_init.nps @@ -0,0 +1,9 @@ +#unit NPS_CFG_TYPE_XXX param0 param1 value +#---- ---------------- ------ ------ ----- +0 NPS_CFG_TYPE_USE_UNIT_PORT 0 0 1 +0 NPS_CFG_TYPE_LED_CFG 0 0 6 +0 NPS_CFG_TYPE_CPI_PORT_MODE 129 0 1 +0 NPS_CFG_TYPE_CPI_PORT_MODE 130 0 1 +0 NPS_CFG_TYPE_USER_BUF_CTRL 0 0 1 +0 NPS_CFG_TYPE_HASH_L2_FDB_REGION_ENTRY_NUM 0 0 49152 +0 NPS_CFG_TYPE_HASH_L3_WITH_IPV6_PREFIX_64_REGION_ENTRY_NUM 0 0 32768 diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..770b0cf43baf --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Ingrasys S9230-64X +# +# 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-0051/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..cc996057e09e --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/psuutil.py @@ -0,0 +1,92 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/i2c-18/18-0050", + "/sys/bus/i2c/devices/i2c-17/17-0050"] + + def __init__(self): + PsuBase.__init__(self) + + + # Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + attr_file = 'psu_pg' + attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU status + if (attr_value == 1): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_absent = 0 + attr_file ='psu_abs' + attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU presence + if (attr_value == 0): + status = 1 + + return status + diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..2f7a5395bb47 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/sfputil.py @@ -0,0 +1,295 @@ +# 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 = 63 + PORTS_IN_BLOCK = 64 + #TODO: modify according to port map + EEPROM_OFFSET = 33 + CPLD1_PORTS = 12 + CPLDx_PORTS = 13 + CPLD_OFFSET = 1 + CPLD_PRES_BIT = 1 + CPLD_RESET_BIT = 0 + CPLD_LPMOD_BIT = 2 + CPLDx_I2C_ADDR = "33" + CPLD_PORT_STATUS_KEY = "cpld_qsfp_port_status" + CPLD_PORT_CONFIG_KEY = "cpld_qsfp_port_config" + CPLD_REG_PATH = "/sys/bus/i2c/devices/{0}-00{1}/{2}_{3}" + + _port_to_eeprom_mapping = {} + + _logic_to_phy_port_mapping = { + 0: 0, + 1: 1, + 2: 4, + 3: 5, + 4: 8, + 5: 9, + 6: 12, + 7: 13, + 8: 16, + 9: 17, + 10: 20, + 11: 21, + 12: 24, + 13: 25, + 14: 28, + 15: 29, + 16: 32, + 17: 33, + 18: 36, + 19: 37, + 20: 40, + 21: 41, + 22: 44, + 23: 45, + 24: 48, + 25: 49, + 26: 52, + 27: 53, + 28: 56, + 29: 57, + 30: 60, + 31: 61, + 32: 2, + 33: 3, + 34: 6, + 35: 7, + 36: 10, + 37: 11, + 38: 14, + 39: 15, + 40: 18, + 41: 19, + 42: 22, + 43: 23, + 44: 26, + 45: 27, + 46: 30, + 47: 31, + 48: 34, + 49: 35, + 50: 38, + 51: 39, + 52: 42, + 53: 43, + 54: 46, + 55: 47, + 56: 50, + 57: 51, + 58: 54, + 59: 55, + 60: 58, + 61: 59, + 62: 62, + 63: 63 + } + + @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 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/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + for x in range(self.port_start, self.port_end + 1): + phy_port = self._logic_to_phy_port_mapping[x] + port_eeprom_path = eeprom_path.format(phy_port + self.EEPROM_OFFSET) + self.port_to_eeprom_mapping[x] = port_eeprom_path + + SfpUtilBase.__init__(self) + + def qsfp_to_cpld_index(self, port_num): + if port_num < self.CPLD1_PORTS: + cpld_id = 0 + cpld_port_index = port_num + 1 + else: + cpld_id = 1 + (port_num - self.CPLD1_PORTS) / self.CPLDx_PORTS + cpld_port_index = ((port_num - self.CPLD1_PORTS) % self.CPLDx_PORTS) + 1 + return cpld_id, cpld_port_index + + 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 + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, \ + self.CPLD_PORT_STATUS_KEY, cpld_port_index) + + try: + reg_file = open(reg_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_file.close() + + reg_value = int(content, 16) + # mask for presence bit (bit 1) + mask = (1 << self.CPLD_PRES_BIT) + + # 0 - presence, 1 - absence + 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 + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, \ + self.CPLD_PORT_CONFIG_KEY, cpld_port_index) + + try: + reg_file = open(reg_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_file.close() + + reg_value = int(content, 16) + # mask for lp_mod bit (bit 2) + mask = (1 << self.CPLD_LPMOD_BIT) + + # 0 - disable, 1 - low power mode + 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 + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, \ + self.CPLD_PORT_CONFIG_KEY, cpld_port_index) + + try: + reg_file = open(reg_path, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + # mask for lp_mod bit (bit 2) + mask = (1 << self.CPLD_LPMOD_BIT) + + # 1 - low power mode, 0 - high power mode + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # convert value to hex string + 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 + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, \ + self.CPLD_PORT_CONFIG_KEY, cpld_port_index) + + # reset the port + try: + reg_file = open(reg_path, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + # mask for reset bit (bit 0) + mask = (1 << self.CPLD_RESET_BIT) + + # 1 - out of reset, 0 - reset + reg_value = reg_value & ~mask + + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 1 second to reset done + time.sleep(1) + + # take the port out of reset + try: + reg_file = open(reg_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 + + def get_transceiver_change_event(self, timeout=0): + raise NotImplementedError diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/sensors.conf new file mode 100644 index 000000000000..84abfe88062b --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/sensors.conf @@ -0,0 +1,83 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + +bus "i2c-16" "i2c-mux-1 (chan_id 7)" +chip "w83795adg-*" + ignore in0 + label in1 "VDD_CORE" + set in1_min 0.90 * 0.98 + set in1_max 0.90 * 1.02 + ignore in2 + label in3 "1.8V" + set in3_min 1.8 * 0.97 + set in3_max 1.8 * 1.03 + label in4 "3.3V" + compute in4 @/(0.3052), (0.3052)*@ + set in4_min 3.3 * 0.95 + set in4_max 3.3 * 1.05 + label in5 "0.9V" + set in5_min 0.90 * 0.98 + set in5_max 0.90 * 1.02 + ignore in6 + ignore in7 + ignore in8 + ignore in9 + ignore in10 + ignore in11 + ignore in12 + ignore in13 + ignore in14 + ignore in15 + ignore in16 + ignore in17 + ignore in18 + ignore in19 + label fan1 "FANTRAY 1" + ignore fan2 + label fan3 "FANTRAY 2" + ignore fan4 + label fan5 "FANTRAY 3" + ignore fan6 + label fan7 "FANTRAY 4" + ignore fan8 + ignore temp1 + ignore temp2 + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore intrusion0 + +chip "tmp75-i2c-*-4A" + label temp1 "BMC Board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-0" "SMBus I801 adapter at f000" +chip "tmp75-i2c-*-4F" + label temp1 "x86 CPU Board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-6" "i2c-0-mux (chan_id 5)" +chip "lm75-i2c-6-4D" + label temp1 "Rear Panel Temp" + set temp1_max 50 + set temp1_max_hyst 45 +chip "lm75-i2c-6-4E" + label temp1 "Rear MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-7" "i2c-0-mux (chan_id 6)" +chip "lm75-i2c-7-4D" + label temp1 "Front Panel Temp" + set temp1_max 50 + set temp1_max_hyst 45 +chip "lm75-i2c-7-4E" + label temp1 "Front MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/port_config.ini b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/port_config.ini new file mode 100644 index 000000000000..749f9f484a3d --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias speed autoneg fec index +Ethernet0 0,1,2,3 Ethernet0 100000 0 0 0 +Ethernet4 4,5,6,7 Ethernet4 100000 0 0 1 +Ethernet8 8,9,10,11 Ethernet8 100000 0 0 2 +Ethernet12 12,13,14,15 Ethernet12 100000 0 0 3 +Ethernet16 16,17,18,19 Ethernet16 100000 0 0 4 +Ethernet20 20,21,22,23 Ethernet20 100000 0 0 5 +Ethernet24 24,25,26,27 Ethernet24 100000 0 0 6 +Ethernet28 28,29,30,31 Ethernet28 100000 0 0 7 +Ethernet32 32,33,34,35 Ethernet32 100000 0 0 8 +Ethernet36 36,37,38,39 Ethernet36 100000 0 0 9 +Ethernet40 40,41,42,43 Ethernet40 100000 0 0 10 +Ethernet44 44,45,46,47 Ethernet44 100000 0 0 11 +Ethernet48 48,49,50,51 Ethernet48 100000 0 0 12 +Ethernet52 52,53,54,55 Ethernet52 100000 0 0 13 +Ethernet56 56,57,58,59 Ethernet56 100000 0 0 14 +Ethernet60 60,61,62,63 Ethernet60 100000 0 0 15 +Ethernet64 64,65,66,67 Ethernet64 100000 0 0 16 +Ethernet68 68,69,70,71 Ethernet68 100000 0 0 17 +Ethernet72 72,73,74,75 Ethernet72 100000 0 0 18 +Ethernet76 76,77,78,79 Ethernet76 100000 0 0 19 +Ethernet80 80,81,82,83 Ethernet80 100000 0 0 20 +Ethernet84 84,85,86,87 Ethernet84 100000 0 0 21 +Ethernet88 88,89,90,91 Ethernet88 100000 0 0 22 +Ethernet92 92,93,94,95 Ethernet92 100000 0 0 23 +Ethernet96 96,97,98,99 Ethernet96 100000 0 0 24 +Ethernet100 100,101,102,103 Ethernet100 100000 0 0 25 +Ethernet104 104,105,106,107 Ethernet104 100000 0 0 26 +Ethernet108 108,109,110,111 Ethernet108 100000 0 0 27 +Ethernet112 112,113,114,115 Ethernet112 100000 0 0 28 +Ethernet116 116,117,118,119 Ethernet116 100000 0 0 29 +Ethernet120 120,121,122,123 Ethernet120 100000 0 0 30 +Ethernet124 124,125,126,127 Ethernet124 100000 0 0 31 +Ethernet128 128,129,130,131 Ethernet128 100000 0 0 32 +Ethernet132 132,133,134,135 Ethernet132 100000 0 0 33 +Ethernet136 136,137,138,139 Ethernet136 100000 0 0 34 +Ethernet140 140,141,142,143 Ethernet140 100000 0 0 35 +Ethernet144 144,145,146,147 Ethernet144 100000 0 0 36 +Ethernet148 148,149,150,151 Ethernet148 100000 0 0 37 +Ethernet152 152,153,154,155 Ethernet152 100000 0 0 38 +Ethernet156 156,157,158,159 Ethernet156 100000 0 0 39 +Ethernet160 160,161,162,163 Ethernet160 100000 0 0 40 +Ethernet164 164,165,166,167 Ethernet164 100000 0 0 41 +Ethernet168 168,169,170,171 Ethernet168 100000 0 0 42 +Ethernet172 172,173,174,175 Ethernet172 100000 0 0 43 +Ethernet176 176,177,178,179 Ethernet176 100000 0 0 44 +Ethernet180 180,181,182,183 Ethernet180 100000 0 0 45 +Ethernet184 184,185,186,187 Ethernet184 100000 0 0 46 +Ethernet188 188,189,190,191 Ethernet188 100000 0 0 47 +Ethernet192 192,193,194,195 Ethernet192 100000 0 0 48 +Ethernet196 196,197,198,199 Ethernet196 100000 0 0 49 +Ethernet200 200,201,202,203 Ethernet200 100000 0 0 50 +Ethernet204 204,205,206,207 Ethernet204 100000 0 0 51 +Ethernet208 208,209,210,211 Ethernet208 100000 0 0 52 +Ethernet212 212,213,214,215 Ethernet212 100000 0 0 53 +Ethernet216 216,217,218,219 Ethernet216 100000 0 0 54 +Ethernet220 220,221,222,223 Ethernet220 100000 0 0 55 +Ethernet224 224,225,226,227 Ethernet224 100000 0 0 56 +Ethernet228 228,229,230,231 Ethernet228 100000 0 0 57 +Ethernet232 232,233,234,235 Ethernet232 100000 0 0 58 +Ethernet236 236,237,238,239 Ethernet236 100000 0 0 59 +Ethernet240 240,241,242,243 Ethernet240 100000 0 0 60 +Ethernet244 244,245,246,247 Ethernet244 100000 0 0 61 +Ethernet248 248,249,250,251 Ethernet248 100000 0 0 62 +Ethernet252 252,253,254,255 Ethernet252 100000 0 0 63 diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/switch-sai.conf b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/switch-sai.conf new file mode 100644 index 000000000000..224d1fc58b18 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/switch-sai.conf @@ -0,0 +1,33 @@ +{ + "chip_list": [ + { + "id": "asic-0", + "chip_family": "Tofino", + "instance": 0, + "pcie_sysfs_prefix": "/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0", + "pcie_domain": 0, + "pcie_bus": 5, + "pcie_fn": 0, + "pcie_dev": 0, + "pcie_int_mode": 1, + "sds_fw_path": "share/tofino_sds_fw/avago/firmware" + } + ], + "instance": 0, + "p4_program_list": [ + { + "id": "pgm-0", + "instance": 0, + "path": "switch", + "program-name": "switch", + "pd": "lib/tofinopd/switch/libpd.so", + "pd-thrift": "lib/tofinopd/switch/libpdthrift.so", + "table-config": "share/tofinopd/switch/context.json", + "tofino-bin": "share/tofinopd/switch/tofino.bin", + "switchapi": "lib/libswitchapi.so", + "switchsai": "lib/libswitchsai.so", + "agent0": "lib/platform/x86_64-ingrasys_s9280_64x-r0/libpltfm_mgr.so", + "switchapi_port_add": false + } + ] +} diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/default_sku new file mode 100644 index 000000000000..68e0c87eb0a3 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S9280-64X t1 diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/fancontrol new file mode 100644 index 000000000000..427cc6561c50 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-002f hwmon3=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-6/6-004c +DEVNAME=hwmon1=w83795adg +FCTEMPS=hwmon1/device/pwm2=hwmon3/temp1_input +FCFANS=hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm2=hwmon1/device/fan3_input hwmon1/device/pwm2=hwmon1/device/fan1_input +MINTEMP=hwmon1/device/pwm2=20 +MAXTEMP=hwmon1/device/pwm2=60 +MINSTART=hwmon1/device/pwm2=75 +MINSTOP=hwmon1/device/pwm2=22 diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..ecf171539843 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Ingrasys S9280-64X +# +# 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-0051/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..c4b78c943e81 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/psuutil.py @@ -0,0 +1,93 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + # TODO: need to check if the patch mapping correct + SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/i2c-18/18-0050", + "/sys/bus/i2c/devices/i2c-17/17-0050"] + + def __init__(self): + PsuBase.__init__(self) + + + # Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + attr_file = 'psu_pg' + attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU status + if (attr_value == 1): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_absent = 0 + attr_file ='psu_abs' + attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU presence + if (attr_value == 0): + status = 1 + + return status + diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..57edb81cd109 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/sfputil.py @@ -0,0 +1,308 @@ +# 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 = 63 + PORTS_IN_BLOCK = 64 + EEPROM_OFFSET = 41 + CPLD1_PORTS = 12 + CPLDx_PORTS = 13 + #TODO: check init sequence for CPLD i2c bus + CPLD_OFFSET = 1 + CPLD_PRES_BIT = 1 + CPLD_RESET_BIT = 0 + CPLD_LPMOD_BIT = 2 + CPLDx_I2C_ADDR = "33" + EEPROM_I2C_ADDR = "50" + CPLD_PORT_STATUS_KEY = "cpld_qsfp_port_status" + CPLD_PORT_CONFIG_KEY = "cpld_qsfp_port_config" + CPLD_REG_PATH = "/sys/bus/i2c/devices/{0}-00{1}/{2}_{3}" + + _port_to_eeprom_mapping = {} + + #TODO: check the fp port to phy port mapping + _fp2phy_port_mapping = { + 0: 0, + 1: 1, + 2: 4, + 3: 5, + 4: 8, + 5: 9, + 6: 12, + 7: 13, + 8: 16, + 9: 17, + 10: 20, + 11: 21, + 12: 24, + 13: 25, + 14: 28, + 15: 29, + 16: 32, + 17: 33, + 18: 36, + 19: 37, + 20: 40, + 21: 41, + 22: 44, + 23: 45, + 24: 48, + 25: 49, + 26: 52, + 27: 53, + 28: 56, + 29: 57, + 30: 60, + 31: 61, + 32: 2, + 33: 3, + 34: 6, + 35: 7, + 36: 10, + 37: 11, + 38: 14, + 39: 15, + 40: 18, + 41: 19, + 42: 22, + 43: 23, + 44: 26, + 45: 27, + 46: 30, + 47: 31, + 48: 34, + 49: 35, + 50: 38, + 51: 39, + 52: 42, + 53: 43, + 54: 46, + 55: 47, + 56: 50, + 57: 51, + 58: 54, + 59: 55, + 60: 58, + 61: 59, + 62: 62, + 63: 63 + } + + @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 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/class/i2c-adapter/i2c-{0}/{0}-00{1}/eeprom" + for x in range(self.port_start, self.port_end + 1): + phy_port = self.fp2phy_port_num(x) + port_eeprom_path = eeprom_path.format(phy_port + self.EEPROM_OFFSET, self.EEPROM_I2C_ADDR) + self.port_to_eeprom_mapping[x] = port_eeprom_path + + SfpUtilBase.__init__(self) + + def qsfp_to_cpld_index(self, port_num): + if port_num < self.CPLD1_PORTS: + cpld_id = 0 + cpld_port_index = port_num + 1 + else: + cpld_id = 1 + (port_num - self.CPLD1_PORTS) / self.CPLDx_PORTS + cpld_port_index = ((port_num - self.CPLD1_PORTS) % self.CPLDx_PORTS) + 1 + return cpld_id, cpld_port_index + + def fp2phy_port_num(self, fp_port_num): + + phy_port_num = self._fp2phy_port_mapping[fp_port_num] + return phy_port_num + + 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 + + # logic port to physical port mapping + port_num = self.fp2phy_port_num(port_num) + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, \ + self.CPLD_PORT_STATUS_KEY, cpld_port_index) + + try: + reg_file = open(reg_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_file.close() + + reg_value = int(content, 16) + # mask for presence bit (bit 1) + mask = (1 << self.CPLD_PRES_BIT) + + # 0 - presence, 1 - absence + 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 + + # logic port to physical port mapping + port_num = self.fp2phy_port_num(port_num) + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, \ + self.CPLD_PORT_CONFIG_KEY, cpld_port_index) + + try: + reg_file = open(reg_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_file.close() + + reg_value = int(content, 16) + # mask for lp_mod bit (bit 2) + mask = (1 << self.CPLD_LPMOD_BIT) + + # 0 - disable, 1 - low power mode + 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 + + # logic port to physical port mapping + port_num = self.fp2phy_port_num(port_num) + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, \ + self.CPLD_PORT_CONFIG_KEY, cpld_port_index) + + try: + reg_file = open(reg_path, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + # mask for lp_mod bit (bit 2) + mask = (1 << self.CPLD_LPMOD_BIT) + + # 1 - low power mode, 0 - high power mode + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # convert value to hex string + 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 + + # logic port to physical port mapping + port_num = self.fp2phy_port_num(port_num) + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, \ + self.CPLD_PORT_CONFIG_KEY, cpld_port_index) + + # reset the port + try: + reg_file = open(reg_path, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + # mask for reset bit (bit 0) + mask = (1 << self.CPLD_RESET_BIT) + + # 1 - out of reset, 0 - reset + reg_value = reg_value & ~mask + + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 1 second to reset done + time.sleep(1) + + # take the port out of reset + try: + reg_file = open(reg_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 + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError + diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/sensors.conf new file mode 100644 index 000000000000..0e9f5cd41ba8 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/sensors.conf @@ -0,0 +1,85 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + +bus "i2c-16" "i2c-mux-1 (chan_id 7)" +chip "w83795adg-*" + ignore in0 + label in1 "VDD_CORE" + set in1_min 0.717 + set in1_max 0.962 + ignore in2 + ignore in3 + label in4 "3.3V" + compute in4 @/(0.3052), (0.3052)*@ + set in4_min 3.3 * 0.95 + set in4_max 3.3 * 1.05 + label in5 "0.9V" + set in5_min 0.90 * 0.98 + set in5_max 0.90 * 1.02 + ignore in6 + ignore in7 + ignore in8 + ignore in9 + ignore in10 + ignore in11 + ignore in12 + ignore in13 + ignore in14 + ignore in15 + ignore in16 + ignore in17 + ignore in18 + ignore in19 + label fan1 "FANTRAY 1" + ignore fan2 + label fan3 "FANTRAY 2" + ignore fan4 + label fan5 "FANTRAY 3" + ignore fan6 + label fan7 "FANTRAY 4" + ignore fan8 + ignore temp1 + ignore temp2 + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore intrusion0 + +chip "tmp75-i2c-*-4A" + label temp1 "BMC Board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-0" "SMBus I801 adapter at f000" +chip "tmp75-i2c-*-4F" + label temp1 "x86 CPU Board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-6" "i2c-0-mux (chan_id 5)" +chip "lm75-i2c-6-4D" + label temp1 "Rear Panel Temp" + set temp1_max 50 + set temp1_max_hyst 45 +chip "lm75-i2c-6-4E" + label temp1 "Right Side MB Tetmp" + set temp1_max 50 + set temp1_max_hyst 45 +chip "lm86-i2c-6-4C" + label temp1 "Front Panel Temp" + set temp1_max 50 + label temp2 "Front MAC Temp" + set temp2_max 70 +bus "i2c-7" "i2c-0-mux (chan_id 6)" +chip "lm75-i2c-7-4D" + label temp1 "Left Side MB Temp" + set temp1_max 50 + set temp1_max_hyst 45 +chip "lm75-i2c-7-4E" + label temp1 "Left Side MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/port_config.ini b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/port_config.ini new file mode 100644 index 000000000000..24823135f4ca --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/port_config.ini @@ -0,0 +1,74 @@ +# name lanes alias +Ethernet0 16 Ethernet0 +Ethernet4 15 Ethernet4 +Ethernet8 14 Ethernet8 +Ethernet12 13 Ethernet12 +Ethernet16 24 Ethernet16 +Ethernet20 23 Ethernet20 +Ethernet24 22 Ethernet24 +Ethernet28 21 Ethernet28 +Ethernet32 28 Ethernet32 +Ethernet36 27 Ethernet36 +Ethernet40 26 Ethernet40 +Ethernet44 25 Ethernet44 +Ethernet48 32 Ethernet48 +Ethernet52 31 Ethernet52 +Ethernet56 30 Ethernet56 +Ethernet60 29 Ethernet60 +Ethernet64 48 Ethernet64 +Ethernet68 47 Ethernet68 +Ethernet72 46 Ethernet72 +Ethernet76 45 Ethernet76 +Ethernet80 52 Ethernet80 +Ethernet84 51 Ethernet84 +Ethernet88 50 Ethernet88 +Ethernet92 49 Ethernet92 +Ethernet96 56 Ethernet96 +Ethernet100 55 Ethernet100 +Ethernet104 54 Ethernet104 +Ethernet108 53 Ethernet108 +Ethernet112 60 Ethernet112 +Ethernet116 59 Ethernet116 +Ethernet120 58 Ethernet120 +Ethernet124 57 Ethernet124 +Ethernet128 64 Ethernet128 +Ethernet132 63 Ethernet132 +Ethernet136 62 Ethernet136 +Ethernet140 61 Ethernet140 +Ethernet144 68 Ethernet144 +Ethernet148 67 Ethernet148 +Ethernet152 66 Ethernet152 +Ethernet156 65 Ethernet156 +Ethernet160 72 Ethernet160 +Ethernet164 71 Ethernet164 +Ethernet168 70 Ethernet168 +Ethernet172 69 Ethernet172 +Ethernet176 76 Ethernet176 +Ethernet180 75 Ethernet180 +Ethernet184 74 Ethernet184 +Ethernet188 73 Ethernet188 +Ethernet192 82 Ethernet192 +Ethernet196 84 Ethernet196 +Ethernet200 81 Ethernet200 +Ethernet204 83 Ethernet204 +Ethernet208 78 Ethernet208 +Ethernet212 80 Ethernet212 +Ethernet216 77 Ethernet216 +Ethernet220 79 Ethernet220 +Ethernet224 98 Ethernet224 +Ethernet228 100 Ethernet228 +Ethernet232 97 Ethernet232 +Ethernet236 99 Ethernet236 +Ethernet240 104 Ethernet240 +Ethernet244 102 Ethernet244 +Ethernet248 103 Ethernet248 +Ethernet252 101 Ethernet252 +Ethernet256 108 Ethernet256 +Ethernet260 106 Ethernet260 +Ethernet264 107 Ethernet264 +Ethernet268 105 Ethernet268 +Ethernet272 112 Ethernet272 +Ethernet276 110 Ethernet276 +Ethernet280 111 Ethernet280 +Ethernet284 109 Ethernet284 + diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/sai.profile b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/sai.profile new file mode 100644 index 000000000000..3f549dd63b40 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-d6254qs-72x10G.config +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/td2-d6254qs-72x10G.config.bcm b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/td2-d6254qs-72x10G.config.bcm new file mode 100644 index 000000000000..66b7172bce7c --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/td2-d6254qs-72x10G.config.bcm @@ -0,0 +1,160 @@ +os=unix +parity_enable=0 +pbmp_xport_xe.0=0x1fffffffffffffffffffffffffffffffe +miim_intr_enable=0 +schan_intr_enable=0 +bcm_stat_interval=2000000 +serdes_firmware_mode_xe=0x2 + +portmap_1=16:10 +portmap_2=15:10 +portmap_3=14:10 +portmap_4=13:10 +portmap_5=24:10 +portmap_6=23:10 +portmap_7=22:10 +portmap_8=21:10 +portmap_9=28:10 +portmap_10=27:10 +portmap_11=26:10 +portmap_12=25:10 +portmap_13=32:10 +portmap_14=31:10 +portmap_15=30:10 +portmap_16=29:10 +portmap_17=48:10 +portmap_18=47:10 +portmap_19=46:10 +portmap_20=45:10 +portmap_21=52:10 +portmap_22=51:10 +portmap_23=50:10 +portmap_24=49:10 +portmap_25=56:10 +portmap_26=55:10 +portmap_27=54:10 +portmap_28=53:10 +portmap_29=60:10 +portmap_30=59:10 +portmap_31=58:10 +portmap_32=57:10 +portmap_33=64:10 +portmap_34=63:10 +portmap_35=62:10 +portmap_36=61:10 +portmap_37=68:10 +portmap_38=67:10 +portmap_39=66:10 +portmap_40=65:10 +portmap_41=72:10 +portmap_42=71:10 +portmap_43=70:10 +portmap_44=69:10 +portmap_45=76:10 +portmap_46=75:10 +portmap_47=74:10 +portmap_48=73:10 + +portmap_49=82:10 +portmap_50=84:10 +portmap_51=81:10 +portmap_52=83:10 + +portmap_53=78:10 +portmap_54=80:10 +portmap_55=77:10 +portmap_56=79:10 + +portmap_57=98:10 +portmap_58=100:10 +portmap_59=97:10 +portmap_60=99:10 + +portmap_61=104:10 +portmap_62=102:10 +portmap_63=103:10 +portmap_64=101:10 + +portmap_65=108:10 +portmap_66=106:10 +portmap_67=107:10 +portmap_68=105:10 + +portmap_69=112:10 +portmap_70=110:10 +portmap_71=111:10 +portmap_72=109:10 + +xgxs_rx_lane_map_xe0=0x0123 +xgxs_rx_lane_map_xe1=0x0123 +xgxs_rx_lane_map_xe2=0x0123 +xgxs_rx_lane_map_xe3=0x0123 +xgxs_rx_lane_map_xe4=0x0123 +xgxs_rx_lane_map_xe5=0x0123 +xgxs_rx_lane_map_xe6=0x0123 +xgxs_rx_lane_map_xe7=0x0123 +xgxs_rx_lane_map_xe8=0x0123 +xgxs_rx_lane_map_xe9=0x0123 +xgxs_rx_lane_map_xe10=0x0123 +xgxs_rx_lane_map_xe11=0x0123 +xgxs_rx_lane_map_xe12=0x0123 +xgxs_rx_lane_map_xe13=0x0123 +xgxs_rx_lane_map_xe14=0x0123 +xgxs_rx_lane_map_xe15=0x0123 +xgxs_rx_lane_map_xe16=0x0123 +xgxs_rx_lane_map_xe17=0x0123 +xgxs_rx_lane_map_xe18=0x0123 +xgxs_rx_lane_map_xe19=0x0123 +xgxs_rx_lane_map_xe20=0x0123 +xgxs_rx_lane_map_xe21=0x0123 +xgxs_rx_lane_map_xe22=0x0123 +xgxs_rx_lane_map_xe23=0x0123 +xgxs_rx_lane_map_xe24=0x0123 +xgxs_rx_lane_map_xe25=0x0123 +xgxs_rx_lane_map_xe26=0x0123 +xgxs_rx_lane_map_xe27=0x0123 +xgxs_rx_lane_map_xe28=0x0123 +xgxs_rx_lane_map_xe29=0x0123 +xgxs_rx_lane_map_xe30=0x0123 +xgxs_rx_lane_map_xe31=0x0123 +xgxs_rx_lane_map_xe32=0x0123 +xgxs_rx_lane_map_xe33=0x0123 +xgxs_rx_lane_map_xe34=0x0123 +xgxs_rx_lane_map_xe35=0x0123 +xgxs_rx_lane_map_xe36=0x0123 +xgxs_rx_lane_map_xe37=0x0123 +xgxs_rx_lane_map_xe38=0x0123 +xgxs_rx_lane_map_xe39=0x0123 +xgxs_rx_lane_map_xe40=0x0123 +xgxs_rx_lane_map_xe41=0x0123 +xgxs_rx_lane_map_xe42=0x0123 +xgxs_rx_lane_map_xe43=0x0123 +xgxs_rx_lane_map_xe44=0x0123 +xgxs_rx_lane_map_xe45=0x0123 +xgxs_rx_lane_map_xe46=0x0123 +xgxs_rx_lane_map_xe47=0x0123 +xgxs_rx_lane_map_xe48=0x0123 +xgxs_rx_lane_map_xe49=0x0123 +xgxs_rx_lane_map_xe50=0x0123 +xgxs_rx_lane_map_xe51=0x0123 +xgxs_rx_lane_map_xe52=0x0123 +xgxs_rx_lane_map_xe53=0x0123 +xgxs_rx_lane_map_xe54=0x0123 +xgxs_rx_lane_map_xe55=0x0123 +xgxs_rx_lane_map_xe56=0x0123 +xgxs_rx_lane_map_xe57=0x0123 +xgxs_rx_lane_map_xe58=0x0123 +xgxs_rx_lane_map_xe59=0x0123 +xgxs_rx_lane_map_xe60=0x0123 +xgxs_rx_lane_map_xe61=0x0123 +xgxs_rx_lane_map_xe62=0x0123 +xgxs_rx_lane_map_xe63=0x0123 +xgxs_rx_lane_map_xe64=0x0123 +xgxs_rx_lane_map_xe65=0x0123 +xgxs_rx_lane_map_xe66=0x0123 +xgxs_rx_lane_map_xe67=0x0123 +xgxs_rx_lane_map_xe68=0x0123 +xgxs_rx_lane_map_xe69=0x0123 +xgxs_rx_lane_map_xe70=0x0123 +xgxs_rx_lane_map_xe71=0x0123 + diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/installer.conf b/device/inventec/x86_64-inventec_d6254qs-r0/installer.conf new file mode 100644 index 000000000000..6b489db6e16f --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 +VAR_LOG_SIZE=1024 diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d6254qs-r0/led_proc_init.soc new file mode 100644 index 000000000000..92423b234498 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/led_proc_init.soc @@ -0,0 +1,136 @@ +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=30 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=29 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=26 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=25 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=22 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=21 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=18 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=17 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=14 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=13 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=10 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=9 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=6 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=5 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=2 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=1 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=62 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=61 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=58 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=54 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=53 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=50 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=49 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=46 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=45 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=42 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=41 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=38 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=37 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=34 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=33 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=2 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=1 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=6 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=5 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=10 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=9 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=14 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=13 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=18 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=17 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=22 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=21 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=26 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=25 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=30 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=29 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=34 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=33 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=38 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=42 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=41 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=46 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=45 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=50 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=49 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=54 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=53 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=58 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=57 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=62 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=61 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=60 + +led 0 stop +led 0 prog 02 00 60 F1 12 00 DA 0F 70 10 67 47 67 42 77 06 02 A0 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DA 80 70 34 86 F0 77 16 12 00 DA 03 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +led 0 start + +led 1 stop +led 1 prog 02 00 60 F1 12 00 DA 0F 70 10 67 47 67 42 77 06 02 A0 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DA 80 70 34 86 F0 77 16 12 00 DA 03 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +led 1 start diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/minigraph.xml b/device/inventec/x86_64-inventec_d6254qs-r0/minigraph.xml new file mode 100644 index 000000000000..e2368e171b58 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/minigraph.xml @@ -0,0 +1,144 @@ + + + + + + OCPSCH0104001MS + 10.10.1.26 + SONiC-Inventec-d6254qs + 10.10.1.25 + 1 + 10 + 3 + + + OCPSCH0104002MS + 10.10.2.26 + SONiC-Inventec-d6254qs + 10.10.2.25 + 1 + 10 + 3 + + + + + 64536 + SONiC-Inventec-d6254qs + + +
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-d6254qs + + + + + + Ethernet0 + 10.10.1.25/30 + + + + Ethernet4 + 10.10.2.25/30 + + + + + + + + + + + + DeviceInterfaceLink + OCPSCH0104001MS + Ethernet24 + SONiC-Inventec-d6254qs + Ethernet0 + + + DeviceInterfaceLink + OCPSCH0104002MS + Ethernet24 + SONiC-Inventec-d6254qs + Ethernet4 + + + + + SONiC-Inventec-d6254qs + INVENTEC-D6254QS + + + + + + + SONiC-Inventec-d6254qs + + + 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-d6254qs + INVENTEC-D6254QS +
diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/eeprom.py new file mode 100644 index 000000000000..de5c24ba0e6d --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-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_d6254qs-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/psuutil.py new file mode 100644 index 000000000000..4bd3f7a27052 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/psuutil.py @@ -0,0 +1,84 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_DIR = "/sys/bus/i2c/devices/0-0066" + + def __init__(self): + PsuBase.__init__(self) + +# Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + attr_file = 'psoc_psu'+ str(index) + '_iout' + attr_path = self.PSU_DIR +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU status + if (attr_value != 0): + status = 1 + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_absent = 0 + ind = index-1 + attr_file ='psu'+ str(ind) + attr_path = self.PSU_DIR +'/' + attr_file + normal_attr_value = '0 : normal' + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU presence + if (attr_value == normal_attr_value): + status = 1 + return status diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/sfputil.py new file mode 100644 index 000000000000..6cd470795fb6 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-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: 10, + 1: 11, + 2: 12, + 3: 13, + 4: 14, + 5: 15, + 6: 16, + 7: 17, + 8: 18, + 9: 19, + 10: 20, + 11: 21, + 12: 22, + 13: 23, + 14: 24, + 15: 25, + 16: 26, + 17: 27, + 18: 28, + 19: 29, + 20: 30, + 21: 31, + 22: 32, + 23: 33, + 24: 34, + 25: 35, + 26: 36, + 27: 37, + 28: 38, + 29: 39, + 30: 40, + 31: 41, + 32: 42, + 33: 43, + 34: 44, + 35: 45, + 36: 46, + 37: 47, + 38: 48, + 39: 49, + 40: 50, + 41: 51, + 42: 52, + 43: 53, + 44: 54, + 45: 55, + 46: 56, + 47: 57, + 48: 58, + 49: 59, + 50: 60, + 51: 61, + 52: 62, + 53: 63 + } + + @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/inventec/x86_64-inventec_d6254qs-r0/sensors.conf b/device/inventec/x86_64-inventec_d6254qs-r0/sensors.conf new file mode 100644 index 000000000000..653900cad36f --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/sensors.conf @@ -0,0 +1,15 @@ +# libsensors configuration file +chip "inv_psoc-*" + ignore temp3 + ignore temp4 + label temp1 "CPU Board Temperature" + label temp2 "SW Board I Temperature" + label temp5 "SW Board II Temperature" + label temp6 "ASIC Temperature" + label in1 "PSU1 Voltage" + label in2 "PSU2 Voltage" + label curr1 "PSU1 Current" + label curr2 "PSU2 Current" + label power1 "PSU1 Power" + label power2 "PSU2 Power" + diff --git a/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/port_config.ini b/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/port_config.ini new file mode 100644 index 000000000000..4af8faabf676 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias +Ethernet0 1 Ethernet0 +Ethernet4 2 Ethernet4 +Ethernet8 3 Ethernet8 +Ethernet12 4 Ethernet12 +Ethernet16 5 Ethernet16 +Ethernet20 6 Ethernet20 +Ethernet24 7 Ethernet24 +Ethernet28 8 Ethernet28 +Ethernet32 13 Ethernet32 +Ethernet36 14 Ethernet36 +Ethernet40 15 Ethernet40 +Ethernet44 16 Ethernet44 +Ethernet48 21 Ethernet48 +Ethernet52 22 Ethernet52 +Ethernet56 23 Ethernet56 +Ethernet60 24 Ethernet60 +Ethernet64 29 Ethernet64 +Ethernet68 30 Ethernet68 +Ethernet72 31 Ethernet72 +Ethernet76 32 Ethernet76 +Ethernet80 33 Ethernet80 +Ethernet84 34 Ethernet84 +Ethernet88 35 Ethernet88 +Ethernet92 36 Ethernet92 +Ethernet96 41 Ethernet96 +Ethernet100 42 Ethernet100 +Ethernet104 43 Ethernet104 +Ethernet108 44 Ethernet108 +Ethernet112 49 Ethernet112 +Ethernet116 50 Ethernet116 +Ethernet120 51 Ethernet120 +Ethernet124 52 Ethernet124 +Ethernet128 57 Ethernet128 +Ethernet132 58 Ethernet132 +Ethernet136 59 Ethernet136 +Ethernet140 60 Ethernet140 +Ethernet144 61 Ethernet144 +Ethernet148 62 Ethernet148 +Ethernet152 63 Ethernet152 +Ethernet156 64 Ethernet156 +Ethernet160 65 Ethernet160 +Ethernet164 66 Ethernet164 +Ethernet168 67 Ethernet168 +Ethernet172 68 Ethernet172 +Ethernet176 69 Ethernet176 +Ethernet180 70 Ethernet180 +Ethernet184 71 Ethernet184 +Ethernet188 72 Ethernet188 +Ethernet192 77,78,79,80 Ethernet192 +Ethernet196 85,86,87,88 Ethernet196 +Ethernet200 93,94,95,96 Ethernet200 +Ethernet204 97,98,99,100 Ethernet204 +Ethernet208 105,106,107,108 Ethernet208 +Ethernet212 113,114,115,116 Ethernet212 +Ethernet216 121,122,123,124 Ethernet216 +Ethernet220 125,126,127,128 Ethernet220 diff --git a/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/sai.profile b/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/sai.profile new file mode 100644 index 000000000000..6f0bf54024a7 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-d6556-48x25G-8x100G.config.bcm.inventec +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/inventec/x86_64-inventec_d6556-r0/installer.conf b/device/inventec/x86_64-inventec_d6556-r0/installer.conf new file mode 100644 index 000000000000..1db64ba02c38 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-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_d6556-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d6556-r0/led_proc_init.soc new file mode 100644 index 000000000000..d4c2fde64f9c --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/led_proc_init.soc @@ -0,0 +1,6 @@ +led auto off +led stop +m0 load 0 0x0 /usr/share/sonic/platform/linkscan_led_fw.bin +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +led auto on +led start diff --git a/device/inventec/x86_64-inventec_d6556-r0/minigraph.xml b/device/inventec/x86_64-inventec_d6556-r0/minigraph.xml new file mode 100644 index 000000000000..50b3a05cfcce --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/minigraph.xml @@ -0,0 +1,144 @@ + + + + + + OCPSCH0104001MS + 10.10.1.26 + SONiC-Inventec-d6556 + 10.10.1.25 + 1 + 10 + 3 + + + OCPSCH0104002MS + 10.10.2.26 + SONiC-Inventec-d6556 + 10.10.2.25 + 1 + 10 + 3 + + + + + 64536 + SONiC-Inventec-d6556 + + +
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-d6556 + + + + + + Ethernet0 + 10.10.1.25/30 + + + + Ethernet4 + 10.10.2.25/30 + + + + + + + + + + + + DeviceInterfaceLink + OCPSCH0104001MS + Ethernet24 + SONiC-Inventec-d6556 + Ethernet0 + + + DeviceInterfaceLink + OCPSCH0104002MS + Ethernet24 + SONiC-Inventec-d6556 + Ethernet4 + + + + + SONiC-Inventec-d6556 + INVENTEC-D6556 + + + + + + + SONiC-Inventec-d6556 + + + 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-d6556 + INVENTEC-D6556 +
diff --git a/device/inventec/x86_64-inventec_d6556-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d6556-r0/plugins/eeprom.py new file mode 100644 index 000000000000..de5c24ba0e6d --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-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_d6556-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d6556-r0/plugins/psuutil.py new file mode 100644 index 000000000000..855162f63b98 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/plugins/psuutil.py @@ -0,0 +1,84 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_DIR = "/sys/class/hwmon/hwmon1" + + def __init__(self): + PsuBase.__init__(self) + +# Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + attr_file = 'psoc_psu'+ str(index) + '_iout' + attr_path = self.PSU_DIR +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU status + if (attr_value != 0): + status = 1 + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_absent = 0 + ind = index-1 + attr_file ='psu'+ str(ind) + attr_path = self.PSU_DIR +'/' + attr_file + normal_attr_value = '0 : normal' + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU presence + if (attr_value == normal_attr_value): + status = 1 + return status diff --git a/device/inventec/x86_64-inventec_d6556-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d6556-r0/plugins/sfputil.py new file mode 100644 index 000000000000..155b956827f1 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/plugins/sfputil.py @@ -0,0 +1,211 @@ +# 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 = 55 + PORTS_IN_BLOCK = 56 + QSFP_PORT_START = 48 + QSFP_PORT_END = 55 + + _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: 30, + 13: 31, + 14: 32, + 15: 33, + 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, + 32: 50, + 33: 51, + 34: 52, + 35: 53, + 36: 54, + 37: 55, + 38: 56, + 39: 57, + 40: 58, + 41: 59, + 42: 60, + 43: 61, + 44: 62, + 45: 63, + 46: 64, + 47: 65, + 48: 10, + 49: 11, + 50: 12, + 51: 13, + 52: 14, + 53: 15, + 54: 16, + 55: 17 + } + + @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/inventec/x86_64-inventec_d6556-r0/sensors.conf b/device/inventec/x86_64-inventec_d6556-r0/sensors.conf new file mode 100644 index 000000000000..98a8e59b9158 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/sensors.conf @@ -0,0 +1,44 @@ +# libsensors configuration file +chip "inv_psoc-*" + label temp1 "FrontSide Temperature" + label temp2 "FanBoard Temperature" + label temp3 "NearASIC Temperature" + label temp4 "Center Temperature" + + label temp5 "CPU Board Temperature" + label temp6 "ASIC Temperature" + label temp7 "PSU1 Temperature1" + label temp8 "PSU2 Temperature1" + label temp9 "PSU1 Temperature2" + label temp10 "PSU2 Temperature2" + label fan1 "FanModule1 Front RPM" + label fan2 "FanModule1 Rear RPM" + label fan3 "FanModule2 Front RPM" + label fan4 "FanModule2 Rear RPM" + label fan5 "FanModule3 Front RPM" + label fan6 "FanModule3 Rear RPM" + label fan7 "FanModule4 Front RPM" + label fan8 "FanModule4 Rear RPM" + label fan9 "FanModule5 Front RPM" + label fan10 "FanModule5 Rear RPM" + label pwm1 "FanModule1 PWM" + label pwm2 "FanModule2 PWM" + label pwm3 "FanModule3 PWM" + label pwm4 "FanModule4 PWM" + label pwm5 "FanModule5 PWM" + label pwm6 "PSU1 FAN PWM" + label pwm7 "PSU2 FAN PWM" + label fan11 "PSU1 FAN RPM" + label fan12 "PSU2 FAN RPM" + label in1 "PSU1 Input Voltage" + label in2 "PSU2 Input Voltage" + label curr1 "PSU1 Input Current" + label curr2 "PSU2 Input Current" + label power1 "PSU1 Input Power" + label power2 "PSU2 Input Power" + label in3 "PSU1 Output Voltage" + label in4 "PSU2 Output Voltage" + label curr3 "PSU1 Output Current" + label curr4 "PSU2 Output Current" + label power3 "PSU1 Output Power" + label power4 "PSU2 Output Power" diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/buffers.json.j2 b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/buffers.json.j2 new file mode 100644 index 000000000000..864e3bd9870d --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/buffers.json.j2 @@ -0,0 +1,128 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_speed = '100G' %} +{% set default_ports_num = 32 -%} + +{# 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' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- 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 -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- 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 -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(0,default_ports_num) %} + {% if PORT.append("Ethernet%d" % (port_idx*4)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + }, + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "6000000", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "8072396", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xon":"18432", + "xoff":"40560", + "size":"41808", + "dynamic_th":"-4", + "xon_offset":"2496" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"6000000" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/port_config.ini b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/port_config.ini new file mode 100644 index 000000000000..9b41dd7f6015 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 1,2,3,4 Ethernet0 +Ethernet4 5,6,7,8 Ethernet4 +Ethernet8 9,10,11,12 Ethernet8 +Ethernet12 13,14,15,16 Ethernet12 +Ethernet16 17,18,19,20 Ethernet16 +Ethernet20 21,22,23,24 Ethernet20 +Ethernet24 25,26,27,28 Ethernet24 +Ethernet28 29,30,31,32 Ethernet28 +Ethernet32 33,34,35,36 Ethernet32 +Ethernet36 37,38,39,40 Ethernet36 +Ethernet40 41,42,43,44 Ethernet40 +Ethernet44 45,46,47,48 Ethernet44 +Ethernet48 49,50,51,52 Ethernet48 +Ethernet52 53,54,55,56 Ethernet52 +Ethernet56 57,58,59,60 Ethernet56 +Ethernet60 61,62,63,64 Ethernet60 +Ethernet64 65,66,67,68 Ethernet64 +Ethernet68 69,70,71,72 Ethernet68 +Ethernet72 73,74,75,76 Ethernet72 +Ethernet76 77,78,79,80 Ethernet76 +Ethernet80 81,82,83,84 Ethernet80 +Ethernet84 85,86,87,88 Ethernet84 +Ethernet88 89,90,91,92 Ethernet88 +Ethernet92 93,94,95,96 Ethernet92 +Ethernet96 97,98,99,100 Ethernet96 +Ethernet100 101,102,103,104 Ethernet100 +Ethernet104 105,106,107,108 Ethernet104 +Ethernet108 109,110,111,112 Ethernet108 +Ethernet112 113,114,115,116 Ethernet112 +Ethernet116 117,118,119,120 Ethernet116 +Ethernet120 121,122,123,124 Ethernet120 +Ethernet124 125,126,127,128 Ethernet124 diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/qos.json b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/qos.json new file mode 100644 index 000000000000..926911ab59d0 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/qos.json @@ -0,0 +1,143 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable": "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"312000", + "red_min_threshold":"104000", + "yellow_max_threshold":"312000", + "yellow_min_threshold":"104000", + "green_max_threshold":"312000", + "green_min_threshold":"104000" + } + }, + "QUEUE": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|3-4" : { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0" : { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|1" : { + "scheduler" : "[SCHEDULER|scheduler.2]" + } + } +} diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/sai.profile b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/sai.profile new file mode 100644 index 000000000000..acd7f9034862 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-d7032q28b-32x100g.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/th-d7032q28b-32x100g.config.bcm b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/th-d7032q28b-32x100g.config.bcm new file mode 100644 index 000000000000..613158431634 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/th-d7032q28b-32x100g.config.bcm @@ -0,0 +1,290 @@ +# Redwood BCM Shell config / all 100G 32 ports + +# Define default OS / SAL +os=unix + +l2_mem_entries=8192 +l3_mem_entries=8192 +l3_alpm_enable=2 +#ipv6_lpm_128b_enable=1 +l2xmsg_mode=1 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +# per Broadcom feedback, no more pbmp_oversubscribe +# pbmp_oversubscribe=0x00003fc000000ff0000003fc000001fe +oversubscribe_mode=1 +pbmp_xport_xe=0x3fd000000ff4000003fc000001fe + +# EagleCore ports +portmap_66=129:10 +portmap_100=131:10 + +# Loopback ports +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 + +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_106=113:100 +portmap_107=117:100 +portmap_108=121:100 +portmap_109=125:100 + +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_6=21:100 +portmap_7=25:100 +portmap_8=29:100 + +portmap_34=33:100 +portmap_35=37:100 +portmap_36=41:100 +portmap_37=45:100 +portmap_38=49:100 +portmap_39=53:100 +portmap_40=57:100 +portmap_41=61:100 + +phy_xaui_tx_polarity_flip_ce0=0x8 +phy_xaui_tx_polarity_flip_ce1=0x6 +phy_xaui_tx_polarity_flip_ce2=0x6 +phy_xaui_tx_polarity_flip_ce3=0x6 +phy_xaui_tx_polarity_flip_ce4=0x3 +phy_xaui_tx_polarity_flip_ce5=0x4 +phy_xaui_tx_polarity_flip_ce6=0xc +phy_xaui_tx_polarity_flip_ce7=0x6 +phy_xaui_tx_polarity_flip_ce8=0xc +phy_xaui_tx_polarity_flip_ce9=0x3 +phy_xaui_tx_polarity_flip_ce10=0x3 +phy_xaui_tx_polarity_flip_ce11=0x3 +phy_xaui_tx_polarity_flip_ce12=0x4 +phy_xaui_tx_polarity_flip_ce13=0x1 +phy_xaui_tx_polarity_flip_ce14=0x2 +phy_xaui_tx_polarity_flip_ce15=0x3 +phy_xaui_tx_polarity_flip_ce16=0x2 +phy_xaui_tx_polarity_flip_ce17=0x3 +phy_xaui_tx_polarity_flip_ce18=0x2 +phy_xaui_tx_polarity_flip_ce19=0x8 +phy_xaui_tx_polarity_flip_ce20=0x2 +phy_xaui_tx_polarity_flip_ce21=0x9 +phy_xaui_tx_polarity_flip_ce22=0x8 +phy_xaui_tx_polarity_flip_ce23=0x9 +phy_xaui_tx_polarity_flip_ce24=0x2 +phy_xaui_tx_polarity_flip_ce25=0x4 +phy_xaui_tx_polarity_flip_ce26=0xd +phy_xaui_tx_polarity_flip_ce27=0xc +phy_xaui_tx_polarity_flip_ce28=0x3 +phy_xaui_tx_polarity_flip_ce29=0xc +phy_xaui_tx_polarity_flip_ce30=0xc +phy_xaui_tx_polarity_flip_ce31=0x2 + +phy_xaui_rx_polarity_flip_ce0=0xb +phy_xaui_rx_polarity_flip_ce1=0xc +phy_xaui_rx_polarity_flip_ce2=0xc +phy_xaui_rx_polarity_flip_ce3=0xc +phy_xaui_rx_polarity_flip_ce4=0x1 +phy_xaui_rx_polarity_flip_ce5=0xc +phy_xaui_rx_polarity_flip_ce6=0x4 +phy_xaui_rx_polarity_flip_ce7=0xc +phy_xaui_rx_polarity_flip_ce8=0xb +phy_xaui_rx_polarity_flip_ce9=0x6 +phy_xaui_rx_polarity_flip_ce10=0x1 +phy_xaui_rx_polarity_flip_ce11=0x8 +phy_xaui_rx_polarity_flip_ce12=0xc +phy_xaui_rx_polarity_flip_ce13=0x6 +phy_xaui_rx_polarity_flip_ce14=0x4 +phy_xaui_rx_polarity_flip_ce15=0xe +phy_xaui_rx_polarity_flip_ce16=0xe +phy_xaui_rx_polarity_flip_ce17=0x2 +phy_xaui_rx_polarity_flip_ce18=0x4 +phy_xaui_rx_polarity_flip_ce19=0x6 +phy_xaui_rx_polarity_flip_ce20=0xe +phy_xaui_rx_polarity_flip_ce21=0x3 +phy_xaui_rx_polarity_flip_ce22=0x3 +phy_xaui_rx_polarity_flip_ce23=0x3 +phy_xaui_rx_polarity_flip_ce24=0xb +phy_xaui_rx_polarity_flip_ce25=0xc +phy_xaui_rx_polarity_flip_ce26=0xe +phy_xaui_rx_polarity_flip_ce27=0xc +phy_xaui_rx_polarity_flip_ce28=0xb +phy_xaui_rx_polarity_flip_ce29=0x9 +phy_xaui_rx_polarity_flip_ce30=0x6 +phy_xaui_rx_polarity_flip_ce31=0x9 + +# EQ/iDriver +serdes_preemphasis_1=0x323E00 +serdes_preemphasis_2=0x323E00 +serdes_preemphasis_3=0x323E00 +serdes_preemphasis_4=0x323E00 + +serdes_preemphasis_5=0x323E00 +serdes_preemphasis_6=0x323E00 +serdes_preemphasis_7=0x323E00 +serdes_preemphasis_8=0x323E00 + +serdes_preemphasis_9=0x343C00 +serdes_preemphasis_10=0x343C00 +serdes_preemphasis_11=0x343C00 +serdes_preemphasis_12=0x343C00 + +serdes_preemphasis_13=0x343C00 +serdes_preemphasis_14=0x343C00 +serdes_preemphasis_15=0x343C00 +serdes_preemphasis_16=0x343C00 + +serdes_preemphasis_17=0x323E00 +serdes_preemphasis_18=0x323E00 +serdes_preemphasis_19=0x323E00 +serdes_preemphasis_20=0x323E00 + +serdes_preemphasis_21=0x323E00 +serdes_preemphasis_22=0x323E00 +serdes_preemphasis_23=0x323E00 +serdes_preemphasis_24=0x323E00 + +serdes_preemphasis_25=0x304000 +serdes_preemphasis_26=0x304000 +serdes_preemphasis_27=0x304000 +serdes_preemphasis_28=0x304000 + +serdes_preemphasis_29=0x304000 +serdes_preemphasis_30=0x304000 +serdes_preemphasis_31=0x304000 +serdes_preemphasis_32=0x304000 + +serdes_preemphasis_34=0x2D4300 +serdes_preemphasis_35=0x2D4300 +serdes_preemphasis_36=0x2D4300 +serdes_preemphasis_37=0x2D4300 + +serdes_preemphasis_38=0x2D4300 +serdes_preemphasis_39=0x2D4300 +serdes_preemphasis_40=0x2D4300 +serdes_preemphasis_41=0x2D4300 + +serdes_preemphasis_42=0x2B4500 +serdes_preemphasis_43=0x2B4500 +serdes_preemphasis_44=0x2B4500 +serdes_preemphasis_45=0x2B4500 + +serdes_preemphasis_46=0x2B4500 +serdes_preemphasis_47=0x2B4500 +serdes_preemphasis_48=0x2B4500 +serdes_preemphasis_49=0x2B4500 + +serdes_preemphasis_50=0x2B4500 +serdes_preemphasis_51=0x2B4500 +serdes_preemphasis_52=0x2B4500 +serdes_preemphasis_53=0x2B4500 + +serdes_preemphasis_54=0x284800 +serdes_preemphasis_55=0x284800 +serdes_preemphasis_56=0x284800 +serdes_preemphasis_57=0x284800 + +serdes_preemphasis_58=0x2B4500 +serdes_preemphasis_59=0x2B4500 +serdes_preemphasis_60=0x2B4500 +serdes_preemphasis_61=0x2B4500 + +serdes_preemphasis_62=0x2B4500 +serdes_preemphasis_63=0x2B4500 +serdes_preemphasis_64=0x2B4500 +serdes_preemphasis_65=0x2B4500 + +serdes_preemphasis_68=0x284800 +serdes_preemphasis_69=0x284800 +serdes_preemphasis_70=0x284800 +serdes_preemphasis_71=0x284800 + +serdes_preemphasis_72=0x284800 +serdes_preemphasis_73=0x284800 +serdes_preemphasis_74=0x284800 +serdes_preemphasis_75=0x284800 + +serdes_preemphasis_76=0x284800 +serdes_preemphasis_77=0x284800 +serdes_preemphasis_78=0x284800 +serdes_preemphasis_79=0x284800 + +serdes_preemphasis_80=0x2A4600 +serdes_preemphasis_81=0x2A4600 +serdes_preemphasis_82=0x2A4600 +serdes_preemphasis_83=0x2A4600 + +serdes_preemphasis_84=0x2B4500 +serdes_preemphasis_85=0x2B4500 +serdes_preemphasis_86=0x2B4500 +serdes_preemphasis_87=0x2B4500 + +serdes_preemphasis_88=0x2A4600 +serdes_preemphasis_89=0x2A4600 +serdes_preemphasis_90=0x2A4600 +serdes_preemphasis_91=0x2A4600 + +serdes_preemphasis_92=0x2B4500 +serdes_preemphasis_93=0x2B4500 +serdes_preemphasis_94=0x2B4500 +serdes_preemphasis_95=0x2B4500 + +serdes_preemphasis_96=0x2B4500 +serdes_preemphasis_97=0x2B4500 +serdes_preemphasis_98=0x2B4500 +serdes_preemphasis_99=0x2B4500 + +serdes_preemphasis_102=0x2B4500 +serdes_preemphasis_103=0x2B4500 +serdes_preemphasis_104=0x2B4500 +serdes_preemphasis_105=0x2B4500 + +serdes_preemphasis_106=0x2B4500 +serdes_preemphasis_107=0x2B4500 +serdes_preemphasis_108=0x2B4500 +serdes_preemphasis_109=0x2B4500 + +serdes_preemphasis_110=0x2D4300 +serdes_preemphasis_111=0x2D4300 +serdes_preemphasis_112=0x2D4300 +serdes_preemphasis_113=0x2D4300 + +serdes_preemphasis_114=0x304000 +serdes_preemphasis_115=0x304000 +serdes_preemphasis_116=0x304000 +serdes_preemphasis_117=0x304000 + +serdes_preemphasis_118=0x304000 +serdes_preemphasis_119=0x304000 +serdes_preemphasis_120=0x304000 +serdes_preemphasis_121=0x304000 + +serdes_preemphasis_122=0x304000 +serdes_preemphasis_123=0x304000 +serdes_preemphasis_124=0x304000 +serdes_preemphasis_125=0x304000 + +serdes_preemphasis_126=0x343C00 +serdes_preemphasis_127=0x343C00 +serdes_preemphasis_128=0x343C00 +serdes_preemphasis_129=0x343C00 + +serdes_preemphasis_130=0x343C00 +serdes_preemphasis_131=0x343C00 +serdes_preemphasis_132=0x343C00 +serdes_preemphasis_133=0x343C00 diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/th-d7032q28b-32x40g.config.bcm b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/th-d7032q28b-32x40g.config.bcm new file mode 100644 index 000000000000..03d0bb06cb06 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/th-d7032q28b-32x40g.config.bcm @@ -0,0 +1,427 @@ +# Redwood BCM Shell config / all 100G 32 ports + +# Define default OS / SAL +os=unix + +l2_mem_entries=8192 +l3_mem_entries=8192 +l3_alpm_enable=2 +#ipv6_lpm_128b_enable=1 +l2xmsg_mode=1 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +# per Broadcom feedback, no more pbmp_oversubscribe +# pbmp_oversubscribe=0x00003fc000000ff0000003fc000001fe +oversubscribe_mode=1 +pbmp_xport_xe=0x3fd000000ff4000003fc000001fe + +# EagleCore ports +portmap_66=129:10 +portmap_100=131:10 + +# Loopback ports +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +portmap_68=65:40 +portmap_69=69:40 +portmap_70=73:40 +portmap_71=77:40 +portmap_72=81:40 +portmap_73=85:40 +portmap_74=89:40 +portmap_75=93:40 + +portmap_102=97:40 +portmap_103=101:40 +portmap_104=105:40 +portmap_105=109:40 +portmap_106=113:40 +portmap_107=117:40 +portmap_108=121:40 +portmap_109=125:40 + +portmap_1=1:40 +portmap_2=5:40 +portmap_3=9:40 +portmap_4=13:40 +portmap_5=17:40 +portmap_6=21:40 +portmap_7=25:40 +portmap_8=29:40 + +portmap_34=33:40 +portmap_35=37:40 +portmap_36=41:40 +portmap_37=45:40 +portmap_38=49:40 +portmap_39=53:40 +portmap_40=57:40 +portmap_41=61:40 + +phy_xaui_tx_polarity_flip_xe0=0x8 +phy_xaui_tx_polarity_flip_xe1=0x6 +phy_xaui_tx_polarity_flip_xe2=0x6 +phy_xaui_tx_polarity_flip_xe3=0x6 +phy_xaui_tx_polarity_flip_xe4=0x3 +phy_xaui_tx_polarity_flip_xe5=0x4 +phy_xaui_tx_polarity_flip_xe6=0xc +phy_xaui_tx_polarity_flip_xe7=0x6 +phy_xaui_tx_polarity_flip_xe8=0xc +phy_xaui_tx_polarity_flip_xe9=0x3 +phy_xaui_tx_polarity_flip_xe10=0x3 +phy_xaui_tx_polarity_flip_xe11=0x3 +phy_xaui_tx_polarity_flip_xe12=0x4 +phy_xaui_tx_polarity_flip_xe13=0x1 +phy_xaui_tx_polarity_flip_xe14=0x2 +phy_xaui_tx_polarity_flip_xe15=0x3 +phy_xaui_tx_polarity_flip_xe16=0x2 +phy_xaui_tx_polarity_flip_xe17=0x3 +phy_xaui_tx_polarity_flip_xe18=0x2 +phy_xaui_tx_polarity_flip_xe19=0x8 +phy_xaui_tx_polarity_flip_xe20=0x2 +phy_xaui_tx_polarity_flip_xe21=0x9 +phy_xaui_tx_polarity_flip_xe22=0x8 +phy_xaui_tx_polarity_flip_xe23=0x9 +phy_xaui_tx_polarity_flip_xe24=0x2 +phy_xaui_tx_polarity_flip_xe25=0x4 +phy_xaui_tx_polarity_flip_xe26=0xd +phy_xaui_tx_polarity_flip_xe27=0xc +phy_xaui_tx_polarity_flip_xe28=0x3 +phy_xaui_tx_polarity_flip_xe29=0xc +phy_xaui_tx_polarity_flip_xe30=0xc +phy_xaui_tx_polarity_flip_xe31=0x2 + +phy_xaui_rx_polarity_flip_xe0=0xb +phy_xaui_rx_polarity_flip_xe1=0xc +phy_xaui_rx_polarity_flip_xe2=0xc +phy_xaui_rx_polarity_flip_xe3=0xc +phy_xaui_rx_polarity_flip_xe4=0x1 +phy_xaui_rx_polarity_flip_xe5=0xc +phy_xaui_rx_polarity_flip_xe6=0x4 +phy_xaui_rx_polarity_flip_xe7=0xc +phy_xaui_rx_polarity_flip_xe8=0xb +phy_xaui_rx_polarity_flip_xe9=0x6 +phy_xaui_rx_polarity_flip_xe10=0x1 +phy_xaui_rx_polarity_flip_xe11=0x8 +phy_xaui_rx_polarity_flip_xe12=0xc +phy_xaui_rx_polarity_flip_xe13=0x6 +phy_xaui_rx_polarity_flip_xe14=0x4 +phy_xaui_rx_polarity_flip_xe15=0xe +phy_xaui_rx_polarity_flip_xe16=0xe +phy_xaui_rx_polarity_flip_xe17=0x2 +phy_xaui_rx_polarity_flip_xe18=0x4 +phy_xaui_rx_polarity_flip_xe19=0x6 +phy_xaui_rx_polarity_flip_xe20=0xe +phy_xaui_rx_polarity_flip_xe21=0x3 +phy_xaui_rx_polarity_flip_xe22=0x3 +phy_xaui_rx_polarity_flip_xe23=0x3 +phy_xaui_rx_polarity_flip_xe24=0xb +phy_xaui_rx_polarity_flip_xe25=0xc +phy_xaui_rx_polarity_flip_xe26=0xe +phy_xaui_rx_polarity_flip_xe27=0xc +phy_xaui_rx_polarity_flip_xe28=0xb +phy_xaui_rx_polarity_flip_xe29=0x9 +phy_xaui_rx_polarity_flip_xe30=0x6 +phy_xaui_rx_polarity_flip_xe31=0x9 + +# EQ/iDriver +# 0 ~ 5 +serdes_preemphasis_1=0x1E5200 +serdes_preemphasis_2=0x1E5200 +serdes_preemphasis_3=0x1E5200 +serdes_preemphasis_4=0x1E5200 +serdes_driver_current_1=0x000001 +serdes_driver_current_2=0x000001 +serdes_driver_current_3=0x000001 +serdes_driver_current_4=0x000001 + +serdes_preemphasis_5=0x1E5200 +serdes_preemphasis_6=0x1E5200 +serdes_preemphasis_7=0x1E5200 +serdes_preemphasis_8=0x1E5200 +serdes_driver_current_5=0x000001 +serdes_driver_current_6=0x000001 +serdes_driver_current_7=0x000001 +serdes_driver_current_8=0x000001 + +serdes_preemphasis_9=0x1E5200 +serdes_preemphasis_10=0x1E5200 +serdes_preemphasis_11=0x1E5200 +serdes_preemphasis_12=0x1E5200 +serdes_driver_current_9=0x000001 +serdes_driver_current_10=0x000001 +serdes_driver_current_11=0x000001 +serdes_driver_current_12=0x000001 + +serdes_preemphasis_13=0x1E5200 +serdes_preemphasis_14=0x1E5200 +serdes_preemphasis_15=0x1E5200 +serdes_preemphasis_16=0x1E5200 +serdes_driver_current_13=0x000001 +serdes_driver_current_14=0x000001 +serdes_driver_current_15=0x000001 +serdes_driver_current_16=0x000001 + +serdes_preemphasis_17=0x1E5200 +serdes_preemphasis_18=0x1E5200 +serdes_preemphasis_19=0x1E5200 +serdes_preemphasis_20=0x1E5200 +serdes_driver_current_17=0x000001 +serdes_driver_current_18=0x000001 +serdes_driver_current_19=0x000001 +serdes_driver_current_20=0x000001 + +serdes_preemphasis_21=0x1E5200 +serdes_preemphasis_22=0x1E5200 +serdes_preemphasis_23=0x1E5200 +serdes_preemphasis_24=0x1E5200 +serdes_driver_current_21=0x000001 +serdes_driver_current_22=0x000001 +serdes_driver_current_23=0x000001 +serdes_driver_current_24=0x000001 + +# 6 ~ 11 +serdes_preemphasis_25=0x1A5600 +serdes_preemphasis_26=0x1A5600 +serdes_preemphasis_27=0x1A5600 +serdes_preemphasis_28=0x1A5600 +serdes_driver_current_25=0x000001 +serdes_driver_current_26=0x000001 +serdes_driver_current_27=0x000001 +serdes_driver_current_28=0x000001 + +serdes_preemphasis_29=0x1A5600 +serdes_preemphasis_30=0x1A5600 +serdes_preemphasis_31=0x1A5600 +serdes_preemphasis_32=0x1A5600 +serdes_driver_current_29=0x000001 +serdes_driver_current_30=0x000001 +serdes_driver_current_31=0x000001 +serdes_driver_current_32=0x000001 + +serdes_preemphasis_34=0x1A5600 +serdes_preemphasis_35=0x1A5600 +serdes_preemphasis_36=0x1A5600 +serdes_preemphasis_37=0x1A5600 +serdes_driver_current_34=0x000001 +serdes_driver_current_35=0x000001 +serdes_driver_current_36=0x000001 +serdes_driver_current_37=0x000001 + +serdes_preemphasis_38=0x1A5600 +serdes_preemphasis_39=0x1A5600 +serdes_preemphasis_40=0x1A5600 +serdes_preemphasis_41=0x1A5600 +serdes_driver_current_38=0x000001 +serdes_driver_current_39=0x000001 +serdes_driver_current_40=0x000001 +serdes_driver_current_41=0x000001 + +serdes_preemphasis_42=0x1A5600 +serdes_preemphasis_43=0x1A5600 +serdes_preemphasis_44=0x1A5600 +serdes_preemphasis_45=0x1A5600 +serdes_driver_current_42=0x000001 +serdes_driver_current_43=0x000001 +serdes_driver_current_44=0x000001 +serdes_driver_current_45=0x000001 + +serdes_preemphasis_46=0x1A5600 +serdes_preemphasis_47=0x1A5600 +serdes_preemphasis_48=0x1A5600 +serdes_preemphasis_49=0x1A5600 +serdes_driver_current_46=0x000001 +serdes_driver_current_47=0x000001 +serdes_driver_current_48=0x000001 +serdes_driver_current_49=0x000001 + +# 12 ~ 13 +serdes_preemphasis_50=0x165A00 +serdes_preemphasis_51=0x165A00 +serdes_preemphasis_52=0x165A00 +serdes_preemphasis_53=0x165A00 +serdes_driver_current_50=0x000000 +serdes_driver_current_51=0x000000 +serdes_driver_current_52=0x000000 +serdes_driver_current_53=0x000000 + +serdes_preemphasis_54=0x165A00 +serdes_preemphasis_55=0x165A00 +serdes_preemphasis_56=0x165A00 +serdes_preemphasis_57=0x165A00 +serdes_driver_current_54=0x000000 +serdes_driver_current_55=0x000000 +serdes_driver_current_56=0x000000 +serdes_driver_current_57=0x000000 + +# 14 ~ 16 +serdes_preemphasis_58=0x125E00 +serdes_preemphasis_59=0x125E00 +serdes_preemphasis_60=0x125E00 +serdes_preemphasis_61=0x125E00 +serdes_driver_current_58=0x000100 +serdes_driver_current_59=0x000100 +serdes_driver_current_60=0x000100 +serdes_driver_current_61=0x000100 + +serdes_preemphasis_62=0x125E00 +serdes_preemphasis_63=0x125E00 +serdes_preemphasis_64=0x125E00 +serdes_preemphasis_65=0x125E00 +serdes_driver_current_62=0x000100 +serdes_driver_current_63=0x000100 +serdes_driver_current_64=0x000100 +serdes_driver_current_65=0x000100 + +serdes_preemphasis_68=0x125E00 +serdes_preemphasis_69=0x125E00 +serdes_preemphasis_70=0x125E00 +serdes_preemphasis_71=0x125E00 +serdes_driver_current_68=0x000100 +serdes_driver_current_69=0x000100 +serdes_driver_current_70=0x000100 +serdes_driver_current_71=0x000100 + +# 17 ~ 21 +serdes_preemphasis_72=0x106000 +serdes_preemphasis_73=0x106000 +serdes_preemphasis_74=0x106000 +serdes_preemphasis_75=0x106000 +serdes_driver_current_72=0x000100 +serdes_driver_current_73=0x000100 +serdes_driver_current_74=0x000100 +serdes_driver_current_75=0x000100 + +serdes_preemphasis_76=0x106000 +serdes_preemphasis_77=0x106000 +serdes_preemphasis_78=0x106000 +serdes_preemphasis_79=0x106000 +serdes_driver_current_76=0x000100 +serdes_driver_current_77=0x000100 +serdes_driver_current_78=0x000100 +serdes_driver_current_79=0x000100 + +serdes_preemphasis_80=0x106000 +serdes_preemphasis_81=0x106000 +serdes_preemphasis_82=0x106000 +serdes_preemphasis_83=0x106000 +serdes_driver_current_80=0x000100 +serdes_driver_current_81=0x000100 +serdes_driver_current_82=0x000100 +serdes_driver_current_83=0x000100 + +serdes_preemphasis_84=0x106000 +serdes_preemphasis_85=0x106000 +serdes_preemphasis_86=0x106000 +serdes_preemphasis_87=0x106000 +serdes_driver_current_84=0x000100 +serdes_driver_current_85=0x000100 +serdes_driver_current_86=0x000100 +serdes_driver_current_87=0x000100 + +serdes_preemphasis_88=0x106000 +serdes_preemphasis_89=0x106000 +serdes_preemphasis_90=0x106000 +serdes_preemphasis_91=0x106000 +serdes_driver_current_88=0x000100 +serdes_driver_current_89=0x000100 +serdes_driver_current_90=0x000100 +serdes_driver_current_91=0x000100 + +# 22 ~ 23 +serdes_preemphasis_92=0x125E00 +serdes_preemphasis_93=0x125E00 +serdes_preemphasis_94=0x125E00 +serdes_preemphasis_95=0x125E00 +serdes_driver_current_92=0x000100 +serdes_driver_current_93=0x000100 +serdes_driver_current_94=0x000100 +serdes_driver_current_95=0x000100 + +serdes_preemphasis_96=0x125E00 +serdes_preemphasis_97=0x125E00 +serdes_preemphasis_98=0x125E00 +serdes_preemphasis_99=0x125E00 +serdes_driver_current_96=0x000100 +serdes_driver_current_97=0x000100 +serdes_driver_current_98=0x000100 +serdes_driver_current_99=0x000100 + +# 24 ~ 25 +serdes_preemphasis_102=0x165A00 +serdes_preemphasis_103=0x165A00 +serdes_preemphasis_104=0x165A00 +serdes_preemphasis_105=0x165A00 +serdes_driver_current_102=0x000000 +serdes_driver_current_103=0x000000 +serdes_driver_current_104=0x000000 +serdes_driver_current_105=0x000000 + +serdes_preemphasis_106=0x165A00 +serdes_preemphasis_107=0x165A00 +serdes_preemphasis_108=0x165A00 +serdes_preemphasis_109=0x165A00 +serdes_driver_current_106=0x000000 +serdes_driver_current_107=0x000000 +serdes_driver_current_108=0x000000 +serdes_driver_current_109=0x000000 + +# 26 ~ 29 +serdes_preemphasis_110=0x1A5600 +serdes_preemphasis_111=0x1A5600 +serdes_preemphasis_112=0x1A5600 +serdes_preemphasis_113=0x1A5600 +serdes_driver_current_110=0x000001 +serdes_driver_current_111=0x000001 +serdes_driver_current_112=0x000001 +serdes_driver_current_113=0x000001 + +serdes_preemphasis_114=0x1A5600 +serdes_preemphasis_115=0x1A5600 +serdes_preemphasis_116=0x1A5600 +serdes_preemphasis_117=0x1A5600 +serdes_driver_current_114=0x000001 +serdes_driver_current_115=0x000001 +serdes_driver_current_116=0x000001 +serdes_driver_current_117=0x000001 + +serdes_preemphasis_118=0x1A5600 +serdes_preemphasis_119=0x1A5600 +serdes_preemphasis_120=0x1A5600 +serdes_preemphasis_121=0x1A5600 +serdes_driver_current_118=0x000001 +serdes_driver_current_119=0x000001 +serdes_driver_current_120=0x000001 +serdes_driver_current_121=0x000001 + +serdes_preemphasis_122=0x1A5600 +serdes_preemphasis_123=0x1A5600 +serdes_preemphasis_124=0x1A5600 +serdes_preemphasis_125=0x1A5600 +serdes_driver_current_122=0x000001 +serdes_driver_current_123=0x000001 +serdes_driver_current_124=0x000001 +serdes_driver_current_125=0x000001 + +# 30 ~ 31 +serdes_preemphasis_126=0x1E5200 +serdes_preemphasis_127=0x1E5200 +serdes_preemphasis_128=0x1E5200 +serdes_preemphasis_129=0x1E5200 +serdes_driver_current_126=0x000001 +serdes_driver_current_127=0x000001 +serdes_driver_current_128=0x000001 +serdes_driver_current_129=0x000001 + +serdes_preemphasis_130=0x1E5200 +serdes_preemphasis_131=0x1E5200 +serdes_preemphasis_132=0x1E5200 +serdes_preemphasis_133=0x1E5200 +serdes_driver_current_130=0x000001 +serdes_driver_current_131=0x000001 +serdes_driver_current_132=0x000001 +serdes_driver_current_133=0x000001 diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/default_sku b/device/inventec/x86_64-inventec_d7032q28b-r0/default_sku new file mode 100644 index 000000000000..505f1765e6e5 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/default_sku @@ -0,0 +1 @@ +INVENTEC-D7032Q28B-C32 t1 diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/installer.conf b/device/inventec/x86_64-inventec_d7032q28b-r0/installer.conf new file mode 100644 index 000000000000..6b489db6e16f --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 +VAR_LOG_SIZE=1024 diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d7032q28b-r0/led_proc_init.soc new file mode 100644 index 000000000000..92423b234498 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/led_proc_init.soc @@ -0,0 +1,136 @@ +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=30 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=29 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=26 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=25 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=22 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=21 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=18 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=17 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=14 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=13 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=10 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=9 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=6 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=5 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=2 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=1 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=62 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=61 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=58 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=54 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=53 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=50 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=49 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=46 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=45 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=42 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=41 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=38 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=37 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=34 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=33 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=2 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=1 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=6 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=5 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=10 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=9 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=14 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=13 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=18 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=17 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=22 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=21 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=26 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=25 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=30 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=29 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=34 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=33 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=38 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=42 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=41 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=46 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=45 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=50 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=49 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=54 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=53 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=58 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=57 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=62 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=61 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=60 + +led 0 stop +led 0 prog 02 00 60 F1 12 00 DA 0F 70 10 67 47 67 42 77 06 02 A0 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DA 80 70 34 86 F0 77 16 12 00 DA 03 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +led 0 start + +led 1 stop +led 1 prog 02 00 60 F1 12 00 DA 0F 70 10 67 47 67 42 77 06 02 A0 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DA 80 70 34 86 F0 77 16 12 00 DA 03 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +led 1 start diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/eeprom.py new file mode 100644 index 000000000000..de5c24ba0e6d --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-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_d7032q28b-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/psuutil.py new file mode 100644 index 000000000000..cc5ca004dadf --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/psuutil.py @@ -0,0 +1,88 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_DIR = "/sys/bus/i2c/devices/0-0066" + + def __init__(self): + PsuBase.__init__(self) + +# Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + if (index == 1): + ind = 2 + if (index == 2): + ind = 1 + attr_file = 'psu'+ str(ind) + '_iout' + attr_path = self.PSU_DIR +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU status + if (attr_value != 0): + status = 1 + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_absent = 0 + ind = index-1 + attr_file ='psu'+ str(ind) + attr_path = self.PSU_DIR +'/' + attr_file + normal_attr_value = '0 : normal' + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU presence + if (attr_value == normal_attr_value): + status = 1 + return status diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/sfputil.py new file mode 100644 index 000000000000..d109f49f2e7d --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/sfputil.py @@ -0,0 +1,187 @@ +# 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 = 31 + PORTS_IN_BLOCK = 32 + QSFP_PORT_START = 0 + QSFP_PORT_END = 31 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: 22, + 1: 23, + 2: 24, + 3: 25, + 4: 26, + 5: 27, + 6: 28, + 7: 29, + 8: 30, + 9: 31, + 10: 32, + 11: 33, + 12: 34, + 13: 35, + 14: 36, + 15: 37, + 16: 6, + 17: 7, + 18: 8, + 19: 9, + 20: 10, + 21: 11, + 22: 12, + 23: 13, + 24: 14, + 25: 15, + 26: 16, + 27: 17, + 28: 18, + 29: 19, + 30: 20, + 31: 21 + } + + @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(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) + + 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 + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/sensors.conf b/device/inventec/x86_64-inventec_d7032q28b-r0/sensors.conf new file mode 100644 index 000000000000..653900cad36f --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/sensors.conf @@ -0,0 +1,15 @@ +# libsensors configuration file +chip "inv_psoc-*" + ignore temp3 + ignore temp4 + label temp1 "CPU Board Temperature" + label temp2 "SW Board I Temperature" + label temp5 "SW Board II Temperature" + label temp6 "ASIC Temperature" + label in1 "PSU1 Voltage" + label in2 "PSU2 Voltage" + label curr1 "PSU1 Current" + label curr2 "PSU2 Current" + label power1 "PSU1 Power" + label power2 "PSU2 Power" + diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/buffers.json.j2 b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/buffers.json.j2 new file mode 100644 index 000000000000..ccf463c40526 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/buffers.json.j2 @@ -0,0 +1,128 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_speed = '100G' %} +{% set default_ports_num = 54 -%} + +{# 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' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- 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 -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- 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 -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(0,default_ports_num) %} + {% if PORT.append("Ethernet%d" % (port_idx*4)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + }, + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "6000000", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "8072396", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xon":"18432", + "xoff":"40560", + "size":"41808", + "dynamic_th":"-4", + "xon_offset":"2496" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"6000000" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} 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..8b0addcada13 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/port_config.ini @@ -0,0 +1,55 @@ +# 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/qos.json b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/qos.json new file mode 100644 index 000000000000..9949a5903d8b --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/qos.json @@ -0,0 +1,143 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124,Ethernet128,Ethernet132,Ethernet136,Ethernet140,Ethernet144,Ethernet148,Ethernet152,Ethernet156,Ethernet160,Ethernet164,Ethernet168,Ethernet172,Ethernet176,Ethernet180,Ethernet184,Ethernet188,Ethernet192,Ethernet196,Ethernet200,Ethernet204,Ethernet208,Ethernet212": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable": "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"312000", + "red_min_threshold":"104000", + "yellow_max_threshold":"312000", + "yellow_min_threshold":"104000", + "green_max_threshold":"312000", + "green_min_threshold":"104000" + } + }, + "QUEUE": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124,Ethernet128,Ethernet132,Ethernet136,Ethernet140,Ethernet144,Ethernet148,Ethernet152,Ethernet156,Ethernet160,Ethernet164,Ethernet168,Ethernet172,Ethernet176,Ethernet180,Ethernet184,Ethernet188,Ethernet192,Ethernet196,Ethernet200,Ethernet204,Ethernet208,Ethernet212|3-4" : { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124,Ethernet128,Ethernet132,Ethernet136,Ethernet140,Ethernet144,Ethernet148,Ethernet152,Ethernet156,Ethernet160,Ethernet164,Ethernet168,Ethernet172,Ethernet176,Ethernet180,Ethernet184,Ethernet188,Ethernet192,Ethernet196,Ethernet200,Ethernet204,Ethernet208,Ethernet212|0" : { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124,Ethernet128,Ethernet132,Ethernet136,Ethernet140,Ethernet144,Ethernet148,Ethernet152,Ethernet156,Ethernet160,Ethernet164,Ethernet168,Ethernet172,Ethernet176,Ethernet180,Ethernet184,Ethernet188,Ethernet192,Ethernet196,Ethernet200,Ethernet204,Ethernet208,Ethernet212|1" : { + "scheduler" : "[SCHEDULER|scheduler.2]" + } + } +} 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..73cbea239694 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-d7054q28b-48x25g-6x100g.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/th-d7054q28b-48x10g-6x100g.config.bcm b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/th-d7054q28b-48x10g-6x100g.config.bcm new file mode 100644 index 000000000000..b90ba92a97bc --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/th-d7054q28b-48x10g-6x100g.config.bcm @@ -0,0 +1,465 @@ +# Cypress BCM Shell config / 10G * 48 ports; 100G * 6 ports + +# Define default OS / SAL +os=unix + +l2_mem_entries=40960 +l3_mem_entries=40960 +fpem_mem_entries=32768 +l2xmsg_mode=1 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 + +## update the hex string based on case ID: 925941 +## 1. type "phy info" then get each hg ports' number +## 2. Set these number as 1 in pbmp_xport_xe and pbmp_oversubscribe +## 130 xe ports, 4 * 32 + 2 +## no more pbmp_oversubscribe +oversubscribe_mode=1 +pbmp_xport_xe=0x3fffffffdffffffff7fffffffdfffffffe + + +# EagleCore ports: 36 & 49 +portmap_66=129:10 +portmap_100=131:10 + +# Loopback ports +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +# First 12*4 48 ports config for 10G +# Second 6 ports config for 100G +# For Tomahawk FalconCore: +# Physical ports in FalconCore[0 - 7] must map to logical port[1 - 32] at any order +# Physical ports in FalconCore[8 - 15] must map to logical port[34 - 65] at any order +# Physical ports in FalconCore[16 - 23] must map to logical port[68 - 99] at any order +# Physical ports in FalconCore[24 - 31] must map to logical port[102 - 133] at any order + +## FalconCore[0,1,2,5] +portmap_1=2:10 +portmap_2=1:10 +portmap_3=4:10 +portmap_4=3:10 +portmap_5=6:10 +portmap_6=5:10 +portmap_7=8:10 +portmap_8=7:10 +portmap_9=10:10 +portmap_10=9:10 +portmap_11=12:10 +portmap_12=11:10 +# FC-05 +portmap_13=22:10 +portmap_14=21:10 +portmap_15=24:10 +portmap_16=23:10 + +## FalconCore[8, 9, 10, 12, 13] +portmap_34=34:10 +portmap_35=33:10 +portmap_36=36:10 +portmap_37=35:10 +portmap_38=38:10 +portmap_39=37:10 +portmap_40=40:10 +portmap_41=39:10 +portmap_42=42:10 +portmap_43=41:10 +portmap_44=44:10 +portmap_45=43:10 +# FC-12 & FC-13 +portmap_46=50:10 +portmap_47=49:10 +portmap_48=52:10 +portmap_49=51:10 +portmap_50=54:10 +portmap_51=53:10 +portmap_52=56:10 +portmap_53=55:10 + +## FalconCore[16, 17, 20] +portmap_68=66:10 +portmap_69=65:10 +portmap_70=68:10 +portmap_71=67:10 +portmap_72=70:10 +portmap_73=69:10 +portmap_74=72:10 +portmap_75=71:10 +# FC-20 +portmap_76=82:10 +portmap_77=81:10 +portmap_78=84:10 +portmap_79=83:10 + +# FC-21 (100G) +portmap_80=85:100 + +## FalconCore[24, 25, 26, 27, 29] (100G) +portmap_102=97:100 +portmap_103=105:100 +portmap_104=101:100 +portmap_105=117:100 +portmap_107=109:100 + + + +# FalconCore[0,1,2,5] ports TX polarity flip for 25G +# no polarity reversal + +# FalconCore[8, 9, 10, 12, 13] ports TX polarity flip for 25G +# For Baidu xe20 & xe22; for GA xe21 & xe23 +phy_xaui_tx_polarity_flip_xe20=1 +phy_xaui_tx_polarity_flip_xe22=1 + +# FalconCore[16, 17, 20] ports TX polarity flip for 25G +# no polarity reversal + +# FC-21 for 100G + +# FalconCore[24, 25, 26, 27, 29] ports TX polarity flip for 100G +phy_xaui_tx_polarity_flip_ce1=0xf +phy_xaui_tx_polarity_flip_ce2=0xf + + +# FalconCore[0,1,2,5] ports RX polarity flip for 25G +# no polarity reversal + +# FalconCore[8, 9, 10, 12, 13] ports RX polarity flip for 25G +# no polarity reversal + +# FalconCore[16, 17, 20] ports RX polarity flip for 25G +# no polarity reversal + +# FC-21 for 100G + +# FalconCore[24, 25, 26, 27, 29] ports RX polarity flip for 100G +phy_xaui_rx_polarity_flip_ce2=0xf + + +## Lane swapping +## The HEX value is connection of red line within Falconcore in "Fig 3-4 SFP28 port connection" +# TX - Config A. (FC 0/1/2/16) +# 0x3210 - port 0-11, 36-39 +xgxs_tx_lane_map_xe0=0x3210 +xgxs_tx_lane_map_xe1=0x3210 +xgxs_tx_lane_map_xe2=0x3210 +xgxs_tx_lane_map_xe3=0x3210 +xgxs_tx_lane_map_xe4=0x3210 +xgxs_tx_lane_map_xe5=0x3210 +xgxs_tx_lane_map_xe6=0x3210 +xgxs_tx_lane_map_xe7=0x3210 +xgxs_tx_lane_map_xe8=0x3210 +xgxs_tx_lane_map_xe9=0x3210 +xgxs_tx_lane_map_xe10=0x3210 +xgxs_tx_lane_map_xe11=0x3210 +xgxs_tx_lane_map_xe37=0x3210 +xgxs_tx_lane_map_xe38=0x3210 +xgxs_tx_lane_map_xe39=0x3210 +xgxs_tx_lane_map_xe40=0x3210 + + +# TX - Config B. (FC 5/9/20) +# 0x0123 - port 12-13, 20-23, 44-47 +xgxs_tx_lane_map_xe12=0x0123 +xgxs_tx_lane_map_xe13=0x0123 +xgxs_tx_lane_map_xe14=0x0123 +xgxs_tx_lane_map_xe15=0x0123 +xgxs_tx_lane_map_xe20=0x0123 +xgxs_tx_lane_map_xe21=0x0123 +xgxs_tx_lane_map_xe22=0x0123 +xgxs_tx_lane_map_xe23=0x0123 +xgxs_tx_lane_map_xe45=0x0123 +xgxs_tx_lane_map_xe46=0x0123 +xgxs_tx_lane_map_xe47=0x0123 +xgxs_tx_lane_map_xe48=0x0123 + + +# TX - Config C. (FC 8/10) +# 0x3210 - port 16-19, 24-27 +xgxs_tx_lane_map_xe16=0x3210 +xgxs_tx_lane_map_xe17=0x3210 +xgxs_tx_lane_map_xe18=0x3210 +xgxs_tx_lane_map_xe19=0x3210 +xgxs_tx_lane_map_xe24=0x3210 +xgxs_tx_lane_map_xe25=0x3210 +xgxs_tx_lane_map_xe26=0x3210 +xgxs_tx_lane_map_xe27=0x3210 + + +# TX - Config D. (FC 12/13/17) +# 0x0123 - port 28-35, 40-43 +xgxs_tx_lane_map_xe28=0x0123 +xgxs_tx_lane_map_xe29=0x0123 +xgxs_tx_lane_map_xe30=0x0123 +xgxs_tx_lane_map_xe31=0x0123 +xgxs_tx_lane_map_xe32=0x0123 +xgxs_tx_lane_map_xe33=0x0123 +xgxs_tx_lane_map_xe34=0x0123 +xgxs_tx_lane_map_xe35=0x0123 +xgxs_tx_lane_map_xe41=0x0123 +xgxs_tx_lane_map_xe42=0x0123 +xgxs_tx_lane_map_xe43=0x0123 +xgxs_tx_lane_map_xe44=0x0123 + + + + +# RX - Config A. (FC 0/1/2/16) +# 0x1032 - port 0-11, 36-39 +xgxs_rx_lane_map_xe0=0x1032 +xgxs_rx_lane_map_xe1=0x1032 +xgxs_rx_lane_map_xe2=0x1032 +xgxs_rx_lane_map_xe3=0x1032 +xgxs_rx_lane_map_xe4=0x1032 +xgxs_rx_lane_map_xe5=0x1032 +xgxs_rx_lane_map_xe6=0x1032 +xgxs_rx_lane_map_xe7=0x1032 +xgxs_rx_lane_map_xe8=0x1032 +xgxs_rx_lane_map_xe9=0x1032 +xgxs_rx_lane_map_xe10=0x1032 +xgxs_rx_lane_map_xe11=0x1032 +xgxs_rx_lane_map_xe37=0x1032 +xgxs_rx_lane_map_xe38=0x1032 +xgxs_rx_lane_map_xe39=0x1032 +xgxs_rx_lane_map_xe40=0x1032 + + + +# RX - Config B. (FC 5/9/20) +# 0x1032 - port 12-13, 20-23, 44-47 +xgxs_rx_lane_map_xe12=0x1032 +xgxs_rx_lane_map_xe13=0x1032 +xgxs_rx_lane_map_xe14=0x1032 +xgxs_rx_lane_map_xe15=0x1032 +xgxs_rx_lane_map_xe20=0x1032 +xgxs_rx_lane_map_xe21=0x1032 +xgxs_rx_lane_map_xe22=0x1032 +xgxs_rx_lane_map_xe23=0x1032 +xgxs_rx_lane_map_xe45=0x1032 +xgxs_rx_lane_map_xe46=0x1032 +xgxs_rx_lane_map_xe47=0x1032 +xgxs_rx_lane_map_xe48=0x1032 + + +# RX - Config C. (FC 8/10) +# 0x3210 - port 16-19, 24-27 +xgxs_rx_lane_map_xe16=0x3210 +xgxs_rx_lane_map_xe17=0x3210 +xgxs_rx_lane_map_xe18=0x3210 +xgxs_rx_lane_map_xe19=0x3210 +xgxs_rx_lane_map_xe24=0x3210 +xgxs_rx_lane_map_xe25=0x3210 +xgxs_rx_lane_map_xe26=0x3210 +xgxs_rx_lane_map_xe27=0x3210 + + +# RX - Config D. (FC 12/13/17) +# 0x3210 - port 28-35, 40-43 +xgxs_rx_lane_map_xe28=0x3210 +xgxs_rx_lane_map_xe29=0x3210 +xgxs_rx_lane_map_xe30=0x3210 +xgxs_rx_lane_map_xe31=0x3210 +xgxs_rx_lane_map_xe32=0x3210 +xgxs_rx_lane_map_xe33=0x3210 +xgxs_rx_lane_map_xe34=0x3210 +xgxs_rx_lane_map_xe35=0x3210 +xgxs_rx_lane_map_xe41=0x3210 +xgxs_rx_lane_map_xe42=0x3210 +xgxs_rx_lane_map_xe43=0x3210 +xgxs_rx_lane_map_xe44=0x3210 + + +## Lane swapping for QSFP28 (100G) +## The HEX value is connection of red line within Falconcore in "Fig 3-4 SFP28 port connection" +# TX - Config A. (FC 21/25) +# 0x3210 - port ce0, ce3 +xgxs_tx_lane_map_ce0=0x3210 +xgxs_tx_lane_map_ce3=0x3210 + + +# TX - Config B. (FC 24) +# 0x3210 - port ce1 +xgxs_tx_lane_map_ce1=0x3210 + + +# TX - Config C. (FC 26) +# 0x3210 - port ce2 +xgxs_tx_lane_map_ce2=0x3210 + + +# TX - Config D. (FC 27) +# 0x3210 - ce5 +xgxs_tx_lane_map_ce5=0x3210 + + +# TX - Config E. (FC 29) +# 0x3210 - ce4 +xgxs_tx_lane_map_ce4=0x3210 + + +# RX - Config A. (FC 21/25) +# 0x1032 - port ce0, ce3 +xgxs_rx_lane_map_ce0=0x1032 +xgxs_rx_lane_map_ce3=0x1032 + + +# RX - Config B. (FC 24) +# 0x1032 - port ce1 +xgxs_rx_lane_map_ce1=0x1032 + + +# RX - Config C. (FC 26) +# 0x2301 - port ce2 +xgxs_rx_lane_map_ce2=0x2301 + + +# RX - Config D. (FC 27) +# 0x2301 - ce5 +xgxs_rx_lane_map_ce5=0x2301 + + +# TX - Config E. (FC 29) +# 0x3210 - ce4 +xgxs_rx_lane_map_ce4=0x3210 + +# EQ/iDriver + +# The 1st 16 ports, xe0-xe15 +serdes_preemphasis_1=0x1A5600 +serdes_preemphasis_2=0x1A5600 +serdes_preemphasis_3=0x1A5600 +serdes_preemphasis_4=0x1A5600 +serdes_preemphasis_5=0x1A5600 +serdes_preemphasis_6=0x1A5600 +serdes_preemphasis_7=0x185800 +serdes_preemphasis_8=0x1A5600 +serdes_preemphasis_9=0x185800 +serdes_preemphasis_10=0x185800 +serdes_preemphasis_11=0x165A00 +serdes_preemphasis_12=0x185800 +serdes_preemphasis_13=0x105F01 +serdes_preemphasis_14=0x165A00 +serdes_preemphasis_15=0x105F01 +serdes_preemphasis_16=0x105F01 + +serdes_driver_current_1=0x000001 +serdes_driver_current_2=0x000001 +serdes_driver_current_3=0x000001 +serdes_driver_current_4=0x000001 +serdes_driver_current_5=0x000001 +serdes_driver_current_6=0x000001 +serdes_driver_current_7=0x000001 +serdes_driver_current_8=0x000001 +serdes_driver_current_9=0x000000 +serdes_driver_current_10=0x000001 +serdes_driver_current_11=0x000000 +serdes_driver_current_12=0x000000 +serdes_driver_current_13=0x000000 +serdes_driver_current_14=0x000000 +serdes_driver_current_15=0x000000 +serdes_driver_current_16=0x000000 + +# The 2nd 20 ports, xe16-xe35 +serdes_preemphasis_34=0x105F01 +serdes_preemphasis_35=0x105F01 +serdes_preemphasis_36=0x0E6002 +serdes_preemphasis_37=0x0E6002 +serdes_preemphasis_38=0x0E6002 +serdes_preemphasis_39=0x0E6002 +serdes_preemphasis_40=0x125B03 +serdes_preemphasis_41=0x0E6002 +serdes_preemphasis_42=0x125B03 +serdes_preemphasis_43=0x125B03 +serdes_preemphasis_44=0x125B03 +serdes_preemphasis_45=0x125B03 +serdes_preemphasis_46=0x125B03 +serdes_preemphasis_47=0x125B03 +serdes_preemphasis_48=0x125B03 +serdes_preemphasis_49=0x125B03 +serdes_preemphasis_50=0x125B03 +serdes_preemphasis_51=0x125B03 +serdes_preemphasis_52=0x125B03 +serdes_preemphasis_53=0x125B03 + +serdes_driver_current_34=0x000000 +serdes_driver_current_35=0x000000 +serdes_driver_current_36=0x000000 +serdes_driver_current_37=0x000000 +serdes_driver_current_38=0x000000 +serdes_driver_current_39=0x000000 +serdes_driver_current_40=0x000000 +serdes_driver_current_41=0x000000 +serdes_driver_current_42=0x000000 +serdes_driver_current_43=0x000000 +serdes_driver_current_44=0x000000 +serdes_driver_current_45=0x000000 +serdes_driver_current_46=0x000000 +serdes_driver_current_47=0x000000 +serdes_driver_current_48=0x000000 +serdes_driver_current_49=0x000000 +serdes_driver_current_50=0x000000 +serdes_driver_current_51=0x000000 +serdes_driver_current_52=0x000000 +serdes_driver_current_53=0x000000 + +# The 3rd 12 ports, xe36-xe47 +serdes_preemphasis_68=0x125B03 +serdes_preemphasis_69=0x125B03 +serdes_preemphasis_70=0x125B03 +serdes_preemphasis_71=0x125B03 +serdes_preemphasis_72=0x125B03 +serdes_preemphasis_73=0x125B03 +serdes_preemphasis_74=0x125B03 +serdes_preemphasis_75=0x125B03 +serdes_preemphasis_76=0x105F01 +serdes_preemphasis_77=0x105F01 +serdes_preemphasis_78=0x105F01 +serdes_preemphasis_79=0x105F01 + +serdes_driver_current_68=0x000000 +serdes_driver_current_69=0x000000 +serdes_driver_current_70=0x000000 +serdes_driver_current_71=0x000000 +serdes_driver_current_72=0x000000 +serdes_driver_current_73=0x000000 +serdes_driver_current_74=0x000000 +serdes_driver_current_75=0x000000 +serdes_driver_current_76=0x000000 +serdes_driver_current_77=0x000000 +serdes_driver_current_78=0x000000 +serdes_driver_current_79=0x000000 + +# 6 x 100G ports, expandable to 24 x 25G ports +serdes_preemphasis_80=0x2D4300 +serdes_preemphasis_81=0x2D4300 +serdes_preemphasis_82=0x2D4300 +serdes_preemphasis_83=0x2D4300 + +serdes_preemphasis_102=0x304000 +serdes_preemphasis_103=0x304000 +serdes_preemphasis_104=0x304000 +serdes_preemphasis_105=0x304000 + +serdes_preemphasis_106=0x304000 +serdes_preemphasis_107=0x304000 +serdes_preemphasis_108=0x304000 +serdes_preemphasis_109=0x304000 + +serdes_preemphasis_110=0x304000 +serdes_preemphasis_111=0x304000 +serdes_preemphasis_112=0x304000 +serdes_preemphasis_113=0x304000 + +serdes_preemphasis_114=0x2E360C +serdes_preemphasis_115=0x2E360C +serdes_preemphasis_116=0x2E360C +serdes_preemphasis_117=0x2E360C + +serdes_preemphasis_118=0x2E360C +serdes_preemphasis_119=0x2E360C +serdes_preemphasis_120=0x2E360C +serdes_preemphasis_121=0x2E360C diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/th-d7054q28b-48x25g-6x100g.config.bcm b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/th-d7054q28b-48x25g-6x100g.config.bcm new file mode 100644 index 000000000000..ff09305ccbff --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/th-d7054q28b-48x25g-6x100g.config.bcm @@ -0,0 +1,414 @@ +# Cypress BCM Shell config / 25G * 48 ports; 100G * 6 ports + +# Define default OS / SAL +os=unix + +l2_mem_entries=40960 +l3_mem_entries=40960 +fpem_mem_entries=32768 +l2xmsg_mode=1 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 + +## update the hex string based on case ID: 925941 +## 1. type "phy info" then get each hg ports' number +## 2. Set these number as 1 in pbmp_xport_xe and pbmp_oversubscribe +## 130 xe ports, 4 * 32 + 2 +## no more pbmp_oversubscribe +oversubscribe_mode=1 +pbmp_xport_xe=0x3fffffffdffffffff7fffffffdfffffffe + + +# EagleCore ports: 36 & 49 +portmap_66=129:10 +portmap_100=131:10 + +# Loopback ports +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +# First 12*4 48 ports config for 25G +# Second 6 ports config for 100G +# For Tomahawk FalconCore: +# Physical ports in FalconCore[0 - 7] must map to logical port[1 - 32] at any order +# Physical ports in FalconCore[8 - 15] must map to logical port[34 - 65] at any order +# Physical ports in FalconCore[16 - 23] must map to logical port[68 - 99] at any order +# Physical ports in FalconCore[24 - 31] must map to logical port[102 - 133] at any order + +## FalconCore[0,1,2,5] +portmap_1=2:25 +portmap_2=1:25 +portmap_3=4:25 +portmap_4=3:25 +portmap_5=6:25 +portmap_6=5:25 +portmap_7=8:25 +portmap_8=7:25 +portmap_9=10:25 +portmap_10=9:25 +portmap_11=12:25 +portmap_12=11:25 +# FC-05 +portmap_13=22:25 +portmap_14=21:25 +portmap_15=24:25 +portmap_16=23:25 + +## FalconCore[8, 9, 10, 12, 13] +portmap_34=34:25 +portmap_35=33:25 +portmap_36=36:25 +portmap_37=35:25 +portmap_38=38:25 +portmap_39=37:25 +portmap_40=40:25 +portmap_41=39:25 +portmap_42=42:25 +portmap_43=41:25 +portmap_44=44:25 +portmap_45=43:25 +# FC-12 & FC-13 +portmap_46=50:25 +portmap_47=49:25 +portmap_48=52:25 +portmap_49=51:25 +portmap_50=54:25 +portmap_51=53:25 +portmap_52=56:25 +portmap_53=55:25 + +## FalconCore[16, 17, 20] +portmap_68=66:25 +portmap_69=65:25 +portmap_70=68:25 +portmap_71=67:25 +portmap_72=70:25 +portmap_73=69:25 +portmap_74=72:25 +portmap_75=71:25 +# FC-20 +portmap_76=82:25 +portmap_77=81:25 +portmap_78=84:25 +portmap_79=83:25 + +# FC-21 (100G) +portmap_80=85:100 + +## FalconCore[24, 25, 26, 27, 29] (100G) +portmap_102=97:100 +portmap_103=105:100 +portmap_104=101:100 +portmap_105=117:100 +portmap_107=109:100 + + + +# FalconCore[0,1,2,5] ports TX polarity flip for 25G +# no polarity reversal + +# FalconCore[8, 9, 10, 12, 13] ports TX polarity flip for 25G +# For Baidu xe20 & xe22; for GA xe21 & xe23 +phy_xaui_tx_polarity_flip_xe20=1 +phy_xaui_tx_polarity_flip_xe22=1 + +# FalconCore[16, 17, 20] ports TX polarity flip for 25G +# no polarity reversal + +# FC-21 for 100G + +# FalconCore[24, 25, 26, 27, 29] ports TX polarity flip for 100G +phy_xaui_tx_polarity_flip_ce1=0xf +phy_xaui_tx_polarity_flip_ce2=0xf + + +# FalconCore[0,1,2,5] ports RX polarity flip for 25G +# no polarity reversal + +# FalconCore[8, 9, 10, 12, 13] ports RX polarity flip for 25G +# no polarity reversal + +# FalconCore[16, 17, 20] ports RX polarity flip for 25G +# no polarity reversal + +# FC-21 for 100G + +# FalconCore[24, 25, 26, 27, 29] ports RX polarity flip for 100G +phy_xaui_rx_polarity_flip_ce2=0xf + + +## Lane swapping +## The HEX value is connection of red line within Falconcore in "Fig 3-4 SFP28 port connection" +# TX - Config A. (FC 0/1/2/16) +# 0x3210 - port 0-11, 36-39 +xgxs_tx_lane_map_xe0=0x3210 +xgxs_tx_lane_map_xe1=0x3210 +xgxs_tx_lane_map_xe2=0x3210 +xgxs_tx_lane_map_xe3=0x3210 +xgxs_tx_lane_map_xe4=0x3210 +xgxs_tx_lane_map_xe5=0x3210 +xgxs_tx_lane_map_xe6=0x3210 +xgxs_tx_lane_map_xe7=0x3210 +xgxs_tx_lane_map_xe8=0x3210 +xgxs_tx_lane_map_xe9=0x3210 +xgxs_tx_lane_map_xe10=0x3210 +xgxs_tx_lane_map_xe11=0x3210 +xgxs_tx_lane_map_xe37=0x3210 +xgxs_tx_lane_map_xe38=0x3210 +xgxs_tx_lane_map_xe39=0x3210 +xgxs_tx_lane_map_xe40=0x3210 + + +# TX - Config B. (FC 5/9/20) +# 0x0123 - port 12-13, 20-23, 44-47 +xgxs_tx_lane_map_xe12=0x0123 +xgxs_tx_lane_map_xe13=0x0123 +xgxs_tx_lane_map_xe14=0x0123 +xgxs_tx_lane_map_xe15=0x0123 +xgxs_tx_lane_map_xe20=0x0123 +xgxs_tx_lane_map_xe21=0x0123 +xgxs_tx_lane_map_xe22=0x0123 +xgxs_tx_lane_map_xe23=0x0123 +xgxs_tx_lane_map_xe45=0x0123 +xgxs_tx_lane_map_xe46=0x0123 +xgxs_tx_lane_map_xe47=0x0123 +xgxs_tx_lane_map_xe48=0x0123 + + +# TX - Config C. (FC 8/10) +# 0x3210 - port 16-19, 24-27 +xgxs_tx_lane_map_xe16=0x3210 +xgxs_tx_lane_map_xe17=0x3210 +xgxs_tx_lane_map_xe18=0x3210 +xgxs_tx_lane_map_xe19=0x3210 +xgxs_tx_lane_map_xe24=0x3210 +xgxs_tx_lane_map_xe25=0x3210 +xgxs_tx_lane_map_xe26=0x3210 +xgxs_tx_lane_map_xe27=0x3210 + + +# TX - Config D. (FC 12/13/17) +# 0x0123 - port 28-35, 40-43 +xgxs_tx_lane_map_xe28=0x0123 +xgxs_tx_lane_map_xe29=0x0123 +xgxs_tx_lane_map_xe30=0x0123 +xgxs_tx_lane_map_xe31=0x0123 +xgxs_tx_lane_map_xe32=0x0123 +xgxs_tx_lane_map_xe33=0x0123 +xgxs_tx_lane_map_xe34=0x0123 +xgxs_tx_lane_map_xe35=0x0123 +xgxs_tx_lane_map_xe41=0x0123 +xgxs_tx_lane_map_xe42=0x0123 +xgxs_tx_lane_map_xe43=0x0123 +xgxs_tx_lane_map_xe44=0x0123 + + + + +# RX - Config A. (FC 0/1/2/16) +# 0x1032 - port 0-11, 36-39 +xgxs_rx_lane_map_xe0=0x1032 +xgxs_rx_lane_map_xe1=0x1032 +xgxs_rx_lane_map_xe2=0x1032 +xgxs_rx_lane_map_xe3=0x1032 +xgxs_rx_lane_map_xe4=0x1032 +xgxs_rx_lane_map_xe5=0x1032 +xgxs_rx_lane_map_xe6=0x1032 +xgxs_rx_lane_map_xe7=0x1032 +xgxs_rx_lane_map_xe8=0x1032 +xgxs_rx_lane_map_xe9=0x1032 +xgxs_rx_lane_map_xe10=0x1032 +xgxs_rx_lane_map_xe11=0x1032 +xgxs_rx_lane_map_xe37=0x1032 +xgxs_rx_lane_map_xe38=0x1032 +xgxs_rx_lane_map_xe39=0x1032 +xgxs_rx_lane_map_xe40=0x1032 + + + +# RX - Config B. (FC 5/9/20) +# 0x1032 - port 12-13, 20-23, 44-47 +xgxs_rx_lane_map_xe12=0x1032 +xgxs_rx_lane_map_xe13=0x1032 +xgxs_rx_lane_map_xe14=0x1032 +xgxs_rx_lane_map_xe15=0x1032 +xgxs_rx_lane_map_xe20=0x1032 +xgxs_rx_lane_map_xe21=0x1032 +xgxs_rx_lane_map_xe22=0x1032 +xgxs_rx_lane_map_xe23=0x1032 +xgxs_rx_lane_map_xe45=0x1032 +xgxs_rx_lane_map_xe46=0x1032 +xgxs_rx_lane_map_xe47=0x1032 +xgxs_rx_lane_map_xe48=0x1032 + + +# RX - Config C. (FC 8/10) +# 0x3210 - port 16-19, 24-27 +xgxs_rx_lane_map_xe16=0x3210 +xgxs_rx_lane_map_xe17=0x3210 +xgxs_rx_lane_map_xe18=0x3210 +xgxs_rx_lane_map_xe19=0x3210 +xgxs_rx_lane_map_xe24=0x3210 +xgxs_rx_lane_map_xe25=0x3210 +xgxs_rx_lane_map_xe26=0x3210 +xgxs_rx_lane_map_xe27=0x3210 + + +# RX - Config D. (FC 12/13/17) +# 0x3210 - port 28-35, 40-43 +xgxs_rx_lane_map_xe28=0x3210 +xgxs_rx_lane_map_xe29=0x3210 +xgxs_rx_lane_map_xe30=0x3210 +xgxs_rx_lane_map_xe31=0x3210 +xgxs_rx_lane_map_xe32=0x3210 +xgxs_rx_lane_map_xe33=0x3210 +xgxs_rx_lane_map_xe34=0x3210 +xgxs_rx_lane_map_xe35=0x3210 +xgxs_rx_lane_map_xe41=0x3210 +xgxs_rx_lane_map_xe42=0x3210 +xgxs_rx_lane_map_xe43=0x3210 +xgxs_rx_lane_map_xe44=0x3210 + + +## Lane swapping for QSFP28 (100G) +## The HEX value is connection of red line within Falconcore in "Fig 3-4 SFP28 port connection" +# TX - Config A. (FC 21/25) +# 0x3210 - port ce0, ce3 +xgxs_tx_lane_map_ce0=0x3210 +xgxs_tx_lane_map_ce3=0x3210 + + +# TX - Config B. (FC 24) +# 0x3210 - port ce1 +xgxs_tx_lane_map_ce1=0x3210 + + +# TX - Config C. (FC 26) +# 0x3210 - port ce2 +xgxs_tx_lane_map_ce2=0x3210 + + +# TX - Config D. (FC 27) +# 0x3210 - ce5 +xgxs_tx_lane_map_ce5=0x3210 + + +# TX - Config E. (FC 29) +# 0x3210 - ce4 +xgxs_tx_lane_map_ce4=0x3210 + + +# RX - Config A. (FC 21/25) +# 0x1032 - port ce0, ce3 +xgxs_rx_lane_map_ce0=0x1032 +xgxs_rx_lane_map_ce3=0x1032 + + +# RX - Config B. (FC 24) +# 0x1032 - port ce1 +xgxs_rx_lane_map_ce1=0x1032 + + +# RX - Config C. (FC 26) +# 0x2301 - port ce2 +xgxs_rx_lane_map_ce2=0x2301 + + +# RX - Config D. (FC 27) +# 0x2301 - ce5 +xgxs_rx_lane_map_ce5=0x2301 + + +# TX - Config E. (FC 29) +# 0x3210 - ce4 +xgxs_rx_lane_map_ce4=0x3210 + +# EQ/iDriver + +# The first 16 ports, xe0-xe15 +serdes_preemphasis_1=0x2E380A +serdes_preemphasis_2=0x2E380A +serdes_preemphasis_3=0x2E380A +serdes_preemphasis_4=0x2E380A +serdes_preemphasis_5=0x2C3A0A +serdes_preemphasis_6=0x2C3A0A +serdes_preemphasis_7=0x2C3A0A +serdes_preemphasis_8=0x2C3A0A +serdes_preemphasis_9=0x323E00 +serdes_preemphasis_10=0x323E00 +serdes_preemphasis_11=0x304000 +serdes_preemphasis_12=0x304000 +serdes_preemphasis_13=0x2D4300 +serdes_preemphasis_14=0x304000 +serdes_preemphasis_15=0x2D4300 +serdes_preemphasis_16=0x2D4300 + +# The 2nd 20 ports, xe16-xe35 +serdes_preemphasis_34=0x2D4300 +serdes_preemphasis_35=0x2D4300 +serdes_preemphasis_36=0x2B4500 +serdes_preemphasis_37=0x2B4500 +serdes_preemphasis_38=0x2B4500 +serdes_preemphasis_39=0x2B4500 +serdes_preemphasis_40=0x2B4500 +serdes_preemphasis_41=0x2B4500 +serdes_preemphasis_42=0x2B4500 +serdes_preemphasis_43=0x2B4500 +serdes_preemphasis_44=0x284800 +serdes_preemphasis_45=0x284800 +serdes_preemphasis_46=0x284800 +serdes_preemphasis_47=0x284800 +serdes_preemphasis_48=0x284800 +serdes_preemphasis_49=0x284800 +serdes_preemphasis_50=0x2B4500 +serdes_preemphasis_51=0x2B4500 +serdes_preemphasis_52=0x284800 +serdes_preemphasis_53=0x284800 + +# The 3rd 12 ports, xe36-xe47 +serdes_preemphasis_68=0x284800 +serdes_preemphasis_69=0x2A4600 +serdes_preemphasis_70=0x2B4500 +serdes_preemphasis_71=0x2A4600 +serdes_preemphasis_72=0x2A4600 +serdes_preemphasis_73=0x2B4500 +serdes_preemphasis_74=0x2B4500 +serdes_preemphasis_75=0x2A4600 +serdes_preemphasis_76=0x2B4500 +serdes_preemphasis_77=0x2B4500 +serdes_preemphasis_78=0x2B4500 +serdes_preemphasis_79=0x2B4500 + +# 6 x 100G ports, expandable to 24 x 25G ports +serdes_preemphasis_80=0x2D4300 +serdes_preemphasis_81=0x2D4300 +serdes_preemphasis_82=0x2D4300 +serdes_preemphasis_83=0x2D4300 + +serdes_preemphasis_102=0x304000 +serdes_preemphasis_103=0x304000 +serdes_preemphasis_104=0x304000 +serdes_preemphasis_105=0x304000 + +serdes_preemphasis_106=0x304000 +serdes_preemphasis_107=0x304000 +serdes_preemphasis_108=0x304000 +serdes_preemphasis_109=0x304000 + +serdes_preemphasis_110=0x304000 +serdes_preemphasis_111=0x304000 +serdes_preemphasis_112=0x304000 +serdes_preemphasis_113=0x304000 + +serdes_preemphasis_114=0x2E360C +serdes_preemphasis_115=0x2E360C +serdes_preemphasis_116=0x2E360C +serdes_preemphasis_117=0x2E360C + +serdes_preemphasis_118=0x2E360C +serdes_preemphasis_119=0x2E360C +serdes_preemphasis_120=0x2E360C +serdes_preemphasis_121=0x2E360C diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/default_sku b/device/inventec/x86_64-inventec_d7054q28b-r0/default_sku new file mode 100644 index 000000000000..3b1520a5e174 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/default_sku @@ -0,0 +1 @@ +INVENTEC-D7054Q28B-S48-Q6 t1 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/led_proc_init.soc b/device/inventec/x86_64-inventec_d7054q28b-r0/led_proc_init.soc new file mode 100644 index 000000000000..ceaa9a8e6d5d --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/led_proc_init.soc @@ -0,0 +1,200 @@ +#LED processor initialization for Inventec d7054q28b platform + +led 0 stop +led 0 prog 02 00 60 F1 12 00 DA 0F 70 10 67 61 67 5C 77 06 02 A0 60 F0 02 00 60 F2 12 00 06 F0 4A 01 71 38 4A 02 27 67 5C 06 F2 28 32 08 67 5C 06 F2 28 32 00 32 01 B7 67 5C 77 44 67 64 67 5C 67 64 67 5C 67 61 67 5C DA 6C 70 4E 86 F0 86 F2 77 1A 12 00 DA 03 70 5A 67 64 67 5C 77 50 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=14 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=13 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=10 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=9 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=6 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=5 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=2 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=1 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=30 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=29 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=34 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=33 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=22 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=21 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=26 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=25 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=18 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=17 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=16 +led 0 start + +led 1 stop +led 1 prog 02 00 60 F1 12 00 DA 0F 70 10 67 61 67 5C 77 06 02 A0 60 F0 02 00 60 F2 12 00 06 F0 4A 01 71 38 4A 02 27 67 5C 06 F2 28 32 08 67 5C 06 F2 28 32 00 32 01 B7 67 5C 77 44 67 64 67 5C 67 64 67 5C 67 61 67 5C DA 6C 70 4E 86 F0 86 F2 77 1A 12 00 DA 03 70 5A 67 64 67 5C 77 50 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=2 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=1 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=6 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=5 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=10 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=9 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=14 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=13 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=18 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=17 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=22 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=21 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=26 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=25 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=30 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=29 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=34 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=33 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=63 +led 1 start + +# Set per port speed config of LED Color register +# For Invnetec Cypress platform, +# If we want to set 10G speed per port, We need to set amber color light, so use cmd "setreg CMIC_LEDUP0_DATA_RAM(160) 0x04". +# If we want to set 25G ( or up ) speed per port, we need to set green color light, so use cmd "setreg CMIC_LEDUP0_DATA_RAM(160) 0x00". + +setreg CMIC_LEDUP0_DATA_RAM(160) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(161) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(162) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(163) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(164) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(165) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(166) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(167) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(168) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(169) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(170) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(171) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(172) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(173) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(174) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(175) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(176) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(177) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(178) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(179) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(180) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(181) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(182) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(183) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(184) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(185) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(186) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(187) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(188) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(189) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(190) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(191) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(192) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(193) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(194) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(195) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(196) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(197) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(198) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(199) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(200) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(201) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(202) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(203) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(204) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(205) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(206) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(207) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(208) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(209) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(210) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(211) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(212) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(213) 0x00 + +age 150 + 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/psuutil.py b/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/psuutil.py new file mode 100644 index 000000000000..4bd3f7a27052 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/psuutil.py @@ -0,0 +1,84 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_DIR = "/sys/bus/i2c/devices/0-0066" + + def __init__(self): + PsuBase.__init__(self) + +# Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + attr_file = 'psoc_psu'+ str(index) + '_iout' + attr_path = self.PSU_DIR +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU status + if (attr_value != 0): + status = 1 + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_absent = 0 + ind = index-1 + attr_file ='psu'+ str(ind) + attr_path = self.PSU_DIR +'/' + attr_file + normal_attr_value = '0 : normal' + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU presence + if (attr_value == normal_attr_value): + status = 1 + return status 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..5dffdd0335b0 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/sfputil.py @@ -0,0 +1,217 @@ +# 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 + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/sensors.conf b/device/inventec/x86_64-inventec_d7054q28b-r0/sensors.conf new file mode 100644 index 000000000000..b3fd61236c9e --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/sensors.conf @@ -0,0 +1,44 @@ +# libsensors configuration file +chip "inv_psoc-*" + label temp1 "FrontSide Temperature" + label temp2 "FanBoard Temperature" + label temp3 "NearASIC Temperature" + label temp4 "NearPSU Temperature" + label temp5 "CPU Board Temperature" + label temp6 "ASIC Temperature" + label temp7 "PSU1 Temperature1" + label temp8 "PSU2 Temperature1" + label temp9 "PSU1 Temperature2" + label temp10 "PSU2 Temperature2" + label fan1 "FanModule1 Front RPM" + label fan2 "FanModule1 Rear RPM" + label fan3 "FanModule2 Front RPM" + label fan4 "FanModule2 Rear RPM" + label fan5 "FanModule3 Front RPM" + label fan6 "FanModule3 Rear RPM" + label fan7 "FanModule4 Front RPM" + label fan8 "FanModule4 Rear RPM" + label fan9 "FanModule5 Front RPM" + label fan10 "FanModule5 Rear RPM" + label pwm1 "FanModule1 PWM" + label pwm2 "FanModule2 PWM" + label pwm3 "FanModule3 PWM" + label pwm4 "FanModule4 PWM" + label pwm5 "FanModule5 PWM" + label pwm6 "PSU1 FAN PWM" + label pwm7 "PSU2 FAN PWM" + label fan11 "PSU1 FAN RPM" + label fan12 "PSU2 FAN RPM" + label in1 "PSU1 Input Voltage" + label in2 "PSU2 Input Voltage" + label curr1 "PSU1 Input Current" + label curr2 "PSU2 Input Current" + label power1 "PSU1 Input Power" + label power2 "PSU2 Input Power" + label in3 "PSU1 Output Voltage" + label in4 "PSU2 Output Voltage" + label curr3 "PSU1 Output Current" + label curr4 "PSU2 Output Current" + label power3 "PSU1 Output Power" + label power4 "PSU2 Output Power" + diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/port_config.ini b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/port_config.ini new file mode 100644 index 000000000000..3fc6db4c8198 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias +Ethernet0 9,10,11,12 Ethernet0 +Ethernet4 1,2,3,4 Ethernet4 +Ethernet8 25,26,27,28 Ethernet8 +Ethernet12 17,18,19,20 Ethernet12 +Ethernet16 41,42,43,44 Ethernet16 +Ethernet20 33,34,35,36 Ethernet20 +Ethernet24 57,58,59,60 Ethernet24 +Ethernet28 49,50,51,52 Ethernet28 +Ethernet32 73,74,75,76 Ethernet32 +Ethernet36 65,66,67,68 Ethernet36 +Ethernet40 89,90,91,92 Ethernet40 +Ethernet44 81,82,83,84 Ethernet44 +Ethernet48 105,106,107,108 Ethernet48 +Ethernet52 97,98,99,100 Ethernet52 +Ethernet56 121,122,123,124 Ethernet56 +Ethernet60 113,114,115,116 Ethernet60 +Ethernet64 137,138,139,140 Ethernet64 +Ethernet68 129,130,131,132 Ethernet68 +Ethernet72 153,154,155,156 Ethernet72 +Ethernet76 145,146,147,148 Ethernet76 +Ethernet80 169,170,171,172 Ethernet80 +Ethernet84 161,162,163,164 Ethernet84 +Ethernet88 185,186,187,188 Ethernet88 +Ethernet92 177,178,179,180 Ethernet92 +Ethernet96 201,202,203,204 Ethernet96 +Ethernet100 193,194,195,196 Ethernet100 +Ethernet104 217,218,219,220 Ethernet104 +Ethernet108 209,210,211,212 Ethernet108 +Ethernet112 233,234,235,236 Ethernet112 +Ethernet116 225,226,227,228 Ethernet116 +Ethernet120 249,250,251,252 Ethernet120 +Ethernet124 241,242,243,244 Ethernet124 +Ethernet128 13,14,15,16 Ethernet128 +Ethernet132 5,6,7,8 Ethernet132 +Ethernet136 29,30,31,32 Ethernet136 +Ethernet140 21,22,23,24 Ethernet140 +Ethernet144 45,46,47,48 Ethernet144 +Ethernet148 37,38,39,40 Ethernet148 +Ethernet152 61,62,63,64 Ethernet152 +Ethernet156 53,54,55,56 Ethernet156 +Ethernet160 77,78,79,80 Ethernet160 +Ethernet164 69,70,71,72 Ethernet164 +Ethernet168 93,94,95,96 Ethernet168 +Ethernet172 85,86,87,88 Ethernet172 +Ethernet176 109,110,111,112 Ethernet176 +Ethernet180 101,102,103,104 Ethernet180 +Ethernet184 125,126,127,128 Ethernet184 +Ethernet188 117,118,119,120 Ethernet188 +Ethernet192 141,142,143,144 Ethernet192 +Ethernet196 133,134,135,136 Ethernet196 +Ethernet200 157,158,159,160 Ethernet200 +Ethernet204 149,150,151,152 Ethernet204 +Ethernet208 173,174,175,176 Ethernet208 +Ethernet212 165,166,167,168 Ethernet212 +Ethernet216 189,190,191,192 Ethernet216 +Ethernet220 181,182,183,184 Ethernet220 +Ethernet224 205,206,207,208 Ethernet224 +Ethernet228 197,198,199,200 Ethernet228 +Ethernet232 221,222,223,224 Ethernet232 +Ethernet236 213,214,215,216 Ethernet236 +Ethernet240 237,238,239,240 Ethernet240 +Ethernet244 229,230,231,232 Ethernet244 +Ethernet248 253,254,255,256 Ethernet248 +Ethernet252 245,246,247,248 Ethernet252 diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/sai.profile b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/sai.profile new file mode 100644 index 000000000000..74c0e88255c0 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-d7264q28b-64x100g.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/th2-d7264q28b-64x100g.config.bcm b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/th2-d7264q28b-64x100g.config.bcm new file mode 100644 index 000000000000..a7eaa1d6ac59 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/th2-d7264q28b-64x100g.config.bcm @@ -0,0 +1,910 @@ +# Sequoia BCM Shell config / 100G * 64 ports + +core_clock_frequency=1700 +dpp_clock_ratio=2:3 +load_firmware=1 +# EagleCore ports: xe0 & xe1 +portmap_66=257:10 +portmap_100=259:10 + +# Loopback ports +portmap_33=260:10 +portmap_67=261:10 +portmap_101=262:10 +portmap_135=263:10 + +# 64 ports config for 100G +# For Tomahawk FalconCore: +#Physical ports in FalconCore[0-15] must map to logical port[1-32] at any order +#Physical ports in FalconCore[16-31] must map to logical port[34-65] at any order +#Physical ports in FalconCore[32-47] must map to logical port[68-99] at any order +#Physical ports in FalconCore[48-63] must map to logical port[102-133] at any order + +## FalconCore[0-15] +portmap_1=9:100 +portmap_2=1:100 +portmap_3=13:100 +portmap_4=5:100 +portmap_5=25:100 +portmap_6=17:100 +portmap_7=29:100 +portmap_8=21:100 +portmap_9=41:100 +portmap_10=33:100 +portmap_11=45:100 +portmap_12=37:100 +portmap_13=57:100 +portmap_14=49:100 +portmap_15=61:100 +portmap_16=53:100 + +## FalconCore[16-31] +portmap_34=73:100 +portmap_35=65:100 +portmap_36=77:100 +portmap_37=69:100 +portmap_38=89:100 +portmap_39=81:100 +portmap_40=93:100 +portmap_41=85:100 +portmap_42=105:100 +portmap_43=97:100 +portmap_44=109:100 +portmap_45=101:100 +portmap_46=121:100 +portmap_47=113:100 +portmap_48=125:100 +portmap_49=117:100 + +## FalconCore[32-47] +portmap_68=137:100 +portmap_69=129:100 +portmap_70=141:100 +portmap_71=133:100 +portmap_72=153:100 +portmap_73=145:100 +portmap_74=157:100 +portmap_75=149:100 +portmap_76=169:100 +portmap_77=161:100 +portmap_78=173:100 +portmap_79=165:100 +portmap_80=185:100 +portmap_81=177:100 +portmap_82=189:100 +portmap_83=181:100 + +## FalconCore[48-63] +portmap_102=201:100 +portmap_103=193:100 +portmap_104=205:100 +portmap_105=197:100 +portmap_106=217:100 +portmap_107=209:100 +portmap_108=221:100 +portmap_109=213:100 +portmap_110=233:100 +portmap_111=225:100 +portmap_112=237:100 +portmap_113=229:100 +portmap_114=249:100 +portmap_115=241:100 +portmap_116=253:100 +portmap_117=245:100 + +pbmp_xport_xe=0x3FFFD0000FFFF40003FFFC0001FFFE +oversubscribe_mode=1 +l2_mem_entries=73728 +l3_mem_entries=73728 +fpem_mem_entries=65536 +l2xmsg_mode=1 + +## FalconCore [0-15] port TX Lane Swapping +phy_chain_tx_lane_map_physical{1.0}=0x3201 +phy_chain_tx_lane_map_physical{5.0}=0x3210 +phy_chain_tx_lane_map_physical{9.0}=0x2301 +phy_chain_tx_lane_map_physical{13.0}=0x3210 +phy_chain_tx_lane_map_physical{17.0}=0x3201 +phy_chain_tx_lane_map_physical{21.0}=0x3201 +phy_chain_tx_lane_map_physical{25.0}=0x3201 +phy_chain_tx_lane_map_physical{29.0}=0x3210 +phy_chain_tx_lane_map_physical{33.0}=0x3201 +phy_chain_tx_lane_map_physical{37.0}=0x3210 +phy_chain_tx_lane_map_physical{41.0}=0x3210 +phy_chain_tx_lane_map_physical{45.0}=0x3210 +phy_chain_tx_lane_map_physical{49.0}=0x3201 +phy_chain_tx_lane_map_physical{53.0}=0x3210 +phy_chain_tx_lane_map_physical{57.0}=0x3210 +phy_chain_tx_lane_map_physical{61.0}=0x3210 + + +## FalconCore [16-31] port TX Lane Swapping +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_tx_lane_map_physical{69.0}=0x3201 +phy_chain_tx_lane_map_physical{73.0}=0x3210 +phy_chain_tx_lane_map_physical{77.0}=0x3210 +phy_chain_tx_lane_map_physical{81.0}=0x3210 +phy_chain_tx_lane_map_physical{85.0}=0x3210 +phy_chain_tx_lane_map_physical{89.0}=0x3210 +phy_chain_tx_lane_map_physical{93.0}=0x3210 +phy_chain_tx_lane_map_physical{97.0}=0x3210 +phy_chain_tx_lane_map_physical{101.0}=0x2310 +phy_chain_tx_lane_map_physical{105.0}=0x2310 +phy_chain_tx_lane_map_physical{109.0}=0x3210 +phy_chain_tx_lane_map_physical{113.0}=0x3210 +phy_chain_tx_lane_map_physical{117.0}=0x2310 +phy_chain_tx_lane_map_physical{121.0}=0x2310 +phy_chain_tx_lane_map_physical{125.0}=0x3210 + + +## FalconCore [32-47] port TX Lane Swapping +phy_chain_tx_lane_map_physical{129.0}=0x2301 +phy_chain_tx_lane_map_physical{133.0}=0x3210 +phy_chain_tx_lane_map_physical{137.0}=0x2301 +phy_chain_tx_lane_map_physical{141.0}=0x3210 +phy_chain_tx_lane_map_physical{145.0}=0x2301 +phy_chain_tx_lane_map_physical{149.0}=0x3210 +phy_chain_tx_lane_map_physical{153.0}=0x3210 +phy_chain_tx_lane_map_physical{157.0}=0x3210 +phy_chain_tx_lane_map_physical{161.0}=0x2310 +phy_chain_tx_lane_map_physical{165.0}=0x2310 +phy_chain_tx_lane_map_physical{169.0}=0x2310 +phy_chain_tx_lane_map_physical{173.0}=0x3210 +phy_chain_tx_lane_map_physical{177.0}=0x3210 +phy_chain_tx_lane_map_physical{181.0}=0x2310 +phy_chain_tx_lane_map_physical{185.0}=0x3210 +phy_chain_tx_lane_map_physical{189.0}=0x2310 + + +## FalconCore [48-63] port TX Lane Swapping +phy_chain_tx_lane_map_physical{193.0}=0x2310 +phy_chain_tx_lane_map_physical{197.0}=0x2310 +phy_chain_tx_lane_map_physical{201.0}=0x2310 +phy_chain_tx_lane_map_physical{205.0}=0x2310 +phy_chain_tx_lane_map_physical{209.0}=0x3210 +phy_chain_tx_lane_map_physical{213.0}=0x2310 +phy_chain_tx_lane_map_physical{217.0}=0x3210 +phy_chain_tx_lane_map_physical{221.0}=0x2301 +phy_chain_tx_lane_map_physical{225.0}=0x3210 +phy_chain_tx_lane_map_physical{229.0}=0x2310 +phy_chain_tx_lane_map_physical{233.0}=0x2310 +phy_chain_tx_lane_map_physical{237.0}=0x1023 +phy_chain_tx_lane_map_physical{241.0}=0x3210 +phy_chain_tx_lane_map_physical{245.0}=0x2310 +phy_chain_tx_lane_map_physical{249.0}=0x3210 +phy_chain_tx_lane_map_physical{253.0}=0x2310 + +## FalconCore [0-15] port RX Lane Swapping +phy_chain_rx_lane_map_physical{1.0}=0x3210 +phy_chain_rx_lane_map_physical{5.0}=0x3210 +phy_chain_rx_lane_map_physical{9.0}=0x3210 +phy_chain_rx_lane_map_physical{13.0}=0x3210 +phy_chain_rx_lane_map_physical{17.0}=0x2310 +phy_chain_rx_lane_map_physical{21.0}=0x0213 +phy_chain_rx_lane_map_physical{25.0}=0x2310 +phy_chain_rx_lane_map_physical{29.0}=0x3210 +phy_chain_rx_lane_map_physical{33.0}=0x3210 +phy_chain_rx_lane_map_physical{37.0}=0x3210 +phy_chain_rx_lane_map_physical{41.0}=0x3210 +phy_chain_rx_lane_map_physical{45.0}=0x3210 +phy_chain_rx_lane_map_physical{49.0}=0x3210 +phy_chain_rx_lane_map_physical{53.0}=0x3210 +phy_chain_rx_lane_map_physical{57.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x3210 + + +## FalconCore [16-31] port RX Lane Swapping +phy_chain_rx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{73.0}=0x3210 +phy_chain_rx_lane_map_physical{77.0}=0x3210 +phy_chain_rx_lane_map_physical{81.0}=0x3210 +phy_chain_rx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{89.0}=0x3210 +phy_chain_rx_lane_map_physical{93.0}=0x3210 +phy_chain_rx_lane_map_physical{97.0}=0x3210 +phy_chain_rx_lane_map_physical{101.0}=0x3201 +phy_chain_rx_lane_map_physical{105.0}=0x3210 +phy_chain_rx_lane_map_physical{109.0}=0x3210 +phy_chain_rx_lane_map_physical{113.0}=0x3210 +phy_chain_rx_lane_map_physical{117.0}=0x3210 +phy_chain_rx_lane_map_physical{121.0}=0x3210 +phy_chain_rx_lane_map_physical{125.0}=0x3210 + + +## FalconCore [32-47] port RX Lane Swapping +phy_chain_rx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_lane_map_physical{133.0}=0x2301 +phy_chain_rx_lane_map_physical{137.0}=0x3210 +phy_chain_rx_lane_map_physical{141.0}=0x2310 +phy_chain_rx_lane_map_physical{145.0}=0x3210 +phy_chain_rx_lane_map_physical{149.0}=0x3210 +phy_chain_rx_lane_map_physical{153.0}=0x3210 +phy_chain_rx_lane_map_physical{157.0}=0x3210 +phy_chain_rx_lane_map_physical{161.0}=0x3210 +phy_chain_rx_lane_map_physical{165.0}=0x3210 +phy_chain_rx_lane_map_physical{169.0}=0x3210 +phy_chain_rx_lane_map_physical{173.0}=0x3210 +phy_chain_rx_lane_map_physical{177.0}=0x3210 +phy_chain_rx_lane_map_physical{181.0}=0x3210 +phy_chain_rx_lane_map_physical{185.0}=0x3210 +phy_chain_rx_lane_map_physical{189.0}=0x3210 + + +## FalconCore [48-63] port RX Lan Swapping +phy_chain_rx_lane_map_physical{193.0}=0x3210 +phy_chain_rx_lane_map_physical{197.0}=0x3210 +phy_chain_rx_lane_map_physical{201.0}=0x3210 +phy_chain_rx_lane_map_physical{205.0}=0x3210 +phy_chain_rx_lane_map_physical{209.0}=0x3210 +phy_chain_rx_lane_map_physical{213.0}=0x3210 +phy_chain_rx_lane_map_physical{217.0}=0x3210 +phy_chain_rx_lane_map_physical{221.0}=0x3210 +phy_chain_rx_lane_map_physical{225.0}=0x3210 +phy_chain_rx_lane_map_physical{229.0}=0x2301 +phy_chain_rx_lane_map_physical{233.0}=0x3210 +phy_chain_rx_lane_map_physical{237.0}=0x1023 +phy_chain_rx_lane_map_physical{241.0}=0x3210 +phy_chain_rx_lane_map_physical{245.0}=0x3210 +phy_chain_rx_lane_map_physical{249.0}=0x3210 +phy_chain_rx_lane_map_physical{253.0}=0x3210 + + +## FalconCore[0-15] ports TX polarity flip +phy_chain_tx_polarity_flip_physical{1.0}=0x1 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_tx_polarity_flip_physical{18.0}=0x1 +phy_chain_tx_polarity_flip_physical{19.0}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=0x0 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x1 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x1 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 +phy_chain_tx_polarity_flip_physical{37.0}=0x0 +phy_chain_tx_polarity_flip_physical{38.0}=0x0 +phy_chain_tx_polarity_flip_physical{39.0}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x1 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +phy_chain_tx_polarity_flip_physical{45.0}=0x0 +phy_chain_tx_polarity_flip_physical{46.0}=0x0 +phy_chain_tx_polarity_flip_physical{47.0}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x0 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x0 +phy_chain_tx_polarity_flip_physical{53.0}=0x0 +phy_chain_tx_polarity_flip_physical{54.0}=0x0 +phy_chain_tx_polarity_flip_physical{55.0}=0x0 +phy_chain_tx_polarity_flip_physical{56.0}=0x0 +phy_chain_tx_polarity_flip_physical{57.0}=0x1 +phy_chain_tx_polarity_flip_physical{58.0}=0x0 +phy_chain_tx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 +phy_chain_tx_polarity_flip_physical{61.0}=0x0 +phy_chain_tx_polarity_flip_physical{62.0}=0x0 +phy_chain_tx_polarity_flip_physical{63.0}=0x0 +phy_chain_tx_polarity_flip_physical{64.0}=0x0 + +## FalconCore[16-31] ports TX polarity flip +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x0 +phy_chain_tx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{73.0}=0x0 +phy_chain_tx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x0 +phy_chain_tx_polarity_flip_physical{76.0}=0x0 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x0 +phy_chain_tx_polarity_flip_physical{79.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +phy_chain_tx_polarity_flip_physical{81.0}=0x0 +phy_chain_tx_polarity_flip_physical{82.0}=0x0 +phy_chain_tx_polarity_flip_physical{83.0}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 +phy_chain_tx_polarity_flip_physical{85.0}=0x0 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +phy_chain_tx_polarity_flip_physical{89.0}=0x1 +phy_chain_tx_polarity_flip_physical{90.0}=0x0 +phy_chain_tx_polarity_flip_physical{91.0}=0x0 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 +phy_chain_tx_polarity_flip_physical{93.0}=0x1 +phy_chain_tx_polarity_flip_physical{94.0}=0x0 +phy_chain_tx_polarity_flip_physical{95.0}=0x0 +phy_chain_tx_polarity_flip_physical{96.0}=0x0 +phy_chain_tx_polarity_flip_physical{97.0}=0x1 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +phy_chain_tx_polarity_flip_physical{101.0}=0x0 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +phy_chain_tx_polarity_flip_physical{103.0}=0x0 +phy_chain_tx_polarity_flip_physical{104.0}=0x0 +phy_chain_tx_polarity_flip_physical{105.0}=0x1 +phy_chain_tx_polarity_flip_physical{106.0}=0x0 +phy_chain_tx_polarity_flip_physical{107.0}=0x0 +phy_chain_tx_polarity_flip_physical{108.0}=0x0 +phy_chain_tx_polarity_flip_physical{109.0}=0x0 +phy_chain_tx_polarity_flip_physical{110.0}=0x0 +phy_chain_tx_polarity_flip_physical{111.0}=0x0 +phy_chain_tx_polarity_flip_physical{112.0}=0x0 +phy_chain_tx_polarity_flip_physical{113.0}=0x0 +phy_chain_tx_polarity_flip_physical{114.0}=0x1 +phy_chain_tx_polarity_flip_physical{115.0}=0x0 +phy_chain_tx_polarity_flip_physical{116.0}=0x0 +phy_chain_tx_polarity_flip_physical{117.0}=0x0 +phy_chain_tx_polarity_flip_physical{118.0}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x0 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +phy_chain_tx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_tx_polarity_flip_physical{123.0}=0x0 +phy_chain_tx_polarity_flip_physical{124.0}=0x0 +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x0 +phy_chain_tx_polarity_flip_physical{127.0}=0x0 +phy_chain_tx_polarity_flip_physical{128.0}=0x0 + +## FalconCore[32-47] ports TX polarity flip +phy_chain_tx_polarity_flip_physical{129.0}=0x0 +phy_chain_tx_polarity_flip_physical{130.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x0 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_tx_polarity_flip_physical{133.0}=0x0 +phy_chain_tx_polarity_flip_physical{134.0}=0x0 +phy_chain_tx_polarity_flip_physical{135.0}=0x0 +phy_chain_tx_polarity_flip_physical{136.0}=0x0 +phy_chain_tx_polarity_flip_physical{137.0}=0x0 +phy_chain_tx_polarity_flip_physical{138.0}=0x1 +phy_chain_tx_polarity_flip_physical{139.0}=0x0 +phy_chain_tx_polarity_flip_physical{140.0}=0x0 +phy_chain_tx_polarity_flip_physical{141.0}=0x0 +phy_chain_tx_polarity_flip_physical{142.0}=0x0 +phy_chain_tx_polarity_flip_physical{143.0}=0x0 +phy_chain_tx_polarity_flip_physical{144.0}=0x0 +phy_chain_tx_polarity_flip_physical{145.0}=0x1 +phy_chain_tx_polarity_flip_physical{146.0}=0x0 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x0 +phy_chain_tx_polarity_flip_physical{149.0}=0x0 +phy_chain_tx_polarity_flip_physical{150.0}=0x0 +phy_chain_tx_polarity_flip_physical{151.0}=0x0 +phy_chain_tx_polarity_flip_physical{152.0}=0x0 +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x1 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x0 +phy_chain_tx_polarity_flip_physical{159.0}=0x0 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 +phy_chain_tx_polarity_flip_physical{161.0}=0x1 +phy_chain_tx_polarity_flip_physical{162.0}=0x0 +phy_chain_tx_polarity_flip_physical{163.0}=0x0 +phy_chain_tx_polarity_flip_physical{164.0}=0x0 +phy_chain_tx_polarity_flip_physical{165.0}=0x0 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x0 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 +phy_chain_tx_polarity_flip_physical{169.0}=0x0 +phy_chain_tx_polarity_flip_physical{170.0}=0x1 +phy_chain_tx_polarity_flip_physical{171.0}=0x0 +phy_chain_tx_polarity_flip_physical{172.0}=0x0 +phy_chain_tx_polarity_flip_physical{173.0}=0x0 +phy_chain_tx_polarity_flip_physical{174.0}=0x0 +phy_chain_tx_polarity_flip_physical{175.0}=0x0 +phy_chain_tx_polarity_flip_physical{176.0}=0x0 +phy_chain_tx_polarity_flip_physical{177.0}=0x0 +phy_chain_tx_polarity_flip_physical{178.0}=0x1 +phy_chain_tx_polarity_flip_physical{179.0}=0x0 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 +phy_chain_tx_polarity_flip_physical{181.0}=0x0 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x0 +phy_chain_tx_polarity_flip_physical{185.0}=0x0 +phy_chain_tx_polarity_flip_physical{186.0}=0x0 +phy_chain_tx_polarity_flip_physical{187.0}=0x0 +phy_chain_tx_polarity_flip_physical{188.0}=0x0 +phy_chain_tx_polarity_flip_physical{189.0}=0x0 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x0 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 + +## FalconCore[48-63] ports TX polarity flip +phy_chain_tx_polarity_flip_physical{193.0}=0x1 +phy_chain_tx_polarity_flip_physical{194.0}=0x0 +phy_chain_tx_polarity_flip_physical{195.0}=0x0 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 +phy_chain_tx_polarity_flip_physical{197.0}=0x0 +phy_chain_tx_polarity_flip_physical{198.0}=0x0 +phy_chain_tx_polarity_flip_physical{199.0}=0x0 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 +phy_chain_tx_polarity_flip_physical{201.0}=0x0 +phy_chain_tx_polarity_flip_physical{202.0}=0x1 +phy_chain_tx_polarity_flip_physical{203.0}=0x0 +phy_chain_tx_polarity_flip_physical{204.0}=0x0 +phy_chain_tx_polarity_flip_physical{205.0}=0x0 +phy_chain_tx_polarity_flip_physical{206.0}=0x0 +phy_chain_tx_polarity_flip_physical{207.0}=0x0 +phy_chain_tx_polarity_flip_physical{208.0}=0x0 +phy_chain_tx_polarity_flip_physical{209.0}=0x0 +phy_chain_tx_polarity_flip_physical{210.0}=0x0 +phy_chain_tx_polarity_flip_physical{211.0}=0x0 +phy_chain_tx_polarity_flip_physical{212.0}=0x0 +phy_chain_tx_polarity_flip_physical{213.0}=0x0 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x0 +phy_chain_tx_polarity_flip_physical{217.0}=0x1 +phy_chain_tx_polarity_flip_physical{218.0}=0x0 +phy_chain_tx_polarity_flip_physical{219.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x0 +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x0 +phy_chain_tx_polarity_flip_physical{223.0}=0x0 +phy_chain_tx_polarity_flip_physical{224.0}=0x0 +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x0 +phy_chain_tx_polarity_flip_physical{227.0}=0x0 +phy_chain_tx_polarity_flip_physical{228.0}=0x0 +phy_chain_tx_polarity_flip_physical{229.0}=0x0 +phy_chain_tx_polarity_flip_physical{230.0}=0x0 +phy_chain_tx_polarity_flip_physical{231.0}=0x0 +phy_chain_tx_polarity_flip_physical{232.0}=0x0 +phy_chain_tx_polarity_flip_physical{233.0}=0x1 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x0 +phy_chain_tx_polarity_flip_physical{236.0}=0x0 +phy_chain_tx_polarity_flip_physical{237.0}=0x0 +phy_chain_tx_polarity_flip_physical{238.0}=0x0 +phy_chain_tx_polarity_flip_physical{239.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 +phy_chain_tx_polarity_flip_physical{241.0}=0x1 +phy_chain_tx_polarity_flip_physical{242.0}=0x0 +phy_chain_tx_polarity_flip_physical{243.0}=0x0 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 +phy_chain_tx_polarity_flip_physical{245.0}=0x0 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x0 +phy_chain_tx_polarity_flip_physical{248.0}=0x1 +phy_chain_tx_polarity_flip_physical{249.0}=0x1 +phy_chain_tx_polarity_flip_physical{250.0}=0x0 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x0 +phy_chain_tx_polarity_flip_physical{253.0}=0x0 +phy_chain_tx_polarity_flip_physical{254.0}=0x0 +phy_chain_tx_polarity_flip_physical{255.0}=0x0 +phy_chain_tx_polarity_flip_physical{256.0}=0x1 + +## FalconCore[0-15] ports RX polarity flip +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x0 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_rx_polarity_flip_physical{17.0}=0x0 +phy_chain_rx_polarity_flip_physical{18.0}=0x0 +phy_chain_rx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x1 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x0 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_rx_polarity_flip_physical{34.0}=0x0 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 +phy_chain_rx_polarity_flip_physical{37.0}=0x0 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x0 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{46.0}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x0 +phy_chain_rx_polarity_flip_physical{48.0}=0x0 +phy_chain_rx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{56.0}=0x0 +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x0 +phy_chain_rx_polarity_flip_physical{59.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x0 +phy_chain_rx_polarity_flip_physical{64.0}=0x0 + +## FalconCore [16-31] ports RX polarity flip +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_rx_polarity_flip_physical{68.0}=0x0 +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x1 +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{76.0}=0x0 +phy_chain_rx_polarity_flip_physical{77.0}=0x0 +phy_chain_rx_polarity_flip_physical{78.0}=0x0 +phy_chain_rx_polarity_flip_physical{79.0}=0x1 +phy_chain_rx_polarity_flip_physical{80.0}=0x0 +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x0 +phy_chain_rx_polarity_flip_physical{84.0}=0x0 +phy_chain_rx_polarity_flip_physical{85.0}=0x0 +phy_chain_rx_polarity_flip_physical{86.0}=0x0 +phy_chain_rx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{91.0}=0x0 +phy_chain_rx_polarity_flip_physical{92.0}=0x0 +phy_chain_rx_polarity_flip_physical{93.0}=0x0 +phy_chain_rx_polarity_flip_physical{94.0}=0x0 +phy_chain_rx_polarity_flip_physical{95.0}=0x0 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x0 +phy_chain_rx_polarity_flip_physical{101.0}=0x0 +phy_chain_rx_polarity_flip_physical{102.0}=0x0 +phy_chain_rx_polarity_flip_physical{103.0}=0x0 +phy_chain_rx_polarity_flip_physical{104.0}=0x0 +phy_chain_rx_polarity_flip_physical{105.0}=0x0 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x0 +phy_chain_rx_polarity_flip_physical{109.0}=0x0 +phy_chain_rx_polarity_flip_physical{110.0}=0x0 +phy_chain_rx_polarity_flip_physical{111.0}=0x0 +phy_chain_rx_polarity_flip_physical{112.0}=0x0 +phy_chain_rx_polarity_flip_physical{113.0}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x0 +phy_chain_rx_polarity_flip_physical{115.0}=0x0 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 +phy_chain_rx_polarity_flip_physical{117.0}=0x0 +phy_chain_rx_polarity_flip_physical{118.0}=0x0 +phy_chain_rx_polarity_flip_physical{119.0}=0x0 +phy_chain_rx_polarity_flip_physical{120.0}=0x0 +phy_chain_rx_polarity_flip_physical{121.0}=0x0 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +phy_chain_rx_polarity_flip_physical{123.0}=0x0 +phy_chain_rx_polarity_flip_physical{124.0}=0x0 +phy_chain_rx_polarity_flip_physical{125.0}=0x0 +phy_chain_rx_polarity_flip_physical{126.0}=0x0 +phy_chain_rx_polarity_flip_physical{127.0}=0x0 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 + +## FalconCore [32-47] ports RX polarity flip +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x0 +phy_chain_rx_polarity_flip_physical{135.0}=0x0 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 +phy_chain_rx_polarity_flip_physical{137.0}=0x0 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x0 +phy_chain_rx_polarity_flip_physical{140.0}=0x0 +phy_chain_rx_polarity_flip_physical{141.0}=0x0 +phy_chain_rx_polarity_flip_physical{142.0}=0x0 +phy_chain_rx_polarity_flip_physical{143.0}=0x0 +phy_chain_rx_polarity_flip_physical{144.0}=0x0 +phy_chain_rx_polarity_flip_physical{145.0}=0x0 +phy_chain_rx_polarity_flip_physical{146.0}=0x0 +phy_chain_rx_polarity_flip_physical{147.0}=0x0 +phy_chain_rx_polarity_flip_physical{148.0}=0x1 +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{150.0}=0x0 +phy_chain_rx_polarity_flip_physical{151.0}=0x0 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 +phy_chain_rx_polarity_flip_physical{153.0}=0x0 +phy_chain_rx_polarity_flip_physical{154.0}=0x0 +phy_chain_rx_polarity_flip_physical{155.0}=0x0 +phy_chain_rx_polarity_flip_physical{156.0}=0x1 +phy_chain_rx_polarity_flip_physical{157.0}=0x0 +phy_chain_rx_polarity_flip_physical{158.0}=0x0 +phy_chain_rx_polarity_flip_physical{159.0}=0x0 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 +phy_chain_rx_polarity_flip_physical{161.0}=0x0 +phy_chain_rx_polarity_flip_physical{162.0}=0x0 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x0 +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x0 +phy_chain_rx_polarity_flip_physical{167.0}=0x0 +phy_chain_rx_polarity_flip_physical{168.0}=0x0 +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{170.0}=0x0 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x0 +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x0 +phy_chain_rx_polarity_flip_physical{175.0}=0x0 +phy_chain_rx_polarity_flip_physical{176.0}=0x0 +phy_chain_rx_polarity_flip_physical{177.0}=0x0 +phy_chain_rx_polarity_flip_physical{178.0}=0x0 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x0 +phy_chain_rx_polarity_flip_physical{181.0}=0x0 +phy_chain_rx_polarity_flip_physical{182.0}=0x0 +phy_chain_rx_polarity_flip_physical{183.0}=0x0 +phy_chain_rx_polarity_flip_physical{184.0}=0x0 +phy_chain_rx_polarity_flip_physical{185.0}=0x0 +phy_chain_rx_polarity_flip_physical{186.0}=0x0 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 +phy_chain_rx_polarity_flip_physical{189.0}=0x0 +phy_chain_rx_polarity_flip_physical{190.0}=0x0 +phy_chain_rx_polarity_flip_physical{191.0}=0x0 +phy_chain_rx_polarity_flip_physical{192.0}=0x0 + +## FalconCore [48-63] ports RX polarity flip +phy_chain_rx_polarity_flip_physical{193.0}=0x0 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x0 +phy_chain_rx_polarity_flip_physical{196.0}=0x0 +phy_chain_rx_polarity_flip_physical{197.0}=0x0 +phy_chain_rx_polarity_flip_physical{198.0}=0x0 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x0 +phy_chain_rx_polarity_flip_physical{201.0}=0x0 +phy_chain_rx_polarity_flip_physical{202.0}=0x0 +phy_chain_rx_polarity_flip_physical{203.0}=0x0 +phy_chain_rx_polarity_flip_physical{204.0}=0x0 +phy_chain_rx_polarity_flip_physical{205.0}=0x0 +phy_chain_rx_polarity_flip_physical{206.0}=0x0 +phy_chain_rx_polarity_flip_physical{207.0}=0x0 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 +phy_chain_rx_polarity_flip_physical{209.0}=0x0 +phy_chain_rx_polarity_flip_physical{210.0}=0x0 +phy_chain_rx_polarity_flip_physical{211.0}=0x1 +phy_chain_rx_polarity_flip_physical{212.0}=0x1 +phy_chain_rx_polarity_flip_physical{213.0}=0x0 +phy_chain_rx_polarity_flip_physical{214.0}=0x0 +phy_chain_rx_polarity_flip_physical{215.0}=0x0 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 +phy_chain_rx_polarity_flip_physical{217.0}=0x0 +phy_chain_rx_polarity_flip_physical{218.0}=0x0 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{220.0}=0x0 +phy_chain_rx_polarity_flip_physical{221.0}=0x0 +phy_chain_rx_polarity_flip_physical{222.0}=0x0 +phy_chain_rx_polarity_flip_physical{223.0}=0x0 +phy_chain_rx_polarity_flip_physical{224.0}=0x0 +phy_chain_rx_polarity_flip_physical{225.0}=0x0 +phy_chain_rx_polarity_flip_physical{226.0}=0x0 +phy_chain_rx_polarity_flip_physical{227.0}=0x0 +phy_chain_rx_polarity_flip_physical{228.0}=0x0 +phy_chain_rx_polarity_flip_physical{229.0}=0x0 +phy_chain_rx_polarity_flip_physical{230.0}=0x0 +phy_chain_rx_polarity_flip_physical{231.0}=0x0 +phy_chain_rx_polarity_flip_physical{232.0}=0x0 +phy_chain_rx_polarity_flip_physical{233.0}=0x0 +phy_chain_rx_polarity_flip_physical{234.0}=0x0 +phy_chain_rx_polarity_flip_physical{235.0}=0x0 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 +phy_chain_rx_polarity_flip_physical{237.0}=0x0 +phy_chain_rx_polarity_flip_physical{238.0}=0x0 +phy_chain_rx_polarity_flip_physical{239.0}=0x0 +phy_chain_rx_polarity_flip_physical{240.0}=0x0 +phy_chain_rx_polarity_flip_physical{241.0}=0x0 +phy_chain_rx_polarity_flip_physical{242.0}=0x0 +phy_chain_rx_polarity_flip_physical{243.0}=0x1 +phy_chain_rx_polarity_flip_physical{244.0}=0x0 +phy_chain_rx_polarity_flip_physical{245.0}=0x0 +phy_chain_rx_polarity_flip_physical{246.0}=0x0 +phy_chain_rx_polarity_flip_physical{247.0}=0x0 +phy_chain_rx_polarity_flip_physical{248.0}=0x0 +phy_chain_rx_polarity_flip_physical{249.0}=0x0 +phy_chain_rx_polarity_flip_physical{250.0}=0x0 +phy_chain_rx_polarity_flip_physical{251.0}=0x1 +phy_chain_rx_polarity_flip_physical{252.0}=0x0 +phy_chain_rx_polarity_flip_physical{253.0}=0x0 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x0 +phy_chain_rx_polarity_flip_physical{256.0}=0x0 + +dport_map_enable=1 +dport_map_port_3=68 +dport_map_port_4=69 +dport_map_port_5=3 +dport_map_port_6=4 +dport_map_port_7=70 +dport_map_port_8=71 +dport_map_port_9=5 +dport_map_port_10=6 +dport_map_port_11=72 +dport_map_port_12=73 +dport_map_port_13=7 +dport_map_port_14=8 +dport_map_port_15=74 +dport_map_port_16=75 +dport_map_port_34=9 +dport_map_port_35=10 +dport_map_port_36=76 +dport_map_port_37=77 +dport_map_port_38=11 +dport_map_port_39=12 +dport_map_port_40=78 +dport_map_port_41=79 +dport_map_port_42=13 +dport_map_port_43=14 +dport_map_port_44=80 +dport_map_port_45=81 +dport_map_port_46=15 +dport_map_port_47=16 +dport_map_port_48=82 +dport_map_port_49=83 +dport_map_port_68=34 +dport_map_port_69=35 +dport_map_port_70=102 +dport_map_port_71=103 +dport_map_port_72=36 +dport_map_port_73=37 +dport_map_port_74=104 +dport_map_port_75=105 +dport_map_port_76=38 +dport_map_port_77=39 +dport_map_port_78=106 +dport_map_port_79=107 +dport_map_port_80=40 +dport_map_port_81=41 +dport_map_port_82=108 +dport_map_port_83=109 +dport_map_port_102=42 +dport_map_port_103=43 +dport_map_port_104=110 +dport_map_port_105=111 +dport_map_port_106=44 +dport_map_port_107=45 +dport_map_port_108=112 +dport_map_port_109=113 +dport_map_port_110=46 +dport_map_port_111=47 +dport_map_port_112=114 +dport_map_port_113=115 +dport_map_port_114=48 +dport_map_port_115=49 + +## ce +## POST: 24(18) MAIN: 62(3E) PRE: 8(08) +serdes_preemphasis_1=0x183E08 +serdes_preemphasis_2=0x193E08 +serdes_preemphasis_5=0x173E08 +serdes_preemphasis_6=0x173E08 +serdes_preemphasis_9=0x163E07 +serdes_preemphasis_10=0x173E08 +serdes_preemphasis_13=0x154007 +serdes_preemphasis_14=0x154007 +serdes_preemphasis_34=0x134007 +serdes_preemphasis_35=0x144007 +serdes_preemphasis_38=0x133F07 +serdes_preemphasis_39=0x133F07 +serdes_preemphasis_42=0x133F07 +serdes_preemphasis_43=0x133F06 +serdes_preemphasis_46=0x113E06 +serdes_preemphasis_47=0x113E05 +serdes_preemphasis_68=0x103F06 +serdes_preemphasis_69=0x103F06 +serdes_preemphasis_72=0x113F06 +serdes_preemphasis_73=0x103F06 +serdes_preemphasis_76=0x124006 +serdes_preemphasis_77=0x124006 +serdes_preemphasis_80=0x144007 +serdes_preemphasis_81=0x144007 +serdes_preemphasis_102=0x144007 +serdes_preemphasis_103=0x144007 +serdes_preemphasis_106=0x153F08 +serdes_preemphasis_107=0x153F08 +serdes_preemphasis_110=0x164008 +serdes_preemphasis_111=0x164008 +serdes_preemphasis_114=0x184008 +serdes_preemphasis_115=0x184008 +serdes_preemphasis_3=0x184108 +serdes_preemphasis_4=0x184108 +serdes_preemphasis_7=0x173F08 +serdes_preemphasis_8=0x174108 +serdes_preemphasis_11=0x154007 +serdes_preemphasis_12=0x154007 +serdes_preemphasis_15=0x144007 +serdes_preemphasis_16=0x144007 +serdes_preemphasis_36=0x133F07 +serdes_preemphasis_37=0x133F07 +serdes_preemphasis_40=0x133F07 +serdes_preemphasis_41=0x123F07 +serdes_preemphasis_44=0x113F07 +serdes_preemphasis_45=0x113F07 +serdes_preemphasis_48=0x113F06 +serdes_preemphasis_49=0x103F06 +serdes_preemphasis_70=0x113F06 +serdes_preemphasis_71=0x103F06 +serdes_preemphasis_74=0x113F06 +serdes_preemphasis_75=0x113F06 +serdes_preemphasis_78=0x123F07 +serdes_preemphasis_79=0x134007 +serdes_preemphasis_82=0x144007 +serdes_preemphasis_83=0x144007 +serdes_preemphasis_104=0x164007 +serdes_preemphasis_105=0x154107 +serdes_preemphasis_108=0x174107 +serdes_preemphasis_109=0x163F07 +serdes_preemphasis_112=0x194107 +serdes_preemphasis_113=0x174107 +serdes_preemphasis_116=0x1B4108 +serdes_preemphasis_117=0x194108 + + diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/default_sku b/device/inventec/x86_64-inventec_d7264q28b-r0/default_sku new file mode 100644 index 000000000000..134ade2e2cd3 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/default_sku @@ -0,0 +1 @@ +INVENTEC-D7264Q28B t1 diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/installer.conf b/device/inventec/x86_64-inventec_d7264q28b-r0/installer.conf new file mode 100644 index 000000000000..1db64ba02c38 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-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_d7264q28b-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d7264q28b-r0/led_proc_init.soc new file mode 100644 index 000000000000..296f8746f101 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/led_proc_init.soc @@ -0,0 +1,273 @@ +#LED processor initialization for Inventec Sequoia platform + +led 0 stop +led 0 prog 02 00 60 F1 12 00 DA 0F 70 10 67 72 67 6D 77 06 02 A0 60 F0 02 00 60 F2 12 00 02 00 60 F4 06 F0 4A 01 71 41 4A 03 27 67 6D 4A 02 27 67 6D 06 F2 28 32 08 67 6D 06 F2 28 32 00 32 01 B7 67 6D 77 4D 67 75 67 6D 67 75 67 6D 67 72 67 6D DA A0 70 5F 86 F0 86 F2 86 F4 06 F4 D2 04 74 2E 77 1A 12 00 DA 00 70 6B 67 75 67 6D 77 61 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=58 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=49 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=50 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=61 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=62 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=53 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=54 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=41 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=42 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=33 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=34 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=45 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=46 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=37 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=38 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=25 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=26 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=17 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=18 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=29 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=30 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=21 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=22 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=9 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=10 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=1 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=2 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=13 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=14 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=5 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=6 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=4 +led 0 start + +led 1 stop +led 1 prog 02 00 60 F1 12 00 DA 0F 70 10 67 72 67 6D 77 06 02 A0 60 F0 02 00 60 F2 12 00 02 00 60 F4 06 F0 4A 01 71 41 4A 03 27 67 6D 4A 02 27 67 6D 06 F2 28 32 08 67 6D 06 F2 28 32 00 32 01 B7 67 6D 77 4D 67 75 67 6D 67 75 67 6D 67 72 67 6D DA A0 70 5F 86 F0 86 F2 86 F4 06 F4 D2 04 74 2E 77 1A 12 00 DA 00 70 6B 67 75 67 6D 77 61 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=5 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=6 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=13 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=14 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=1 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=2 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=9 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=10 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=21 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=22 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=29 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=30 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=17 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=18 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=25 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=26 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=39 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=38 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=45 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=46 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=33 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=34 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=41 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=42 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=53 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=54 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=61 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=62 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=60 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=49 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=50 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=59 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=57 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=58 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56 +led 1 start + +led 2 stop +led 2 prog 02 00 60 F1 12 00 DA 0F 70 10 67 72 67 6D 77 06 02 A0 60 F0 02 00 60 F2 12 00 02 00 60 F4 06 F0 4A 01 71 41 4A 03 27 67 6D 4A 02 27 67 6D 06 F2 28 32 08 67 6D 06 F2 28 32 00 32 01 B7 67 6D 77 4D 67 75 67 6D 67 75 67 6D 67 72 67 6D DA A0 70 5F 86 F0 86 F2 86 F4 06 F4 D2 04 74 2E 77 1A 12 00 DA 00 70 6B 67 75 67 6D 77 61 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=59 +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=57 +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=58 +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=56 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=51 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=49 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=50 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=48 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=63 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=61 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=62 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=60 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=55 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=53 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=54 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=52 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=43 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=41 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=42 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=40 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=35 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=33 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=34 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=32 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=47 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=45 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=46 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=44 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=39 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=37 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=38 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=36 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=27 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=25 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=26 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=24 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=19 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=17 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=18 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=16 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=31 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=29 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=30 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=28 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=23 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=21 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=22 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=20 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=11 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=9 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=10 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=8 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=3 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=1 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=2 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=0 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=15 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=13 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=14 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=12 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=7 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=5 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=6 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=4 +led 2 start + +led 3 stop +led 3 prog 02 00 60 F1 12 00 DA 0F 70 10 67 72 67 6D 77 06 02 A0 60 F0 02 00 60 F2 12 00 02 00 60 F4 06 F0 4A 01 71 41 4A 03 27 67 6D 4A 02 27 67 6D 06 F2 28 32 08 67 6D 06 F2 28 32 00 32 01 B7 67 6D 77 4D 67 75 67 6D 67 75 67 6D 67 72 67 6D DA A0 70 5F 86 F0 86 F2 86 F4 06 F4 D2 04 74 2E 77 1A 12 00 DA 00 70 6B 67 75 67 6D 77 61 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=7 +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=5 +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=6 +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=4 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=15 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=13 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=14 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=12 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=3 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=1 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=2 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=0 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=11 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=9 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=10 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=8 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=23 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=21 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=22 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=20 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=29 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=30 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=28 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=19 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=17 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=18 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=16 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=27 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=25 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=26 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=39 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=37 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=38 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=36 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=47 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=45 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=46 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=44 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=33 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=34 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=32 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=43 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=41 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=42 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=40 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=55 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=53 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=54 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=52 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=63 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=61 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=62 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=60 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=51 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=49 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=50 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=48 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=59 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=57 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=58 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56 +led 3 start diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/eeprom.py new file mode 100644 index 000000000000..de5c24ba0e6d --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-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_d7264q28b-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/psuutil.py new file mode 100755 index 000000000000..c2337a97f4ea --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/psuutil.py @@ -0,0 +1,93 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_DIR1 = "/sys/class/hwmon/hwmon1/device" + PSU_DIR2 = "/sys/class/hwmon/hwmon3/device" + + def __init__(self): + PsuBase.__init__(self) + +# Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + attr_file = 'psoc_psu'+ str(index) + '_iout' + attr_path = self.PSU_DIR1 +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + if (attr_value == 'ERR'): + attr_path = self.PSU_DIR2 +'/' + attr_file + attr_value = self.get_attr_value(attr_path) + # Check for PSU status + if (attr_value != 0): + status = 1 + if (attr_value != 0): + status = 1 + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_absent = 0 + ind = index-1 + attr_file ='psu'+ str(ind) + normal_attr_value = '0 : normal' + attr_path = self.PSU_DIR1 +'/' + attr_file + attr_value = self.get_attr_value(attr_path) + if (attr_value == 'ERR'): + attr_path = self.PSU_DIR2 +'/' + attr_file + attr_value = self.get_attr_value(attr_path) + # Check for PSU presence + if (attr_value == normal_attr_value): + status = 1 + if (attr_value == normal_attr_value): + status = 1 + return status diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/sfputil.py new file mode 100755 index 000000000000..6f23ad01bd2c --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/sfputil.py @@ -0,0 +1,227 @@ +# 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 = 63 + PORTS_IN_BLOCK = 64 + QSFP_PORT_START = 0 + QSFP_PORT_END = 63 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: 10, + 1: 11, + 2: 12, + 3: 13, + 4: 14, + 5: 15, + 6: 16, + 7: 17, + 8: 18, + 9: 19, + 10: 20, + 11: 21, + 12: 22, + 13: 23, + 14: 24, + 15: 25, + 16: 26, + 17: 27, + 18: 28, + 19: 29, + 20: 30, + 21: 31, + 22: 32, + 23: 33, + 24: 34, + 25: 35, + 26: 36, + 27: 37, + 28: 38, + 29: 39, + 30: 40, + 31: 41, + 32: 45, + 33: 44, + 34: 43, + 35: 42, + 36: 49, + 37: 48, + 38: 47, + 39: 46, + 40: 53, + 41: 52, + 42: 51, + 43: 50, + 44: 57, + 45: 56, + 46: 55, + 47: 54, + 48: 61, + 49: 60, + 50: 59, + 51: 58, + 52: 65, + 53: 64, + 54: 63, + 55: 62, + 56: 69, + 57: 68, + 58: 67, + 59: 66, + 60: 73, + 61: 72, + 62: 71, + 63: 70 + } + + @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 + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/sensors.conf b/device/inventec/x86_64-inventec_d7264q28b-r0/sensors.conf new file mode 100644 index 000000000000..38072557730e --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/sensors.conf @@ -0,0 +1,44 @@ +# libsensors configuration file +chip "inv_psoc-*" + label temp1 "FrontSide Temperature" + label temp2 "FanBoard Temperature" + label temp3 "NearASIC Temperature" + label temp4 "Center(U10) Temperature" + label temp5 "CPU Board Temperature" + label temp6 "ASIC Temperature" + label temp7 "PSU1 Temperature1" + label temp8 "PSU2 Temperature1" + label temp9 "PSU1 Temperature2" + label temp10 "PSU2 Temperature2" + label fan1 "FanModule1 Front RPM" + label fan2 "FanModule1 Rear RPM" + label fan3 "FanModule2 Front RPM" + label fan4 "FanModule2 Rear RPM" + label fan5 "FanModule3 Front RPM" + label fan6 "FanModule3 Rear RPM" + label fan7 "FanModule4 Front RPM" + label fan8 "FanModule4 Rear RPM" + label fan9 "FanModule5 Front RPM" + label fan10 "FanModule5 Rear RPM" + label pwm1 "FanModule1 PWM" + label pwm2 "FanModule2 PWM" + label pwm3 "FanModule3 PWM" + label pwm4 "FanModule4 PWM" + label pwm5 "FanModule5 PWM" + label pwm6 "PSU1 FAN PWM" + label pwm7 "PSU2 FAN PWM" + label fan11 "PSU1 FAN RPM" + label fan12 "PSU2 FAN RPM" + label in1 "PSU1 Input Voltage" + label in2 "PSU2 Input Voltage" + label curr1 "PSU1 Input Current" + label curr2 "PSU2 Input Current" + label power1 "PSU1 Input Power" + label power2 "PSU2 Input Power" + label in3 "PSU1 Output Voltage" + label in4 "PSU2 Output Voltage" + label curr3 "PSU1 Output Current" + label curr4 "PSU2 Output Current" + label power3 "PSU1 Output Power" + label power4 "PSU2 Output Power" + diff --git a/device/marvell/x86_64-marvell_slm5401_54x-r0/SLM5401-54x/port_config.ini b/device/marvell/x86_64-marvell_slm5401_54x-r0/SLM5401-54x/port_config.ini new file mode 100755 index 000000000000..74865956f61b --- /dev/null +++ b/device/marvell/x86_64-marvell_slm5401_54x-r0/SLM5401-54x/port_config.ini @@ -0,0 +1,55 @@ +# name lanes +Ethernet0 0 +Ethernet1 1 +Ethernet2 2 +Ethernet3 3 +Ethernet4 4 +Ethernet5 5 +Ethernet6 6 +Ethernet7 7 +Ethernet8 8 +Ethernet9 9 +Ethernet10 10 +Ethernet11 11 +Ethernet12 12 +Ethernet13 13 +Ethernet14 14 +Ethernet15 15 +Ethernet16 16 +Ethernet17 17 +Ethernet18 18 +Ethernet19 19 +Ethernet20 20 +Ethernet21 21 +Ethernet22 22 +Ethernet23 23 +Ethernet24 24 +Ethernet25 25 +Ethernet26 26 +Ethernet27 27 +Ethernet28 28 +Ethernet29 29 +Ethernet30 30 +Ethernet31 31 +Ethernet32 32 +Ethernet33 33 +Ethernet34 34 +Ethernet35 35 +Ethernet36 36 +Ethernet37 37 +Ethernet38 38 +Ethernet39 39 +Ethernet40 40 +Ethernet41 41 +Ethernet42 42 +Ethernet43 43 +Ethernet44 44 +Ethernet45 45 +Ethernet46 46 +Ethernet47 47 +Ethernet48 48 +Ethernet49 49 +Ethernet50 50 +Ethernet51 51 +Ethernet52 52 +Ethernet53 53 diff --git a/device/marvell/x86_64-marvell_slm5401_54x-r0/SLM5401-54x/sai.profile b/device/marvell/x86_64-marvell_slm5401_54x-r0/SLM5401-54x/sai.profile new file mode 100755 index 000000000000..edba72ba4823 --- /dev/null +++ b/device/marvell/x86_64-marvell_slm5401_54x-r0/SLM5401-54x/sai.profile @@ -0,0 +1,2 @@ +mode=1 +hwId=slm5401-54x diff --git a/device/marvell/x86_64-marvell_slm5401_54x-r0/default_sku b/device/marvell/x86_64-marvell_slm5401_54x-r0/default_sku new file mode 100644 index 000000000000..8ace9a8abcef --- /dev/null +++ b/device/marvell/x86_64-marvell_slm5401_54x-r0/default_sku @@ -0,0 +1 @@ +SLM5401-54x t1 diff --git a/device/marvell/x86_64-marvell_slm5401_54x-r0/installer.conf b/device/marvell/x86_64-marvell_slm5401_54x-r0/installer.conf new file mode 100755 index 000000000000..14404194ef53 --- /dev/null +++ b/device/marvell/x86_64-marvell_slm5401_54x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/marvell/x86_64-marvell_slm5401_54x-r0/plugins/eeprom.py b/device/marvell/x86_64-marvell_slm5401_54x-r0/plugins/eeprom.py new file mode 100755 index 000000000000..7681caafeef4 --- /dev/null +++ b/device/marvell/x86_64-marvell_slm5401_54x-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom" + #Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/marvell/x86_64-marvell_slm5401_54x-r0/plugins/sfputil.py b/device/marvell/x86_64-marvell_slm5401_54x-r0/plugins/sfputil.py new file mode 100755 index 000000000000..fa706867a585 --- /dev/null +++ b/device/marvell/x86_64-marvell_slm5401_54x-r0/plugins/sfputil.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class sfputil(SfpUtilBase): + """Platform specific sfputil class""" + + port_start = 0 + port_end = 31 + ports_in_block = 32 + + port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 9 : 18, + 10 : 19, + 11 : 20, + 12 : 21, + 1 : 22, + 2 : 23, + 3 : 24, + 4 : 25, + 6 : 26, + 5 : 27, + 8 : 28, + 7 : 29, + 13 : 30, + 14 : 31, + 15 : 32, + 16 : 33, + 17 : 34, + 18 : 35, + 19 : 36, + 20 : 37, + 25 : 38, + 26 : 39, + 27 : 40, + 28 : 41, + 29 : 42, + 30 : 43, + 31 : 44, + 32 : 45, + 21 : 46, + 22 : 47, + 23 : 48, + 24 : 49, + } + + _qsfp_ports = range(0, ports_in_block + 1) + + def __init__(self): + # Override port_to_eeprom_mapping for class initialization + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom' + for x in range(self.port_start, self.port_end + 1): + port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x+1]) + self.port_to_eeprom_mapping[x] = port_eeprom_path + SfpUtilBase.__init__(self) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + path = "/sys/bus/i2c/devices/{0}-0050/sfp_port_reset" + port_ps = path.format(self.port_to_i2c_mapping[port_num+1]) + + try: + reg_file = open(port_ps, 'w') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + #toggle reset + reg_file.seek(0) + reg_file.write('1') + time.sleep(1) + reg_file.seek(0) + reg_file.write('0') + reg_file.close() + return True + + def set_low_power_mode(self, port_nuM, lpmode): + raise NotImplementedErro + + def get_low_power_mode(self, port_num): + raise NotImplementedErro + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present" + port_ps = path.format(self.port_to_i2c_mapping[port_num+1]) + + + try: + reg_file = open(port_ps) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return range(0, self.ports_in_block + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/mellanox/x86_64-mlnx_lssn2700-r0/LS-SN2700 b/device/mellanox/x86_64-mlnx_lssn2700-r0/LS-SN2700 new file mode 120000 index 000000000000..dfed1bb2cfb5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-r0/LS-SN2700 @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/ACS-MSN2700/ \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_lssn2700-r0/default_sku b/device/mellanox/x86_64-mlnx_lssn2700-r0/default_sku new file mode 100644 index 000000000000..22e3116d2dbb --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-r0/default_sku @@ -0,0 +1 @@ +LS-SN2700 t1 diff --git a/device/mellanox/x86_64-mlnx_lssn2700-r0/installer.conf b/device/mellanox/x86_64-mlnx_lssn2700-r0/installer.conf new file mode 120000 index 000000000000..955db12ff425 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-r0/installer.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/installer.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_lssn2700-r0/platform_reboot b/device/mellanox/x86_64-mlnx_lssn2700-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-r0/platform_reboot @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/platform_reboot \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_lssn2700-r0/sensors.conf b/device/mellanox/x86_64-mlnx_lssn2700-r0/sensors.conf new file mode 120000 index 000000000000..ea04d66d008c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-r0/sensors.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/sensors.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers.json.j2 new file mode 120000 index 000000000000..add8bf8bb7c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..7bcae62336f6 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..a437d613434d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/pg_profile_lookup.ini new file mode 120000 index 000000000000..3c97f3dcb16f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/pg_profile_lookup.ini @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/port_config.ini b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/port_config.ini new file mode 100644 index 000000000000..2bd7aef02e1f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/port_config.ini @@ -0,0 +1,23 @@ +# name lanes index +Ethernet0 0 0 +Ethernet4 4 1 +Ethernet8 8 2 +Ethernet12 12 3 +Ethernet16 16 4 +Ethernet20 20 5 +Ethernet24 24 6 +Ethernet28 28 7 +Ethernet32 32 8 +Ethernet36 36 9 +Ethernet40 40 10 +Ethernet44 44 11 +Ethernet48 48 12 +Ethernet52 52 13 +Ethernet56 56 14 +Ethernet60 60 15 +Ethernet64 64 16 +Ethernet68 68 17 +Ethernet72 72,73,74,75 18 +Ethernet76 76,77,78,79 19 +Ethernet80 80,81,82,83 20 +Ethernet84 84,85,86,87 21 diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/qos.json.j2 new file mode 120000 index 000000000000..eccf286dc879 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/qos.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/qos.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/sai.profile b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/sai.profile new file mode 100644 index 000000000000..32994eb9a823 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sai_2010.xml diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/sai_2010.xml b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/sai_2010.xml new file mode 100644 index 000000000000..8f4af640ddde --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/sai_2010.xml @@ -0,0 +1,243 @@ + + + + + + 00:02:03:04:05:00 + + + 32 + + + + + 1 + 32 + 1 + + + 0 + + + 939524096 + + + 2 + 33 + 1 + 0 + 939524096 + + + 3 + 34 + 1 + 0 + 939524096 + + + 4 + 35 + 1 + 0 + 939524096 + + + 5 + 36 + 1 + 0 + 4096 + + + 6 + 37 + 1 + 0 + 4096 + + + 7 + 38 + 1 + 0 + 4096 + + + 8 + 39 + 1 + 0 + 4096 + + + 9 + 40 + 1 + 0 + 4096 + + + 10 + 41 + 1 + 0 + 4096 + + + 11 + 42 + 1 + 0 + 4096 + + + 12 + 43 + 1 + 0 + 4096 + + + 13 + 44 + 1 + 0 + 4096 + + + 14 + 45 + 1 + 0 + 4096 + + + 15 + 46 + 1 + 0 + 4096 + + + 16 + 47 + 1 + 0 + 4096 + + + 17 + 48 + 1 + 0 + 4096 + + + 18 + 49 + 1 + 0 + 4096 + + + 19 + 1 + 3 + 0 + 4096 + + + 20 + 1 + 4 + 0 + 4096 + + + 21 + 1 + 5 + 0 + 4096 + + + 22 + 1 + 6 + 0 + 4096 + + + 23 + 1 + 7 + 0 + 4096 + + + 24 + 1 + 8 + 0 + 4096 + + + 25 + 1 + 9 + 0 + 4096 + + + 26 + 1 + 10 + 0 + 4096 + + + 27 + 1 + 11 + 0 + 4096 + + + 28 + 1 + 12 + 0 + 4096 + + + 29 + 1 + 13 + 0 + 4096 + + + 30 + 1 + 14 + 0 + 4096 + + + 31 + 1 + 15 + 0 + 4096 + + + 32 + 1 + 16 + 0 + 4096 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/default_sku b/device/mellanox/x86_64-mlnx_msn2010-r0/default_sku new file mode 100644 index 000000000000..558120a701d4 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN2010 t1 diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/installer.conf b/device/mellanox/x86_64-mlnx_msn2010-r0/installer.conf new file mode 100644 index 000000000000..c9c9493a5404 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/installer.conf @@ -0,0 +1 @@ +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=lax acpi=noirq" diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn2010-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/platform_reboot @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/platform_reboot \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/eeprom.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/eeprom.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/psuutil.py new file mode 100644 index 000000000000..914ef050d2c7 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/psuutil.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + self.psu_path = "" + for index in range(0, 100): + hwmon_path = "/sys/devices/platform/mlxplat/mlxreg-hotplug/hwmon/hwmon{}/".format(index) + if os.path.exists(hwmon_path): + self.psu_path = hwmon_path + break + self.psu_presence = "pwr{}" + self.psu_oper_status = "pwr{}" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path + self.psu_oper_status.format(index), 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path + self.psu_presence.format(index), 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfplpmget.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfplpmset.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfpreset.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfpreset.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfputil.py new file mode 120000 index 000000000000..45909b880fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfputil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfputil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn2010-r0/sensors.conf new file mode 100644 index 000000000000..170b0371fb0d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/sensors.conf @@ -0,0 +1,19 @@ +bus "i2c-2" "i2c-1-mux (chan_id 1)" +chip "mlxsw-i2c-2-48" + label temp1 "ASIC Temp" + +bus "i2c-7" "i2c-1-mux (chan_id 6)" +chip "lm75-*" + label temp1 "Ambient Port Temp" + +bus "i2c-5" "i2c-1-mux (chan_id 4)" +chip "tps53679-*" + label vin "TPS vin" + label vout1 "TPS vout1" + label vout2 "TPS vout2" + label temp1 "TPS Temp1" + label temp2 "TPS Temp2" + label pout1 "TPS pouti1" + label pout2 "TPS pout2" + label iout1 "TPS iout1" + label iout2 "TPS iout2" diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers.json.j2 new file mode 120000 index 000000000000..add8bf8bb7c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..7bcae62336f6 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..a437d613434d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/pg_profile_lookup.ini new file mode 120000 index 000000000000..3c97f3dcb16f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/pg_profile_lookup.ini @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/port_config.ini b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/port_config.ini new file mode 100644 index 000000000000..c792a4114b9c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/port_config.ini @@ -0,0 +1,17 @@ +# name lanes +Ethernet0 0,1,2,3 +Ethernet4 4,5,6,7 +Ethernet8 8,9,10,11 +Ethernet12 12,13,14,15 +Ethernet16 16,17,18,19 +Ethernet20 20,21,22,23 +Ethernet24 24,25,26,27 +Ethernet28 28,29,30,31 +Ethernet32 32,33,34,35 +Ethernet36 36,37,38,39 +Ethernet40 40,41,42,43 +Ethernet44 44,45,46,47 +Ethernet48 48,49,50,51 +Ethernet52 52,53,54,55 +Ethernet56 56,57,58,59 +Ethernet60 60,61,62,63 diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/sai.profile b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/sai.profile new file mode 100644 index 000000000000..5a381e4666ee --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_2100.xml diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/sai_2100.xml b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/sai_2100.xml new file mode 100644 index 000000000000..c9b844cd4bf8 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/sai_2100.xml @@ -0,0 +1,131 @@ + + + + + + 00:02:03:04:05:00 + + + 16 + + + + + 25 + 4 + 0 + + + 3 + + + 98368 + + + 29 + 4 + 1 + 3 + 98368 + + + 17 + 4 + 2 + 3 + 98368 + + + 21 + 4 + 3 + 3 + 98368 + + + 9 + 4 + 4 + 3 + 98368 + + + 13 + 4 + 5 + 3 + 98368 + + + 1 + 4 + 6 + 3 + 98368 + + + 5 + 4 + 7 + 3 + 98368 + + + 37 + 4 + 8 + 3 + 98368 + + + 33 + 4 + 9 + 3 + 98368 + + + 45 + 4 + 10 + 3 + 98368 + + + 41 + 4 + 11 + 3 + 98368 + + + 53 + 4 + 12 + 3 + 98368 + + + 49 + 4 + 13 + 3 + 98368 + + + 61 + 4 + 14 + 3 + 98368 + + + 57 + 4 + 15 + 3 + 98368 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/default_sku b/device/mellanox/x86_64-mlnx_msn2100-r0/default_sku new file mode 100644 index 000000000000..5d7c94c0bc8c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN2100 t1 diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/installer.conf b/device/mellanox/x86_64-mlnx_msn2100-r0/installer.conf new file mode 120000 index 000000000000..955db12ff425 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/installer.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/installer.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn2100-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/platform_reboot @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/platform_reboot \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/eeprom.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/eeprom.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/psuutil.py new file mode 100644 index 000000000000..b9bb580d7c57 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/psuutil.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "" + for index in range(0, 100): + hwmon_path = "/sys/devices/platform/mlxplat/mlxreg-hotplug/hwmon/hwmon{}/".format(index) + if os.path.exists(hwmon_path): + self.psu_path = hwmon_path + break + self.psu_presence = "pwr{}" + self.psu_oper_status = "pwr{}" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path + self.psu_oper_status.format(index), 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + return isinstance(index, int) and index > 0 and index <= self.get_num_psus() diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfplpmget.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfplpmset.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfpreset.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfpreset.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfputil.py new file mode 120000 index 000000000000..45909b880fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfputil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfputil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn2100-r0/sensors.conf new file mode 120000 index 000000000000..ea04d66d008c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/sensors.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/sensors.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers.json.j2 new file mode 120000 index 000000000000..add8bf8bb7c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..7bcae62336f6 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..a437d613434d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/pg_profile_lookup.ini new file mode 120000 index 000000000000..3c97f3dcb16f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/pg_profile_lookup.ini @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/port_config.ini b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/port_config.ini new file mode 100644 index 000000000000..c7db66b02274 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/port_config.ini @@ -0,0 +1,57 @@ +# name lanes +Ethernet0 0 +Ethernet4 4 +Ethernet8 8 +Ethernet12 12 +Ethernet16 16 +Ethernet20 20 +Ethernet24 24 +Ethernet28 28 +Ethernet32 32 +Ethernet36 36 +Ethernet40 40 +Ethernet44 44 +Ethernet48 48 +Ethernet52 52 +Ethernet56 56 +Ethernet60 60 +Ethernet64 64 +Ethernet68 68 +Ethernet72 72 +Ethernet76 76 +Ethernet80 80 +Ethernet84 84 +Ethernet88 88 +Ethernet92 92 +Ethernet96 96 +Ethernet100 100 +Ethernet104 104 +Ethernet108 108 +Ethernet112 112 +Ethernet116 116 +Ethernet120 120 +Ethernet124 124 +Ethernet128 128 +Ethernet132 132 +Ethernet136 136 +Ethernet140 140 +Ethernet144 144 +Ethernet148 148 +Ethernet152 152 +Ethernet156 156 +Ethernet160 160 +Ethernet164 164 +Ethernet168 168 +Ethernet172 172 +Ethernet176 176 +Ethernet180 180 +Ethernet184 184 +Ethernet188 188 +Ethernet192 192,193,194,195 +Ethernet196 196,197,198,199 +Ethernet200 200,201,202,203 +Ethernet204 204,205,206,207 +Ethernet208 208,209,210,211 +Ethernet212 212,213,214,215 +Ethernet216 216,217,218,219 +Ethernet220 220,221,222,223 diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/sai.profile b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/sai.profile new file mode 100644 index 000000000000..f7cb264c2287 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_2410.xml diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/sai_2410.xml b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/sai_2410.xml new file mode 100644 index 000000000000..1f97994f887b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/sai_2410.xml @@ -0,0 +1,411 @@ + + + + + + 00:02:03:04:05:00 + + + 56 + + + + + 1 + 32 + 1 + + + 0 + + + 939524096 + + + 2 + 33 + 1 + 0 + 939524096 + + + 3 + 34 + 1 + 0 + 939524096 + + + 4 + 35 + 1 + 0 + 939524096 + + + 5 + 36 + 1 + 0 + 939524096 + + + 6 + 37 + 1 + 0 + 939524096 + + + 7 + 38 + 1 + 0 + 939524096 + + + 8 + 39 + 1 + 0 + 939524096 + + + 9 + 40 + 1 + 0 + 939524096 + + + 10 + 41 + 1 + 0 + 939524096 + + + 11 + 42 + 1 + 0 + 939524096 + + + 12 + 43 + 1 + 0 + 939524096 + + + 13 + 44 + 1 + 0 + 939524096 + + + 14 + 45 + 1 + 0 + 939524096 + + + 15 + 46 + 1 + 0 + 939524096 + + + 16 + 47 + 1 + 0 + 939524096 + + + 17 + 48 + 4 + 3 + 11534336 + + + 19 + 49 + 4 + 1 + 11534336 + + + 21 + 50 + 4 + 3 + 11534336 + + + 23 + 51 + 4 + 1 + 11534336 + + + 25 + 52 + 4 + 3 + 11534336 + + + 27 + 53 + 4 + 1 + 11534336 + + + 29 + 54 + 4 + 3 + 11534336 + + + 31 + 55 + 4 + 1 + 11534336 + + + 33 + 28 + 1 + 0 + 939524096 + + + 34 + 29 + 1 + 0 + 939524096 + + + 35 + 30 + 1 + 0 + 939524096 + + + 36 + 31 + 1 + 0 + 939524096 + + + 37 + 24 + 1 + 0 + 939524096 + + + 38 + 25 + 1 + 0 + 939524096 + + + 39 + 26 + 1 + 0 + 939524096 + + + 40 + 27 + 1 + 0 + 939524096 + + + 41 + 20 + 1 + 0 + 939524096 + + + 42 + 21 + 1 + 0 + 939524096 + + + 43 + 22 + 1 + 0 + 939524096 + + + 44 + 23 + 1 + 0 + 939524096 + + + 45 + 16 + 1 + 0 + 939524096 + + + 46 + 17 + 1 + 0 + 939524096 + + + 47 + 18 + 1 + 0 + 939524096 + + + 48 + 19 + 1 + 0 + 939524096 + + + 49 + 12 + 1 + 0 + 939524096 + + + 50 + 13 + 1 + 0 + 939524096 + + + 51 + 14 + 1 + 0 + 939524096 + + + 52 + 15 + 1 + 0 + 939524096 + + + 53 + 8 + 1 + 0 + 939524096 + + + 54 + 9 + 1 + 0 + 939524096 + + + 55 + 10 + 1 + 0 + 939524096 + + + 56 + 11 + 1 + 0 + 939524096 + + + 57 + 4 + 1 + 0 + 939524096 + + + 58 + 5 + 1 + 0 + 939524096 + + + 59 + 6 + 1 + 0 + 939524096 + + + 60 + 7 + 1 + 0 + 939524096 + + + 61 + 0 + 1 + 0 + 939524096 + + + 62 + 1 + 1 + 0 + 939524096 + + + 63 + 2 + 1 + 0 + 939524096 + + + 64 + 3 + 1 + 0 + 939524096 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/default_sku b/device/mellanox/x86_64-mlnx_msn2410-r0/default_sku new file mode 100644 index 000000000000..ac04d6adf5f5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN2410 t1 diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/installer.conf b/device/mellanox/x86_64-mlnx_msn2410-r0/installer.conf new file mode 120000 index 000000000000..955db12ff425 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/installer.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/installer.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn2410-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/platform_reboot @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/platform_reboot \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/eeprom.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/eeprom.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/psuutil.py new file mode 100644 index 000000000000..954045dde59c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/psuutil.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "" + for index in range(0, 100): + hwmon_path = "/sys/devices/platform/mlxplat/mlxreg-hotplug/hwmon/hwmon{}/".format(index) + if os.path.exists(hwmon_path): + self.psu_path = hwmon_path + break + self.psu_presence = "psu{}" + self.psu_oper_status = "pwr{}" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path + self.psu_oper_status.format(index), 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path + self.psu_presence.format(index), 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfplpmget.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfplpmset.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfpreset.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfpreset.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfputil.py new file mode 120000 index 000000000000..45909b880fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfputil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfputil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn2410-r0/sensors.conf new file mode 120000 index 000000000000..ea04d66d008c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/sensors.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/sensors.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..018c2f96bc1b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2 @@ -0,0 +1,93 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '4194304' %} +{% set ingress_lossy_pool_size = '7340032' %} +{% set egress_lossless_pool_size = '16777152' %} +{% set egress_lossy_pool_size = '7340032' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0, 32) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"0" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "q_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_profile_lists(port_names) %} + "BUFFER_PORT_INGRESS_PROFILE_LIST": { + "{{ port_names }}": { + "profile_list" : "[BUFFER_PROFILE|ingress_lossless_profile],[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, + "BUFFER_PORT_EGRESS_PROFILE_LIST": { + "{{ port_names }}": { + "profile_list" : "[BUFFER_PROFILE|egress_lossless_profile],[BUFFER_PROFILE|egress_lossy_profile]" + } + } +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + }, + "{{ port_names }}|5": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} + + diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..c315ccf59547 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 @@ -0,0 +1,93 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '2097152' %} +{% set ingress_lossy_pool_size = '5242880' %} +{% set egress_lossless_pool_size = '16777152' %} +{% set egress_lossy_pool_size = '5242880' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0, 32) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"0" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "q_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_profile_lists(port_names) %} + "BUFFER_PORT_INGRESS_PROFILE_LIST": { + "{{ port_names }}": { + "profile_list" : "[BUFFER_PROFILE|ingress_lossless_profile],[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, + "BUFFER_PORT_EGRESS_PROFILE_LIST": { + "{{ port_names }}": { + "profile_list" : "[BUFFER_PROFILE|egress_lossless_profile],[BUFFER_PROFILE|egress_lossy_profile]" + } + } +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + }, + "{{ port_names }}|5": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} + + diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini new file mode 100644 index 000000000000..b66b129fe43f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/port_config.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/port_config.ini new file mode 100644 index 000000000000..1e1906ff0ef5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 0,1,2,3 etp1 +Ethernet4 4,5,6,7 etp2 +Ethernet8 8,9,10,11 etp3 +Ethernet12 12,13,14,15 etp4 +Ethernet16 16,17,18,19 etp5 +Ethernet20 20,21,22,23 etp6 +Ethernet24 24,25,26,27 etp7 +Ethernet28 28,29,30,31 etp8 +Ethernet32 32,33,34,35 etp9 +Ethernet36 36,37,38,39 etp10 +Ethernet40 40,41,42,43 etp11 +Ethernet44 44,45,46,47 etp12 +Ethernet48 48,49,50,51 etp13 +Ethernet52 52,53,54,55 etp14 +Ethernet56 56,57,58,59 etp15 +Ethernet60 60,61,62,63 etp16 +Ethernet64 64,65,66,67 etp17 +Ethernet68 68,69,70,71 etp18 +Ethernet72 72,73,74,75 etp19 +Ethernet76 76,77,78,79 etp20 +Ethernet80 80,81,82,83 etp21 +Ethernet84 84,85,86,87 etp22 +Ethernet88 88,89,90,91 etp23 +Ethernet92 92,93,94,95 etp24 +Ethernet96 96,97,98,99 etp25 +Ethernet100 100,101,102,103 etp26 +Ethernet104 104,105,106,107 etp27 +Ethernet108 108,109,110,111 etp28 +Ethernet112 112,113,114,115 etp29 +Ethernet116 116,117,118,119 etp30 +Ethernet120 120,121,122,123 etp31 +Ethernet124 124,125,126,127 etp32 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/sai.profile b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/sai.profile new file mode 100644 index 000000000000..696f3d8182f9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_2700.xml diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/sai_2700.xml b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/sai_2700.xml new file mode 100644 index 000000000000..7831c9cf59d0 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/sai_2700.xml @@ -0,0 +1,243 @@ + + + + + + 00:02:03:04:05:00 + + + 32 + + + + + 1 + 4 + 16 + + + 3 + + + 98368 + + + 3 + 4 + 17 + 1 + 98368 + + + 5 + 4 + 18 + 3 + 98368 + + + 7 + 4 + 19 + 1 + 98368 + + + 9 + 4 + 20 + 3 + 98368 + + + 11 + 4 + 21 + 1 + 98368 + + + 13 + 4 + 22 + 3 + 98368 + + + 15 + 4 + 23 + 1 + 98368 + + + 17 + 4 + 24 + 3 + 98368 + + + 19 + 4 + 25 + 1 + 98368 + + + 21 + 4 + 26 + 3 + 98368 + + + 23 + 4 + 27 + 1 + 98368 + + + 25 + 4 + 28 + 3 + 98368 + + + 27 + 4 + 29 + 1 + 98368 + + + 29 + 4 + 30 + 3 + 98368 + + + 31 + 4 + 31 + 1 + 98368 + + + 33 + 4 + 14 + 3 + 98368 + + + 35 + 4 + 15 + 1 + 98368 + + + 37 + 4 + 12 + 3 + 98368 + + + 39 + 4 + 13 + 1 + 98368 + + + 41 + 4 + 10 + 3 + 98368 + + + 43 + 4 + 11 + 1 + 98368 + + + 45 + 4 + 8 + 3 + 98368 + + + 47 + 4 + 9 + 1 + 98368 + + + 49 + 4 + 6 + 3 + 98368 + + + 51 + 4 + 7 + 1 + 98368 + + + 53 + 4 + 4 + 3 + 98368 + + + 55 + 4 + 5 + 1 + 98368 + + + 57 + 4 + 2 + 3 + 98368 + + + 59 + 4 + 3 + 1 + 98368 + + + 61 + 4 + 0 + 3 + 98368 + + + 63 + 4 + 1 + 1 + 98368 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700 new file mode 120000 index 000000000000..9f12504c7c5a --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700 @@ -0,0 +1 @@ +ACS-MSN2700 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers.json.j2 new file mode 120000 index 000000000000..30c4e1d5bfdd --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers.json.j2 @@ -0,0 +1 @@ +../ACS-MSN2700/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..a722094938f8 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../ACS-MSN2700/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..b02d5e0194ac --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../ACS-MSN2700/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/pg_profile_lookup.ini new file mode 120000 index 000000000000..229a556f88a8 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/pg_profile_lookup.ini @@ -0,0 +1 @@ +../ACS-MSN2700/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/port_config.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/port_config.ini new file mode 100644 index 000000000000..9e01da79f449 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/port_config.ini @@ -0,0 +1,57 @@ +# name lanes speed alias index +Ethernet0 0,1 50000 etp1a 1 +Ethernet2 2,3 50000 etp1b 1 +Ethernet4 4,5 50000 etp2a 2 +Ethernet6 6,7 50000 etp2b 2 +Ethernet8 8,9 50000 etp3a 3 +Ethernet10 10,11 50000 etp3b 3 +Ethernet12 12,13 50000 etp4a 4 +Ethernet14 14,15 50000 etp4b 4 +Ethernet16 16,17 50000 etp5a 5 +Ethernet18 18,19 50000 etp5b 5 +Ethernet20 20,21 50000 etp6a 6 +Ethernet22 22,23 50000 etp6b 6 +Ethernet24 24,25,26,27 100000 etp7 7 +Ethernet28 28,29,30,31 100000 etp8 8 +Ethernet32 32,33,34,35 100000 etp9 9 +Ethernet36 36,37,38,39 100000 etp10 10 +Ethernet40 40,41 50000 etp11a 11 +Ethernet42 42,43 50000 etp11b 11 +Ethernet44 44,45 50000 etp12a 12 +Ethernet46 46,47 50000 etp12b 12 +Ethernet48 48,49 50000 etp13a 13 +Ethernet50 50,51 50000 etp13b 13 +Ethernet52 52,53 50000 etp14a 14 +Ethernet54 54,55 50000 etp14b 14 +Ethernet56 56,57 50000 etp15a 15 +Ethernet58 58,59 50000 etp15b 15 +Ethernet60 60,61 50000 etp16a 16 +Ethernet62 62,63 50000 etp16b 16 +Ethernet64 64,65 50000 etp17a 17 +Ethernet66 66,67 50000 etp17b 17 +Ethernet68 68,69 50000 etp18a 18 +Ethernet70 70,71 50000 etp18b 18 +Ethernet72 72,73 50000 etp19a 19 +Ethernet74 74,75 50000 etp19b 19 +Ethernet76 76,77 50000 etp20a 20 +Ethernet78 78,79 50000 etp20b 20 +Ethernet80 80,81 50000 etp21a 21 +Ethernet82 82,83 50000 etp21b 21 +Ethernet84 84,85 50000 etp22a 22 +Ethernet86 86,87 50000 etp22b 22 +Ethernet88 88,89,90,91 100000 etp23 23 +Ethernet92 92,93,94,95 100000 etp24 24 +Ethernet96 96,97,98,99 100000 etp25 25 +Ethernet100 100,101,102,103 100000 etp26 26 +Ethernet104 104,105 50000 etp27a 27 +Ethernet106 106,107 50000 etp27b 27 +Ethernet108 108,109 50000 etp28a 28 +Ethernet110 110,111 50000 etp28b 28 +Ethernet112 112,113 50000 etp29a 29 +Ethernet114 114,115 50000 etp29b 29 +Ethernet116 116,117 50000 etp30a 30 +Ethernet118 118,119 50000 etp30b 30 +Ethernet120 120,121 50000 etp31a 31 +Ethernet122 122,123 50000 etp31b 31 +Ethernet124 124,125 50000 etp32a 32 +Ethernet126 126,127 50000 etp32b 32 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/sai.profile b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/sai.profile new file mode 100644 index 000000000000..bfbcb1e78f47 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_2700_48x50g_8x100g.xml diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/sai_2700_48x50g_8x100g.xml b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/sai_2700_48x50g_8x100g.xml new file mode 100644 index 000000000000..bda7a3e1cc17 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/sai_2700_48x50g_8x100g.xml @@ -0,0 +1,267 @@ + + + + + + 00:02:03:04:05:00 + + + 32 + + + + + 1 + 4 + 16 + + + 3 + + + 3221225472 + 2 + + + 3 + 4 + 17 + 1 + 3221225472 + 2 + + + 5 + 4 + 18 + 3 + 3221225472 + 2 + + + 7 + 4 + 19 + 1 + 3221225472 + 2 + + + 9 + 4 + 20 + 3 + 3221225472 + 2 + + + 11 + 4 + 21 + 1 + 3221225472 + 2 + + + 13 + 4 + 22 + 3 + 11534336 + + + 15 + 4 + 23 + 1 + 11534336 + + + 17 + 4 + 24 + 3 + 11534336 + + + 19 + 4 + 25 + 1 + 11534336 + + + 21 + 4 + 26 + 3 + 3221225472 + 2 + + + 23 + 4 + 27 + 1 + 3221225472 + 2> + + + 25 + 4 + 28 + 3 + 3221225472 + 2 + + + 27 + 4 + 29 + 1 + 3221225472 + 2 + + + 29 + 4 + 30 + 3 + 3221225472 + 2 + + + 31 + 4 + 31 + 1 + 3221225472 + 2 + + + 33 + 4 + 14 + 3 + 3221225472 + 2 + + + 35 + 4 + 15 + 1 + 3221225472 + 2 + + + 37 + 4 + 12 + 3 + 3221225472 + 2 + + + 39 + 4 + 13 + 1 + 3221225472 + 2 + + + 41 + 4 + 10 + 3 + 3221225472 + 2 + + + 43 + 4 + 11 + 1 + 3221225472 + 2 + + + 45 + 4 + 8 + 3 + 11534336 + + + 47 + 4 + 9 + 1 + 11534336 + + + 49 + 4 + 6 + 3 + 11534336 + + + 51 + 4 + 7 + 1 + 11534336 + + + 53 + 4 + 4 + 3 + 3221225472 + 2 + + + 55 + 4 + 5 + 1 + 3221225472 + 2 + + + 57 + 4 + 2 + 3 + 3221225472 + 2 + + + 59 + 4 + 3 + 1 + 3221225472 + 2 + + + 61 + 4 + 0 + 3 + 3221225472 + 2 + + + 63 + 4 + 1 + 1 + 3221225472 + 2 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/default_sku b/device/mellanox/x86_64-mlnx_msn2700-r0/default_sku new file mode 100644 index 000000000000..bcce12890af1 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/default_sku @@ -0,0 +1 @@ +Mellanox-SN2700 t1 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/installer.conf b/device/mellanox/x86_64-mlnx_msn2700-r0/installer.conf new file mode 100644 index 000000000000..c9c9493a5404 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/installer.conf @@ -0,0 +1 @@ +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=lax acpi=noirq" diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn2700-r0/platform_reboot new file mode 100755 index 000000000000..58ead6402398 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/platform_reboot @@ -0,0 +1,34 @@ +#!/bin/bash + +declare -r EXIT_SUCCESS="0" +declare -r EXIT_ERROR="1" + +declare -r FW_UPGRADE_SCRIPT="/usr/bin/mlnx-fw-upgrade.sh" + +FORCE_REBOOT="no" + +function ParseArguments() { + while [ $# -ge 1 ]; do + case "$1" in + -f|--force) + FORCE_REBOOT="yes" + ;; + esac + shift + done +} + +ParseArguments "$@" + +${FW_UPGRADE_SCRIPT} --upgrade +EXIT_CODE="$?" +if [[ "${EXIT_CODE}" != "${EXIT_SUCCESS}" ]]; then + echo "Failed to burn MLNX FW: errno=${EXIT_CODE}" + + if [[ "${FORCE_REBOOT}" != "yes" ]]; then + echo "Reboot is interrupted: use -f|--force to override" + exit "${EXIT_ERROR}" + fi +fi + +exec /sbin/reboot $@ diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/eeprom.py new file mode 100644 index 000000000000..3d7e8d0556d5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/eeprom.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# 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: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + import syslog + from cStringIO import StringIO + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = "eeprom.py" +EEPROM_SYMLINK = "/bsp/eeprom/vpd_info" +CACHE_FILE = "/var/cache/sonic/decode-syseeprom/syseeprom_cache" + +def log_error(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + _TLV_INFO_MAX_LEN = 256 + RETRIES = 5 + + def __init__(self, name, path, cpld_root, ro): + for attempt in range(self.RETRIES): + if not os.path.islink(EEPROM_SYMLINK): + time.sleep(1) + else: + break + + if not (os.path.exists(EEPROM_SYMLINK) or os.path.isfile(CACHE_FILE)): + log_error("Nowhere to read syseeprom from! No symlink or cache file found") + raise RuntimeError("No syseeprom symlink or cache file found") + + self.eeprom_path = EEPROM_SYMLINK + super(board, self).__init__(self.eeprom_path, 0, '', True) + + def decode_eeprom(self, e): + original_stdout = sys.stdout + sys.stdout = StringIO() + eeprom_tlvinfo.TlvInfoDecoder.decode_eeprom(self, e) + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + print(decode_output.replace('\0', '')) diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/psuutil.py new file mode 100644 index 000000000000..954045dde59c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/psuutil.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "" + for index in range(0, 100): + hwmon_path = "/sys/devices/platform/mlxplat/mlxreg-hotplug/hwmon/hwmon{}/".format(index) + if os.path.exists(hwmon_path): + self.psu_path = hwmon_path + break + self.psu_presence = "psu{}" + self.psu_oper_status = "pwr{}" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path + self.psu_oper_status.format(index), 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path + self.psu_presence.format(index), 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py new file mode 100644 index 000000000000..170766e9bce4 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +import sys, errno +import os +from python_sdk_api.sxd_api import * +from python_sdk_api.sx_api import * + +# Check if SFP port number is provided +if len(sys.argv) < 2: + print "SFP module number is missed." + print "Usage: sfplpmget.py " + sys.exit(errno.EINVAL) + +# Init SDK API +rc, handle = sx_api_open(None) +if (rc != SX_STATUS_SUCCESS): + print "Failed to open api handle.\nPlease check that SDK is running." + sys.exit(errno.EACCES) + +pid = os.getpid() +rc = sxd_access_reg_init(pid, None, 0) +if (rc != 0): + print "Failed to initializing register access.\nPlease check that SDK is running." + sys.exit(errno.EACCES) + +# Get SFP module number +sfp_module = int(sys.argv[1]) + +# Get MCION +mcion = ku_mcion_reg() +mcion.module = sfp_module +meta = sxd_reg_meta_t() +meta.dev_id = 1 +meta.swid = 0 +meta.access_cmd = SXD_ACCESS_CMD_GET + +rc = sxd_access_reg_mcion(mcion, meta, 1, None, None) +assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_mcion failed, rc = %d" % rc + +# Get low power mode status +lpm_mask = 1 << 8 +lpm_status = (lpm_mask & mcion.module_status_bits) != 0 +print "LPM ON" if lpm_status else "LPM OFF" diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py new file mode 100644 index 000000000000..3f31af9f2944 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python + +import sys, errno +import time +import os +from python_sdk_api.sxd_api import * +from python_sdk_api.sx_api import * + +def get_log_ports(handle, sfp_module): + port_attributes_list = new_sx_port_attributes_t_arr(64) + port_cnt_p = new_uint32_t_p() + uint32_t_p_assign(port_cnt_p, 64) + + rc = sx_api_port_device_get(handle, 1 , 0, port_attributes_list, port_cnt_p) + assert rc == SX_STATUS_SUCCESS, "sx_api_port_device_get failed, rc = %d" % rc + + port_cnt = uint32_t_p_value(port_cnt_p) + log_port_list = [] + for i in range(0, port_cnt): + port_attributes = sx_port_attributes_t_arr_getitem(port_attributes_list, i) + if port_attributes.port_mapping.module_port == sfp_module: + log_port_list.append(port_attributes.log_port) + + return log_port_list + +def set_sfp_admin_status(handle, meta, sfp_module, sfp_log_port_list, admin_status): + # Get PMAOS + pmaos = ku_pmaos_reg() + pmaos.module = sfp_module + meta.access_cmd = SXD_ACCESS_CMD_GET + rc = sxd_access_reg_pmaos(pmaos, meta, 1, None, None) + assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmaos failed, rc = %d" % rc + + # Set admin status to PMAOS + pmaos.ase = 1 + pmaos.ee = 1 + pmaos.e = 2 + pmaos.rst = 0 + if admin_status == SX_PORT_ADMIN_STATUS_DOWN: + pmaos.admin_status = 2 + else: + pmaos.admin_status = 1 + + meta.access_cmd = SXD_ACCESS_CMD_SET + rc = sxd_access_reg_pmaos(pmaos, meta, 1, None, None) + assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmaos failed, rc = %d" % rc + +# Check if SFP port number is provided +if len(sys.argv) < 3: + print "SFP module number or LPM is missed." + print "Usage: sfplpmset.py " + sys.exit(errno.EINVAL) + +lpm_enable = None +if sys.argv[2] == 'on': + lpm_enable = True +elif sys.argv[2] == 'off': + lpm_enable = False +else: + print "Unrecognized LPM parameter. Please use or values" + sys.exit(errno.EINVAL) + +# Init SDK API +rc, handle = sx_api_open(None) +if (rc != SX_STATUS_SUCCESS): + print "Failed to open api handle.\nPlease check that SDK is running." + sys.exit(errno.EACCES) + +pid = os.getpid() +rc = sxd_access_reg_init(pid, None, 0) +if (rc != 0): + print "Failed to initializing register access.\nPlease check that SDK is running." + sys.exit(errno.EACCES); + +# Get SFP module and log ports number and LPM status +sfp_module = int(sys.argv[1]) +log_port_list = get_log_ports(handle, sfp_module) +if not log_port_list: + print "Failed to get log ports" + sys.exit(errno.EACCES) + +# Get PMMP +pmmp = ku_pmmp_reg() +pmmp.module = sfp_module +meta = sxd_reg_meta_t() +meta.dev_id = 1 +meta.swid = 0 +meta.access_cmd = SXD_ACCESS_CMD_GET +rc = sxd_access_reg_pmmp(pmmp, meta, 1, None, None) +assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmmp failed, rc = %d" % rc + +# Disable admin status before LPM settings +set_sfp_admin_status(handle, meta, sfp_module, log_port_list, SX_PORT_ADMIN_STATUS_DOWN) + +# Set low power mode status +lpm_mask = 1 << 8 +if lpm_enable: + pmmp.eeprom_override = pmmp.eeprom_override | lpm_mask +else: + pmmp.eeprom_override = pmmp.eeprom_override & (~lpm_mask) + +meta.access_cmd = SXD_ACCESS_CMD_SET +rc = sxd_access_reg_pmmp(pmmp, meta, 1, None, None) +assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmmp failed, rc = %d" % rc + +# Enable admin status after LPM settings +set_sfp_admin_status(handle, meta, sfp_module, log_port_list, SX_PORT_ADMIN_STATUS_UP) diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py new file mode 100644 index 000000000000..69fa2be614c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +import sys, errno +import os +from python_sdk_api.sxd_api import * +from python_sdk_api.sx_api import * + +# Check if SFP port number is provided +if len(sys.argv) < 2: + print "SFP module number or LPM is missed." + print "Usage: sfpreset.py " + sys.exit(errno.EINVAL) + +# Init SDK API +rc, handle = sx_api_open(None) +if (rc != SX_STATUS_SUCCESS): + print "Failed to open api handle.\nPlease check that SDK is running." + sys.exit(errno.EACCES) + +pid = os.getpid() +rc = sxd_access_reg_init(pid, None, 0) +if (rc != 0): + print "Failed to initializing register access.\nPlease check that SDK is running." + sys.exit(errno.EACCES) + +# Get SFP module number +sfp_module = int(sys.argv[1]) + +# Get PMAOS +pmaos = ku_pmaos_reg() +pmaos.module = sfp_module +meta = sxd_reg_meta_t() +meta.dev_id = 1 +meta.swid = 0 +meta.access_cmd = SXD_ACCESS_CMD_GET + +rc = sxd_access_reg_pmaos(pmaos, meta, 1, None, None) +assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmaos failed, rc = %d" % rc + +# Reset SFP +pmaos.rst = 1 +meta.access_cmd = SXD_ACCESS_CMD_SET +rc = sxd_access_reg_pmaos(pmaos, meta, 1, None, None) +assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmaos failed, rc = %d" % rc +print "Reset flag is set" diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py new file mode 100644 index 000000000000..98a7477aa601 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py @@ -0,0 +1,219 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import subprocess + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# parameters for DB connection +REDIS_HOSTNAME = "localhost" +REDIS_PORT = 6379 +REDIS_TIMEOUT_USECS = 0 + +# parameters for SFP presence +SFP_STATUS_INSERTED = '1' + +GET_HWSKU_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.hwsku" + +# magic code defnition for port number, qsfp port position of each hwsku +# port_position_tuple = (PORT_START, QSFP_PORT_START, PORT_END, PORT_IN_BLOCK, EEPROM_OFFSET) +hwsku_dict = {'ACS-MSN2700': 0, "LS-SN2700":0, 'ACS-MSN2740': 0, 'ACS-MSN2100': 1, 'ACS-MSN2410': 2, 'ACS-MSN2010': 3, } +port_position_tuple_list = [(0, 0, 31, 32, 1), (0, 0, 15, 16, 1), (0, 48, 55, 56, 1),(0, 18, 21, 22, 1)] + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + PORT_START = 0 + QSFP_PORT_START = 0 + PORT_END = 0 + PORTS_IN_BLOCK = 0 + EEPROM_OFFSET = 0 + + _port_to_eeprom_mapping = {} + + db_sel = None + db_sel_timeout = None + db_sel_object = None + db_sel_tbl = None + state_db = None + sfpd_status_tbl = None + qsfp_sysfs_path = "/sys/devices/platform/i2c_mlxcpld.1/i2c-1/i2c-2/2-0048/" + + @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(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def get_port_position_tuple_by_sku_name(self): + p = subprocess.Popen(GET_HWSKU_CMD, shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + position_tuple = port_position_tuple_list[hwsku_dict[out.rstrip('\n')]] + return position_tuple + + def __init__(self): + port_position_tuple = self.get_port_position_tuple_by_sku_name() + self.PORT_START = port_position_tuple[0] + self.QSFP_PORT_START = port_position_tuple[1] + self.PORT_END = port_position_tuple[2] + self.PORTS_IN_BLOCK = port_position_tuple[3] + self.EEPROM_OFFSET = port_position_tuple[4] + + for x in range(0, self.port_end + 1): + self._port_to_eeprom_mapping[x] = self.qsfp_sysfs_path + "qsfp{}".format(x + self.EEPROM_OFFSET) + + 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(self.qsfp_sysfs_path + "qsfp{}_status".format(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 == SFP_STATUS_INSERTED: + 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 + + lpm_cmd = "docker exec syncd python /usr/share/sonic/platform/plugins/sfplpmget.py {}".format(port_num) + + try: + output = subprocess.check_output(lpm_cmd, shell=True) + if 'LPM ON' in output: + return True + except subprocess.CalledProcessError as e: + print "Error! Unable to get LPM for {}, rc = {}, err msg: {}".format(port_num, e.returncode, e.output) + return False + + return False + + 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 + + curr_lpmode = self.get_low_power_mode(port_num) + if curr_lpmode == lpmode: + return True + + lpm = 'on' if lpmode else 'off' + lpm_cmd = "docker exec syncd python /usr/share/sonic/platform/plugins/sfplpmset.py {} {}".format(port_num, lpm) + sfp_port_names = self.physical_to_logical[port_num] + + # Get port admin status + try: + enabled_ports = subprocess.check_output("ip link show up", shell=True) + except subprocess.CalledProcessError as e: + print "Error! Unable to get ports status, err msg: {}".format(e.output) + return False + + port_to_disable = [] + for port in sfp_port_names: + if port in enabled_ports: + port_to_disable.append(port) + + # Disable ports before LPM settings + for port in port_to_disable: + try: + subprocess.check_output("ifconfig {} down".format(port), shell=True) + except subprocess.CalledProcessError as e: + print "Error! Unable to set admin status to DOWN for {}, rc = {}, err msg: {}".format(port, e.returncode, e.output) + return False + + time.sleep(3) + + # Set LPM + try: + subprocess.check_output(lpm_cmd, shell=True) + except subprocess.CalledProcessError as e: + print "Error! Unable to set LPM for {}, rc = {}, err msg: {}".format(port_num, e.returncode, e.output) + return False + + # Enable ports after LPM settings + for port in port_to_disable: + try: + subprocess.check_output("ifconfig {} up".format(port), shell=True) + except subprocess.CalledProcessError as e: + print "Error! Unable to set admin status to UP for {}, rc = {}, err msg: {}".format(port, e.returncode, e.output) + return False + + 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 + + lpm_cmd = "docker exec syncd python /usr/share/sonic/platform/plugins/sfpreset.py {}".format(port_num) + + try: + subprocess.check_output(lpm_cmd, shell=True) + return True + except subprocess.CalledProcessError as e: + print "Error! Unable to set LPM for {}, rc = {}, err msg: {}".format(port_num, e.returncode, e.output) + return False + + return False + + def get_transceiver_change_event(self, timeout=0): + phy_port_dict = {} + status = True + + if self.db_sel == None: + from swsscommon import swsscommon + self.state_db = swsscommon.DBConnector(swsscommon.STATE_DB, + REDIS_HOSTNAME, + REDIS_PORT, + REDIS_TIMEOUT_USECS) + + # Subscribe to state table for SFP change notifications + self.db_sel = swsscommon.Select() + self.db_sel_tbl = swsscommon.NotificationConsumer(self.state_db, 'TRANSCEIVER_NOTIFY') + self.db_sel.addSelectable(self.db_sel_tbl) + self.db_sel_timeout = swsscommon.Select.TIMEOUT + self.db_sel_object = swsscommon.Select.OBJECT + self.sfpd_status_tbl = swsscommon.Table(self.state_db, 'MLNX_SFPD_TASK') + + # Check the liveness of mlnx-sfpd, if it failed, return false + keys = self.sfpd_status_tbl.getKeys() + if 'LIVENESS' not in keys: + return False, phy_port_dict + + (state, c) = self.db_sel.select(timeout) + if state == self.db_sel_timeout: + status = True + elif state != self.db_sel_object: + status = False + else: + (key, op, fvp) = self.db_sel_tbl.pop() + phy_port_dict[key] = op + + return status, phy_port_dict + diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn2700-r0/sensors.conf new file mode 100644 index 000000000000..a3e30391863e --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/sensors.conf @@ -0,0 +1,21 @@ +bus "i2c-7" "i2c-1-mux (chan_id 5)" +chip "lm75-i2c-7-4a" + label temp1 "Ambient Port Temp" + +bus "i2c-5" "i2c-1-mux (chan_id 3)" +chip "ucd9200-i2c-5-27" + label in1 "UCD1 vin" + label in2 "ASIC 3.3 vout" + label in3 "ASIC 1.2 vout" + label temp1 "UCD1 Temp" + label temp2 "UCD1 Temp2" + +chip "ucd9200-i2c-5-41" + label in1 "UCD2 vin" + label in2 "ASIC Vcore vout" + label temp1 "UCD2 Temp1" + label temp2 "UCD2 Temp2" + +bus "i2c-17" "i2c-1-mux (chan_id 7)" +chip "lm75-i2c-17-49" + label temp1 "Ambient Board Temp" diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers.json.j2 new file mode 120000 index 000000000000..add8bf8bb7c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..7bcae62336f6 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..a437d613434d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/pg_profile_lookup.ini new file mode 120000 index 000000000000..3c97f3dcb16f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/pg_profile_lookup.ini @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/port_config.ini b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/port_config.ini new file mode 100644 index 000000000000..816bb0e94a70 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/port_config.ini @@ -0,0 +1,33 @@ +# name lanes +Ethernet0 0,1,2,3 +Ethernet4 4,5,6,7 +Ethernet8 8,9,10,11 +Ethernet12 12,13,14,15 +Ethernet16 16,17,18,19 +Ethernet20 20,21,22,23 +Ethernet24 24,25,26,27 +Ethernet28 28,29,30,31 +Ethernet32 32,33,34,35 +Ethernet36 36,37,38,39 +Ethernet40 40,41,42,43 +Ethernet44 44,45,46,47 +Ethernet48 48,49,50,51 +Ethernet52 52,53,54,55 +Ethernet56 56,57,58,59 +Ethernet60 60,61,62,63 +Ethernet64 64,65,66,67 +Ethernet68 68,69,70,71 +Ethernet72 72,73,74,75 +Ethernet76 76,77,78,79 +Ethernet80 80,81,82,83 +Ethernet84 84,85,86,87 +Ethernet88 88,89,90,91 +Ethernet92 92,93,94,95 +Ethernet96 96,97,98,99 +Ethernet100 100,101,102,103 +Ethernet104 104,105,106,107 +Ethernet108 108,109,110,111 +Ethernet112 112,113,114,115 +Ethernet116 116,117,118,119 +Ethernet120 120,121,122,123 +Ethernet124 124,125,126,127 diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/qos.json.j2 new file mode 120000 index 000000000000..eccf286dc879 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/qos.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/qos.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/sai.profile b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/sai.profile new file mode 100644 index 000000000000..adaa280e6cd5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_2740.xml diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/sai_2740.xml b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/sai_2740.xml new file mode 100644 index 000000000000..559f2bdd10c8 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/sai_2740.xml @@ -0,0 +1,243 @@ + + + + + + 00:02:03:04:05:00 + + + 32 + + + + + 1 + 4 + 16 + + + 3 + + + 98368 + + + 3 + 4 + 17 + 1 + 98368 + + + 5 + 4 + 18 + 3 + 98368 + + + 7 + 4 + 19 + 1 + 98368 + + + 9 + 4 + 20 + 3 + 98368 + + + 11 + 4 + 21 + 1 + 98368 + + + 13 + 4 + 22 + 3 + 98368 + + + 15 + 4 + 23 + 1 + 98368 + + + 17 + 4 + 24 + 3 + 98368 + + + 19 + 4 + 25 + 1 + 98368 + + + 21 + 4 + 26 + 3 + 98368 + + + 23 + 4 + 27 + 1 + 98368 + + + 25 + 4 + 28 + 3 + 98368 + + + 27 + 4 + 29 + 1 + 98368 + + + 29 + 4 + 30 + 3 + 98368 + + + 31 + 4 + 31 + 1 + 98368 + + + 33 + 4 + 14 + 3 + 98368 + + + 35 + 4 + 15 + 1 + 98368 + + + 37 + 4 + 12 + 3 + 98368 + + + 39 + 4 + 13 + 1 + 98368 + + + 41 + 4 + 10 + 3 + 98368 + + + 43 + 4 + 11 + 1 + 98368 + + + 45 + 4 + 8 + 3 + 98368 + + + 47 + 4 + 9 + 1 + 98368 + + + 49 + 4 + 6 + 3 + 98368 + + + 51 + 4 + 7 + 1 + 98368 + + + 53 + 4 + 4 + 3 + 98368 + + + 55 + 4 + 5 + 1 + 98368 + + + 57 + 4 + 2 + 3 + 98368 + + + 59 + 4 + 3 + 1 + 98368 + + + 61 + 4 + 0 + 3 + 98368 + + + 63 + 4 + 1 + 1 + 98368 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/default_sku b/device/mellanox/x86_64-mlnx_msn2740-r0/default_sku new file mode 100644 index 000000000000..9641115a4946 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN2740 t1 diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/installer.conf b/device/mellanox/x86_64-mlnx_msn2740-r0/installer.conf new file mode 120000 index 000000000000..955db12ff425 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/installer.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/installer.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn2740-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/platform_reboot @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/platform_reboot \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/eeprom.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/eeprom.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/psuutil.py new file mode 100644 index 000000000000..8c47a0083249 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/psuutil.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + self.psu_path = "" + for index in range(0, 100): + hwmon_path = "/sys/devices/platform/mlxplat/mlxreg-hotplug/hwmon/hwmon{}/".format(index) + if os.path.exists(hwmon_path): + self.psu_path = hwmon_path + break + self.psu_presence = "psu{}" + self.psu_oper_status = "pwr{}" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path + self.psu_oper_status.format(index), 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path + self.psu_presence.format(index), 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfplpmget.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfplpmset.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfpreset.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfpreset.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfputil.py new file mode 120000 index 000000000000..45909b880fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfputil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/sfputil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn2740-r0/sensors.conf new file mode 120000 index 000000000000..ea04d66d008c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/sensors.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/sensors.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_x86-r5.0.1400/default_sku b/device/mellanox/x86_64-mlnx_x86-r5.0.1400/default_sku new file mode 100644 index 000000000000..9641115a4946 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_x86-r5.0.1400/default_sku @@ -0,0 +1 @@ +ACS-MSN2740 t1 diff --git a/device/mellanox/x86_64-mlnx_x86-r5.0.1400/installer.conf b/device/mellanox/x86_64-mlnx_x86-r5.0.1400/installer.conf new file mode 100644 index 000000000000..c9c9493a5404 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_x86-r5.0.1400/installer.conf @@ -0,0 +1 @@ +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=lax acpi=noirq" diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/port_config.ini b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/port_config.ini new file mode 100644 index 000000000000..1fa6d21d9609 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 49,50,51,52 hundredGigE1 +Ethernet4 53,54,55,56 hundredGigE2 +Ethernet8 57,58,59,60 hundredGigE3 +Ethernet12 61,62,63,64 hundredGigE4 +Ethernet16 65,66,67,68 hundredGigE5 +Ethernet20 69,70,71,72 hundredGigE6 +Ethernet24 73,74,75,76 hundredGigE7 +Ethernet28 77,78,79,80 hundredGigE8 +Ethernet32 33,34,35,36 hundredGigE9 +Ethernet36 37,38,39,40 hundredGigE10 +Ethernet40 41,42,43,44 hundredGigE11 +Ethernet44 45,46,47,48 hundredGigE12 +Ethernet48 81,82,83,84 hundredGigE13 +Ethernet52 85,86,87,88 hundredGigE14 +Ethernet56 89,90,91,92 hundredGigE15 +Ethernet60 93,94,95,96 hundredGigE16 +Ethernet64 97,98,99,100 hundredGigE17 +Ethernet68 101,102,103,104 hundredGigE18 +Ethernet72 105,106,107,108 hundredGigE19 +Ethernet76 109,110,111,112 hundredGigE20 +Ethernet80 17,18,19,20 hundredGigE21 +Ethernet84 21,22,23,24 hundredGigE22 +Ethernet88 25,26,27,28 hundredGigE23 +Ethernet92 29,30,31,32 hundredGigE24 +Ethernet96 113,114,115,116 hundredGigE25 +Ethernet100 117,118,119,120 hundredGigE26 +Ethernet104 121,122,123,124 hundredGigE27 +Ethernet108 125,126,127,128 hundredGigE28 +Ethernet112 1,2,3,4 hundredGigE29 +Ethernet116 5,6,7,8 hundredGigE30 +Ethernet120 9,10,11,12 hundredGigE31 +Ethernet124 13,14,15,16 hundredGigE32 diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/sai.profile b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/sai.profile new file mode 100644 index 000000000000..a58c3ac6eabf --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-ly1200-32x100G.config.bcm diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/th-ly1200-32x100G.config.bcm b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/th-ly1200-32x100G.config.bcm new file mode 100644 index 000000000000..84b2c572664f --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/th-ly1200-32x100G.config.bcm @@ -0,0 +1,319 @@ +### BMS (start) +## Global settings +bcm_num_cos=8 +dport_map_indexed=0 + +## Switch settings +# Port number and bandwidth assignment. +portmap_1=1:100 +portmap_5=5:100 +portmap_9=9:100 +portmap_13=13:100 +portmap_17=17:100 +portmap_21=21:100 +portmap_25=25:100 +portmap_29=29:100 +portmap_34=33:100 +portmap_38=37:100 +portmap_42=41:100 +portmap_46=45:100 +portmap_50=49:100 +portmap_54=53:100 +portmap_58=57:100 +portmap_62=61:100 +portmap_68=65:100 +portmap_72=69:100 +portmap_76=73:100 +portmap_80=77:100 +portmap_84=81:100 +portmap_88=85:100 +portmap_92=89:100 +portmap_96=93:100 +portmap_102=97:100 +portmap_106=101:100 +portmap_110=105:100 +portmap_114=109:100 +portmap_118=113:100 +portmap_122=117:100 +portmap_126=121:100 +portmap_130=125:100 + +# pbmp_xport_xe is used to specify if a XPORT block is configured as xe port +# By default, an XPORT block is treated as HG port. +pbmp_xport_xe=0x0444444441111111104444444422222222 + +# Map dport number to internal port number . +dport_map_port_0=327 +dport_map_port_1=112 +dport_map_port_5=116 +dport_map_port_9=120 +dport_map_port_13=124 +dport_map_port_17=80 +dport_map_port_21=84 +dport_map_port_25=88 +dport_map_port_29=92 +dport_map_port_34=32 +dport_map_port_38=36 +dport_map_port_42=40 +dport_map_port_46=44 +dport_map_port_50=0 +dport_map_port_54=4 +dport_map_port_58=8 +dport_map_port_62=12 +dport_map_port_68=16 +dport_map_port_72=20 +dport_map_port_76=24 +dport_map_port_80=28 +dport_map_port_84=48 +dport_map_port_88=52 +dport_map_port_92=56 +dport_map_port_96=60 +dport_map_port_102=64 +dport_map_port_106=68 +dport_map_port_110=72 +dport_map_port_114=76 +dport_map_port_118=96 +dport_map_port_122=100 +dport_map_port_126=104 +dport_map_port_130=108 + +# Remap XGXS rx and tx lanes to desired mapping. Four bits were used for +# specifying each lane in the format of Lane 0 (bit 15-12), Lane 1 (bit 11-8), +# lane 2 (bit 7-4), and lane 3 (bit 3-0). +# For example, to reverse the tx lane mapping in 3, 2, 1, 0 order, +xgxs_tx_lane_map_ce0=0x3210 +xgxs_rx_lane_map_ce0=0x3210 +xgxs_tx_lane_map_ce4=0x3210 +xgxs_rx_lane_map_ce4=0x2103 +xgxs_tx_lane_map_ce8=0x3210 +xgxs_rx_lane_map_ce8=0x3210 +xgxs_tx_lane_map_ce12=0x3210 +xgxs_rx_lane_map_ce12=0x2103 +xgxs_tx_lane_map_ce16=0x0123 +xgxs_rx_lane_map_ce16=0x0123 +xgxs_tx_lane_map_ce20=0x3210 +xgxs_rx_lane_map_ce20=0x2103 +xgxs_tx_lane_map_ce24=0x3210 +xgxs_rx_lane_map_ce24=0x3210 +xgxs_tx_lane_map_ce28=0x0123 +xgxs_rx_lane_map_ce28=0x1203 +xgxs_tx_lane_map_ce32=0x3210 +xgxs_rx_lane_map_ce32=0x3210 +xgxs_tx_lane_map_ce36=0x2301 +xgxs_rx_lane_map_ce36=0x3120 +xgxs_tx_lane_map_ce40=0x3210 +xgxs_rx_lane_map_ce40=0x3210 +xgxs_tx_lane_map_ce44=0x3102 +xgxs_rx_lane_map_ce44=0x2301 +xgxs_tx_lane_map_ce48=0x3210 +xgxs_rx_lane_map_ce48=0x1203 +xgxs_tx_lane_map_ce52=0x0123 +xgxs_rx_lane_map_ce52=0x3210 +xgxs_tx_lane_map_ce56=0x3210 +xgxs_rx_lane_map_ce56=0x1203 +xgxs_tx_lane_map_ce60=0x0213 +xgxs_rx_lane_map_ce60=0x3210 +xgxs_tx_lane_map_ce64=0x3120 +xgxs_rx_lane_map_ce64=0x1032 +xgxs_tx_lane_map_ce68=0x0123 +xgxs_rx_lane_map_ce68=0x3012 +xgxs_tx_lane_map_ce72=0x1230 +xgxs_rx_lane_map_ce72=0x1032 +xgxs_tx_lane_map_ce76=0x0123 +xgxs_rx_lane_map_ce76=0x3012 +xgxs_tx_lane_map_ce80=0x0213 +xgxs_rx_lane_map_ce80=0x2031 +xgxs_tx_lane_map_ce84=0x2301 +xgxs_rx_lane_map_ce84=0x3120 +xgxs_tx_lane_map_ce88=0x3210 +xgxs_rx_lane_map_ce88=0x3210 +xgxs_tx_lane_map_ce92=0x2301 +xgxs_rx_lane_map_ce92=0x3120 +xgxs_tx_lane_map_ce96=0x3210 +xgxs_rx_lane_map_ce96=0x0321 +xgxs_tx_lane_map_ce100=0x0123 +xgxs_rx_lane_map_ce100=0x1032 +xgxs_tx_lane_map_ce104=0x0123 +xgxs_rx_lane_map_ce104=0x0123 +xgxs_tx_lane_map_ce108=0x3210 +xgxs_rx_lane_map_ce108=0x2103 +xgxs_tx_lane_map_ce112=0x0123 +xgxs_rx_lane_map_ce112=0x0123 +xgxs_tx_lane_map_ce116=0x0123 +xgxs_rx_lane_map_ce116=0x1230 +xgxs_tx_lane_map_ce120=0x0123 +xgxs_rx_lane_map_ce120=0x0123 +xgxs_tx_lane_map_ce124=0x0123 +xgxs_rx_lane_map_ce124=0x1230 + +# Config to describe the system Linerate or Oversubscribe mode. +# 0: Linerate only (default). +# 1: Oversubscribe mode (all ports will be oversub). +# 2: Mixed mode. Check device specification for applicability. Port bitmap specified via pbmp_oversubscribe. +oversubscribe_mode=1 + +# Set the default MMU lossless behavior. +mmu_lossless=0 + +# Set preemphasis +serdes_preemphasis_lane0_ce0=0x2c3c08 +serdes_preemphasis_lane1_ce0=0x2c3c08 +serdes_preemphasis_lane2_ce0=0x2c3c08 +serdes_preemphasis_lane3_ce0=0x2c3c08 + +serdes_preemphasis_lane0_ce4=0x2c3c08 +serdes_preemphasis_lane1_ce4=0x2c3c08 +serdes_preemphasis_lane2_ce4=0x2c3c08 +serdes_preemphasis_lane3_ce4=0x2c3c08 + +serdes_preemphasis_lane0_ce8=0x2c3c08 +serdes_preemphasis_lane1_ce8=0x2c3c08 +serdes_preemphasis_lane2_ce8=0x2c3c08 +serdes_preemphasis_lane3_ce8=0x2c3c08 + +serdes_preemphasis_lane0_ce12=0x2c3c08 +serdes_preemphasis_lane1_ce12=0x2c3c08 +serdes_preemphasis_lane2_ce12=0x2c3c08 +serdes_preemphasis_lane3_ce12=0x2c3c08 + +serdes_preemphasis_lane0_ce16=0x244408 +serdes_preemphasis_lane1_ce16=0x244408 +serdes_preemphasis_lane2_ce16=0x244408 +serdes_preemphasis_lane3_ce16=0x244408 + +serdes_preemphasis_lane0_ce20=0x244408 +serdes_preemphasis_lane1_ce20=0x244408 +serdes_preemphasis_lane2_ce20=0x244408 +serdes_preemphasis_lane3_ce20=0x244408 + +serdes_preemphasis_lane0_ce24=0x244408 +serdes_preemphasis_lane1_ce24=0x244408 +serdes_preemphasis_lane2_ce24=0x244408 +serdes_preemphasis_lane3_ce24=0x244408 + +serdes_preemphasis_lane0_ce28=0x244408 +serdes_preemphasis_lane1_ce28=0x244408 +serdes_preemphasis_lane2_ce28=0x244408 +serdes_preemphasis_lane3_ce28=0x244408 + +serdes_preemphasis_lane0_ce32=0x2c3c08 +serdes_preemphasis_lane1_ce32=0x2c3c08 +serdes_preemphasis_lane2_ce32=0x2c3c08 +serdes_preemphasis_lane3_ce32=0x2c3c08 + +serdes_preemphasis_lane0_ce36=0x2c3c08 +serdes_preemphasis_lane1_ce36=0x2c3c08 +serdes_preemphasis_lane2_ce36=0x2c3c08 +serdes_preemphasis_lane3_ce36=0x2c3c08 + +serdes_preemphasis_lane0_ce40=0x2c3c08 +serdes_preemphasis_lane1_ce40=0x2c3c08 +serdes_preemphasis_lane2_ce40=0x2c3c08 +serdes_preemphasis_lane3_ce40=0x2c3c08 + +serdes_preemphasis_lane0_ce44=0x244408 +serdes_preemphasis_lane1_ce44=0x244408 +serdes_preemphasis_lane2_ce44=0x244408 +serdes_preemphasis_lane3_ce44=0x244408 + +serdes_preemphasis_lane0_ce48=0x244408 +serdes_preemphasis_lane1_ce48=0x244408 +serdes_preemphasis_lane2_ce48=0x244408 +serdes_preemphasis_lane3_ce48=0x244408 + +serdes_preemphasis_lane0_ce52=0x244408 +serdes_preemphasis_lane1_ce52=0x244408 +serdes_preemphasis_lane2_ce52=0x244408 +serdes_preemphasis_lane3_ce52=0x244408 + +serdes_preemphasis_lane0_ce56=0x244408 +serdes_preemphasis_lane1_ce56=0x244408 +serdes_preemphasis_lane2_ce56=0x244408 +serdes_preemphasis_lane3_ce56=0x244408 + +serdes_preemphasis_lane0_ce60=0x244408 +serdes_preemphasis_lane1_ce60=0x244408 +serdes_preemphasis_lane2_ce60=0x244408 +serdes_preemphasis_lane3_ce60=0x244408 + +serdes_preemphasis_lane0_ce64=0x244408 +serdes_preemphasis_lane1_ce64=0x244408 +serdes_preemphasis_lane2_ce64=0x244408 +serdes_preemphasis_lane3_ce64=0x244408 + +serdes_preemphasis_lane0_ce68=0x244408 +serdes_preemphasis_lane1_ce68=0x244408 +serdes_preemphasis_lane2_ce68=0x244408 +serdes_preemphasis_lane3_ce68=0x244408 + +serdes_preemphasis_lane0_ce72=0x244408 +serdes_preemphasis_lane1_ce72=0x244408 +serdes_preemphasis_lane2_ce72=0x244408 +serdes_preemphasis_lane3_ce72=0x244408 + +serdes_preemphasis_lane0_ce76=0x244408 +serdes_preemphasis_lane1_ce76=0x244408 +serdes_preemphasis_lane2_ce76=0x244408 +serdes_preemphasis_lane3_ce76=0x244408 + +serdes_preemphasis_lane0_ce80=0x244408 +serdes_preemphasis_lane1_ce80=0x244408 +serdes_preemphasis_lane2_ce80=0x244408 +serdes_preemphasis_lane3_ce80=0x244408 + +serdes_preemphasis_lane0_ce84=0x2c3c08 +serdes_preemphasis_lane1_ce84=0x2c3c08 +serdes_preemphasis_lane2_ce84=0x2c3c08 +serdes_preemphasis_lane3_ce84=0x2c3c08 + +serdes_preemphasis_lane0_ce88=0x2c3c08 +serdes_preemphasis_lane1_ce88=0x2c3c08 +serdes_preemphasis_lane2_ce88=0x2c3c08 +serdes_preemphasis_lane3_ce88=0x2c3c08 + +serdes_preemphasis_lane0_ce92=0x2c3c08 +serdes_preemphasis_lane1_ce92=0x2c3c08 +serdes_preemphasis_lane2_ce92=0x2c3c08 +serdes_preemphasis_lane3_ce92=0x2c3c08 + +serdes_preemphasis_lane0_ce96=0x244408 +serdes_preemphasis_lane1_ce96=0x244408 +serdes_preemphasis_lane2_ce96=0x244408 +serdes_preemphasis_lane3_ce96=0x244408 + +serdes_preemphasis_lane0_ce100=0x244408 +serdes_preemphasis_lane1_ce100=0x244408 +serdes_preemphasis_lane2_ce100=0x244408 +serdes_preemphasis_lane3_ce100=0x244408 + +serdes_preemphasis_lane0_ce104=0x244408 +serdes_preemphasis_lane1_ce104=0x244408 +serdes_preemphasis_lane2_ce104=0x244408 +serdes_preemphasis_lane3_ce104=0x244408 + +serdes_preemphasis_lane0_ce108=0x244408 +serdes_preemphasis_lane1_ce108=0x244408 +serdes_preemphasis_lane2_ce108=0x244408 +serdes_preemphasis_lane3_ce108=0x244408 + +serdes_preemphasis_lane0_ce112=0x2c3c08 +serdes_preemphasis_lane1_ce112=0x2c3c08 +serdes_preemphasis_lane2_ce112=0x2c3c08 +serdes_preemphasis_lane3_ce112=0x2c3c08 + +serdes_preemphasis_lane0_ce116=0x2c3c08 +serdes_preemphasis_lane1_ce116=0x2c3c08 +serdes_preemphasis_lane2_ce116=0x2c3c08 +serdes_preemphasis_lane3_ce116=0x2c3c08 + +serdes_preemphasis_lane0_ce120=0x2c3c08 +serdes_preemphasis_lane1_ce120=0x2c3c08 +serdes_preemphasis_lane2_ce120=0x2c3c08 +serdes_preemphasis_lane3_ce120=0x2c3c08 + +serdes_preemphasis_lane0_ce124=0x2c3c08 +serdes_preemphasis_lane1_ce124=0x2c3c08 +serdes_preemphasis_lane2_ce124=0x2c3c08 +serdes_preemphasis_lane3_ce124=0x2c3c08 + +### BMS (end) \ No newline at end of file diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/default_sku b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/default_sku new file mode 100644 index 000000000000..b533cbe35c56 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/default_sku @@ -0,0 +1 @@ +MiTAC-LY1200-B32H0-C3 t1 diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf new file mode 100644 index 000000000000..8d4683add468 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=lax pcie_aspm=off irqpoll" diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/led_proc_init.soc b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/led_proc_init.soc new file mode 100644 index 000000000000..867cd1b6fe37 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/led_proc_init.soc @@ -0,0 +1,43 @@ +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=62 REMAP_PORT_18=61 REMAP_PORT_19=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=59 REMAP_PORT_21=58 REMAP_PORT_22=57 REMAP_PORT_23=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=55 REMAP_PORT_25=54 REMAP_PORT_26=53 REMAP_PORT_27=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=51 REMAP_PORT_29=50 REMAP_PORT_30=49 REMAP_PORT_31=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=47 REMAP_PORT_33=46 REMAP_PORT_34=45 REMAP_PORT_35=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=43 REMAP_PORT_37=42 REMAP_PORT_38=41 REMAP_PORT_39=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=39 REMAP_PORT_41=38 REMAP_PORT_42=37 REMAP_PORT_43=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=35 REMAP_PORT_45=34 REMAP_PORT_46=33 REMAP_PORT_47=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=35 REMAP_PORT_1=34 REMAP_PORT_2=33 REMAP_PORT_3=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=39 REMAP_PORT_5=38 REMAP_PORT_6=37 REMAP_PORT_7=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=43 REMAP_PORT_9=42 REMAP_PORT_10=41 REMAP_PORT_11=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=47 REMAP_PORT_13=46 REMAP_PORT_14=45 REMAP_PORT_15=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=3 REMAP_PORT_17=2 REMAP_PORT_18=1 REMAP_PORT_19=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=7 REMAP_PORT_21=6 REMAP_PORT_22=5 REMAP_PORT_23=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=11 REMAP_PORT_25=10 REMAP_PORT_26=9 REMAP_PORT_27=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=15 REMAP_PORT_29=14 REMAP_PORT_30=13 REMAP_PORT_31=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 REMAP_PORT_33=18 REMAP_PORT_34=17 REMAP_PORT_35=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 REMAP_PORT_37=22 REMAP_PORT_38=21 REMAP_PORT_39=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 REMAP_PORT_41=26 REMAP_PORT_42=25 REMAP_PORT_43=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 REMAP_PORT_45=30 REMAP_PORT_46=29 REMAP_PORT_47=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 prog 06 EE 80 D2 0A 71 08 E0 60 EE E9 D2 05 75 10 81 61 ED 02 00 12 A0 F8 15 67 22 F2 01 D2 40 74 14 3A 80 28 32 08 97 71 2A 77 65 1A 07 71 30 77 3C 1A 02 27 1A 03 27 C7 97 71 5E 77 4A 28 32 00 32 01 B7 26 ED C7 97 75 50 77 65 1A 02 71 50 77 57 32 0E 87 32 0F 87 57 32 0F 87 32 0E 87 57 32 0E 87 32 0E 87 57 32 0F 87 32 0F 87 57 + +led 0 start + +led 1 prog 06 EE 80 D2 0A 71 08 E0 60 EE E9 D2 05 75 10 81 61 ED 02 00 12 A0 F8 15 67 22 F2 01 D2 40 74 14 3A 80 28 32 08 97 71 2A 77 65 1A 07 71 30 77 3C 1A 02 27 1A 03 27 C7 97 71 5E 77 4A 28 32 00 32 01 B7 26 ED C7 97 75 50 77 65 1A 02 71 50 77 57 32 0E 87 32 0F 87 57 32 0F 87 32 0E 87 57 32 0E 87 32 0E 87 57 32 0F 87 32 0F 87 57 + +led 1 start + +led auto on diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/eeprom.py b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/eeprom.py new file mode 100644 index 000000000000..96dcc5975328 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/2-0050/eeprom" + #Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/2-0050/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/sfputil.py b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/sfputil.py new file mode 100644 index 000000000000..33e98016384a --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/sfputil.py @@ -0,0 +1,190 @@ +# 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 = 31 + PORTS_IN_BLOCK = 32 + + EEPROM_OFFSET = 10 + + _port_to_eeprom_mapping = {} + + @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 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): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET) + + 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 + + if port_num > 16: + cpld_addr=33 + else: + cpld_addr=32 + + file_path="/sys/bus/i2c/devices/1-00" + str(cpld_addr) + "/port" + str(port_num) + "/port" + str(port_num) + "_present" + + try: + reg_file = open("file_path") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + + # ModPrsL is active low + 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 > 16: + cpld_addr=33 + else: + cpld_addr=32 + + + file_path="/sys/bus/i2c/devices/1-00" + str(cpld_addr) + "/port" + str(port_num) + "/port" + str(port_num) + "_lpmode" + + try: + reg_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # LPMode is active high + 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 > 16: + cpld_addr=33 + else: + cpld_addr=32 + + file_path="/sys/bus/i2c/devices/1-00" + str(cpld_num) + "/port" + str(port_num) + "/port" + str(port_num) + "_lpmode" + + try: + reg_file = open(file_path, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + # 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 + + if port_num > 16: + cpld_addr=33 + else: + cpld_addr=32 + + file_path="/sys/bus/i2c/devices/1-00" + str(cpld_num) + "/port" + str(port_num) + "/port" + str(port_num) + "_rst" + + try: + reg_file = open(file_path, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # ResetL is active low + reg_value = 0 + + # 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: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = 1 + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/default_sku b/device/pegatron/x86_64-pegatron_porsche-r0/default_sku new file mode 100644 index 000000000000..6b47d90d1cff --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/default_sku @@ -0,0 +1 @@ +porsche t1 diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/installer.conf b/device/pegatron/x86_64-pegatron_porsche-r0/installer.conf new file mode 100755 index 000000000000..14404194ef53 --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/plugins/eeprom.py b/device/pegatron/x86_64-pegatron_porsche-r0/plugins/eeprom.py new file mode 100755 index 000000000000..6964c6bade4f --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/plugins/eeprom.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/4-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/plugins/psuutil.py b/device/pegatron/x86_64-pegatron_porsche-r0/plugins/psuutil.py new file mode 100755 index 000000000000..a23a7b7fe73e --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/plugins/psuutil.py @@ -0,0 +1,92 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_DIR = "/sys/bus/i2c/devices/7-0075" + + def __init__(self): + PsuBase.__init__(self) + + + # Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + + fd.close() + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + attr_file = 'psu_'+str(index)+'_status' + attr_path = self.SYSFS_PSU_DIR +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU status + if (attr_value == 1): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + attr_file = 'psu_'+str(index)+'_present' + attr_path = self.SYSFS_PSU_DIR +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU presence + if (attr_value == 0): + status = 1 + + return status + diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/plugins/sfputil.py b/device/pegatron/x86_64-pegatron_porsche-r0/plugins/sfputil.py new file mode 100755 index 000000000000..28909f00110c --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/plugins/sfputil.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python + +try: + import os + import re + import time + 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 = 53 + ports_in_block = 54 + cplda_sfp_num = 24 + cpldb_sfp_num = 12 + cpldc_sfp_num = 18 + + port_to_eeprom_mapping = {} + port_to_i2c_mapping = {} + sfp_ports = range(0, ports_in_block) + qsfp_ports = range(ports_in_block - 6, ports_in_block) + + + def __init__(self): + for x in range(self.port_start, self.port_end + 1): + if x < self.cpldb_sfp_num: + self.port_to_i2c_mapping.update({x:7}) + elif x < self.cplda_sfp_num + self.cpldb_sfp_num: + self.port_to_i2c_mapping.update({x:6}) + else: + self.port_to_i2c_mapping.update({x:8}) + + for x in range(self.port_start, self.port_end+1): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp'+str(x+1)+'_eeprom' + 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): + if port_num < self.port_start or port_num > self.port_end: + return False + + if port_num < self.cpldb_sfp_num: + presence_path = '/sys/bus/i2c/devices/7-0075/sfp'+str(port_num+1)+'_present' + elif port_num < self.cpldb_sfp_num + self.cplda_sfp_num: + presence_path = '/sys/bus/i2c/devices/6-0074/sfp'+str(port_num+1)+'_present' + else: + presence_path = '/sys/bus/i2c/devices/8-0076/sfp'+str(port_num+1)+'_present' + + try: + file = open(presence_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + value = int(file.readline().rstrip()) + + file.close() + if value == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + if port_num not in self.qsfp_ports: + return False + + lowpower_path = '/sys/bus/i2c/devices/8-0076/sfp'+str(port_num+1)+'_lowpower' + + try: + file = open(lowpower_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + value = int(file.readline().rstrip()) + + file.close() + if value == 1: + return True + + return False + + def set_low_power_mode(self, port_num, lpmode): + if port_num not in self.qsfp_ports: + return False + + lowpower_path = '/sys/bus/i2c/devices/8-0076/sfp'+str(port_num+1)+'_lowpower' + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + value = 1 + else: + value = 0 + + try: + file = open(lowpower_path, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + file.seek(0) + file.write(str(value)) + file.close() + + return True + + def reset(self, port_num): + if port_num not in self.qsfp_ports: + return False + reset_path = '/sys/bus/i2c/devices/8-0076/sfp'+str(port_num+1)+'_reset' + + try: + file = open(reset_path, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + file.seek(0) + file.write(str(2)) + file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + try: + file = open(reset_path, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + file.seek(0) + file.write(str(1)) + file.close() + + return True + + def read_porttab_mappings(self, porttabfile): + logical = [] + logical_to_bcm = {} + logical_to_physical = {} + physical_to_logical = {} + last_fp_port_index = 0 + last_portname = "" + first = 1 + port_pos_in_file = 0 + parse_fmt_port_config_ini = False + + try: + f = open(porttabfile) + except: + raise + + parse_fmt_port_config_ini = (os.path.basename(porttabfile) == "port_config.ini") + + # Read the porttab file and generate dicts + # with mapping for future reference. + # XXX: move the porttab + # parsing stuff to a separate module, or reuse + # if something already exists + for line in f: + line.strip() + if re.search("^#", line) is not None: + continue + + # Parsing logic for 'port_config.ini' file + if (parse_fmt_port_config_ini): + # bcm_port is not explicitly listed in port_config.ini format + # Currently we assume ports are listed in numerical order according to bcm_port + # so we use the port's position in the file (zero-based) as bcm_port + portname = line.split()[0] + + bcm_port = str(port_pos_in_file) + + if len(line.split()) >= 4: + fp_port_index = int(line.split()[3]) + else: + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))/4 + else: # Parsing logic for older 'portmap.ini' file + (portname, bcm_port) = line.split("=")[1].split(",")[:2] + + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))/4 + + if ((len(self.sfp_ports) > 0) and (fp_port_index not in self.sfp_ports)): + continue + + if first == 1: + # Initialize last_[physical|logical]_port + # to the first valid port + last_fp_port_index = fp_port_index + last_portname = portname + first = 0 + + logical.append(portname) + + logical_to_bcm[portname] = "xe" + bcm_port + logical_to_physical[portname] = [fp_port_index] + if physical_to_logical.get(fp_port_index) is None: + physical_to_logical[fp_port_index] = [portname] + else: + physical_to_logical[fp_port_index].append( + portname) + + if (fp_port_index - last_fp_port_index) > 1: + # last port was a gang port + for p in range(last_fp_port_index+1, fp_port_index): + logical_to_physical[last_portname].append(p) + if physical_to_logical.get(p) is None: + physical_to_logical[p] = [last_portname] + else: + physical_to_logical[p].append(last_portname) + + last_fp_port_index = fp_port_index + last_portname = portname + + port_pos_in_file += 1 + + self.logical = logical + self.logical_to_bcm = logical_to_bcm + self.logical_to_physical = logical_to_physical + self.physical_to_logical = physical_to_logical + + """ + print "logical: " + self.logical + print "logical to bcm: " + self.logical_to_bcm + print "logical to physical: " + self.logical_to_physical + print "physical to logical: " + self.physical_to_logical + """ + + + diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/porsche/port_config.ini b/device/pegatron/x86_64-pegatron_porsche-r0/porsche/port_config.ini new file mode 100755 index 000000000000..15fc60375941 --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/porsche/port_config.ini @@ -0,0 +1,55 @@ +#name lanes alias index speed +Ethernet0 8 Ethernet1/1 0 10000 +Ethernet1 9 Ethernet2/1 1 10000 +Ethernet2 10 Ethernet3/1 2 10000 +Ethernet3 11 Ethernet4/1 3 10000 +Ethernet4 12 Ethernet5/1 4 10000 +Ethernet5 13 Ethernet6/1 5 10000 +Ethernet6 14 Ethernet7/1 6 10000 +Ethernet7 15 Ethernet8/1 7 10000 +Ethernet8 16 Ethernet9/1 8 10000 +Ethernet9 17 Ethernet10/1 9 10000 +Ethernet10 18 Ethernet11/1 10 10000 +Ethernet11 19 Ethernet12/1 11 10000 +Ethernet12 20 Ethernet13/1 12 10000 +Ethernet13 21 Ethernet14/1 13 10000 +Ethernet14 22 Ethernet15/1 14 10000 +Ethernet15 23 Ethernet16/1 15 10000 +Ethernet16 32 Ethernet17/1 16 10000 +Ethernet17 33 Ethernet18/1 17 10000 +Ethernet18 34 Ethernet19/1 18 10000 +Ethernet19 35 Ethernet20/1 19 10000 +Ethernet20 40 Ethernet21/1 20 10000 +Ethernet21 41 Ethernet22/1 21 10000 +Ethernet22 42 Ethernet23/1 22 10000 +Ethernet23 43 Ethernet24/1 23 10000 +Ethernet24 48 Ethernet25/1 24 10000 +Ethernet25 49 Ethernet26/1 25 10000 +Ethernet26 50 Ethernet27/1 26 10000 +Ethernet27 51 Ethernet28/1 27 10000 +Ethernet28 56 Ethernet29/1 28 10000 +Ethernet29 57 Ethernet30/1 29 10000 +Ethernet30 58 Ethernet31/1 30 10000 +Ethernet31 59 Ethernet32/1 31 10000 +Ethernet32 64 Ethernet33/1 32 10000 +Ethernet33 65 Ethernet34/1 33 10000 +Ethernet34 66 Ethernet35/1 34 10000 +Ethernet35 67 Ethernet36/1 35 10000 +Ethernet36 68 Ethernet37/1 36 10000 +Ethernet37 69 Ethernet38/1 37 10000 +Ethernet38 70 Ethernet39/1 38 10000 +Ethernet39 71 Ethernet40/1 39 10000 +Ethernet40 72 Ethernet41/1 40 10000 +Ethernet41 73 Ethernet42/1 41 10000 +Ethernet42 74 Ethernet43/1 42 10000 +Ethernet43 75 Ethernet44/1 43 10000 +Ethernet44 76 Ethernet45/1 44 10000 +Ethernet45 77 Ethernet46/1 45 10000 +Ethernet46 78 Ethernet47/1 46 10000 +Ethernet47 79 Ethernet48/1 47 10000 +Ethernet48 80,81,82,83 Ethernet49/1 48 100000 +Ethernet49 84,85,86,87 Ethernet50/1 49 100000 +Ethernet50 104,105,106,107 Ethernet51/1 50 100000 +Ethernet51 108,109,110,111 Ethernet52/1 51 100000 +Ethernet52 112,113,114,115 Ethernet53/1 52 100000 +Ethernet53 116,117,118,119 Ethernet54/1 53 100000 diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/porsche/sai.profile b/device/pegatron/x86_64-pegatron_porsche-r0/porsche/sai.profile new file mode 100755 index 000000000000..f19a366b1cac --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/porsche/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/tau-porsche.cfg +SAI_DSH_CONFIG_FILE=/usr/share/sonic/hwsku/tau-porsche.dsh diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/porsche/tau-porsche.dsh b/device/pegatron/x86_64-pegatron_porsche-r0/porsche/tau-porsche.dsh new file mode 100755 index 000000000000..b370fe83b837 --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/porsche/tau-porsche.dsh @@ -0,0 +1,497 @@ +init start stage unit=0 low-level +init set port-map unit=0 port=0 eth-macro=2 lane=0 max-speed=10g active=true +init set port-map unit=0 port=1 eth-macro=2 lane=1 max-speed=10g active=true +init set port-map unit=0 port=2 eth-macro=2 lane=2 max-speed=10g active=true +init set port-map unit=0 port=3 eth-macro=2 lane=3 max-speed=10g active=true +init set port-map unit=0 port=4 eth-macro=3 lane=0 max-speed=10g active=true +init set port-map unit=0 port=5 eth-macro=3 lane=1 max-speed=10g active=true +init set port-map unit=0 port=6 eth-macro=3 lane=2 max-speed=10g active=true +init set port-map unit=0 port=7 eth-macro=3 lane=3 max-speed=10g active=true +init set port-map unit=0 port=8 eth-macro=4 lane=0 max-speed=10g active=true +init set port-map unit=0 port=9 eth-macro=4 lane=1 max-speed=10g active=true +init set port-map unit=0 port=10 eth-macro=4 lane=2 max-speed=10g active=true +init set port-map unit=0 port=11 eth-macro=4 lane=3 max-speed=10g active=true +init set port-map unit=0 port=12 eth-macro=5 lane=0 max-speed=10g active=true +init set port-map unit=0 port=13 eth-macro=5 lane=1 max-speed=10g active=true +init set port-map unit=0 port=14 eth-macro=5 lane=2 max-speed=10g active=true +init set port-map unit=0 port=15 eth-macro=5 lane=3 max-speed=10g active=true +init set port-map unit=0 port=16 eth-macro=8 lane=0 max-speed=10g active=true +init set port-map unit=0 port=17 eth-macro=8 lane=1 max-speed=10g active=true +init set port-map unit=0 port=18 eth-macro=8 lane=2 max-speed=10g active=true +init set port-map unit=0 port=19 eth-macro=8 lane=3 max-speed=10g active=true +init set port-map unit=0 port=20 eth-macro=10 lane=0 max-speed=10g active=true +init set port-map unit=0 port=21 eth-macro=10 lane=1 max-speed=10g active=true +init set port-map unit=0 port=22 eth-macro=10 lane=2 max-speed=10g active=true +init set port-map unit=0 port=23 eth-macro=10 lane=3 max-speed=10g active=true +init set port-map unit=0 port=24 eth-macro=12 lane=0 max-speed=10g active=true +init set port-map unit=0 port=25 eth-macro=12 lane=1 max-speed=10g active=true +init set port-map unit=0 port=26 eth-macro=12 lane=2 max-speed=10g active=true +init set port-map unit=0 port=27 eth-macro=12 lane=3 max-speed=10g active=true +init set port-map unit=0 port=28 eth-macro=14 lane=0 max-speed=10g active=true +init set port-map unit=0 port=29 eth-macro=14 lane=1 max-speed=10g active=true +init set port-map unit=0 port=30 eth-macro=14 lane=2 max-speed=10g active=true +init set port-map unit=0 port=31 eth-macro=14 lane=3 max-speed=10g active=true +init set port-map unit=0 port=32 eth-macro=16 lane=0 max-speed=10g active=true +init set port-map unit=0 port=33 eth-macro=16 lane=1 max-speed=10g active=true +init set port-map unit=0 port=34 eth-macro=16 lane=2 max-speed=10g active=true +init set port-map unit=0 port=35 eth-macro=16 lane=3 max-speed=10g active=true +init set port-map unit=0 port=36 eth-macro=17 lane=0 max-speed=10g active=true +init set port-map unit=0 port=37 eth-macro=17 lane=1 max-speed=10g active=true +init set port-map unit=0 port=38 eth-macro=17 lane=2 max-speed=10g active=true +init set port-map unit=0 port=39 eth-macro=17 lane=3 max-speed=10g active=true +init set port-map unit=0 port=40 eth-macro=18 lane=0 max-speed=10g active=true +init set port-map unit=0 port=41 eth-macro=18 lane=1 max-speed=10g active=true +init set port-map unit=0 port=42 eth-macro=18 lane=2 max-speed=10g active=true +init set port-map unit=0 port=43 eth-macro=18 lane=3 max-speed=10g active=true +init set port-map unit=0 port=44 eth-macro=19 lane=0 max-speed=10g active=true +init set port-map unit=0 port=45 eth-macro=19 lane=1 max-speed=10g active=true +init set port-map unit=0 port=46 eth-macro=19 lane=2 max-speed=10g active=true +init set port-map unit=0 port=47 eth-macro=19 lane=3 max-speed=10g active=true +init set port-map unit=0 port=48 eth-macro=20 lane=0 max-speed=100g active=true +init set port-map unit=0 port=49 eth-macro=21 lane=0 max-speed=100g active=true +init set port-map unit=0 port=50 eth-macro=26 lane=0 max-speed=100g active=true +init set port-map unit=0 port=51 eth-macro=27 lane=0 max-speed=100g active=true +init set port-map unit=0 port=52 eth-macro=28 lane=0 max-speed=100g active=true +init set port-map unit=0 port=53 eth-macro=29 lane=0 max-speed=100g active=true init-done=true +init start stage unit=0 task-rsrc +init start stage unit=0 module +init start stage unit=0 task +phy set lane-swap unit=0 portlist=0 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=1 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=2 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=3 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=4 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=5 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=6 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=7 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=8 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=9 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=10 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=11 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=12 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=13 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=14 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=15 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=16 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=17 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=18 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=19 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=20 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=21 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=22 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=23 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=24 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=25 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=26 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=27 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=28 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=29 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=30 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=31 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=32 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=33 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=34 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=35 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=36 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=37 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=38 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=39 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=40 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=41 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=42 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=43 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=44 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=45 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=46 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=47 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=48 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=tx data=0x01.02.03.00 +phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=tx data=0x01.02.03.00 +phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=52 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=tx data=0x01.02.03.00 +phy set lane-swap unit=0 portlist=0 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=1 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=2 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=3 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=4 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=5 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=6 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=7 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=8 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=9 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=10 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=11 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=12 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=13 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=14 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=15 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=16 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=17 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=18 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=19 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=20 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=21 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=22 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=23 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=24 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=25 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=26 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=27 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=28 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=29 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=30 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=31 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=32 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=33 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=34 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=35 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=36 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=37 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=38 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=39 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=40 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=41 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=42 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=43 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=44 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=45 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=46 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=47 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=48 lane-cnt=4 property=rx data=0x03.00.01.02 +phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=rx data=0x03.00.01.02 +phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=rx data=0x03.01.02.00 +phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=52 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=rx data=0x00.01.02.03 +phy set polarity-rev unit=0 portlist=0 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=1 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=2 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=3 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=4 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=5 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=6 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=7 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=8 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=9 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=10 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=11 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=12 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=13 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=14 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=15 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=16 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=17 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=18 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=19 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=20 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=21 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=22 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=23 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=24 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=25 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=26 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=27 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=28 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=29 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=30 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=31 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=32 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=33 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=34 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=35 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=36 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=37 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=38 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=39 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=40 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=41 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=42 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=43 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=44 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=45 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=46 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=47 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=48 lane-cnt=4 property=tx data=0x00.01.00.00 +phy set polarity-rev unit=0 portlist=49 lane-cnt=4 property=tx data=0x00.00.01.00 +phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=tx data=0x01.00.01.01 +phy set polarity-rev unit=0 portlist=51 lane-cnt=4 property=tx data=0x01.01.01.01 +phy set polarity-rev unit=0 portlist=52 lane-cnt=4 property=tx data=0x01.00.00.00 +phy set polarity-rev unit=0 portlist=53 lane-cnt=4 property=tx data=0x00.00.01.00 +phy set polarity-rev unit=0 portlist=0 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=1 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=2 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=3 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=4 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=5 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=6 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=7 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=8 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=9 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=10 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=11 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=12 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=13 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=14 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=15 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=16 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=17 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=18 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=19 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=20 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=21 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=22 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=23 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=24 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=25 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=26 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=27 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=28 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=29 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=30 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=31 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=32 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=33 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=34 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=35 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=36 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=37 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=38 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=39 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=40 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=41 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=42 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=43 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=44 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=45 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=46 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=47 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=48 lane-cnt=4 property=rx data=0x00.01.00.00 +phy set polarity-rev unit=0 portlist=49 lane-cnt=4 property=rx data=0x00.00.01.00 +phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=rx data=0x00.00.01.01 +phy set polarity-rev unit=0 portlist=51 lane-cnt=4 property=rx data=0x00.01.00.01 +phy set polarity-rev unit=0 portlist=52 lane-cnt=4 property=rx data=0x00.01.00.01 +phy set polarity-rev unit=0 portlist=53 lane-cnt=4 property=rx data=0x01.01.01.01 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c2 data=0x00 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=cn1 data=0x04 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c0 data=0x1E +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c1 data=0x02 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c2 data=0x00 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=cn1 data=0x04 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c0 data=0x1E +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c1 data=0x02 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c2 data=0x00 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=cn1 data=0x04 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c0 data=0x1E +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c1 data=0x02 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c2 data=0x00 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=cn1 data=0x04 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c0 data=0x1E +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c1 data=0x02 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c0 data=0x1D +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c0 data=0x1D +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c0 data=0x1D +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c0 data=0x1D +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c0 data=0x1A.1A.1A.1A +phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c1 data=0x07.07.07.07 +port set property unit=0 portlist=0-47 speed=10g +port set property unit=0 portlist=0-47 medium-type=sr +port set property unit=0 portlist=48-53 speed=100g +port set property unit=0 portlist=48-53 medium-type=sr4 +port set property unit=0 portlist=0-53 fec=disable +port set property unit=0 portlist=0-53 an=disable +port set property unit=0 portlist=0-53 admin=enable \ No newline at end of file diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/tau-porsche.cfg b/device/pegatron/x86_64-pegatron_porsche-r0/tau-porsche.cfg new file mode 100755 index 000000000000..bbd7c8f80ff5 --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/tau-porsche.cfg @@ -0,0 +1,23 @@ +#This configuration file is for customer init value feature. Please refer to mtk_cfg.h/mtk_cfg.c for detail. +#1. The lines beginning with # are comment lines. The lines beginning with number are the setting lines. +#2. There are five parameters which can be set. +# 1) the first is unit. +# 2) the second is NPS_CFG_TYPE_XXX. Refer to NPS_CFG_TYPE_T. +# 3) the 3-5 are {param0, param1, value} pairs. Refer to NPS_CFG_VALUE_T. Support HEX format. +# 4) the (unit, NPS_CFG_TYPE_XXX, param0, param1) group is the key to get the correspingding value. +# There should be no same (unit, NPS_CFG_TYPE_XXX, param0, param1) group. +#3. User must follow correct format to apply the setting. Please refer to below commentted example(#0 NPS_CFG_TYPE_L2_ADDR_MODE 0 0 1); +#4. Usage under the linux shell: +# 1) ./image-path/image-name -c cfg-path/NPS_Ari_EVB_24.cfg : mamually specify directory path if they are not in current work dirctory. +# 2) ./image-name -c NPS_Ari_EVB_24.cfg : the image and the NPS_Ari_EVB_24.cfg are in the current work directory. + +#unit NPS_CFG_TYPE_XXX param0 param1 value +#---- ---------------- ------ ------ ----- +0 NPS_CFG_TYPE_USE_UNIT_PORT 0 0 1 +0 NPS_CFG_TYPE_LED_CFG 0 0 3 +0 NPS_CFG_TYPE_CPI_PORT_MODE 129 0 1 +0 NPS_CFG_TYPE_CPI_PORT_MODE 130 0 1 +0 NPS_CFG_TYPE_USER_BUF_CTRL 0 0 1 +0 NPS_CFG_TYPE_HASH_L2_FDB_REGION_ENTRY_NUM 0 0 49152 +0 NPS_CFG_TYPE_HASH_L3_WITH_IPV6_PREFIX_64_REGION_ENTRY_NUM 0 0 32768 + diff --git a/device/quanta/x86_64-quanta_ix1b_32x-r0/default_sku b/device/quanta/x86_64-quanta_ix1b_32x-r0/default_sku new file mode 100644 index 000000000000..68cbc0d6058d --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_32x-r0/default_sku @@ -0,0 +1 @@ +Quanta-IX1B-32X t1 diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/port_config.ini b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/port_config.ini new file mode 100755 index 000000000000..4f4f63925d8b --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 65,66,67,68 hundredGigE1 +Ethernet4 69,70,71,72 hundredGigE2 +Ethernet8 73,74,75,76 hundredGigE3 +Ethernet12 77,78,79,80 hundredGigE4 +Ethernet16 45,46,47,48 hundredGigE5 +Ethernet20 41,42,43,44 hundredGigE6 +Ethernet24 53,54,55,56 hundredGigE7 +Ethernet28 49,50,51,52 hundredGigE8 +Ethernet32 61,62,63,64 hundredGigE9 +Ethernet36 57,58,59,60 hundredGigE10 +Ethernet40 37,38,39,40 hundredGigE11 +Ethernet44 33,34,35,36 hundredGigE12 +Ethernet48 81,82,83,84 hundredGigE13 +Ethernet52 85,86,87,88 hundredGigE14 +Ethernet56 89,90,91,92 hundredGigE15 +Ethernet60 93,94,95,96 hundredGigE16 +Ethernet64 97,98,99,100 hundredGigE17 +Ethernet68 101,102,103,104 hundredGigE18 +Ethernet72 105,106,107,108 hundredGigE19 +Ethernet76 109,110,111,112 hundredGigE20 +Ethernet80 29,30,31,32 hundredGigE21 +Ethernet84 25,26,27,28 hundredGigE22 +Ethernet88 5,6,7,8 hundredGigE23 +Ethernet92 1,2,3,4 hundredGigE24 +Ethernet96 13,14,15,16 hundredGigE25 +Ethernet100 9,10,11,12 hundredGigE26 +Ethernet104 21,22,23,24 hundredGigE27 +Ethernet108 17,18,19,20 hundredGigE28 +Ethernet112 113,114,115,116 hundredGigE29 +Ethernet116 117,118,119,120 hundredGigE30 +Ethernet120 121,122,123,124 hundredGigE31 +Ethernet124 125,126,127,128 hundredGigE32 diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/sai.profile b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/sai.profile new file mode 100755 index 000000000000..fbd01105a4f3 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-ix1b-32x100G.config.bcm diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/th-ix1b-32x100G.config.bcm b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/th-ix1b-32x100G.config.bcm new file mode 100644 index 000000000000..051b8ed71e8e --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/th-ix1b-32x100G.config.bcm @@ -0,0 +1,256 @@ +os=unix + +pbmp_xport_xe=0x3fd000000ff4000003fc000001fe +pbmp_oversubscribe=0x3fd000000ff4000003fc000001fe +l2xmsg_mode=1 + +schan_intr_enable=0 + +# Control to disable parity messages +parity_enable=1 + +# Control to disable parity correction +parity_correction=1 + +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 + +l2_mem_entries=40960 +l3_mem_entries=40960 + +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_6=21:100 +portmap_7=25:100 +portmap_8=29:100 +portmap_34=33:100 +portmap_35=37:100 +portmap_36=41:100 +portmap_37=45:100 +portmap_38=49:100 +portmap_39=53:100 +portmap_40=57:100 +portmap_41=61:100 +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_106=113:100 +portmap_107=117:100 +portmap_108=121:100 +portmap_109=125:100 + +portmap_66=129:10 +portmap_100=131:10 +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + + +mem_cache_enable=1 +ctr_evict_enable=0 + +#mdio setting +rate_ext_mdio_divisor=0x2f +mdio_output_delay=15 + +#lanes swap and polarity +xgxs_rx_lane_map_1=0x3120 +phy_xaui_rx_polarity_flip_1=0xa +xgxs_tx_lane_map_1=0x1230 +phy_xaui_tx_polarity_flip_1=0x7 + +xgxs_rx_lane_map_2=0x3120 +phy_xaui_rx_polarity_flip_2=0xc +xgxs_tx_lane_map_2=0x0213 +phy_xaui_tx_polarity_flip_2=0x5 + +xgxs_rx_lane_map_3=0x2013 +phy_xaui_rx_polarity_flip_3=0xb +xgxs_tx_lane_map_3=0x3120 +phy_xaui_tx_polarity_flip_3=0x6 + +xgxs_rx_lane_map_4=0x2103 +phy_xaui_rx_polarity_flip_4=0xf +xgxs_tx_lane_map_4=0x3201 +phy_xaui_tx_polarity_flip_4=0x5 + +xgxs_rx_lane_map_5=0x1032 +phy_xaui_rx_polarity_flip_5=0x7 +xgxs_tx_lane_map_5=0x1302 +phy_xaui_tx_polarity_flip_5=0x0 + +xgxs_rx_lane_map_6=0x2103 +phy_xaui_rx_polarity_flip_6=0x3 +xgxs_tx_lane_map_6=0x3120 +phy_xaui_tx_polarity_flip_6=0x2 + +xgxs_rx_lane_map_7=0x0123 +phy_xaui_rx_polarity_flip_7=0x5 +xgxs_tx_lane_map_7=0x3012 +phy_xaui_tx_polarity_flip_7=0x3 + +xgxs_rx_lane_map_8=0x1032 +phy_xaui_rx_polarity_flip_8=0xf +xgxs_tx_lane_map_8=0x3120 +phy_xaui_tx_polarity_flip_8=0x2 + +xgxs_rx_lane_map_34=0x3021 +phy_xaui_rx_polarity_flip_34=0xa +xgxs_tx_lane_map_34=0x3210 +phy_xaui_tx_polarity_flip_34=0xf + +xgxs_rx_lane_map_35=0x2103 +phy_xaui_rx_polarity_flip_35=0x6 +xgxs_tx_lane_map_35=0x3120 +phy_xaui_tx_polarity_flip_35=0x5 + +xgxs_rx_lane_map_36=0x0312 +phy_xaui_rx_polarity_flip_36=0x4 +xgxs_tx_lane_map_36=0x3210 +phy_xaui_tx_polarity_flip_36=0x2 + +xgxs_rx_lane_map_37=0x0231 +phy_xaui_rx_polarity_flip_37=0x4 +xgxs_tx_lane_map_37=0x1032 +phy_xaui_tx_polarity_flip_37=0x2 + +xgxs_rx_lane_map_38=0x3012 +phy_xaui_rx_polarity_flip_38=0xa +xgxs_tx_lane_map_38=0x2103 +phy_xaui_tx_polarity_flip_38=0xd + +xgxs_rx_lane_map_39=0x0123 +phy_xaui_rx_polarity_flip_39=0x9 +xgxs_tx_lane_map_39=0x3120 +phy_xaui_tx_polarity_flip_39=0xd + +xgxs_rx_lane_map_40=0x2310 +phy_xaui_rx_polarity_flip_40=0x6 +xgxs_tx_lane_map_40=0x0123 + +xgxs_rx_lane_map_41=0x1230 +phy_xaui_rx_polarity_flip_41=0xa +xgxs_tx_lane_map_41=0x0123 +phy_xaui_tx_polarity_flip_41=0xe + +xgxs_rx_lane_map_68=0x1230 +phy_xaui_rx_polarity_flip_68=0xb +xgxs_tx_lane_map_68=0x3012 +phy_xaui_tx_polarity_flip_68=0xa + +xgxs_rx_lane_map_69=0x2310 +phy_xaui_rx_polarity_flip_69=0xf +xgxs_tx_lane_map_69=0x3120 +phy_xaui_tx_polarity_flip_69=0x2 + +xgxs_rx_lane_map_70=0x2310 +phy_xaui_rx_polarity_flip_70=0xe +xgxs_tx_lane_map_70=0x0213 +phy_xaui_tx_polarity_flip_70=0x2 + +xgxs_rx_lane_map_71=0x2130 +phy_xaui_rx_polarity_flip_71=0x5 +xgxs_tx_lane_map_71=0x3210 + +phy_xaui_rx_polarity_flip_72=0xa +xgxs_tx_lane_map_72=0x1230 + +xgxs_rx_lane_map_73=0x0213 +phy_xaui_rx_polarity_flip_73=0x5 +xgxs_tx_lane_map_73=0x1320 +phy_xaui_tx_polarity_flip_73=0x3 + +xgxs_rx_lane_map_74=0x2310 +phy_xaui_rx_polarity_flip_74=0xe +xgxs_tx_lane_map_74=0x2310 +phy_xaui_tx_polarity_flip_74=0xc + +xgxs_rx_lane_map_75=0x0321 +xgxs_tx_lane_map_75=0x2130 +phy_xaui_tx_polarity_flip_75=0x6 + +xgxs_rx_lane_map_102=0x1302 +phy_xaui_rx_polarity_flip_102=0x4 +xgxs_tx_lane_map_102=0x0123 +phy_xaui_tx_polarity_flip_102=0xa + +xgxs_tx_lane_map_103=0x2130 +phy_xaui_tx_polarity_flip_103=0x8 + +xgxs_rx_lane_map_104=0x1302 +phy_xaui_rx_polarity_flip_104=0xd +xgxs_tx_lane_map_104=0x1302 +phy_xaui_tx_polarity_flip_104=0x2 + +xgxs_rx_lane_map_105=0x1230 +phy_xaui_rx_polarity_flip_105=0x8 +xgxs_tx_lane_map_105=0x1320 + +xgxs_rx_lane_map_106=0x3120 +phy_xaui_rx_polarity_flip_106=0xc +xgxs_tx_lane_map_106=0x3120 +phy_xaui_tx_polarity_flip_106=0x0 + +xgxs_rx_lane_map_107=0x0321 +phy_xaui_rx_polarity_flip_107=0xa +xgxs_tx_lane_map_107=0x1032 +phy_xaui_tx_polarity_flip_107=0xf + +xgxs_rx_lane_map_108=0x0321 +phy_xaui_rx_polarity_flip_108=0xf +xgxs_tx_lane_map_108=0x3210 +phy_xaui_tx_polarity_flip_108=0x0 + +xgxs_rx_lane_map_109=0x0321 +phy_xaui_rx_polarity_flip_109=0xa +xgxs_tx_lane_map_109=0x3021 +phy_xaui_tx_polarity_flip_109=0x3 + +dport_map_port_68=1 +dport_map_port_69=2 +dport_map_port_70=3 +dport_map_port_71=4 +dport_map_port_37=5 +dport_map_port_36=6 +dport_map_port_39=7 +dport_map_port_38=8 +dport_map_port_41=9 +dport_map_port_40=10 +dport_map_port_35=11 +dport_map_port_34=12 +dport_map_port_72=13 +dport_map_port_73=14 +dport_map_port_74=15 +dport_map_port_75=16 +dport_map_port_102=17 +dport_map_port_103=18 +dport_map_port_104=19 +dport_map_port_105=20 +dport_map_port_8=21 +dport_map_port_7=22 +dport_map_port_2=23 +dport_map_port_1=24 +dport_map_port_4=25 +dport_map_port_3=26 +dport_map_port_6=27 +dport_map_port_5=28 +dport_map_port_106=29 +dport_map_port_107=30 +dport_map_port_108=31 +dport_map_port_109=32 +dport_map_port_66=33 +dport_map_port_100=34 + diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/installer.conf b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/installer.conf new file mode 100755 index 000000000000..14404194ef53 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/led_proc_init.soc b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/led_proc_init.soc new file mode 100755 index 000000000000..831f74df7557 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/led_proc_init.soc @@ -0,0 +1,10 @@ +led 0 stop +led 1 stop + +led 0 prog 02 00 60 E2 D2 40 71 12 12 F0 85 05 D2 0A 71 19 52 00 67 1B 06 E2 80 77 02 3A 80 67 20 67 2E 57 06 E2 12 00 F0 80 F8 15 1A 00 75 4E 77 52 06 E2 F0 12 00 F8 15 1A 00 75 3B 77 46 06 E2 F0 12 00 F8 15 1A 01 75 4E 16 F0 DA 05 75 4E 77 52 32 0F 87 57 32 0E 87 57 00 00 00 00 00 00 00 00 00 00 +led 1 prog 02 00 60 E2 D2 40 71 12 12 F0 85 05 D2 0A 71 19 52 00 67 1B 06 E2 80 77 02 3A 80 67 20 67 2E 57 06 E2 12 00 F0 80 F8 15 1A 00 75 4E 77 52 06 E2 F0 12 00 F8 15 1A 00 75 3B 77 46 06 E2 F0 12 00 F8 15 1A 01 75 4E 16 F0 DA 05 75 4E 77 52 32 0F 87 57 32 0E 87 57 00 00 00 00 00 00 00 00 00 00 + +led 0 auto on +led 1 auto on +led 0 start +led 1 start \ No newline at end of file diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/minigraph.xml b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/minigraph.xml new file mode 100755 index 000000000000..9d348f0051ba --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/minigraph.xml @@ -0,0 +1,1074 @@ + + + + + + ARISTA01T0 + 10.0.0.33 + sonic + 10.0.0.32 + 1 + 180 + 60 + + + sonic + 10.0.0.0 + ARISTA01T2 + 10.0.0.1 + 1 + 180 + 60 + + + ARISTA02T0 + 10.0.0.35 + sonic + 10.0.0.34 + 1 + 180 + 60 + + + sonic + 10.0.0.2 + ARISTA02T2 + 10.0.0.3 + 1 + 180 + 60 + + + ARISTA03T0 + 10.0.0.37 + sonic + 10.0.0.36 + 1 + 180 + 60 + + + sonic + 10.0.0.4 + ARISTA03T2 + 10.0.0.5 + 1 + 180 + 60 + + + ARISTA04T0 + 10.0.0.39 + sonic + 10.0.0.38 + 1 + 180 + 60 + + + sonic + 10.0.0.6 + ARISTA04T2 + 10.0.0.7 + 1 + 180 + 60 + + + ARISTA05T0 + 10.0.0.41 + sonic + 10.0.0.40 + 1 + 180 + 60 + + + sonic + 10.0.0.8 + ARISTA05T2 + 10.0.0.9 + 1 + 180 + 60 + + + ARISTA06T0 + 10.0.0.43 + sonic + 10.0.0.42 + 1 + 180 + 60 + + + sonic + 10.0.0.10 + ARISTA06T2 + 10.0.0.11 + 1 + 180 + 60 + + + ARISTA07T0 + 10.0.0.45 + sonic + 10.0.0.44 + 1 + 180 + 60 + + + sonic + 10.0.0.12 + ARISTA07T2 + 10.0.0.13 + 1 + 180 + 60 + + + ARISTA08T0 + 10.0.0.47 + sonic + 10.0.0.46 + 1 + 180 + 60 + + + sonic + 10.0.0.14 + ARISTA08T2 + 10.0.0.15 + 1 + 180 + 60 + + + ARISTA09T0 + 10.0.0.49 + sonic + 10.0.0.48 + 1 + 180 + 60 + + + sonic + 10.0.0.16 + ARISTA09T2 + 10.0.0.17 + 1 + 180 + 60 + + + ARISTA10T0 + 10.0.0.51 + sonic + 10.0.0.50 + 1 + 180 + 60 + + + sonic + 10.0.0.18 + ARISTA10T2 + 10.0.0.19 + 1 + 180 + 60 + + + ARISTA11T0 + 10.0.0.53 + sonic + 10.0.0.52 + 1 + 180 + 60 + + + sonic + 10.0.0.20 + ARISTA11T2 + 10.0.0.21 + 1 + 180 + 60 + + + ARISTA12T0 + 10.0.0.55 + sonic + 10.0.0.54 + 1 + 180 + 60 + + + sonic + 10.0.0.22 + ARISTA12T2 + 10.0.0.23 + 1 + 180 + 60 + + + ARISTA13T0 + 10.0.0.57 + sonic + 10.0.0.56 + 1 + 180 + 60 + + + sonic + 10.0.0.24 + ARISTA13T2 + 10.0.0.25 + 1 + 180 + 60 + + + ARISTA14T0 + 10.0.0.59 + sonic + 10.0.0.58 + 1 + 180 + 60 + + + sonic + 10.0.0.26 + ARISTA14T2 + 10.0.0.27 + 1 + 180 + 60 + + + ARISTA15T0 + 10.0.0.61 + sonic + 10.0.0.60 + 1 + 180 + 60 + + + sonic + 10.0.0.28 + ARISTA15T2 + 10.0.0.29 + 1 + 180 + 60 + + + ARISTA16T0 + 10.0.0.63 + sonic + 10.0.0.62 + 1 + 180 + 60 + + + sonic + 10.0.0.30 + ARISTA16T2 + 10.0.0.31 + 1 + 180 + 60 + + + + + 65100 + sonic + + +
10.0.0.33
+ + +
+ +
10.0.0.1
+ + +
+ +
10.0.0.35
+ + +
+ +
10.0.0.3
+ + +
+ +
10.0.0.37
+ + +
+ +
10.0.0.5
+ + +
+ +
10.0.0.39
+ + +
+ +
10.0.0.7
+ + +
+ +
10.0.0.41
+ + +
+ +
10.0.0.9
+ + +
+ +
10.0.0.43
+ + +
+ +
10.0.0.11
+ + +
+ +
10.0.0.45
+ + +
+ +
10.0.0.13
+ + +
+ +
10.0.0.47
+ + +
+ +
10.0.0.15
+ + +
+ +
10.0.0.49
+ + +
+ +
10.0.0.17
+ + +
+ +
10.0.0.51
+ + +
+ +
10.0.0.19
+ + +
+ +
10.0.0.53
+ + +
+ +
10.0.0.21
+ + +
+ +
10.0.0.55
+ + +
+ +
10.0.0.23
+ + +
+ +
10.0.0.57
+ + +
+ +
10.0.0.25
+ + +
+ +
10.0.0.59
+ + +
+ +
10.0.0.27
+ + +
+ +
10.0.0.61
+ + +
+ +
10.0.0.29
+ + +
+ +
10.0.0.63
+ + +
+ +
10.0.0.31
+ + +
+
+ +
+ + 64001 + ARISTA01T0 + + + + 65200 + ARISTA01T2 + + + + 64002 + ARISTA02T0 + + + + 65200 + ARISTA02T2 + + + + 64003 + ARISTA03T0 + + + + 65200 + ARISTA03T2 + + + + 64004 + ARISTA04T0 + + + + 65200 + ARISTA04T2 + + + + 64005 + ARISTA05T0 + + + + 65200 + ARISTA05T2 + + + + 64006 + ARISTA06T0 + + + + 65200 + ARISTA06T2 + + + + 64007 + ARISTA07T0 + + + + 65200 + ARISTA07T2 + + + + 64008 + ARISTA08T0 + + + + 65200 + ARISTA08T2 + + + + 64009 + ARISTA09T0 + + + + 65200 + ARISTA09T2 + + + + 64010 + ARISTA10T0 + + + + 65200 + ARISTA10T2 + + + + 64011 + ARISTA11T0 + + + + 65200 + ARISTA11T2 + + + + 64012 + ARISTA12T0 + + + + 65200 + ARISTA12T2 + + + + 64013 + ARISTA13T0 + + + + 65200 + ARISTA13T2 + + + + 64014 + ARISTA14T0 + + + + 65200 + ARISTA14T2 + + + + 64015 + ARISTA15T0 + + + + 65200 + ARISTA15T2 + + + + 64016 + ARISTA16T0 + + + + 65200 + ARISTA16T2 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + + + + + + sonic + + + + + + Ethernet0 + 10.0.0.0/31 + + + + Ethernet4 + 10.0.0.2/31 + + + + Ethernet8 + 10.0.0.4/31 + + + + Ethernet12 + 10.0.0.6/31 + + + + Ethernet16 + 10.0.0.8/31 + + + + Ethernet20 + 10.0.0.10/31 + + + + Ethernet24 + 10.0.0.12/31 + + + + Ethernet28 + 10.0.0.14/31 + + + + Ethernet32 + 10.0.0.16/31 + + + + Ethernet36 + 10.0.0.18/31 + + + + Ethernet40 + 10.0.0.20/31 + + + + Ethernet44 + 10.0.0.22/31 + + + + Ethernet48 + 10.0.0.24/31 + + + + Ethernet52 + 10.0.0.26/31 + + + + Ethernet56 + 10.0.0.28/31 + + + + Ethernet60 + 10.0.0.30/31 + + + + Ethernet64 + 10.0.0.32/31 + + + + Ethernet68 + 10.0.0.34/31 + + + + Ethernet72 + 10.0.0.36/31 + + + + Ethernet76 + 10.0.0.38/31 + + + + Ethernet80 + 10.0.0.40/31 + + + + Ethernet84 + 10.0.0.42/31 + + + + Ethernet88 + 10.0.0.44/31 + + + + Ethernet92 + 10.0.0.46/31 + + + + Ethernet96 + 10.0.0.48/31 + + + + Ethernet100 + 10.0.0.50/31 + + + + Ethernet104 + 10.0.0.52/31 + + + + Ethernet108 + 10.0.0.54/31 + + + + Ethernet112 + 10.0.0.56/31 + + + + Ethernet116 + 10.0.0.58/31 + + + + Ethernet120 + 10.0.0.60/31 + + + + Ethernet124 + 10.0.0.62/31 + + + + + + + + + + + + DeviceInterfaceLink + sonic + Ethernet0 + ARISTA01T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet4 + ARISTA02T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet8 + ARISTA03T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet12 + ARISTA04T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet16 + ARISTA05T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet20 + ARISTA06T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet24 + ARISTA07T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet28 + ARISTA08T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet32 + ARISTA09T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet36 + ARISTA10T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet40 + ARISTA11T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet44 + ARISTA12T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet48 + ARISTA13T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet52 + ARISTA14T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet56 + ARISTA15T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet60 + ARISTA16T2 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet64 + ARISTA01T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet68 + ARISTA02T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet72 + ARISTA03T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet76 + ARISTA04T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet80 + ARISTA05T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet84 + ARISTA06T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet88 + ARISTA07T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet92 + ARISTA08T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet96 + ARISTA09T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet100 + ARISTA10T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet104 + ARISTA11T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet108 + ARISTA12T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet112 + ARISTA13T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet116 + ARISTA14T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet120 + ARISTA15T0 + Ethernet1 + + + DeviceInterfaceLink + sonic + Ethernet124 + ARISTA16T0 + Ethernet1 + + + + + sonic + Quanta-IX1B-32X + + + + + + + sonic + + + DhcpResources + + + + + NtpResources + + 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org + + + SyslogResources + + + + + + + + + sonic + Quanta-IX1B-32X +
diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/eeprom.py b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/eeprom.py new file mode 100755 index 000000000000..989f7fe50794 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/eeprom.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/22-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/psuutil.py b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/psuutil.py new file mode 100755 index 000000000000..1986aa846c5e --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/psuutil.py @@ -0,0 +1,170 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path +import subprocess +import logging + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +DEBUG = False + +def show_log(txt): + if DEBUG == True: + print("[IX2]"+txt) + return + +def exec_cmd(cmd, show): + logging.info('Run :'+cmd) + try: + output = subprocess.check_output(cmd, shell=True) + show_log (cmd +"output:"+str(output)) + except subprocess.CalledProcessError as e: + logging.info("Failed :"+cmd) + if show: + print("Failed :"+cmd +"returncode = {}, err msg: {}".format(e.returncode, e.output)) + return output + +def my_log(txt): + if DEBUG == True: + print("[QUANTA DBG]: "+txt) + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + try: + output = subprocess.check_output(cmd, shell=True) + my_log (cmd +"output:"+str(output)) + except subprocess.CalledProcessError as e: + logging.info('Failed :'+cmd) + if show: + print("Failed :"+cmd +"returncode = {}, err msg: {}".format(e.returncode, e.output)) + return output + +def gpio16_exist(): + ls = log_os_system("ls /sys/class/gpio/ | grep gpio16", 0) + logging.info('mods:'+ls) + if len(ls) ==0: + return False + +def gpio17_exist(): + ls = log_os_system("ls /sys/class/gpio/ | grep gpio17", 0) + logging.info('mods:'+ls) + if len(ls) ==0: + return False + +def gpio19_exist(): + ls = log_os_system("ls /sys/class/gpio/ | grep gpio19", 0) + logging.info('mods:'+ls) + if len(ls) ==0: + return False + +def gpio20_exist(): + ls = log_os_system("ls /sys/class/gpio/ | grep gpio20", 0) + logging.info('mods:'+ls) + if len(ls) ==0: + return False + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_PRESENT_DIR = ["/sys/class/gpio/gpio16", + "/sys/class/gpio/gpio19"] + + SYSFS_PSU_POWERGOOD_DIR = ["/sys/class/gpio/gpio17", + "/sys/class/gpio/gpio20"] + def __init__(self): + PsuBase.__init__(self) + + if gpio16_exist() == False: + output = exec_cmd("echo 16 > /sys/class/gpio/export ", 1) + output = exec_cmd("echo in > /sys/class/gpio/gpio16/direction ", 1) + + if gpio17_exist() == False: + output = exec_cmd("echo 17 > /sys/class/gpio/export ", 1) + output = exec_cmd("echo in > /sys/class/gpio/gpio17/direction ", 1) + + if gpio19_exist() == False: + output = exec_cmd("echo 19 > /sys/class/gpio/export ", 1) + output = exec_cmd("echo in > /sys/class/gpio/gpio19/direction ", 1) + + if gpio20_exist() == False: + output = exec_cmd("echo 20 > /sys/class/gpio/export ", 1) + output = exec_cmd("echo in > /sys/class/gpio/gpio20/direction ", 1) + + # Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + attr_file = 'value' + attr_path = self.SYSFS_PSU_POWERGOOD_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU status + if (attr_value == 1): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_absent = 0 + attr_file ='value' + attr_path = self.SYSFS_PSU_PRESENT_DIR[index-1] +'/' + attr_file + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + # Check for PSU presence + if (attr_value == 0): + status = 1 + + return status + diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/sfputil.py b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/sfputil.py new file mode 100755 index 000000000000..851f4b90277d --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/sfputil.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + _port_start = 0 + _port_end = 31 + ports_in_block = 32 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 1 : 32, + 2 : 33, + 3 : 34, + 4 : 35, + 5 : 36, + 6 : 37, + 7 : 38, + 8 : 39, + 9 : 40, + 10 : 41, + 11 : 42, + 12 : 43, + 13 : 44, + 14 : 45, + 15 : 46, + 16 : 47, + 17 : 48, + 18 : 49, + 19 : 50, + 20 : 51, + 21 : 52, + 22 : 53, + 23 : 54, + 24 : 55, + 25 : 56, + 26 : 57, + 27 : 58, + 28 : 59, + 29 : 60, + 30 : 61, + 31 : 62, + 32 : 63, + } + + _qsfp_ports = range(0, ports_in_block + 1) + + 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+1]) + self._port_to_eeprom_mapping[x] = port_eeprom_path + SfpUtilBase.__init__(self) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/cpld-qsfp28/port-"+str(port_num+1)+"/reset", "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("/sys/class/cpld-qsfp28/port-"+str(port_num+1)+"/reset", "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 + + 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/cpld-qsfp28/port-"+str(port_num+1)+"/lpmode", "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 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/cpld-qsfp28/port-"+str(port_num+1)+"/lpmode") + 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 False + + return True + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + #path = "/sys/class/cpld-qsfp28/port-{0}/module_present" + #port_ps = path.format(self.port_to_i2c_mapping[port_num+1]) + + try: + reg_file = open("/sys/class/cpld-qsfp28/port-"+str(port_num+1)+"/module_present") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return range(0, self.ports_in_block + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError + + diff --git a/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/buffers.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/buffers.json.j2 new file mode 100644 index 000000000000..551f73ca0477 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/buffers.json.j2 @@ -0,0 +1,128 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_speed = '100G' %} +{% set default_ports_num = 32 -%} + +{# 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' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- 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 -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- 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 -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(0,default_ports_num) %} + {% if PORT.append("Ethernet%d" % (port_idx*4)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + }, + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "8072396", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xon":"18432", + "xoff":"40560", + "size":"41808", + "dynamic_th":"-4", + "xon_offset":"2496" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/lanemap.ini b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/lanemap.ini new file mode 100644 index 000000000000..16a4d5b9ac78 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/lanemap.ini @@ -0,0 +1,34 @@ +; comment +# comment +eth1:29,30,31,32 +eth2:25,26,27,28 +eth3:37,38,39,40 +eth4:33,34,35,36 +eth5:41,42,43,44 +eth6:45,46,47,48 +eth7:5,6,7,8 +eth8:1,2,3,4 +eth9:9,10,11,12 +eth10:13,14,15,16 +eth11:21,22,23,24 +eth12:17,18,19,20 +eth13:49,50,51,52 +eth14:53,54,55,56 +eth15:61,62,63,64 +eth16:57,58,59,60 +eth17:65,66,67,68 +eth18:69,70,71,72 +eth19:77,78,79,80 +eth20:73,74,75,76 +eth21:105,106,107,108 +eth22:109,110,111,112 +eth23:117,118,119,120 +eth24:113,114,115,116 +eth25:121,122,123,124 +eth26:125,126,127,128 +eth27:85,86,87,88 +eth28:81,82,83,84 +eth29:89,90,91,92 +eth30:93,94,95,96 +eth31:97,98,99,100 +eth32:101,102,103,104 diff --git a/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/pg_profile_lookup.ini b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/pg_profile_lookup.ini new file mode 100644 index 000000000000..3b2a417cebcd --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -4 2288 + 25000 5m 1248 2288 53248 -4 2288 + 40000 5m 1248 2288 66560 -4 2288 + 50000 5m 1248 2288 90272 -4 2288 + 100000 5m 1248 2288 165568 -4 2288 + 10000 40m 1248 2288 37024 -4 2288 + 25000 40m 1248 2288 53248 -4 2288 + 40000 40m 1248 2288 71552 -4 2288 + 50000 40m 1248 2288 96096 -4 2288 + 100000 40m 1248 2288 177632 -4 2288 + 10000 300m 1248 2288 46176 -4 2288 + 25000 300m 1248 2288 79040 -4 2288 + 40000 300m 1248 2288 108160 -4 2288 + 50000 300m 1248 2288 141856 -4 2288 + 100000 300m 1248 2288 268736 -4 2288 diff --git a/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/port_config.ini b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/port_config.ini new file mode 100644 index 000000000000..06898f1d7964 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 29,30,31,32 fortyGigE0/0 +Ethernet4 25,26,27,28 fortyGigE0/4 +Ethernet8 37,38,39,40 fortyGigE0/8 +Ethernet12 33,34,35,36 fortyGigE0/12 +Ethernet16 41,42,43,44 fortyGigE0/16 +Ethernet20 45,46,47,48 fortyGigE0/20 +Ethernet24 5,6,7,8 fortyGigE0/24 +Ethernet28 1,2,3,4 fortyGigE0/28 +Ethernet32 9,10,11,12 fortyGigE0/32 +Ethernet36 13,14,15,16 fortyGigE0/36 +Ethernet40 21,22,23,24 fortyGigE0/40 +Ethernet44 17,18,19,20 fortyGigE0/44 +Ethernet48 49,50,51,52 fortyGigE0/48 +Ethernet52 53,54,55,56 fortyGigE0/52 +Ethernet56 61,62,63,64 fortyGigE0/56 +Ethernet60 57,58,59,60 fortyGigE0/60 +Ethernet64 65,66,67,68 fortyGigE0/64 +Ethernet68 69,70,71,72 fortyGigE0/68 +Ethernet72 77,78,79,80 fortyGigE0/72 +Ethernet76 73,74,75,76 fortyGigE0/76 +Ethernet80 105,106,107,108 fortyGigE0/80 +Ethernet84 109,110,111,112 fortyGigE0/84 +Ethernet88 117,118,119,120 fortyGigE0/88 +Ethernet92 113,114,115,116 fortyGigE0/92 +Ethernet96 121,122,123,124 fortyGigE0/96 +Ethernet100 125,126,127,128 fortyGigE0/100 +Ethernet104 85,86,87,88 fortyGigE0/104 +Ethernet108 81,82,83,84 fortyGigE0/108 +Ethernet112 89,90,91,92 fortyGigE0/112 +Ethernet116 93,94,95,96 fortyGigE0/116 +Ethernet120 97,98,99,100 fortyGigE0/120 +Ethernet124 101,102,103,104 fortyGigE0/124 diff --git a/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/qos.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/sai.profile b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/sai.profile new file mode 100644 index 000000000000..bfc466f27e54 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/sai.profile @@ -0,0 +1,5 @@ +SAI_WARM_BOOT_READ_FILE=/var/cache/sai_warmboot.bin +SAI_WARM_BOOT_WRITE_FILE=/var/cache/sai_warmboot.bin +SAI_VS_SWITCH_TYPE=SAI_VS_SWITCH_TYPE_BCM56850 +SAI_VS_HOSTIF_USE_TAP_DEVICE=true +SAI_VS_INTERFACE_LANE_MAP_FILE=/usr/share/sonic/hwsku/lanemap.ini diff --git a/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/td2-s6000-32x40G.config.bcm b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/td2-s6000-32x40G.config.bcm new file mode 100644 index 000000000000..068b587202bd --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/Force10-S6000/td2-s6000-32x40G.config.bcm @@ -0,0 +1,646 @@ +# Old LPM only configuration +# l2_mem_entries=163840 +# l3_mem_entries=90112 +# l3_alpm_enable=0 +# ipv6_lpm_128b_enable=0 +# +# ALPM enable +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l2_mem_entries=32768 +l3_mem_entries=16384 + +# From old config file +os=unix +higig2_hdr_mode=1 + +# Parity +parity_correction=1 +parity_enable=1 +stat_if_parity_enable=0 + +# +bcm_num_cos=8 +bcm_stat_interval=2000000 +l2xmsg_hostbuf_size=8192 +l2xmsg_mode=1 +lls_num_l2uc=12 +max_vp_lags=0 +miim_intr_enable=0 +mmu_lossless=0 +module_64ports=0 +schan_intr_enable=0 +stable_size=0x2000000 +tdma_timeout_usec=5000000 + +pbmp_oversubscribe=0x000007fffffffffffffffffffffffffe +pbmp_xport_xe=0x000007fffffffffffffffffffffffffe + +# Ports configuration +# xe0 (40G) +portmap_1=29:40 +xgxs_rx_lane_map_1=0x213 +xgxs_tx_lane_map_1=0x213 +phy_xaui_rx_polarity_flip_1=0xc +phy_xaui_tx_polarity_flip_1=0x9 +serdes_driver_current_lane0_xe0=0x6 +serdes_driver_current_lane1_xe0=0x7 +serdes_driver_current_lane2_xe0=0x6 +serdes_driver_current_lane3_xe0=0x6 +serdes_pre_driver_current_lane0_xe0=0x6 +serdes_pre_driver_current_lane1_xe0=0x7 +serdes_pre_driver_current_lane2_xe0=0x6 +serdes_pre_driver_current_lane3_xe0=0x6 +serdes_preemphasis_lane0_xe0=0xc2f0 +serdes_preemphasis_lane1_xe0=0xd2b0 +serdes_preemphasis_lane2_xe0=0xc6e0 +serdes_preemphasis_lane3_xe0=0xc2f0 + +# xe1 (40G) +portmap_2=25:40 +xgxs_rx_lane_map_2=0x213 +xgxs_tx_lane_map_2=0x2031 +phy_xaui_rx_polarity_flip_2=0xe +phy_xaui_tx_polarity_flip_2=0x2 +serdes_driver_current_lane0_xe1=0x5 +serdes_driver_current_lane1_xe1=0x5 +serdes_driver_current_lane2_xe1=0x5 +serdes_driver_current_lane3_xe1=0x5 +serdes_pre_driver_current_lane0_xe1=0x5 +serdes_pre_driver_current_lane1_xe1=0x5 +serdes_pre_driver_current_lane2_xe1=0x5 +serdes_pre_driver_current_lane3_xe1=0x5 +serdes_preemphasis_lane0_xe1=0xcad0 +serdes_preemphasis_lane1_xe1=0xc6e0 +serdes_preemphasis_lane2_xe1=0xc6e0 +serdes_preemphasis_lane3_xe1=0xd2b0 + +# xe2 (40G) +portmap_3=37:40 +xgxs_rx_lane_map_3=0x213 +xgxs_tx_lane_map_3=0x1203 +phy_xaui_rx_polarity_flip_3=0x3 +phy_xaui_tx_polarity_flip_3=0xe +serdes_driver_current_lane0_xe2=0x4 +serdes_driver_current_lane1_xe2=0x4 +serdes_driver_current_lane2_xe2=0x4 +serdes_driver_current_lane3_xe2=0x4 +serdes_pre_driver_current_lane0_xe2=0x4 +serdes_pre_driver_current_lane1_xe2=0x4 +serdes_pre_driver_current_lane2_xe2=0x4 +serdes_pre_driver_current_lane3_xe2=0x4 +serdes_preemphasis_lane0_xe2=0xcad0 +serdes_preemphasis_lane1_xe2=0xcad0 +serdes_preemphasis_lane2_xe2=0xc2f0 +serdes_preemphasis_lane3_xe2=0xc2f0 + +# xe3 (40G) +portmap_4=33:40 +xgxs_rx_lane_map_4=0x213 +xgxs_tx_lane_map_4=0x132 +phy_xaui_rx_polarity_flip_4=0xe +phy_xaui_tx_polarity_flip_4=0x2 +serdes_driver_current_lane0_xe3=0x4 +serdes_driver_current_lane1_xe3=0x4 +serdes_driver_current_lane2_xe3=0x4 +serdes_driver_current_lane3_xe3=0x4 +serdes_pre_driver_current_lane0_xe3=0x4 +serdes_pre_driver_current_lane1_xe3=0x4 +serdes_pre_driver_current_lane2_xe3=0x4 +serdes_pre_driver_current_lane3_xe3=0x4 +serdes_preemphasis_lane0_xe3=0xc6e0 +serdes_preemphasis_lane1_xe3=0xc6e0 +serdes_preemphasis_lane2_xe3=0xc6e0 +serdes_preemphasis_lane3_xe3=0xc6e0 + +# xe4 (40G) +portmap_5=41:40 +xgxs_rx_lane_map_5=0x213 +xgxs_tx_lane_map_5=0x3021 +phy_xaui_rx_polarity_flip_5=0x3 +phy_xaui_tx_polarity_flip_5=0xb +serdes_driver_current_lane0_xe4=0x4 +serdes_driver_current_lane1_xe4=0x4 +serdes_driver_current_lane2_xe4=0x4 +serdes_driver_current_lane3_xe4=0x4 +serdes_pre_driver_current_lane0_xe4=0x4 +serdes_pre_driver_current_lane1_xe4=0x4 +serdes_pre_driver_current_lane2_xe4=0x4 +serdes_pre_driver_current_lane3_xe4=0x4 +serdes_preemphasis_lane0_xe4=0xc6e0 +serdes_preemphasis_lane1_xe4=0xc2f0 +serdes_preemphasis_lane2_xe4=0xc2f0 +serdes_preemphasis_lane3_xe4=0xcad0 + +# xe5 (40G) +portmap_6=45:40 +xgxs_rx_lane_map_6=0x213 +xgxs_tx_lane_map_6=0x213 +phy_xaui_rx_polarity_flip_6=0xe +phy_xaui_tx_polarity_flip_6=0x8 +serdes_driver_current_lane0_xe5=0x4 +serdes_driver_current_lane1_xe5=0x4 +serdes_driver_current_lane2_xe5=0x4 +serdes_driver_current_lane3_xe5=0x4 +serdes_pre_driver_current_lane0_xe5=0x4 +serdes_pre_driver_current_lane1_xe5=0x4 +serdes_pre_driver_current_lane2_xe5=0x4 +serdes_pre_driver_current_lane3_xe5=0x4 +serdes_preemphasis_lane0_xe5=0xc2f0 +serdes_preemphasis_lane1_xe5=0xc2f0 +serdes_preemphasis_lane2_xe5=0xc2f0 +serdes_preemphasis_lane3_xe5=0xc2f0 + +# xe6 (40G) +portmap_7=5:40 +xgxs_rx_lane_map_7=0x213 +xgxs_tx_lane_map_7=0x1203 +phy_xaui_rx_polarity_flip_7=0xc +phy_xaui_tx_polarity_flip_7=0x1 +serdes_driver_current_lane0_xe6=0x4 +serdes_driver_current_lane1_xe6=0x4 +serdes_driver_current_lane2_xe6=0x4 +serdes_driver_current_lane3_xe6=0x4 +serdes_pre_driver_current_lane0_xe6=0x4 +serdes_pre_driver_current_lane1_xe6=0x4 +serdes_pre_driver_current_lane2_xe6=0x4 +serdes_pre_driver_current_lane3_xe6=0x4 +serdes_preemphasis_lane0_xe6=0xc6e0 +serdes_preemphasis_lane1_xe6=0xc6e0 +serdes_preemphasis_lane2_xe6=0xc6e0 +serdes_preemphasis_lane3_xe6=0xc6e0 + +# xe7 (40G) +portmap_8=1:40 +xgxs_rx_lane_map_8=0x213 +xgxs_tx_lane_map_8=0x2031 +phy_xaui_rx_polarity_flip_8=0xe +phy_xaui_tx_polarity_flip_8=0xd +serdes_driver_current_lane0_xe7=0x5 +serdes_driver_current_lane1_xe7=0x5 +serdes_driver_current_lane2_xe7=0x5 +serdes_driver_current_lane3_xe7=0x5 +serdes_pre_driver_current_lane0_xe7=0x5 +serdes_pre_driver_current_lane1_xe7=0x5 +serdes_pre_driver_current_lane2_xe7=0x5 +serdes_pre_driver_current_lane3_xe7=0x5 +serdes_preemphasis_lane0_xe7=0xc6e0 +serdes_preemphasis_lane1_xe7=0xcad0 +serdes_preemphasis_lane2_xe7=0xc6e0 +serdes_preemphasis_lane3_xe7=0xcad0 + +# xe9 (40G) +portmap_9=9:40 +xgxs_rx_lane_map_9=0x3120 +xgxs_tx_lane_map_9=0x3021 +phy_xaui_rx_polarity_flip_9=0x0 +phy_xaui_tx_polarity_flip_9=0x4 +serdes_driver_current_lane0_xe8=0x3 +serdes_driver_current_lane1_xe8=0x3 +serdes_driver_current_lane2_xe8=0x3 +serdes_driver_current_lane3_xe8=0x3 +serdes_pre_driver_current_lane0_xe8=0x3 +serdes_pre_driver_current_lane1_xe8=0x3 +serdes_pre_driver_current_lane2_xe8=0x3 +serdes_pre_driver_current_lane3_xe8=0x3 +serdes_preemphasis_lane0_xe8=0xc2f0 +serdes_preemphasis_lane1_xe8=0xc6e0 +serdes_preemphasis_lane2_xe8=0xbf00 +serdes_preemphasis_lane3_xe8=0xc2f0 + +# xe9 (40G) +portmap_10=13:40 +xgxs_rx_lane_map_10=0x213 +xgxs_tx_lane_map_10=0x132 +phy_xaui_rx_polarity_flip_10=0xe +phy_xaui_tx_polarity_flip_10=0x0 +serdes_driver_current_lane0_xe9=0x2 +serdes_driver_current_lane1_xe9=0x3 +serdes_driver_current_lane2_xe9=0x2 +serdes_driver_current_lane3_xe9=0x2 +serdes_pre_driver_current_lane0_xe9=0x2 +serdes_pre_driver_current_lane1_xe9=0x3 +serdes_pre_driver_current_lane2_xe9=0x2 +serdes_pre_driver_current_lane3_xe9=0x2 +serdes_preemphasis_lane0_xe9=0xb270 +serdes_preemphasis_lane1_xe9=0xbb10 +serdes_preemphasis_lane2_xe9=0xb720 +serdes_preemphasis_lane3_xe9=0xb720 + +# xe10 (40G) +portmap_11=21:40 +xgxs_rx_lane_map_11=0x123 +xgxs_tx_lane_map_11=0x1203 +phy_xaui_rx_polarity_flip_11=0xc +phy_xaui_tx_polarity_flip_11=0xe +serdes_driver_current_lane0_xe10=0x2 +serdes_driver_current_lane1_xe10=0x2 +serdes_driver_current_lane2_xe10=0x2 +serdes_driver_current_lane3_xe10=0x2 +serdes_pre_driver_current_lane0_xe10=0x2 +serdes_pre_driver_current_lane1_xe10=0x2 +serdes_pre_driver_current_lane2_xe10=0x2 +serdes_pre_driver_current_lane3_xe10=0x2 +serdes_preemphasis_lane0_xe10=0xb330 +serdes_preemphasis_lane1_xe10=0xb330 +serdes_preemphasis_lane2_xe10=0xb330 +serdes_preemphasis_lane3_xe10=0xb330 + +# xe11 (40G) +portmap_12=17:40 +xgxs_rx_lane_map_12=0x213 +xgxs_tx_lane_map_12=0x132 +phy_xaui_rx_polarity_flip_12=0xe +phy_xaui_tx_polarity_flip_12=0x0 +serdes_driver_current_lane0_xe11=0x2 +serdes_driver_current_lane1_xe11=0x2 +serdes_driver_current_lane2_xe11=0x2 +serdes_driver_current_lane3_xe11=0x2 +serdes_pre_driver_current_lane0_xe11=0x2 +serdes_pre_driver_current_lane1_xe11=0x2 +serdes_pre_driver_current_lane2_xe11=0x2 +serdes_pre_driver_current_lane3_xe11=0x2 +serdes_preemphasis_lane0_xe11=0xb330 +serdes_preemphasis_lane1_xe11=0xbb10 +serdes_preemphasis_lane2_xe11=0xbb10 +serdes_preemphasis_lane3_xe11=0xbb10 + +# xe12 (40G) +portmap_13=49:40 +xgxs_rx_lane_map_13=0x1302 +xgxs_tx_lane_map_13=0x2031 +phy_xaui_rx_polarity_flip_13=0xb +phy_xaui_tx_polarity_flip_13=0x3 +serdes_driver_current_lane0_xe12=0x2 +serdes_driver_current_lane1_xe12=0x2 +serdes_driver_current_lane2_xe12=0x2 +serdes_driver_current_lane3_xe12=0x2 +serdes_pre_driver_current_lane0_xe12=0x2 +serdes_pre_driver_current_lane1_xe12=0x2 +serdes_pre_driver_current_lane2_xe12=0x2 +serdes_pre_driver_current_lane3_xe12=0x2 +serdes_preemphasis_lane0_xe12=0xa760 +serdes_preemphasis_lane1_xe12=0xa760 +serdes_preemphasis_lane2_xe12=0xa760 +serdes_preemphasis_lane3_xe12=0xa760 + +# xe13 (40G) +portmap_14=53:40 +xgxs_rx_lane_map_14=0x213 +xgxs_tx_lane_map_14=0x231 +phy_xaui_rx_polarity_flip_14=0x1 +phy_xaui_tx_polarity_flip_14=0x0 +serdes_driver_current_lane0_xe13=0x2 +serdes_driver_current_lane1_xe13=0x2 +serdes_driver_current_lane2_xe13=0x2 +serdes_driver_current_lane3_xe13=0x2 +serdes_pre_driver_current_lane0_xe13=0x2 +serdes_pre_driver_current_lane1_xe13=0x2 +serdes_pre_driver_current_lane2_xe13=0x2 +serdes_pre_driver_current_lane3_xe13=0x2 +serdes_preemphasis_lane0_xe13=0xaf40 +serdes_preemphasis_lane1_xe13=0xaf40 +serdes_preemphasis_lane2_xe13=0xaf40 +serdes_preemphasis_lane3_xe13=0xaf40 + +# xe14 (40G) +portmap_15=61:40 +xgxs_rx_lane_map_15=0x132 +xgxs_tx_lane_map_15=0x213 +phy_xaui_rx_polarity_flip_15=0x0 +phy_xaui_tx_polarity_flip_15=0x0 +serdes_driver_current_lane0_xe14=0x2 +serdes_driver_current_lane1_xe14=0x2 +serdes_driver_current_lane2_xe14=0x2 +serdes_driver_current_lane3_xe14=0x2 +serdes_pre_driver_current_lane0_xe14=0x2 +serdes_pre_driver_current_lane1_xe14=0x2 +serdes_pre_driver_current_lane2_xe14=0x2 +serdes_pre_driver_current_lane3_xe14=0x2 +serdes_preemphasis_lane0_xe14=0xa760 +serdes_preemphasis_lane1_xe14=0xa760 +serdes_preemphasis_lane2_xe14=0xa760 +serdes_preemphasis_lane3_xe14=0xa760 + +# xe15 (40G) +portmap_16=57:40 +xgxs_rx_lane_map_16=0x213 +xgxs_tx_lane_map_16=0x2031 +phy_xaui_rx_polarity_flip_16=0x1 +phy_xaui_tx_polarity_flip_16=0x0 +serdes_driver_current_lane0_xe15=0x1 +serdes_driver_current_lane1_xe15=0x1 +serdes_driver_current_lane2_xe15=0x1 +serdes_driver_current_lane3_xe15=0x1 +serdes_pre_driver_current_lane0_xe15=0x1 +serdes_pre_driver_current_lane1_xe15=0x1 +serdes_pre_driver_current_lane2_xe15=0x1 +serdes_pre_driver_current_lane3_xe15=0x1 +serdes_preemphasis_lane0_xe15=0xa760 +serdes_preemphasis_lane1_xe15=0xa760 +serdes_preemphasis_lane2_xe15=0xa760 +serdes_preemphasis_lane3_xe15=0xa760 + +# xe16 (40G) +portmap_17=65:40 +xgxs_rx_lane_map_17=0x132 +xgxs_tx_lane_map_17=0x2031 +phy_xaui_rx_polarity_flip_17=0x3 +phy_xaui_tx_polarity_flip_17=0x9 +serdes_driver_current_lane0_xe16=0x1 +serdes_driver_current_lane1_xe16=0x1 +serdes_driver_current_lane2_xe16=0x1 +serdes_driver_current_lane3_xe16=0x1 +serdes_pre_driver_current_lane0_xe16=0x1 +serdes_pre_driver_current_lane1_xe16=0x1 +serdes_pre_driver_current_lane2_xe16=0x1 +serdes_pre_driver_current_lane3_xe16=0x1 +serdes_preemphasis_lane0_xe16=0xa370 +serdes_preemphasis_lane1_xe16=0xa370 +serdes_preemphasis_lane2_xe16=0xa370 +serdes_preemphasis_lane3_xe16=0xa370 + +# xe17 (40G) +portmap_18=69:40 +xgxs_rx_lane_map_18=0x213 +xgxs_tx_lane_map_18=0x2130 +phy_xaui_rx_polarity_flip_18=0x1 +phy_xaui_tx_polarity_flip_18=0xf +serdes_driver_current_lane0_xe17=0x1 +serdes_driver_current_lane1_xe17=0x1 +serdes_driver_current_lane2_xe17=0x1 +serdes_driver_current_lane3_xe17=0x1 +serdes_pre_driver_current_lane0_xe17=0x1 +serdes_pre_driver_current_lane1_xe17=0x1 +serdes_pre_driver_current_lane2_xe17=0x1 +serdes_pre_driver_current_lane3_xe17=0x1 +serdes_preemphasis_lane0_xe17=0xa760 +serdes_preemphasis_lane1_xe17=0xa760 +serdes_preemphasis_lane2_xe17=0xa760 +serdes_preemphasis_lane3_xe17=0xa760 + +# xe19 (40G) +portmap_19=77:40 +xgxs_rx_lane_map_19=0x123 +xgxs_tx_lane_map_19=0x1203 +phy_xaui_rx_polarity_flip_19=0x3 +phy_xaui_tx_polarity_flip_19=0xe +serdes_driver_current_lane0_xe18=0x2 +serdes_driver_current_lane1_xe18=0x2 +serdes_driver_current_lane2_xe18=0x2 +serdes_driver_current_lane3_xe18=0x2 +serdes_pre_driver_current_lane0_xe18=0x2 +serdes_pre_driver_current_lane1_xe18=0x2 +serdes_pre_driver_current_lane2_xe18=0x2 +serdes_pre_driver_current_lane3_xe18=0x2 +serdes_preemphasis_lane0_xe18=0xaf40 +serdes_preemphasis_lane1_xe18=0xaf40 +serdes_preemphasis_lane2_xe18=0xaf40 +serdes_preemphasis_lane3_xe18=0xaf40 + +# xe19 (40G) +portmap_20=73:40 +xgxs_rx_lane_map_20=0x213 +xgxs_tx_lane_map_20=0x2031 +phy_xaui_rx_polarity_flip_20=0x1 +phy_xaui_tx_polarity_flip_20=0x0 +serdes_driver_current_lane0_xe19=0x2 +serdes_driver_current_lane1_xe19=0x2 +serdes_driver_current_lane2_xe19=0x2 +serdes_driver_current_lane3_xe19=0x2 +serdes_pre_driver_current_lane0_xe19=0x2 +serdes_pre_driver_current_lane1_xe19=0x2 +serdes_pre_driver_current_lane2_xe19=0x2 +serdes_pre_driver_current_lane3_xe19=0x2 +serdes_preemphasis_lane0_xe19=0xa760 +serdes_preemphasis_lane1_xe19=0xa760 +serdes_preemphasis_lane2_xe19=0xa760 +serdes_preemphasis_lane3_xe19=0xa760 + +# xe20 (40G) +portmap_21=105:40 +xgxs_rx_lane_map_21=0x1320 +xgxs_tx_lane_map_21=0x3021 +phy_xaui_rx_polarity_flip_21=0xd +phy_xaui_tx_polarity_flip_21=0xb +serdes_driver_current_lane0_xe20=0x1 +serdes_driver_current_lane1_xe20=0x1 +serdes_driver_current_lane2_xe20=0x1 +serdes_driver_current_lane3_xe20=0x1 +serdes_pre_driver_current_lane0_xe20=0x1 +serdes_pre_driver_current_lane1_xe20=0x1 +serdes_pre_driver_current_lane2_xe20=0x1 +serdes_pre_driver_current_lane3_xe20=0x1 +serdes_preemphasis_lane0_xe20=0xb330 +serdes_preemphasis_lane1_xe20=0xb330 +serdes_preemphasis_lane2_xe20=0xb330 +serdes_preemphasis_lane3_xe20=0xb330 + +# xe21 (40G) +portmap_22=109:40 +xgxs_rx_lane_map_22=0x132 +xgxs_tx_lane_map_22=0x132 +phy_xaui_rx_polarity_flip_22=0x8 +phy_xaui_tx_polarity_flip_22=0x0 +serdes_driver_current_lane0_xe21=0x1 +serdes_driver_current_lane1_xe21=0x1 +serdes_driver_current_lane2_xe21=0x1 +serdes_driver_current_lane3_xe21=0x2 +serdes_pre_driver_current_lane0_xe21=0x1 +serdes_pre_driver_current_lane1_xe21=0x1 +serdes_pre_driver_current_lane2_xe21=0x1 +serdes_pre_driver_current_lane3_xe21=0x2 +serdes_preemphasis_lane0_xe21=0xb330 +serdes_preemphasis_lane1_xe21=0xb330 +serdes_preemphasis_lane2_xe21=0xb330 +serdes_preemphasis_lane3_xe21=0xbff0 + +# xe22 (40G) +portmap_23=117:40 +xgxs_rx_lane_map_23=0x231 +xgxs_tx_lane_map_23=0x1203 +phy_xaui_rx_polarity_flip_23=0x3 +phy_xaui_tx_polarity_flip_23=0xe +serdes_driver_current_lane0_xe22=0x3 +serdes_driver_current_lane1_xe22=0x5 +serdes_driver_current_lane2_xe22=0x3 +serdes_driver_current_lane3_xe22=0x3 +serdes_pre_driver_current_lane0_xe22=0x3 +serdes_pre_driver_current_lane1_xe22=0x5 +serdes_pre_driver_current_lane2_xe22=0x3 +serdes_pre_driver_current_lane3_xe22=0x3 +serdes_preemphasis_lane0_xe22=0xc6e0 +serdes_preemphasis_lane1_xe22=0xc6e0 +serdes_preemphasis_lane2_xe22=0xc6e0 +serdes_preemphasis_lane3_xe22=0xc6e0 + +# xe23 (40G) +portmap_24=113:40 +xgxs_rx_lane_map_24=0x132 +xgxs_tx_lane_map_24=0x132 +phy_xaui_rx_polarity_flip_24=0x8 +phy_xaui_tx_polarity_flip_24=0x0 +serdes_driver_current_lane0_xe23=0x1 +serdes_driver_current_lane1_xe23=0x1 +serdes_driver_current_lane2_xe23=0x1 +serdes_driver_current_lane3_xe23=0x1 +serdes_pre_driver_current_lane0_xe23=0x1 +serdes_pre_driver_current_lane1_xe23=0x1 +serdes_pre_driver_current_lane2_xe23=0x1 +serdes_pre_driver_current_lane3_xe23=0x1 +serdes_preemphasis_lane0_xe23=0xbb10 +serdes_preemphasis_lane1_xe23=0xbb10 +serdes_preemphasis_lane2_xe23=0xbb10 +serdes_preemphasis_lane3_xe23=0xc2f0 + +# xe24 (40G) +portmap_25=121:40 +xgxs_rx_lane_map_25=0x1320 +xgxs_tx_lane_map_25=0x3021 +phy_xaui_rx_polarity_flip_25=0xd +phy_xaui_tx_polarity_flip_25=0xb +serdes_driver_current_lane0_xe24=0x4 +serdes_driver_current_lane1_xe24=0x4 +serdes_driver_current_lane2_xe24=0x4 +serdes_driver_current_lane3_xe24=0x4 +serdes_pre_driver_current_lane0_xe24=0x4 +serdes_pre_driver_current_lane1_xe24=0x4 +serdes_pre_driver_current_lane2_xe24=0x4 +serdes_pre_driver_current_lane3_xe24=0x4 +serdes_preemphasis_lane0_xe24=0xc6e0 +serdes_preemphasis_lane1_xe24=0xc6e0 +serdes_preemphasis_lane2_xe24=0xc6e0 +serdes_preemphasis_lane3_xe24=0xc6e0 + +# xe25 (40G) +portmap_26=125:40 +xgxs_rx_lane_map_26=0x132 +xgxs_tx_lane_map_26=0x132 +phy_xaui_rx_polarity_flip_26=0x8 +phy_xaui_tx_polarity_flip_26=0x0 +serdes_driver_current_lane0_xe25=0x4 +serdes_driver_current_lane1_xe25=0x4 +serdes_driver_current_lane2_xe25=0x4 +serdes_driver_current_lane3_xe25=0x4 +serdes_pre_driver_current_lane0_xe25=0x4 +serdes_pre_driver_current_lane1_xe25=0x4 +serdes_pre_driver_current_lane2_xe25=0x4 +serdes_pre_driver_current_lane3_xe25=0x4 +serdes_preemphasis_lane0_xe25=0xc6e0 +serdes_preemphasis_lane1_xe25=0xc6e0 +serdes_preemphasis_lane2_xe25=0xc6e0 +serdes_preemphasis_lane3_xe25=0xcec0 + +# xe26 (40G) +portmap_27=85:40 +xgxs_rx_lane_map_27=0x213 +xgxs_tx_lane_map_27=0x1203 +phy_xaui_rx_polarity_flip_27=0xc +phy_xaui_tx_polarity_flip_27=0xe +serdes_driver_current_lane0_xe26=0x4 +serdes_driver_current_lane1_xe26=0x5 +serdes_driver_current_lane2_xe26=0x4 +serdes_driver_current_lane3_xe26=0x5 +serdes_pre_driver_current_lane0_xe26=0x4 +serdes_pre_driver_current_lane1_xe26=0x5 +serdes_pre_driver_current_lane2_xe26=0x4 +serdes_pre_driver_current_lane3_xe26=0x5 +serdes_preemphasis_lane0_xe26=0xc2f0 +serdes_preemphasis_lane1_xe26=0xc6e0 +serdes_preemphasis_lane2_xe26=0xc6e0 +serdes_preemphasis_lane3_xe26=0xc6e0 + +# xe27 (40G) +portmap_28=81:40 +xgxs_rx_lane_map_28=0x1320 +xgxs_tx_lane_map_28=0x2031 +phy_xaui_rx_polarity_flip_28=0x1 +phy_xaui_tx_polarity_flip_28=0x2 +serdes_driver_current_lane0_xe27=0x2 +serdes_driver_current_lane1_xe27=0x2 +serdes_driver_current_lane2_xe27=0x2 +serdes_driver_current_lane3_xe27=0x2 +serdes_pre_driver_current_lane0_xe27=0x2 +serdes_pre_driver_current_lane1_xe27=0x2 +serdes_pre_driver_current_lane2_xe27=0x2 +serdes_pre_driver_current_lane3_xe27=0x2 +serdes_preemphasis_lane0_xe27=0xbb10 +serdes_preemphasis_lane1_xe27=0xbb10 +serdes_preemphasis_lane2_xe27=0xbf00 +serdes_preemphasis_lane3_xe27=0xbb10 + +# xe29 (40G) +portmap_29=89:40 +xgxs_rx_lane_map_29=0x1320 +xgxs_tx_lane_map_29=0x3021 +phy_xaui_rx_polarity_flip_29=0x2 +phy_xaui_tx_polarity_flip_29=0xb +serdes_driver_current_lane0_xe28=0x4 +serdes_driver_current_lane1_xe28=0x4 +serdes_driver_current_lane2_xe28=0x4 +serdes_driver_current_lane3_xe28=0x4 +serdes_pre_driver_current_lane0_xe28=0x4 +serdes_pre_driver_current_lane1_xe28=0x4 +serdes_pre_driver_current_lane2_xe28=0x4 +serdes_pre_driver_current_lane3_xe28=0x4 +serdes_preemphasis_lane0_xe28=0xcad0 +serdes_preemphasis_lane1_xe28=0xc6e0 +serdes_preemphasis_lane2_xe28=0xc6e0 +serdes_preemphasis_lane3_xe28=0xc6e0 + +# xe29 (40G) +portmap_30=93:40 +xgxs_rx_lane_map_30=0x1320 +xgxs_tx_lane_map_30=0x2031 +phy_xaui_rx_polarity_flip_30=0x1 +phy_xaui_tx_polarity_flip_30=0x2 +serdes_driver_current_lane0_xe29=0x4 +serdes_driver_current_lane1_xe29=0x4 +serdes_driver_current_lane2_xe29=0x4 +serdes_driver_current_lane3_xe29=0x4 +serdes_pre_driver_current_lane0_xe29=0x4 +serdes_pre_driver_current_lane1_xe29=0x4 +serdes_pre_driver_current_lane2_xe29=0x4 +serdes_pre_driver_current_lane3_xe29=0x4 +serdes_preemphasis_lane0_xe29=0xc2f0 +serdes_preemphasis_lane1_xe29=0xc2f0 +serdes_preemphasis_lane2_xe29=0xc2f0 +serdes_preemphasis_lane3_xe29=0xc2f0 + +# xe30 (40G) +portmap_31=97:40 +xgxs_rx_lane_map_31=0x213 +xgxs_tx_lane_map_31=0x2031 +phy_xaui_rx_polarity_flip_31=0xc +phy_xaui_tx_polarity_flip_31=0x3 +serdes_driver_current_lane0_xe30=0x5 +serdes_driver_current_lane1_xe30=0x5 +serdes_driver_current_lane2_xe30=0x5 +serdes_driver_current_lane3_xe30=0x5 +serdes_pre_driver_current_lane0_xe30=0x5 +serdes_pre_driver_current_lane1_xe30=0x5 +serdes_pre_driver_current_lane2_xe30=0x5 +serdes_pre_driver_current_lane3_xe30=0x5 +serdes_preemphasis_lane0_xe30=0xcad0 +serdes_preemphasis_lane1_xe30=0xcad0 +serdes_preemphasis_lane2_xe30=0xcad0 +serdes_preemphasis_lane3_xe30=0xcad0 + +# xe31 (40G) +portmap_32=101:40 +xgxs_rx_lane_map_32=0x1320 +xgxs_tx_lane_map_32=0x1203 +phy_xaui_rx_polarity_flip_32=0x1 +phy_xaui_tx_polarity_flip_32=0x6 +serdes_driver_current_lane0_xe31=0x6 +serdes_driver_current_lane1_xe31=0x6 +serdes_driver_current_lane2_xe31=0x6 +serdes_driver_current_lane3_xe31=0x7 +serdes_pre_driver_current_lane0_xe31=0x6 +serdes_pre_driver_current_lane1_xe31=0x6 +serdes_pre_driver_current_lane2_xe31=0x6 +serdes_pre_driver_current_lane3_xe31=0x7 +serdes_preemphasis_lane0_xe31=0xcec0 +serdes_preemphasis_lane1_xe31=0xcec0 +serdes_preemphasis_lane2_xe31=0xcad0 +serdes_preemphasis_lane3_xe31=0xc6e0 diff --git a/device/virtual/x86_64-kvm_x86_64-r0/default_sku b/device/virtual/x86_64-kvm_x86_64-r0/default_sku new file mode 100644 index 000000000000..493e1989b662 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/default_sku @@ -0,0 +1 @@ +Force10-S6000 t1 diff --git a/generic/platform.conf b/device/virtual/x86_64-kvm_x86_64-r0/installer.conf similarity index 100% rename from generic/platform.conf rename to device/virtual/x86_64-kvm_x86_64-r0/installer.conf diff --git a/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/port_config.ini b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/port_config.ini new file mode 100644 index 000000000000..578f59203d30 --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias speed autoneg fec +Ethernet0 0 Ethernet0 25000 1 rs +Ethernet4 1 Ethernet4 25000 1 rs +Ethernet8 2 Ethernet8 25000 1 rs +Ethernet12 3 Ethernet12 25000 1 rs +Ethernet16 4 Ethernet16 25000 1 rs +Ethernet20 5 Ethernet20 25000 1 rs +Ethernet24 6 Ethernet24 25000 1 rs +Ethernet28 7 Ethernet28 25000 1 rs +Ethernet32 8 Ethernet32 25000 1 rs +Ethernet36 9 Ethernet36 25000 1 rs +Ethernet40 10 Ethernet40 25000 1 rs +Ethernet44 11 Ethernet44 25000 1 rs +Ethernet48 12 Ethernet48 25000 1 rs +Ethernet52 13 Ethernet52 25000 1 rs +Ethernet56 14 Ethernet56 25000 1 rs +Ethernet60 15 Ethernet60 25000 1 rs +Ethernet64 16 Ethernet64 25000 1 rs +Ethernet68 17 Ethernet68 25000 1 rs +Ethernet72 18 Ethernet72 25000 1 rs +Ethernet76 19 Ethernet76 25000 1 rs +Ethernet80 20 Ethernet80 25000 1 rs +Ethernet84 21 Ethernet84 25000 1 rs +Ethernet88 22 Ethernet88 25000 1 rs +Ethernet92 23 Ethernet92 25000 1 rs +Ethernet96 24 Ethernet96 25000 1 rs +Ethernet100 25 Ethernet100 25000 1 rs +Ethernet104 26 Ethernet104 25000 1 rs +Ethernet108 27 Ethernet108 25000 1 rs +Ethernet112 28 Ethernet112 25000 1 rs +Ethernet116 29 Ethernet116 25000 1 rs +Ethernet120 30 Ethernet120 25000 1 rs +Ethernet124 31 Ethernet124 25000 1 rs +Ethernet128 32 Ethernet128 25000 1 rs +Ethernet132 33 Ethernet132 25000 1 rs +Ethernet136 34 Ethernet136 25000 1 rs +Ethernet140 35 Ethernet140 25000 1 rs +Ethernet144 36 Ethernet144 25000 1 rs +Ethernet148 37 Ethernet148 25000 1 rs +Ethernet152 38 Ethernet152 25000 1 rs +Ethernet156 39 Ethernet156 25000 1 rs +Ethernet160 40 Ethernet160 25000 1 rs +Ethernet164 41 Ethernet164 25000 1 rs +Ethernet168 42 Ethernet168 25000 1 rs +Ethernet172 43 Ethernet172 25000 1 rs +Ethernet176 44 Ethernet176 25000 1 rs +Ethernet180 45 Ethernet180 25000 1 rs +Ethernet184 46 Ethernet184 25000 1 rs +Ethernet188 47 Ethernet188 25000 1 rs +Ethernet192 48,49,50,51 Ethernet192 100000 1 rs +Ethernet196 52,53,54,55 Ethernet196 100000 1 rs +Ethernet200 56,57,58,59 Ethernet200 100000 1 rs +Ethernet204 60,61,62,63 Ethernet204 100000 1 rs +Ethernet208 64,65,66,67 Ethernet208 100000 1 rs +Ethernet212 68,69,70,71 Ethernet212 100000 1 rs diff --git a/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/switch-sai.conf b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/switch-sai.conf new file mode 100644 index 000000000000..65a02a621f03 --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/switch-sai.conf @@ -0,0 +1,33 @@ +{ + "chip_list": [ + { + "id": "asic-0", + "chip_family": "Tofino", + "instance": 0, + "pcie_sysfs_prefix": "/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0", + "pcie_domain": 0, + "pcie_bus": 5, + "pcie_fn": 0, + "pcie_dev": 0, + "pcie_int_mode": 1, + "sds_fw_path": "share/tofino_sds_fw/avago/firmware" + } + ], + "instance": 0, + "p4_program_list": [ + { + "id": "pgm-0", + "instance": 0, + "path": "switch", + "program-name": "switch", + "pd": "lib/tofinopd/switch/libpd.so", + "pd-thrift": "lib/tofinopd/switch/libpdthrift.so", + "table-config": "share/tofinopd/switch/context.json", + "tofino-bin": "share/tofinopd/switch/tofino.bin", + "switchapi": "lib/libswitchapi.so", + "switchsai": "lib/libswitchsai.so", + "agent0": "lib/platform/x86_64-wnc_osw1800-r0/libpltfm_mgr.so", + "switchapi_port_add": false + } + ] +} diff --git a/device/wnc/x86_64-wnc_osw1800-r0/default_sku b/device/wnc/x86_64-wnc_osw1800-r0/default_sku new file mode 100644 index 000000000000..0f663505d7a4 --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/default_sku @@ -0,0 +1 @@ +OSW1800-48x6q t1 diff --git a/device/wnc/x86_64-wnc_osw1800-r0/fancontrol b/device/wnc/x86_64-wnc_osw1800-r0/fancontrol new file mode 100644 index 000000000000..d661bd11f1b2 --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/fancontrol @@ -0,0 +1,11 @@ +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:16.0/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.2/i2c-2/i2c-5/5-0033 hwmon2=devices/pci0000:00/0000:00:16.0/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.2/i2c-2/i2c-7/7-001e hwmon3=devices/pci0000:00/0000:00:16.0/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.2/i2c-2/i2c-7/7-004e hwmon4=devices/pci0000:00/0000:00:16.0/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.2/i2c-2/i2c-7/7-004f +DEVNAME=hwmon1=wnc_cpld3 hwmon2=tmp421 hwmon3=tmp75 hwmon4=tmp421 +FCTEMPS=hwmon1/pwm1=hwmon2/temp1_input hwmon1/pwm2=hwmon2/temp2_input hwmon1/pwm3=hwmon3/temp1_input hwmon1/pwm4=hwmon4/temp1_input hwmon1/pwm5=hwmon4/temp2_input +FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input hwmon1/pwm4=hwmon1/fan4_input hwmon1/pwm5=hwmon1/fan5_input +MINTEMP=hwmon1/pwm1=20 hwmon1/pwm2=20 hwmon1/pwm3=20 hwmon1/pwm4=20 hwmon1/pwm5=20 +MAXTEMP=hwmon1/pwm1=50 hwmon1/pwm2=50 hwmon1/pwm3=50 hwmon1/pwm4=50 hwmon1/pwm5=50 +MINSTART=hwmon1/pwm1=32 hwmon1/pwm2=32 hwmon1/pwm3=32 hwmon1/pwm4=32 hwmon1/pwm5=32 +MINSTOP=hwmon1/pwm1=22 hwmon1/pwm2=22 hwmon1/pwm3=22 hwmon1/pwm4=22 hwmon1/pwm5=22 +MINPWM=hwmon1/pwm1=10 hwmon1/pwm2=10 hwmon1/pwm3=10 hwmon1/pwm4=10 hwmon1/pwm5=10 +MAXPWM=hwmon1/pwm1=100 hwmon1/pwm2=100 hwmon1/pwm3=100 hwmon1/pwm4=100 hwmon1/pwm5=100 diff --git a/device/wnc/x86_64-wnc_osw1800-r0/installer.conf b/device/wnc/x86_64-wnc_osw1800-r0/installer.conf new file mode 100644 index 000000000000..dfa6df22689b --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=57600 diff --git a/device/wnc/x86_64-wnc_osw1800-r0/plugins/eeprom.py b/device/wnc/x86_64-wnc_osw1800-r0/plugins/eeprom.py new file mode 100644 index 000000000000..a073374794fa --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo +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-8/8-0052/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) + diff --git a/device/wnc/x86_64-wnc_osw1800-r0/plugins/psuutil.py b/device/wnc/x86_64-wnc_osw1800-r0/plugins/psuutil.py new file mode 100644 index 000000000000..e62159c8a8cc --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/plugins/psuutil.py @@ -0,0 +1,64 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def get_num_psus(self): + return 2 + + def get_psu_status(self, index): + if index == 1: + psu_path = "/sys/bus/i2c/devices/6-0050/eeprom" + elif index == 2: + psu_path = "/sys/bus/i2c/devices/6-0051/eeprom" + else: + return False + + try: + data = open(psu_path, "rb") + except IOError: + return False + + result = int(data.read(1).encode("hex"), 16) + data.close() + + if result != 255 and result != 0: + return True + else: + return False + + def get_psu_presence(self, index): + if index == 1: + psu_path = "/sys/bus/i2c/devices/6-0050/eeprom" + elif index == 2: + psu_path = "/sys/bus/i2c/devices/6-0051/eeprom" + else: + return False + + try: + data = open(psu_path, "rb") + except IOError: + return False + + result = int(data.read(1).encode("hex"), 16) + data.close() + + if result != 255 and result != 0: + return True + else: + return False diff --git a/device/wnc/x86_64-wnc_osw1800-r0/plugins/sfputil.py b/device/wnc/x86_64-wnc_osw1800-r0/plugins/sfputil.py new file mode 100644 index 000000000000..549790bfb44f --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/plugins/sfputil.py @@ -0,0 +1,213 @@ +#! /usr/bin/python +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase + import sys + sys.path.append('/usr/lib/python2.7/dist-packages/sonic_sfp/') + from sff8472 import sff8472InterfaceId + from sff8472 import sff8472Dom + from sff8436 import sff8436InterfaceId + from sff8436 import sff8436Dom +except ImportError, 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 + + EEPROM_OFFSET = 11 + + _port_to_eeprom_mapping = {} + + @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(self.PORT_START + 48, self.PORTS_IN_BLOCK) + + @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): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET) + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + bit_mask = port_num % 8 + + if port_num <= 7: + presence_path = "/sys/bus/i2c/devices/3-0031/sfp_mod_abs1" + elif 8 <= port_num and port_num <= 15: + presence_path = "/sys/bus/i2c/devices/3-0031/sfp_mod_abs2" + elif 16 <= port_num and port_num <= 23: + presence_path = "/sys/bus/i2c/devices/3-0031/sfp_mod_abs3" + elif 24 <= port_num and port_num <= 27: + presence_path = "/sys/bus/i2c/devices/3-0031/sfp_mod_abs4" + elif 28 <= port_num and port_num <= 31: + presence_path = "/sys/bus/i2c/devices/4-0032/sfp_mod_abs1" + bit_mask = bit_mask - 4 + elif 32 <= port_num and port_num <= 39: + presence_path = "/sys/bus/i2c/devices/4-0032/sfp_mod_abs2" + elif 40 <= port_num and port_num <= 47: + presence_path = "/sys/bus/i2c/devices/4-0032/sfp_mod_abs3" + elif 48 <= port_num and port_num <= 71: + presence_path = "/sys/bus/i2c/devices/4-0032/qsfp_modprs" + else: + return False + + try: + reg_file = open(presence_path, "rb") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + reg_file.close() + + if reg_value & (1 << bit_mask) == 0: + return True + else: + return False + + def get_low_power_mode(self, port_num): + if port_num in self.qsfp_ports: + bit_mask = port_num % 8 + else: + return False + + try: + reg_file = open("/sys/bus/i2c/devices/4-0032/qsfp_lpmode") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + reg_file.close() + + if reg_value & (1 << bit_mask) == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + if port_num in self.qsfp_ports: + bit_mask = port_num % 8 + else: + return False + + try: + reg_file = open("/sys/bus/i2c/devices/4-0032/qsfp_lpmode", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + + if lpmode is True: + reg_value = reg_value | (1 << bit_mask) + else: + reg_value = reg_value & ~(1 << bit_mask) + + reg_file.seek(0) + reg_file.write(str(reg_value)) + reg_file.close() + + return True + + def reset(self, port_num): + if port_num in self.qsfp_ports: + bit_mask = (port_num % 8) + 2 + else: + return False + + try: + reg_file = open("/sys/bus/i2c/devices/4-0032/reset_control", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + reg_value = reg_value & ~(1 << bit_mask) + + reg_file.seek(0) + reg_file.write(str(reg_value)) + reg_file.close() + + time.sleep(1) + + try: + reg_file = open("/sys/bus/i2c/devices/4-0032/reset_control", "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_value | (1 << bit_mask) + reg_file.seek(0) + reg_file.write(str(reg_value)) + reg_file.close() + + return True + + def get_eeprom_dict(self, port_num): + if not self.get_presence(port_num): + return None + + sfp_data = {} + + eeprom_ifraw = self.get_eeprom_raw(port_num) + eeprom_domraw = self.get_eeprom_dom_raw(port_num) + + if eeprom_ifraw is None: + return None + + if port_num in self.qsfp_ports: + sfpi_obj = sff8436InterfaceId(eeprom_ifraw) + if sfpi_obj is not None: + sfp_data['interface'] = sfpi_obj.get_data_pretty() + + sfpd_obj = sff8436Dom(eeprom_ifraw) + if sfpd_obj is not None: + sfp_data['dom'] = sfpd_obj.get_data_pretty() + return sfp_data + + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + if sfpi_obj is not None: + sfp_data['interface'] = sfpi_obj.get_data_pretty() + cal_type = sfpi_obj.get_calibration_type() + + if eeprom_domraw is not None: + sfpd_obj = sff8472Dom(eeprom_domraw, cal_type) + if sfpd_obj is not None: + sfp_data['dom'] = sfpd_obj.get_data_pretty() + + return sfp_data + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/wnc/x86_64-wnc_osw1800-r0/sensors.conf b/device/wnc/x86_64-wnc_osw1800-r0/sensors.conf new file mode 100644 index 000000000000..d91945ff722b --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/sensors.conf @@ -0,0 +1,33 @@ +# libsensors configuration filei +# -------------------------------------------------- +# + +bus "i2c-7" "i2c-2-mux" +chip "tmp421-i2c-7-1E" + label temp1 "ts1" + set temp1_max 50 + set temp1_max_hyst 25 + label temp2 "ts4" + set temp2_max 50 + set temp2_max_hyst 25 + +chip "tmp75-i2c-7-4E" + label temp1 "ts3" + set temp1_max 50 + set temp1_max_hyst 25 + +chip "tmp421-i2c-7-4F" + label temp1 "ts2" + set temp1_max 50 + set temp1_max_hyst 25 + label temp2 "ts5" + set temp2_max 50 + set temp2_max_hyst 25 + +bus "i2c-5" "i2c-2-mux" +chip "wnc_cpld3-i2c-5-33" + label fan1 "fan1" + label fan2 "fan2" + label fan3 "fan3" + label fan4 "fan4" + label fan5 "fan5" diff --git a/docker-bgp/Dockerfile b/docker-bgp/Dockerfile deleted file mode 100755 index 711e48fee206..000000000000 --- a/docker-bgp/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -FROM debian:jessie - -## Set the apt source -COPY files/sources.list /etc/sources.list -RUN apt-get clean && apt-get update - -## Pre-install the fundamental packages -RUN apt-get -y install \ - rsyslog \ - python - -COPY deps /deps -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/quagga_*.deb - -ENTRYPOINT service rsyslog start \ - && service quagga start \ - && /bin/bash diff --git a/docker-database/Dockerfile b/docker-database/Dockerfile deleted file mode 100755 index e830385d4fb8..000000000000 --- a/docker-database/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM debian:jessie - -## Set the apt source -COPY files/sources.list /etc/sources.list -RUN apt-get clean && apt-get update - -## Pre-install the fundamental packages -RUN apt-get -y install \ - rsyslog \ - redis-server - -ENTRYPOINT service rsyslog start \ - && service redis-server start \ - && /bin/bash diff --git a/docker-lldp/Dockerfile b/docker-lldp/Dockerfile deleted file mode 100755 index 322a92f57ea3..000000000000 --- a/docker-lldp/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM debian:jessie - -## Set the apt source -COPY files/sources.list /etc/sources.list -RUN apt-get clean && apt-get update - -## Pre-install the fundamental packages -RUN apt-get -y install \ - rsyslog \ - lldpd - -COPY deps /deps - -## Install Python SSWSDK (lldpsyncd dependancy) -## Note: dpkg_apt function has the benefit to detect missing .deb file -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/python-sswsdk_*.deb -## Install LLDP Sync Daemon -## Note: dpkg_apt function has the benefit to detect missing .deb file -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/lldpsyncd_*.deb - -## Specify init as CMD to enable systemd -## Note: don't provide ENTRYPOINT at the same time -CMD ["/sbin/init"] diff --git a/docker-ptf/Dockerfile b/docker-ptf/Dockerfile deleted file mode 100644 index 6c35e524a91d..000000000000 --- a/docker-ptf/Dockerfile +++ /dev/null @@ -1,48 +0,0 @@ -FROM debian:jessie - -MAINTAINER Pavel Shirshov - -## Copy dependencies -COPY deps /root/deps - -## Make apt-get non-interactive -ENV DEBIAN_FRONTEND=noninteractive - -## Set the apt source, update package cache and install necessary packages -RUN echo "deb http://ftp.us.debian.org/debian/ jessie main contrib non-free" > /etc/apt/sources.list \ - && apt-get update \ - && apt-get upgrade -y \ - && apt-get dist-upgrade -y \ - && apt-get install -y --no-install-recommends \ - openssh-server \ - vim-tiny \ - python \ - python-scapy \ - net-tools \ - python-setuptools \ - supervisor \ - traceroute \ - lsof \ - tcpdump \ - && dpkg -i /root/deps/python-ptf_*.deb \ - && dpkg -i --force-depends /root/deps/libthrift-0.9.2_*.deb \ - && dpkg -i --force-depends /root/deps/python-thrift_*.deb \ - && apt-get -y install -f \ - && rm -rf /root/deps \ - && apt-get -y autoclean \ - && apt-get -y autoremove \ - && rm -rf /var/lib/apt/lists/* - -## Adjust sshd settings -RUN mkdir /var/run/sshd \ - && echo 'root:root' | chpasswd \ - && sed -ri 's/^PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config \ - && sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config \ - && sed -i '$aUseDNS no' /etc/ssh/sshd_config \ - && mkdir /root/deps - -COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf - -EXPOSE 22 - -ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/docker-snmp/Dockerfile b/docker-snmp/Dockerfile deleted file mode 100755 index 2afc5eddeee8..000000000000 --- a/docker-snmp/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM debian:jessie - -## Set the apt source -COPY files/sources.list /etc/sources.list -RUN apt-get clean && apt-get update - -## Pre-install the fundamental packages -RUN apt-get -y install \ - rsyslog \ - snmp \ - snmpd - -COPY deps /deps - -## Install Python SSWSDK (SNMP subagent dependancy) -## Note: dpkg_apt function has the benefit to detect missing .deb file -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/python-sswsdk_*.deb -## Install SNMP subagent -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/acs-snmp-subagent_*.deb - -## Specify init as CMD to enable systemd -## Note: don't provide ENTRYPOINT at the same time -CMD ["/sbin/init"] diff --git a/docker-sswsyncd/Dockerfile b/docker-sswsyncd/Dockerfile deleted file mode 100755 index d260f442b392..000000000000 --- a/docker-sswsyncd/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM debian:jessie - -## Set the apt source -COPY files/sources.list /etc/sources.list -RUN apt-get clean && apt-get update - -## Pre-install the fundamental packages -## TODO: sswsyncd depends on ifupdown -RUN apt-get -y install \ - ifupdown \ - rsyslog - -COPY deps /deps -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/libopennsl_*.deb -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/libsaibcm_*.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 \ - && service sswsyncd start \ - && /bin/bash diff --git a/dockers/docker-base/Dockerfile.j2 b/dockers/docker-base/Dockerfile.j2 new file mode 100644 index 000000000000..2aef59241b13 --- /dev/null +++ b/dockers/docker-base/Dockerfile.j2 @@ -0,0 +1,81 @@ +FROM debian:jessie + +# Clean documentation in FROM image +RUN find /usr/share/doc -depth \( -type f -o -type l \) ! -name copyright | xargs rm || true + +# Clean doc directories that are empty or only contain empty directories +RUN while [ -n "$(find /usr/share/doc -depth -type d -empty -print -exec rmdir {} +)" ]; do :; done +RUN rm -rf \ + /usr/share/man/* \ + /usr/share/groff/* \ + /usr/share/info/* \ + /usr/share/lintian/* \ + /usr/share/linda/* \ + /var/cache/man/* \ + /usr/share/locale/* + +# Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +# Configure data sources for apt/dpkg +COPY ["dpkg_01_drop", "/etc/dpkg/dpkg.cfg.d/01_drop"] +COPY ["sources.list", "/etc/apt/sources.list"] +COPY ["no_install_recommend_suggest", "/etc/apt/apt.conf.d"] +RUN apt-get update + +# Pre-install fundamental packages +RUN apt-get -y install \ + vim-tiny \ + perl \ + python \ + less + +# Install a newer version of rsyslog from jessie-backports in hopes of +# eliminating memory leaks +RUN apt-get -y -t jessie-backports install rsyslog + +COPY ["etc/rsyslog.conf", "/etc/rsyslog.conf"] +COPY ["etc/rsyslog.d/*", "/etc/rsyslog.d/"] +COPY ["root/.vimrc", "/root/.vimrc"] + +# Install dependencies of supervisor +RUN apt-get -y install python-pkg-resources python-meld3 + +RUN mkdir -p /etc/supervisor +RUN mkdir -p /var/log/supervisor + +COPY ["etc/supervisor/supervisord.conf", "/etc/supervisor/"] + +RUN apt-get -y purge \ + exim4 \ + exim4-base \ + exim4-config \ + exim4-daemon-light + +{% if docker_base_debs.strip() -%} +# Copy built Debian packages +{%- for deb in docker_base_debs.split(' ') %} +COPY debs/{{ deb }} debs/ +{%- endfor %} + +# Install built Debian packages and implicitly install their dependencies +{%- for deb in docker_base_debs.split(' ') %} +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt debs/{{ deb }} +{%- endfor %} +{%- endif %} + +{% if docker_base_dbgs.strip() -%} +# Install common debug-packages +{%- for dbg_pkg in docker_base_dbgs.split(' ') %} +RUN apt-get -y install {{ dbg_pkg }} +{%- endfor %} +{% else %} +RUN ln /usr/bin/vim.tiny /usr/bin/vim +{%- endif %} + +# Clean up apt +# Remove /var/lib/apt/lists/*, could be obsoleted for derived images +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /var/lib/apt/lists/* + +RUN rm -rf /tmp/* diff --git a/dockers/docker-base/LICENSE b/dockers/docker-base/LICENSE new file mode 100644 index 000000000000..03d8f31e513c --- /dev/null +++ b/dockers/docker-base/LICENSE @@ -0,0 +1,13 @@ +Copyright 2016 Microsoft, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/dockers/docker-base/dpkg_01_drop b/dockers/docker-base/dpkg_01_drop new file mode 100644 index 000000000000..e75ef3147158 --- /dev/null +++ b/dockers/docker-base/dpkg_01_drop @@ -0,0 +1,22 @@ +## Drop unnecessary files +## ref: https://wiki.ubuntu.com/ReducingDiskFootprint + +## Documentation +path-exclude /usr/share/doc/* +# we need to keep copyright files for legal reasons +path-include /usr/share/doc/*/copyright +path-exclude /usr/share/man/* +path-exclude /usr/share/groff/* +path-exclude /usr/share/info/* +# lintian stuff is small, but really unnecessary +path-exclude /usr/share/lintian/* +path-exclude /usr/share/linda/* + +## Translations +path-exclude /usr/share/locale/* + +## Landscape +path-exclude /usr/share/pyshared/twisted/test* +path-exclude /usr/lib/python*/dist-packages/twisted/test* +path-exclude /usr/share/pyshared/twisted/*/test* +path-exclude /usr/lib/python*/dist-packages/twisted/*/test* diff --git a/dockers/docker-base/etc/rsyslog.conf b/dockers/docker-base/etc/rsyslog.conf new file mode 100644 index 000000000000..cf5509a3e8b3 --- /dev/null +++ b/dockers/docker-base/etc/rsyslog.conf @@ -0,0 +1,69 @@ +############################################################################### +# Managed by Ansible +# file: ansible/roles/acs/templates/rsyslog.conf.j2 +############################################################################### +# +# /etc/rsyslog.conf Configuration file for rsyslog. +# +# For more information see +# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html + + +################# +#### MODULES #### +################# + +$ModLoad imuxsock # provides support for local system logging +#$ModLoad imklog # provides kernel logging support +#$ModLoad immark # provides --MARK-- message capability + +# provides UDP syslog reception +#$ModLoad imudp +#$UDPServerRun 514 + +# provides TCP syslog reception +#$ModLoad imtcp +#$InputTCPServerRun 514 + + +########################### +#### GLOBAL DIRECTIVES #### +########################### + +# Set remote syslog server +template (name="ForwardFormatInContainer" type="string" string="<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg%") +*.* action(type="omfwd" target="127.0.0.1" port="514" protocol="udp" Template="ForwardFormatInContainer") + +# +# Use traditional timestamp format. +# To enable high precision timestamps, comment out the following line. +# +#$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat + +# Define a custom template +$template SONiCFileFormat,"%TIMESTAMP%.%timestamp:::date-subseconds% %HOSTNAME% %syslogseverity-text:::uppercase% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" +$ActionFileDefaultTemplate SONiCFileFormat + +# +# Set the default permissions for all log files. +# +$FileOwner root +$FileGroup adm +$FileCreateMode 0640 +$DirCreateMode 0755 +$Umask 0022 + +# +# Where to place spool and state files +# +$WorkDirectory /var/spool/rsyslog + +# +# Include all config files in /etc/rsyslog.d/ +# +$IncludeConfig /etc/rsyslog.d/*.conf + + +############### +#### RULES #### +############### diff --git a/dockers/docker-base/etc/rsyslog.d/supervisor.conf b/dockers/docker-base/etc/rsyslog.d/supervisor.conf new file mode 100644 index 000000000000..e6fece313efc --- /dev/null +++ b/dockers/docker-base/etc/rsyslog.d/supervisor.conf @@ -0,0 +1,8 @@ +$ModLoad imfile + +$InputFileName /var/log/supervisor/supervisord.log +$InputFileTag supervisord +$InputFileStateFile state-supervisor +$InputFileSeverity info +$InputFileFacility local0 +$InputRunFileMonitor diff --git a/dockers/docker-base/etc/supervisor/supervisord.conf b/dockers/docker-base/etc/supervisor/supervisord.conf new file mode 100644 index 000000000000..351cc06fc048 --- /dev/null +++ b/dockers/docker-base/etc/supervisor/supervisord.conf @@ -0,0 +1,33 @@ +; supervisor config file + +[unix_http_server] +file=/var/run/supervisor.sock ; (the path to the socket file) +chmod=0700 ; sockef file mode (default 0700) +username=dummy +password=dummy + +[supervisord] +logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) +pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) +childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) +user=root + +; the below section must remain in the config file for RPC +; (supervisorctl/web interface) to work, additional interfaces may be +; added by defining them in separate rpcinterface: sections +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[supervisorctl] +serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket +username=dummy +password=dummy + +; The [include] section can just contain the "files" setting. This +; setting can list multiple files (separated by whitespace or +; newlines). It can also contain wildcards. The filenames are +; interpreted as relative to this file. Included files *cannot* +; include files themselves. + +[include] +files = /etc/supervisor/conf.d/*.conf diff --git a/dockers/docker-base/no_install_recommend_suggest b/dockers/docker-base/no_install_recommend_suggest new file mode 100644 index 000000000000..b5bca577de1e --- /dev/null +++ b/dockers/docker-base/no_install_recommend_suggest @@ -0,0 +1,5 @@ +# Instruct apt-get to NOT install "recommended" or "suggested" packages by +# default when installing a package. + +APT::Install-Recommends "false"; +APT::Install-Suggests "false"; diff --git a/dockers/docker-base/root/.vimrc b/dockers/docker-base/root/.vimrc new file mode 100644 index 000000000000..5c1ba8a04f47 --- /dev/null +++ b/dockers/docker-base/root/.vimrc @@ -0,0 +1,2 @@ +" enable vim features +set nocompatible diff --git a/dockers/docker-base/sources.list b/dockers/docker-base/sources.list new file mode 100644 index 000000000000..7121d6fd8c2d --- /dev/null +++ b/dockers/docker-base/sources.list @@ -0,0 +1,8 @@ +## Debian mirror on Microsoft Azure +## Ref: http://debian-archive.trafficmanager.net/ + +deb http://debian-archive.trafficmanager.net/debian/ jessie main contrib non-free +deb-src http://debian-archive.trafficmanager.net/debian/ jessie main contrib non-free +deb http://debian-archive.trafficmanager.net/debian-security/ jessie/updates main contrib non-free +deb-src http://debian-archive.trafficmanager.net/debian-security/ jessie/updates main contrib non-free +deb http://debian-archive.trafficmanager.net/debian/ jessie-backports main contrib non-free diff --git a/dockers/docker-basic_router/Dockerfile b/dockers/docker-basic_router/Dockerfile new file mode 100644 index 000000000000..7d7c724920c2 --- /dev/null +++ b/dockers/docker-basic_router/Dockerfile @@ -0,0 +1,22 @@ +FROM docker-base + +MAINTAINER Xudong Wu + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +## Update apt's cache of available packages +RUN apt-get clean && apt-get update + +COPY deps /deps + +RUN dpkg -i /deps/libopennsl_*.deb; \ + dpkg -i /deps/libsaibcm_*.deb; \ + apt-get -y install -f + +RUN mv /deps/basic_router /usr/sbin/basic_router + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/dockers/docker-basic_router/start.sh b/dockers/docker-basic_router/start.sh new file mode 100755 index 000000000000..a4d378ef77d9 --- /dev/null +++ b/dockers/docker-basic_router/start.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd diff --git a/dockers/docker-basic_router/supervisord.conf b/dockers/docker-basic_router/supervisord.conf new file mode 100644 index 000000000000..bfa84fdcdfb5 --- /dev/null +++ b/dockers/docker-basic_router/supervisord.conf @@ -0,0 +1,20 @@ +[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 diff --git a/dockers/docker-config-engine/Dockerfile.j2 b/dockers/docker-config-engine/Dockerfile.j2 new file mode 100644 index 000000000000..bc82e1ca2883 --- /dev/null +++ b/dockers/docker-config-engine/Dockerfile.j2 @@ -0,0 +1,47 @@ +FROM docker-base + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +# Dependencies for sonic-cfggen +RUN apt-get install -y python-lxml python-yaml python-bitarray python-pip python-dev python-natsort + +RUN pip install --upgrade pip + +RUN pip install netaddr ipaddr jinja2 pyangbind==0.5.10 + +{% if docker_config_engine_debs.strip() %} +COPY \ +{% for deb in docker_config_engine_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ +{%- endif -%} + +{% if docker_config_engine_debs.strip() %} +RUN dpkg -i \ +{% for deb in docker_config_engine_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} +{%- endif -%} + +{% if docker_config_engine_whls.strip() %} +COPY \ +{% for whl in docker_config_engine_whls.split(' ') -%} +python-wheels/{{ whl }}{{' '}} +{%- endfor -%} +python-wheels/ +{%- endif -%} + +{% if docker_config_engine_whls.strip() %} +RUN pip install \ +{% for whl in docker_config_engine_whls.split(' ') -%} +python-wheels/{{ whl }}{{' '}} +{%- endfor %} +{%- endif -%} + +## Clean up +RUN apt-get remove -y python-pip python-dev; apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs /python-wheels diff --git a/dockers/docker-database/Dockerfile.j2 b/dockers/docker-database/Dockerfile.j2 new file mode 100644 index 000000000000..e24d528a980e --- /dev/null +++ b/dockers/docker-database/Dockerfile.j2 @@ -0,0 +1,40 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#syslogtag%/;" /etc/rsyslog.conf + +# Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +# Update apt's cache of available packages +RUN apt-get update + +{% if docker_database_debs.strip() -%} +# Copy locally-built Debian package dependencies +{%- for deb in docker_database_debs.split(' ') %} +COPY debs/{{ deb }} /debs/ +{%- endfor %} + +# Install locally-built Debian packages and implicitly install their dependencies +{%- for deb in docker_database_debs.split(' ') %} +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /debs/{{ deb }} +{%- endfor %} +{%- endif %} + +# Clean up +RUN apt-get clean -y +RUN apt-get autoclean -y +RUN apt-get autoremove -y +RUN rm -rf /debs ~/.cache + +RUN sed -ri 's/^(save .*$)/# \1/g; \ + s/^daemonize yes$/daemonize no/; \ + s/^logfile .*$/logfile ""/; \ + s/^# syslog-enabled no$/syslog-enabled no/; \ + s/^# unixsocket/unixsocket/; \ + s/^client-output-buffer-limit pubsub [0-9]+mb [0-9]+mb [0-9]+/client-output-buffer-limit pubsub 0 0 0/ \ + ' /etc/redis/redis.conf + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/dockers/docker-database/base_image_files/redis-cli b/dockers/docker-database/base_image_files/redis-cli new file mode 100755 index 000000000000..6ce1951cd4b9 --- /dev/null +++ b/dockers/docker-database/base_image_files/redis-cli @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS database redis-cli "$@" diff --git a/dockers/docker-database/supervisord.conf b/dockers/docker-database/supervisord.conf new file mode 100644 index 000000000000..798fedd0c895 --- /dev/null +++ b/dockers/docker-database/supervisord.conf @@ -0,0 +1,21 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[program:rsyslogd] +command=/bin/bash -c "rm -f /var/run/rsyslogd.pid && /usr/sbin/rsyslogd -n" +priority=1 +autostart=true +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:redis-server] +command=/bin/bash -c "{ [[ -s /var/lib/redis/dump.rdb ]] || rm -f /var/lib/redis/dump.rdb; } && exec /usr/bin/redis-server /etc/redis/redis.conf" +priority=2 +autostart=true +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + diff --git a/dockers/docker-dhcp-relay/Dockerfile.j2 b/dockers/docker-dhcp-relay/Dockerfile.j2 new file mode 100644 index 000000000000..0a760d301f3a --- /dev/null +++ b/dockers/docker-dhcp-relay/Dockerfile.j2 @@ -0,0 +1,31 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +# Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +# Update apt's cache of available packages +RUN apt-get update + +{% if docker_dhcp_relay_debs.strip() -%} +# Copy built Debian packages +{%- for deb in docker_dhcp_relay_debs.split(' ') %} +COPY debs/{{ deb }} debs/ +{%- endfor %} + +# Install built Debian packages and implicitly install their dependencies +{%- for deb in docker_dhcp_relay_debs.split(' ') %} +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt debs/{{ deb }} +{%- endfor %} +{%- endif %} + +# Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +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/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/start.sh b/dockers/docker-dhcp-relay/start.sh new file mode 100755 index 000000000000..0ac5ea1a10ec --- /dev/null +++ b/dockers/docker-dhcp-relay/start.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# Remove stale rsyslog PID file if it exists +rm -f /var/run/rsyslogd.pid + +# Start rsyslog +supervisorctl start rsyslogd + +# If our supervisor config has entries in the "isc-dhcp-relay" group... +if [ $(supervisorctl status | grep -c "^isc-dhcp-relay:") -gt 0 ]; then + # Wait for all interfaces to come up and be assigned IPv4 addresses before + # starting the DHCP relay agent(s). If an interface the relay should listen + # on is down, the relay agent will not start. If an interface the relay + # should listen on is up but does not have an IP address assigned when the + # relay agent starts, it will not listen or send on that interface for the + # lifetime of the process. + /usr/bin/wait_for_intf.sh + + # Start all DHCP relay agent(s) + supervisorctl start isc-dhcp-relay:* +fi diff --git a/dockers/docker-dhcp-relay/wait_for_intf.sh.j2 b/dockers/docker-dhcp-relay/wait_for_intf.sh.j2 new file mode 100644 index 000000000000..037dc66ead63 --- /dev/null +++ b/dockers/docker-dhcp-relay/wait_for_intf.sh.j2 @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +function wait_until_iface_ready +{ + IFACE=$1 + + echo "Waiting until interface $IFACE is up..." + + # Wait for the interface to come up (i.e., 'ip link show' returns 0) + until ip link show dev $IFACE up > /dev/null 2>&1; do + sleep 1 + done + + echo "Interface $IFACE is up" + + echo "Waiting until interface $IFACE has an IPv4 address..." + + # Wait until the interface gets assigned an IPv4 address + while true; do + IP=$(ip -4 addr show dev $IFACE | grep "inet " | awk '{ print $2 }' | cut -d '/' -f1) + + if [ -n "$IP" ]; then + break + fi + + sleep 1 + done + + echo "Interface $IFACE is configured with IP $IP" +} + + +# Wait for all interfaces to come up and have IPv4 addresses assigned +{% for (name, prefix) in INTERFACE %} +wait_until_iface_ready {{ name }} +{% endfor %} +{% for (name, prefix) in VLAN_INTERFACE %} +wait_until_iface_ready {{ name }} +{% endfor %} +{% for (name, prefix) in PORTCHANNEL_INTERFACE %} +wait_until_iface_ready {{ name }} +{% endfor %} diff --git a/dockers/docker-fpm-frr/Dockerfile.j2 b/dockers/docker-fpm-frr/Dockerfile.j2 new file mode 100644 index 000000000000..6f046af6cf27 --- /dev/null +++ b/dockers/docker-fpm-frr/Dockerfile.j2 @@ -0,0 +1,47 @@ +FROM docker-config-engine + +ARG docker_container_name +ARG frr_user_uid +ARG frr_user_gid + +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +# Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +# Update apt's cache of available packages +RUN apt-get update + +# Install required packages +RUN apt-get install -y libdbus-1-3 libdaemon0 libjansson4 libc-ares2 iproute libpython2.7 + +{% if docker_fpm_frr_debs.strip() -%} +# Copy locally-built Debian package dependencies +{%- for deb in docker_fpm_frr_debs.split(' ') %} +COPY debs/{{ deb }} /debs/ +{%- endfor %} + +RUN groupadd -g ${frr_user_gid} frr +RUN useradd -u ${frr_user_uid} -g ${frr_user_gid} -M -s /bin/false frr + +# Install locally-built Debian packages and implicitly install their dependencies +{%- for deb in docker_fpm_frr_debs.split(' ') %} +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /debs/{{ deb }} +{%- endfor %} +{%- endif %} + +# Clean up +RUN apt-get clean -y +RUN apt-get autoclean -y +RUN apt-get autoremove -y +RUN rm -rf /debs ~/.cache + +COPY ["*.j2", "/usr/share/sonic/templates/"] +COPY ["start.sh", "config.sh", "/usr/bin/"] +COPY ["daemons", "/etc/frr/"] +COPY ["daemons.conf", "/etc/frr/"] +COPY ["vtysh.conf", "/etc/frr/"] + +ENTRYPOINT /usr/bin/config.sh \ + && /usr/bin/start.sh \ + && /bin/bash diff --git a/dockers/docker-fpm-frr/base_image_files/vtysh b/dockers/docker-fpm-frr/base_image_files/vtysh new file mode 100755 index 000000000000..24016bd96b2c --- /dev/null +++ b/dockers/docker-fpm-frr/base_image_files/vtysh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + # Prepare a function to send HUP signal to vtysh in the container + # we mark the new instance of vtysh with the current tty as a tag + TTY=$(tty) + function cleanup + { + docker exec -i bgp pkill -HUP -f "vtysh $TTY" + } + trap cleanup HUP + docker exec -ti bgp vtysh "$TTY" "$@" +else + docker exec -i bgp vtysh "$@" +fi diff --git a/dockers/docker-fpm-frr/config.sh b/dockers/docker-fpm-frr/config.sh new file mode 100755 index 000000000000..5e481d0c8516 --- /dev/null +++ b/dockers/docker-fpm-frr/config.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +mkdir -p /etc/frr + +CONFIG_TYPE=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["docker_routing_config_mode"]'` + +if [ -z "$CONFIG_TYPE" ] || [ "$CONFIG_TYPE" == "unified" ]; then + sonic-cfggen -d -t /usr/share/sonic/templates/frr.conf.j2 >/etc/frr/frr.conf +fi + +sonic-cfggen -d -t /usr/share/sonic/templates/isolate.j2 >/usr/sbin/bgp-isolate +chown root:root /usr/sbin/bgp-isolate +chmod 0755 /usr/sbin/bgp-isolate + +sonic-cfggen -d -t /usr/share/sonic/templates/unisolate.j2 >/usr/sbin/bgp-unisolate +chown root:root /usr/sbin/bgp-unisolate +chmod 0755 /usr/sbin/bgp-unisolate + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" >/var/sonic/config_status diff --git a/dockers/docker-fpm-frr/daemons b/dockers/docker-fpm-frr/daemons new file mode 100644 index 000000000000..c008d1248bf3 --- /dev/null +++ b/dockers/docker-fpm-frr/daemons @@ -0,0 +1,36 @@ +# This file tells the frr package which daemons to start. +# +# Entries are in the format: =(yes|no|priority) +# 0, "no" = disabled +# 1, "yes" = highest priority +# 2 .. 10 = lower priorities +# Read /usr/share/doc/frr/README.Debian for details. +# +# Sample configurations for these daemons can be found in +# /usr/share/doc/frr/examples/. +# +# ATTENTION: +# +# When activation a daemon at the first time, a config file, even if it is +# empty, has to be present *and* be owned by the user and group "frr", else +# the daemon will not be started by /etc/init.d/frr. The permissions should +# be u=rw,g=r,o=. +# When using "vtysh" such a config file is also needed. It should be owned by +# group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too. +# +# The watchfrr daemon is always started. Per default in monitoring-only but +# that can be changed via /etc/frr/daemons.conf. +# +zebra=yes +bgpd=yes +ospfd=no +ospf6d=no +ripd=no +ripngd=no +isisd=no +pimd=no +ldpd=no +nhrpd=no +eigrpd=no +babeld=no +sharpd=no diff --git a/dockers/docker-fpm-frr/daemons.conf b/dockers/docker-fpm-frr/daemons.conf new file mode 100644 index 000000000000..33f4acd0ae88 --- /dev/null +++ b/dockers/docker-fpm-frr/daemons.conf @@ -0,0 +1,28 @@ +# +# If this option is set the /etc/init.d/frr script automatically loads +# the config via "vtysh -b" when the servers are started. +# Check /etc/pam.d/frr if you intend to use "vtysh"! +# +vtysh_enable=yes +zebra_options=" -s 90000000 --daemon -A 127.0.0.1 -M fpm" +bgpd_options=" --daemon -A 127.0.0.1" +ospfd_options=" --daemon -A 127.0.0.1" +ospf6d_options=" --daemon -A ::1" +ripd_options=" --daemon -A 127.0.0.1" +ripngd_options=" --daemon -A ::1" +isisd_options=" --daemon -A 127.0.0.1" +pimd_options=" --daemon -A 127.0.0.1" +ldpd_options=" --daemon -A 127.0.0.1" +nhrpd_options=" --daemon -A 127.0.0.1" +eigrpd_options=" --daemon -A 127.0.0.1" +babeld_options=" --daemon -A 127.0.0.1" +sharpd_options=" --daemon -A 127.0.0.1" + +# The list of daemons to watch is automatically generated by the init script. +watchfrr_enable=yes +watchfrr_options=(-d -r /usr/sbin/servicebBfrrbBrestartbB%s -s /usr/sbin/servicebBfrrbBstartbB%s -k /usr/sbin/servicebBfrrbBstopbB%s -b bB -t 30) + +# If valgrind_enable is 'yes' the frr daemons will be started via valgrind. +# The use case for doing so is tracking down memory leaks, etc in frr. +valgrind_enable=no +valgrind=/usr/bin/valgrind diff --git a/dockers/docker-fpm-frr/frr.conf.j2 b/dockers/docker-fpm-frr/frr.conf.j2 new file mode 100644 index 000000000000..d4fdec897da2 --- /dev/null +++ b/dockers/docker-fpm-frr/frr.conf.j2 @@ -0,0 +1,209 @@ +! +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr/frr.conf.j2 with config DB data +! file: frr.conf +! +{% endblock banner %} +! +{% block system_init %} +hostname {{ DEVICE_METADATA['localhost']['hostname'] }} +password zebra +log syslog informational +log facility local4 +! enable password {# {{ en_passwd }} TODO: param needed #} +{% endblock system_init %} +! +{% block interfaces %} +! Enable link-detect (default disabled) +{% for (name, prefix) in INTERFACE %} +interface {{ name }} +link-detect +! +{% endfor %} +{% for pc in PORTCHANNEL %} +interface {{ pc }} +link-detect +! +{% endfor %} +{% endblock interfaces %} +! +{% block default_route %} +! set static default route to mgmt gateway as a backup to learned default +{% for (name, prefix) in MGMT_INTERFACE %} +{% if prefix | ipv4 %} +ip route 0.0.0.0/0 {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} 200 +{% endif %} +{% endfor %} +{% endblock default_route %} +! +{% block source_loopback %} +{% set lo_ipv4_addrs = [] %} +{% set lo_ipv6_addrs = [] %} +{% if LOOPBACK_INTERFACE %} +{% for (name, prefix) in LOOPBACK_INTERFACE %} +{% if name == 'Loopback0' %} +{% if prefix | ipv6 %} +{% if lo_ipv6_addrs.append(prefix) %} +{% endif %} +{% else %} +{% if lo_ipv4_addrs.append(prefix) %} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +! Set ip source to loopback for bgp learned routes +route-map RM_SET_SRC permit 10 + set src {{ lo_ipv4_addrs[0] | ip }} +! +{% if lo_ipv6_addrs|length > 0 %} +route-map RM_SET_SRC6 permit 10 + set src {{ lo_ipv6_addrs[0] | ip }} +! +{% endif %} +ip protocol bgp route-map RM_SET_SRC +! +{% if lo_ipv6_addrs|length > 0 %} +ipv6 protocol bgp route-map RM_SET_SRC6 +! +{% endif %} +{% endblock source_loopback %} +! +{% if DEVICE_METADATA['localhost'].has_key('bgp_asn') %} +{% block bgp_init %} +! +! bgp multiple-instance +! +route-map FROM_BGP_SPEAKER_V4 permit 10 +! +route-map TO_BGP_SPEAKER_V4 deny 10 +! +router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast +{# Advertise graceful restart capability for ToR #} +{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %} + bgp graceful-restart +{% endif %} +{% for (name, prefix) in LOOPBACK_INTERFACE %} +{% if prefix | ipv4 and name == 'Loopback0' %} + bgp router-id {{ prefix | ip }} +{% endif %} +{% endfor %} +{# advertise loopback #} +{% for (name, prefix) in LOOPBACK_INTERFACE %} +{% if prefix | ipv4 and name == 'Loopback0' %} + network {{ prefix | ip }}/32 +{% elif prefix | ipv6 and name == 'Loopback0' %} + address-family ipv6 + network {{ prefix | ip }}/128 + exit-address-family +{% endif %} +{% endfor %} +{% endblock bgp_init %} +{% endif %} +{% block vlan_advertisement %} +{% for (name, prefix) in VLAN_INTERFACE %} +{% if prefix | ipv4 %} + network {{ prefix }} +{% elif prefix | ipv6 %} + address-family ipv6 + network {{ prefix }} + exit-address-family +{% endif %} +{% endfor %} +{% endblock vlan_advertisement %} +{% block bgp_sessions %} +{% for neighbor_addr, bgp_session in BGP_NEIGHBOR.iteritems() %} +{% if bgp_session['asn'] | int != 0 %} + neighbor {{ neighbor_addr }} remote-as {{ bgp_session['asn'] }} + neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }} +{# set the bgp neighbor timers if they have not default values #} +{% if (bgp_session['keepalive'] is defined and bgp_session['keepalive'] | int != 60) + or (bgp_session['holdtime'] is defined and bgp_session['holdtime'] | int != 180) %} + neighbor {{ neighbor_addr }} timers {{ bgp_session['keepalive'] }} {{ bgp_session['holdtime'] }} +{% endif %} +{% if bgp_session.has_key('admin_status') and bgp_session['admin_status'] == 'down' or not bgp_session.has_key('admin_status') and DEVICE_METADATA['localhost'].has_key('default_bgp_status') and DEVICE_METADATA['localhost']['default_bgp_status'] == 'down' %} + neighbor {{ neighbor_addr }} shutdown +{% endif %} +{% if neighbor_addr | ipv4 %} + address-family ipv4 +{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %} + neighbor {{ neighbor_addr }} allowas-in 1 +{% endif %} + neighbor {{ neighbor_addr }} activate + neighbor {{ neighbor_addr }} soft-reconfiguration inbound +{% 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 +{% endif %} +{% if neighbor_addr | ipv6 %} + address-family ipv6 +{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %} + neighbor {{ neighbor_addr }} allowas-in 1 +{% endif %} + neighbor {{ neighbor_addr }} activate + neighbor {{ neighbor_addr }} soft-reconfiguration inbound +{% 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 +{% endif %} +{% endif %} +{% endfor %} +{% endblock bgp_sessions %} +{% block bgp_peers_with_range %} +{% if BGP_PEER_RANGE %} +{% for bgp_peer in BGP_PEER_RANGE.values() %} + neighbor {{ bgp_peer['name'] }} peer-group + neighbor {{ bgp_peer['name'] }} passive + neighbor {{ bgp_peer['name'] }} remote-as {{ deployment_id_asn_map[DEVICE_METADATA['localhost']['deployment_id']] }} + neighbor {{ bgp_peer['name'] }} ebgp-multihop 255 +{% for (name, prefix) in LOOPBACK_INTERFACE %} +{% if name == 'Loopback1' %} + neighbor {{ bgp_peer['name'] }} update-source {{ prefix | ip }} +{% endif %} +{% endfor %} +{% for ip_range in bgp_peer['ip_range'] %} + bgp listen range {{ip_range}} peer-group {{ bgp_peer['name'] }} +{% endfor %} + address-family ipv4 + neighbor {{ bgp_peer['name'] }} activate + neighbor {{ bgp_peer['name'] }} soft-reconfiguration inbound + neighbor {{ bgp_peer['name'] }} route-map FROM_BGP_SPEAKER_V4 in + neighbor {{ bgp_peer['name'] }} route-map TO_BGP_SPEAKER_V4 out + maximum-paths 64 + exit-address-family + address-family ipv6 + neighbor {{ bgp_peer['name'] }} activate + neighbor {{ bgp_peer['name'] }} soft-reconfiguration inbound + maximum-paths 64 + exit-address-family +{% endfor %} +{% endif %} +{% endblock bgp_peers_with_range %} +! +{% if DEVICE_METADATA['localhost'].has_key('bgp_asn') %} +maximum-paths 64 +! +route-map ISOLATE permit 10 +set as-path prepend {{ DEVICE_METADATA['localhost']['bgp_asn'] }} +{% endif %} +! +route-map set-next-hop-global-v6 permit 10 +set ipv6 next-hop prefer-global +! diff --git a/dockers/docker-fpm-frr/isolate.j2 b/dockers/docker-fpm-frr/isolate.j2 new file mode 100755 index 000000000000..cfcd023ea1f3 --- /dev/null +++ b/dockers/docker-fpm-frr/isolate.j2 @@ -0,0 +1,20 @@ +#!/bin/bash +## vtysh only accepts script in stdin, so cannot be directly used in shebang +## Cut the tail of this script and feed vtysh stdin +sed -n -e '9,$p' < "$0" | vtysh "$@" +## Exit with vtysh return code +exit $? + +## vtysh script start from next line, which line number MUST equal in 'sed' command above + +configure terminal + router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} +{% for neighbor_addr in BGP_NEIGHBOR %} + neighbor {{ neighbor_addr }} route-map ISOLATE out +{% endfor %} + exit +exit + +{% for neighbor_addr in BGP_NEIGHBOR %} +clear ip bgp {{ neighbor_addr }} soft out +{% endfor %} diff --git a/dockers/docker-fpm-frr/start.sh b/dockers/docker-fpm-frr/start.sh new file mode 100755 index 000000000000..f46a42b4c34c --- /dev/null +++ b/dockers/docker-fpm-frr/start.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +rm -f /var/run/rsyslogd.pid +service rsyslog start +service frr start +fpmsyncd & diff --git a/dockers/docker-fpm-frr/unisolate.j2 b/dockers/docker-fpm-frr/unisolate.j2 new file mode 100755 index 000000000000..2a0780745d75 --- /dev/null +++ b/dockers/docker-fpm-frr/unisolate.j2 @@ -0,0 +1,20 @@ +#!/bin/bash +## vtysh only accepts script in stdin, so cannot be directly used in shebang +## Cut the tail of this script and feed vtysh stdin +sed -n -e '9,$p' < "$0" | vtysh "$@" +## Exit with vtysh return code +exit $? + +## vtysh script start from next line, which line number MUST equal in 'sed' command above + +configure terminal + router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} +{% for neighbor_ip in BGP_NEIGHBOR %} + no neighbor {{ neighbor_ip }} route-map ISOLATE out +{% endfor %} + exit +exit + +{% for neighbor_ip in BGP_NEIGHBOR %} +clear ip bgp {{ neighbor_ip }} soft out +{% endfor %} diff --git a/dockers/docker-fpm-frr/vtysh.conf b/dockers/docker-fpm-frr/vtysh.conf new file mode 100644 index 000000000000..e0ab9cb6f314 --- /dev/null +++ b/dockers/docker-fpm-frr/vtysh.conf @@ -0,0 +1 @@ +service integrated-vtysh-config diff --git a/dockers/docker-fpm-gobgp/Dockerfile.j2 b/dockers/docker-fpm-gobgp/Dockerfile.j2 new file mode 100644 index 000000000000..1e333d9026c0 --- /dev/null +++ b/dockers/docker-fpm-gobgp/Dockerfile.j2 @@ -0,0 +1,28 @@ +FROM docker-fpm-quagga + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_fpm_gobgp_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_fpm_gobgp_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["*.j2", "/usr/share/sonic/templates/"] +COPY ["daemons", "/etc/quagga/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/dockers/docker-fpm-gobgp/daemons b/dockers/docker-fpm-gobgp/daemons new file mode 100644 index 000000000000..6832c3db78d0 --- /dev/null +++ b/dockers/docker-fpm-gobgp/daemons @@ -0,0 +1,31 @@ +# This file tells the quagga package which daemons to start. +# +# Entries are in the format: =(yes|no|priority) +# 0, "no" = disabled +# 1, "yes" = highest priority +# 2 .. 10 = lower priorities +# Read /usr/share/doc/quagga/README.Debian for details. +# +# Sample configurations for these daemons can be found in +# /usr/share/doc/quagga/examples/. +# +# ATTENTION: +# +# When activation a daemon at the first time, a config file, even if it is +# empty, has to be present *and* be owned by the user and group "quagga", else +# the daemon will not be started by /etc/init.d/quagga. The permissions should +# be u=rw,g=r,o=. +# When using "vtysh" such a config file is also needed. It should be owned by +# group "quaggavty" and set to ug=rw,o= though. Check /etc/pam.d/quagga, too. +# +# The watchquagga daemon is always started. Per default in monitoring-only but +# that can be changed via /etc/quagga/debian.conf. +# +zebra=yes +bgpd=no +ospfd=no +ospf6d=no +ripd=no +ripngd=no +isisd=no +babeld=no diff --git a/dockers/docker-fpm-gobgp/gobgpd.conf.j2 b/dockers/docker-fpm-gobgp/gobgpd.conf.j2 new file mode 100644 index 000000000000..a4fb80bf11ca --- /dev/null +++ b/dockers/docker-fpm-gobgp/gobgpd.conf.j2 @@ -0,0 +1,28 @@ +[global.config] + as = {{ DEVICE_METADATA['localhost']['bgp_asn'] }} + router-id = "{{ LOOPBACK_INTERFACE.keys()[0][1] }}" +{% for neighbor_addr, bgp_session in BGP_NEIGHBOR.iteritems() %} +{% if bgp_session['asn'] | int != 0 %} +[[neighbors]] + [neighbors.config] + peer-as = {{ bgp_session['asn'] }} + neighbor-address = "{{ neighbor_addr }}" + [neighbors.graceful-restart.config] + enabled = true + [[neighbors.afi-safis]] + [neighbors.afi-safis.config] +{% if neighbor_addr | ipv6 %} + afi-safi-name = "ipv6-unicast" +{% else %} + afi-safi-name = "ipv4-unicast" +{% endif %} + [neighbors.afi-safis.mp-graceful-restart.config] + enabled = true +{% endif %} +{% endfor %} +[zebra] + [zebra.config] + enabled = true + url = "unix:/var/run/quagga/zserv.api" + redistribute-route-type-list = ["connect"] + diff --git a/dockers/docker-fpm-gobgp/isolate.j2 b/dockers/docker-fpm-gobgp/isolate.j2 new file mode 100755 index 000000000000..4502ff895777 --- /dev/null +++ b/dockers/docker-fpm-gobgp/isolate.j2 @@ -0,0 +1,4 @@ +#!/bin/bash + +echo Not implemented yet +exit diff --git a/dockers/docker-fpm-gobgp/start.sh b/dockers/docker-fpm-gobgp/start.sh new file mode 100755 index 000000000000..83afbda4f736 --- /dev/null +++ b/dockers/docker-fpm-gobgp/start.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +mkdir -p /etc/quagga +sonic-cfggen -d -t /usr/share/sonic/templates/gobgpd.conf.j2 > /etc/gobgp/gobgpd.conf +sonic-cfggen -d -t /usr/share/sonic/templates/zebra.conf.j2 > /etc/quagga/zebra.conf + +sonic-cfggen -d -t /usr/share/sonic/templates/isolate.j2 > /usr/sbin/bgp-isolate +chown root:root /usr/sbin/bgp-isolate +chmod 0755 /usr/sbin/bgp-isolate + +sonic-cfggen -d -t /usr/share/sonic/templates/unisolate.j2 > /usr/sbin/bgp-unisolate +chown root:root /usr/sbin/bgp-unisolate +chmod 0755 /usr/sbin/bgp-unisolate + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +# Quagga has its own monitor process, 'watchquagga' +service quagga start + +supervisorctl start fpmsyncd diff --git a/dockers/docker-fpm-gobgp/supervisord.conf b/dockers/docker-fpm-gobgp/supervisord.conf new file mode 100644 index 000000000000..4e635f4093d4 --- /dev/null +++ b/dockers/docker-fpm-gobgp/supervisord.conf @@ -0,0 +1,36 @@ +[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:gobgpd] +command=/usr/sbin/gobgpd -p -f /etc/gobgp/gobgpd.conf -r +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:fpmsyncd] +command=fpmsyncd +priority=5 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/dockers/docker-fpm-gobgp/unisolate.j2 b/dockers/docker-fpm-gobgp/unisolate.j2 new file mode 100755 index 000000000000..69172744bae7 --- /dev/null +++ b/dockers/docker-fpm-gobgp/unisolate.j2 @@ -0,0 +1,5 @@ +#!/bin/bash + +echo Not implemented yet +exit + diff --git a/dockers/docker-fpm-gobgp/zebra.conf.j2 b/dockers/docker-fpm-gobgp/zebra.conf.j2 new file mode 100644 index 000000000000..8b967f98671c --- /dev/null +++ b/dockers/docker-fpm-gobgp/zebra.conf.j2 @@ -0,0 +1,74 @@ +! +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/zebra.conf.j2 using config DB data +! file: zebra.conf +! +{% endblock banner %} +! +{% block sys_init %} +hostname {{ DEVICE_METADATA['localhost']['hostname'] }} +password zebra +enable password zebra +{% endblock sys_init %} +! +{% block interfaces %} +! Enable link-detect (default disabled) +{% for (name, prefix) in INTERFACE %} +interface {{ name }} +link-detect +! +{% endfor %} +{% for pc in PORTCHANNEL %} +interface {{ pc }} +link-detect +! +{% endfor %} +{% endblock interfaces %} +! +{% block default_route %} +! set static default route to mgmt gateway as a backup to learned default +{% for (name, prefix) in MGMT_INTERFACE %} +{% if prefix | ipv4 %} +ip route 0.0.0.0/0 {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} 200 +{% endif %} +{% endfor %} +{% endblock default_route %} +! +{% block source_loopback %} +{% set lo_ipv4_addrs = [] %} +{% set lo_ipv6_addrs = [] %} +{% if LOOPBACK_INTERFACE %} +{% for (name, prefix) in LOOPBACK_INTERFACE %} +{% if prefix | ipv6 %} +{% if lo_ipv6_addrs.append(prefix) %} +{% endif %} +{% else %} +{% if lo_ipv4_addrs.append(prefix) %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +! Set ip source to loopback for bgp learned routes +route-map RM_SET_SRC permit 10 + set src {{ lo_ipv4_addrs[0] | ip }} +! +{% if lo_ipv6_addrs|length > 0 %} +route-map RM_SET_SRC6 permit 10 + set src {{ lo_ipv6_addrs[0] | ip }} +! +{% endif %} +ip protocol bgp route-map RM_SET_SRC +! +{% if lo_ipv6_addrs|length > 0 %} +ipv6 protocol bgp route-map RM_SET_SRC6 +! +{% endif %} +{% endblock source_loopback %} +! +{% block logging %} +log syslog informational +log facility local4 +{% endblock logging %} +! + diff --git a/dockers/docker-fpm-quagga/Dockerfile.j2 b/dockers/docker-fpm-quagga/Dockerfile.j2 new file mode 100644 index 000000000000..f048e2789429 --- /dev/null +++ b/dockers/docker-fpm-quagga/Dockerfile.j2 @@ -0,0 +1,37 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +# Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +# Update apt's cache of available packages +RUN apt-get update + +# Install required packages +RUN apt-get install -y libdbus-1-3 libdaemon0 libjansson4 libpython2.7 + +{% if docker_fpm_quagga_debs.strip() -%} +# Copy locally-built Debian package dependencies +{%- for deb in docker_fpm_quagga_debs.split(' ') %} +COPY debs/{{ deb }} /debs/ +{%- endfor %} + +# Install locally-built Debian packages and implicitly install their dependencies +{%- for deb in docker_fpm_quagga_debs.split(' ') %} +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /debs/{{ deb }} +{%- endfor %} +{%- endif %} + +# Clean up +RUN apt-get clean -y +RUN apt-get autoclean -y +RUN apt-get autoremove -y +RUN rm -rf /debs ~/.cache + +COPY ["bgpcfgd", "start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["*.j2", "/usr/share/sonic/templates/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/dockers/docker-fpm-quagga/base_image_files/vtysh b/dockers/docker-fpm-quagga/base_image_files/vtysh new file mode 100755 index 000000000000..24016bd96b2c --- /dev/null +++ b/dockers/docker-fpm-quagga/base_image_files/vtysh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + # Prepare a function to send HUP signal to vtysh in the container + # we mark the new instance of vtysh with the current tty as a tag + TTY=$(tty) + function cleanup + { + docker exec -i bgp pkill -HUP -f "vtysh $TTY" + } + trap cleanup HUP + docker exec -ti bgp vtysh "$TTY" "$@" +else + docker exec -i bgp vtysh "$@" +fi diff --git a/dockers/docker-fpm-quagga/bgpcfgd b/dockers/docker-fpm-quagga/bgpcfgd new file mode 100755 index 000000000000..012a766c20b9 --- /dev/null +++ b/dockers/docker-fpm-quagga/bgpcfgd @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +import sys +import redis +import subprocess +import syslog +from swsssdk import ConfigDBConnector + +class BGPConfigDaemon: + + def __init__(self): + self.config_db = ConfigDBConnector() + self.config_db.connect() + self.bgp_asn = self.config_db.get_entry('DEVICE_METADATA', 'localhost')['bgp_asn'] + self.bgp_neighbor = self.config_db.get_table('BGP_NEIGHBOR') + + def __run_command(self, command): +# print command + p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) + stdout = p.communicate()[0] + p.wait() + if p.returncode != 0: + syslog.syslog(syslog.LOG_ERR, '[bgp cfgd] command execution returned {}. Command: "{}", stdout: "{}"'.format(p.returncode, command, stdout)) + + def metadata_handler(self, key, data): + if key == 'localhost' and data.has_key('bgp_asn'): + if data['bgp_asn'] != self.bgp_asn: + syslog.syslog(syslog.LOG_INFO, '[bgp cfgd] ASN changed to {} from {}, restart BGP...'.format(data['bgp_asn'], self.bgp_asn)) + self.__run_command("supervisorctl restart start.sh") + self.__run_command("service quagga restart") + self.bgp_asn = data['bgp_asn'] + + def bgp_handler(self, key, data): + syslog.syslog(syslog.LOG_INFO, '[bgp cfgd] value for {} changed to {}'.format(key, data)) + if not data: + # Neighbor is deleted + command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'no neighbor {}'".format(self.bgp_asn, key) + self.__run_command(command) + self.bgp_neighbor.pop(key) + else: + command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} remote-as {}'".format(self.bgp_asn, key, data['asn']) + self.__run_command(command) + if data.has_key('name'): + command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} description {}'".format(self.bgp_asn, key, data['name']) + self.__run_command(command) + if data.has_key('admin_status'): + command_mod = 'no ' if data['admin_status'] == 'up' else '' + command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c '{}neighbor {} shutdown'".format(self.bgp_asn, command_mod, key) + self.__run_command(command) + self.bgp_neighbor[key] = data + + def start(self): + self.config_db.subscribe('BGP_NEIGHBOR', + lambda table, key, data: self.bgp_handler(key, data)) + self.config_db.subscribe('DEVICE_METADATA', + lambda table, key, data: self.metadata_handler(key, data)) + self.config_db.listen() + + +def main(): + daemon = BGPConfigDaemon() + daemon.start() + +if __name__ == "__main__": + main() diff --git a/dockers/docker-fpm-quagga/bgpd.conf.j2 b/dockers/docker-fpm-quagga/bgpd.conf.j2 new file mode 100644 index 000000000000..ebbe655e817a --- /dev/null +++ b/dockers/docker-fpm-quagga/bgpd.conf.j2 @@ -0,0 +1,131 @@ +! +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/bgpd.conf.j2 with config DB data +! file: bgpd.conf +! +{% endblock banner %} +! +{% block system_init %} +hostname {{ DEVICE_METADATA['localhost']['hostname'] }} +password zebra +log syslog informational +log facility local4 +! enable password {# {{ en_passwd }} TODO: param needed #} +{% endblock system_init %} +! +{% if DEVICE_METADATA['localhost'].has_key('bgp_asn') %} +{% block bgp_init %} +! +! bgp multiple-instance +! +route-map FROM_BGP_SPEAKER_V4 permit 10 +! +route-map TO_BGP_SPEAKER_V4 deny 10 +! +router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast + bgp graceful-restart +{% for (name, prefix) in LOOPBACK_INTERFACE %} +{% if prefix | ipv4 and name == 'Loopback0' %} + bgp router-id {{ prefix | ip }} +{% endif %} +{% endfor %} +{# advertise loopback #} +{% for (name, prefix) in LOOPBACK_INTERFACE %} +{% if prefix | ipv4 and name == 'Loopback0' %} + network {{ prefix | ip }}/32 +{% elif prefix | ipv6 and name == 'Loopback0' %} + address-family ipv6 + network {{ prefix | ip }}/64 + exit-address-family +{% endif %} +{% endfor %} +{% endblock bgp_init %} +{% endif %} +{% block vlan_advertisement %} +{% for (name, prefix) in VLAN_INTERFACE %} +{% if prefix | ipv4 %} + network {{ prefix }} +{% elif prefix | ipv6 %} + address-family ipv6 + network {{ prefix }} + exit-address-family +{% endif %} +{% endfor %} +{% endblock vlan_advertisement %} +{% block bgp_sessions %} +{% for neighbor_addr, bgp_session in BGP_NEIGHBOR.iteritems() %} +{% if bgp_session['asn'] | int != 0 %} + neighbor {{ neighbor_addr }} remote-as {{ bgp_session['asn'] }} + neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }} +{# set the bgp neighbor timers if they have not default values #} +{% if (bgp_session['keepalive'] is defined and bgp_session['keepalive'] | int != 60) + or (bgp_session['holdtime'] is defined and bgp_session['holdtime'] | int != 180) %} + neighbor {{ neighbor_addr }} timers {{ bgp_session['keepalive'] }} {{ bgp_session['holdtime'] }} +{% endif %} +{% if bgp_session.has_key('admin_status') and bgp_session['admin_status'] == 'down' or not bgp_session.has_key('admin_status') and DEVICE_METADATA['localhost'].has_key('default_bgp_status') and DEVICE_METADATA['localhost']['default_bgp_status'] == 'down' %} + neighbor {{ neighbor_addr }} shutdown +{% endif %} +{% if neighbor_addr | ipv4 %} + address-family ipv4 +{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %} + neighbor {{ neighbor_addr }} allowas-in 1 +{% endif %} + neighbor {{ neighbor_addr }} activate + neighbor {{ neighbor_addr }} soft-reconfiguration inbound + maximum-paths 64 + exit-address-family +{% endif %} +{% if neighbor_addr | ipv6 %} + address-family ipv6 +{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %} + neighbor {{ neighbor_addr }} allowas-in 1 +{% endif %} + neighbor {{ neighbor_addr }} activate + neighbor {{ neighbor_addr }} soft-reconfiguration inbound + maximum-paths 64 + exit-address-family +{% endif %} +{% endif %} +{% endfor %} +{% endblock bgp_sessions %} +{% block bgp_peers_with_range %} +{% if BGP_PEER_RANGE %} +{% for bgp_peer in BGP_PEER_RANGE.values() %} + neighbor {{ bgp_peer['name'] }} peer-group + neighbor {{ bgp_peer['name'] }} passive + 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 +{% 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'] %} + bgp listen range {{ip_range}} peer-group {{ bgp_peer['name'] }} +{% endfor %} + address-family ipv4 + neighbor {{ bgp_peer['name'] }} activate + maximum-paths 64 + exit-address-family + address-family ipv6 + neighbor {{ bgp_peer['name'] }} activate + maximum-paths 64 + exit-address-family +{% endfor %} +{% endif %} +{% endblock bgp_peers_with_range %} +! +{% if DEVICE_METADATA['localhost'].has_key('bgp_asn') %} +maximum-paths 64 +! +route-map ISOLATE permit 10 +set as-path prepend {{ DEVICE_METADATA['localhost']['bgp_asn'] }} +{% endif %} +! diff --git a/dockers/docker-fpm-quagga/isolate.j2 b/dockers/docker-fpm-quagga/isolate.j2 new file mode 100755 index 000000000000..cfcd023ea1f3 --- /dev/null +++ b/dockers/docker-fpm-quagga/isolate.j2 @@ -0,0 +1,20 @@ +#!/bin/bash +## vtysh only accepts script in stdin, so cannot be directly used in shebang +## Cut the tail of this script and feed vtysh stdin +sed -n -e '9,$p' < "$0" | vtysh "$@" +## Exit with vtysh return code +exit $? + +## vtysh script start from next line, which line number MUST equal in 'sed' command above + +configure terminal + router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} +{% for neighbor_addr in BGP_NEIGHBOR %} + neighbor {{ neighbor_addr }} route-map ISOLATE out +{% endfor %} + exit +exit + +{% for neighbor_addr in BGP_NEIGHBOR %} +clear ip bgp {{ neighbor_addr }} soft out +{% endfor %} diff --git a/dockers/docker-fpm-quagga/start.sh b/dockers/docker-fpm-quagga/start.sh new file mode 100755 index 000000000000..06fdd3bb3961 --- /dev/null +++ b/dockers/docker-fpm-quagga/start.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +mkdir -p /etc/quagga +sonic-cfggen -d -y /etc/sonic/deployment_id_asn_map.yml -t /usr/share/sonic/templates/bgpd.conf.j2 > /etc/quagga/bgpd.conf + +sonic-cfggen -d -t /usr/share/sonic/templates/zebra.conf.j2 > /etc/quagga/zebra.conf + +sonic-cfggen -d -t /usr/share/sonic/templates/isolate.j2 > /usr/sbin/bgp-isolate +chown root:root /usr/sbin/bgp-isolate +chmod 0755 /usr/sbin/bgp-isolate + +sonic-cfggen -d -t /usr/share/sonic/templates/unisolate.j2 > /usr/sbin/bgp-unisolate +chown root:root /usr/sbin/bgp-unisolate +chmod 0755 /usr/sbin/bgp-unisolate + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status + +rm -f /var/run/rsyslogd.pid + +supervisorctl start bgpcfgd + +supervisorctl start rsyslogd + +# Start Quagga processes +supervisorctl start zebra +supervisorctl start bgpd + +supervisorctl start fpmsyncd diff --git a/dockers/docker-fpm-quagga/supervisord.conf b/dockers/docker-fpm-quagga/supervisord.conf new file mode 100644 index 000000000000..c4351fafefe9 --- /dev/null +++ b/dockers/docker-fpm-quagga/supervisord.conf @@ -0,0 +1,59 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[program:start.sh] +command=/usr/bin/start.sh +priority=1 +autostart=true +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:bgpcfgd] +command=/usr/bin/bgpcfgd +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n +priority=3 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:zebra] +command=/usr/lib/quagga/zebra -A 127.0.0.1 +priority=4 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:bgpd] +command=/usr/lib/quagga/bgpd -A 127.0.0.1 -F +priority=5 +stopsignal=KILL +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:fpmsyncd] +command=fpmsyncd +priority=6 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/dockers/docker-fpm-quagga/unisolate.j2 b/dockers/docker-fpm-quagga/unisolate.j2 new file mode 100755 index 000000000000..2a0780745d75 --- /dev/null +++ b/dockers/docker-fpm-quagga/unisolate.j2 @@ -0,0 +1,20 @@ +#!/bin/bash +## vtysh only accepts script in stdin, so cannot be directly used in shebang +## Cut the tail of this script and feed vtysh stdin +sed -n -e '9,$p' < "$0" | vtysh "$@" +## Exit with vtysh return code +exit $? + +## vtysh script start from next line, which line number MUST equal in 'sed' command above + +configure terminal + router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} +{% for neighbor_ip in BGP_NEIGHBOR %} + no neighbor {{ neighbor_ip }} route-map ISOLATE out +{% endfor %} + exit +exit + +{% for neighbor_ip in BGP_NEIGHBOR %} +clear ip bgp {{ neighbor_ip }} soft out +{% endfor %} diff --git a/dockers/docker-fpm-quagga/zebra.conf.j2 b/dockers/docker-fpm-quagga/zebra.conf.j2 new file mode 100644 index 000000000000..4acb474b0e35 --- /dev/null +++ b/dockers/docker-fpm-quagga/zebra.conf.j2 @@ -0,0 +1,78 @@ +! +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/zebra.conf.j2 using config DB data +! file: zebra.conf +! +{% endblock banner %} +! +{% block sys_init %} +hostname {{ DEVICE_METADATA['localhost']['hostname'] }} +password zebra +enable password zebra +{% endblock sys_init %} +! +{% block interfaces %} +! Enable link-detect (default disabled) +{% for (name, prefix) in INTERFACE %} +interface {{ name }} +link-detect +! +{% endfor %} +{% for pc in PORTCHANNEL %} +interface {{ pc }} +link-detect +! +{% endfor %} +{% endblock interfaces %} +! +{% block default_route %} +! set static default route to mgmt gateway as a backup to learned default +{% for (name, prefix) in MGMT_INTERFACE %} +{% if prefix | ipv4 %} +ip route 0.0.0.0/0 {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} 200 +{% endif %} +{% endfor %} +{% endblock default_route %} +! +{% block source_loopback %} +{% set lo_ipv4_addrs = [] %} +{% set lo_ipv6_addrs = [] %} +{% if LOOPBACK_INTERFACE %} +{% for (name, prefix) in LOOPBACK_INTERFACE %} +{% if name == 'Loopback0' %} +{% if prefix | ipv6 %} +{% if lo_ipv6_addrs.append(prefix) %} +{% endif %} +{% else %} +{% if lo_ipv4_addrs.append(prefix) %} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +! Set ip source to loopback for bgp learned routes +{% if lo_ipv4_addrs|length > 0 -%} +route-map RM_SET_SRC permit 10 + set src {{ lo_ipv4_addrs[0] | ip }} +! +{% endif %} +{% if lo_ipv6_addrs|length > 0 %} +route-map RM_SET_SRC6 permit 10 + set src {{ lo_ipv6_addrs[0] | ip }} +! +{% endif %} +ip protocol bgp route-map RM_SET_SRC +! +{% if lo_ipv6_addrs|length > 0 %} +ipv6 protocol bgp route-map RM_SET_SRC6 +! +{% endif %} +{% endblock source_loopback %} +! +{% block logging %} +log syslog informational +log facility local4 +{% endblock logging %} +! + diff --git a/dockers/docker-lldp-sv2/Dockerfile.j2 b/dockers/docker-lldp-sv2/Dockerfile.j2 new file mode 100644 index 000000000000..f08a70c01302 --- /dev/null +++ b/dockers/docker-lldp-sv2/Dockerfile.j2 @@ -0,0 +1,52 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +# Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +# Update apt's cache of available packages +RUN apt-get update + +# Install dependencies +RUN apt-get install -y python-pip libbsd0 libevent-2.0-5 libjansson4 libwrap0 libxml2 libpci3 libperl5.20 libpython2.7 + +{% if docker_lldp_sv2_debs.strip() -%} +# Copy locally-built Debian package dependencies +{%- for deb in docker_lldp_sv2_debs.split(' ') %} +COPY debs/{{ deb }} /debs/ +{%- endfor %} + +# Install locally-built Debian packages and implicitly install their dependencies +{%- for deb in docker_lldp_sv2_debs.split(' ') %} +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /debs/{{ deb }} +{%- endfor %} +{%- endif %} + +{% if docker_lldp_sv2_whls.strip() -%} +# Copy locally-built Python wheel dependencies +{%- for whl in docker_lldp_sv2_whls.split(' ') %} +COPY python-wheels/{{ whl }} /python-wheels/ +{%- endfor %} + +# Install locally-built Python wheel dependencies +{%- for whl in docker_lldp_sv2_whls.split(' ') %} +RUN pip install /python-wheels/{{ whl }} +{%- endfor %} +{% endif %} + +# Clean up +RUN apt-get remove -y python-pip +RUN apt-get clean -y +RUN apt-get autoclean -y +RUN apt-get autoremove -y +RUN rm -rf /debs /python-wheels ~/.cache + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["lldpd.conf.j2", "/usr/share/sonic/templates/"] +COPY ["lldpd", "/etc/default/"] +COPY ["lldpmgrd", "/usr/bin/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/dockers/docker-lldp-sv2/base_image_files/lldpctl b/dockers/docker-lldp-sv2/base_image_files/lldpctl new file mode 100755 index 000000000000..f5b6d8307ee9 --- /dev/null +++ b/dockers/docker-lldp-sv2/base_image_files/lldpctl @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS lldp lldpctl "$@" diff --git a/dockers/docker-lldp-sv2/lldpd b/dockers/docker-lldp-sv2/lldpd new file mode 100644 index 000000000000..ba22e49b9b47 --- /dev/null +++ b/dockers/docker-lldp-sv2/lldpd @@ -0,0 +1,6 @@ +############################################################################### +# Managed by sonic-cfggen +############################################################################### + +# Uncomment to start SNMP subagent and enable CDP, SONMP and EDP protocol +DAEMON_ARGS="" diff --git a/dockers/docker-lldp-sv2/lldpd.conf.j2 b/dockers/docker-lldp-sv2/lldpd.conf.j2 new file mode 100644 index 000000000000..94a04596699f --- /dev/null +++ b/dockers/docker-lldp-sv2/lldpd.conf.j2 @@ -0,0 +1,3 @@ +{% if MGMT_INTERFACE %} +configure ports eth0 lldp portidsubtype local {{ MGMT_INTERFACE.keys()[0][0] }} +{% endif %} diff --git a/dockers/docker-lldp-sv2/lldpmgrd b/dockers/docker-lldp-sv2/lldpmgrd new file mode 100755 index 000000000000..a044d5ed9d77 --- /dev/null +++ b/dockers/docker-lldp-sv2/lldpmgrd @@ -0,0 +1,251 @@ +#!/usr/bin/env python + +""" + lldpmgrd + + LLDP manager daemon for SONiC + + Daemon which listens for changes in the PORT table of the State DB + and updates LLDP configuration accordingly for that port by calling + lldpcli. + + TODO: Also listen for changes in DEVICE_NEIGHBOR and PORT tables in + Config DB and update LLDP config upon changes. +""" + + +try: + import os + import signal + import subprocess + import sys + import syslog + import os.path + from swsscommon import swsscommon +except ImportError as err: + raise ImportError("%s - required module not found" % str(err)) + +VERSION = "1.0" + +SYSLOG_IDENTIFIER = "lldpmgrd" + + +# ========================== Syslog wrappers ========================== + +def log_debug(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_DEBUG, msg) + syslog.closelog() + + +def log_info(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + + +def log_warning(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_WARNING, msg) + syslog.closelog() + + +def log_error(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + +# ========================== Signal Handling ========================== + +def signal_handler(sig, frame): + if sig == signal.SIGHUP: + log_info("Caught SIGHUP - ignoring...") + return + elif sig == signal.SIGINT: + log_info("Caught SIGINT - exiting...") + sys.exit(128 + sig) + elif sig == signal.SIGTERM: + log_info("Caught SIGTERM - exiting...") + sys.exit(128 + sig) + else: + log_warning("Caught unhandled signal '" + sig + "'") + +# ========================== Helpers ================================== + +def is_port_up(port_name): + filename = "/sys/class/net/%s/operstate" % port_name + if not os.path.exists(filename): + return False + + with open(filename) as fp: + state = fp.read() + if 'up' in state: + return True + else: + return False + +# ============================== Classes ============================== + +class LldpManager(object): + """ + Class which subscribes to notifications of changes in the PORT table of + the Redis State database and updates LLDP configuration accordingly for + that port by calling lldpcli. + Attributes: + state_db: Handle to Redis State database via swsscommon lib + config_db: Handle to Redis Config database via swsscommon lib + pending_cmds: Dictionary where key is port name, value is pending + LLDP configuration command to run + """ + REDIS_HOSTNAME = "localhost" + REDIS_PORT = 6379 + REDIS_TIMEOUT_MS = 0 + + def __init__(self): + # Open a handle to the State database + self.state_db = swsscommon.DBConnector(swsscommon.STATE_DB, + self.REDIS_HOSTNAME, + self.REDIS_PORT, + self.REDIS_TIMEOUT_MS) + + # Open a handle to the Config database + self.config_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, + self.REDIS_HOSTNAME, + self.REDIS_PORT, + self.REDIS_TIMEOUT_MS) + + self.pending_cmds = {} + + def generate_pending_lldp_config_cmd_for_port(self, port_name): + """ + For port `port_name`, look up the neighboring device's hostname and + corresponding port alias in the Config database, then form the + appropriate lldpcli configuration command and run it. + """ + # Retrieve all entires for this port from the Port table + port_table = swsscommon.Table(self.config_db, swsscommon.CFG_PORT_TABLE_NAME) + (status, fvp) = port_table.get(port_name) + if status: + # Convert list of tuples to a dictionary + port_table_dict = dict(fvp) + + # Get the port alias. If None or empty string, use port name instead + port_alias = port_table_dict.get("alias") + if not port_alias: + log_info("Unable to retrieve port alias for port '{}'. Using port name instead.".format(port_name)) + port_alias = port_name + else: + log_error("Port '{}' not found in {} table in Config DB. Using port name instead of port alias.".format(port_name, swsscommon.CFG_PORT_TABLE_NAME)) + port_alias = port_name + + lldpcli_cmd = "lldpcli configure ports {0} lldp portidsubtype local {1}".format(port_name, port_alias) + + # Retrieve all entires for this port from the Device Neighbor table + device_neighbor_table = swsscommon.Table(self.config_db, swsscommon.CFG_DEVICE_NEIGHBOR_TABLE_NAME) + (status, fvp) = device_neighbor_table.get(port_name) + if status: + # Convert list of tuples to a dictionary + device_neighbor_table_dict = dict(fvp) + + # Get neighbor host name and port name + neighbor_hostname = device_neighbor_table_dict.get("name") + neighbor_portname = device_neighbor_table_dict.get("port") + + # If we sucessfully obtained the neighbor's host name and port name, append a port description to the command + if neighbor_hostname and neighbor_portname: + lldpcli_cmd += " description {0}:{1}".format(neighbor_hostname, neighbor_portname) + else: + if not neighbor_hostname: + log_info("Failed to retrieve neighbor host name for port '{}'. Not adding port description.".format(port_name)) + + if not neighbor_portname: + log_info("Failed to retrieve neighbor port name for port '{}'. Not adding port description.".format(port_name)) + else: + log_info("Unable to retrieve neighbor information for port '{}'. Not adding port description.".format(port_name)) + + # Add the command to our dictionary of pending commands, overwriting any + # previous pending command for this port + self.pending_cmds[port_name] = lldpcli_cmd + + def process_pending_cmds(self): + # List of port names (keys of elements) to delete from self.pending_cmds + to_delete = [] + + for (port_name, cmd) in self.pending_cmds.iteritems(): + if not is_port_up(port_name): + # it doesn't make any sense to configure lldpd if the target port is unavailable + # let's postpone the command for the next iteration + continue + + log_debug("Running command: '{}'".format(cmd)) + + proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + (stdout, stderr) = proc.communicate() + + # If the command succeeds, add the port name to our to_delete list. + # We will delete this command from self.pending_cmds below. + # If the command fails, log a message, but don't delete the command + # from self.pending_cmds, so that the command will be retried the + # next time this method is called. + if proc.returncode == 0: + to_delete.append(port_name) + else: + log_warning("Command failed '{}': {}".format(cmd, stderr)) + + # Delete all successful commands from self.pending_cmds + for port_name in to_delete: + self.pending_cmds.pop(port_name, None) + + def run(self): + """ + Infinite loop. Subscribes to notifications of changes in the PORT table + of the Redis State database. When we are notified of the creation of an + interface, update LLDP configuration accordingly. + """ + # Set select timeout to 10 seconds + SELECT_TIMEOUT_MS = 1000 * 10 + + # Subscribe to PORT table notifications in the State DB + sel = swsscommon.Select() + sst = swsscommon.SubscriberStateTable(self.state_db, swsscommon.STATE_PORT_TABLE_NAME) + sel.addSelectable(sst) + + # Listen indefinitely for changes to the PORT table in the State DB + while True: + (state, c) = sel.select(SELECT_TIMEOUT_MS) + + if state == swsscommon.Select.OBJECT: + (key, op, fvp) = sst.pop() + + fvp_dict = dict(fvp) + + if op == "SET" and fvp_dict.get("state") == "ok": + self.generate_pending_lldp_config_cmd_for_port(key) + + # Process all pending commands + self.process_pending_cmds() + + +# ============================= Functions ============================= + +def main(): + log_info("Starting up...") + + if not os.geteuid() == 0: + log_error("Must be root to run this daemon") + print "Error: Must be root to run this daemon" + sys.exit(1) + + # Register our signal handlers + signal.signal(signal.SIGHUP, signal_handler) + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + # Instantiate a LldpManager object + lldpmgr = LldpManager() + lldpmgr.run() + +if __name__ == "__main__": + main() diff --git a/dockers/docker-lldp-sv2/start.sh b/dockers/docker-lldp-sv2/start.sh new file mode 100755 index 000000000000..adc322979813 --- /dev/null +++ b/dockers/docker-lldp-sv2/start.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +sonic-cfggen -d -t /usr/share/sonic/templates/lldpd.conf.j2 > /etc/lldpd.conf + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status + +rm -f /var/run/rsyslogd.pid +rm -f /var/run/lldpd.socket + +supervisorctl start rsyslogd +supervisorctl start lldpd +supervisorctl start lldp-syncd +supervisorctl start lldpmgrd + +# Current lldpd version has a bug. +# When lldpd starts it is in the pause state by default +# But then it execute 'lldpcli resume' to configure and unpause itself. +# When lldpd execute lldpcli, it doesn't check the return code +# Sometimes lldpcli returns failure, but lldpd doesn't catch it +# and keeps working paused and unconfigured +# +# The fix below addresses the issue. +# + +# wait until lldpd started +until [[ -e /var/run/lldpd.socket ]]; +do + sleep 1; +done + +# Manually try to resume lldpd, until it's successful +while /bin/true; +do + lldpcli -u /var/run/lldpd.socket -c /etc/lldpd.conf -c /etc/lldpd.d resume > /dev/null && break + sleep 1 +done diff --git a/dockers/docker-lldp-sv2/supervisord.conf b/dockers/docker-lldp-sv2/supervisord.conf new file mode 100644 index 000000000000..5feb3543f1bc --- /dev/null +++ b/dockers/docker-lldp-sv2/supervisord.conf @@ -0,0 +1,49 @@ +[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: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*,eth0 -C eth0 +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:lldp-syncd] +command=/usr/bin/env python2 -m lldp_syncd +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:lldpmgrd] +command=/usr/bin/lldpmgrd +priority=5 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/dockers/docker-orchagent-bfn b/dockers/docker-orchagent-bfn new file mode 120000 index 000000000000..8d52609c56e5 --- /dev/null +++ b/dockers/docker-orchagent-bfn @@ -0,0 +1 @@ +docker-orchagent \ No newline at end of file diff --git a/dockers/docker-orchagent-cavm b/dockers/docker-orchagent-cavm new file mode 120000 index 000000000000..8d52609c56e5 --- /dev/null +++ b/dockers/docker-orchagent-cavm @@ -0,0 +1 @@ +docker-orchagent \ No newline at end of file diff --git a/dockers/docker-orchagent-centec b/dockers/docker-orchagent-centec new file mode 120000 index 000000000000..8d52609c56e5 --- /dev/null +++ b/dockers/docker-orchagent-centec @@ -0,0 +1 @@ +docker-orchagent \ No newline at end of file diff --git a/dockers/docker-orchagent-mlnx b/dockers/docker-orchagent-mlnx new file mode 120000 index 000000000000..8d52609c56e5 --- /dev/null +++ b/dockers/docker-orchagent-mlnx @@ -0,0 +1 @@ +docker-orchagent \ No newline at end of file diff --git a/dockers/docker-orchagent-nephos b/dockers/docker-orchagent-nephos new file mode 120000 index 000000000000..8d52609c56e5 --- /dev/null +++ b/dockers/docker-orchagent-nephos @@ -0,0 +1 @@ +docker-orchagent \ No newline at end of file diff --git a/dockers/docker-orchagent/Dockerfile.j2 b/dockers/docker-orchagent/Dockerfile.j2 new file mode 100755 index 000000000000..4fcbe08ab7ac --- /dev/null +++ b/dockers/docker-orchagent/Dockerfile.j2 @@ -0,0 +1,47 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +RUN apt-get install -f -y ifupdown arping libdbus-1-3 libdaemon0 libjansson4 libpython2.7 + +RUN apt-get install -f -y ndisc6 tcpdump python-scapy +## Install redis-tools dependencies +## TODO: implicitly install dependencies +RUN apt-get -y install libjemalloc1 + +RUN apt-get install -y libelf1 libmnl0 + +RUN pip install setuptools +RUN pip install pyroute2==0.5.3 netifaces==0.10.7 +RUN pip install monotonic==1.5 + +COPY \ +{% for deb in docker_orchagent_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_orchagent_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +COPY ["files/arp_update", "/usr/bin"] +COPY ["enable_counters.py", "/usr/bin"] +COPY ["start.sh", "orchagent.sh", "swssconfig.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +## 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/base_image_files/swssloglevel b/dockers/docker-orchagent/base_image_files/swssloglevel new file mode 100755 index 000000000000..d03685ed383c --- /dev/null +++ b/dockers/docker-orchagent/base_image_files/swssloglevel @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS swss swssloglevel "$@" diff --git a/dockers/docker-orchagent/enable_counters.py b/dockers/docker-orchagent/enable_counters.py new file mode 100755 index 000000000000..712d34492b47 --- /dev/null +++ b/dockers/docker-orchagent/enable_counters.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python + +import swsssdk +import time + +def enable_counter_group(db, name): + info = {} + info['FLEX_COUNTER_STATUS'] = 'enable' + db.mod_entry("FLEX_COUNTER_TABLE", name, info) + +def enable_counters(): + db = swsssdk.ConfigDBConnector() + db.connect() + enable_counter_group(db, 'PORT') + enable_counter_group(db, 'QUEUE') + enable_counter_group(db, 'PFCWD') + +def get_uptime(): + with open('/proc/uptime') as fp: + return float(fp.read().split(' ')[0]) + +def main(): + # If the switch was just started (uptime less than 5 minutes), + # wait for 3 minutes and enable counters + # otherwise wait for 60 seconds and enable counters + uptime = get_uptime() + if uptime < 300: + time.sleep(180) + else: + time.sleep(60) + enable_counters() + +if __name__ == '__main__': + main() diff --git a/dockers/docker-orchagent/ipinip.json.j2 b/dockers/docker-orchagent/ipinip.json.j2 new file mode 100644 index 000000000000..7ce291dbdf8c --- /dev/null +++ b/dockers/docker-orchagent/ipinip.json.j2 @@ -0,0 +1,78 @@ +{% set ipv4_addresses = [] %} +{% set ipv6_addresses = [] %} +{% set ipv4_loopback_addresses = [] %} +{% set ipv6_loopback_addresses = [] %} +{% for (name, prefix) in LOOPBACK_INTERFACE %} + {%- if prefix | ipv4 and name == 'Loopback0' %} + {%- set ipv4_addresses = ipv4_addresses.append(prefix) %} + {%- set ipv4_loopback_addresses = ipv4_loopback_addresses.append(prefix) %} + {%- endif %} + {%- if prefix | ipv6 and name == 'Loopback0' %} + {%- set ipv6_addresses = ipv6_addresses.append(prefix) %} + {%- set ipv6_loopback_addresses = ipv6_loopback_addresses.append(prefix) %} + {%- endif %} +{% endfor %} +{% for (name, prefix) in INTERFACE %} + {%- if prefix | ipv4 %} + {%- set ipv4_addresses = ipv4_addresses.append(prefix) %} + {%- endif %} + {%- if prefix | ipv6 %} + {%- set ipv6_addresses = ipv6_addresses.append(prefix) %} + {%- endif %} +{% endfor %} +{% for (name, prefix) in PORTCHANNEL_INTERFACE %} + {%- if prefix | ipv4 %} + {%- set ipv4_addresses = ipv4_addresses.append(prefix) %} + {%- endif %} + {%- if prefix | ipv6 %} + {%- set ipv6_addresses = ipv6_addresses.append(prefix) %} + {%- endif %} +{% endfor %} +{% for (name, prefix) in VLAN_INTERFACE %} + {%- if prefix | ipv4 %} + {%- set ipv4_addresses = ipv4_addresses.append(prefix) %} + {%- endif %} + {%- if prefix | ipv6 %} + {%- set ipv6_addresses = ipv6_addresses.append(prefix) %} + {%- endif %} +{% endfor %} +[ +{% if ipv4_loopback_addresses %} + { + "TUNNEL_DECAP_TABLE:IPINIP_TUNNEL" : { + "tunnel_type":"IPINIP", +{% if "mlnx" in DEVICE_METADATA.localhost.platform %} + "dst_ip":"{% for prefix in ipv4_loopback_addresses %}{{ prefix | ip }}{% if not loop.last %},{% endif %}{% endfor %}", + "dscp_mode":"uniform", + "ecn_mode":"standard", +{% else %} + "dst_ip":"{% for prefix in ipv4_addresses %}{{ prefix | ip }}{% if not loop.last %},{% endif %}{% endfor %}", + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", +{% endif %} + "ttl_mode":"pipe" + }, + "OP": "SET" + } +{% endif %} +{% if ipv4_loopback_addresses and ipv6_loopback_addresses %} , +{% endif %} +{% if ipv6_loopback_addresses %} + { + "TUNNEL_DECAP_TABLE:IPINIP_V6_TUNNEL" : { + "tunnel_type":"IPINIP", +{% if "mlnx" in DEVICE_METADATA.localhost.platform %} + "dst_ip":"{% for prefix in ipv6_loopback_addresses %}{{ prefix | ip }}{% if not loop.last %},{% endif %}{% endfor %}", + "dscp_mode":"uniform", + "ecn_mode":"standard", +{% else %} + "dst_ip":"{% for prefix in ipv6_addresses %}{{ prefix | ip }}{% if not loop.last %},{% endif %}{% endfor %}", + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", +{% endif %} + "ttl_mode":"pipe" + }, + "OP": "SET" + } +{% endif %} +] diff --git a/dockers/docker-orchagent/orchagent.sh b/dockers/docker-orchagent/orchagent.sh new file mode 100755 index 000000000000..9ad3355e3c5e --- /dev/null +++ b/dockers/docker-orchagent/orchagent.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +# Export platform information. Required to be able to write +# vendor specific code. +export platform=`sonic-cfggen -y /etc/sonic/sonic_version.yml -v asic_type` + +MAC_ADDRESS=`ip link show eth0 | grep ether | awk '{print $2}'` + +# Create a folder for SwSS record files +mkdir -p /var/log/swss +ORCHAGENT_ARGS="-d /var/log/swss " + +# Set orchagent pop batch size to 8192 +ORCHAGENT_ARGS+="-b 8192 " + +# Add platform specific arguments if necessary +if [ "$platform" == "broadcom" ]; then + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +elif [ "$platform" == "cavium" ]; then + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +elif [ "$platform" == "nephos" ]; then + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +elif [ "$platform" == "centec" ]; then + last_byte=$(python -c "print '$MAC_ADDRESS'[-2:]") + aligned_last_byte=$(python -c "print format(int(int('$last_byte', 16) + 1), '02x')") # put mask and take away the 0x prefix + ALIGNED_MAC_ADDRESS=$(python -c "print '$MAC_ADDRESS'[:-2] + '$aligned_last_byte'") # put aligned byte into the end of MAC + ORCHAGENT_ARGS+="-m $ALIGNED_MAC_ADDRESS" +elif [ "$platform" == "barefoot" ]; then + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +elif [ "$platform" == "vs" ]; then + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +fi + +exec /usr/bin/orchagent ${ORCHAGENT_ARGS} diff --git a/dockers/docker-orchagent/ports.json.j2 b/dockers/docker-orchagent/ports.json.j2 new file mode 100644 index 000000000000..b10d4d58a43d --- /dev/null +++ b/dockers/docker-orchagent/ports.json.j2 @@ -0,0 +1,20 @@ +[ +{% set ports_with_speed_set=[] %} +{% if PORT %} +{% for port in PORT %} +{% if PORT[port].has_key('speed') %} + {%- if ports_with_speed_set.append(port) -%}{%- endif -%} +{%- endif -%} +{% endfor %} +{% for port in ports_with_speed_set %} + { + "PORT_TABLE:{{ port }}": { + "speed": "{{ PORT[port]['speed'] }}", + "description": "{{ PORT[port]['description'] }}" + }, + "OP": "SET" + }{% if not loop.last %},{% endif %} + +{% endfor %} +{% endif %} +] diff --git a/dockers/docker-orchagent/start.sh b/dockers/docker-orchagent/start.sh new file mode 100755 index 000000000000..d9e9bcad0b91 --- /dev/null +++ b/dockers/docker-orchagent/start.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +mkdir -p /etc/swss/config.d/ + +sonic-cfggen -d -y /etc/sonic/sonic_version.yml -t /usr/share/sonic/templates/switch.json.j2 > /etc/swss/config.d/switch.json +sonic-cfggen -d -t /usr/share/sonic/templates/ipinip.json.j2 > /etc/swss/config.d/ipinip.json +sonic-cfggen -d -t /usr/share/sonic/templates/ports.json.j2 > /etc/swss/config.d/ports.json + +# Executed HWSKU specific initialization tasks. +if [ -x /usr/share/sonic/hwsku/hwsku-init ]; then + /usr/share/sonic/hwsku/hwsku-init +fi + +export platform=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform` + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start orchagent + +supervisorctl start restore_neighbors + +supervisorctl start portsyncd + +supervisorctl start intfsyncd + +supervisorctl start neighsyncd + +supervisorctl start swssconfig + +supervisorctl start vlanmgrd + +supervisorctl start intfmgrd + +supervisorctl start portmgrd + +supervisorctl start buffermgrd + +supervisorctl start enable_counters + +supervisorctl start vrfmgrd + +supervisorctl start nbrmgrd + +# Start arp_update when VLAN exists +VLAN=`sonic-cfggen -d -v 'VLAN.keys() | join(" ") if VLAN'` +if [ "$VLAN" != "" ]; then + supervisorctl start arp_update +fi diff --git a/dockers/docker-orchagent/supervisord.conf b/dockers/docker-orchagent/supervisord.conf new file mode 100644 index 000000000000..2fe25a7a4106 --- /dev/null +++ b/dockers/docker-orchagent/supervisord.conf @@ -0,0 +1,137 @@ +[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:orchagent] +command=/usr/bin/orchagent.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:portsyncd] +command=/usr/bin/portsyncd -p /usr/share/sonic/hwsku/port_config.ini +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:intfsyncd] +command=/usr/bin/intfsyncd +priority=5 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:neighsyncd] +command=/usr/bin/neighsyncd +priority=6 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:swssconfig] +command=/usr/bin/swssconfig.sh +priority=7 +autostart=false +autorestart=unexpected +startretries=0 +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:arp_update] +command=/usr/bin/arp_update +priority=8 +autostart=false +autorestart=unexpected +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 + +[program:portmgrd] +command=/usr/bin/portmgrd +priority=11 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:buffermgrd] +command=/usr/bin/buffermgrd -l /usr/share/sonic/hwsku/pg_profile_lookup.ini +priority=12 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:enable_counters] +command=/usr/bin/enable_counters.py +priority=13 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:vrfmgrd] +command=/usr/bin/vrfmgrd +priority=14 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:restore_neighbors] +command=/usr/bin/restore_neighbors.py +priority=15 +autostart=false +autorestart=false +startsecs=0 +startretries=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:nbrmgrd] +command=/usr/bin/nbrmgrd +priority=16 +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..7aaada1b1e40 --- /dev/null +++ b/dockers/docker-orchagent/switch.json.j2 @@ -0,0 +1,19 @@ +{# the range of hash_seed is 0-15 #} +{# set default hash seed to 0 #} +{% set hash_seed = 0 %} +{% if DEVICE_METADATA.localhost.type %} +{% if DEVICE_METADATA.localhost.type == "ToRRouter" %} +{% set hash_seed = 0 %} +{% elif DEVICE_METADATA.localhost.type == "LeafRouter" %} +{% set hash_seed = 10 %} +{% 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 new file mode 100755 index 000000000000..c6915f0597a1 --- /dev/null +++ b/dockers/docker-orchagent/swssconfig.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +set -e + +function fast_reboot { + case "$(cat /proc/cmdline)" in + *fast-reboot*) + if [[ -f /fdb.json ]]; + then + swssconfig /fdb.json + rm -f /fdb.json + fi + + if [[ -f /arp.json ]]; + then + swssconfig /arp.json + rm -f /arp.json + fi + + if [[ -f /default_routes.json ]]; + then + swssconfig /default_routes.json + rm -f /default_routes.json + fi + + ;; + *) + ;; + esac +} + +# Wait until swss.sh in the host system create file swss:/ready +until [[ -e /ready ]]; do + sleep 0.1; +done + +rm -f /ready + +# Restore FDB and ARP table ASAP +fast_reboot + +HWSKU=`sonic-cfggen -d -v "DEVICE_METADATA['localhost']['hwsku']"` + +# Don't load json config if system warm start or +# swss docker warm start is enabled, the data already exists in appDB. +SYSTEM_WARM_START=`redis-cli -n 4 hget "WARM_RESTART|system" enable` +SWSS_WARM_START=`redis-cli -n 4 hget "WARM_RESTART|swss" enable` +if [[ "$SYSTEM_WARM_START" == "true" ]] || [[ "$SWSS_WARM_START" == "true" ]]; then + # We have to make sure db data has not been flushed. + RESTORE_COUNT=`redis-cli -n 6 hget "WARM_RESTART_TABLE|orchagent" restore_count` + if [[ -n "$RESTORE_COUNT" ]] && [[ "$RESTORE_COUNT" != "0" ]]; then + exit 0 + fi +fi + +SWSSCONFIG_ARGS="00-copp.config.json ipinip.json ports.json switch.json " + +for file in $SWSSCONFIG_ARGS; do + swssconfig /etc/swss/config.d/$file + sleep 1 +done diff --git a/dockers/docker-platform-monitor/Dockerfile.j2 b/dockers/docker-platform-monitor/Dockerfile.j2 new file mode 100755 index 000000000000..e33ea72f07b1 --- /dev/null +++ b/dockers/docker-platform-monitor/Dockerfile.j2 @@ -0,0 +1,49 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +# Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +# Update apt's cache of available packages +RUN apt-get update + +# Install required packages +RUN apt-get install -y python-pip libpython2.7 sensord fancontrol ipmitool + +{% if docker_platform_monitor_debs.strip() -%} +# Copy locally-built Debian package dependencies +{%- for deb in docker_platform_monitor_debs.split(' ') %} +COPY debs/{{ deb }} /debs/ +{%- endfor %} + +# Install locally-built Debian packages and implicitly install their dependencies +{%- for deb in docker_platform_monitor_debs.split(' ') %} +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /debs/{{ deb }} +{%- endfor %} +{%- endif %} + +{% if docker_platform_monitor_whls.strip() -%} +# Copy locally-built Python wheel dependencies +{%- for whl in docker_platform_monitor_whls.split(' ') %} +COPY python-wheels/{{ whl }} /python-wheels/ +{%- endfor %} + +# Install locally-built Python wheel dependencies +{%- for whl in docker_platform_monitor_whls.split(' ') %} +RUN pip install /python-wheels/{{ whl }} +{%- endfor %} +{% endif %} + +# Clean up +RUN apt-get remove -y python-pip +RUN apt-get clean -y +RUN apt-get autoclean -y +RUN apt-get autoremove -y +RUN rm -rf /debs /python-wheels ~/.cache + +COPY ["start.sh", "lm-sensors.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/dockers/docker-platform-monitor/base_image_files/sensors b/dockers/docker-platform-monitor/base_image_files/sensors new file mode 100755 index 000000000000..23a12034f071 --- /dev/null +++ b/dockers/docker-platform-monitor/base_image_files/sensors @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS pmon sensors "$@" diff --git a/dockers/docker-platform-monitor/lm-sensors.sh b/dockers/docker-platform-monitor/lm-sensors.sh new file mode 100755 index 000000000000..2f4768a8cdda --- /dev/null +++ b/dockers/docker-platform-monitor/lm-sensors.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# +# Based off /etc/init.d/lm-sensors +# + + +# 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 +# can't use supervisord. Instead, we just start the service for now. +service sensord start diff --git a/dockers/docker-platform-monitor/start.sh b/dockers/docker-platform-monitor/start.sh new file mode 100755 index 000000000000..30699694b6d2 --- /dev/null +++ b/dockers/docker-platform-monitor/start.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +# If this platform has an lm-sensors config file, copy it to it's proper place +# and start lm-sensors +if [ -e /usr/share/sonic/platform/sensors.conf ]; then + mkdir -p /etc/sensors.d + /bin/cp -f /usr/share/sonic/platform/sensors.conf /etc/sensors.d/ + supervisorctl start lm-sensors +fi + +# If this platform has a fancontrol config file, copy it to it's proper place +# and start fancontrol +if [ -e /usr/share/sonic/platform/fancontrol ]; then + # Remove stale pid file if it exists + rm -f /var/run/fancontrol.pid + + /bin/cp -f /usr/share/sonic/platform/fancontrol /etc/ + supervisorctl start fancontrol +fi + +supervisorctl start ledd + +supervisorctl start xcvrd diff --git a/dockers/docker-platform-monitor/supervisord.conf b/dockers/docker-platform-monitor/supervisord.conf new file mode 100644 index 000000000000..aa947ce2c9ae --- /dev/null +++ b/dockers/docker-platform-monitor/supervisord.conf @@ -0,0 +1,56 @@ +[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 +startsecs=0 + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:lm-sensors] +command=/usr/bin/lm-sensors.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +startsecs=0 + +[program:fancontrol] +command=/usr/sbin/fancontrol +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:ledd] +command=/usr/bin/ledd +priority=5 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +startsecs=0 + +[program:xcvrd] +command=/usr/bin/xcvrd +priority=6 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +startsecs=0 diff --git a/dockers/docker-ptf-saithrift/Dockerfile.j2 b/dockers/docker-ptf-saithrift/Dockerfile.j2 new file mode 100644 index 000000000000..3076de4878b6 --- /dev/null +++ b/dockers/docker-ptf-saithrift/Dockerfile.j2 @@ -0,0 +1,17 @@ +FROM docker-ptf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_ptf_saithrift_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_ptf_saithrift_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["*.ini", "/etc/ptf/"] diff --git a/dockers/docker-ptf-saithrift/brcm_interface_to_front_map.ini b/dockers/docker-ptf-saithrift/brcm_interface_to_front_map.ini new file mode 100644 index 000000000000..0db110025b8a --- /dev/null +++ b/dockers/docker-ptf-saithrift/brcm_interface_to_front_map.ini @@ -0,0 +1,33 @@ +# ptf host interface @ switch front port name +0@Ethernet0 +1@Ethernet4 +2@Ethernet8 +3@Ethernet12 +4@Ethernet16 +5@Ethernet20 +6@Ethernet24 +7@Ethernet28 +8@Ethernet32 +9@Ethernet36 +10@Ethernet40 +11@Ethernet44 +12@Ethernet48 +13@Ethernet52 +14@Ethernet56 +15@Ethernet60 +16@Ethernet64 +17@Ethernet68 +18@Ethernet72 +19@Ethernet76 +20@Ethernet80 +21@Ethernet84 +22@Ethernet88 +23@Ethernet92 +24@Ethernet96 +25@Ethernet100 +26@Ethernet104 +27@Ethernet108 +28@Ethernet112 +29@Ethernet116 +30@Ethernet120 +31@Ethernet124 diff --git a/dockers/docker-ptf-saithrift/msn_2700_interface_to_front_map.ini b/dockers/docker-ptf-saithrift/msn_2700_interface_to_front_map.ini new file mode 100644 index 000000000000..4421812aeef9 --- /dev/null +++ b/dockers/docker-ptf-saithrift/msn_2700_interface_to_front_map.ini @@ -0,0 +1,33 @@ +# ptf host interface @ switch front port name +0@Ethernet1 +1@Ethernet2 +2@Ethernet3 +3@Ethernet4 +4@Ethernet5 +5@Ethernet6 +6@Ethernet7 +7@Ethernet8 +8@Ethernet9 +9@Ethernet10 +10@Ethernet11 +11@Ethernet12 +12@Ethernet13 +13@Ethernet14 +14@Ethernet15 +15@Ethernet16 +16@Ethernet17 +17@Ethernet18 +18@Ethernet19 +19@Ethernet20 +20@Ethernet21 +21@Ethernet22 +22@Ethernet23 +23@Ethernet24 +24@Ethernet25 +25@Ethernet26 +26@Ethernet27 +27@Ethernet28 +28@Ethernet29 +29@Ethernet30 +30@Ethernet31 +31@Ethernet32 diff --git a/dockers/docker-ptf/Dockerfile.j2 b/dockers/docker-ptf/Dockerfile.j2 new file mode 100644 index 000000000000..2d9b1544d95a --- /dev/null +++ b/dockers/docker-ptf/Dockerfile.j2 @@ -0,0 +1,111 @@ +FROM debian:jessie + +MAINTAINER Pavel Shirshov + +## Copy dependencies +COPY \ +{% for deb in docker_ptf_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +## Set the apt source, update package cache and install necessary packages +RUN sed --in-place 's/httpredir.debian.org/debian-archive.trafficmanager.net/' /etc/apt/sources.list \ + && apt-get update \ + && apt-get upgrade -y \ + && apt-get dist-upgrade -y \ + && apt-get install -y \ + openssh-server \ + vim \ + net-tools \ + traceroute \ + lsof \ + tcpdump \ + unzip \ + pkg-config \ + binutils \ + net-tools \ + build-essential \ + libssl-dev \ + libffi-dev \ + wget \ + cmake \ + libqt5core5a \ + libqt5network5 \ + less \ + git \ + iputils-ping \ + hping3 \ + curl \ + tcpdump \ + python \ + python-dev \ + python-scapy + +RUN dpkg -i \ +{% for deb in docker_ptf_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +# Install all python modules from pypi. python-scapy is exception, ptf debian package requires python-scapy +RUN rm -rf /debs \ + && apt-get -y autoclean \ + && apt-get -y autoremove \ + && rm -rf /var/lib/apt/lists/* \ + && wget --https-only https://bootstrap.pypa.io/get-pip.py \ + && python get-pip.py \ + && rm -f get-pip.py \ + && pip install setuptools \ + && pip install supervisor \ + && pip install ipython==5.4.1 \ + && git clone https://github.com/p4lang/scapy-vxlan.git \ + && cd scapy-vxlan \ + && python setup.py install \ + && cd .. \ + && rm -fr scapy-vxlan \ + && wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cd build \ + && cmake .. \ + && make install \ + && ldconfig \ + && cd ../.. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi \ + && pip install nnpy \ + && pip install dpkt \ + && pip install ipaddress \ + && pip install pysubnettree \ + && pip install paramiko \ + && pip install flask \ + && pip install exabgp==3.4.17\ + && pip install pyaml \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py + +## Adjust sshd settings +RUN mkdir /var/run/sshd \ + && echo 'root:root' | chpasswd \ + && sed -ri 's/^PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config \ + && sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config \ + && sed -i '$aUseDNS no' /etc/ssh/sshd_config + +COPY ["supervisord.conf", "/etc/supervisor/"] +COPY ["conf.d/supervisord.conf", "conf.d/sshd.conf", "conf.d/ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +# Move tcpdump into /usr/bin Otherwise it's impossible to run tcpdump due to a docker bug +RUN mv /usr/sbin/tcpdump /usr/bin/tcpdump +RUN ln -s /usr/bin/tcpdump /usr/sbin/tcpdump + +RUN mkdir -p /var/log/supervisor + +EXPOSE 22 + +ENTRYPOINT ["/usr/local/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] diff --git a/dockers/docker-ptf/conf.d/ptf_nn_agent.conf b/dockers/docker-ptf/conf.d/ptf_nn_agent.conf new file mode 100644 index 000000000000..6fb30d61d7c2 --- /dev/null +++ b/dockers/docker-ptf/conf.d/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 0@tcp://127.0.0.1:10900 -i 0-3@eth3 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/docker-ptf/supervisord.conf b/dockers/docker-ptf/conf.d/sshd.conf similarity index 83% rename from docker-ptf/supervisord.conf rename to dockers/docker-ptf/conf.d/sshd.conf index 94559fd0785c..8238e7762fbf 100644 --- a/docker-ptf/supervisord.conf +++ b/dockers/docker-ptf/conf.d/sshd.conf @@ -1,6 +1,3 @@ -[supervisord] -nodaemon=true - [program:sshd] command=/usr/sbin/sshd -D process_name=sshd @@ -10,4 +7,4 @@ redirect_stderr=false autostart=true autorestart=true startsecs=1 -numprocs=1 \ No newline at end of file +numprocs=1 diff --git a/dockers/docker-ptf/conf.d/supervisord.conf b/dockers/docker-ptf/conf.d/supervisord.conf new file mode 100644 index 000000000000..54296b8b254e --- /dev/null +++ b/dockers/docker-ptf/conf.d/supervisord.conf @@ -0,0 +1,2 @@ +[supervisord] +nodaemon=true diff --git a/dockers/docker-ptf/supervisord.conf b/dockers/docker-ptf/supervisord.conf new file mode 100644 index 000000000000..9c236612d25c --- /dev/null +++ b/dockers/docker-ptf/supervisord.conf @@ -0,0 +1,28 @@ +; supervisor config file + +[unix_http_server] +file=/var/run/supervisor.sock ; (the path to the socket file) +chmod=0700 ; sockef file mode (default 0700) + +[supervisord] +logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) +pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) +childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) + +; the below section must remain in the config file for RPC +; (supervisorctl/web interface) to work, additional interfaces may be +; added by defining them in separate rpcinterface: sections +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[supervisorctl] +serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket + +; The [include] section can just contain the "files" setting. This +; setting can list multiple files (separated by whitespace or +; newlines). It can also contain wildcards. The filenames are +; interpreted as relative to this file. Included files *cannot* +; include files themselves. + +[include] +files = /etc/supervisor/conf.d/*.conf diff --git a/dockers/docker-router-advertiser/Dockerfile.j2 b/dockers/docker-router-advertiser/Dockerfile.j2 new file mode 100644 index 000000000000..1385e1ebec63 --- /dev/null +++ b/dockers/docker-router-advertiser/Dockerfile.j2 @@ -0,0 +1,35 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +# Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +# Update apt's cache of available packages +RUN apt-get update + +# Install radvd Debian package +RUN apt-get -y install radvd + +{% if docker_router_advertiser_debs.strip() -%} +# Copy built Debian packages +{%- for deb in docker_router_advertiser_debs.split(' ') %} +COPY debs/{{ deb }} debs/ +{%- endfor %} + +# Install built Debian packages and implicitly install their dependencies +{%- for deb in docker_router_advertiser_debs.split(' ') %} +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt debs/{{ deb }} +{%- endfor %} +{%- endif %} + +# Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +COPY ["start.sh", "/usr/bin/"] +COPY ["docker-router-advertiser.supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["radvd.conf.j2", "/usr/share/sonic/templates/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf b/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf new file mode 100644 index 000000000000..f0bb4d5b3bbd --- /dev/null +++ b/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf @@ -0,0 +1,29 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[program:start.sh] +command=/usr/bin/start.sh +priority=1 +autostart=true +autorestart=false +startsecs=0 +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:radvd] +command=/usr/sbin/radvd -n +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/dockers/docker-router-advertiser/radvd.conf.j2 b/dockers/docker-router-advertiser/radvd.conf.j2 new file mode 100644 index 000000000000..940c26fd6588 --- /dev/null +++ b/dockers/docker-router-advertiser/radvd.conf.j2 @@ -0,0 +1,37 @@ +{% block banner %} +# =========== Managed by sonic-cfggen -- DO NOT edit manually! ==================== +# Generated by /usr/share/sonic/templates/radvd.conf.j2 using config DB data +# File: /etc/radvd.conf +# +{% endblock banner %} +# Config file for radvd, the router advertisement daemon +# See man page for radvd.conf for descriptions of all available options +# + +{# If our configuration has VLAN interfaces... #} +{% if VLAN_INTERFACE %} +{% for (name, prefix) in VLAN_INTERFACE %} +{# If this VLAN has an IPv6 address... #} +{% if prefix | ipv6 %} +interface {{ name }} +{ + IgnoreIfMissing on; + AdvSendAdvert on; + MinRtrAdvInterval 200; + MaxRtrAdvInterval 600; + AdvManagedFlag on; + AdvOtherConfigFlag off; + AdvLinkMTU 9100; + AdvHomeAgentFlag off; + prefix {{ prefix | network }}/{{ prefix | prefixlen }} { + AdvOnLink on; + AdvAutonomous off; + AdvRouterAddr off; + AdvValidLifetime infinity; + AdvPreferredLifetime infinity; + }; +}; + +{% endif %} +{% endfor %} +{% endif %} diff --git a/dockers/docker-router-advertiser/start.sh b/dockers/docker-router-advertiser/start.sh new file mode 100755 index 000000000000..159006a176bd --- /dev/null +++ b/dockers/docker-router-advertiser/start.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +# Router advertiser should only run on ToR (T0) devices +DEVICE_ROLE=$(sonic-cfggen -d -v "DEVICE_METADATA.localhost.type") +if [ "$DEVICE_ROLE" != "ToRRouter" ]; then + echo "Device role is not ToRRouter. Not starting router advertiser process." + exit 0 +fi + +# Generate /etc/radvd.conf config file +sonic-cfggen -d -t /usr/share/sonic/templates/radvd.conf.j2 > /etc/radvd.conf + +# Enusre at least one interface is specified in radvd.conf +NUM_IFACES=$(grep -c "^interface " /etc/radvd.conf) +if [ $NUM_IFACES -eq 0 ]; then + echo "No interfaces specified in radvd.conf. Not starting router advertiser process." + exit 0 +fi + +# Start the router advertiser +supervisorctl start radvd diff --git a/dockers/docker-snmp-sv2/Dockerfile.j2 b/dockers/docker-snmp-sv2/Dockerfile.j2 new file mode 100644 index 000000000000..f8deee49d37c --- /dev/null +++ b/dockers/docker-snmp-sv2/Dockerfile.j2 @@ -0,0 +1,65 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +# Enable -O for all Python calls +ENV PYTHONOPTIMIZE 1 + +# Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +# Update apt's cache of available packages +RUN apt-get update + +# Install curl so we can download and install pip later +# Also install major root CA certificates for curl to reference +RUN apt-get install -y curl ca-certificates + +# Install gcc which is required for installing hiredis +RUN apt-get install -y gcc + +{% if docker_snmp_sv2_debs.strip() -%} +# Copy locally-built Debian package dependencies +{%- for deb in docker_snmp_sv2_debs.split(' ') %} +COPY debs/{{ deb }} /debs/ +{%- endfor %} + +# Install locally-built Debian packages and implicitly install their dependencies +{%- for deb in docker_snmp_sv2_debs.split(' ') %} +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /debs/{{ deb }} +{%- endfor %} +{%- endif %} + +# Install up-to-date version of pip +RUN curl https://bootstrap.pypa.io/get-pip.py | python3.6 +RUN python3.6 -m pip install --no-cache-dir hiredis + +{% if docker_snmp_sv2_whls.strip() -%} +# Copy locally-built Python wheel dependencies +{%- for whl in docker_snmp_sv2_whls.split(' ') %} +COPY python-wheels/{{ whl }} /python-wheels/ +{%- endfor %} + +# Install locally-built Python wheel dependencies +{%- for whl in docker_snmp_sv2_whls.split(' ') %} +RUN pip install /python-wheels/{{ whl }} +{%- endfor %} +{% endif %} + +RUN python3.6 -m sonic_ax_impl install + +# Clean up +RUN apt-get -y purge libpython3.6-dev curl gcc +RUN apt-get clean -y && apt-get autoclean -y && apt-get autoremove -y --purge +RUN find / | grep -E "__pycache__" | xargs rm -rf +RUN rm -rf /debs /python-wheels ~/.cache + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["*.j2", "/usr/share/sonic/templates/"] + +# Although exposing ports is not needed 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-sv2/snmpd.conf.j2 b/dockers/docker-snmp-sv2/snmpd.conf.j2 new file mode 100644 index 000000000000..6353246acb08 --- /dev/null +++ b/dockers/docker-snmp-sv2/snmpd.conf.j2 @@ -0,0 +1,126 @@ +############################################################################### +# Managed by sonic-config-engine +############################################################################### +# +# EXAMPLE.conf: +# An example configuration file for configuring the Net-SNMP agent ('snmpd') +# See the 'snmpd.conf(5)' man page for details +# +# Some entries are deliberately commented out, and will need to be explicitly activated +# +############################################################################### +# +# AGENT BEHAVIOUR +# + +# Listen for connections on all ip addresses, including eth0, ipv4 lo +agentAddress udp:161 +# TODO: only support ipv4 lo addresses, add ipv6 support later + +############################################################################### +# +# ACCESS CONTROL +# + + # system + hrSystem groups only +view systemonly included .1.3.6.1.2.1.1 +view systemonly included .1.3.6.1.2.1.25.1 + + # Default access to basic system info +{% if snmp_rocommunities %} +{% for community in snmp_rocommunities %} +rocommunity {{ community }} +{% endfor %} +{% else %} +rocommunity {{ snmp_rocommunity }} +{% endif %} + +############################################################################### +# +# SYSTEM INFORMATION +# + +# Note that setting these values here, results in the corresponding MIB objects being 'read-only' +# See snmpd.conf(5) for more details +sysLocation {{ snmp_location }} +sysContact Azure Cloud Switch vteam + # Application + End-to-End layers +sysServices 72 + + +# +# Process Monitoring +# +# todo: should we enable snmp based monitoring of sswsyncd and other processes? + +# At least one 'sendmail' process, but no more than 10 +#proc sendmail 10 1 + +# Walk the UCD-SNMP-MIB::prTable to see the resulting output +# Note that this table will be empty if there are no "proc" entries in the snmpd.conf file + + +# +# Disk Monitoring +# + # 10MBs required on root disk, 5% free on /var, 10% free on all other disks +disk / 10000 +disk /var 5% +includeAllDisks 10% + +# Walk the UCD-SNMP-MIB::dskTable to see the resulting output +# Note that this table will be empty if there are no "disk" entries in the snmpd.conf file + + +# +# System Load +# + # Unacceptable 1-, 5-, and 15-minute load averages +load 12 10 5 + +# Walk the UCD-SNMP-MIB::laTable to see the resulting output +# Note that this table *will* be populated, even without a "load" entry in the snmpd.conf file + + + +############################################################################### +# +# ACTIVE MONITORING +# +# Note: disabled snmp traps due to side effect of causing snmpd to listen on all ports (0.0.0.0) +# +# send SNMPv1 traps +#trapsink localhost public +# send SNMPv2c traps +#trap2sink localhost public +# send SNMPv2c INFORMs +#informsink localhost public + +# Note that you typically only want *one* of these three lines +# Uncommenting two (or all three) will result in multiple copies of each notification. + + +# +# Event MIB - automatically generate alerts +# +# Remember to activate the 'createUser' lines above +#iquerySecName internalUser +#rouser internalUser +# generate traps on UCD error conditions +#defaultMonitors yes +#note, this release of snmpd does not support linkUpDownNotifications +# generate traps on linkUp/Down +#linkUpDownNotifications yes + + +# +# AgentX Sub-agents +# + # Run as an AgentX master agent +master agentx + +# +# SysDescription pass-through +# + +pass -p 10 .1.3.6.1.2.1.1.1 /usr/share/snmp/sysDescr_pass.py diff --git a/dockers/docker-snmp-sv2/start.sh b/dockers/docker-snmp-sv2/start.sh new file mode 100755 index 000000000000..6ec3379df58f --- /dev/null +++ b/dockers/docker-snmp-sv2/start.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +mkdir -p /etc/ssw +sonic-cfggen -d -y /etc/sonic/sonic_version.yml -t /usr/share/sonic/templates/sysDescription.j2 > /etc/ssw/sysDescription + +mkdir -p /etc/snmp +sonic-cfggen -d -y /etc/sonic/snmp.yml -t /usr/share/sonic/templates/snmpd.conf.j2 > /etc/snmp/snmpd.conf + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd +supervisorctl start snmpd +supervisorctl start snmp-subagent diff --git a/dockers/docker-snmp-sv2/supervisord.conf b/dockers/docker-snmp-sv2/supervisord.conf new file mode 100644 index 000000000000..d80579506100 --- /dev/null +++ b/dockers/docker-snmp-sv2/supervisord.conf @@ -0,0 +1,36 @@ +[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:snmpd] +command=/usr/sbin/snmpd -f -LS4d -u Debian-snmp -g Debian-snmp -I -smux,mteTrigger,mteTriggerConf,ifTable,ifXTable,inetCidrRouteTable,ipCidrRouteTable,ip,disk_hw -p /run/snmpd.pid +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:snmp-subagent] +command=/usr/bin/env python3.6 -m sonic_ax_impl +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/dockers/docker-snmp-sv2/sysDescription.j2 b/dockers/docker-snmp-sv2/sysDescription.j2 new file mode 100644 index 000000000000..207a8bf7de9a --- /dev/null +++ b/dockers/docker-snmp-sv2/sysDescription.j2 @@ -0,0 +1 @@ +SONiC Software Version: SONiC.{{ build_version }} - HwSku: {{ DEVICE_METADATA['localhost']['hwsku'] }} - Distribution: Debian {{ debian_version }} - Kernel: {{ kernel_version }} diff --git a/dockers/docker-sonic-mgmt/Dockerfile.j2 b/dockers/docker-sonic-mgmt/Dockerfile.j2 new file mode 100644 index 000000000000..aa02a701f510 --- /dev/null +++ b/dockers/docker-sonic-mgmt/Dockerfile.j2 @@ -0,0 +1,107 @@ +FROM ubuntu:16.04 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update +RUN apt-get install -y \ + openssh-server \ + gcc \ + vim \ + make \ + git \ + sudo \ + python \ + python-dev \ + python-cffi \ + libffi-dev \ + libssl-dev \ + sshpass \ + libxml2 \ + libxslt1-dev \ + python-setuptools \ + build-essential \ + curl + +# For JNLP launcher +RUN apt-get install -y default-jre + +# For syslog test +RUN apt-get install -y rsyslog psmisc + +# Remove cffi 1.5.2, will install 1.10.0 by pip later +RUN apt-get remove -y python-cffi python-cffi-backend +# Remove pycparser 2.14, will install >=2.17 by pip later +RUN apt-get remove -y python-ply python-pycparser + +RUN easy_install pip + +RUN pip install ipaddr \ + lxml \ + netaddr \ + natsort \ + six \ + pexpect \ + pyasn1==0.1.9 \ + pysnmp==4.2.5 \ + jinja2==2.7.2 \ + cffi==1.10.0 \ + paramiko==2.1.2 + +# Install Microsoft Azure Kusto Library for Python +RUN pip install azure-kusto-data==0.0.13 \ + azure-kusto-ingest==0.0.13 + +## Copy and install sonic-mgmt docker dependencies +COPY \ +{% for deb in docker_sonic_mgmt_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_sonic_mgmt_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +RUN git clone https://github.com/ansible/ansible +RUN cd ansible && git checkout v2.0.0.2-1 -b v2.0.0.2-1 && git submodule update --init --recursive && make && make install + +RUN mkdir /var/run/sshd +EXPOSE 22 + +# Add user +ARG user +ARG uid +ARG guid +ARG hostname + +ENV BUILD_HOSTNAME $hostname +ENV USER $user + +RUN groupadd -f -r -g $guid g$user + +RUN useradd $user -l -u $uid -g $guid -d /var/$user -m -s /bin/bash + +COPY sonic-jenkins.pub /var/$user/.ssh/authorized_keys2 + +RUN echo "Host *\n\tStrictHostKeyChecking no\n" > /var/$user/.ssh/config +RUN chown $user /var/$user/.ssh -R +RUN chmod go= /var/$user/.ssh -R + +# Add user to sudoers +RUN echo "$user ALL=(ALL) NOPASSWD:ALL" >>/etc/sudoers + +USER $user + +# Install Azure CLI +WORKDIR /var/$user +RUN curl -L https://aka.ms/InstallAzureCliBundled -o azure-cli_bundle.tar.gz +RUN tar -xvzf azure-cli_bundle.tar.gz +RUN azure-cli_bundle_*/installer + +# Known bug: azure keyvault cannot work behind a proxy +# Temporary fix: upgrade the azure-keyvault package within az cli +# TODO: if azure-cli contains newer version azure-keyvault, remove this +RUN ~/lib/azure-cli/bin/python -m pip install azure-keyvault==0.3.7 -U + +RUN git clone https://github.com/Azure/sonic-mgmt diff --git a/dockers/docker-sonic-mgmt/sonic-jenkins.pub b/dockers/docker-sonic-mgmt/sonic-jenkins.pub new file mode 100644 index 000000000000..8cbd97ce8c57 --- /dev/null +++ b/dockers/docker-sonic-mgmt/sonic-jenkins.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEJhhzQtlgNkBWxWXNm/qxZC26pFC16uOdGMx7BfMP9KxpKB46sFO5nkZXh8CiyjHitks2BYjbrK2IYubiyQhHaKh+4mnCnO58GLRRAiCUzeaC1jSrmqseBN8ZN7UV7gZUWQOxHErUHVhTbujUR0eZLymwPV0bNO9/bAWR5a+l5l/kf3VMREHF5Z6KyIuA9fT9XUJz8wLEUZCC8Id9RGwmKHS4FYuwtvcYm1MKb+ULXlri5o25G/X3I1pBpU/xUPBDUu+g3cIavrl7wVVGbIXYcYoH5qrTycMY0Y3rLBxu9SECUCqIxhnKQsiv+iXZSibnUXT4r6HcLMej5e+o1Jx3 lgh@jenkins-master-phx diff --git a/dockers/docker-sonic-telemetry/Dockerfile.j2 b/dockers/docker-sonic-telemetry/Dockerfile.j2 new file mode 100644 index 000000000000..6b77f999e5ee --- /dev/null +++ b/dockers/docker-sonic-telemetry/Dockerfile.j2 @@ -0,0 +1,34 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +RUN apt-get install -f -y libdbus-1-3 libdaemon0 libjansson4 + +## Install redis-tools dependencies +## TODO: implicitly install dependencies +RUN apt-get -y install libjemalloc1 + +COPY \ +{% for deb in docker_sonic_telemetry_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_sonic_telemetry_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "telemetry.sh", "dialout.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/dockers/docker-sonic-telemetry/dialout.sh b/dockers/docker-sonic-telemetry/dialout.sh new file mode 100755 index 000000000000..8683e8edae8e --- /dev/null +++ b/dockers/docker-sonic-telemetry/dialout.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# Start with default config + +exec /usr/sbin/dialout_client_cli -insecure -logtostderr -v 2 + diff --git a/dockers/docker-sonic-telemetry/start.sh b/dockers/docker-sonic-telemetry/start.sh new file mode 100755 index 000000000000..b307e387d557 --- /dev/null +++ b/dockers/docker-sonic-telemetry/start.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start telemetry +supervisorctl start dialout diff --git a/dockers/docker-sonic-telemetry/supervisord.conf b/dockers/docker-sonic-telemetry/supervisord.conf new file mode 100644 index 000000000000..dcd8a9eb1e80 --- /dev/null +++ b/dockers/docker-sonic-telemetry/supervisord.conf @@ -0,0 +1,36 @@ +[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:telemetry] +command=/usr/bin/telemetry.sh +priority=3 +autostart=false +autorestart=true +stdout_logfile=syslog +stderr_logfile=syslog + +[program:dialout] +command=/usr/bin/dialout.sh +priority=4 +autostart=false +autorestart=true +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/dockers/docker-sonic-telemetry/telemetry.sh b/dockers/docker-sonic-telemetry/telemetry.sh new file mode 100755 index 000000000000..053b1dae6ead --- /dev/null +++ b/dockers/docker-sonic-telemetry/telemetry.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# Try to read telemetry and x509 config from ConfigDB. +# Use default value if no valid config exists +X509=`sonic-cfggen -d -v "DEVICE_METADATA['x509']"` +TELEMETRY=`sonic-cfggen -d -v 'TELEMETRY.keys() | join(" ") if TELEMETRY'` + +TELEMETRY_ARGS=" -logtostderr" + +if [ ! -z $X509 ]; then + SERVER_CRT=`sonic-cfggen -d -v "DEVICE_METADATA['x509']['server_crt']"` + SERVER_KEY=`sonic-cfggen -d -v "DEVICE_METADATA['x509']['server_key']"` + if [ -z $SERVER_CRT ] || [ -z $SERVER_KEY ]; then + TELEMETRY_ARGS+=" --insecure" + else + TELEMETRY_ARGS+=" --server_crt $SERVER_CRT --server_key $SERVER_KEY " + fi +else + TELEMETRY_ARGS+=" --insecure" +fi + +if [ ! -z $X509 ]; then + CA_CRT=`sonic-cfggen -d -v "DEVICE_METADATA['x509']['ca_crt']"` + if [ ! -z $CA_CRT ]; then + TELEMETRY_ARGS+=" --ca_crt $CA_CRT" + fi +fi + +# If no configuration entry exists for TELEMETRY, create one default port +if [ -z $TELEMETRY ]; then + redis-cli -n 4 hset "TELEMETRY|gnmi" port 8080 +fi + +PORT=`sonic-cfggen -d -v "TELEMETRY['gnmi']['port']"` +TELEMETRY_ARGS+=" --port $PORT" + +CLIENT_AUTH=`sonic-cfggen -d -v "TELEMETRY['gnmi']['client_auth']"` +if [ -z $CLIENT_AUTH ] || [ $CLIENT_AUTH == "false" ]; then + TELEMETRY_ARGS+=" --allow_no_client_auth" +fi + +LOG_LEVEL=`sonic-cfggen -d -v "TELEMETRY['gnmi']['log_level']"` +if [ ! -z $LOG_LEVEL ]; then + TELEMETRY_ARGS+=" -v=$LOG_LEVEL" +else + TELEMETRY_ARGS+=" -v=2" +fi + +exec /usr/sbin/telemetry ${TELEMETRY_ARGS} + + diff --git a/dockers/docker-teamd/Dockerfile.j2 b/dockers/docker-teamd/Dockerfile.j2 new file mode 100644 index 000000000000..cb749ccf8eae --- /dev/null +++ b/dockers/docker-teamd/Dockerfile.j2 @@ -0,0 +1,34 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +RUN apt-get install -f -y libdbus-1-3 libdaemon0 libjansson4 libpython2.7 + +## Install redis-tools dependencies +## TODO: implicitly install dependencies +RUN apt-get -y install libjemalloc1 + +COPY \ +{% for deb in docker_teamd_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_teamd_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/dockers/docker-teamd/base_image_files/teamdctl b/dockers/docker-teamd/base_image_files/teamdctl new file mode 100755 index 000000000000..615bc3d953fa --- /dev/null +++ b/dockers/docker-teamd/base_image_files/teamdctl @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS teamd teamdctl "$@" diff --git a/dockers/docker-teamd/start.sh b/dockers/docker-teamd/start.sh new file mode 100755 index 000000000000..4cbc65ab0cc3 --- /dev/null +++ b/dockers/docker-teamd/start.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid +rm -f /var/run/teamd/* + +mkdir -p /var/warmboot/teamd + +supervisorctl start rsyslogd + +supervisorctl start teammgrd + +supervisorctl start teamsyncd diff --git a/dockers/docker-teamd/supervisord.conf b/dockers/docker-teamd/supervisord.conf new file mode 100644 index 000000000000..738751d0a59f --- /dev/null +++ b/dockers/docker-teamd/supervisord.conf @@ -0,0 +1,36 @@ +[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:teammgrd] +command=/usr/bin/teammgrd +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:teamsyncd] +command=/usr/bin/teamsyncd +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/files/Aboot/boot0 b/files/Aboot/boot0 deleted file mode 100644 index 98522bdfe647..000000000000 --- a/files/Aboot/boot0 +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (C) 2016 Arista Networks, Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Aboot stage 0 boot - -set -x - -bootconfigvars="SWI SWI_COPY POST_LEVEL CONSOLESPEED PASSWORD NETDEV NETAUTO NETIP NETMASK NETGW NETDOMAIN NETDNS NETHW memtest" - -parseenvironmentconfig() { - for n in ${bootconfigvars}; do - eval v="\$$n" - if [ "$v" ]; then - echo "$n=$v" - fi - done -} - -kernel=boot/vmlinuz-3.16.0-4-amd64 -initrd=boot/initrd.img-3.16.0-4-amd64 - -TARGET_PATH=/mnt/flash -if [ -d "${swipath}" ]; then - # Not expect a directory name for swipath - exit 1 -fi - -## Determine whether installing by hash file in the image -GIT_REVISION=$(unzip -p ${swipath} .imagehash) -LOCAL_IMAGEHASH=$(cat $TARGET_PATH/.imagehash 2>/dev/null || true) -if [ "$GIT_REVISION" != "$LOCAL_IMAGEHASH" ]; then - unzip -oq ${swipath} -x boot0 -d ${TARGET_PATH} -fi - -echo "${append}" >/tmp/append -parseenvironmentconfig >>/tmp/append -cat /etc/cmdline | sed "/^\(${bootconfigvars// /\|}\|crashkernel\|loglevel\|ignore_loglevel\)\(\$\|=\)/d;/^\$/d" >>/tmp/append - -echo "root=/dev/sda1 rw loop=fs.squashfs loopfstype=squashfs apparmor=1 security=apparmor quiet" >>/tmp/append - -kexec --load --initrd=${TARGET_PATH}/${initrd} --append="$(tr '\n' ' ' . + +# Aboot stage 0 boot script +# +# This boot0 script can be used in different scenario +# - Installation and boot from Aboot (manual or reboot on a new image) +# - EOS to SONiC fast-reboot (installation and kexec in EOS) +# - SONiC to SONiC fast-reboot (installation and kexec in SONiC) +# +# Use it this way: +# - swipath=path/to/swi install=true boot0 +# - swipath=path/to/swi install=true force=true boot0 +# - swipath=path/to/swi kexec=true boot0 +# +# The logic defaults to the first scenario but providing extra environment variable +# will affect the behavior of the script. +# The list of variables is maintained here +# - KERNEL : relative path to the kernel to execute +# - INITRD : relative path to the initrd to load +# - CMDLINE : place to find the default kernel cmdline to use for the platform +# - VERBOSE : setting it to 1 will enable debug traces +# +# By default the boot0 script will behave for an Aboot based behavior. +# Options can be provided to only run some features of this script. +# +# Extra kernel parameters can be provided at runtime by the user by adding them +# into a kernel-params file. + +image_name="image-%%IMAGE_VERSION%%" +dockerfs="{{ FILESYSTEM_DOCKERFS }}" + +do_not_clean="do-not-clean" +kernel_params="kernel-params" + +aboot_machine="arista_unknown" + +info() { printf "%04.2f: $@\n" "$(cut -f1 -d' ' /proc/uptime)"; } +err() { info "Error: $@"; } +warn() { info "Warning: $@"; } + +# extract mount point from the swi path, e.g., /mnt/flash/sonic.swi --> /mnt/flash +if [ -z "$target_path" ]; then + if [ -z "$swipath" ]; then + err "target_path= is required when swipath= is not provided" + exit 1 + fi + target_path=$(df "$swipath" | tail -1 | tr -s " " | cut -d ' ' -f6) +fi +image_path="$target_path/$image_name" +hook_path="$image_path/platform/hooks" +data_path="$image_path/platform/data" + +cmdline_base="$target_path/kernel-params-base" +cmdline_image="$image_path/kernel-cmdline" +boot_config="$target_path/boot-config" + +bootconfigvars="KERNEL INITRD CONSOLESPEED PASSWORD NETDEV NETAUTO NETIP NETMASK NETGW NETDOMAIN NETDNS NETHW memtest" +flash_re=" /mnt/flash| /host" + +# for backward compatibility with the sonic_upgrade= behavior +install="${install:-${sonic_upgrade:-}}" + +parse_environment_config() { + for n in ${bootconfigvars}; do + eval v="\$$n" + if [ "$v" ]; then + echo "$n=$v" + fi + done +} + +clean_flash() { + ## Remove all the other unnecssary files except swi file, boot-config + for f in $(ls -A $target_path); do + if [ $f != "${swipath##*/}" ] && + [ $f != "boot-config" ] && + [ $f != "$kernel_params" ] && + [ $f != "$cmdline_base" ] && + [ $f != "aquota.user" ] && + [ $f != "old_config" ] && + [ $f != "minigraph.xml" ] + then + rm -rf "$target_path/$f" + fi + done +} + +update_boot_config() { + local key="$1" + local value="$2" + + if grep "$key" "$boot_config" 2>&1 > /dev/null; then + sed -i "s#^$key=.*\$#$key=$value#" "$boot_config" + else + echo "$key=$value" >> "$boot_config" + fi +} + +get_boot_config() { + local key="$1" + + sed -n "s#^$key=##p" "$boot_config" || : +} + +update_next_boot() { + local default="$(get_boot_config SWI_DEFAULT)" + + if [ -z "$default" ]; then + warn "boot-config has no variable SWI_DEFAULT" + else + update_boot_config SWI "$default" + fi +} + +extract_image() { + mkdir -p "$image_path" + + info "Extracting swi content" + ## Unzip the image except boot0 and dockerfs archive + unzip -oq "$swipath" -x boot0 "$dockerfs" -d "$image_path" + + ## detect rootfs type + rootfs_type=`grep " $target_path " /proc/mounts | cut -d' ' -f3` + + info "Extracting $dockerfs from swi" + ## vfat does not support symbol link + if [ -n "$install" ] || [ "$rootfs_type" != "vfat" ]; then + mkdir -p "$image_path/{{ DOCKERFS_DIR }}" + + if [ -n "$install" ]; then + TAR_EXTRA_OPTION="--numeric-owner --warning=no-timestamp" + fi + + ## extract docker archive + info "Unpacking $dockerfs" + unzip -oqp "$swipath" "$dockerfs" | tar xzf - -C "$image_path/{{ DOCKERFS_DIR }}" $TAR_EXTRA_OPTION + else + ## save dockerfs archive in the image directory + unzip -oq "$swipath" "$dockerfs" -d "$image_path" + info "Unpacking $dockerfs delayed to initrd because $target_path is $rootfs_type" + fi + + ## use new reduced-size boot swi + local swi_boot_path="flash:$image_name/{{ ABOOT_BOOT_IMAGE }}" + update_boot_config SWI "$swi_boot_path" + update_boot_config SWI_DEFAULT "$swi_boot_path" + + ## Remove installer swi as it has lots of redundunt contents + rm -f "$swipath" + + ## sync disk operations + sync +} + +write_machine_config() { + ## Detect SKU and create a hardware description file + aboot_version=$(grep ^Aboot "$cmdline_base" | sed 's/^.*norcal.-//' | tail -n 1) + if [ -x /bin/sysinit ]; then + aboot_build_date=$(stat -c %y /bin/sysinit | sed 's/ /T/') + else + aboot_build_date="unknown" + fi + cat < ${target_path}/machine.conf +aboot_version=$aboot_version +aboot_vendor=arista +aboot_platform=x86_64-$aboot_machine +aboot_machine=$aboot_machine +aboot_arch=x86_64 +aboot_build_date=$aboot_build_date +EOF + chmod a+r "${target_path}/machine.conf" +} + +platform_specific() { + local platform="$(grep -Eo 'platform=[^ ]+' "$cmdline_base" | cut -f2 -d=)" + local sid="$(grep -Eo 'sid=[^ ]+' "$cmdline_base" | cut -f2 -d=)" + + # set varlog size to 100MB + local varlog_size=100 + + # detect the size of the flash partition from name in Aboot/EOS/SONiC + local flash_size=$(($(df | grep -E "$flash_re" | tr -s ' ' | cut -f2 -d' ') / 1000)) + + if [ "$platform" = "raven" ]; then + aboot_machine=arista_7050_qx32 + flash_size=2000 + echo "modprobe.blacklist=radeon,sp5100_tco acpi=off" >>/tmp/append + fi + if [ "$platform" = "crow" ]; then + aboot_machine=arista_7050_qx32s + flash_size=3700 + echo "modprobe.blacklist=radeon,sp5100_tco" >>/tmp/append + fi + if [ "$sid" = "Upperlake" ] || [ "$sid" = "UpperlakeES" ]; then + aboot_machine=arista_7060_cx32s + flash_size=3700 + echo "amd_iommu=off" >> /tmp/append + fi + if [ "$sid" = "Gardena" ] || [ "$sid" = "GardenaSsd" ]; then + aboot_machine=arista_7260cx3_64 + flash_size=28000 + fi + if [ "$sid" = "Alhambra" ] || [ "$sid" = "AlhambraSsd" ]; then + aboot_machine=arista_7170_64c + flash_size=28000 + echo "hugepages=128" >> /tmp/append + fi + if [ "$platform" = "rook" ]; then + echo "iommu=on intel_iommu=on tsc=reliable pcie_ports=native" >>/tmp/append + echo "rhash_entries=1 usb-storage.delay_use=0" >>/tmp/append + if [ -x /bin/readprefdl ]; then + readprefdl -f /tmp/.system-prefdl -d > /mnt/flash/.system-prefdl + elif [ -f /etc/prefdl ]; then + cp /etc/prefdl /mnt/flash/.system-prefdl + chmod a+r /mnt/flash/.system-prefdl + fi + echo "reassign_prefmem" >> /tmp/append + fi + + if [ $flash_size -ge 28000 ]; then + varlog_size=4096 + elif [ $flash_size -ge 3700 ]; then + varlog_size=400 + fi + + echo "varlog_size=$varlog_size" >>/tmp/append + # disable deterministic interface naming + echo "net.ifnames=0" >>/tmp/append +} + +get_uuid_for() { + local dev="$1" + + if type lsblk 2>&1 > /dev/null; then + lsblk "$dev" -n --output UUID + elif type blkid 2>&1 > /dev/null; then + blkid | grep "^$dev" | sed -n "s/^.* UUID=\"//p" | grep -Eo '[^"]+' + fi +} + +write_boot_configs() { + if $in_aboot; then + # generate the default kernel parameters for the platform + echo "$append" > $cmdline_base + cat /etc/cmdline | sed "/^\(${bootconfigvars// /\|}\|crashkernel\|loglevel\|ignore_loglevel\)\(\$\|=\)/d;/^\$/d" >> $cmdline_base + parse_environment_config >> $cmdline_base + elif [ ! -f "$cmdline_base" ]; then + # some systems were started with other versions of this script and therefore + # do not have the $cmdline_base file. we assume that we are on Sonic or EOS. + cat /proc/cmdline | sed -E 's/^(.*) rw .*$/\1/' | tr ' ' '\n' > $cmdline_base + fi + + cp $cmdline_base /tmp/append + + platform_specific + echo "rw loop=$image_name/fs.squashfs loopfstype=squashfs apparmor=1 security=apparmor quiet" >> /tmp/append + + # Pass the MAC address to the new kernel as a command line parameter. This makes it + # possible to restore the MAC address in the new kernel without requiring driver modifications. + if [ -f /sys/class/net/ma1/address ]; then + echo "hwaddr_ma1=$(cat /sys/class/net/ma1/address)" >> /tmp/append + elif [ -f /sys/class/net/eth0/address ]; then + echo "hwaddr_ma1=$(cat /sys/class/net/eth0/address)" >> /tmp/append + else + err "Management port not found." + fi + + # use extra parameters from kernel-params hook if the file exists + if [ -f "$target_path/$kernel_params" ]; then + cat "$target_path/$kernel_params" >> /tmp/append + fi + + # setting root partition if not overridden by kernel-params + if ! grep -q "root=" /tmp/append; then + rootdev="$(mount | grep -E "$flash_re" | cut -f1 -d' ')" + rootfstype="$(mount | grep -E "$flash_re" | cut -f5 -d' ')" + rootuuid="$(get_uuid_for $rootdev)" + if [ -z "$rootuuid" ] || [ "$rootfstype" = "vfat" ] ; then + echo "root=$rootdev" >> /tmp/append + else + echo "root=UUID=$rootuuid" >> /tmp/append + fi + fi + + mv /tmp/append $cmdline_image + [ -e ${target_path}/machine.conf ] || write_machine_config +} + +run_kexec() { + local cmdline="$(cat $cmdline_image | tr '\n' ' ')" + local kernel="${KERNEL:-$(find $image_path/boot -name 'vmlinuz-*' -type f | head -n 1)}" + local initrd="${INITRD:-$(find $image_path/boot -name 'initrd.img-*' -type f | head -n 1)}" + + if ! $verbose; then + # Start showing systemd information from the first failing unit if any. + # systemd.show_status=false or quiet can be used to silence systemd entierly + cmdline="$cmdline systemd.show_status=auto" + fi + + kexec --load --initrd="$initrd" --append="$cmdline" "$kernel" + + [ -z "$testonly" ] || exit 0 + info "Kexecing..." + kexec --exec +} + +get_sorted_hooks() { + echo $(find "$1" -name '[0-9][0-9]-*' -type f) +} + +run_hooks() { + if [ -d "$hook_path/$1" ]; then + for hook in $(get_sorted_hooks "$hook_path/$1"); do + if [ ! -z "$hook" ]; then + info "Running hook $hook" + . "$hook" + fi + done + fi +} + +# In Aboot no option will be provided therefore these are the default values to use +in_aboot=true +do_clean=true +do_install=true +do_kexec=true + +# prevent the flash from being cleaned if the do-not-clean file exists +if [ -f "$target_path/$do_not_clean" ]; then + do_clean=false +fi + +# Parse the cmdline options (used from EOS or from SONiC) +if [ ! -z "$install" ]; then + # install from SONiC or EOS + in_aboot=false + do_clean=false + do_kexec=false +elif [ ! -z "$kexec" ]; then + # kexec from SONiC or EOS + in_aboot=false + do_install=false + do_clean=false +elif [ $# -ne 0 ]; then + echo "usage: $0 (see code)" + exit 1 +fi + +# Verbosity can be defined by the caller, default to false otherwise +verbose=${verbose:-false} +if [ -f "$target_path/verbose-boot" ] || + [ "$(get_boot_config VERBOSE)" = "1" ] || + ! $in_aboot; then + verbose=true +fi + +# enable shell debug mode to get the most verbosity +if $verbose; then + set -x +fi + +# install the image if newer +if $do_install; then + # we expect the swi to install to be a non empty file + if [ ! -s "$swipath" ]; then + err "The swipath= environment variable does not point to a valid SWI" + exit 1 + fi + + # check the hash file in the image, and determine to install or just skip + GIT_REVISION=$(unzip -p "$swipath" .imagehash) + LOCAL_IMAGEHASH=$(cat $image_path/.imagehash 2>/dev/null || true) + + if [ "$GIT_REVISION" != "$LOCAL_IMAGEHASH" ] || [ ! -z "$force" ]; then + if $do_clean; then + info "Cleaning flash content $target_path" + clean_flash + fi + + info "Installing image under $image_path" + extract_image + + info "Generating boot-config, machine.conf and cmdline" + write_boot_configs + + run_hooks post-install + else + info "Using previously installed image" + fi +fi + +# chainloading using kexec +if $do_kexec; then + run_hooks pre-kexec + update_next_boot + run_kexec +fi diff --git a/files/apt/apt.conf.d/81norecommends b/files/apt/apt.conf.d/81norecommends new file mode 100644 index 000000000000..d868eb45e228 --- /dev/null +++ b/files/apt/apt.conf.d/81norecommends @@ -0,0 +1,3 @@ +APT::Install-Recommends "false"; +APT::AutoRemove::RecommendsImportant "false"; +APT::AutoRemove::SuggestsImportant "false"; diff --git a/files/apt/apt.conf.d/apt-clean b/files/apt/apt.conf.d/apt-clean new file mode 100644 index 000000000000..886c6d829a3b --- /dev/null +++ b/files/apt/apt.conf.d/apt-clean @@ -0,0 +1,19 @@ +# Since for most Docker users, package installs happen in "docker build" steps, +# they essentially become individual layers due to the way Docker handles +# layering, especially using CoW filesystems. What this means for us is that +# the caches that APT keeps end up just wasting space in those layers, making +# our layers unnecessarily large (especially since we'll normally never use +# these caches again and will instead just "docker build" again and make a brand +# new image). + +# Ideally, these would just be invoking "apt-get clean", but in our testing, +# that ended up being cyclic and we got stuck on APT's lock, so we get this fun +# creation that's essentially just "apt-get clean". +DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; }; +APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; }; + +Dir::Cache::pkgcache ""; +Dir::Cache::srcpkgcache ""; + +# Note that we do realize this isn't the ideal way to do this, and are always +# open to better suggestions (https://github.com/docker/docker/issues). diff --git a/files/apt/apt.conf.d/apt-gzip-indexes b/files/apt/apt.conf.d/apt-gzip-indexes new file mode 100644 index 000000000000..6d29ac4474de --- /dev/null +++ b/files/apt/apt.conf.d/apt-gzip-indexes @@ -0,0 +1,11 @@ +# Since Docker users using "RUN apt-get update && apt-get install -y ..." in +# their Dockerfiles don't go delete the lists files afterwards, we want them to +# be as small as possible on-disk, so we explicitly request "gz" versions and +# tell Apt to keep them gzipped on-disk. + +# For comparison, an "apt-get update" layer without this on a pristine +# "debian:wheezy" base image was "29.88 MB", where with this it was only +# "8.273 MB". + +Acquire::GzipIndexes "true"; +Acquire::CompressionTypes::Order:: "gz"; diff --git a/files/apt/apt.conf.d/apt-no-languages b/files/apt/apt.conf.d/apt-no-languages new file mode 100644 index 000000000000..964d83d6c5b9 --- /dev/null +++ b/files/apt/apt.conf.d/apt-no-languages @@ -0,0 +1,5 @@ +# In Docker, we don't often need the "Translations" files, so we're just wasting +# time and space by downloading them, and this inhibits that. For users that do +# need them, it's a simple matter to delete this file and "apt-get update". :) + +Acquire::Languages "none"; diff --git a/files/apt/sources.list b/files/apt/sources.list new file mode 100644 index 000000000000..b1ce507a44f5 --- /dev/null +++ b/files/apt/sources.list @@ -0,0 +1,8 @@ +## Debian mirror on Microsoft Azure +## Ref: http://debian-archive.trafficmanager.net/ + +deb http://debian-archive.trafficmanager.net/debian/ stretch main contrib non-free +deb-src http://debian-archive.trafficmanager.net/debian/ stretch main contrib non-free +deb http://debian-archive.trafficmanager.net/debian-security/ stretch/updates main contrib non-free +deb-src http://debian-archive.trafficmanager.net/debian-security/ stretch/updates main contrib non-free +deb http://debian-archive.trafficmanager.net/debian/ stretch-backports main contrib non-free diff --git a/files/build_templates/bgp.service.j2 b/files/build_templates/bgp.service.j2 new file mode 100644 index 000000000000..bc023b7d714d --- /dev/null +++ b/files/build_templates/bgp.service.j2 @@ -0,0 +1,14 @@ +[Unit] +Description=BGP container +Requires=updategraph.service +After=updategraph.service +Before=ntp-config.service + +[Service] +User={{ sonicadmin_user }} +ExecStartPre=/usr/bin/{{docker_container_name}}.sh start +ExecStart=/usr/bin/{{docker_container_name}}.sh attach +ExecStop=/usr/bin/{{docker_container_name}}.sh stop + +[Install] +WantedBy=multi-user.target diff --git a/files/build_templates/buffers_config.j2 b/files/build_templates/buffers_config.j2 new file mode 100644 index 000000000000..7c9b22de1954 --- /dev/null +++ b/files/build_templates/buffers_config.j2 @@ -0,0 +1,154 @@ +{%- macro set_default_topology() %} +{%- if default_topo is defined %} +{{ default_topo }} +{%- else %} +def +{%- endif %} +{%- endmacro -%} + +{# Determine device topology and filename postfix #} +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- if switch_role.lower() == 'torrouter' %} +{%- set filename_postfix = 't0' %} +{%- elif switch_role.lower() == 'leafrouter' %} +{%- set filename_postfix = 't1' %} +{%- else %} +{%- set filename_postfix = set_default_topology() %} +{%- endif %} +{%- else %} +{%- set filename_postfix = set_default_topology() %} +{%- set switch_role = '' %} +{%- endif -%} + +{# Import default values from device HWSKU folder #} +{%- import 'buffers_defaults_%s.j2' % filename_postfix as defs %} + +{%- set default_cable = defs.default_cable -%} + +{# 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' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +-%} + +{%- 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 %} + {%- set roles1 = roles1 | lower %} + {%- set roles2 = roles2 | lower %} + {%- 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 %} + {%- if switch_role.lower() == 'torrouter' %} + {%- for local_port in VLAN_MEMBER %} + {%- if local_port[1] == port_name %} + {%- set roles3 = switch_role + '_' + 'server' %} + {%- set roles3 = roles3 | lower %} + {%- if roles3 in ports2cable %} + {%- if cable_len.append(ports2cable[roles3]) %}{% endif %} + {%- endif %} + {%- endif %} + {%- endfor %} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif %} + {%- else -%} + {{ default_cable }} + {%- endif %} + {%- endif %} +{%- endmacro %} + +{%- set PORT_ALL = [] %} + +{%- if PORT is not defined %} + {%- if defs.generate_port_lists(PORT_ALL) %} {% endif %} +{%- else %} + {%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') %} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {%- set cable = cable_length(port) %} + "{{ port }}": "{{ cable }}"{%- if not loop.last %},{% endif %} + + {% endfor %} + } + }, + +{% if defs.generate_buffer_pool_and_profiles is defined %} +{{ defs.generate_buffer_pool_and_profiles() }} +{% endif %} + +{%- if defs.generate_profile_lists is defined %} +{{ defs.generate_profile_lists(port_names_active) }}, +{% endif %} + +{%- if defs.generate_pg_profils is defined %} +{{ defs.generate_pg_profils(port_names_active) }} +{% else %} + "BUFFER_PG": { + "{{ port_names_active }}|0-1": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names_active }}|5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, +{% endif %} + +{% if defs.generate_queue_buffers is defined %} +{{ defs.generate_queue_buffers(port_names_active) }} +{% else %} + "BUFFER_QUEUE": { + "{{ port_names_active }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names_active }}|0-1": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names_active }}|5": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +{% endif %} +} diff --git a/files/build_templates/database.service.j2 b/files/build_templates/database.service.j2 new file mode 100644 index 000000000000..b248dfc7fecd --- /dev/null +++ b/files/build_templates/database.service.j2 @@ -0,0 +1,13 @@ +[Unit] +Description=Database container +Requires=docker.service +After=docker.service + +[Service] +User=root +ExecStartPre=/usr/bin/{{docker_container_name}}.sh start +ExecStart=/usr/bin/{{docker_container_name}}.sh attach +ExecStop=/usr/bin/{{docker_container_name}}.sh stop + +[Install] +WantedBy=multi-user.target diff --git a/files/build_templates/dhcp_relay.service.j2 b/files/build_templates/dhcp_relay.service.j2 new file mode 100644 index 000000000000..b4d9ceb38f0c --- /dev/null +++ b/files/build_templates/dhcp_relay.service.j2 @@ -0,0 +1,14 @@ +[Unit] +Description=DHCP relay container +Requires=updategraph.service swss.service teamd.service +After=updategraph.service swss.service teamd.service +Before=ntp-config.service + +[Service] +User={{ sonicadmin_user }} +ExecStartPre=/usr/bin/{{ docker_container_name }}.sh start +ExecStart=/usr/bin/{{ docker_container_name }}.sh attach +ExecStop=/usr/bin/{{ docker_container_name }}.sh stop + +[Install] +WantedBy=multi-user.target teamd.service diff --git a/files/build_templates/docker_image_ctl.j2 b/files/build_templates/docker_image_ctl.j2 new file mode 100644 index 000000000000..22d69702286b --- /dev/null +++ b/files/build_templates/docker_image_ctl.j2 @@ -0,0 +1,169 @@ +#!/bin/bash + +function getMountPoint() +{ + echo $1 | python -c "import sys, json, os; mnts = [x for x in json.load(sys.stdin)[0]['Mounts'] if x['Destination'] == '/usr/share/sonic/hwsku']; print '' if len(mnts) == 0 else os.path.basename(mnts[0]['Source'])" 2>/dev/null +} + +function getBootType() +{ + local BOOT_TYPE + case "$(cat /proc/cmdline | grep -o 'SONIC_BOOT_TYPE=\S*' | cut -d'=' -f2)" in + warm*) + TYPE='warm' + ;; + fastfast) + TYPE='fastfast' + ;; + fast*) + TYPE='fast' + ;; + *) + TYPE='cold' + esac + echo "${TYPE}" +} + +function preStartAction() +{ +{%- if docker_container_name == "database" %} + WARM_DIR=/host/warmboot + if [[ "$BOOT_TYPE" == "warm" && -f $WARM_DIR/dump.rdb ]]; then + # Load redis content from /host/warmboot/dump.rdb + docker cp $WARM_DIR/dump.rdb database:/var/lib/redis/dump.rdb + else + # Create an emtpy file and overwrite any RDB if already there + echo -n > /tmp/dump.rdb + docker cp /tmp/dump.rdb database:/var/lib/redis/ + fi +{%- else %} + : # nothing +{%- endif %} +} + +function postStartAction() +{ +{%- if docker_container_name == "database" %} + # Wait until redis starts + REDIS_SOCK="/var/run/redis/redis.sock" + until [[ $(/usr/bin/docker exec database redis-cli -s $REDIS_SOCK ping | grep -c PONG) -gt 0 ]]; do + sleep 1; + done + if [[ "$BOOT_TYPE" == "warm" && -f $WARM_DIR/dump.rdb ]]; then + rm -f $WARM_DIR/dump.rdb + else + # If there is a config db dump file, load it + if [ -r /etc/sonic/config_db.json ]; then + sonic-cfggen -j /etc/sonic/config_db.json --write-to-db + fi + + redis-cli -n 4 SET "CONFIG_DB_INITIALIZED" "1" + fi +{%- elif docker_container_name == "swss" %} + docker exec swss rm -f /ready # remove cruft + if [[ "$BOOT_TYPE" == "fast" || "$BOOT_TYPE" == "fastfast" ]] && [[ -d /host/fast-reboot ]]; then + test -e /host/fast-reboot/fdb.json && docker cp /host/fast-reboot/fdb.json swss:/ + test -e /host/fast-reboot/arp.json && docker cp /host/fast-reboot/arp.json swss:/ + test -e /host/fast-reboot/default_routes.json && docker cp /host/fast-reboot/default_routes.json swss:/ + rm -fr /host/fast-reboot + fi + docker exec swss touch /ready # signal swssconfig.sh to go +{%- elif docker_container_name == "pmon" %} + + DEVPATH="/usr/share/sonic/device" + REBOOT="platform_reboot" + PSENSOR="/usr/local/bin/platform_sensors.py" + if [ -d ${DEVPATH}/${PLATFORM} ] && [ -f $PSENSOR ]; then + exist=`docker exec -i pmon ls /usr/bin/platform_sensors.py "$@" 2>/dev/null` + if [ -z "$exist" ]; then + docker cp $PSENSOR pmon:/usr/bin/ + fi + fi +{%- elif docker_container_name == "snmp" %} + docker exec -i database redis-cli -n 6 HSET 'DEVICE_METADATA|localhost' chassis_serial_number $(decode-syseeprom -s) +{%- else %} + : # nothing +{%- endif %} +} + +start() { + # Obtain boot type from kernel arguments + BOOT_TYPE=`getBootType` + + # Obtain our platform as we will mount directories with these names in each docker + PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform` + + {%- if docker_container_name == "database" %} + # Don't mount HWSKU in {{docker_container_name}} container. + HWSKU="" + {%- else %} + # Obtain our HWSKU as we will mount directories with these names in each docker + HWSKU=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hwsku"]'` + {%- endif %} + + DOCKERCHECK=`docker inspect --type container {{docker_container_name}} 2>/dev/null` + if [ "$?" -eq "0" ]; then + DOCKERMOUNT=`getMountPoint "$DOCKERCHECK"` + if [ "$DOCKERMOUNT" == "$HWSKU" ]; then + echo "Starting existing {{docker_container_name}} container with HWSKU $HWSKU" + preStartAction + docker start {{docker_container_name}} + postStartAction + exit $? + fi + + # docker created with a different HWSKU, remove and recreate + echo "Removing obsolete {{docker_container_name}} container with HWSKU $DOCKERMOUNT" + docker rm -f {{docker_container_name}} + fi + +{%- if docker_container_name == "database" %} + echo "Creating new {{docker_container_name}} container" +{%- else %} + echo "Creating new {{docker_container_name}} container with HWSKU $HWSKU" +{%- endif %} + docker create {{docker_image_run_opt}} \ +{%- if '--log-driver=json-file' in docker_image_run_opt or '--log-driver' not in docker_image_run_opt %} + --log-opt max-size=2M --log-opt max-file=5 \ +{%- endif %} +{%- if docker_container_name == "syncd" and sonic_asic_platform == "mellanox" %} + -e SX_SNIFFER_ENABLE \ + -e SX_SNIFFER_TARGET \ + -e PRM_SNIFFER \ + -e PRM_SNIFFER_FILE_PATH \ + -v /var/log/mellanox/sniffer:/var/log/mellanox/sniffer:rw \ +{%- endif %} + -v /var/run/redis:/var/run/redis:rw \ + -v /usr/share/sonic/device/$PLATFORM:/usr/share/sonic/platform:ro \ +{%- if docker_container_name != "database" %} + -v /usr/share/sonic/device/$PLATFORM/$HWSKU:/usr/share/sonic/hwsku:ro \ +{%- endif %} + --tmpfs /tmp \ + --tmpfs /var/tmp \ + --name={{docker_container_name}} {{docker_image_name}}:latest || { + echo "Failed to docker run" >&1 + exit 4 + } + + preStartAction + docker start {{docker_container_name}} + postStartAction +} + +attach() { + docker attach --no-stdin {{docker_container_name}} +} + +stop() { + docker stop {{docker_container_name}} +} + +case "$1" in + start|stop|attach) + $1 + ;; + *) + echo "Usage: $0 {start|stop|attach}" + exit 1 + ;; +esac diff --git a/files/build_templates/lldp.service.j2 b/files/build_templates/lldp.service.j2 new file mode 100644 index 000000000000..d294a08900f4 --- /dev/null +++ b/files/build_templates/lldp.service.j2 @@ -0,0 +1,14 @@ +[Unit] +Description=LLDP container +Requires=updategraph.service +After=updategraph.service +Before=ntp-config.service + +[Service] +User={{ sonicadmin_user }} +ExecStartPre=/usr/bin/{{docker_container_name}}.sh start +ExecStart=/usr/bin/{{docker_container_name}}.sh attach +ExecStop=/usr/bin/{{docker_container_name}}.sh stop + +[Install] +WantedBy=multi-user.target diff --git a/files/build_templates/organization_extensions.sh b/files/build_templates/organization_extensions.sh new file mode 100755 index 000000000000..db05a4e3f59d --- /dev/null +++ b/files/build_templates/organization_extensions.sh @@ -0,0 +1,52 @@ +#!/bin/bash +######################################################################### +## This script is to automate Orignaization specific extensions # +## such as Configuration & Scripts for features like AAA, ZTP, etc. # +## to include in ONIE installer image # +## # +## USAGE: # +## ./organization_extensions.sh -f -n # +## ./organization_extensions.sh \ # +## --fsroot \ # +## --hostname # +## PARAMETERS: # +## -f FILESYSTEM_ROOT # +## The location of the root file system # +## -h HOSTNAME # +## The hostname of the target system # +######################################################################### + +## Initialize the arguments to default values. +## The values get updated to user provided value, if supplied +FILESYSTEM_ROOT=./fsroot +HOSTNAME=sonic + +# read the options +TEMP=`getopt -o f:h: --long fsroot:,hostname: -- "$@"` +eval set -- "$TEMP" + +# extract options and their arguments into variables. +while true ; do + case "$1" in + -f|--fsroot) + case "$2" in + "") shift 2 ;; + *) FILESYSTEM_ROOT=$2 ; shift 2 ;; + esac ;; + -h|--hostname) + case "$2" in + "") shift 2 ;; + *) HOSTNAME=$2 ; shift 2 ;; + esac ;; + --) shift ; break ;; + *) echo "Internal error!" ; exit 1 ;; + esac +done + +echo "Executing SONIC Organization Extensions" + +## Place your Organization specific code / scipts here ... + + +echo "SONIC Organization Extensions - Done" + diff --git a/files/build_templates/pmon.service.j2 b/files/build_templates/pmon.service.j2 new file mode 100644 index 000000000000..de4e62df5e10 --- /dev/null +++ b/files/build_templates/pmon.service.j2 @@ -0,0 +1,14 @@ +[Unit] +Description=Platform monitor container +Requires=updategraph.service +After=updategraph.service +Before=ntp-config.service + +[Service] +User={{ sonicadmin_user }} +ExecStartPre=/usr/bin/{{docker_container_name}}.sh start +ExecStart=/usr/bin/{{docker_container_name}}.sh attach +ExecStop=/usr/bin/{{docker_container_name}}.sh stop + +[Install] +WantedBy=multi-user.target diff --git a/files/build_templates/qos_config.j2 b/files/build_templates/qos_config.j2 new file mode 100644 index 000000000000..a76a64e3fb35 --- /dev/null +++ b/files/build_templates/qos_config.j2 @@ -0,0 +1,216 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0" : "0", + "1" : "0", + "2" : "0", + "3" : "3", + "4" : "4", + "5" : "0", + "6" : "0", + "7" : "0", + "8" : "1", + "9" : "0", + "10": "0", + "11": "0", + "12": "0", + "13": "0", + "14": "0", + "15": "0", + "16": "0", + "17": "0", + "18": "0", + "19": "0", + "20": "0", + "21": "0", + "22": "0", + "23": "0", + "24": "0", + "25": "0", + "26": "0", + "27": "0", + "28": "0", + "29": "0", + "30": "0", + "31": "0", + "32": "0", + "33": "0", + "34": "0", + "35": "0", + "36": "0", + "37": "0", + "38": "0", + "39": "0", + "40": "0", + "41": "0", + "42": "0", + "43": "0", + "44": "0", + "45": "0", + "46": "5", + "47": "0", + "48": "0", + "49": "0", + "50": "0", + "51": "0", + "52": "0", + "53": "0", + "54": "0", + "55": "0", + "56": "0", + "57": "0", + "58": "0", + "59": "0", + "60": "0", + "61": "0", + "62": "0", + "63": "0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "20" + } + }, +{% if asic_type in pfc_to_pg_map_supported_asics %} + "PFC_PRIORITY_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "3": "3", + "4": "4" + } + }, +{% endif %} + "PORT_QOS_MAP": { + "{{ port_names_active }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", +{% if asic_type in pfc_to_pg_map_supported_asics %} + "pfc_to_pg_map" : "[PFC_PRIORITY_TO_PRIORITY_GROUP_MAP|AZURE]", +{% endif %} + "pfc_enable" : "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "1048576", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, + "QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }{% if not loop.last %},{% endif %} + +{% endfor %} + } +} diff --git a/files/build_templates/radv.service.j2 b/files/build_templates/radv.service.j2 new file mode 100644 index 000000000000..065f01906076 --- /dev/null +++ b/files/build_templates/radv.service.j2 @@ -0,0 +1,14 @@ +[Unit] +Description=Router advertiser container +Requires=updategraph.service swss.service +After=updategraph.service swss.service +Before=ntp-config.service + +[Service] +User={{ sonicadmin_user }} +ExecStartPre=/usr/bin/{{ docker_container_name }}.sh start +ExecStart=/usr/bin/{{ docker_container_name }}.sh attach +ExecStop=/usr/bin/{{ docker_container_name }}.sh stop + +[Install] +WantedBy=multi-user.target diff --git a/files/build_templates/snmp.service.j2 b/files/build_templates/snmp.service.j2 new file mode 100644 index 000000000000..f344f2e805ea --- /dev/null +++ b/files/build_templates/snmp.service.j2 @@ -0,0 +1,10 @@ +[Unit] +Description=SNMP container +Requires=updategraph.service swss.service +After=updategraph.service swss.service +Before=ntp-config.service + +[Service] +ExecStartPre=/usr/bin/{{docker_container_name}}.sh start +ExecStart=/usr/bin/{{docker_container_name}}.sh attach +ExecStop=/usr/bin/{{docker_container_name}}.sh stop diff --git a/files/build_templates/snmp.timer b/files/build_templates/snmp.timer new file mode 100644 index 000000000000..464cf01459ba --- /dev/null +++ b/files/build_templates/snmp.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Delays snmp container until SONiC has started + +[Timer] +OnBootSec=3min 30 sec +Unit=snmp.service + +[Install] +WantedBy=timers.target diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 new file mode 100644 index 000000000000..3294068e71a6 --- /dev/null +++ b/files/build_templates/sonic_debian_extension.j2 @@ -0,0 +1,335 @@ +#!/bin/bash +## This script is to automate loading of vendor specific docker images +## and instalation of configuration files and vendor specific packages +## to debian file system. +## +## USAGE: +## ./sonic_debian_extension.sh FILESYSTEM_ROOT PLATFORM_DIR +## PARAMETERS: +## FILESYSTEM_ROOT +## Path to debian file system root directory + +FILESYSTEM_ROOT=$1 +[ -n "$FILESYSTEM_ROOT" ] || { + echo "Error: no or empty FILESYSTEM_ROOT argument" + exit 1 +} + +PLATFORM_DIR=$2 +[ -n "$PLATFORM_DIR" ] || { + echo "Error: no or empty PLATFORM_DIR argument" + exit 1 +} + +## Enable debug output for script +set -x -e + +. functions.sh +BUILD_TEMPLATES=files/build_templates +IMAGE_CONFIGS=files/image_config +SCRIPTS_DIR=files/scripts + +# Define target fold macro +FILESYSTEM_ROOT_USR="$FILESYSTEM_ROOT/usr" +FILESYSTEM_ROOT_USR_SHARE="$FILESYSTEM_ROOT_USR/share" +FILESYSTEM_ROOT_USR_SHARE_SONIC="$FILESYSTEM_ROOT_USR_SHARE/sonic" +FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES="$FILESYSTEM_ROOT_USR_SHARE_SONIC/templates" + +clean_sys() { + sudo umount $FILESYSTEM_ROOT/sys/fs/cgroup/* \ + $FILESYSTEM_ROOT/sys/fs/cgroup \ + $FILESYSTEM_ROOT/sys || true +} +trap_push clean_sys +sudo LANG=C chroot $FILESYSTEM_ROOT mount sysfs /sys -t sysfs + +sudo bash -c "echo \"DOCKER_OPTS=\"--storage-driver=overlay\"\" >> $FILESYSTEM_ROOT/etc/default/docker" +sudo chroot $FILESYSTEM_ROOT service docker start + +# Apply apt configuration files +sudo cp $IMAGE_CONFIGS/apt/sources.list $FILESYSTEM_ROOT/etc/apt/ +sudo cp -R $IMAGE_CONFIGS/apt/sources.list.d/ $FILESYSTEM_ROOT/etc/apt/ +cat $IMAGE_CONFIGS/apt/sonic-dev.gpg.key | sudo LANG=C chroot $FILESYSTEM_ROOT apt-key add - + +# Update apt's snapshot of its repos +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get update + +# Apply environtment configuration files +sudo cp $IMAGE_CONFIGS/environment/environment $FILESYSTEM_ROOT/etc/ +sudo cp $IMAGE_CONFIGS/environment/motd $FILESYSTEM_ROOT/etc/ + +# Create all needed directories +sudo mkdir -p $FILESYSTEM_ROOT/etc/sonic/ +sudo mkdir -p $FILESYSTEM_ROOT/etc/modprobe.d/ +sudo mkdir -p $FILESYSTEM_ROOT/var/cache/sonic/ +sudo mkdir -p $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ + +# Install dependencies for SONiC config engine +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install \ + python-dev \ + python-lxml \ + python-yaml \ + python-bitarray + +# Install SONiC config engine Python package +CONFIG_ENGINE_WHEEL_NAME=$(basename {{config_engine_wheel_path}}) +sudo cp {{config_engine_wheel_path}} $FILESYSTEM_ROOT/$CONFIG_ENGINE_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install $CONFIG_ENGINE_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$CONFIG_ENGINE_WHEEL_NAME + +# Install Python client for Redis +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install "redis==2.10.6" + +# Install redis-dump-load Python 2 package +REDIS_DUMP_LOAD_PY2_WHEEL_NAME=$(basename {{redis_dump_load_py2_wheel_path}}) +sudo cp {{redis_dump_load_py2_wheel_path}} $FILESYSTEM_ROOT/$REDIS_DUMP_LOAD_PY2_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install $REDIS_DUMP_LOAD_PY2_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$REDIS_DUMP_LOAD_PY2_WHEEL_NAME + +# Install SwSS SDK Python 2 package +SWSSSDK_PY2_WHEEL_NAME=$(basename {{swsssdk_py2_wheel_path}}) +sudo cp {{swsssdk_py2_wheel_path}} $FILESYSTEM_ROOT/$SWSSSDK_PY2_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install $SWSSSDK_PY2_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$SWSSSDK_PY2_WHEEL_NAME + +# Install sonic-platform-common Python 2 package +PLATFORM_COMMON_PY2_WHEEL_NAME=$(basename {{platform_common_py2_wheel_path}}) +sudo cp {{platform_common_py2_wheel_path}} $FILESYSTEM_ROOT/$PLATFORM_COMMON_PY2_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install $PLATFORM_COMMON_PY2_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$PLATFORM_COMMON_PY2_WHEEL_NAME + +# Install built Python Click package (and its dependencies via 'apt-get -y install -f') +# Do this before installing sonic-utilities so that it doesn't attempt to install +# an older version as part of its dependencies +sudo dpkg --root=$FILESYSTEM_ROOT -i target/debs/python-click*_all.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f + +# Install python pexpect used by sonic-utilities consutil +# using pip install instead to get a more recent version than is available through debian +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install pexpect + +# Install tabulate >= 0.8.1 via pip in order to support multi-line row output for sonic-utilities +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install tabulate==0.8.2 + +# Install SONiC Utilities (and its dependencies via 'apt-get -y install -f') +sudo dpkg --root=$FILESYSTEM_ROOT -i target/debs/python-sonic-utilities_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f + +# SONiC utilities installs bash-completion as a dependency. However, it is disabled by default +# in bash.bashrc, so we copy a version of the file with it enabled here. +sudo cp -f $IMAGE_CONFIGS/bash/bash.bashrc $FILESYSTEM_ROOT/etc/ + +# Install SONiC Device Data (and its dependencies via 'apt-get -y install -f') +sudo dpkg --root=$FILESYSTEM_ROOT -i target/debs/sonic-device-data_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f + +# Install pam-tacplus and nss-tacplus +sudo dpkg --root=$FILESYSTEM_ROOT -i target/debs/libtac2_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f +sudo dpkg --root=$FILESYSTEM_ROOT -i target/debs/libpam-tacplus_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f +sudo dpkg --root=$FILESYSTEM_ROOT -i target/debs/libnss-tacplus_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f +# Disable tacplus by default +sudo LANG=C chroot $FILESYSTEM_ROOT pam-auth-update --remove tacplus +sudo sed -i -e '/^passwd/s/ tacplus//' $FILESYSTEM_ROOT/etc/nsswitch.conf + +# Copy crontabs +sudo cp -f $IMAGE_CONFIGS/cron.d/* $FILESYSTEM_ROOT/etc/cron.d/ + +# Copy NTP configuration files and templates +sudo cp $IMAGE_CONFIGS/ntp/ntp-config.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable ntp-config.service +sudo cp $IMAGE_CONFIGS/ntp/ntp-config.sh $FILESYSTEM_ROOT/usr/bin/ +sudo cp $IMAGE_CONFIGS/ntp/ntp.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ + +# Copy rsyslog configuration files and templates +sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog-config.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable rsyslog-config.service +sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog-config.sh $FILESYSTEM_ROOT/usr/bin/ +sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ +sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog.d/* $FILESYSTEM_ROOT/etc/rsyslog.d/ + +# Copy logrotate.d configuration files +sudo cp -f $IMAGE_CONFIGS/logrotate/logrotate.d/* $FILESYSTEM_ROOT/etc/logrotate.d/ + +# Copy systemd-journald configuration files +sudo cp -f $IMAGE_CONFIGS/systemd/journald.conf $FILESYSTEM_ROOT/etc/systemd/ + +# Copy interfaces configuration files and templates +sudo cp $IMAGE_CONFIGS/interfaces/interfaces-config.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable interfaces-config.service +sudo cp $IMAGE_CONFIGS/interfaces/interfaces-config.sh $FILESYSTEM_ROOT/usr/bin/ +sudo cp $IMAGE_CONFIGS/interfaces/*.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ + +# Copy initial interfaces configuration file, will be overwritten on first boot +sudo cp $IMAGE_CONFIGS/interfaces/init_interfaces $FILESYSTEM_ROOT/etc/network/interfaces + +# Copy hostcfgd files +sudo cp $IMAGE_CONFIGS/hostcfgd/hostcfgd.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable hostcfgd.service +sudo cp $IMAGE_CONFIGS/hostcfgd/hostcfgd $FILESYSTEM_ROOT/usr/bin/ +sudo cp $IMAGE_CONFIGS/hostcfgd/*.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ + +# Copy the buffer configuration template +sudo cp $BUILD_TEMPLATES/buffers_config.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ + +# Copy the qos configuration template +sudo cp $BUILD_TEMPLATES/qos_config.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ + +# Copy hostname configuration scripts +sudo cp $IMAGE_CONFIGS/hostname/hostname-config.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable hostname-config.service +sudo cp $IMAGE_CONFIGS/hostname/hostname-config.sh $FILESYSTEM_ROOT/usr/bin/ + +# Copy updategraph script and service file +j2 files/build_templates/updategraph.service.j2 | sudo tee $FILESYSTEM_ROOT/etc/systemd/system/updategraph.service +sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable updategraph.service +sudo cp $IMAGE_CONFIGS/updategraph/updategraph $FILESYSTEM_ROOT/usr/bin/ +{% if enable_dhcp_graph_service == "y" %} +sudo bash -c "echo enabled=true > $FILESYSTEM_ROOT/etc/sonic/updategraph.conf" +sudo bash -c "echo src=dhcp >> $FILESYSTEM_ROOT/etc/sonic/updategraph.conf" +sudo bash -c "echo dhcp_as_static=true >> $FILESYSTEM_ROOT/etc/sonic/updategraph.conf" +{% else %} +sudo bash -c "echo enabled=false > $FILESYSTEM_ROOT/etc/sonic/updategraph.conf" +{% endif %} +sudo bash -c "echo '{ \"DEVICE_METADATA\": { \"localhost\": { \"default_bgp_status\": {% if shutdown_bgp_on_start == "y" %}\"down\"{% else %}\"up\"{% endif %}, \"default_pfcwd_status\": {% if enable_pfcwd_on_start == "y" %}\"enable\"{% else %}\"disable\"{% endif %} } }, +{%- print ' \\"CRM\\": { \\"Config\\": { \\"polling_interval\\": \\"300\\", ' %} +{%- for crm_res in ["ipv4_route", "ipv6_route", "ipv4_nexthop", "ipv6_nexthop", "ipv4_neighbor", "ipv6_neighbor", "nexthop_group_member", "nexthop_group", "acl_table", "acl_group", "acl_entry", "acl_counter", "fdb_entry"] -%} +\"{{crm_res}}_threshold_type\": \"percentage\", \"{{crm_res}}_low_threshold\": \"70\", \"{{crm_res}}_high_threshold\": \"85\"{% if not loop.last %}, {% endif %} +{%- endfor %} } } }' >> $FILESYSTEM_ROOT/etc/sonic/init_cfg.json" + +# Copy SNMP configuration files +sudo cp $IMAGE_CONFIGS/snmp/snmp.yml $FILESYSTEM_ROOT/etc/sonic/ + +# Copy ASN configuration files +sudo cp $IMAGE_CONFIGS/asn/deployment_id_asn_map.yml $FILESYSTEM_ROOT/etc/sonic/ + +# Copy sudoers configuration file +sudo cp $IMAGE_CONFIGS/sudoers/sudoers $FILESYSTEM_ROOT/etc/ +sudo cp $IMAGE_CONFIGS/sudoers/sudoers.lecture $FILESYSTEM_ROOT/etc/ + +# Copy control plane ACL management daemon files +sudo cp $IMAGE_CONFIGS/caclmgrd/caclmgrd.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable caclmgrd.service +sudo cp $IMAGE_CONFIGS/caclmgrd/caclmgrd $FILESYSTEM_ROOT/usr/bin/ + +## Install package without starting service +## ref: https://wiki.debian.org/chroot +sudo tee -a $FILESYSTEM_ROOT/usr/sbin/policy-rc.d > /dev/null < /tmp/dhcp_graph_url + else + echo "N/A" > /tmp/dhcp_graph_url + fi + if [ -n "$new_acl_url" ]; then + echo $new_acl_url > /tmp/dhcp_acl_url + fi + ;; +esac diff --git a/files/dhcp/rfc3442-classless-routes b/files/dhcp/rfc3442-classless-routes new file mode 100644 index 000000000000..64e24192816b --- /dev/null +++ b/files/dhcp/rfc3442-classless-routes @@ -0,0 +1,63 @@ +# set classless routes based on the format specified in RFC3442 +# e.g.: +# new_rfc3442_classless_static_routes='24 192 168 10 192 168 1 1 8 10 10 17 66 41' +# specifies the routes: +# 192.168.10.0/24 via 192.168.1.1 +# 10.0.0.0/8 via 10.10.17.66.41 + +RUN="yes" + + +if [ "$RUN" = "yes" ]; then + if [ -n "$new_rfc3442_classless_static_routes" ]; then + if [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then + + set -- $new_rfc3442_classless_static_routes + + while [ $# -gt 0 ]; do + net_length=$1 + via_arg='' + + case $net_length in + 32|31|30|29|28|27|26|25) + net_address="${2}.${3}.${4}.${5}" + gateway="${6}.${7}.${8}.${9}" + shift 9 + ;; + 24|23|22|21|20|19|18|17) + net_address="${2}.${3}.${4}.0" + gateway="${5}.${6}.${7}.${8}" + shift 8 + ;; + 16|15|14|13|12|11|10|9) + net_address="${2}.${3}.0.0" + gateway="${4}.${5}.${6}.${7}" + shift 7 + ;; + 8|7|6|5|4|3|2|1) + net_address="${2}.0.0.0" + gateway="${3}.${4}.${5}.${6}" + shift 6 + ;; + 0) # default route + net_address="0.0.0.0" + gateway="${2}.${3}.${4}.${5}" + shift 5 + ;; + *) # error + return 1 + ;; + esac + + # take care of link-local routes + if [ "${gateway}" != '0.0.0.0' ]; then + via_arg="via ${gateway}" + fi + + # set route (ip detects host routes automatically) + ip -4 route add "${net_address}/${net_length}" \ + ${via_arg} dev "${interface}" table default >/dev/null 2>&1 + done + fi + fi +fi diff --git a/files/dhcp/sethostname b/files/dhcp/sethostname new file mode 100644 index 000000000000..8cef73239455 --- /dev/null +++ b/files/dhcp/sethostname @@ -0,0 +1,12 @@ +case $reason in + BOUND|RENEW|REBIND|REBOOT) + current_host_name=`hostname -s` + if [ "$current_host_name" != "$new_host_name" ] && [ -n "$new_host_name" ] + then + echo $new_host_name > /etc/hostname + hostname -F /etc/hostname + sed -i "/\s$current_host_name$/d" /etc/hosts + echo "127.0.0.1 $new_host_name" >> /etc/hosts + fi + ;; +esac diff --git a/files/dhcp/snmpcommunity b/files/dhcp/snmpcommunity new file mode 100644 index 000000000000..63924e01fc5f --- /dev/null +++ b/files/dhcp/snmpcommunity @@ -0,0 +1,11 @@ +case $reason in + BOUND|RENEW|REBIND|REBOOT) + if [ -n "${new_snmp_community}" ]; then + if [ -f /etc/sonic/snmp.yml ]; then + sed -i "s/^snmp_rocommunity:.*/snmp_rocommunity: $new_snmp_community/g" /etc/sonic/snmp.yml + else + echo "snmp_rocommunity: "$new_snmp_community > /etc/sonic/snmp.yml + fi + fi + ;; +esac diff --git a/files/docker/docker.service.conf b/files/docker/docker.service.conf index 2d6d3cfaa6fb..b124d94f70d1 100644 --- a/files/docker/docker.service.conf +++ b/files/docker/docker.service.conf @@ -1,3 +1,3 @@ [Service] ExecStart= -ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=aufs +ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay --bip=240.127.1.1/24 --iptables=false diff --git a/files/image_config/apt/sonic-dev.gpg.key b/files/image_config/apt/sonic-dev.gpg.key new file mode 100644 index 000000000000..fb9a37901bc7 --- /dev/null +++ b/files/image_config/apt/sonic-dev.gpg.key @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQENBFQ1bTIBCAC7oGfkv/ck0XsLuG8cdcSB2ISqxFAcBvH9BitEtxmpW2uhykKk +xY4rVD/4Uys1s3PF1/64QfPR+hYcewueOwz0ZAcLyFXXk4McICXaPq3NrLiWYKKX +UZLnrPzcrGZoW/kHDDp4OmBiDmT1PGvZlpuimwkMCusUzIr7Cbbp2dIy8MERL5tA +LcgLu3KL6clJ+aTW2jgepI1D7sTepOeGd7eRSb5njKg2M7k/93v/7MipZxiVtyXH +B74YiK6jSbst5JpuYsLa/Dqryvx7Xq3n53oif892pv3euTduo1fYw8Hgh/OOYdeT +c9WCj03KA1jCSFURjdrug0kR8BPlfjqtRLXFABEBAAG0JE1TIE9wZW4gVGVjaCA8 +aW50ZXJvcEBtaWNyb3NvZnQuY29tPokBOAQTAQIAIgUCVDVtMgIbAwYLCQgHAwIG +FQgCCQoLBBYCAwECHgECF4AACgkQsCxG30F6CJO1uAf/cmL68bM8YgF/61hkaY56 +LqrppUTJH/w4fKq47Pf6KfgSLvxfNU6soi2KHYRjIvTRx3tV4vUM5n2plaQg2s8V +/Epg4FeIRTk75YwiHAzLhLnp5cdUaTvC4j4mwxoB6j9Ty+fXJwQ0MvpDhIZb9vM4 +GXw/fEQHCT4f3gx4nReeqE+FB2wVHleX9+Lpodu98JyJTKJRBRHYLqy6S+/lyp2W +aBlsI1LOqBcx1uRK24U7duIpbYwIyrx0cafSruqR2GjVdu+imkhHyUn52VbzYhq1 +af0rqYiZ1VOamVOG0By8+hVyNa1MLc1K2uWGs0o5fDe9F5/swbvLHVXI+M50Vs+m +J7kBDQRUNW0yAQgAu7DkTVj0ZQC4F7bFivAwrdby8gCakTXOl1kcK622hjRJ8nam +aZeW+eADfLRsTmdUmXgZu1YWS5Gn2ZVngC8SGPUBT071+oRETCz4uNB7IimB9QfP +++orI6o2vmnVVsq5wWCbEdNU+TCVv1zjrYev5lwckkKpjHt6o8MNoX2DFuQymSyR +eZKaqhdKmcji4Ke7OIYqwgPjch3wxzE1b5gNOR/iwxWyjjOffZPLr/VhIfIJRs86 +dSXrwjHtEh810SKDLghHM0VAdY34nyC5ZZ61yhts5HtQDFK+9mNpH1mkc4gDBlgG +266pVvknumK6lPNm/osF/cpjWmEw24ypcQIvOQARAQABiQEfBBgBAgAJBQJUNW0y +AhsMAAoJELAsRt9BegiTMBUH/0sZ6gZy7mCTSAYT+NSXLFtGC2zNUVL80SWvfgYm +k9XPVI22MrefZfQ6M01RylyxtWXjRM8UoN8SDKWPpXumzJf831f/7om5zwutaG7b +tjDPYqRKJSbAIFZu2mN+uLrNQ2SV6XK7FoV0dtcrEX9S7RICb6i19D+70+Oh/qgU +R04H1jqS29XBzqAlIzdBoA+sYAwbOIJsSL3YyNQcUv3B5+5yR/bo/L8pnUJt6iuL +nWW+mi7r8gWPHDSrcdYq1TmmlOM7CwZPgWRZzkQPSeZz52Tt7IP47eyGJ09U4PIf +FtMH1ElL2UgHoA/F9Q88e7LkztaTqE59uXWbIYyuSMJVvRU= +=sb3d +-----END PGP PUBLIC KEY BLOCK----- diff --git a/files/image_config/apt/sources.list b/files/image_config/apt/sources.list new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/files/image_config/apt/sources.list.d/debian_archive_trafficmanager_net_debian.list b/files/image_config/apt/sources.list.d/debian_archive_trafficmanager_net_debian.list new file mode 100644 index 000000000000..cda7053c35c1 --- /dev/null +++ b/files/image_config/apt/sources.list.d/debian_archive_trafficmanager_net_debian.list @@ -0,0 +1,3 @@ +deb http://debian-archive.trafficmanager.net/debian/ stretch main contrib non-free +deb http://debian-archive.trafficmanager.net/debian-security/ stretch/updates main contrib non-free +deb http://debian-archive.trafficmanager.net/debian/ stretch-backports main contrib non-free diff --git a/files/image_config/apt/sources.list.d/packages_microsoft_com_repos_sonic_dev.list b/files/image_config/apt/sources.list.d/packages_microsoft_com_repos_sonic_dev.list new file mode 100644 index 000000000000..468dcccc6eec --- /dev/null +++ b/files/image_config/apt/sources.list.d/packages_microsoft_com_repos_sonic_dev.list @@ -0,0 +1 @@ +deb [arch=amd64] http://packages.microsoft.com/repos/sonic-dev/ jessie main diff --git a/files/image_config/asn/deployment_id_asn_map.yml b/files/image_config/asn/deployment_id_asn_map.yml new file mode 100644 index 000000000000..36168f828954 --- /dev/null +++ b/files/image_config/asn/deployment_id_asn_map.yml @@ -0,0 +1,2 @@ +deployment_id_asn_map: + "1" : 65432 diff --git a/files/image_config/bash/bash.bashrc b/files/image_config/bash/bash.bashrc new file mode 100644 index 000000000000..d65beb5b0847 --- /dev/null +++ b/files/image_config/bash/bash.bashrc @@ -0,0 +1,58 @@ +# System-wide .bashrc file for interactive bash(1) shells. + +# To enable the settings / commands in this file for login shells as well, +# this file has to be sourced in /etc/profile. + +# If not running interactively, don't do anything +[ -z "$PS1" ] && return + +# check the window size after each command and, if necessary, +# update the values of LINES and COLUMNS. +shopt -s checkwinsize + +# set variable identifying the chroot you work in (used in the prompt below) +if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then + debian_chroot=$(cat /etc/debian_chroot) +fi + +# set a fancy prompt (non-color, overwrite the one in /etc/profile) +PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' + +# Commented out, don't overwrite xterm -T "title" -n "icontitle" by default. +# If this is an xterm set the title to user@host:dir +#case "$TERM" in +#xterm*|rxvt*) +# PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"' +# ;; +#*) +# ;; +#esac + +# enable bash completion in interactive shells +if ! shopt -oq posix; then + if [ -f /usr/share/bash-completion/bash_completion ]; then + . /usr/share/bash-completion/bash_completion + elif [ -f /etc/bash_completion ]; then + . /etc/bash_completion + fi +fi + +# if the command-not-found package is installed, use it +if [ -x /usr/lib/command-not-found -o -x /usr/share/command-not-found/command-not-found ]; then + function command_not_found_handle { + # check because c-n-f could've been removed in the meantime + if [ -x /usr/lib/command-not-found ]; then + /usr/lib/command-not-found -- "$1" + return $? + elif [ -x /usr/share/command-not-found/command-not-found ]; then + /usr/share/command-not-found/command-not-found -- "$1" + return $? + else + printf "%s: command not found\n" "$1" >&2 + return 127 + fi + } +fi + +# enable auto-logout for console ttyS* sessions +tty | grep ttyS >/dev/null && TMOUT=300 diff --git a/files/image_config/caclmgrd/caclmgrd b/files/image_config/caclmgrd/caclmgrd new file mode 100755 index 000000000000..a7ec952ca21f --- /dev/null +++ b/files/image_config/caclmgrd/caclmgrd @@ -0,0 +1,289 @@ +#!/usr/bin/env python +# +# caclmgrd +# +# Control plane ACL manager daemon for SONiC +# +# Upon starting, this daemon reads control plane ACL tables and rules from +# Config DB, converts the rules into iptables rules and installs the iptables +# rules. The daemon then indefintely listens for notifications from Config DB +# and updates iptables rules if control plane ACL configuration has changed. +# + +try: + import ipaddr as ipaddress + import os + import subprocess + import sys + import syslog + from swsssdk import ConfigDBConnector +except ImportError as err: + raise ImportError("%s - required module not found" % str(err)) + +VERSION = "1.0" + +SYSLOG_IDENTIFIER = "caclmgrd" + + +# ========================== Syslog wrappers ========================== + +def log_info(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + + +def log_warning(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_WARNING, msg) + syslog.closelog() + + +def log_error(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + +# ============================== Classes ============================== + +class ControlPlaneAclManager(object): + """ + Class which reads control plane ACL tables and rules from Config DB, + translates them into equivalent iptables commands and runs those + commands in order to apply the control plane ACLs. + + Attributes: + config_db: Handle to Config Redis database via SwSS SDK + """ + ACL_TABLE = "ACL_TABLE" + ACL_RULE = "ACL_RULE" + + ACL_TABLE_TYPE_CTRLPLANE = "CTRLPLANE" + + # To specify a port range, use iptables format: separate start and end + # ports with a colon, e.g., "1000:2000" + ACL_SERVICES = { + "NTP": {"ip_protocols": ["udp"], "dst_ports": ["123"]}, + "SNMP": {"ip_protocols": ["tcp", "udp"], "dst_ports": ["161"]}, + "SSH": {"ip_protocols": ["tcp"], "dst_ports": ["22"]} + } + + def __init__(self): + # Open a handle to the Config database + self.config_db = ConfigDBConnector() + self.config_db.connect() + + def run_commands(self, commands): + """ + Given a list of shell commands, run them in order + + Args: + commands: List of strings, each string is a shell command + """ + for cmd in commands: + proc = subprocess.Popen(cmd, shell=True) + + (stdout, stderr) = proc.communicate() + + if proc.returncode != 0: + log_error("Error running command '{}'".format(cmd)) + + def parse_int_to_tcp_flags(self, hex_value): + tcp_flags_str = "" + if hex_value & 0x01: + tcp_flags_str += "FIN," + if hex_value & 0x02: + tcp_flags_str += "SYN," + if hex_value & 0x04: + tcp_flags_str += "RST," + if hex_value & 0x08: + tcp_flags_str += "PSH," + if hex_value & 0x10: + tcp_flags_str += "ACK," + if hex_value & 0x20: + tcp_flags_str += "URG," + # iptables doesn't handle the flags below now. It has some special keys for it: + # --ecn-tcp-cwr This matches if the TCP ECN CWR (Congestion Window Received) bit is set. + # --ecn-tcp-ece This matches if the TCP ECN ECE (ECN Echo) bit is set. + # if hex_value & 0x40: + # tcp_flags_str += "ECE," + # if hex_value & 0x80: + # tcp_flags_str += "CWR," + + # Delete the trailing comma + tcp_flags_str = tcp_flags_str[:-1] + return tcp_flags_str + + def get_acl_rules_and_translate_to_iptables_commands(self): + """ + Retrieves current ACL tables and rules from Config DB, translates + control plane ACLs into a list of iptables commands that can be run + in order to install ACL rules. + + Returns: + A list of strings, each string is an iptables shell command + + """ + iptables_cmds = [] + + # First, add iptables commands to set default policies to accept all + # traffic. In case we are connected remotely, the connection will not + # drop when we flush the current rules + iptables_cmds.append("iptables -P INPUT ACCEPT") + iptables_cmds.append("iptables -P FORWARD ACCEPT") + iptables_cmds.append("iptables -P OUTPUT ACCEPT") + + # Add iptables command to flush the current rules + iptables_cmds.append("iptables -F") + + # Add iptables command to delete all non-default chains + iptables_cmds.append("iptables -X") + + # Add same set of commands for ip6tables + iptables_cmds.append("ip6tables -P INPUT ACCEPT") + iptables_cmds.append("ip6tables -P FORWARD ACCEPT") + iptables_cmds.append("ip6tables -P OUTPUT ACCEPT") + iptables_cmds.append("ip6tables -F") + iptables_cmds.append("ip6tables -X") + + # Add iptables commands to allow all IPv4 and IPv6 traffic from localhost + iptables_cmds.append("iptables -A INPUT -s 127.0.0.1 -i lo -j ACCEPT") + iptables_cmds.append("ip6tables -A INPUT -s ::1 -i lo -j ACCEPT") + + # Get current ACL tables and rules from Config DB + self._tables_db_info = self.config_db.get_table(self.ACL_TABLE) + self._rules_db_info = self.config_db.get_table(self.ACL_RULE) + + # Walk the ACL tables + for (table_name, table_data) in self._tables_db_info.iteritems(): + + table_ip_version = None + + # Ignore non-control-plane ACL tables + if table_data["type"] != self.ACL_TABLE_TYPE_CTRLPLANE: + continue + + acl_services = table_data["services"] + + for acl_service in acl_services: + if acl_service not in self.ACL_SERVICES: + log_warning("Ignoring control plane ACL '{}' with unrecognized service '{}'" + .format(table_name, acl_service)) + continue + + log_info("Translating ACL rules for control plane ACL '{}' (service: '{}')" + .format(table_name, acl_service)) + + # Obtain default IP protocol(s) and destination port(s) for this service + ip_protocols = self.ACL_SERVICES[acl_service]["ip_protocols"] + dst_ports = self.ACL_SERVICES[acl_service]["dst_ports"] + + acl_rules = {} + + for ((rule_table_name, rule_id), rule_props) in self._rules_db_info.iteritems(): + if rule_table_name == table_name: + acl_rules[rule_props["PRIORITY"]] = rule_props + + # If we haven't determined the IP version for this ACL table yet, + # try to do it now. We determine heuristically based on whether the + # src IP is an IPv4 or IPv6 address. + if not table_ip_version and "SRC_IP" in rule_props and rule_props["SRC_IP"]: + ip_addr = ipaddress.IPAddress(rule_props["SRC_IP"].split("/")[0]) + if isinstance(ip_addr, ipaddress.IPv6Address): + table_ip_version = 6 + elif isinstance(ip_addr, ipaddress.IPv4Address): + table_ip_version = 4 + + # If we were unable to determine whether this ACL table contains + # IPv4 or IPv6 rules, log a message and skip processing this table. + if not table_ip_version: + log_warning("Unable to determine if ACL table '{}' contains IPv4 or IPv6 rules. Skipping table..." + .format(table_name)) + continue + + # For each ACL rule in this table (in descending order of priority) + for priority in sorted(acl_rules.iterkeys(), reverse=True): + rule_props = acl_rules[priority] + + if "PACKET_ACTION" not in rule_props: + log_error("ACL rule does not contain PACKET_ACTION property") + continue + + # Apply the rule to the default protocol(s) for this ACL service + for ip_protocol in ip_protocols: + for dst_port in dst_ports: + rule_cmd = "ip6tables" if table_ip_version == 6 else "iptables" + rule_cmd += " -A INPUT -p {}".format(ip_protocol) + + if "SRC_IP" in rule_props and rule_props["SRC_IP"]: + rule_cmd += " -s {}".format(rule_props["SRC_IP"]) + + rule_cmd += " --dport {}".format(dst_port) + + # If there are TCP flags present and ip protocol is TCP, append them + if ip_protocol == "tcp" and "TCP_FLAGS" in rule_props and rule_props["TCP_FLAGS"]: + tcp_flags, tcp_flags_mask = rule_props["TCP_FLAGS"].split("/") + + tcp_flags = int(tcp_flags, 16) + tcp_flags_mask = int(tcp_flags_mask, 16) + + if tcp_flags_mask > 0: + rule_cmd += " --tcp-flags {mask} {flags}".format(mask = self.parse_int_to_tcp_flags(tcp_flags_mask), flags = self.parse_int_to_tcp_flags(tcp_flags)) + + # Append the packet action as the jump target + rule_cmd += " -j {}".format(rule_props["PACKET_ACTION"]) + + iptables_cmds.append(rule_cmd) + + return iptables_cmds + + def update_control_plane_acls(self): + """ + Convenience wrapper which retrieves current ACL tables and rules from + Config DB, translates control plane ACLs into a list of iptables + commands and runs them. + """ + iptables_cmds = self.get_acl_rules_and_translate_to_iptables_commands() + + log_info("Issuing the following iptables commands:") + for cmd in iptables_cmds: + log_info(" " + cmd) + + self.run_commands(iptables_cmds) + + def notification_handler(self, key, data): + log_info("ACL configuration changed. Updating iptables rules for control plane ACLs...") + self.update_control_plane_acls() + + def run(self): + # Unconditionally update control plane ACLs once at start + self.update_control_plane_acls() + + # Subscribe to notifications when ACL tables or rules change + self.config_db.subscribe(self.ACL_TABLE, + lambda table, key, data: self.notification_handler(key, data)) + self.config_db.subscribe(self.ACL_RULE, + lambda table, key, data: self.notification_handler(key, data)) + + # Indefinitely listen for Config DB notifications + self.config_db.listen() + + +# ============================= Functions ============================= + +def main(): + log_info("Starting up...") + + if not os.geteuid() == 0: + log_error("Must be root to run this daemon") + print "Error: Must be root to run this daemon" + sys.exit(1) + + # Instantiate a ControlPlaneAclManager object + caclmgr = ControlPlaneAclManager() + caclmgr.run() + + +if __name__ == "__main__": + main() diff --git a/files/image_config/caclmgrd/caclmgrd.service b/files/image_config/caclmgrd/caclmgrd.service new file mode 100644 index 000000000000..f385384375c0 --- /dev/null +++ b/files/image_config/caclmgrd/caclmgrd.service @@ -0,0 +1,11 @@ +[Unit] +Description=Control Plane ACL configuration daemon +Requires=updategraph.service +After=updategraph.service + +[Service] +Type=simple +ExecStart=/usr/bin/caclmgrd + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/cron.d/logrotate b/files/image_config/cron.d/logrotate new file mode 100644 index 000000000000..d0c2e0829ba9 --- /dev/null +++ b/files/image_config/cron.d/logrotate @@ -0,0 +1,2 @@ +# Attempt to rotate system logs once per minute +* * * * * root /usr/sbin/logrotate /etc/logrotate.conf > /dev/null 2>&1 diff --git a/files/image_config/environment/environment b/files/image_config/environment/environment new file mode 100644 index 000000000000..6c85276371bf --- /dev/null +++ b/files/image_config/environment/environment @@ -0,0 +1 @@ +VTYSH_PAGER=more diff --git a/files/image_config/environment/motd b/files/image_config/environment/motd new file mode 100644 index 000000000000..8562e330fe2c --- /dev/null +++ b/files/image_config/environment/motd @@ -0,0 +1,14 @@ +You are on + ____ ___ _ _ _ ____ + / ___| / _ \| \ | (_)/ ___| + \___ \| | | | \| | | | + ___) | |_| | |\ | | |___ + |____/ \___/|_| \_|_|\____| + +-- Software for Open Networking in the Cloud -- + +Unauthorized access and/or use are prohibited. +All access and/or use are subject to monitoring. + +Help: http://azure.github.io/SONiC/ + diff --git a/files/image_config/hostcfgd/common-auth-sonic.j2 b/files/image_config/hostcfgd/common-auth-sonic.j2 new file mode 100644 index 000000000000..288d19f714df --- /dev/null +++ b/files/image_config/hostcfgd/common-auth-sonic.j2 @@ -0,0 +1,43 @@ +#THIS IS AN AUTO-GENERATED FILE +# +# /etc/pam.d/common-auth- authentication settings common to all services +# This file is included from other service-specific PAM config files, +# and should contain a list of the authentication modules that define +# the central authentication scheme for use on the system +# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the +# traditional Unix authentication mechanisms. +# +# here are the per-package modules (the "Primary" block) + +{% if auth['login'] == 'local' %} +auth [success=1 default=ignore] pam_unix.so nullok try_first_pass + +{% elif auth['login'] == 'local,tacacs+' %} +auth [success=done new_authtok_reqd=done default=ignore{{ ' auth_err=die' if not auth['failthrough'] }}] pam_unix.so nullok try_first_pass +{% for server in servers | sub(0, -1) %} +auth [success=done new_authtok_reqd=done default=ignore{{ ' auth_err=die' if not auth['failthrough'] }}] pam_tacplus.so server={{ server.ip }}:{{ server.tcp_port }} secret={{ server.passkey }} login={{ server.auth_type }} timeout={{ server.timeout }} {% if server.vrf %} vrf={{ server.vrf }} {% endif %} try_first_pass +{% endfor %} +{% if servers | count %} +{% set last_server = servers | last %} +auth [success=1 default=ignore] pam_tacplus.so server={{ last_server.ip }}:{{ last_server.tcp_port }} secret={{ last_server.passkey }} login={{ last_server.auth_type }} timeout={{ last_server.timeout }} {% if server.vrf %} vrf={{ last_server.vrf }} {% endif %} try_first_pass + +{% endif %} +{% elif auth['login'] == 'tacacs+' or auth['login'] == 'tacacs+,local' %} +{% for server in servers %} +auth [success=done new_authtok_reqd=done default=ignore{{ ' auth_err=die' if not auth['failthrough'] }}] pam_tacplus.so server={{ server.ip }}:{{ server.tcp_port }} secret={{ server.passkey }} login={{ server.auth_type }} timeout={{ server.timeout }} {%if server.vrf %} vrf={{ server.vrf }} {% endif %} try_first_pass +{% endfor %} +auth [success=1 default=ignore] pam_unix.so nullok try_first_pass + +{% else %} +auth [success=1 default=ignore] pam_unix.so nullok try_first_pass + +{% endif %} +# +# here's the fallback if no module succeeds +auth requisite pam_deny.so +# prime the stack with a positive return value if there isn't one already; +# this avoids us returning an error just because nothing sets a success code +# since the modules above will each just jump around +auth required pam_permit.so +# and here are more per-package modules (the "Additional" block) + diff --git a/files/image_config/hostcfgd/hostcfgd b/files/image_config/hostcfgd/hostcfgd new file mode 100755 index 000000000000..f156f7e9402c --- /dev/null +++ b/files/image_config/hostcfgd/hostcfgd @@ -0,0 +1,185 @@ +#!/usr/bin/python -u +# -*- coding: utf-8 -*- + +import os +import sys +import subprocess +import syslog +import copy +import jinja2 +from swsssdk import ConfigDBConnector + +# FILE +PAM_AUTH_CONF = "/etc/pam.d/common-auth-sonic" +PAM_AUTH_CONF_TEMPLATE = "/usr/share/sonic/templates/common-auth-sonic.j2" +NSS_TACPLUS_CONF = "/etc/tacplus_nss.conf" +NSS_TACPLUS_CONF_TEMPLATE = "/usr/share/sonic/templates/tacplus_nss.conf.j2" +NSS_CONF = "/etc/nsswitch.conf" + +# TACACS+ +TACPLUS_SERVER_PASSKEY_DEFAULT = "" +TACPLUS_SERVER_TIMEOUT_DEFAULT = "5" +TACPLUS_SERVER_AUTH_TYPE_DEFAULT = "pap" + + +def is_true(val): + if val == 'True' or val == 'true': + return True + else: + return False + + +def sub(l, start, end): + return l[start:end] + + +def obfuscate(data): + if data: + return data[0] + '*****' + else: + return data + + +class AaaCfg(object): + def __init__(self): + self.auth_default = { + 'login': 'local', + 'failthrough': True, + 'fallback': True + } + self.tacplus_global_default = { + 'auth_type': TACPLUS_SERVER_AUTH_TYPE_DEFAULT, + 'timeout': TACPLUS_SERVER_TIMEOUT_DEFAULT, + 'passkey': TACPLUS_SERVER_PASSKEY_DEFAULT + } + self.auth = {} + self.tacplus_global = {} + self.tacplus_servers = {} + self.debug = False + + # Load conf from ConfigDb + def load(self, aaa_conf, tac_global_conf, tacplus_conf): + for row in aaa_conf: + self.aaa_update(row, aaa_conf[row], modify_conf=False) + for row in tac_global_conf: + self.tacacs_global_update(row, tac_global_conf[row], modify_conf=False) + for row in tacplus_conf: + self.tacacs_server_update(row, tacplus_conf[row], modify_conf=False) + self.modify_conf_file() + + def aaa_update(self, key, data, modify_conf=True): + if key == 'authentication': + self.auth = data + if 'failthrough' in data: + self.auth['failthrough'] = is_true(data['failthrough']) + if 'debug' in data: + self.debug = is_true(data['debug']) + if modify_conf: + self.modify_conf_file() + + def tacacs_global_update(self, key, data, modify_conf=True): + if key == 'global': + self.tacplus_global = data + if modify_conf: + self.modify_conf_file() + + def tacacs_server_update(self, key, data, modify_conf=True): + if data == {}: + if key in self.tacplus_servers: + del self.tacplus_servers[key] + else: + self.tacplus_servers[key] = data + + if modify_conf: + self.modify_conf_file() + + def modify_conf_file(self): + auth = self.auth_default.copy() + auth.update(self.auth) + tacplus_global = self.tacplus_global_default.copy() + tacplus_global.update(self.tacplus_global) + + servers_conf = [] + if self.tacplus_servers: + for addr in self.tacplus_servers: + server = tacplus_global.copy() + server['ip'] = addr + server.update(self.tacplus_servers[addr]) + servers_conf.append(server) + sorted(servers_conf, key=lambda t: t['priority'], reverse=True) + + template_file = os.path.abspath(PAM_AUTH_CONF_TEMPLATE) + env = jinja2.Environment(loader=jinja2.FileSystemLoader('/'), trim_blocks=True) + env.filters['sub'] = sub + template = env.get_template(template_file) + pam_conf = template.render(auth=auth, servers=servers_conf) + with open(PAM_AUTH_CONF, 'w') as f: + f.write(pam_conf) + + # Modify common-auth include file in /etc/pam.d/login and sshd + if os.path.isfile(PAM_AUTH_CONF): + os.system("sed -i -e '/^@include/s/common-auth$/common-auth-sonic/' /etc/pam.d/sshd") + os.system("sed -i -e '/^@include/s/common-auth$/common-auth-sonic/' /etc/pam.d/login") + else: + os.system("sed -i -e '/^@include/s/common-auth-sonic$/common-auth/' /etc/pam.d/sshd") + os.system("sed -i -e '/^@include/s/common-auth-sonic$/common-auth/' /etc/pam.d/login") + + # Add tacplus in nsswitch.conf if TACACS+ enable + if 'tacacs+' in auth['login']: + if os.path.isfile(NSS_CONF): + os.system("sed -i -e '/tacplus/b' -e '/^passwd/s/compat/tacplus &/' /etc/nsswitch.conf") + else: + if os.path.isfile(NSS_CONF): + os.system("sed -i -e '/^passwd/s/tacplus //' /etc/nsswitch.conf") + + # Set tacacs+ server in nss-tacplus conf + template_file = os.path.abspath(NSS_TACPLUS_CONF_TEMPLATE) + template = env.get_template(template_file) + nss_tacplus_conf = template.render(debug=self.debug, servers=servers_conf) + with open(NSS_TACPLUS_CONF, 'w') as f: + f.write(nss_tacplus_conf) + + +class HostConfigDaemon: + def __init__(self): + self.config_db = ConfigDBConnector() + self.config_db.connect(wait_for_init=True, retry_on=True) + syslog.syslog(syslog.LOG_INFO, 'ConfigDB connect success') + aaa = self.config_db.get_table('AAA') + tacacs_global = self.config_db.get_table('TACPLUS') + tacacs_server = self.config_db.get_table('TACPLUS_SERVER') + self.aaacfg = AaaCfg() + self.aaacfg.load(aaa, tacacs_global, tacacs_server) + + def aaa_handler(self, key, data): + self.aaacfg.aaa_update(key, data) + + def tacacs_server_handler(self, key, data): + self.aaacfg.tacacs_server_update(key, data) + log_data = copy.deepcopy(data) + if log_data.has_key('passkey'): + log_data['passkey'] = obfuscate(log_data['passkey']) + syslog.syslog(syslog.LOG_DEBUG, 'value of {} changed to {}'.format(key, log_data)) + + def tacacs_global_handler(self, key, data): + self.aaacfg.tacacs_global_update(key, data) + log_data = copy.deepcopy(data) + if log_data.has_key('passkey'): + log_data['passkey'] = obfuscate(log_data['passkey']) + syslog.syslog(syslog.LOG_DEBUG, 'value of {} changed to {}'.format(key, log_data)) + + def start(self): + self.config_db.subscribe('AAA', lambda table, key, data: self.aaa_handler(key, data)) + self.config_db.subscribe('TACPLUS_SERVER', lambda table, key, data: self.tacacs_server_handler(key, data)) + self.config_db.subscribe('TACPLUS', lambda table, key, data: self.tacacs_global_handler(key, data)) + self.config_db.listen() + + +def main(): + daemon = HostConfigDaemon() + daemon.start() + + +if __name__ == "__main__": + main() + diff --git a/files/image_config/hostcfgd/hostcfgd.service b/files/image_config/hostcfgd/hostcfgd.service new file mode 100644 index 000000000000..762786ad830e --- /dev/null +++ b/files/image_config/hostcfgd/hostcfgd.service @@ -0,0 +1,11 @@ +[Unit] +Description=Host config enforcer daemon +Requires=updategraph.service +After=updategraph.service + +[Service] +Type=simple +ExecStart=/usr/bin/hostcfgd + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/hostcfgd/tacplus_nss.conf.j2 b/files/image_config/hostcfgd/tacplus_nss.conf.j2 new file mode 100644 index 000000000000..347a9ec3d8c2 --- /dev/null +++ b/files/image_config/hostcfgd/tacplus_nss.conf.j2 @@ -0,0 +1,25 @@ +onfiguration for libnss-tacplus + +# debug - If you want to open debug log, set it on +# Default: off +# debug=on +{% if debug %} +debug=on +{% endif %} + +# server - set ip address, tcp port, secret string and timeout for TACACS+ servers +# Default: None (no TACACS+ server) +# server=1.1.1.1:49,secret=test,timeout=3 +{% for server in servers %} +server={{ server.ip }}:{{ server.tcp_port }},secret={{ server.passkey }},timeout={{ server.timeout }}{% if server.vrf %},vrf={{ server.vrf }}{% endif %}{{''}} +{% endfor %} + +# user_priv - set the map between TACACS+ user privilege and local user's passwd +# Default: +# user_priv=15;pw_info=remote_user_su;gid=1000;group=sudo,docker;shell=/bin/bash +# user_priv=1;pw_info=remote_user;gid=999;group=docker;shell=/bin/bash + +# many_to_one - create one local user for many TACACS+ users which has the same privilege +# Default: many_to_one=n +# many_to_one=y + diff --git a/files/image_config/hostname/hostname-config.service b/files/image_config/hostname/hostname-config.service new file mode 100644 index 000000000000..c23ae10227a4 --- /dev/null +++ b/files/image_config/hostname/hostname-config.service @@ -0,0 +1,11 @@ +[Unit] +Description=Update hostname based on configdb +Requires=updategraph.service +After=updategraph.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/hostname-config.sh + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/hostname/hostname-config.sh b/files/image_config/hostname/hostname-config.sh new file mode 100755 index 000000000000..eec7c2f732dc --- /dev/null +++ b/files/image_config/hostname/hostname-config.sh @@ -0,0 +1,11 @@ +#!/bin/bash -e + +CURRENT_HOSTNAME=`hostname` +HOSTNAME=`sonic-cfggen -d -v DEVICE_METADATA[\'localhost\'][\'hostname\']` + +echo $HOSTNAME > /etc/hostname +hostname -F /etc/hostname + +sed -i "/\s$CURRENT_HOSTNAME$/d" /etc/hosts +echo "127.0.0.1 $HOSTNAME" >> /etc/hosts + diff --git a/files/image_config/interfaces/init_interfaces b/files/image_config/interfaces/init_interfaces new file mode 100644 index 000000000000..9d251045b5eb --- /dev/null +++ b/files/image_config/interfaces/init_interfaces @@ -0,0 +1,8 @@ +# Initial /etc/network/interface file for first boot +# Will be overwritten based on minigraph information by interfaces-config service + +# The loopback network interface +auto lo +iface lo inet loopback +# +# Disable the management network interface during boot up diff --git a/files/image_config/interfaces/interfaces-config.service b/files/image_config/interfaces/interfaces-config.service new file mode 100644 index 000000000000..71178affdee8 --- /dev/null +++ b/files/image_config/interfaces/interfaces-config.service @@ -0,0 +1,11 @@ +[Unit] +Description=Update interfaces configuration +Requires=updategraph.service +After=updategraph.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/interfaces-config.sh + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/interfaces/interfaces-config.sh b/files/image_config/interfaces/interfaces-config.sh new file mode 100755 index 000000000000..29664bcda564 --- /dev/null +++ b/files/image_config/interfaces/interfaces-config.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +ifdown --force eth0 + +sonic-cfggen -d -t /usr/share/sonic/templates/interfaces.j2 > /etc/network/interfaces + +# Add usb0 interface for bfn platforms +platform=$(sonic-cfggen -H -v 'DEVICE_METADATA["localhost"]["platform"]') +if [[ "$platform" == "x86_64-accton_wedge100bf_32x-r0" || "$platform" == "x86_64-accton_wedge100bf_65x-r0" ]]; then +cat <<'EOF' >> /etc/network/interfaces +# BMC interface +auto usb0 +allow-hotplug usb0 +iface usb0 inet6 auto +up ifconfig usb0 txqueuelen 64 +EOF +fi + +[ -f /var/run/dhclient.eth0.pid ] && kill `cat /var/run/dhclient.eth0.pid` && rm -f /var/run/dhclient.eth0.pid + +systemctl restart networking + +ifdown lo && ifup lo diff --git a/files/image_config/interfaces/interfaces.j2 b/files/image_config/interfaces/interfaces.j2 new file mode 100644 index 000000000000..e2ee58e9c320 --- /dev/null +++ b/files/image_config/interfaces/interfaces.j2 @@ -0,0 +1,50 @@ +# +{% block banner %} +# =============== Managed by SONiC Config Engine DO NOT EDIT! =============== +# generated from /usr/share/sonic/templates/interfaces.j2 using sonic-cfggen +# file: /etc/network/interfaces +# +{% endblock banner %} +{% block loopback %} +# The loopback network interface +auto lo +iface lo inet loopback +# Use command 'ip addr list dev lo' to check all addresses +{% for (name, prefix) in LOOPBACK_INTERFACE %} +iface lo {{ 'inet' if prefix | ipv4 else 'inet6' }} static + address {{ prefix | ip }} + netmask {{ prefix | netmask if prefix | ipv4 else prefix | prefixlen }} +# +{% endfor %} +{% endblock loopback %} +{% block mgmt_interface %} + +# The management network interface +auto eth0 +{% if MGMT_INTERFACE %} +{% for (name, prefix) in MGMT_INTERFACE %} +iface eth0 {{ 'inet' if prefix | ipv4 else 'inet6' }} static + address {{ prefix | ip }} + netmask {{ prefix | netmask if prefix | ipv4 else prefix | prefixlen }} + ########## management network policy routing rules + # management port up rules + up ip {{ '-4' if prefix | ipv4 else '-6' }} route add default via {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} dev eth0 table default + up ip {{ '-4' if prefix | ipv4 else '-6' }} route add {{ prefix | network }}/{{ prefix | prefixlen }} dev eth0 table default + up ip {{ '-4' if prefix | ipv4 else '-6' }} rule add from {{ prefix | ip }}/{{ '32' if prefix | ipv4 else '128' }} table default +{% for route in MGMT_INTERFACE[(name, prefix)]['forced_mgmt_routes'] %} + up ip rule add to {{ route }} table default +{% endfor %} + # management port down rules + down ip {{ '-4' if prefix | ipv4 else '-6' }} route delete default via {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} dev eth0 table default + down ip {{ '-4' if prefix | ipv4 else '-6' }} route delete {{ prefix | network }}/{{ prefix | prefixlen }} dev eth0 table default + down ip {{ '-4' if prefix | ipv4 else '-6' }} rule delete from {{ prefix | ip }}/{{ '32' if prefix | ipv4 else '128' }} table default +{% for route in MGMT_INTERFACE[(name, prefix)]['forced_mgmt_routes'] %} + down ip rule delete to {{ route }} table default +{% endfor %} +{# TODO: COPP policy type rules #} +{% endfor %} +{% else %} +iface eth0 inet dhcp +{% endif %} +# +{% endblock mgmt_interface %} diff --git a/files/image_config/logrotate/logrotate.conf b/files/image_config/logrotate/logrotate.conf new file mode 100644 index 000000000000..6f107e209837 --- /dev/null +++ b/files/image_config/logrotate/logrotate.conf @@ -0,0 +1,32 @@ +# see "man logrotate" for details +# Rotate log files daily by default +daily + +# Keep 4 days worth of backlogs by default +rotate 4 + +# create new (empty) log files after rotating old ones +create + +# uncomment this if you want your log files compressed +#compress + +# packages drop log rotation information into this directory +include /etc/logrotate.d + +# no packages own wtmp, or btmp -- we'll rotate them here +/var/log/wtmp { + missingok + size 100k + create 0664 root utmp + rotate 1 +} + +/var/log/btmp { + missingok + size 100k + create 0660 root utmp + rotate 1 +} + +# system-specific logs may be configured here diff --git a/files/image_config/logrotate/logrotate.d/apt b/files/image_config/logrotate/logrotate.d/apt new file mode 100644 index 000000000000..7584dcacc881 --- /dev/null +++ b/files/image_config/logrotate/logrotate.d/apt @@ -0,0 +1,15 @@ +/var/log/apt/term.log { + size 100k + rotate 1 + compress + missingok + notifempty +} + +/var/log/apt/history.log { + size 100k + rotate 1 + compress + missingok + notifempty +} diff --git a/files/image_config/logrotate/logrotate.d/dpkg b/files/image_config/logrotate/logrotate.d/dpkg new file mode 100644 index 000000000000..5e24c7ed74e1 --- /dev/null +++ b/files/image_config/logrotate/logrotate.d/dpkg @@ -0,0 +1,18 @@ +/var/log/dpkg.log { + size 100k + rotate 1 + compress + delaycompress + missingok + notifempty + create 644 root root +} +/var/log/alternatives.log { + size 100k + rotate 1 + compress + delaycompress + missingok + notifempty + create 644 root root +} diff --git a/files/image_config/logrotate/logrotate.d/monit b/files/image_config/logrotate/logrotate.d/monit new file mode 100644 index 000000000000..7846dfadb77c --- /dev/null +++ b/files/image_config/logrotate/logrotate.d/monit @@ -0,0 +1,12 @@ +/var/log/monit.log { + size 100k + rotate 1 + missingok + create 640 root adm + notifempty + compress + delaycompress + postrotate + invoke-rc.d monit reload > /dev/null + endscript +} diff --git a/files/image_config/logrotate/logrotate.d/rsyslog b/files/image_config/logrotate/logrotate.d/rsyslog new file mode 100644 index 000000000000..6788762d7687 --- /dev/null +++ b/files/image_config/logrotate/logrotate.d/rsyslog @@ -0,0 +1,97 @@ +# These logs should no longer get created. However, in case they do get created, +# we should keep them to a small size and rotate them also. +/var/log/mail.info +/var/log/mail.warn +/var/log/mail.err +/var/log/mail.log +/var/log/daemon.log +/var/log/kern.log +/var/log/user.log +/var/log/lpr.log +/var/log/debug +/var/log/messages +{ + size 10k + rotate 1 + missingok + notifempty + compress + delaycompress + sharedscripts + postrotate + # calling kill directly instead of 'service rsyslog rotate >/dev/null' due + # to bug in init-system-helpers. bug has apparently been fixed in v1.47. + # however, debian jessie is still using v1.22. + # see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=672218 + kill -hup $(cat /var/run/rsyslogd.pid) + endscript +} + +/var/log/auth.log +/var/log/cron.log +/var/log/syslog +/var/log/teamd.log +/var/log/telemetry.log +/var/log/quagga/bgpd.log +/var/log/quagga/zebra.log +/var/log/swss/sairedis.rec +/var/log/swss/swss.rec +{ + size 1M + rotate 5000 + missingok + notifempty + compress + delaycompress + nosharedscripts + prerotate + # Adjust NUM_LOGS_TO_ROTATE to reflect number of log files that trigger this block specified above + NUM_LOGS_TO_ROTATE=8 + + # Adjust LOG_FILE_ROTATE_SIZE_KB to reflect the "size" parameter specified above, in kB + LOG_FILE_ROTATE_SIZE_KB=1024 + + # Reserve space for btmp, wtmp, dpkg.log, monit.log, etc., as well as logs that + # should be disabled, just in case they get created and rotated + RESERVED_SPACE_KB=4096 + + VAR_LOG_SIZE_KB=$(df -k /var/log | sed -n 2p | awk '{ print $2 }') + + # Limit usable space to 90% of the partition minus the reserved space for other logs + USABLE_SPACE_KB=$(( (VAR_LOG_SIZE_KB * 90 / 100) - RESERVED_SPACE_KB)) + + # Set our threshold so as to maintain enough space to write all logs from empty to full + # Most likely, some logs will have non-zero size when this is called, so this errs on the side + # of caution, giving us a bit of a cushion if a log grows quickly and passes its rotation size + THRESHOLD_KB=$((USABLE_SPACE_KB - (NUM_LOGS_TO_ROTATE * LOG_FILE_ROTATE_SIZE_KB * 2))) + + while true; do + USED_KB=$(du -s /var/log | awk '{ print $1; }') + + if [ $USED_KB -lt $THRESHOLD_KB ]; then + break + else + OLDEST_ARCHIVE_FILE=$(find /var/log -type f -printf '%T+ %p\n' | grep -E '.+\.[0-9]+(\.gz)?$' | sort | head -n 1 | awk '{ print $2; }') + + if [ -z "$OLDEST_ARCHIVE_FILE" ]; then + logger -p syslog.err -t "logrotate" "No archive file to delete -- potential for filling up /var/log partition!" + break + fi + + logger -p syslog.info -t "logrotate" "Deleting archive file $OLDEST_ARCHIVE_FILE to free up space" + rm -rf "$OLDEST_ARCHIVE_FILE" + fi + done + endscript + postrotate + if [ $(echo $1 | grep -c "/var/log/swss/") -gt 0 ]; then + pgrep -x orchagent | xargs /bin/kill -HUP 2>/dev/null || true + else + # Calling kill directly instead of 'service rsyslog rotate >/dev/null' due + # to bug in init-system-helpers. Bug has apparently been fixed in v1.47. + # However, Debian Jessie is still using v1.22. + # See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=672218 + kill -HUP $(cat /var/run/rsyslogd.pid) + fi + endscript +} diff --git a/files/image_config/ntp/ntp-config.service b/files/image_config/ntp/ntp-config.service new file mode 100644 index 000000000000..c86710e3d209 --- /dev/null +++ b/files/image_config/ntp/ntp-config.service @@ -0,0 +1,11 @@ +[Unit] +Description=Update NTP configuration +Requires=updategraph.service +After=updategraph.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/ntp-config.sh + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/ntp/ntp-config.sh b/files/image_config/ntp/ntp-config.sh new file mode 100755 index 000000000000..601b7bd421f0 --- /dev/null +++ b/files/image_config/ntp/ntp-config.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +sonic-cfggen -d -t /usr/share/sonic/templates/ntp.conf.j2 >/etc/ntp.conf + +systemctl restart ntp diff --git a/files/image_config/ntp/ntp.conf.j2 b/files/image_config/ntp/ntp.conf.j2 new file mode 100644 index 000000000000..d7df6bcd2e04 --- /dev/null +++ b/files/image_config/ntp/ntp.conf.j2 @@ -0,0 +1,69 @@ +############################################################################### +# Managed by Ansible +# file: ansible/roles/acs/templates/ntp.conf.j2 +############################################################################### + +# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help + +driftfile /var/lib/ntp/ntp.drift + + +# Enable this if you want statistics to be logged. +#statsdir /var/log/ntpstats/ + +statistics loopstats peerstats clockstats +filegen loopstats file loopstats type day enable +filegen peerstats file peerstats type day enable +filegen clockstats file clockstats type day enable + + +# You do need to talk to an NTP server or two (or three). +#server ntp.your-provider.example + +# pool.ntp.org maps to about 1000 low-stratum NTP servers. Your server will +# pick a different set every time it starts up. Please consider joining the +# pool: +{% for ntp_server in NTP_SERVER %} +server {{ ntp_server }} iburst +{% endfor %} + +#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 +# details. The web page +# might also be helpful. +# +# Note that "restrict" applies to both servers and clients, so a configuration +# that might be intended to block requests from certain clients could also end +# up blocking replies from your own upstream servers. + +# By default, exchange time with everybody, but don't allow configuration. +restrict -4 default kod notrap nomodify nopeer noquery +restrict -6 default kod notrap nomodify nopeer noquery + +# Local users may interrogate the ntp server more closely. +restrict 127.0.0.1 +restrict ::1 + +# Clients from this (example!) subnet have unlimited access, but only if +# cryptographically authenticated. +#restrict 192.168.123.0 mask 255.255.255.0 notrust + + +# If you want to provide time to your local subnet, change the next line. +# (Again, the address is an example only.) +#broadcast 192.168.123.255 + +# If you want to listen to time broadcasts on your local subnet, de-comment the +# next lines. Please do this only if you trust everybody on the network! +#disable auth +#broadcastclient diff --git a/files/image_config/platform/linux_kernel_bde.conf b/files/image_config/platform/linux_kernel_bde.conf new file mode 100644 index 000000000000..5f2b1c4e644d --- /dev/null +++ b/files/image_config/platform/linux_kernel_bde.conf @@ -0,0 +1 @@ +blacklist linux_kernel_bde diff --git a/files/image_config/platform/rc.local b/files/image_config/platform/rc.local new file mode 100755 index 000000000000..acac42e326e1 --- /dev/null +++ b/files/image_config/platform/rc.local @@ -0,0 +1,350 @@ +#!/bin/sh -x +# +# rc.local +# +# This script is executed at the end of each multiuser runlevel. +# Make sure that the script will "exit 0" on success or any other +# value on error. +# +# In order to enable or disable this script just change the execution +# bits. +# +# By default this script does nothing. + +SONIC_VERSION=$(sonic-cfggen -y /etc/sonic/sonic_version.yml -v build_version) +FIRST_BOOT_FILE="/host/image-${SONIC_VERSION}/platform/firsttime" + +# In case the unit is migrating from another NOS, save the logs +log_migration() { + echo $1 >> /host/migration/migration.log +} + +# Import files from another NOS's partition onto SONiC +nos_migration_import() { + [ -f $1 ] && cp $1 $2 || log_migration "ERROR: $1 not found!" +} + +# While migrating form another NOS, we need to preserve the MAC addresses +# of eth0 (and eventually switchports). +# Update the eth0 mac and also the EEPROM using ethtool so that subsequent +# reboots use the NOS's mac. +# Input : mgmt_interface.cfg file imported from the previous NOS. +update_mgmt_interface_macaddr() { + mgmt_config=$1 + if [ ! -f "$mgmt_config" ]; then + log_migration "ERROR : unable update eth0 MAC : $mgmt_config not found!" + return + fi + + # Save the previous NOS's mac + old_mac=`ip link show eth0 | grep ether | awk '{print $2}'` + [ -z "$old_mac" ] && log_migration "Unable to retrieve old mac address !" && return + + # Extract, validate and set the eth0's mac address for the current session + new_mac=$(grep "macaddr" $mgmt_config | awk -F'=' '{print $2}') + log_migration "Setting eth0 mac as $new_mac." + if [ `echo $new_mac | egrep "^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$"` ]; then + ip link set eth0 down + ip link set eth0 address $new_mac + ip link set eth0 up + else + log_migration "ERROR: mac imported from NOS is invalid : $new_mac !" + return + fi + + # Get the ethtool magic and offset for changing the mac address in the EEPROM + ethtool_magic=$(grep "ethtool_magic" $mgmt_config | awk -F'=' '{print $2}') + ethtool_offset=$(grep "ethtool_offset" $mgmt_config | awk -F'=' '{print $2}') + if [ -z "$ethtool_magic" ] || [ -z "$ethtool_offset" ]; then + log_migration "Unable to retrieve ethtool params ($ethtool_magic,$ethtool_offset)" + return + fi + + log_migration "eth0 mac in EEPROM before update:" + ethtool -e eth0 offset $ethtool_offset length 6 >> /host/migration/migration.log + + # Update the mac address in the EEPROM for subsequent reboots + # Write only changed octets + for i in 1 2 3 4 5 6; do + offset=$(($ethtool_offset+$i-1)) + old_mac_octet="$(echo $old_mac | cut -d":" -f$i)" + new_mac_octet="$(echo $new_mac | cut -d":" -f$i)" + + if [ "$old_mac_octet" != "$new_mac_octet" ]; then + ethtool -E eth0 magic $ethtool_magic offset $offset value 0x$new_mac_octet + if [ $? != 0 ]; then + log_migration "ERROR: unable to update eth0 EEPROM!" + log_migration "index $i, magic $ethtool_magic offset $offset, value $new_mac_octet" + return + fi + fi + done + + log_migration "eth0 mac in EEPROM after update:" + ethtool -e eth0 offset $ethtool_offset length 6 >> /host/migration/migration.log + + # Update the 70-persistent-net.rules with the new mac for eth0 + log_migration "/etc/udev/rules.d/70-persistent-net.rules : replacing $old_mac with $new_mac for eth0" + sed -i "/eth0/ s/ATTR{address}==\"$old_mac\"/ATTR{address}==\"$new_mac\"/g" /etc/udev/rules.d/70-persistent-net.rules +} + +firsttime_exit() { + rm -rf $FIRST_BOOT_FILE + exit 0 +} + +# Given a string of tuples of the form field=value, extract the value for a field +# In : $string, $field +# Out: $value +value_extract() { + set -- $string + for x in "$@"; do + case "$x" in + $field=*) + value="${x#$field=}" + esac + done +} + +# Set up previous and next reboot cause files +process_reboot_cause() { + REBOOT_CAUSE_FILE="/var/cache/sonic/reboot-cause.txt" + PREVIOUS_REBOOT_CAUSE_FILE="/var/cache/sonic/previous-reboot-cause.txt" + + # Set the previous reboot cause accordingly + # If this is the first boot after an image install, state that as the + # cause. Otherwise, move REBOOT_CAUSE_FILE to PREVIOUS_REBOOT_CAUSE_FILE. + # REBOOT_CAUSE_FILE should always exist, but we add the else case + # to ensure we always generate PREVIOUS_REBOOT_CAUSE_FILE here + if [ -f $FIRST_BOOT_FILE ]; then + echo "SONiC image installation" > $PREVIOUS_REBOOT_CAUSE_FILE + elif [ -f $REBOOT_CAUSE_FILE ]; then + mv -f $REBOOT_CAUSE_FILE $PREVIOUS_REBOOT_CAUSE_FILE + else + echo "Unknown reboot cause" > $PREVIOUS_REBOOT_CAUSE_FILE + fi + + # Set the default cause for the next reboot + echo "Unexpected reboot" > $REBOOT_CAUSE_FILE +} + +program_console_speed() +{ + speed=$(cat /proc/cmdline | grep -Eo 'console=ttyS[0-9]+,[0-9]+' | cut -d "," -f2) + if [ -z "$speed" ]; then + CONSOLE_SPEED=9600 + else + CONSOLE_SPEED=$speed + fi + + sed -i "s|\-\-keep\-baud .* %I| $CONSOLE_SPEED %I|g" /lib/systemd/system/serial-getty@.service + systemctl daemon-reload +} + +#### Begin Main Body #### + +# Set up previous and next reboot cause files +process_reboot_cause + +# If the machine.conf is absent, it indicates that the unit booted +# into SONiC from another NOS. Extract the machine.conf from ONIE. +if [ ! -e /host/machine.conf ]; then + mkdir -p /host/migration + + onie_dev=$(blkid | grep ONIE-BOOT | head -n 1 | awk '{print $1}' | sed -e 's/:.*$//') + mkdir -p /mnt/onie-boot + mount $onie_dev /mnt/onie-boot + onie_grub_cfg=/mnt/onie-boot/onie/grub/grub-machine.cfg + + if [ ! -e $onie_grub_cfg ]; then + log_migration "$onie_grub_cfg not found" + else + . ./$onie_grub_cfg + grep = $onie_grub_cfg | sed -e 's/onie_//' -e 's/=.*$//' | while read var ; do + eval val='$'onie_$var + echo "onie_${var}=${val}" >> /host/machine.conf + done + fi + + # Extract the previous NOS's partition that contains the migration artifacts + set -- $(cat /proc/cmdline) + for x in "$@"; do + case "$x" in + nos-config-part=*) + nos_val="${x#nos-config-part=}" + ;; + esac + done + + if [ -n "$nos_val" ]; then + nos_dev=$(findfs $nos_val) + if [ $? != 0 ]; then + log_migration "ERROR: nos_dev not found. Check grub parameters" + fi + else + log_migration "ERROR: nos_val not found. Check grub parameters" + fi + + if [ -n "$nos_dev" ]; then + # Mount the previous NOS's partition + NOS_DIR=/mnt/nos_migration + MG_GZFILE=$NOS_DIR/minigraph.xml.gz.base64.txt + MG_FILE=$NOS_DIR/minigraph.xml + ACL_GZFILE=$NOS_DIR/acl.json.gz.base64.txt + ACL_FILE=$NOS_DIR/acl.json + SNMP_FILE=$NOS_DIR/snmp.yml + mkdir -p $NOS_DIR + mount $nos_dev $NOS_DIR + mkdir -p /host/fast-reboot + + # decode & unzip minigraph.xml.gz.base64.txt + [ -f $MG_GZFILE ] && /usr/bin/base64 -d $MG_GZFILE | /bin/gunzip > $MG_FILE + [ -f $ACL_GZFILE ] && /usr/bin/base64 -d $ACL_GZFILE | /bin/gunzip > $ACL_FILE + + # Copy relevant files + nos_migration_import $NOS_DIR/mgmt_interface.cfg /host/migration + nos_migration_import $MG_FILE /host/migration + nos_migration_import $ACL_FILE /host/migration + nos_migration_import $SNMP_FILE /host/migration + nos_migration_import $NOS_DIR/arp.json /host/fast-reboot + nos_migration_import $NOS_DIR/fdb.json /host/fast-reboot + nos_migration_import $NOS_DIR/default_routes.json /host/fast-reboot + + umount $NOS_DIR + rmdir $NOS_DIR + fi + + update_mgmt_interface_macaddr /host/migration/mgmt_interface.cfg + + migration="TRUE" + umount /mnt/onie-boot +fi + +. /host/machine.conf + +program_console_speed + +if [ -f $FIRST_BOOT_FILE ]; then + + echo "First boot detected. Performing first boot tasks..." + + if [ -n "$aboot_platform" ]; then + platform=$aboot_platform + elif [ -n "$onie_platform" ]; then + platform=$onie_platform + else + echo "Unknown SONiC platform" + firsttime_exit + fi + + # Try to take old configuration saved during installation + # and create a flag in /tmp/ to let updategraph service know + if [ -d /host/old_config ]; then + mv -f /host/old_config /etc/sonic/ + rm -rf /etc/sonic/old_config/old_config + touch /tmp/pending_config_migration + elif [ -f /host/minigraph.xml ]; then + mkdir -p /etc/sonic/old_config + mv /host/minigraph.xml /etc/sonic/old_config/ + touch /tmp/pending_config_migration + elif [ -n "$migration" ] && [ -f /host/migration/minigraph.xml ]; then + mkdir -p /etc/sonic/old_config + mv /host/migration/minigraph.xml /etc/sonic/old_config/ + [ -f /host/migration/acl.json ] && mv /host/migration/acl.json /etc/sonic/old_config/ + [ -f /host/migration/snmp.yml ] && mv /host/migration/snmp.yml /etc/sonic/old_config/ + touch /tmp/pending_config_migration + [ -f /etc/sonic/updategraph.conf ] && sed -i -e "s/enabled=false/enabled=true/g" /etc/sonic/updategraph.conf + else + touch /tmp/pending_config_initialization + fi + + if [ -d /host/image-$SONIC_VERSION/platform/$platform ]; then + dpkg -i /host/image-$SONIC_VERSION/platform/$platform/*.deb + fi + + # If the unit booted into SONiC from another NOS's grub, + # we now install a grub for SONiC. + if [ -n "$onie_platform" ] && [ -n "$migration" ]; then + + grub_bin=$(ls /host/image-$SONIC_VERSION/platform/x86_64-grub/grub-pc-bin*.deb 2> /dev/null) + if [ -z "$grub_bin" ]; then + log_migration "Unable to locate grub package !" + firsttime_exit + fi + + dpkg -i $grub_bin > /dev/null 2>&1 + if [ $? != 0 ]; then + log_migration "Unable to install grub package !" + firsttime_exit + fi + + # Determine the block device to install grub + sonic_dev=$(blkid | grep SONiC-OS | head -n 1 | awk '{print $1}' | sed -e 's/[0-9]:.*$//') + if [ -z "$sonic_dev" ]; then + log_migration "Unable to determine sonic partition !" + firsttime_exit + fi + + grub-install --boot-directory=/host --recheck $sonic_dev 2>/dev/null + if [ $? != 0 ]; then + log_migration "grub install failed !" + firsttime_exit + fi + + # The SONiC "raw" build mode has already generated a proto grub.cfg + # as part of the migration. Platform specific constants need to be + # retrieved from installer.conf (if present) and assigned. + . /usr/share/sonic/device/$platform/installer.conf + + if [ ! -z "$CONSOLE_PORT" ]; then + field="\-\-port" + string=$(grep $field /host/grub.cfg) + value_extract $string $field + console_port=$value + if [ ! -z "$console_port" ] && [ "$console_port" != "$CONSOLE_PORT" ]; then + sed -i -e "s/\-\-port=$console_port/\-\-port=$CONSOLE_PORT/g" /host/grub.cfg + fi + log_migration "grub.cfg console port=$console_port & installer.conf CONSOLE_PORT=$CONSOLE_PORT" + fi + + if [ ! -z "$CONSOLE_DEV" ]; then + field="console" + string=$(grep $field /host/grub.cfg) + value_extract $string $field + console_dev_name=$(echo $value | sed -e "s/^.*=//" -e "s/,.*//") + console_dev="${console_dev_name#ttyS}" + if [ "$console_dev" != "$CONSOLE_DEV" ]; then + sed -i -e "s/console=ttyS$console_dev/console=ttyS$CONSOLE_DEV/g" /host/grub.cfg + fi + log_migration "grub.cfg console dev=$console_dev & installer.conf CONSOLE_DEV=$CONSOLE_DEV" + fi + + if [ ! -z "$VAR_LOG_SIZE" ]; then + field="var_log_size" + string=$(grep $field /host/grub.cfg) + value_extract $string $field + var_log_size=$value + if [ ! -z "$var_log_size" ] && [ "$var_log_size" != "$VAR_LOG_SIZE" ]; then + sed -i -e "s/var_log_size=$var_log_size/var_log_size=$VAR_LOG_SIZE/g" /host/grub.cfg + fi + log_migration "grub.cfg var_log_size=$var_log_size & installer.conf VAR_LOG_SIZE=$VAR_LOG_SIZE" + fi + + # Set the root based on the label + sonic_root=$(blkid | grep SONiC-OS | head -n 1 | awk '{print $1}' | sed -e 's/:.*$//') + sonic_root=$(echo "$sonic_root" | sed 's/\//\\\//g') + sed -i -e "s/%%SONIC_ROOT%%/$sonic_root/g" /host/grub.cfg + + # Add the Diag and ONIE entries + mount $onie_dev /mnt/onie-boot + . /mnt/onie-boot/onie/grub.d/50_onie_grub >> /host/grub.cfg + umount /mnt/onie-boot + + # Initialize the SONiC's grub config + mv /host/grub.cfg /host/grub/grub.cfg + fi + + firsttime_exit +fi + +exit 0 diff --git a/files/image_config/rsyslog/rsyslog-config.service b/files/image_config/rsyslog/rsyslog-config.service new file mode 100644 index 000000000000..ee62a36ccf2d --- /dev/null +++ b/files/image_config/rsyslog/rsyslog-config.service @@ -0,0 +1,11 @@ +[Unit] +Description=Update rsyslog configuration +Requires=updategraph.service +After=updategraph.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/rsyslog-config.sh + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/rsyslog/rsyslog-config.sh b/files/image_config/rsyslog/rsyslog-config.sh new file mode 100755 index 000000000000..c8ba7b99453c --- /dev/null +++ b/files/image_config/rsyslog/rsyslog-config.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +sonic-cfggen -d -t /usr/share/sonic/templates/rsyslog.conf.j2 >/etc/rsyslog.conf +systemctl restart rsyslog diff --git a/files/image_config/rsyslog/rsyslog.conf.j2 b/files/image_config/rsyslog/rsyslog.conf.j2 new file mode 100644 index 000000000000..063f119f6bdd --- /dev/null +++ b/files/image_config/rsyslog/rsyslog.conf.j2 @@ -0,0 +1,70 @@ +############################################################################### +# Managed by Ansible +# file: ansible/roles/acs/templates/rsyslog.conf.j2 +############################################################################### +# +# /etc/rsyslog.conf Configuration file for rsyslog. +# +# For more information see +# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html + + +################# +#### MODULES #### +################# + +$ModLoad imuxsock # provides support for local system logging +$ModLoad imklog # provides kernel logging support +#$ModLoad immark # provides --MARK-- message capability + +# provides UDP syslog reception +$ModLoad imudp +$UDPServerAddress 127.0.0.1 # bind to localhost before udp server run +$UDPServerRun 514 + +# provides TCP syslog reception +#$ModLoad imtcp +#$InputTCPServerRun 514 + + +########################### +#### GLOBAL DIRECTIVES #### +########################### +# +# Use traditional timestamp format. +# To enable high precision timestamps, comment out the following line. +# +#$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat + +# Define a custom template +$template SONiCFileFormat,"%timegenerated%.%timegenerated:::date-subseconds% %HOSTNAME% %syslogseverity-text:::uppercase% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" +$ActionFileDefaultTemplate SONiCFileFormat + +#Set remote syslog server +{% for server in SYSLOG_SERVER %} +*.* @{{ server }}:514;SONiCFileFormat +{% endfor %} + +# +# Set the default permissions for all log files. +# +$FileOwner root +$FileGroup adm +$FileCreateMode 0640 +$DirCreateMode 0755 +$Umask 0022 + +# +# Where to place spool and state files +# +$WorkDirectory /var/spool/rsyslog + +# +# Include all config files in /etc/rsyslog.d/ +# +$IncludeConfig /etc/rsyslog.d/*.conf + + +############### +#### RULES #### +############### diff --git a/files/image_config/rsyslog/rsyslog.d/00-sonic.conf b/files/image_config/rsyslog/rsyslog.d/00-sonic.conf new file mode 100644 index 000000000000..455fe89fd2bf --- /dev/null +++ b/files/image_config/rsyslog/rsyslog.d/00-sonic.conf @@ -0,0 +1,27 @@ +## Quagga rules + +if $programname == ["bgp#quagga", + "bgp#watchquagga", + "bgp#zebra"] + then { + /var/log/quagga/zebra.log + stop +} + +if $programname == "bgp#bgpd" then { + /var/log/quagga/bgpd.log + stop +} + +## Teamd rules + +if $programname contains "teamd_" then { + /var/log/teamd.log + stop +} + +## telemetry rules +if $msg startswith " telemetry" or ($msg startswith " dialout" )then { + /var/log/telemetry.log + stop +} diff --git a/files/image_config/rsyslog/rsyslog.d/99-default.conf b/files/image_config/rsyslog/rsyslog.d/99-default.conf new file mode 100644 index 000000000000..77609410c57a --- /dev/null +++ b/files/image_config/rsyslog/rsyslog.d/99-default.conf @@ -0,0 +1,27 @@ +# +# First some standard log files. Log by facility. +# + +# Log all facilities to /var/log/syslog except cron, auth +# and authpriv. They are noisy - log them to their own files +*.*;cron,auth,authpriv.none -/var/log/syslog +auth,authpriv.* /var/log/auth.log +cron.* /var/log/cron.log + +# +# Emergencies are sent to everybody logged in. +# +*.emerg :omusrmsg:* + +# The named pipe /dev/xconsole is for the `xconsole' utility. To use it, +# you must invoke `xconsole' with the `-file' option: +# +# $ xconsole -file /dev/xconsole [...] +# +# NOTE: adjust the list below, or you'll go crazy if you have a reasonably +# busy site.. +# +#daemon.*;mail.*;\ +# news.err;\ +# *.=debug;*.=info;\ +# *.=notice;*.=warn |/dev/xconsole diff --git a/files/image_config/snmp/snmp.yml b/files/image_config/snmp/snmp.yml new file mode 100644 index 000000000000..117619975fbb --- /dev/null +++ b/files/image_config/snmp/snmp.yml @@ -0,0 +1,2 @@ +snmp_rocommunity: public +snmp_location: public diff --git a/files/image_config/sudoers/sudoers b/files/image_config/sudoers/sudoers new file mode 100644 index 000000000000..9944299830b0 --- /dev/null +++ b/files/image_config/sudoers/sudoers @@ -0,0 +1,57 @@ +# +# This file MUST be edited with the 'visudo' command as root. +# +# Please consider adding local content in /etc/sudoers.d/ instead of +# directly modifying this file. +# +# See the man page for details on how to write a sudoers file. +# +Defaults env_reset +#Defaults mail_badpass +Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" +Defaults env_keep += "SONIC_CLI_IFACE_MODE" +Defaults env_keep += "VTYSH_PAGER" +Defaults lecture_file = /etc/sudoers.lecture + +# Host alias specification + +# User alias specification + +# Cmnd alias specification +# Note: bcmcmd is dangerous for users in read only netgroups because it may operate ASIC +Cmnd_Alias READ_ONLY_CMDS = /sbin/brctl show, \ + /usr/bin/decode-syseeprom, \ + /usr/bin/docker images *, \ + /usr/bin/docker exec snmp cat /etc/snmp/snmpd.conf, \ + /usr/bin/docker exec bgp cat /etc/quagga/bgpd.conf, \ + /usr/bin/docker exec * ps aux, \ + /usr/bin/docker ps*, \ + /usr/bin/generate_dump, \ + /usr/bin/lldpctl, \ + /usr/bin/lldpshow, \ + /usr/bin/psuutil *, \ + /usr/bin/sensors, \ + /usr/bin/sfputil show *, \ + /usr/bin/vtysh -c show *, \ + /bin/cat /var/log/syslog*, \ + /usr/bin/tail -F /var/log/syslog + +Cmnd_Alias PASSWD_CMDS = /usr/bin/config tacacs passkey *, \ + /usr/sbin/chpasswd * + +# User privilege specification +root ALL=(ALL:ALL) ALL + +# Allow all users to execute read only commands +ALL ALL=NOPASSWD: READ_ONLY_CMDS + +# Allow members of group sudo to execute any command +%sudo ALL=(ALL:ALL) NOPASSWD: ALL + +# Prevent password related command into syslog +Defaults!PASSWD_CMDS !syslog + +# See sudoers(5) for more information on "#include" directives: + +#includedir /etc/sudoers.d + diff --git a/files/image_config/sudoers/sudoers.lecture b/files/image_config/sudoers/sudoers.lecture new file mode 100644 index 000000000000..e89340092c70 --- /dev/null +++ b/files/image_config/sudoers/sudoers.lecture @@ -0,0 +1,4 @@ + +Make sure your account has RW permission to current device. +Otherwise sudo requests will be rejected. + diff --git a/files/image_config/systemd/journald.conf b/files/image_config/systemd/journald.conf new file mode 100644 index 000000000000..0f3d1b5ec25b --- /dev/null +++ b/files/image_config/systemd/journald.conf @@ -0,0 +1,35 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# See journald.conf(5) for details + +[Journal] +#Storage=auto +#Compress=yes +#Seal=yes +#SplitMode=uid +#SyncIntervalSec=5m +#RateLimitInterval=30s +#RateLimitBurst=1000 +SystemMaxUse=50M +#SystemKeepFree= +#SystemMaxFileSize= +RuntimeMaxUse=50M +#RuntimeKeepFree= +#RuntimeMaxFileSize= +#MaxRetentionSec= +#MaxFileSec=1month +#ForwardToSyslog=yes +#ForwardToKMsg=no +#ForwardToConsole=no +#ForwardToWall=yes +#TTYPath=/dev/console +#MaxLevelStore=debug +#MaxLevelSyslog=debug +#MaxLevelKMsg=notice +#MaxLevelConsole=info +#MaxLevelWall=emerg diff --git a/files/image_config/updategraph/updategraph b/files/image_config/updategraph/updategraph new file mode 100755 index 000000000000..63f788afc465 --- /dev/null +++ b/files/image_config/updategraph/updategraph @@ -0,0 +1,194 @@ +#!/bin/bash + +CONFIG_DB_INDEX=4 + +reload_minigraph() +{ + echo "Reloading minigraph..." + if [ ! -f /etc/sonic/init_cfg.json ]; then + echo "{}" > /etc/sonic/init_cfg.json + fi + redis-cli -n $CONFIG_DB_INDEX FLUSHDB + sonic-cfggen -H -m -j /etc/sonic/init_cfg.json --write-to-db + redis-cli -n $CONFIG_DB_INDEX SET "CONFIG_DB_INITIALIZED" "1" + if [ -f /etc/sonic/acl.json ]; then + acl-loader update full /etc/sonic/acl.json + fi + config qos reload + pfcwd start_default +} + +function copy_config_files() +{ + for file in $@; do + if [ -f /etc/sonic/old_config/${file} ]; then + logger "Copying SONiC configuration ${file} ..." + cp /etc/sonic/old_config/${file} /etc/sonic/ + else + logger "Missing SONiC configuration ${file} ..." + fi + done +} + +function check_system_warm_boot() +{ + SYSTEM_WARM_START=`/usr/bin/redis-cli -n 4 hget "WARM_RESTART|system" enable` + # SYSTEM_WARM_START could be empty, always make WARM_BOOT meaningful. + if [[ x"$SYSTEM_WARM_START" == x"true" ]]; then + WARM_BOOT="true" + else + WARM_BOOT="false" + fi +} + + +if [ ! -f /etc/sonic/updategraph.conf ]; then + echo "No updategraph.conf found, generating a default one." + echo "enabled=false" >/etc/sonic/updategraph.conf +fi + +. /etc/sonic/updategraph.conf + +check_system_warm_boot + +if [ -f /tmp/pending_config_migration ]; then + copy_config_files minigraph.xml snmp.yml acl.json config_db.json + if [ x"${WARM_BOOT}" == x"true" ]; then + echo "Warm reboot detected..." + elif [ "$enabled" = "true" ]; then + echo "Use minigraph.xml from old system..." + reload_minigraph + sonic-cfggen -d --print-data > /etc/sonic/config_db.json + else + echo "Use config_db.json from old system..." + sonic-cfggen -j /etc/sonic/config_db.json --write-to-db + fi + rm -f /tmp/pending_config_migration + sed -i "/enabled=/d" /etc/sonic/updategraph.conf + echo "enabled=false" >> /etc/sonic/updategraph.conf + exit 0 +fi + +if [ -f /tmp/pending_config_initialization ]; then + rm -f /tmp/pending_config_initialization + if [ "$enabled" != "true" ]; then + PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform` + PRESET=(`head -n 1 /usr/share/sonic/device/$PLATFORM/default_sku`) + sonic-cfggen -H -k ${PRESET[0]} --preset ${PRESET[1]} > /etc/sonic/config_db.json + redis-cli -n $CONFIG_DB_INDEX FLUSHDB + sonic-cfggen -j /etc/sonic/config_db.json --write-to-db + redis-cli -n $CONFIG_DB_INDEX SET "CONFIG_DB_INITIALIZED" "1" + exit 0 + fi +fi + +if [ "$enabled" = "reload_only" ]; then + reload_minigraph + sed -i "/enabled=/d" /etc/sonic/updategraph.conf + echo "enabled=false" >> /etc/sonic/updategraph.conf + exit 0 +fi + +if [ "$enabled" != "true" ]; then + echo "Disabled in updategraph.conf. Skipping graph update." + exit 0 +fi + +ACL_URL=$acl_src + +if [ "$src" = "dhcp" ]; then + # Enable dhcp client on management port eth0 + /sbin/dhclient -4 -v -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhclient.eth0.leases -I -df /var/lib/dhcp/dhclient6.eth0.leases eth0 & + disown + + while [ ! -f /tmp/dhcp_graph_url ]; do + echo "Waiting for DHCP response..." + sleep 1 + done + + if [ "`cat /tmp/dhcp_graph_url`" = "N/A" ]; then + echo "No graph_url option in DHCP response. Skipping graph update and generating an empty configuration." + PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform` + if [ -f /etc/sonic/minigraph.xml ]; then + sonic-cfggen -H -m /etc/sonic/minigraph.xml --preset empty > /tmp/device_meta.json + else + PRESET=(`head -n 1 /usr/share/sonic/device/$PLATFORM/default_sku`) + sonic-cfggen -H -k ${PRESET[0]} --preset empty > /tmp/device_meta.json + fi + 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 + redis-cli -n $CONFIG_DB_INDEX FLUSHDB + sonic-cfggen -j /etc/sonic/config_db.json --write-to-db + redis-cli -n $CONFIG_DB_INDEX SET "CONFIG_DB_INITIALIZED" "1" + 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 + + + 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\+&@#/%=~_|]$' + if [[ ! $GRAPH_URL =~ $URL_REGEX ]]; then + echo "\"$GRAPH_URL\" is not a valid url. Skipping graph update." + exit 0 + fi + if [ "$dhcp_as_static" = "true" ]; then + sed -i "/src=/d" /etc/sonic/updategraph.conf + echo "src=\"$GRAPH_URL\"" >> /etc/sonic/updategraph.conf + fi + + if [ -f /tmp/dhcp_acl_url ]; then + ACL_URL=`sonic-cfggen -t /tmp/dhcp_acl_url -a "{\"hostname\": \"$HOSTNAME\"}"` + if [[ ! $ACL_URL =~ $URL_REGEX ]]; then + echo "\"$ACL_URL\" is not a valid url. Skipping acl update." + ACL_URL="" + fi + if [ "$dhcp_as_static" = "true" ]; then + sed -i "/acl_src=/d" /etc/sonic/updategraph.conf + echo "acl_src=\"$ACL_URL\"" >> /etc/sonic/updategraph.conf + fi + fi +else + GRAPH_URL=$src +fi + +if [ -f /etc/sonic/minigraph.xml ]; then + echo "Renaming minigraph.xml to minigraph.old" + mv /etc/sonic/minigraph.xml /etc/sonic/minigraph.old +fi + +echo "Getting minigraph from $GRAPH_URL" + +while true; do + curl -f $GRAPH_URL -o /etc/sonic/minigraph.xml --connect-timeout 15 && break + sleep 5 +done + +if [ -n "$ACL_URL" ]; then + if [ -f /etc/sonic/acl.json ]; then + echo "Renaming acl.json to acl.json.old" + mv /etc/sonic/acl.json /etc/sonic/acl.json.old + fi + echo "Getting ACL config from $ACL_URL" + + while true; do + curl -f $ACL_URL -o /etc/sonic/acl.json --connect-timeout 15 && break + sleep 5 + done +else + echo "Skip ACL config download." +fi + +reload_minigraph +sonic-cfggen -d --print-data > /etc/sonic/config_db.json + +# Mark as disabled after graph is successfully downloaded +sed -i "/enabled=/d" /etc/sonic/updategraph.conf +echo "enabled=false" >> /etc/sonic/updategraph.conf + diff --git a/files/initramfs-tools/arista-convertfs.j2 b/files/initramfs-tools/arista-convertfs.j2 new file mode 100644 index 000000000000..7b315b7725c6 --- /dev/null +++ b/files/initramfs-tools/arista-convertfs.j2 @@ -0,0 +1,228 @@ +#!/bin/sh + +case $1 in + prereqs) + exit 0 + ;; +esac + +set -e +# set -x +total_mem=$(free | awk '/^Mem:/{print $2}') +tmpfs_size=$(( $total_mem / 20 * 17 )) +free_mem_thres=$(( $total_mem / 20 * 18 )) +tmp_mnt='/mnt/ramdisk-convfs' +root_mnt='/mnt/root-convfs' +root_dev='' +flash_dev='' +block_flash='' +aboot_flag='' +backup_file='' + +# Wait until get the fullpath of flash device, e.g., /dev/sda +wait_get_flash_dev() { + local try_rounds=30 + while [ $try_rounds -gt 0 ]; do + for dev in $(ls /sys/block); do + local is_mmc=$(echo "$dev" | grep 'mmcblk.*boot.*' | cat) + if [ -n "$is_mmc" ]; then + continue + fi + local devid=$(realpath "/sys/block/$dev/device") + local is_device=$(echo "$devid" | grep '^/sys/devices/' | cat) + local is_flash=$(echo "$devid" | grep "$block_flash" | cat) + if [ -n "$is_device" -a -n "$is_flash" ]; then + flash_dev="/dev/$dev" + return 0 + fi + done + sleep 1 + try_rounds=$(( $try_rounds - 1 )) + done + return 1 +} + +# Wait for root_dev to be ready +wait_for_root_dev() { + local try_rounds=30 + while [ $try_rounds -gt 0 ]; do + if blkid | sed 's/"//g' | grep -q "$root_dev"; then + return 0 + fi + if [ -e "$root_dev" ]; then + return 0 + fi + sleep 1 + try_rounds=$(( $try_rounds - 1 )) + done + return 1 +} + +# Alway run cleanup before exit +cleanup() { + if grep -q "$root_mnt" /proc/mounts; then + umount "$root_mnt" + fi + if grep -q "$tmp_mnt" /proc/mounts; then + umount "$tmp_mnt" + fi + [ -e "$root_mnt" ] && rmdir "$root_mnt" + [ -e "$tmp_mnt" ] && rmdir "$tmp_mnt" +} +trap cleanup EXIT + +notification() { +cat << EOF +A failure happend in modifying the root file system which stopped the upgrade. Manual interventions are needed to fix the issue. Note that: +1) files in the old root file system may have been lost and the old partition table may have been corrupted; +2) The files in the old root file system were copied to $tmp_mnt; +3) The old partition table was dumped to the file $tmp_mnt/$backup_file by sfdisk; +4) Quitting the current shell will lose all files mentioned above permanently. +EOF +} + +run_cmd() { + if ! eval "$1"; then + echo "$2" + notification + sh + exit 1 + 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" + + # remove all the filesystem acls from the flash + setfacl -Rb "$flash_mnt" +} + +# Update ROOT device referring to the path under block_flash +# This is for the occasional name swap between /dev/sda and /dev/sdb +update_root() { + # Check that root=/dev/*, ignoring any cases like root=UUID=* + [ "${ROOT#/dev}" = "${ROOT}" ] && return 0 + + # Replace the beginning chars of ROOT by the ones of flash_dev with same index +{% raw %} + prefix_length="${#flash_dev}" +{% endraw %} + part_id="${ROOT:$prefix_length}" + ROOT="$flash_dev$part_id" + + echo "ROOT=$ROOT" > /conf/param.conf +} + +# Extract kernel parameters +set -- $(cat /proc/cmdline) +for x in "$@"; do + case "$x" in + block_flash=*) + block_flash="${x#block_flash=}" + ;; + Aboot=*) + aboot_flag="${x#Aboot=}" + ;; + loop=*) + x1="${x#loop=}" + image_dir="${x1%/*}" + ;; + esac +done + +#Check aboot +[ -z "$aboot_flag" ] && exit 0 + +# Get flash dev name +if [ -z "$block_flash" ]; then + echo "Error: flash device info is not provided" + exit 1 +fi +if ! wait_get_flash_dev; then + echo "Error: flash device is not found" + exit 1 +fi + +# If root=/dev/*, update ROOT to the device under block_flash +update_root + +root_dev="$ROOT" +if [ -z "$root_dev" ]; then + echo "Error: root device name is not provided" + exit 1 +fi +if ! wait_for_root_dev; then + echo "Error: timeout in waiting for $root_dev" + exit 1 +fi + +# exit when the root is ext4 +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 + +# Check memory size for tmpfs +free_mem=$(free | awk '/^Mem:/{print $4}') +if [ "$free_mem" -lt "$free_mem_thres" ]; then + echo "Error: memory is not enough" + exit 1 +fi + +# Backup partition table +mkdir -p "$root_mnt" +mount "$root_dev" "$root_mnt" +backup_file=backup.$(date +%Y-%m-%d.%H-%M-%S) +sfdisk -d "$flash_dev" > "$root_mnt/$backup_file" + +# Check total size of files in root +total_file_size=$(du -s "$root_mnt" | awk '{print $1}') +if [ "$total_file_size" -gt "$tmpfs_size" ]; then + echo "Error: total file size is too large" + exit 1 +fi + +# Create tmpfs, and copy files to tmpfs +mkdir -p "$tmp_mnt" +mount -t tmpfs -o size="${tmpfs_size}k" tmpfs "$tmp_mnt" +cp -a "$root_mnt/." "$tmp_mnt/" +umount "$root_mnt" + +#### Lines below will modify the root file system, so any failure will be trapped to shell for manual interventions. + +if [ $(echo -n "$root_dev" | tail -c 1) == "1" ]; then + # Create a new partition table (content in flash_dev will be deleted) + err_msg="Error: repartitioning $flash_dev failed" + cmd="echo '2048' | sfdisk $flash_dev || (sleep 3; blockdev --rereadpt $flash_dev && fdisk -l $flash_dev | grep -q ${root_dev}.*Linux)" + run_cmd "$cmd" "$err_msg" +fi + +sleep 2 +err_msg="Error: timeout in waiting for $root_dev after repartition" +cmd="wait_for_root_dev" +run_cmd "$cmd" "$err_msg" + +err_msg="Error: formatting to ext4 failed" +cmd="mke2fs -t ext4 -F -O '^huge_file,^metadata_csum' $root_dev" +run_cmd "$cmd" "$err_msg" + +err_msg="Error: mounting $root_dev to $root_mnt failed" +cmd="mount -t ext4 $root_dev $root_mnt" +run_cmd "$cmd" "$err_msg" + +err_msg="Error: extract docker directory" +cmd="[ -f $tmp_mnt/$image_dir/{{ FILESYSTEM_DOCKERFS }} ] && rm -rf $root_mnt/$image_dir/{{ DOCKERFS_DIR }} && mkdir -p $root_mnt/$image_dir/{{ DOCKERFS_DIR }} && tar xzf $tmp_mnt/$image_dir/{{ FILESYSTEM_DOCKERFS }} -C $root_mnt/$image_dir/{{ DOCKERFS_DIR }} && rm -f $tmp_mnt/$image_dir/{{ FILESYSTEM_DOCKERFS }}" +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/files/initramfs-tools/arista-net b/files/initramfs-tools/arista-net new file mode 100644 index 000000000000..8759746458d6 --- /dev/null +++ b/files/initramfs-tools/arista-net @@ -0,0 +1,113 @@ +#!/bin/sh + +case $1 in + prereqs) + exit 0 + ;; +esac + +set -e + +# Extract kernel parameters +set -- $(cat /proc/cmdline) +items="" +for x in "$@"; do + case "$x" in + Aboot=*) + aboot_flag="${x#Aboot=}" + ;; + net_*) + item="${x#net_}" + items="$items $item" + ;; + platform=*) + platform_flag="${x#platform=}" + ;; + esac +done + +random() { + echo $(od -vAn -N1 -tu1 < /dev/urandom) +} + +arista_net_devname() { + local pciaddr="$1" + local devname_prefix="$2" + for path in $(ls -d /sys/class/net/${devname_prefix}* 2>/dev/null); do + local devid="$(realpath "$path/device")" + if echo "$devid" | grep -q "$pciaddr"; then + echo "${path##*/}" + return + fi + done +} + +arista_net_rename() { + local device_path="$1" + local new_name="$2" + local from_name="$3" + devname=$(arista_net_devname "$device_path" "$from_name") + [ -n "$devname" ] && ip link set "$devname" name "$new_name" +} + +# Sets the MAC address to the value passed by Aboot through /proc/cmdline +tg3fixhwaddr() +{ + local default_tg3_hwaddr="00:10:18:00:00:00" + local pciaddr="$1" + local hwaddr="$2" + + devname=$(arista_net_devname "$pciaddr") + if [ -z "$devname" ]; then + return + fi + + driver=$(basename $(readlink "/sys/class/net/$devname/device/driver")) + if [ "$driver" != "tg3" ]; then + return 0 + fi + + if [ "$hwaddr" = "$default_tg3_hwaddr" ]; then + hwaddr=$(cat /sys/class/net/$devname/address) + fi + + if [ "$hwaddr" = "$default_tg3_hwaddr" ]; then + hwaddr=$(printf "%02x" "$(($(random) & 0xfe | 0x02))") + for i in 1 2 3 4 5; do + hwaddr=$(printf "$hwaddr:%02x" "$(($(random) & 0xfe | 0x02))") + done + fi + + ip link set dev "$devname" addr "$hwaddr" +} + +if [ -n "$aboot_flag" ]; then + for item in $items; do + key="${item%=*}" + value="${item#*=}" + hwaddr=$(eval echo \${hwaddr_${key}}) + if [ -n "$hwaddr" ]; then + tg3fixhwaddr "$value" "$hwaddr" + fi + done +fi + +# Iterate over all the net_maX items found in the cmdline two times. +# First time renaming the interfaces to maX. +# The second time renaming them to their final name ethX. +if [ -n "$aboot_flag" -a "$platform_flag" == 'rook' ]; then + for item in $items; do + key="${item%=*}" + value="${item#*=}" + arista_net_rename "$value" "$key" eth + done + for item in $items; do + key="${item%=*}" + value="${item#*=}" + index="${key#ma}" + index="$(( $index - 1 ))" + newKey="eth$index" + arista_net_rename "$value" "$newKey" ma + done +fi + diff --git a/files/initramfs-tools/mgmt-intf-dhcp b/files/initramfs-tools/mgmt-intf-dhcp new file mode 100644 index 000000000000..52f7ff5f495c --- /dev/null +++ b/files/initramfs-tools/mgmt-intf-dhcp @@ -0,0 +1,36 @@ +#!/bin/sh + +PREREQS="union-mount" + +prereqs() { echo "$PREREQS"; } + +case $1 in + prereqs) + prereqs + exit 0 + ;; +esac + +# Extract kernel parameters +set -- $(cat /proc/cmdline) +for x in "$@"; do + case "$x" in + mgmt-intf-dhcp=*) + val="${x#mgmt-intf-dhcp=}" + + if [ -z "$val" ]; then + echo "ERROR: mgmt-intf-dhcp value (on/off) not specified !" + exit 0 + fi + + if [ -e "${rootmnt}/etc/network/interfaces" ]; then + if [ "$val" = "off" ]; then + sed -i 's/iface eth0 inet dhcp/iface eth0 inet static/g' ${rootmnt}/etc/network/interfaces + elif [ "$val" = "on" ]; then + sed -i 's/iface eth0 inet static/iface eth0 inet dhcp/g' ${rootmnt}/etc/network/interfaces + fi + fi + + ;; + esac +done diff --git a/files/initramfs-tools/mke2fs b/files/initramfs-tools/mke2fs new file mode 100644 index 000000000000..52933d644a87 --- /dev/null +++ b/files/initramfs-tools/mke2fs @@ -0,0 +1,52 @@ +#!/bin/sh +#Part of the code is revised based on initramfs-tools/hooks/fsck and initramfs-tool is under GPL v2. + +PREREQ="" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +. /usr/share/initramfs-tools/hook-functions + +copy_exec /sbin/mke2fs +copy_exec /sbin/sfdisk +copy_exec /sbin/fdisk +copy_exec /sbin/resize2fs +copy_exec /sbin/findfs + +fstypes="ext4 ext3" + +for type in $fstypes; do + prog="/sbin/mkfs.${type}" + if [ -h "$prog" ]; then + link=$(readlink -f "$prog") + copy_exec "$link" + ln -s "$link" "${DESTDIR}/$prog" + elif [ -x "$prog" ] ; then + copy_exec "$prog" + else + echo "Warning: /sbin/mkfs.${type} doesn't exist, can't install to initramfs, ignoring." + fi +done + +for type in $fstypes; do + prog="/sbin/fsck.${type}" + if [ -h "$prog" ]; then + link=$(readlink -f "$prog") + copy_exec "$link" + ln -s "$link" "${DESTDIR}/$prog" + elif [ -x "$prog" ] ; then + copy_exec "$prog" + else + echo "Warning: /sbin/fsck.${type} doesn't exist, can't install to initramfs, ignoring." + fi +done diff --git a/files/initramfs-tools/modules b/files/initramfs-tools/modules index 86a1fcf20bd7..e7fcbef870d2 100644 --- a/files/initramfs-tools/modules +++ b/files/initramfs-tools/modules @@ -1,2 +1,6 @@ squashfs -aufs +overlay +vfat +nls_ascii +nls_cp437 +nls_utf8 diff --git a/files/initramfs-tools/resize-rootfs b/files/initramfs-tools/resize-rootfs new file mode 100644 index 000000000000..17ffcb94e693 --- /dev/null +++ b/files/initramfs-tools/resize-rootfs @@ -0,0 +1,39 @@ +#!/bin/sh + +case $1 in + prereqs) + exit 0 + ;; +esac + +# Extract kernel parameters +set -- $(cat /proc/cmdline) +for x in "$@"; do + case "$x" in + root=*) + root_val="${x#root=}" + ;; + resize-rootfs) + need_resize=1 + ;; + esac +done + +if [ -n "$need_resize" ]; then + if [ -z "$root_val" ]; then + echo "ERROR: resize required but unable to get root location from command line" + exit 1 + fi + + root_dev=$(findfs $root_val) + if [ $? != 0 ]; then + echo "ERROR: resize required but findfs failed" + exit 1 + fi + + resize2fs -f $root_dev + if [ $? != 0 ]; then + echo "ERROR: Unable to resize the root file system. Manual intervention needed to fix the issue." + exit 1 + fi +fi diff --git a/files/initramfs-tools/setfacl b/files/initramfs-tools/setfacl new file mode 100644 index 000000000000..96564e06b245 --- /dev/null +++ b/files/initramfs-tools/setfacl @@ -0,0 +1,20 @@ +#!/bin/sh +#Part of the code is revised based on initramfs-tools/hooks/fsck and initramfs-tool is under GPL v2. + +PREREQ="" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +. /usr/share/initramfs-tools/hook-functions + +copy_exec /usr/bin/setfacl /sbin/setfacl diff --git a/files/initramfs-tools/udev.patch b/files/initramfs-tools/udev.patch new file mode 100644 index 000000000000..38c43dc27d69 --- /dev/null +++ b/files/initramfs-tools/udev.patch @@ -0,0 +1,10 @@ +--- a/udev 2017-09-02 23:13:45.078773236 +0000 ++++ b/udev 2017-09-02 22:40:08.502773236 +0000 +@@ -1,6 +1,6 @@ + #!/bin/sh -e + +-PREREQS="" ++PREREQS="union-mount" + + prereqs() { echo "$PREREQS"; } + diff --git a/files/initramfs-tools/union-mount b/files/initramfs-tools/union-mount deleted file mode 100644 index 85fba9df3a0a..000000000000 --- a/files/initramfs-tools/union-mount +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -e -case $1 in - prereqs) - exit 0 - ;; -esac -mkdir -p ${rootmnt}/host/rw -mount -n -o dirs=${rootmnt}/host/rw:${rootmnt}=ro -t aufs root-aufs ${rootmnt} -mount ${ROOT} ${rootmnt}/host -mkdir -p /root/var/lib/docker -mount --bind /root/host/var/lib/docker /root/var/lib/docker -mkdir -p /root/boot -mount --bind /root/host/boot /root/boot diff --git a/files/initramfs-tools/union-mount.j2 b/files/initramfs-tools/union-mount.j2 new file mode 100644 index 000000000000..6369b8449681 --- /dev/null +++ b/files/initramfs-tools/union-mount.j2 @@ -0,0 +1,30 @@ +#!/bin/sh -e + +PREREQS="varlog" + +prereqs() { echo "$PREREQS"; } + +case $1 in + prereqs) + prereqs + exit 0 + ;; +esac + +## Mount the overlay file system: rw layer over squashfs +image_dir=$(cat /proc/cmdline | sed -e 's/.*loop=\(\S*\)\/.*/\1/') +mkdir -p ${rootmnt}/host/$image_dir/rw +mkdir -p ${rootmnt}/host/$image_dir/work +mount -n -o lowerdir=${rootmnt},upperdir=${rootmnt}/host/$image_dir/rw,workdir=${rootmnt}/host/$image_dir/work -t overlay root-overlay ${rootmnt} +## Check if the root block device is still there +[ -b ${ROOT} ] || mdev -s +## Mount the raw partition again +mount ${ROOT} ${rootmnt}/host +## Mount the working directory of docker engine in the raw partition, bypass the overlay +mkdir -p ${rootmnt}/var/lib/docker +mount --bind ${rootmnt}/host/$image_dir/{{ DOCKERFS_DIR }} ${rootmnt}/var/lib/docker +## Mount the boot directory in the raw partition, bypass the overlay +mkdir -p ${rootmnt}/boot +mount --bind ${rootmnt}/host/$image_dir/boot ${rootmnt}/boot +## Mount loop device for /var/log +[ -f ${rootmnt}/host/disk-img/var-log.ext4 ] && mount -t ext4 -o loop,rw ${rootmnt}/host/disk-img/var-log.ext4 ${rootmnt}/var/log diff --git a/files/initramfs-tools/varlog b/files/initramfs-tools/varlog new file mode 100644 index 000000000000..d1340eaa9d8b --- /dev/null +++ b/files/initramfs-tools/varlog @@ -0,0 +1,36 @@ +#!/bin/sh -e + +PREREQS="" + +prereqs() { echo "$PREREQS"; } + +case $1 in + prereqs) + prereqs + exit 0 + ;; +esac + +# Extract kernel parameters +set -- $(cat /proc/cmdline) +for x in "$@"; do + case "$x" in + varlog_size=*) + varlog_size="${x#varlog_size=}" + esac +done + +[ -z "$varlog_size" ] && exit 0 + +# exit when the var_log.ext4 exists and the size matches +if [ -e "${rootmnt}/host/disk-img/var-log.ext4" ]; then + cur_varlog_size=$(ls -l ${rootmnt}/host/disk-img/var-log.ext4 | awk '{print $5}') + if [ $cur_varlog_size == $((1024*1024*$varlog_size)) ]; then + exit 0 + else + rm -rf ${rootmnt}/host/disk-img + fi +fi + +# create varlog disk +mkdir -p ${rootmnt}/host/disk-img && ${rootmnt}/usr/bin/fallocate -l "$varlog_size"M ${rootmnt}/host/disk-img/var-log.ext4 && mkfs.ext4 -q -F ${rootmnt}/host/disk-img/var-log.ext4 diff --git a/files/scripts/arp_update b/files/scripts/arp_update new file mode 100755 index 000000000000..f7c5ec8bb856 --- /dev/null +++ b/files/scripts/arp_update @@ -0,0 +1,50 @@ +#!/bin/bash +# +# usage: +# arp_update: +# Send ipv6 multicast pings to all "UP" L3 interfaces including vlan interfaces to +# refresh link-local addresses from neighbors. +# Send gratuitous ARP/NDP requests to VLAN member neighbors to refresh +# the ipv4/ipv6 neighbors state. + +while /bin/true; do + # find L3 interfaces which are UP, send ipv6 multicast pings + echo "{% for (name, prefix) in INTERFACE %} {{name}} {% endfor %}" > /tmp/intf_tmp.j2 + INTERFACE=`sonic-cfggen -d -t /tmp/intf_tmp.j2` + echo "{% for (name, prefix) in PORTCHANNEL_INTERFACE %} {{name}} {% endfor %}" > /tmp/pc_intf_tmp.j2 + PC_INTERFACE=`sonic-cfggen -d -t /tmp/pc_intf_tmp.j2` + + ALL_INTERFACE="$INTERFACE $PC_INTERFACE" + for intf in $ALL_INTERFACE; do + ping6cmd="ping6 -I $intf -n -q -i 0 -c 1 -W 0 ff02::1 >/dev/null" + intf_up=$(ip link show $intf | grep "state UP") + if [[ -n "$intf_up" ]]; then + eval $ping6cmd + fi + done + + VLAN=`sonic-cfggen -d -v 'VLAN.keys() | join(" ") if VLAN'` + for vlan in $VLAN; do + # generate a list of arping commands: + # arping -q -w 0 -c 1 -i ; + # arping -q -w 0 -c 1 -i ; + # ... + arpingcmd="sed -e 's/ / -i /' -e 's/^/arping -q -w 0 -c 1 /' -e 's/$/;/'" + ipcmd="ip -4 neigh show | grep $vlan | cut -d ' ' -f 1,3 | $arpingcmd" + + eval `eval $ipcmd` + + # send ipv6 multicast pings to Vlan interfaces to get/refresh link-local addrs + ping6cmd="ping6 -I $vlan -n -q -i 0 -c 1 -W 0 ff02::1 >/dev/null" + eval $ping6cmd + + # generate a list of ndisc6 commands (exclude link-local addrs since it is done above): + # ndisc6 -q -w 0 -1 ; + # ndisc6 -q -w 0 -1 ; + # ... + ndisc6cmd="sed -e 's/^/ndisc6 -q -w 0 -1 /' -e 's/$/;/'" + ip6cmd="ip -6 neigh show | grep -v fe80 | grep $vlan | cut -d ' ' -f 1,3 | $ndisc6cmd" + eval `eval $ip6cmd` + done + sleep 300 +done diff --git a/files/scripts/configdb-load.sh b/files/scripts/configdb-load.sh new file mode 100755 index 000000000000..5ba2e0e0bc7f --- /dev/null +++ b/files/scripts/configdb-load.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# Wait until redis starts +until [[ $(redis-cli ping | grep -c PONG) -gt 0 ]]; do + sleep 1; +done + +# If there is a config db dump file, load it +if [ -r /etc/sonic/config_db.json ]; then + sonic-cfggen -j /etc/sonic/config_db.json --write-to-db +fi + +redis-cli -n 4 SET "CONFIG_DB_INITIALIZED" "1" diff --git a/files/scripts/swss.sh b/files/scripts/swss.sh new file mode 100755 index 000000000000..b5ff18770938 --- /dev/null +++ b/files/scripts/swss.sh @@ -0,0 +1,145 @@ +#!/bin/bash + +SERVICE="swss" +PEER="syncd" +DEBUGLOG="/tmp/swss-syncd-debug.log" +LOCKFILE="/tmp/swss-syncd-lock" + +function debug() +{ + /bin/echo `date` "- $1" >> ${DEBUGLOG} +} + +function lock_service_state_change() +{ + debug "Locking ${LOCKFILE} from ${SERVICE} service" + + exec {LOCKFD}>${LOCKFILE} + /usr/bin/flock -x ${LOCKFD} + trap "/usr/bin/flock -u ${LOCKFD}" 0 2 3 15 + + debug "Locked ${LOCKFILE} (${LOCKFD}) from ${SERVICE} service" +} + +function unlock_service_state_change() +{ + debug "Unlocking ${LOCKFILE} (${LOCKFD}) from ${SERVICE} service" + /usr/bin/flock -u ${LOCKFD} +} + +function check_warm_boot() +{ + SYSTEM_WARM_START=`/usr/bin/redis-cli -n 4 hget "WARM_RESTART|system" enable` + SERVICE_WARM_START=`/usr/bin/redis-cli -n 4 hget "WARM_RESTART|${SERVICE}" enable` + if [[ x"$SYSTEM_WARM_START" == x"true" ]] || [[ x"$SERVICE_WARM_START" == x"true" ]]; then + WARM_BOOT="true" + else + WARM_BOOT="false" + fi +} + +function validate_restore_count() +{ + if [[ x"$WARM_BOOT" == x"true" ]]; then + RESTORE_COUNT=`/usr/bin/redis-cli -n 6 hget "WARM_RESTART_TABLE|orchagent" restore_count` + # We have to make sure db data has not been flushed. + if [[ -z "$RESTORE_COUNT" ]]; then + WARM_BOOT="false" + fi + fi +} + +function wait_for_database_service() +{ + # Wait for redis server start before database clean + until [[ $(/usr/bin/docker exec database redis-cli ping | grep -c PONG) -gt 0 ]]; + do sleep 1; + done + + # Wait for configDB initialization + until [[ $(/usr/bin/docker exec database redis-cli -n 4 GET "CONFIG_DB_INITIALIZED") ]]; + do sleep 1; + done +} + +# This function cleans up the tables with specific prefixes from the database +# $1 the index of the database +# $2 the string of a list of table prefixes +function clean_up_tables() +{ + redis-cli -n $1 EVAL " + local tables = {$2} + for i = 1, table.getn(tables) do + local matches = redis.call('KEYS', tables[i]) + for j,name in ipairs(matches) do + redis.call('DEL', name) + end + end" 0 +} + +start() { + debug "Starting ${SERVICE} service..." + + lock_service_state_change + + wait_for_database_service + check_warm_boot + validate_restore_count + + debug "Warm boot flag: ${SERVICE} ${WARM_BOOT}." + + # Don't flush DB during warm boot + if [[ x"$WARM_BOOT" != x"true" ]]; then + # Don't flush APP_DB during MLNX fastfast boot + BOOT_TYPE="$(cat /proc/cmdline | grep -o 'SONIC_BOOT_TYPE=\S*' | cut -d'=' -f2)" + if [[ x"$BOOT_TYPE" != x"fastfast" ]] && [[ ! -f /var/warmboot/issu_started ]]; then + /usr/bin/docker exec database redis-cli -n 0 FLUSHDB + fi + /usr/bin/docker exec database redis-cli -n 2 FLUSHDB + /usr/bin/docker exec database redis-cli -n 5 FLUSHDB + clean_up_tables 6 "'PORT_TABLE*', 'MGMT_PORT_TABLE*', 'VLAN_TABLE*', 'VLAN_MEMBER_TABLE*', 'INTERFACE_TABLE*', 'MIRROR_SESSION*'" + fi + + # start service docker + /usr/bin/${SERVICE}.sh start + debug "Started ${SERVICE} service..." + + # Unlock has to happen before reaching out to peer service + unlock_service_state_change + + if [[ x"$WARM_BOOT" != x"true" ]]; then + /bin/systemctl start ${PEER} + fi + /usr/bin/${SERVICE}.sh attach +} + +stop() { + debug "Stopping ${SERVICE} service..." + + [[ -f ${LOCKFILE} ]] || /usr/bin/touch ${LOCKFILE} + + lock_service_state_change + check_warm_boot + debug "Warm boot flag: ${SERVICE} ${WARM_BOOT}." + + /usr/bin/${SERVICE}.sh stop + debug "Stopped ${SERVICE} service..." + + # Unlock has to happen before reaching out to peer service + unlock_service_state_change + + # if warm start enabled or peer lock exists, don't stop peer service docker + if [[ x"$WARM_BOOT" != x"true" ]]; then + /bin/systemctl stop ${PEER} + fi +} + +case "$1" in + start|stop) + $1 + ;; + *) + echo "Usage: $0 {start|stop}" + exit 1 + ;; +esac diff --git a/files/scripts/syncd.sh b/files/scripts/syncd.sh new file mode 100755 index 000000000000..ce593d6cbdfb --- /dev/null +++ b/files/scripts/syncd.sh @@ -0,0 +1,146 @@ +#!/bin/bash + +SERVICE="syncd" +PEER="swss" +DEBUGLOG="/tmp/swss-syncd-debug.log" +LOCKFILE="/tmp/swss-syncd-lock" + +function debug() +{ + /bin/echo `date` "- $1" >> ${DEBUGLOG} +} + +function lock_service_state_change() +{ + debug "Locking ${LOCKFILE} from ${SERVICE} service" + + exec {LOCKFD}>${LOCKFILE} + /usr/bin/flock -x ${LOCKFD} + trap "/usr/bin/flock -u ${LOCKFD}" 0 2 3 15 + + debug "Locked ${LOCKFILE} (${LOCKFD}) from ${SERVICE} service" +} + +function unlock_service_state_change() +{ + debug "Unlocking ${LOCKFILE} (${LOCKFD}) from ${SERVICE} service" + /usr/bin/flock -u ${LOCKFD} +} + +function check_warm_boot() +{ + SYSTEM_WARM_START=`/usr/bin/redis-cli -n 4 hget "WARM_RESTART|system" enable` + SERVICE_WARM_START=`/usr/bin/redis-cli -n 4 hget "WARM_RESTART|${SERVICE}" enable` + # SYSTEM_WARM_START could be empty, always make WARM_BOOT meaningful. + if [[ x"$SYSTEM_WARM_START" == x"true" ]] || [[ x"$SERVICE_WARM_START" == x"true" ]]; then + WARM_BOOT="true" + else + WARM_BOOT="false" + fi +} + +function wait_for_database_service() +{ + # Wait for redis server start before database clean + until [[ $(/usr/bin/docker exec database redis-cli ping | grep -c PONG) -gt 0 ]]; + do sleep 1; + done + + # Wait for configDB initialization + until [[ $(/usr/bin/docker exec database redis-cli -n 4 GET "CONFIG_DB_INITIALIZED") ]]; + do sleep 1; + done +} + +start() { + debug "Starting ${SERVICE} service..." + + lock_service_state_change + + mkdir -p /host/warmboot + + wait_for_database_service + check_warm_boot + + debug "Warm boot flag: ${SERVICE} ${WARM_BOOT}." + + if [[ x"$WARM_BOOT" == x"true" ]]; then + # Leave a mark for syncd scripts running inside docker. + touch /host/warmboot/warm-starting + else + rm -f /host/warmboot/warm-starting + + # Flush DB during non-warm start + /usr/bin/docker exec database redis-cli -n 1 FLUSHDB + + # platform specific tasks + if [ x$sonic_asic_platform == x'mellanox' ]; then + export FAST_BOOT=1 + /usr/bin/mst start + /usr/bin/mlnx-fw-upgrade.sh + /etc/init.d/sxdkernel start + /sbin/modprobe i2c-dev + elif [ x$sonic_asic_platform == x'cavium' ]; then + /etc/init.d/xpnet.sh start + fi + fi + + # start service docker + /usr/bin/${SERVICE}.sh start + debug "Started ${SERVICE} service..." + + unlock_service_state_change + /usr/bin/${SERVICE}.sh attach +} + +stop() { + debug "Stopping ${SERVICE} service..." + + lock_service_state_change + check_warm_boot + debug "Warm boot flag: ${SERVICE} ${WARM_BOOT}." + + if [[ x"$WARM_BOOT" == x"true" ]]; then + TYPE=warm + else + TYPE=cold + fi + + debug "${TYPE} shutdown syncd process ..." + /usr/bin/docker exec -i syncd /usr/bin/syncd_request_shutdown --${TYPE} + + # wait until syncd quits gracefully + while docker top syncd | grep -q /usr/bin/syncd; do + sleep 0.1 + done + + /usr/bin/docker exec -i syncd /bin/sync + debug "Finished ${TYPE} shutdown syncd process ..." + + /usr/bin/${SERVICE}.sh stop + debug "Stopped ${SERVICE} service..." + + # if warm start enabled, don't stop peer service docker + if [[ x"$WARM_BOOT" != x"true" ]]; then + # platform specific tasks + if [ x$sonic_asic_platform == x'mellanox' ]; then + /etc/init.d/sxdkernel stop + /usr/bin/mst stop + elif [ x$sonic_asic_platform == x'cavium' ]; then + /etc/init.d/xpnet.sh stop + /etc/init.d/xpnet.sh start + fi + fi + + unlock_service_state_change +} + +case "$1" in + start|stop) + $1 + ;; + *) + echo "Usage: $0 {start|stop}" + exit 1 + ;; +esac diff --git a/files/sources.list b/files/sources.list deleted file mode 100644 index d2aaf4251bb3..000000000000 --- a/files/sources.list +++ /dev/null @@ -1,8 +0,0 @@ -deb http://httpredir.debian.org/debian jessie main contrib non-free -deb-src http://httpredir.debian.org/debian jessie main contrib non-free - -deb http://httpredir.debian.org/debian jessie-updates main contrib non-free -deb-src http://httpredir.debian.org/debian jessie-updates main contrib non-free - -deb http://security.debian.org/ jessie/updates main contrib non-free -deb-src http://security.debian.org/ jessie/updates main contrib non-free diff --git a/files/sshd/host-ssh-keygen.sh b/files/sshd/host-ssh-keygen.sh new file mode 100755 index 000000000000..ade24e6383de --- /dev/null +++ b/files/sshd/host-ssh-keygen.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +[ -r /etc/ssh/ssh_host_rsa_key ] || { + rm -f /etc/ssh/ssh_host_*_key* + /usr/bin/ssh-keygen -t rsa -N '' -f /etc/ssh/ssh_host_rsa_key + /usr/bin/ssh-keygen -t dsa -N '' -f /etc/ssh/ssh_host_dsa_key + /usr/bin/ssh-keygen -t rsa1 -N '' -f /etc/ssh/ssh_host_key + /usr/bin/ssh-keygen -t ecdsa -N '' -f /etc/ssh/ssh_host_ecdsa_key + /usr/bin/ssh-keygen -t ed25519 -N '' -f /etc/ssh/ssh_host_ed25519_key +} diff --git a/files/sshd/sshd.service b/files/sshd/sshd.service new file mode 100644 index 000000000000..d79c574da516 --- /dev/null +++ b/files/sshd/sshd.service @@ -0,0 +1,16 @@ +[Unit] +Description=OpenBSD Secure Shell server +After=network.target auditd.service +ConditionPathExists=!/etc/ssh/sshd_not_to_be_run + +[Service] +EnvironmentFile=-/etc/default/ssh +ExecStartPre=-/usr/local/bin/host-ssh-keygen.sh +ExecStart=/usr/sbin/sshd -D $SSHD_OPTS +ExecReload=/bin/kill -HUP $MAINPID +KillMode=process +Restart=on-failure + +[Install] +WantedBy=multi-user.target +Alias=sshd.service diff --git a/functions.sh b/functions.sh index b9e7ee0b55e6..45812a8dab75 100644 --- a/functions.sh +++ b/functions.sh @@ -36,3 +36,33 @@ die() { warn "$message" exit 1 } + +docker_try_rmi() { + local image_name="$1" + ## Note: inspect output has quotation characters, so sed to remove it as an argument + local image_id=$(docker inspect --format="{{json .Id}}" $image_name | sed -e 's/^"//' -e 's/"$//') + [ -z "$image_id" ] || { + ## Remove all the exited containers from this image + docker ps -a -q -f "status=exited" -f "ancestor=$1" | xargs --no-run-if-empty docker rm + ## Note: If there are running containers from this image, the build system is in an + ## unexpected state. The 'rmi' will fail and we need investigate the build environment. + docker rmi $image_name + } +} + +sonic_get_version() { + local describe=$(git describe --tags) + local latest_tag=$(git describe --tags --abbrev=0) + local branch_name=$(git rev-parse --abbrev-ref HEAD) + if [ -n "$(git status --untracked-files=no -s --ignore-submodules)" ]; then + local dirty="-dirty-$BUILD_TIMESTAMP" + fi + BUILD_NUMBER=${BUILD_NUMBER:-0} + ## Check if we are on tagged commit + ## Note: escape the version string by sed: / -> _ + if [ "$describe" == "$latest_tag" ]; then + echo "${latest_tag}${dirty}" | sed 's/\//_/g' + else + echo "${branch_name}.${BUILD_NUMBER}${dirty:--$(git rev-parse --short HEAD)}" | sed 's/\//_/g' + fi +} diff --git a/get_deps.sh b/get_deps.sh deleted file mode 100755 index 145caf620af9..000000000000 --- a/get_deps.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -## This script is to build the dependencies of an ONIE installer image -## -## USAGE: -## ./get_deps.sh - -# Obtaining the initramfs-tools -rm -rf deps/initramfs-tools -git clone --branch v0.120 https://anonscm.debian.org/git/kernel/initramfs-tools.git deps/initramfs-tools - -# Patch -pushd deps/initramfs-tools -patch -p1 < $OLDPWD/patch/initramfs-tools/loopback-file-system-support.patch - -# Build the package -fakeroot debian/rules clean -fakeroot debian/rules binary - -popd diff --git a/get_docker-base.sh b/get_docker-base.sh new file mode 100755 index 000000000000..ff2bdeaff02b --- /dev/null +++ b/get_docker-base.sh @@ -0,0 +1,21 @@ +#!/bin/bash +## This script is to retrieve and import the docker-base image from +## local folder where the image is built on the local machine +## +## USAGE: +## ./get_docker-base.sh + +set -x -e + +. ./functions.sh + +TARGET_PATH=$(sed -n 's/TARGET_PATH\s*=\s*//p' slave.mk) + +## [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Read-only link of Azure Blob storage with shared access signature (SAS)")] +BASE_URL="https://sonicstorage.blob.core.windows.net/packages/docker-base.ea507753d98b0769e2a15be13003331f8ad38d1c15b40a683e05fc53b1463b10.gz?sv=2015-04-05&sr=b&sig=YNN6eYVMEFndUaiHIRnqcZFdDZwIG%2BaAuVj0IoyDWPw%3D&se=2026-10-27T20%3A46%3A18Z&sp=r" + +base_image_name=docker-base +docker_try_rmi $base_image_name +mkdir -p $TARGET_PATH +wget --no-use-server-timestamps -O $TARGET_PATH/$base_image_name.gz "$BASE_URL" +docker load < $TARGET_PATH/$base_image_name.gz diff --git a/installer/sharch_body.sh b/installer/sharch_body.sh index 8260d0fd00e6..d22fe26b6998 100644 --- a/installer/sharch_body.sh +++ b/installer/sharch_body.sh @@ -27,6 +27,7 @@ echo " OK." # Untar and launch install script in a tmpfs cur_wd=$(pwd) +export cur_wd archive_path=$(realpath "$0") tmp_dir=$(mktemp -d) if [ "$(id -u)" = "0" ] ; then diff --git a/installer/x86_64/install.sh b/installer/x86_64/install.sh index 528c14727280..e39ed9727473 100755 --- a/installer/x86_64/install.sh +++ b/installer/x86_64/install.sh @@ -5,10 +5,6 @@ # # SPDX-License-Identifier: GPL-2.0 -# Function definitions -# wc -l -line_count() { return $(echo $1 | wc -l); } - # Appends a command to a trap, which is needed because default trap behavior is to replace # previous trap for the same signal # - 1st arg: code to add @@ -28,8 +24,25 @@ _trap_push true set -e cd $(dirname $0) +if [ -d "/etc/sonic" ]; then + echo "Installing SONiC in SONiC" + install_env="sonic" +elif grep -Fxqs "DISTRIB_ID=onie" /etc/lsb-release > /dev/null +then + echo "Installing SONiC in ONIE" + install_env="onie" +else + echo "Installing SONiC in BUILD" + install_env="build" +fi + +if [ -r ./machine.conf ]; then . ./machine.conf +fi + +if [ -r ./onie-image.conf ]; then . ./onie-image.conf +fi echo "ONIE Installer: platform: $platform" @@ -39,59 +52,90 @@ if [ $(id -u) -ne 0 ] exit 1 fi -# Install demo on same block device as ONIE -onie_dev=$(blkid | grep ONIE-BOOT | head -n 1 | awk '{print $1}' | sed -e 's/:.*$//') -blk_dev=$(echo $onie_dev | sed -e 's/[1-9][0-9]*$//' | sed -e 's/\([0-9]\)\(p\)/\1/') -# Note: ONIE has no mount setting for / with device node, so below will be empty string -cur_part=$(cat /proc/mounts | awk "{ if(\$2==\"/\") print \$1 }" | grep $blk_dev || true) - -[ -b "$blk_dev" ] || { - echo "Error: Unable to determine block device of ONIE install" +# get running machine from conf file +if [ -r /etc/machine.conf ]; then + . /etc/machine.conf +elif [ -r /host/machine.conf ]; then + . /host/machine.conf +elif [ "$install_env" != "build" ]; then + echo "cannot find machine.conf" exit 1 -} +fi + +echo "onie_platform: $onie_platform" + +# Get platform specific linux kernel command line arguments +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="" + +# Default var/log device size in MB +VAR_LOG_SIZE=4096 + +[ -r platforms/$onie_platform ] && . platforms/$onie_platform + +# Pick up console port and speed from install enviroment if not defined yet. +# Console port and speed setting in cmdline is like "console=ttyS0,9600n", +# so we can use pattern 'console=ttyS[0-9]+,[0-9]+' to match it. +# If failed to get the speed and ttyS from cmdline then set them to default: ttyS0 and 9600 +if [ -z "$CONSOLE_PORT" ]; then + console_ttys=$(cat /proc/cmdline | grep -Eo 'console=ttyS[0-9]+' | cut -d "=" -f2) + if [ -z "$console_ttys" -o "$console_ttys" = "ttyS0" ]; then + CONSOLE_PORT=0x3f8 + CONSOLE_DEV=0 + elif [ "$console_ttys" = "ttyS1" ]; then + CONSOLE_PORT=0x2f8 + CONSOLE_DEV=1 + elif [ "$console_ttys" = "ttyS2" ]; then + CONSOLE_PORT=0x3e8 + CONSOLE_DEV=2 + elif [ "$console_ttys" = "ttyS3" ]; then + CONSOLE_PORT=0x2e8 + CONSOLE_DEV=3 + fi +fi + +if [ -z "$CONSOLE_SPEED" ]; then + speed=$(cat /proc/cmdline | grep -Eo 'console=ttyS[0-9]+,[0-9]+' | cut -d "," -f2) + if [ -z "$speed" ]; then + CONSOLE_SPEED=9600 + else + CONSOLE_SPEED=$speed + fi +fi + +# Install demo on same block device as ONIE +if [ "$install_env" != "build" ]; then + onie_dev=$(blkid | grep ONIE-BOOT | head -n 1 | awk '{print $1}' | sed -e 's/:.*$//') + blk_dev=$(echo $onie_dev | sed -e 's/[1-9][0-9]*$//' | sed -e 's/\([0-9]\)\(p\)/\1/') + # Note: ONIE has no mount setting for / with device node, so below will be empty string + cur_part=$(cat /proc/mounts | awk "{ if(\$2==\"/\") print \$1 }" | grep $blk_dev || true) + + [ -b "$blk_dev" ] || { + echo "Error: Unable to determine block device of ONIE install" + exit 1 + } +fi # If running in ONIE -if [ "$onie_dev" = "$cur_part" ] || [ -z "$cur_part" ]; then +if [ "$install_env" = "onie" ]; then # The onie bin tool prefix onie_bin= # The persistent ONIE directory location onie_root_dir=/mnt/onie-boot/onie # The onie file system root onie_initrd_tmp=/ -# Else running in normal Linux -else - # Mount ONIE-BOOT partition - onie_mnt=$(mktemp -d) || { - echo "Error: Unable to create file system mount point" - exit 1 - } - trap_push "fuser -km $onie_mnt || umount $onie_mnt || rmdir $onie_mnt || true" - mount $onie_dev $onie_mnt - onie_root_dir=$onie_mnt/onie - - # Mount initrd inside ONIE-BOOT partition - onie_initrd_tmp=$(mktemp -d) || { - echo "Error: Unable to create file system mount point" - exit 1 - } - trap_push "rm -rf $onie_initrd_tmp || true" - cd $onie_initrd_tmp - # Note: use wildcard in filename below to prevent hard-code version - cat $onie_mnt/onie/initrd.img-*-onie | unxz | cpio -id - cd - - onie_bin="chroot $onie_initrd_tmp" fi # The build system prepares this script by replacing %%DEMO-TYPE%% # with "OS" or "DIAG". demo_type="%%DEMO_TYPE%%" -# The build system prepares this script by replacing %%GIT_REVISION%% +# The build system prepares this script by replacing %%IMAGE_VERSION%% # with git revision hash as a version identifier -git_revision="%%GIT_REVISION%%" +image_version="%%IMAGE_VERSION%%" +timestamp="$(date -u +%Y%m%d)" -demo_volume_label="ACS-${demo_type}" -demo_volume_revision_label="ACS-${demo_type}-${git_revision}" +demo_volume_label="SONiC-${demo_type}" +demo_volume_revision_label="SONiC-${demo_type}-${image_version}" # auto-detect whether BIOS or UEFI if [ -d "/sys/firmware/efi/efivars" ] ; then @@ -100,19 +144,21 @@ else firmware="bios" fi -# determine ONIE partition type -onie_partition_type=$(${onie_bin} onie-sysinfo -t) -# demo partition size in MB -demo_part_size="%%ONIE_IMAGE_PART_SIZE%%" -if [ "$firmware" = "uefi" ] ; then - create_demo_partition="create_demo_uefi_partition" -elif [ "$onie_partition_type" = "gpt" ] ; then - create_demo_partition="create_demo_gpt_partition" -elif [ "$onie_partition_type" = "msdos" ] ; then - create_demo_partition="create_demo_msdos_partition" -else - echo "ERROR: Unsupported partition type: $onie_partition_type" - exit 1 +if [ "$install_env" = "onie" ]; then + # determine ONIE partition type + onie_partition_type=$(${onie_bin} onie-sysinfo -t) + # demo partition size in MB + demo_part_size="%%ONIE_IMAGE_PART_SIZE%%" + if [ "$firmware" = "uefi" ] ; then + create_demo_partition="create_demo_uefi_partition" + elif [ "$onie_partition_type" = "gpt" ] ; then + create_demo_partition="create_demo_gpt_partition" + elif [ "$onie_partition_type" = "msdos" ] ; then + create_demo_partition="create_demo_msdos_partition" + else + echo "ERROR: Unsupported partition type: $onie_partition_type" + exit 1 + fi fi # Creates a new partition for the DEMO OS. @@ -121,6 +167,8 @@ fi # # Returns the created partition number in $demo_part demo_part="" +# TODO: remove reference to "ACS-OS" after all baseimages are upgraded +legacy_volume_label="ACS-OS" create_demo_gpt_partition() { blk_dev="$1" @@ -131,7 +179,7 @@ create_demo_gpt_partition() mkfifo -m 600 "$tmpfifo" # See if demo partition already exists - demo_part=$(sgdisk -p $blk_dev | grep "$demo_volume_label" | awk '{print $1}') + demo_part=$(sgdisk -p $blk_dev | grep -e "$demo_volume_label" -e "$legacy_volume_label" | awk '{print $1}') if [ -n "$demo_part" ] ; then # delete existing partitions # if there are multiple partitions matched, we should delete each one, except the current OS's @@ -140,11 +188,21 @@ create_demo_gpt_partition() while read -r part_index; do if [ "$blk_dev$part_index" = "$cur_part" ]; then continue; fi echo "deleting partition $part_index ..." + # if the partition is already mounted, umount first + df $blk_dev$part_index 2>/dev/null && { + umount $blk_dev$part_index || { + echo "Error: Unable to umount $blk_dev$part_index" + exit 1 + } + } sgdisk -d $part_index $blk_dev || { echo "Error: Unable to delete partition $part_index on $blk_dev" exit 1 } - partprobe + partprobe || { + echo "Error: Unable to partprobe" + exit 1 + } done < $tmpfifo fi @@ -178,13 +236,14 @@ create_demo_gpt_partition() fi sgdisk --new=${demo_part}::+${demo_part_size}MB \ --attributes=${demo_part}:=:$attr_bitmask \ - --change-name=${demo_part}:$demo_volume_revision_label $blk_dev \ + --change-name=${demo_part}:$demo_volume_label $blk_dev \ || { + echo "Warning: The first trial of creating partition failed, trying the largest aligned available block of sectors on the disk" begin=$(sgdisk -F $blk_dev) end=$(sgdisk -E $blk_dev) sgdisk --new=${demo_part}:$begin:$end \ --attributes=${demo_part}:=:$attr_bitmask \ - --change-name=${demo_part}:$demo_volume_revision_label $blk_dev + --change-name=${demo_part}:$demo_volume_label $blk_dev } || { echo "Error: Unable to create partition $demo_part on $blk_dev" exit 1 @@ -202,7 +261,7 @@ create_demo_msdos_partition() # See if demo partition already exists -- look for the filesystem # label. - part_info="$(blkid | grep $demo_volume_label | awk -F: '{print $1}')" + part_info="$(blkid | grep -e "$demo_volume_label" -e "$legacy_volume_label" | awk -F: '{print $1}')" if [ -n "$part_info" ] ; then # delete existing partition demo_part="$(echo -n $part_info | sed -e s#${blk_dev}##)" @@ -245,7 +304,7 @@ create_demo_uefi_partition() create_demo_gpt_partition "$1" # erase any related EFI BootOrder variables from NVRAM. - for b in $(efibootmgr | grep "$demo_volume_label" | awk '{ print $1 }') ; do + for b in $(efibootmgr | grep -e "$demo_volume_label" -e "$legacy_volume_label" | awk '{ print $1 }') ; do local num=${b#Boot} # Remove trailing '*' num=${num%\*} @@ -297,6 +356,7 @@ demo_install_grub() cat $grub_install_log && rm -f $grub_install_log exit 1 } + rm -f $grub_install_log # restore immutable flag on the core.img file as discussed @@ -336,7 +396,7 @@ demo_install_uefi_grub() grub_install_log=$(mktemp) grub-install \ --no-nvram \ - --bootloader-id="$onie_initrd_tmp/$demo_volume_label" \ + --bootloader-id="$demo_volume_label" \ --efi-directory="/boot/efi" \ --boot-directory="$demo_mnt" \ --recheck \ @@ -359,35 +419,97 @@ demo_install_uefi_grub() } -eval $create_demo_partition $blk_dev -demo_dev=$(echo $blk_dev | sed -e 's/\(mmcblk[0-9]\)/\1p/')$demo_part +image_dir="image-$image_version" -# Make filesystem -mkfs.ext4 -L $demo_volume_revision_label $demo_dev +if [ "$install_env" = "onie" ]; then + eval $create_demo_partition $blk_dev + demo_dev=$(echo $blk_dev | sed -e 's/\(mmcblk[0-9]\)/\1p/')$demo_part -# Mount demo filesystem -demo_mnt=$(${onie_bin} mktemp -d) || { - echo "Error: Unable to create file system mount point" - exit 1 -} -trap_push "${onie_bin} fuser -km $demo_mnt || ${onie_bin} umount $demo_mnt || ${onie_bin} rmdir $demo_mnt || true" -${onie_bin} mount -t ext4 -o defaults,rw $demo_dev $demo_mnt || { - echo "Error: Unable to mount $demo_dev on $demo_mnt" - exit 1 -} + # Make filesystem + mkfs.ext4 -L $demo_volume_label $demo_dev -# Decompress the file for the file system directly to the partition -unzip $ONIE_INSTALLER_PAYLOAD -d $demo_mnt + # Mount demo filesystem + demo_mnt=$(${onie_bin} mktemp -d) || { + echo "Error: Unable to create file system mount point" + exit 1 + } + trap_push "${onie_bin} fuser -km $demo_mnt || ${onie_bin} umount $demo_mnt || ${onie_bin} rmdir $demo_mnt || true" + ${onie_bin} mount -t ext4 -o defaults,rw $demo_dev $demo_mnt || { + echo "Error: Unable to mount $demo_dev on $demo_mnt" + exit 1 + } + +elif [ "$install_env" = "sonic" ]; then + demo_mnt="/host" + eval running_sonic_revision=$(cat /etc/sonic/sonic_version.yml | grep build_version | cut -f2 -d" ") + # Prevent installing existing SONiC if it is running + if [ "$image_dir" = "image-$running_sonic_revision" ]; then + echo "Not installing SONiC version $running_sonic_revision, as current running SONiC has the same version" + exit 0 + fi + # Remove extra SONiC images if any + for f in $demo_mnt/image-* ; do + if [ -d $f ] && [ "$f" != "$demo_mnt/image-$running_sonic_revision" ] && [ "$f" != "$demo_mnt/$image_dir" ]; then + echo "Removing old SONiC installation $f" + rm -rf $f + fi + done +else + demo_mnt="build_raw_image_mnt" + demo_dev=$cur_wd/"%%OUTPUT_RAW_IMAGE%%" + + mkfs.ext4 -L $demo_volume_label $demo_dev + + echo "Mounting $demo_dev on $demo_mnt..." + mkdir $demo_mnt + mount -t auto -o loop $demo_dev $demo_mnt +fi + +echo "Installing SONiC to $demo_mnt/$image_dir" + +# Create target directory or clean it up if exists +if [ -d $demo_mnt/$image_dir ]; then + echo "Directory $demo_mnt/$image_dir/ already exists. Cleaning up..." + rm -rf $demo_mnt/$image_dir/* +else + mkdir $demo_mnt/$image_dir || { + echo "Error: Unable to create SONiC directory" + exit 1 + } +fi -# store installation log in demo file system -rm -f $onie_initrd_tmp/tmp/onie-support.tar.bz2 -${onie_bin} onie-support /tmp -mv $onie_initrd_tmp/tmp/onie-support.tar.bz2 $demo_mnt +# Decompress the file for the file system directly to the partition +unzip -o $ONIE_INSTALLER_PAYLOAD -x "$FILESYSTEM_DOCKERFS" -d $demo_mnt/$image_dir -if [ "$firmware" = "uefi" ] ; then - demo_install_uefi_grub "$demo_mnt" "$blk_dev" +if [ "$install_env" = "onie" ]; then + TAR_EXTRA_OPTION="--numeric-owner" else - demo_install_grub "$demo_mnt" "$blk_dev" + TAR_EXTRA_OPTION="--numeric-owner --warning=no-timestamp" +fi +mkdir -p $demo_mnt/$image_dir/$DOCKERFS_DIR +unzip -op $ONIE_INSTALLER_PAYLOAD "$FILESYSTEM_DOCKERFS" | tar xz $TAR_EXTRA_OPTION -f - -C $demo_mnt/$image_dir/$DOCKERFS_DIR + +if [ "$install_env" = "onie" ]; then + # Store machine description in target file system + if [ -f /etc/machine-build.conf ]; then + # onie_ variable are generate at runtime. + # they are no longer hardcoded in /etc/machine.conf + # also remove single quotes around the value + set | grep ^onie | sed -e "s/='/=/" -e "s/'$//" > $demo_mnt/machine.conf + else + cp /etc/machine.conf $demo_mnt + fi + + # Store installation log in target file system + rm -f $onie_initrd_tmp/tmp/onie-support*.tar.bz2 + ${onie_bin} onie-support /tmp + mv $onie_initrd_tmp/tmp/onie-support*.tar.bz2 $demo_mnt/$image_dir/ + + if [ "$firmware" = "uefi" ] ; then + demo_install_uefi_grub "$demo_mnt" "$blk_dev" + else + demo_install_grub "$demo_mnt" "$blk_dev" + fi fi # Create a minimal grub.cfg that allows for: @@ -408,8 +530,8 @@ trap_push "rm $grub_cfg || true" [ -r ./platform.conf ] && . ./platform.conf -DEFAULT_GRUB_SERIAL_COMMAND="serial --port=%%CONSOLE_PORT%% --speed=%%CONSOLE_SPEED%% --word=8 --parity=no --stop=1" -DEFAULT_GRUB_CMDLINE_LINUX="console=tty0 console=ttyS%%CONSOLE_DEV%%,%%CONSOLE_SPEED%%n8 quiet" +DEFAULT_GRUB_SERIAL_COMMAND="serial --port=${CONSOLE_PORT} --speed=${CONSOLE_SPEED} --word=8 --parity=no --stop=1" +DEFAULT_GRUB_CMDLINE_LINUX="console=tty0 console=ttyS${CONSOLE_DEV},${CONSOLE_SPEED}n8 quiet" GRUB_SERIAL_COMMAND=${GRUB_SERIAL_COMMAND:-"$DEFAULT_GRUB_SERIAL_COMMAND"} GRUB_CMDLINE_LINUX=${GRUB_CMDLINE_LINUX:-"$DEFAULT_GRUB_CMDLINE_LINUX"} export GRUB_SERIAL_COMMAND @@ -425,11 +547,14 @@ set timeout=5 EOF -# Add the logic to support grub-reboot +# Add the logic to support grub-reboot and grub-set-default cat <> $grub_cfg if [ -s \$prefix/grubenv ]; then load_env fi +if [ "\${saved_entry}" ] ; then + set default="\${saved_entry}" +fi if [ "\${next_entry}" ] ; then set default="\${next_entry}" set next_entry= @@ -450,27 +575,54 @@ fi # Add a menu entry for the DEMO OS # Note: assume that apparmor is supported in the kernel demo_grub_entry="$demo_volume_revision_label" +if [ "$install_env" = "sonic" ]; then + old_sonic_menuentry=$(cat /host/grub/grub.cfg | sed "/$running_sonic_revision/,/}/!d") + demo_dev=$(echo $old_sonic_menuentry | sed -e "s/.*root\=\(.*\)rw.*/\1/") + onie_menuentry=$(cat /host/grub/grub.cfg | sed "/menuentry ONIE/,/}/!d") +fi + +if [ "$install_env" = "build" ]; then + grub_cfg_root=%%SONIC_ROOT%% +else + grub_cfg_root=$demo_dev +fi + cat <> $grub_cfg menuentry '$demo_grub_entry' { - search --no-floppy --label --set=root $demo_volume_revision_label - echo 'Loading $demo_volume_revision_label $demo_type kernel ...' + search --no-floppy --label --set=root $demo_volume_label + echo 'Loading $demo_volume_label $demo_type kernel ...' insmod gzio if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_msdos insmod ext2 - linux /boot/vmlinuz-3.16.0-4-amd64 root=$demo_dev rw $GRUB_CMDLINE_LINUX \ - loop=$FILESYSTEM_SQUASHFS loopfstype=squashfs \ - apparmor=1 security=apparmor - echo 'Loading $demo_volume_revision_label $demo_type initial ramdisk ...' - initrd /boot/initrd.img-3.16.0-4-amd64 + linux /$image_dir/boot/vmlinuz-4.9.0-7-amd64 root=$grub_cfg_root rw $GRUB_CMDLINE_LINUX \ + net.ifnames=0 biosdevname=0 \ + loop=$image_dir/$FILESYSTEM_SQUASHFS loopfstype=squashfs \ + apparmor=1 security=apparmor varlog_size=$VAR_LOG_SIZE usbcore.autosuspend=-1 $ONIE_PLATFORM_EXTRA_CMDLINE_LINUX + echo 'Loading $demo_volume_label $demo_type initial ramdisk ...' + initrd /$image_dir/boot/initrd.img-4.9.0-7-amd64 } EOF -# Add menu entries for ONIE -- use the grub fragment provided by the -# ONIE distribution. -$onie_root_dir/grub.d/50_onie_grub >> $grub_cfg +if [ "$install_env" = "onie" ]; then + # Add menu entries for ONIE -- use the grub fragment provided by the + # ONIE distribution. + $onie_root_dir/grub.d/50_onie_grub >> $grub_cfg + mkdir -p $onie_initrd_tmp/$demo_mnt/grub +else +cat <> $grub_cfg +$old_sonic_menuentry +$onie_menuentry +EOF +fi -mkdir -p $onie_initrd_tmp/$demo_mnt/grub -cp $grub_cfg $onie_initrd_tmp/$demo_mnt/grub/grub.cfg +if [ "$install_env" = "build" ]; then + cp $grub_cfg $demo_mnt/grub.cfg + umount $demo_mnt +else + cp $grub_cfg $onie_initrd_tmp/$demo_mnt/grub/grub.cfg +fi cd / + +echo "Installed SONiC base image $demo_volume_label successfully" diff --git a/onie-image.conf b/onie-image.conf index 25c631563cd9..1d7c6f1e8aa5 100644 --- a/onie-image.conf +++ b/onie-image.conf @@ -1,5 +1,5 @@ ## DESCRIPTION: -## partition related config +## config for ONIE image ## ## Partition size in MB @@ -18,5 +18,29 @@ FILESYSTEM_SQUASHFS=fs.squashfs ## Filename for onie installer payload, will be the main part of onie installer ONIE_INSTALLER_PAYLOAD=fs.zip +## Filename for docker file system +FILESYSTEM_DOCKERFS=dockerfs.tar.gz + +## docker directory on the root filesystem +DOCKERFS_DIR=docker + ## Output file name for onie installer -OUTPUT_ONIE_IMAGE=acs-$TARGET_MACHINE.bin +OUTPUT_ONIE_IMAGE=target/sonic-$TARGET_MACHINE.bin + +## Output file name for raw image +OUTPUT_RAW_IMAGE=target/sonic-$TARGET_MACHINE.raw + +## Raw image size in MB +RAW_IMAGE_DISK_SIZE=1024 + +## Output file name for kvm image +OUTPUT_KVM_IMAGE=target/sonic-$TARGET_MACHINE.img + +## Kvm image size in GB +KVM_IMAGE_DISK_SIZE=16 + +## Output file name for aboot installer +OUTPUT_ABOOT_IMAGE=target/sonic-aboot-$TARGET_MACHINE.swi + +## Aboot boot image name +ABOOT_BOOT_IMAGE=.sonic-boot.swi diff --git a/onie-mk-demo.sh b/onie-mk-demo.sh index 3dd81b876fd6..b8418d79a678 100755 --- a/onie-mk-demo.sh +++ b/onie-mk-demo.sh @@ -12,7 +12,7 @@ installer_dir=$4 platform_conf=$5 output_file=$6 demo_type=$7 -git_revision=$8 +image_version=$8 onie_image_part_size=$9 shift 9 @@ -29,7 +29,7 @@ if [ ! -d $installer_dir/$arch ] || \ exit 1 fi -[ -n "$git_revision" ] || { +[ -n "$image_version" ] || { echo "Error: Invalid git revisions" exit 1 } @@ -39,11 +39,6 @@ fi exit 1 } -[ -n "$CONSOLE_SPEED" ] || { - echo "Error: Invalid CONSOLE_SPEED" - exit 1 -} - [ -r "$platform_conf" ] || { echo "Error: Unable to read installer platform configuration file: $platform_conf" exit 1 @@ -81,22 +76,23 @@ tmp_dir=$(mktemp --directory) tmp_installdir="$tmp_dir/installer" mkdir $tmp_installdir || clean_up 1 -cp $installer_dir/$arch/install.sh $tmp_installdir || clean_up 1 +cp -r $installer_dir/$arch/* $tmp_installdir || clean_up 1 cp onie-image.conf $tmp_installdir # Escape special chars in the user provide kernel cmdline string for use in # sed. Special chars are: \ / & EXTRA_CMDLINE_LINUX=`echo $EXTRA_CMDLINE_LINUX | sed -e 's/[\/&]/\\\&/g'` +output_raw_image=$(cat onie-image.conf | grep OUTPUT_RAW_IMAGE | cut -f2 -d"=") +[ -z "$TARGET_MACHINE" ] && output_raw_image=$(echo $output_raw_image | sed -e 's/$TARGET_MACHINE/$machine/g') +output_raw_image=$(eval echo $output_raw_image) + # Tailor the demo installer for OS mode or DIAG mode sed -i -e "s/%%DEMO_TYPE%%/$demo_type/g" \ - -e "s/%%GIT_REVISION%%/$git_revision/g" \ + -e "s/%%IMAGE_VERSION%%/$image_version/g" \ -e "s/%%ONIE_IMAGE_PART_SIZE%%/$onie_image_part_size/" \ - -e "s/%%CONSOLE_SPEED%%/$CONSOLE_SPEED/g" \ - -e "s/%%CONSOLE_DEV%%/$CONSOLE_DEV/g" \ - -e "s/%%CONSOLE_FLAG%%/$CONSOLE_FLAG/g" \ - -e "s/%%CONSOLE_PORT%%/$CONSOLE_PORT/g" \ -e "s/%%EXTRA_CMDLINE_LINUX%%/$EXTRA_CMDLINE_LINUX/" \ + -e "s@%%OUTPUT_RAW_IMAGE%%@$output_raw_image@" \ $tmp_installdir/install.sh || clean_up 1 echo -n "." cp -r $* $tmp_installdir || clean_up 1 diff --git a/platform/barefoot/bfn-modules.mk b/platform/barefoot/bfn-modules.mk new file mode 100644 index 000000000000..67b7fa924da1 --- /dev/null +++ b/platform/barefoot/bfn-modules.mk @@ -0,0 +1,10 @@ +# BFN Platform modules + +VERSION = 1.0 + +BFN_MODULE = bfn-modules_$(VERSION)_amd64.deb +$(BFN_MODULE)_SRC_PATH = $(PLATFORM_PATH)/bfn-modules +$(BFN_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_DPKG_DEBS += $(BFN_MODULE) + +SONIC_STRETCH_DEBS += $(BFN_MODULE) diff --git a/platform/barefoot/bfn-modules/LICENSE b/platform/barefoot/bfn-modules/LICENSE new file mode 100644 index 000000000000..e9d73a1c63cc --- /dev/null +++ b/platform/barefoot/bfn-modules/LICENSE @@ -0,0 +1,37 @@ +BAREFOOT NETWORKS CONFIDENTIAL & PROPRIETARY + + Copyright (c) 2015-2016 Barefoot Networks, Inc. + + All Rights Reserved. + + NOTICE: All information contained herein is, and remains the property of + Barefoot Networks, Inc. and its suppliers, if any. The intellectual and + technical concepts contained herein are proprietary to Barefoot Networks, + Inc. + and its suppliers and may be covered by U.S. and Foreign Patents, patents in + process, and are protected by trade secret or copyright law. + Dissemination of this information or reproduction of this material is + strictly forbidden unless prior written permission is obtained from + Barefoot Networks, Inc. + + No warranty, explicit or implicit is provided, unless granted under a + written agreement with Barefoot Networks, Inc. + + +GPL LICENSE SUMMARY + + Copyright(c) 2015 Barefoot Networks. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the... + + diff --git a/platform/barefoot/bfn-modules/MAINTAINERS b/platform/barefoot/bfn-modules/MAINTAINERS new file mode 100644 index 000000000000..b9c62ce01546 --- /dev/null +++ b/platform/barefoot/bfn-modules/MAINTAINERS @@ -0,0 +1,4 @@ +# This file describes the maintainers for sonic-platform-modules-bfn +# See the SONiC project governance document for more information + +Mailinglist = sonicproject@googlegroups.com diff --git a/platform/barefoot/bfn-modules/README.md b/platform/barefoot/bfn-modules/README.md new file mode 100644 index 000000000000..6c47cbed2a5d --- /dev/null +++ b/platform/barefoot/bfn-modules/README.md @@ -0,0 +1,2 @@ +# bfn-modules +Device drivers for support of BFN platform for the SONiC project diff --git a/platform/barefoot/bfn-modules/debian/changelog b/platform/barefoot/bfn-modules/debian/changelog new file mode 100644 index 000000000000..85ab933da304 --- /dev/null +++ b/platform/barefoot/bfn-modules/debian/changelog @@ -0,0 +1,5 @@ +bfn-modules (1.0) unstable; urgency=low + + * Initial release + + -- Support Mon, 22 Oct 2018 11:11:11 -0800 diff --git a/platform/barefoot/bfn-modules/debian/compat b/platform/barefoot/bfn-modules/debian/compat new file mode 100644 index 000000000000..45a4fb75db86 --- /dev/null +++ b/platform/barefoot/bfn-modules/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/barefoot/bfn-modules/debian/control b/platform/barefoot/bfn-modules/debian/control new file mode 100644 index 000000000000..7e0ae5cf5003 --- /dev/null +++ b/platform/barefoot/bfn-modules/debian/control @@ -0,0 +1,12 @@ +Source: bfn-modules +Section: main +Priority: extra +Maintainer: support +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: bfn-modules +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for bfn asic for mmap + diff --git a/platform/barefoot/bfn-modules/debian/copyright b/platform/barefoot/bfn-modules/debian/copyright new file mode 100644 index 000000000000..ade42b7aa75a --- /dev/null +++ b/platform/barefoot/bfn-modules/debian/copyright @@ -0,0 +1,15 @@ +Provides linux kernel driver for BF PCIe devices + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/bfn-modules/debian/files b/platform/barefoot/bfn-modules/debian/files new file mode 100644 index 000000000000..cffeb8a7d9c9 --- /dev/null +++ b/platform/barefoot/bfn-modules/debian/files @@ -0,0 +1 @@ +bfn-modules_1.0_amd64.deb main extra diff --git a/platform/barefoot/bfn-modules/debian/rules b/platform/barefoot/bfn-modules/debian/rules new file mode 100755 index 000000000000..c588b075e5e7 --- /dev/null +++ b/platform/barefoot/bfn-modules/debian/rules @@ -0,0 +1,30 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_NAME := bfn-modules +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MODULE_SRC := $(shell pwd)/modules + +%: + dh $@ + +override_dh_auto_build: + make -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + +override_dh_auto_install: + dh_installdirs -p$(PACKAGE_NAME) $(KERNEL_SRC)/$(INSTALL_MOD_DIR) + cp $(MODULE_SRC)/*.ko debian/$(PACKAGE_NAME)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) + dh_installdirs -p$(PACKAGE_NAME) usr/local/bin + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + rm -f $(MODULE_SRC)/*.o $(MODULE_SRC)/*.ko $(MODULE_SRC)/*.mod.c $(MODULE_SRC)/.*.cmd + rm -f $(MODULE_SRC)/Module.markers $(MODULE_SRC)/Module.symvers $(MODULE_SRC)/modules.order + rm -rf $(MODULE_SRC)/.tmp_versions + diff --git a/platform/barefoot/bfn-modules/modules/Makefile b/platform/barefoot/bfn-modules/modules/Makefile new file mode 100644 index 000000000000..d180b29f6ae2 --- /dev/null +++ b/platform/barefoot/bfn-modules/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := bf_kdrv.o +obj-m += bf_tun.o diff --git a/platform/barefoot/bfn-modules/modules/bf_ioctl.h b/platform/barefoot/bfn-modules/modules/bf_ioctl.h new file mode 100644 index 000000000000..e14716f50fa3 --- /dev/null +++ b/platform/barefoot/bfn-modules/modules/bf_ioctl.h @@ -0,0 +1,49 @@ +/******************************************************************************* + * BAREFOOT NETWORKS CONFIDENTIAL & PROPRIETARY + * + * Copyright (c) 2018-2018 Barefoot Networks, Inc. + * + * NOTICE: All information contained herein is, and remains the property of + * Barefoot Networks, Inc. and its suppliers, if any. The intellectual and + * technical concepts contained herein are proprietary to Barefoot Networks, + * Inc. + * and its suppliers and may be covered by U.S. and Foreign Patents, patents in + * process, and are protected by trade secret or copyright law. + * Dissemination of this information or reproduction of this material is + * strictly forbidden unless prior written permission is obtained from + * Barefoot Networks, Inc. + * + * No warranty, explicit or implicit is provided, unless granted under a + * written agreement with Barefoot Networks, Inc. + * + * $Id: $ + * + ******************************************************************************/ + +#ifndef _BF_IOCTL_H_ +#define _BF_IOCTL_H_ + +#ifdef __KERNEL__ +#include +#else +#include + +#ifndef phys_addr_t +typedef uint64_t phys_addr_t; +#endif + +#endif /* __KERNEL__ */ + +#define BF_IOC_MAGIC 'b' + +typedef struct bf_dma_bus_map_s +{ + phys_addr_t phy_addr; + void *dma_addr; + size_t size; +} bf_dma_bus_map_t; + +#define BF_IOCMAPDMAADDR _IOWR(BF_IOC_MAGIC, 0, bf_dma_bus_map_t) +#define BF_IOCUNMAPDMAADDR _IOW(BF_IOC_MAGIC, 0, bf_dma_bus_map_t) + +#endif /* _BF_IOCTL_H_ */ diff --git a/platform/barefoot/bfn-modules/modules/bf_kdrv.c b/platform/barefoot/bfn-modules/modules/bf_kdrv.c new file mode 100644 index 000000000000..a9e8e65f968b --- /dev/null +++ b/platform/barefoot/bfn-modules/modules/bf_kdrv.c @@ -0,0 +1,1382 @@ +/******************************************************************************* + * BAREFOOT NETWORKS CONFIDENTIAL & PROPRIETARY + * + * Copyright (c) 2015-2016 Barefoot Networks, Inc. + + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains the property of + * Barefoot Networks, Inc. and its suppliers, if any. The intellectual and + * technical concepts contained herein are proprietary to Barefoot Networks, + * Inc. + * and its suppliers and may be covered by U.S. and Foreign Patents, patents in + * process, and are protected by trade secret or copyright law. + * Dissemination of this information or reproduction of this material is + * strictly forbidden unless prior written permission is obtained from + * Barefoot Networks, Inc. + * + * No warranty, explicit or implicit is provided, unless granted under a + * written agreement with Barefoot Networks, Inc. + * + * $Id: $ + * + ******************************************************************************/ +/** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2015 Barefoot Networks. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the... + * + **/ + +/* bf_drv kernel module + * + * This is kernel mode driver for Tofino chip. + * Provides user space mmap service and user space "wait for interrupt" + * and "enable interrupt" services. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bf_ioctl.h" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) + #include +#else + #include +#endif + +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) +//#error unsupported linux kernel version +#endif + +/* TBD: Need to build with CONFIG_PCI_MSI */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) +extern int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec); +extern int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec); +#else +extern int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec); +extern int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, int maxvec); +#endif + +#define PCI_VENDOR_ID_BF 0x1d1c +#define TOFINO_DEV_ID_A0 0x01 +#define TOFINO_DEV_ID_B0 0x10 +#define TOFINO2_DEV_ID_A0 0x0100 + +#ifndef PCI_MSIX_ENTRY_SIZE +#define PCI_MSIX_ENTRY_SIZE 16 +#define PCI_MSIX_ENTRY_LOWER_ADDR 0 +#define PCI_MSIX_ENTRY_UPPER_ADDR 4 +#define PCI_MSIX_ENTRY_DATA 8 +#define PCI_MSIX_ENTRY_VECTOR_CTRL 12 +#define PCI_MSIX_ENTRY_CTRL_MASKBIT 1 +#endif + +#define BF_CLASS_NAME "bf" +#define BF_MAX_DEVICE_CNT 256 +#define BF_INTR_MODE_NONE_NAME "none" +#define BF_INTR_MODE_LEGACY_NAME "legacy" +#define BF_INTR_MODE_MSI_NAME "msi" +#define BF_INTR_MODE_MSIX_NAME "msix" +#define BF_MAX_BAR_MAPS 6 +#define BF_MSIX_ENTRY_CNT 128 /* TBD make it 512 */ +#define BF_MSI_ENTRY_CNT 2 + +/* interrupt mode */ +enum bf_intr_mode { + BF_INTR_MODE_NONE = 0, + BF_INTR_MODE_LEGACY, + BF_INTR_MODE_MSI, + BF_INTR_MODE_MSIX +}; + +/* device memory */ +struct bf_dev_mem { + const char *name; + phys_addr_t addr; + resource_size_t size; + void __iomem *internal_addr; +}; + +struct bf_listener { + struct bf_pci_dev *bfdev; + s32 event_count[BF_MSIX_ENTRY_CNT]; + int minor; + struct bf_listener *next; +}; + +/* device information */ +struct bf_dev_info { + struct module *owner; + struct device *dev; + int minor; + atomic_t event[BF_MSIX_ENTRY_CNT]; + wait_queue_head_t wait; + const char *version; + struct bf_dev_mem mem[BF_MAX_BAR_MAPS]; + struct msix_entry *msix_entries; + long irq; /* first irq vector */ + int num_irq; /* number of irq vectors */ + unsigned long irq_flags;/* sharable ?? */ + int pci_error_state; /* was there a pci bus error */ +}; + +/* cookie to be passed to IRQ handler, useful especially with MSIX */ +struct bf_int_vector { + struct bf_pci_dev *bf_dev; + int int_vec_offset; +}; + + +/** + * A structure describing the private information for a BF pcie device. + */ +struct bf_pci_dev { + struct bf_dev_info info; + struct pci_dev *pdev; + enum bf_intr_mode mode; + u8 instance; + char name[16]; + struct bf_int_vector bf_int_vec[BF_MSIX_ENTRY_CNT]; + struct bf_listener *listener_head; /* head of a singly linked list of + listeners */ +}; + +/* Keep any global information here that must survive even after the + * bf_pci_dev is free-ed up. + */ +struct bf_global { + struct bf_pci_dev *bfdev ; + struct cdev *bf_cdev; + struct fasync_struct *async_queue; +}; + +static int bf_major; +static int bf_minor[BF_MAX_DEVICE_CNT] = {0}; +static struct class *bf_class = NULL; +static char *intr_mode = NULL; +static enum bf_intr_mode bf_intr_mode_default = BF_INTR_MODE_MSI; +static spinlock_t bf_nonisr_lock; +/* dev->minor should index into this array */ +static struct bf_global bf_global[BF_MAX_DEVICE_CNT]; + +static void bf_add_listener(struct bf_pci_dev *bfdev, + struct bf_listener *listener) +{ + struct bf_listener **cur_listener = &bfdev->listener_head; + + if (!listener) { + return; + } + spin_lock(&bf_nonisr_lock); + + while (*cur_listener) { + cur_listener = &((*cur_listener)->next); + } + *cur_listener = listener; + listener->next = NULL; + + spin_unlock(&bf_nonisr_lock); +} + +static void bf_remove_listener(struct bf_pci_dev *bfdev, + struct bf_listener *listener) +{ + struct bf_listener **cur_listener = &bfdev->listener_head; + + /* in case of certain error conditions, this function might be called after bf_pci_remove() + */ + if (!bfdev || !listener) { + return; + } + spin_lock(&bf_nonisr_lock); + + if (*cur_listener == listener) { + *cur_listener = listener->next; + } else { + while (*cur_listener) { + if ((*cur_listener)->next == listener) { + (*cur_listener)->next = listener->next; + break; + } + cur_listener = &((*cur_listener)->next); + } + listener->next = NULL; + } + + spin_unlock(&bf_nonisr_lock); +} + +/* a pool of minor numbers is maintained */ +/* return the first available minor number */ +static int bf_get_next_minor_no(int *minor) +{ + int i; + + spin_lock(&bf_nonisr_lock); + for(i = 0; i < BF_MAX_DEVICE_CNT; i++) { + if (bf_minor[i] == 0) { + *minor = i; + bf_minor[i] = 1; /* mark it as taken */ + spin_unlock(&bf_nonisr_lock); + return 0; + } + } + *minor = -1; + spin_unlock(&bf_nonisr_lock); + return -1; +} + +/* return a minor number back to the pool for recycling */ +static int bf_return_minor_no(int minor) +{ + int err; + + spin_lock(&bf_nonisr_lock); + if (bf_minor[minor] == 0) { /* was already returned */ + err = -1; /* don't change anything, but return error */ + } else { + bf_minor[minor] = 0; /* mark it as available */ + err = 0; + } + spin_unlock(&bf_nonisr_lock); + return err; +} + +static inline struct bf_pci_dev *bf_get_pci_dev(struct bf_dev_info *info) +{ + return container_of(info, struct bf_pci_dev, info); +} + +/* + * It masks the msix on/off of generating MSI-X messages. + */ +static void +bf_msix_mask_irq(struct msi_desc *desc, int32_t state) +{ + u32 mask_bits = desc->masked; + unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_VECTOR_CTRL; + + if (state != 0) + mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; + else + mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT; + + if (mask_bits != desc->masked) { + writel(mask_bits, desc->mask_base + offset); + readl(desc->mask_base); + desc->masked = mask_bits; + } +} + +/** + * irqcontrol can be used to disable/enable interrupt from user space processes. + * + * @param bf_dev + * pointer to bf_pci_dev + * @param irq_state + * state value. 1 to enable interrupt, 0 to disable interrupt. + * + * @return + * - On success, 0. + * - On failure, a negative value. + */ +static int +bf_pci_irqcontrol(struct bf_pci_dev *bfdev, s32 irq_state) +{ + struct pci_dev *pdev = bfdev->pdev; + + pci_cfg_access_lock(pdev); + if (bfdev->mode == BF_INTR_MODE_LEGACY) + pci_intx(pdev, !!irq_state); + + else if (bfdev->mode == BF_INTR_MODE_MSIX) { + struct msi_desc *desc; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0) + list_for_each_entry(desc, &pdev->msi_list, list) + bf_msix_mask_irq(desc, irq_state); +#else + for_each_pci_msi_entry(desc, pdev) + bf_msix_mask_irq(desc, irq_state); +#endif + } + pci_cfg_access_unlock(pdev); + + return 0; +} + +/** + * interrupt handler which will check if the interrupt is from the right + * device. If so, disable it here and will be enabled later. + */ +static irqreturn_t bf_pci_irqhandler(int irq, struct bf_pci_dev *bfdev) +{ + /* Legacy mode need to mask in hardware */ + if (bfdev->mode == BF_INTR_MODE_LEGACY && + !pci_check_and_mask_intx(bfdev->pdev)) + return IRQ_NONE; + + /* NOTE : if bfdev->info.pci_error_state == 1, then do not access the + * device and return IRQ_NOTHANDLED. + */ + /* Message signal mode, no share IRQ and automasked */ + return IRQ_HANDLED; +} + +/* Remap pci resources described by bar #pci_bar */ +static int +bf_pci_setup_iomem(struct pci_dev *dev, struct bf_dev_info *info, + int n, int pci_bar, const char *name) +{ + unsigned long addr, len; + void *internal_addr; + + if (sizeof(info->mem) / sizeof(info->mem[0]) <= n) + return -EINVAL; + + addr = pci_resource_start(dev, pci_bar); + len = pci_resource_len(dev, pci_bar); + if (addr == 0 || len == 0) + return -1; + internal_addr = pci_ioremap_bar(dev, pci_bar); + if (internal_addr == NULL) + return -1; + info->mem[n].name = name; + info->mem[n].addr = addr; + info->mem[n].internal_addr = internal_addr; + info->mem[n].size = len; + return 0; +} + +/* Unmap previously ioremap'd resources */ +static void +bf_pci_release_iomem(struct bf_dev_info *info) +{ + int i; + + for (i = 0; i < BF_MAX_BAR_MAPS; i++) { + if (info->mem[i].internal_addr) + iounmap(info->mem[i].internal_addr); + } +} + +static int +bf_setup_bars(struct pci_dev *dev, struct bf_dev_info *info) +{ + int i, iom, ret; + unsigned long flags; + static const char *bar_names[BF_MAX_BAR_MAPS] = { + "BAR0", "BAR1", "BAR2", "BAR3", "BAR4", "BAR5", + }; + + iom = 0; + + for (i = 0; i < BF_MAX_BAR_MAPS; i++) { + if (pci_resource_len(dev, i) != 0 && + pci_resource_start(dev, i) != 0) { + flags = pci_resource_flags(dev, i); + if (flags & IORESOURCE_MEM) { + ret = bf_pci_setup_iomem(dev, info, iom, i, bar_names[i]); + if (ret != 0) + return ret; + iom++; + } + } + } + return (iom != 0) ? ret : -ENOENT; +} + +static irqreturn_t bf_interrupt(int irq, void *bfdev_id) +{ + struct bf_pci_dev *bfdev = ((struct bf_int_vector *)bfdev_id)->bf_dev; + int vect_off = ((struct bf_int_vector *)bfdev_id)->int_vec_offset; + + irqreturn_t ret = bf_pci_irqhandler(irq, bfdev); + + if (ret == IRQ_HANDLED) + atomic_inc(&(bfdev->info.event[vect_off])); + + return ret; +} + +static unsigned int bf_poll(struct file *filep, poll_table *wait) +{ + struct bf_listener *listener = (struct bf_listener *)filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + int i; + + if (!bfdev) { + return -ENODEV; + } + if (!bfdev->info.irq) + return -EIO; + + poll_wait(filep, &bfdev->info.wait, wait); + + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) + if (listener->event_count[i] != atomic_read(&bfdev->info.event[i])) + return POLLIN | POLLRDNORM; + return 0; +} + +static int bf_find_mem_index(struct vm_area_struct *vma) +{ + struct bf_pci_dev *bfdev = vma->vm_private_data; + if (vma->vm_pgoff < BF_MAX_BAR_MAPS) { + if (bfdev->info.mem[vma->vm_pgoff].size == 0) + return -1; + return (int)vma->vm_pgoff; + } + return -1; +} + +static const struct vm_operations_struct bf_physical_vm_ops = { +#ifdef CONFIG_HAVE_IOREMAP_PROT + .access = generic_access_phys, +#endif +}; + +static int bf_mmap_physical(struct vm_area_struct *vma) +{ + struct bf_pci_dev *bfdev = vma->vm_private_data; + int bar = bf_find_mem_index(vma); + struct bf_dev_mem *mem; + if (bar < 0) + return -EINVAL; + + mem = bfdev->info.mem + bar; + + if (mem->addr & ~PAGE_MASK) + return -ENODEV; + if (vma->vm_end - vma->vm_start > mem->size) + return -EINVAL; + + vma->vm_ops = &bf_physical_vm_ops; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + /* + * We cannot use the vm_iomap_memory() helper here, + * because vma->vm_pgoff is the map index we looked + * up above in bf_find_mem_index(), rather than an + * actual page offset into the mmap. + * + * So we just do the physical mmap without a page + * offset. + */ + return remap_pfn_range(vma, vma->vm_start, mem->addr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot); +} + +static int bf_mmap(struct file *filep, struct vm_area_struct *vma) +{ + struct bf_listener *listener = filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + int bar; + unsigned long requested_pages, actual_pages; + + if (!bfdev) { + return -ENODEV; + } + if (vma->vm_end < vma->vm_start) + return -EINVAL; + + vma->vm_private_data = bfdev; + + bar = bf_find_mem_index(vma); + if (bar < 0) + return -EINVAL; + + requested_pages = vma_pages(vma); + actual_pages = ((bfdev->info.mem[bar].addr & ~PAGE_MASK) + + bfdev->info.mem[bar].size + PAGE_SIZE -1) >> PAGE_SHIFT; + if (requested_pages > actual_pages) + return -EINVAL; + + return bf_mmap_physical(vma); +} + +static int bf_fasync(int fd, struct file *filep, int mode) +{ + int minor; + + if (!filep->private_data) { + return (-EINVAL); + } + minor = ((struct bf_listener *)filep->private_data)->minor; + if (minor >= BF_MAX_DEVICE_CNT) { + return (-EINVAL); + } + if (mode == 0 && &bf_global[minor].async_queue == NULL) { + return 0; /* nothing to do */ + } + return (fasync_helper(fd, filep, mode, &bf_global[minor].async_queue)); +} + +static int bf_open(struct inode *inode, struct file *filep) +{ + struct bf_pci_dev *bfdev; + struct bf_listener *listener; + int i; + + bfdev = bf_global[iminor(inode)].bfdev; + listener = kmalloc(sizeof(*listener), GFP_KERNEL); + if (listener) { + listener->bfdev = bfdev; + listener->minor = bfdev->info.minor; + listener->next = NULL; + bf_add_listener(bfdev, listener); + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) + listener->event_count[i] = atomic_read(&bfdev->info.event[i]); + filep->private_data = listener; + return 0; + } else { + return(-ENOMEM); + } +} + +static int bf_release(struct inode *inode, struct file *filep) +{ + struct bf_listener *listener = filep->private_data; + + bf_fasync(-1, filep, 0); /* empty any process id in the notification list */ + if (listener->bfdev) { + bf_remove_listener(listener->bfdev, listener); + } + kfree(listener); + return 0; +} + +/* user space support: make read() system call after poll() of select() */ +static ssize_t bf_read(struct file *filep, char __user *buf, + size_t count, loff_t *ppos) +{ + struct bf_listener *listener = filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + int retval, event_count[BF_MSIX_ENTRY_CNT]; + int i, mismatch_found = 0; /* OR of per vector mismatch */ + unsigned char cnt_match[BF_MSIX_ENTRY_CNT]; /* per vector mismatch */ + + if (!bfdev) { + return -ENODEV; + } + /* irq must be setup for read() to work */ + if (!bfdev->info.irq) + return -EIO; + + /* ensure that there is enough space on user buffer for the given interrupt + * mode */ + if (bfdev->mode == BF_INTR_MODE_MSIX) { + if (count < sizeof(s32)*BF_MSIX_ENTRY_CNT) + return -EINVAL; + count = sizeof(s32)*BF_MSIX_ENTRY_CNT; + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + if (count < sizeof(s32)*BF_MSI_ENTRY_CNT) + return -EINVAL; + count = sizeof(s32)*BF_MSI_ENTRY_CNT; + } else { + if (count < sizeof(s32)) + return -EINVAL; + count = sizeof(s32); + } + + do { + set_current_state(TASK_INTERRUPTIBLE); + + for (i = 0; i < (count/sizeof(s32)); i++) { + event_count[i] = atomic_read(&(bfdev->info.event[i])); + if (event_count[i] != listener->event_count[i]) { + mismatch_found |= 1; + cnt_match[i] = 1; + } else { + event_count[i] = 0; + cnt_match[i] = 0; + } + } + if (mismatch_found) { + __set_current_state(TASK_RUNNING); + if (copy_to_user(buf, &event_count, count)) + retval = -EFAULT; + else { /* adjust the listener->event_count; */ + for (i = 0 ; i < (count/sizeof(s32)); i++) { + if (cnt_match[i]) { + listener->event_count[i] = event_count[i]; + } + } + retval = count; + } + break; + } + + if (filep->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + break; + } + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } while (1); + + __set_current_state(TASK_RUNNING); + + return retval; +} + +/* user space is supposed to call this after it is done with interrupt + * processing + */ +static ssize_t bf_write(struct file *filep, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct bf_listener *listener = filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + ssize_t ret; + s32 int_en; + + if (!bfdev || !bfdev->info.irq) + return -EIO; + + if (count != sizeof(s32)) + return -EINVAL; + + if (copy_from_user(&int_en, buf, count)) + return -EFAULT; + + /* clear pci_error_state */ + bfdev->info.pci_error_state = 0; + + ret = bf_pci_irqcontrol(bfdev, int_en); + + return ret ? ret : sizeof(s32); +} + +static long bf_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +{ + struct bf_listener *listener = filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + bf_dma_bus_map_t dma_map; + void *addr = (void __user *)arg; + dma_addr_t dma_hndl; + + if (!bfdev || !addr) { + return EFAULT; + } + switch(cmd) { + case BF_IOCMAPDMAADDR: + if (access_ok(VERIFY_WRITE, addr, sizeof(bf_dma_bus_map_t))) { + if (copy_from_user(&dma_map, addr, sizeof(bf_dma_bus_map_t))) { + return EFAULT; + } + if (!dma_map.phy_addr || !dma_map.size) { + return EFAULT; + } + dma_hndl = dma_map_single(&bfdev->pdev->dev, phys_to_virt(dma_map.phy_addr), dma_map.size, DMA_BIDIRECTIONAL); + if (dma_mapping_error(&bfdev->pdev->dev, dma_hndl)) { + return EFAULT; + } + dma_map.dma_addr = (void *)dma_hndl; + if (copy_to_user(addr, &dma_map, sizeof(bf_dma_bus_map_t))) { + return EFAULT; + } + } else { + return EFAULT; + } + break; + case BF_IOCUNMAPDMAADDR: + if (access_ok(VERIFY_READ, addr, sizeof(bf_dma_bus_map_t))) { + if (copy_from_user(&dma_map, addr, sizeof(bf_dma_bus_map_t))) { + return EFAULT; + } + if (!dma_map.dma_addr || !dma_map.size) { + return EFAULT; + } + dma_unmap_single(&bfdev->pdev->dev, (dma_addr_t)dma_map.dma_addr, dma_map.size, DMA_BIDIRECTIONAL); + } else { + return EFAULT; + } + break; + default: + return EINVAL; + } + return 0; +} + +static const struct file_operations bf_fops = { + .owner = THIS_MODULE, + .open = bf_open, + .release = bf_release, + .unlocked_ioctl = bf_ioctl, + .read = bf_read, + .write = bf_write, + .mmap = bf_mmap, + .poll = bf_poll, + .fasync = bf_fasync, +}; + +static int bf_major_init(struct bf_pci_dev *bfdev, int minor) +{ + struct cdev *cdev; + static const char name[] = "bf"; + dev_t bf_dev = 0; + int result; + + result = alloc_chrdev_region(&bf_dev, 0, BF_MAX_DEVICE_CNT, name); + if (result) + return result; + + result = -ENOMEM; + cdev = cdev_alloc(); + if (!cdev) { + goto fail_dev_add; + } + cdev->ops = &bf_fops; + cdev->owner = THIS_MODULE; + kobject_set_name(&cdev->kobj, "%s", name); + result = cdev_add(cdev, bf_dev, BF_MAX_DEVICE_CNT); + + if (result) + goto fail_dev_add; + + bf_major = MAJOR(bf_dev); + bf_global[minor].bf_cdev = cdev; + return 0; + +fail_dev_add: + unregister_chrdev_region(bf_dev, BF_MAX_DEVICE_CNT); + return result; +} + +static void bf_major_cleanup(struct bf_pci_dev *bfdev, int minor) +{ + unregister_chrdev_region(MKDEV(bf_major, 0), BF_MAX_DEVICE_CNT); + cdev_del(bf_global[minor].bf_cdev); +} + +static int bf_init_cdev(struct bf_pci_dev *bfdev, int minor) +{ + int ret; + ret = bf_major_init(bfdev, minor); + if (ret) + return ret; + + bf_class = class_create(THIS_MODULE, BF_CLASS_NAME); + if (!bf_class) { + printk(KERN_ERR "create_class failed for bf_dev\n"); + ret = -ENODEV; + goto err_class_register; + } + return 0; + +err_class_register: + bf_major_cleanup(bfdev, minor); + return ret; +} + +static void bf_remove_cdev(struct bf_pci_dev *bfdev) +{ + class_destroy(bf_class); + bf_major_cleanup(bfdev, bfdev->info.minor); +} + + +/** + * bf_register_device - register a new userspace mem device + * @parent: parent device + * @bfdev: bf pci device + * + * returns zero on success or a negative error code. + */ +int bf_register_device(struct device *parent, struct bf_pci_dev *bfdev) +{ + struct bf_dev_info *info = &bfdev->info; + int i, j, ret = 0; + int minor; + + if (!parent || !info || !info->version) + return -EINVAL; + + init_waitqueue_head(&info->wait); + + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) { + atomic_set(&info->event[i], 0); + } + + if (bf_get_next_minor_no(&minor)) { + return -EINVAL; + } + + ret = bf_init_cdev(bfdev, minor); + if (ret) { + printk(KERN_ERR "BF: device cdev creation failed\n"); + return ret; + } + + info->dev = device_create(bf_class, parent, + MKDEV(bf_major, minor), bfdev, + "bf%d", minor); + if (!info->dev) { + printk(KERN_ERR "BF: device creation failed\n"); + return -ENODEV; + } + + info->minor = minor; + + /* bind ISRs and request interrupts */ + if (info->irq && (bfdev->mode != BF_INTR_MODE_NONE)) { + /* + * Note that we deliberately don't use devm_request_irq + * here. The parent module can unregister the UIO device + * and call pci_disable_msi, which requires that this + * irq has been freed. However, the device may have open + * FDs at the time of unregister and therefore may not be + * freed until they are released. + */ + if (bfdev->mode == BF_INTR_MODE_LEGACY) { + ret = request_irq(info->irq, bf_interrupt, + info->irq_flags, bfdev->name, + (void *)&(bfdev->bf_int_vec[0])); + if (ret) { + printk(KERN_ERR "bf failed to request legacy irq %ld error %d\n", + info->irq, ret); + return ret; + } + printk(KERN_NOTICE "BF allocating legacy int vector %ld\n", info->irq); + } else if (bfdev->mode == BF_INTR_MODE_MSIX) { + for (i = 0; i < info->num_irq; i++) { + ret = request_irq(info->msix_entries[i].vector, bf_interrupt, + info->irq_flags, bfdev->name, + (void *)&(bfdev->bf_int_vec[i])); + if (ret) { + /* undo all other previous bindings */ + printk(KERN_ERR "bf failed to request MSIX ret %d itr %d\n", ret, i); + for (j = i - 1; j >= 0; j--) { + free_irq(info->msix_entries[j].vector, + (void *)&(bfdev->bf_int_vec[j])); + } + return ret; + } + } + printk(KERN_NOTICE "BF allocating %d MSIx vectors from %ld\n", + info->num_irq, info->irq); + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + for (i = 0; i < info->num_irq; i++) { + ret = request_irq(info->irq + i, bf_interrupt, + info->irq_flags, bfdev->name, + (void *)&(bfdev->bf_int_vec[i])); + if (ret) { + /* undo all other previous bindings */ + printk(KERN_ERR "bf failed to request MSI ret %d itr %d\n", ret, i); + for (j = i - 1; j >= 0; j--) { + free_irq(info->irq + j, (void *)&(bfdev->bf_int_vec[j])); + } + return ret; + } + } + printk(KERN_NOTICE "BF allocating %d MSI vectors from %ld\n", + info->num_irq, info->irq); + } + } + return 0; +} + +/** + * bf_unregister_device - register a new userspace mem device + * @bfdev: bf pci device + * + * returns none + */ +void bf_unregister_device(struct bf_pci_dev *bfdev) +{ + struct bf_dev_info *info = &bfdev->info; + int i; + + if (info->irq) { + if (bfdev->mode == BF_INTR_MODE_LEGACY) { + free_irq(info->irq, (void *)&(bfdev->bf_int_vec[0])); + } else if (bfdev->mode == BF_INTR_MODE_MSIX) { + for (i = 0; i < info->num_irq; i++) { + free_irq(info->msix_entries[i].vector, (void *)&(bfdev->bf_int_vec[i])); + } + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + for (i = 0; i < info->num_irq; i++) { + free_irq(info->irq + i, (void *)&(bfdev->bf_int_vec[i])); + } + } + } + device_destroy(bf_class, MKDEV(bf_major, info->minor)); + bf_remove_cdev(bfdev); + bf_return_minor_no(info->minor); + return; +} + +static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) +{ + return &pdev->dev; +} + +static void bf_disable_int_dma(struct bf_pci_dev *bfdev) { + u8 *bf_base_addr, i; + u32 *bf_addr; + volatile u32 val; + + /* maskinterrupts and DMA */ + bf_base_addr = (bfdev->info.mem[0].internal_addr); + /* return if called before mmap */ + if (!bf_base_addr) { + return; + } + /* mask interrupt at shadow level */ + bf_addr = (u32 *)((u8 *)bf_base_addr + 0xc0); + for (i = 0; i < 16; i++) { + *bf_addr = 0xffffffff; + bf_addr++; + } + /* mask DMA */ + bf_addr = (u32 *)((u8 *)bf_base_addr + 0x14); + val = *bf_addr; + val &= 0xfffffffeUL; + *bf_addr = val; +} + +static int +bf_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct bf_pci_dev *bfdev; + int err; + int i, num_irq; + + memset(bf_global, 0, sizeof(bf_global)); + + bfdev = kzalloc(sizeof(struct bf_pci_dev), GFP_KERNEL); + if (!bfdev) + return -ENOMEM; + + /* init the cookies to be passed to ISRs */ + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) { + bfdev->bf_int_vec[i].int_vec_offset = i; + bfdev->bf_int_vec[i].bf_dev = bfdev; + } + + /* initialize intr_mode to none */ + bfdev->mode = BF_INTR_MODE_NONE; + + /* clear pci_error_state */ + bfdev->info.pci_error_state = 0; + + /* + * enable device + */ + err = pci_enable_device(pdev); + if (err != 0) { + dev_err(&pdev->dev, "Cannot enable PCI device\n"); + goto fail_free; + } + + /* + * reserve device's PCI memory regions for use by this + * module + */ + err = pci_request_regions(pdev, "bf_umem"); + if (err != 0) { + dev_err(&pdev->dev, "Cannot request regions\n"); + goto fail_pci_disable; + } + /* remap IO memory */ + err = bf_setup_bars(pdev, &bfdev->info); + if (err != 0) + goto fail_release_iomem; + + if (!dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(64)) && + !dma_set_coherent_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(64))) { + } else { + err = dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(32)); + if (err) { + err = dma_set_coherent_mask(pci_dev_to_dev(pdev), + DMA_BIT_MASK(32)); + if (err) { + dev_err(pci_dev_to_dev(pdev), "No usable DMA " + "configuration, aborting\n"); + goto fail_release_iomem; + } + } + } + + /* enable pci error reporting */ + /* for the current kernel version, kernel config must have set the followings: + * CONFIG_PCIEPORTBUS=y and CONFIG_PCIEAER = y + * we have pci_error_handlers defined that gets invoked by kernel AER module + * upon detecting the pcie error on this device's addresses. + * However, there seems no way that AER would pass the offending addresses + * to the callback functions. AER logs the error messages on the console. + * This driver's calback function send the SIGIO signal to the user space + * to indicate the error condition. + */ + pci_enable_pcie_error_reporting(pdev); + + bf_disable_int_dma(bfdev); + + /* enable bus mastering on the device */ + pci_set_master(pdev); + + /* fill in bfdev info */ + bfdev->info.version = "0.2"; + bfdev->info.owner = THIS_MODULE; + bfdev->pdev = pdev; + + switch (bf_intr_mode_default) { +#ifdef CONFIG_PCI_MSI + case BF_INTR_MODE_MSIX: + /* Only 1 msi-x vector needed */ + bfdev->info.msix_entries = kcalloc(BF_MSIX_ENTRY_CNT, + sizeof(struct msix_entry), GFP_KERNEL); + if (!bfdev->info.msix_entries) { + err = -ENOMEM; + goto fail_clear_pci_master; + } + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) { + bfdev->info.msix_entries[i].entry= i; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) + num_irq = pci_enable_msix(pdev, bfdev->info.msix_entries, + BF_MSIX_ENTRY_CNT); + if (num_irq == 0) { + dev_dbg(&pdev->dev, "using MSI-X"); + bfdev->info.num_irq = BF_MSIX_ENTRY_CNT; + bfdev->info.irq = bfdev->info.msix_entries[0].vector; + bfdev->mode = BF_INTR_MODE_MSIX; + printk(KERN_DEBUG "bf using %d MSIX irq from %ld\n", num_irq, + bfdev->info.irq); + break; + } +#else + num_irq = pci_enable_msix_range(pdev, bfdev->info.msix_entries, + BF_MSIX_ENTRY_CNT, BF_MSIX_ENTRY_CNT); + if (num_irq == BF_MSIX_ENTRY_CNT) { + dev_dbg(&pdev->dev, "using MSI-X"); + bfdev->info.num_irq = num_irq; + bfdev->info.irq = bfdev->info.msix_entries[0].vector; + bfdev->mode = BF_INTR_MODE_MSIX; + printk(KERN_DEBUG "bf using %d MSIX irq from %ld\n", num_irq, + bfdev->info.irq); + break; + } else { + if (num_irq) + pci_disable_msix(pdev); + kfree(bfdev->info.msix_entries); + bfdev->info.msix_entries = NULL; + printk(KERN_ERR "bf error allocating MSIX vectors. Trying MSI...\n"); + /* and, fall back to MSI */ + } +#endif /* LINUX_VERSION_CODE */ + /* ** intentional no-break */ + case BF_INTR_MODE_MSI: +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) + num_irq = pci_enable_msi_block(pdev, BF_MSI_ENTRY_CNT); + /* we must get requested number of MSI vectors enabled */ + if (num_irq == 0) { + dev_dbg(&pdev->dev, "using MSI"); + bfdev->info.num_irq = BF_MSI_ENTRY_CNT; + bfdev->info.irq = pdev->irq; + bfdev->mode = BF_INTR_MODE_MSI; + printk(KERN_DEBUG "bf using %d MSI irq from %ld\n", bfdev->info.num_irq, + bfdev->info.irq); + break; + } +#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) + num_irq = pci_enable_msi_range(pdev, BF_MSI_ENTRY_CNT, BF_MSI_ENTRY_CNT); + if (num_irq > 0) { + dev_dbg(&pdev->dev, "using MSI"); + bfdev->info.num_irq = num_irq; + bfdev->info.irq = pdev->irq; + bfdev->mode = BF_INTR_MODE_MSI; + printk(KERN_DEBUG "bf using %d MSI irq from %ld\n", bfdev->info.num_irq, + bfdev->info.irq); + break; + } +#else + num_irq = pci_alloc_irq_vectors_affinity(pdev, BF_MSI_ENTRY_CNT, + BF_MSI_ENTRY_CNT, PCI_IRQ_MSI | PCI_IRQ_AFFINITY, NULL); + if (num_irq > 0) { + dev_dbg(&pdev->dev, "using MSI"); + bfdev->info.num_irq = num_irq; + bfdev->info.irq = pci_irq_vector(pdev, 0); + bfdev->mode = BF_INTR_MODE_MSI; + printk(KERN_DEBUG "bf using %d MSI irq from %ld\n", bfdev->info.num_irq, + bfdev->info.irq); + break; + } +#endif /* LINUX_VERSION_CODE */ +#endif /* CONFIG_PCI_MSI */ + /* fall back to Legacy Interrupt, intentional no-break */ + + case BF_INTR_MODE_LEGACY: + if (pci_intx_mask_supported(pdev)) { + dev_dbg(&pdev->dev, "using INTX"); + bfdev->info.irq_flags = IRQF_SHARED; + bfdev->info.irq = pdev->irq; + bfdev->mode = BF_INTR_MODE_LEGACY; + printk(KERN_DEBUG "bf using LEGACY irq %ld\n", bfdev->info.irq); + break; + } + dev_notice(&pdev->dev, "PCI INTx mask not supported\n"); + /* fall back to no Interrupt, intentional no-break */ + case BF_INTR_MODE_NONE: + bfdev->info.irq = 0; + bfdev->info.num_irq = 0; + bfdev->mode = BF_INTR_MODE_NONE; + break; + + default: + dev_err(&pdev->dev, "invalid IRQ mode %u", bf_intr_mode_default); + err = -EINVAL; + goto fail_clear_pci_master; + } + + pci_set_drvdata(pdev, bfdev); + sprintf(bfdev->name, "bf_%d", bfdev->info.minor); + /* register bf driver */ + err = bf_register_device(&pdev->dev, bfdev); + if (err != 0) + goto fail_release_irq; + + bf_global[bfdev->info.minor].async_queue = NULL; + bf_global[bfdev->info.minor].bfdev = bfdev; + + dev_info(&pdev->dev, "bf device %d registered with irq %ld\n", + bfdev->instance, bfdev->info.irq); + printk(KERN_ALERT "bf probe ok\n"); + return 0; + +fail_release_irq: + pci_set_drvdata(pdev, NULL); + if (bfdev->mode == BF_INTR_MODE_MSIX) { + pci_disable_msix(bfdev->pdev); + kfree(bfdev->info.msix_entries); + bfdev->info.msix_entries = NULL; + } + else if (bfdev->mode == BF_INTR_MODE_MSI) + pci_disable_msi(bfdev->pdev); +fail_clear_pci_master: + pci_clear_master(pdev); +fail_release_iomem: + bf_pci_release_iomem(&bfdev->info); + pci_release_regions(pdev); +fail_pci_disable: + pci_disable_device(pdev); +fail_free: + kfree(bfdev); + + printk(KERN_ERR "bf probe not ok\n"); + return err; +} + + +static void +bf_pci_remove(struct pci_dev *pdev) +{ + struct bf_pci_dev *bfdev = pci_get_drvdata(pdev); + struct bf_listener *cur_listener; + + bf_disable_int_dma(bfdev); + bf_unregister_device(bfdev); + if (bfdev->mode == BF_INTR_MODE_MSIX) { + pci_disable_msix(pdev); + kfree(bfdev->info.msix_entries); + bfdev->info.msix_entries = NULL; + } + else if (bfdev->mode == BF_INTR_MODE_MSI) + pci_disable_msi(pdev); + pci_clear_master(pdev); + bf_pci_release_iomem(&bfdev->info); + pci_release_regions(pdev); + pci_disable_pcie_error_reporting(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + bf_global[bfdev->info.minor].bfdev = NULL; + /* existing filep structures in open file(s) must be informed that + * bf_pci_dev is no longer valid */ + spin_lock(&bf_nonisr_lock); + cur_listener = bfdev->listener_head; + while (cur_listener) { + cur_listener->bfdev = NULL; + cur_listener = cur_listener->next; + } + spin_unlock(&bf_nonisr_lock); + kfree(bfdev); +} + +/** + * bf_pci_error_detected - called when PCI error is detected + * @pdev: Pointer to PCI device + * @state: The current pci connection state + * + * called when root complex detects pci error associated with the device + */ +static pci_ers_result_t bf_pci_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct bf_pci_dev *bfdev = pci_get_drvdata(pdev); + int minor; + + if (!bfdev) { + return PCI_ERS_RESULT_NONE; + } + printk(KERN_ERR "pci_err_detected state %d\n", state); + if (state == pci_channel_io_perm_failure || state == pci_channel_io_frozen) { + bfdev->info.pci_error_state = 1; + /* send a signal to the user space program of the error */ + minor = bfdev->info.minor; + if (minor < BF_MAX_DEVICE_CNT && bf_global[minor].async_queue) { + kill_fasync(&bf_global[minor].async_queue, SIGIO, POLL_ERR); + } + return PCI_ERS_RESULT_DISCONNECT; + } else { + return PCI_ERS_RESULT_NONE; + } +} + +/** + * bf_pci_slot_reset - called after the pci bus has been reset. + * @pdev: Pointer to PCI device + * + * Restart the card from scratch, as if from a cold-boot. + */ +static pci_ers_result_t bf_pci_slot_reset(struct pci_dev *pdev) +{ + /* nothing to do for now as we do not expect to get backto normal after + * a pcie link reset + * TBD: fill in this function if tofino can recover after an error + */ + return PCI_ERS_RESULT_DISCONNECT; +} + +/** + * bf_pci_resume - called when kernel thinks the device is up on PCIe. + * @pdev: Pointer to PCI device + * + * This callback is called when the error recovery driver tells us that + * its OK to resume normal operation. + */ +static void bf_pci_resume(struct pci_dev *pdev) +{ + /* this function should never be called for Tofinoi */ + struct bf_pci_dev *bfdev = pci_get_drvdata(pdev); + + printk(KERN_ERR "BF io_resume invoked after pci error\n"); + if (bfdev) { + bfdev->info.pci_error_state = 0; + } +} + +static int +bf_config_intr_mode(char *intr_str) +{ + if (!intr_str) { + pr_info("Use MSIX interrupt by default\n"); + return 0; + } + + if (!strcmp(intr_str, BF_INTR_MODE_MSIX_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_MSIX; + pr_info("Use MSIX interrupt\n"); + } else if (!strcmp(intr_str, BF_INTR_MODE_MSI_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_MSI; + pr_info("Use MSI interrupt\n"); + } else if (!strcmp(intr_str, BF_INTR_MODE_LEGACY_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_LEGACY; + pr_info("Use legacy interrupt\n"); + } else { + bf_intr_mode_default = BF_INTR_MODE_NONE; + pr_info(" No Interrupt \n"); + } + + + return 0; +} + +static const struct pci_device_id bf_pci_tbl[] = { + {PCI_VDEVICE(BF, TOFINO_DEV_ID_A0), 0}, + {PCI_VDEVICE(BF, TOFINO_DEV_ID_B0), 0}, + {PCI_VDEVICE(BF, TOFINO2_DEV_ID_A0), 0}, + /* required last entry */ + { .device = 0 } +}; + +/* PCI bus error handlers */ +static struct pci_error_handlers bf_pci_err_handler = { + .error_detected = bf_pci_error_detected, + .slot_reset = bf_pci_slot_reset, + .resume = bf_pci_resume, +}; + +static struct pci_driver bf_pci_driver = { + .name = "bf", + .id_table = bf_pci_tbl, + .probe = bf_pci_probe, + .remove = bf_pci_remove, + .err_handler = &bf_pci_err_handler +}; + +static int __init +bfdrv_init(void) +{ + int ret; + + ret = bf_config_intr_mode(intr_mode); + if (ret < 0) + return ret; + + spin_lock_init(&bf_nonisr_lock); + return pci_register_driver(&bf_pci_driver); +} + +static void __exit +bfdrv_exit(void) +{ + pci_unregister_driver(&bf_pci_driver); +} + +module_init(bfdrv_init); +module_exit(bfdrv_exit); + +module_param(intr_mode, charp, S_IRUGO); +MODULE_PARM_DESC(intr_mode, +"bf interrupt mode (default=msix):\n" +" " BF_INTR_MODE_MSIX_NAME " Use MSIX interrupt\n" +" " BF_INTR_MODE_MSI_NAME " Use MSI interrupt\n" +" " BF_INTR_MODE_LEGACY_NAME " Use Legacy interrupt\n" +"\n"); + +MODULE_DEVICE_TABLE(pci, bf_pci_tbl); +MODULE_DESCRIPTION("Barefoot Tofino PCI device"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Barefoot Networks"); diff --git a/platform/barefoot/bfn-modules/modules/bf_tun.c b/platform/barefoot/bfn-modules/modules/bf_tun.c new file mode 100644 index 000000000000..45913a681a9a --- /dev/null +++ b/platform/barefoot/bfn-modules/modules/bf_tun.c @@ -0,0 +1,2617 @@ +/* + * TUN - Universal TUN/TAP device driver. + * Copyright (C) 1999-2002 Maxim Krasnyansky + * + * 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. + * + * $Id: tun.c,v 1.15 2002/03/01 02:44:24 maxk Exp $ + */ + +/* + * Changes: + * + * Mike Kershaw 2005/08/14 + * Add TUNSETLINK ioctl to set the link encapsulation + * + * Mark Smith + * Use eth_random_addr() for tap MAC address. + * + * Harald Roelle 2004/04/20 + * Fixes in packet dropping, queue length setting and queue wakeup. + * Increased default tx queue length. + * Added ethtool API. + * Minor cleanups + * + * Daniel Podlejski + * Modifications for 2.3.99-pre5 kernel. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#define DRV_NAME "bf_tun" +#define DRV_VERSION "1.6" +#define DRV_DESCRIPTION "Universal TUN/TAP device driver" +#define DRV_COPYRIGHT "(C) 1999-2004 Max Krasnyansky " + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define TUN_MINOR1 201 + +/* Uncomment to enable debugging */ +/* #define TUN_DEBUG 1 */ + +#ifdef TUN_DEBUG +static int debug; + +#define tun_debug(level, tun, fmt, args...) \ +do { \ + if (tun->debug) \ + netdev_printk(level, tun->dev, fmt, ##args); \ +} while (0) +#define DBG1(level, fmt, args...) \ +do { \ + if (debug == 2) \ + printk(level fmt, ##args); \ +} while (0) +#else +#define tun_debug(level, tun, fmt, args...) \ +do { \ + if (0) \ + netdev_printk(level, tun->dev, fmt, ##args); \ +} while (0) +#define DBG1(level, fmt, args...) \ +do { \ + if (0) \ + printk(level fmt, ##args); \ +} while (0) +#endif + +/* TUN device flags */ + +/* IFF_ATTACH_QUEUE is never stored in device flags, + * overload it to mean fasync when stored there. + */ +#define TUN_FASYNC IFF_ATTACH_QUEUE +/* High bits in flags field are unused. */ +#define TUN_VNET_LE 0x80000000 +#define TUN_VNET_BE 0x40000000 + +#define TUN_FEATURES (IFF_NO_PI | IFF_ONE_QUEUE | IFF_VNET_HDR | \ + IFF_MULTI_QUEUE) +#define GOODCOPY_LEN 128 + +#define FLT_EXACT_COUNT 8 +struct tap_filter { + unsigned int count; /* Number of addrs. Zero means disabled */ + u32 mask[2]; /* Mask of the hashed addrs */ + unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN]; +}; + +/* MAX_TAP_QUEUES 256 is chosen to allow rx/tx queues to be equal + * to max number of VCPUs in guest. */ +#define MAX_TAP_QUEUES 256 +#define MAX_TAP_FLOWS 4096 + +#define TUN_FLOW_EXPIRE (3 * HZ) + +struct tun_pcpu_stats { + u64 rx_packets; + u64 rx_bytes; + u64 tx_packets; + u64 tx_bytes; + struct u64_stats_sync syncp; + u32 rx_dropped; + u32 tx_dropped; + u32 rx_frame_errors; +}; + +/* A tun_file connects an open character device to a tuntap netdevice. It + * also contains all socket related structures (except sock_fprog and tap_filter) + * to serve as one transmit queue for tuntap device. The sock_fprog and + * tap_filter were kept in tun_struct since they were used for filtering for the + * netdevice not for a specific queue (at least I didn't see the requirement for + * this). + * + * RCU usage: + * The tun_file and tun_struct are loosely coupled, the pointer from one to the + * other can only be read while rcu_read_lock or rtnl_lock is held. + */ +struct tun_file { + struct sock sk; + struct socket socket; + struct socket_wq wq; + struct tun_struct __rcu *tun; + struct fasync_struct *fasync; + /* only used for fasnyc */ + unsigned int flags; + union { + u16 queue_index; + unsigned int ifindex; + }; + struct list_head next; + struct tun_struct *detached; + struct skb_array tx_array; +}; + +struct tun_flow_entry { + struct hlist_node hash_link; + struct rcu_head rcu; + struct tun_struct *tun; + + u32 rxhash; + u32 rps_rxhash; + int queue_index; + unsigned long updated; +}; + +#define TUN_NUM_FLOW_ENTRIES 1024 + +/* Since the socket were moved to tun_file, to preserve the behavior of persist + * device, socket filter, sndbuf and vnet header size were restore when the + * file were attached to a persist device. + */ +struct tun_struct { + struct tun_file __rcu *tfiles[MAX_TAP_QUEUES]; + unsigned int numqueues; + unsigned int flags; + kuid_t owner; + kgid_t group; + + struct net_device *dev; + netdev_features_t set_features; +#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ + NETIF_F_TSO6|NETIF_F_UFO) + + int align; + int vnet_hdr_sz; + int sndbuf; + struct tap_filter txflt; + struct sock_fprog fprog; + /* protected by rtnl lock */ + bool filter_attached; +#ifdef TUN_DEBUG + int debug; +#endif + spinlock_t lock; + struct hlist_head flows[TUN_NUM_FLOW_ENTRIES]; + struct timer_list flow_gc_timer; + unsigned long ageing_time; + unsigned int numdisabled; + struct list_head disabled; + void *security; + u32 flow_count; + struct tun_pcpu_stats __percpu *pcpu_stats; +}; + +#ifdef CONFIG_TUN_VNET_CROSS_LE +static inline bool tun_legacy_is_little_endian(struct tun_struct *tun) +{ + return tun->flags & TUN_VNET_BE ? false : + virtio_legacy_is_little_endian(); +} + +static long tun_get_vnet_be(struct tun_struct *tun, int __user *argp) +{ + int be = !!(tun->flags & TUN_VNET_BE); + + if (put_user(be, argp)) + return -EFAULT; + + return 0; +} + +static long tun_set_vnet_be(struct tun_struct *tun, int __user *argp) +{ + int be; + + if (get_user(be, argp)) + return -EFAULT; + + if (be) + tun->flags |= TUN_VNET_BE; + else + tun->flags &= ~TUN_VNET_BE; + + return 0; +} +#else +static inline bool tun_legacy_is_little_endian(struct tun_struct *tun) +{ + return virtio_legacy_is_little_endian(); +} + +static long tun_get_vnet_be(struct tun_struct *tun, int __user *argp) +{ + return -EINVAL; +} + +static long tun_set_vnet_be(struct tun_struct *tun, int __user *argp) +{ + return -EINVAL; +} +#endif /* CONFIG_TUN_VNET_CROSS_LE */ + +static inline bool tun_is_little_endian(struct tun_struct *tun) +{ + return tun->flags & TUN_VNET_LE || + tun_legacy_is_little_endian(tun); +} + +static inline u16 tun16_to_cpu(struct tun_struct *tun, __virtio16 val) +{ + return __virtio16_to_cpu(tun_is_little_endian(tun), val); +} + +static inline __virtio16 cpu_to_tun16(struct tun_struct *tun, u16 val) +{ + return __cpu_to_virtio16(tun_is_little_endian(tun), val); +} + +static inline u32 tun_hashfn(u32 rxhash) +{ + return rxhash & 0x3ff; +} + +static struct tun_flow_entry *tun_flow_find(struct hlist_head *head, u32 rxhash) +{ + struct tun_flow_entry *e; + + hlist_for_each_entry_rcu(e, head, hash_link) { + if (e->rxhash == rxhash) + return e; + } + return NULL; +} + +static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun, + struct hlist_head *head, + u32 rxhash, u16 queue_index) +{ + struct tun_flow_entry *e = kmalloc(sizeof(*e), GFP_ATOMIC); + + if (e) { + tun_debug(KERN_INFO, tun, "create flow: hash %u index %u\n", + rxhash, queue_index); + e->updated = jiffies; + e->rxhash = rxhash; + e->rps_rxhash = 0; + e->queue_index = queue_index; + e->tun = tun; + hlist_add_head_rcu(&e->hash_link, head); + ++tun->flow_count; + } + return e; +} + +static void tun_flow_delete(struct tun_struct *tun, struct tun_flow_entry *e) +{ + tun_debug(KERN_INFO, tun, "delete flow: hash %u index %u\n", + e->rxhash, e->queue_index); + hlist_del_rcu(&e->hash_link); + kfree_rcu(e, rcu); + --tun->flow_count; +} + +static void tun_flow_flush(struct tun_struct *tun) +{ + int i; + + spin_lock_bh(&tun->lock); + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) { + struct tun_flow_entry *e; + struct hlist_node *n; + + hlist_for_each_entry_safe(e, n, &tun->flows[i], hash_link) + tun_flow_delete(tun, e); + } + spin_unlock_bh(&tun->lock); +} + +static void tun_flow_delete_by_queue(struct tun_struct *tun, u16 queue_index) +{ + int i; + + spin_lock_bh(&tun->lock); + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) { + struct tun_flow_entry *e; + struct hlist_node *n; + + hlist_for_each_entry_safe(e, n, &tun->flows[i], hash_link) { + if (e->queue_index == queue_index) + tun_flow_delete(tun, e); + } + } + spin_unlock_bh(&tun->lock); +} + +static void tun_flow_cleanup(unsigned long data) +{ + struct tun_struct *tun = (struct tun_struct *)data; + unsigned long delay = tun->ageing_time; + unsigned long next_timer = jiffies + delay; + unsigned long count = 0; + int i; + + tun_debug(KERN_INFO, tun, "tun_flow_cleanup\n"); + + spin_lock_bh(&tun->lock); + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) { + struct tun_flow_entry *e; + struct hlist_node *n; + + hlist_for_each_entry_safe(e, n, &tun->flows[i], hash_link) { + unsigned long this_timer; + count++; + this_timer = e->updated + delay; + if (time_before_eq(this_timer, jiffies)) + tun_flow_delete(tun, e); + else if (time_before(this_timer, next_timer)) + next_timer = this_timer; + } + } + + if (count) + mod_timer(&tun->flow_gc_timer, round_jiffies_up(next_timer)); + spin_unlock_bh(&tun->lock); +} + +static void tun_flow_update(struct tun_struct *tun, u32 rxhash, + struct tun_file *tfile) +{ + struct hlist_head *head; + struct tun_flow_entry *e; + unsigned long delay = tun->ageing_time; + u16 queue_index = tfile->queue_index; + + if (!rxhash) + return; + else + head = &tun->flows[tun_hashfn(rxhash)]; + + rcu_read_lock(); + + /* We may get a very small possibility of OOO during switching, not + * worth to optimize.*/ + if (tun->numqueues == 1 || tfile->detached) + goto unlock; + + e = tun_flow_find(head, rxhash); + if (likely(e)) { + /* TODO: keep queueing to old queue until it's empty? */ + e->queue_index = queue_index; + e->updated = jiffies; + sock_rps_record_flow_hash(e->rps_rxhash); + } else { + spin_lock_bh(&tun->lock); + if (!tun_flow_find(head, rxhash) && + tun->flow_count < MAX_TAP_FLOWS) + tun_flow_create(tun, head, rxhash, queue_index); + + if (!timer_pending(&tun->flow_gc_timer)) + mod_timer(&tun->flow_gc_timer, + round_jiffies_up(jiffies + delay)); + spin_unlock_bh(&tun->lock); + } + +unlock: + rcu_read_unlock(); +} + +/** + * Save the hash received in the stack receive path and update the + * flow_hash table accordingly. + */ +static inline void tun_flow_save_rps_rxhash(struct tun_flow_entry *e, u32 hash) +{ + if (unlikely(e->rps_rxhash != hash)) + e->rps_rxhash = hash; +} + +/* We try to identify a flow through its rxhash first. The reason that + * we do not check rxq no. is because some cards(e.g 82599), chooses + * the rxq based on the txq where the last packet of the flow comes. As + * the userspace application move between processors, we may get a + * different rxq no. here. If we could not get rxhash, then we would + * hope the rxq no. may help here. + */ +static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback) +{ + struct tun_struct *tun = netdev_priv(dev); + struct tun_flow_entry *e; + u32 txq = 0; + u32 numqueues = 0; + + rcu_read_lock(); + numqueues = ACCESS_ONCE(tun->numqueues); + + txq = skb_get_hash(skb); + if (txq) { + e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq); + if (e) { + tun_flow_save_rps_rxhash(e, txq); + txq = e->queue_index; + } else + /* use multiply and shift instead of expensive divide */ + txq = ((u64)txq * numqueues) >> 32; + } else if (likely(skb_rx_queue_recorded(skb))) { + txq = skb_get_rx_queue(skb); + while (unlikely(txq >= numqueues)) + txq -= numqueues; + } + + rcu_read_unlock(); + return txq; +} + +static inline bool tun_not_capable(struct tun_struct *tun) +{ + const struct cred *cred = current_cred(); + struct net *net = dev_net(tun->dev); + + return ((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) || + (gid_valid(tun->group) && !in_egroup_p(tun->group))) && + !ns_capable(net->user_ns, CAP_NET_ADMIN); +} + +static void tun_set_real_num_queues(struct tun_struct *tun) +{ + netif_set_real_num_tx_queues(tun->dev, tun->numqueues); + netif_set_real_num_rx_queues(tun->dev, tun->numqueues); +} + +static void tun_disable_queue(struct tun_struct *tun, struct tun_file *tfile) +{ + tfile->detached = tun; + list_add_tail(&tfile->next, &tun->disabled); + ++tun->numdisabled; +} + +static struct tun_struct *tun_enable_queue(struct tun_file *tfile) +{ + struct tun_struct *tun = tfile->detached; + + tfile->detached = NULL; + list_del_init(&tfile->next); + --tun->numdisabled; + return tun; +} + +static void tun_queue_purge(struct tun_file *tfile) +{ + struct sk_buff *skb; + + while ((skb = skb_array_consume(&tfile->tx_array)) != NULL) + kfree_skb(skb); + + skb_queue_purge(&tfile->sk.sk_error_queue); +} + +static void tun_cleanup_tx_array(struct tun_file *tfile) +{ + if (tfile->tx_array.ring.queue) { + skb_array_cleanup(&tfile->tx_array); + memset(&tfile->tx_array, 0, sizeof(tfile->tx_array)); + } +} + +static void __tun_detach(struct tun_file *tfile, bool clean) +{ + struct tun_file *ntfile; + struct tun_struct *tun; + + tun = rtnl_dereference(tfile->tun); + + if (tun && !tfile->detached) { + u16 index = tfile->queue_index; + BUG_ON(index >= tun->numqueues); + + rcu_assign_pointer(tun->tfiles[index], + tun->tfiles[tun->numqueues - 1]); + ntfile = rtnl_dereference(tun->tfiles[index]); + ntfile->queue_index = index; + + --tun->numqueues; + if (clean) { + RCU_INIT_POINTER(tfile->tun, NULL); + sock_put(&tfile->sk); + } else + tun_disable_queue(tun, tfile); + + synchronize_net(); + tun_flow_delete_by_queue(tun, tun->numqueues + 1); + /* Drop read queue */ + tun_queue_purge(tfile); + tun_set_real_num_queues(tun); + } else if (tfile->detached && clean) { + tun = tun_enable_queue(tfile); + sock_put(&tfile->sk); + } + + if (clean) { + if (tun && tun->numqueues == 0 && tun->numdisabled == 0) { + netif_carrier_off(tun->dev); + + if (!(tun->flags & IFF_PERSIST) && + tun->dev->reg_state == NETREG_REGISTERED) + unregister_netdevice(tun->dev); + } + tun_cleanup_tx_array(tfile); + sock_put(&tfile->sk); + } +} + +static void tun_detach(struct tun_file *tfile, bool clean) +{ + rtnl_lock(); + __tun_detach(tfile, clean); + rtnl_unlock(); +} + +static void tun_detach_all(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + struct tun_file *tfile, *tmp; + int i, n = tun->numqueues; + + for (i = 0; i < n; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + BUG_ON(!tfile); + tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN; + tfile->socket.sk->sk_data_ready(tfile->socket.sk); + RCU_INIT_POINTER(tfile->tun, NULL); + --tun->numqueues; + } + list_for_each_entry(tfile, &tun->disabled, next) { + tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN; + tfile->socket.sk->sk_data_ready(tfile->socket.sk); + RCU_INIT_POINTER(tfile->tun, NULL); + } + BUG_ON(tun->numqueues != 0); + + synchronize_net(); + for (i = 0; i < n; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + /* Drop read queue */ + tun_queue_purge(tfile); + sock_put(&tfile->sk); + tun_cleanup_tx_array(tfile); + } + list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) { + tun_enable_queue(tfile); + tun_queue_purge(tfile); + sock_put(&tfile->sk); + tun_cleanup_tx_array(tfile); + } + BUG_ON(tun->numdisabled != 0); + + if (tun->flags & IFF_PERSIST) + module_put(THIS_MODULE); +} + +static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filter) +{ + struct tun_file *tfile = file->private_data; + struct net_device *dev = tun->dev; + int err; + + err = security_tun_dev_attach(tfile->socket.sk, tun->security); + if (err < 0) + goto out; + + err = -EINVAL; + if (rtnl_dereference(tfile->tun) && !tfile->detached) + goto out; + + err = -EBUSY; + if (!(tun->flags & IFF_MULTI_QUEUE) && tun->numqueues == 1) + goto out; + + err = -E2BIG; + if (!tfile->detached && + tun->numqueues + tun->numdisabled == MAX_TAP_QUEUES) + goto out; + + err = 0; + + /* Re-attach the filter to persist device */ + if (!skip_filter && (tun->filter_attached == true)) { + lock_sock(tfile->socket.sk); + err = sk_attach_filter(&tun->fprog, tfile->socket.sk); + release_sock(tfile->socket.sk); + if (!err) + goto out; + } + + if (!tfile->detached && + skb_array_init(&tfile->tx_array, dev->tx_queue_len, GFP_KERNEL)) { + err = -ENOMEM; + goto out; + } + + tfile->queue_index = tun->numqueues; + tfile->socket.sk->sk_shutdown &= ~RCV_SHUTDOWN; + rcu_assign_pointer(tfile->tun, tun); + rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile); + tun->numqueues++; + + if (tfile->detached) + tun_enable_queue(tfile); + else + sock_hold(&tfile->sk); + + tun_set_real_num_queues(tun); + + /* device is allowed to go away first, so no need to hold extra + * refcnt. + */ + +out: + return err; +} + +static struct tun_struct *__tun_get(struct tun_file *tfile) +{ + struct tun_struct *tun; + + rcu_read_lock(); + tun = rcu_dereference(tfile->tun); + if (tun) + dev_hold(tun->dev); + rcu_read_unlock(); + + return tun; +} + +static struct tun_struct *tun_get(struct file *file) +{ + return __tun_get(file->private_data); +} + +static void tun_put(struct tun_struct *tun) +{ + dev_put(tun->dev); +} + +/* TAP filtering */ +static void addr_hash_set(u32 *mask, const u8 *addr) +{ + int n = ether_crc(ETH_ALEN, addr) >> 26; + mask[n >> 5] |= (1 << (n & 31)); +} + +static unsigned int addr_hash_test(const u32 *mask, const u8 *addr) +{ + int n = ether_crc(ETH_ALEN, addr) >> 26; + return mask[n >> 5] & (1 << (n & 31)); +} + +static int update_filter(struct tap_filter *filter, void __user *arg) +{ + struct { u8 u[ETH_ALEN]; } *addr; + struct tun_filter uf; + int err, alen, n, nexact; + + if (copy_from_user(&uf, arg, sizeof(uf))) + return -EFAULT; + + if (!uf.count) { + /* Disabled */ + filter->count = 0; + return 0; + } + + alen = ETH_ALEN * uf.count; + addr = memdup_user(arg + sizeof(uf), alen); + if (IS_ERR(addr)) + return PTR_ERR(addr); + + /* The filter is updated without holding any locks. Which is + * perfectly safe. We disable it first and in the worst + * case we'll accept a few undesired packets. */ + filter->count = 0; + wmb(); + + /* Use first set of addresses as an exact filter */ + for (n = 0; n < uf.count && n < FLT_EXACT_COUNT; n++) + memcpy(filter->addr[n], addr[n].u, ETH_ALEN); + + nexact = n; + + /* Remaining multicast addresses are hashed, + * unicast will leave the filter disabled. */ + memset(filter->mask, 0, sizeof(filter->mask)); + for (; n < uf.count; n++) { + if (!is_multicast_ether_addr(addr[n].u)) { + err = 0; /* no filter */ + goto free_addr; + } + addr_hash_set(filter->mask, addr[n].u); + } + + /* For ALLMULTI just set the mask to all ones. + * This overrides the mask populated above. */ + if ((uf.flags & TUN_FLT_ALLMULTI)) + memset(filter->mask, ~0, sizeof(filter->mask)); + + /* Now enable the filter */ + wmb(); + filter->count = nexact; + + /* Return the number of exact filters */ + err = nexact; +free_addr: + kfree(addr); + return err; +} + +/* Returns: 0 - drop, !=0 - accept */ +static int run_filter(struct tap_filter *filter, const struct sk_buff *skb) +{ + /* Cannot use eth_hdr(skb) here because skb_mac_hdr() is incorrect + * at this point. */ + struct ethhdr *eh = (struct ethhdr *) skb->data; + int i; + + /* Exact match */ + for (i = 0; i < filter->count; i++) + if (ether_addr_equal(eh->h_dest, filter->addr[i])) + return 1; + + /* Inexact match (multicast only) */ + if (is_multicast_ether_addr(eh->h_dest)) + return addr_hash_test(filter->mask, eh->h_dest); + + return 0; +} + +/* + * Checks whether the packet is accepted or not. + * Returns: 0 - drop, !=0 - accept + */ +static int check_filter(struct tap_filter *filter, const struct sk_buff *skb) +{ + if (!filter->count) + return 1; + + return run_filter(filter, skb); +} + +/* Network device part of the driver */ + +static const struct ethtool_ops tun_ethtool_ops; + +/* Net device detach from fd. */ +static void tun_net_uninit(struct net_device *dev) +{ + tun_detach_all(dev); +} + +/* Net device open. */ +static int tun_net_open(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + int i; + + netif_tx_start_all_queues(dev); + + for (i = 0; i < tun->numqueues; i++) { + struct tun_file *tfile; + + tfile = rtnl_dereference(tun->tfiles[i]); + tfile->socket.sk->sk_write_space(tfile->socket.sk); + } + + return 0; +} + +/* Net device close. */ +static int tun_net_close(struct net_device *dev) +{ + netif_tx_stop_all_queues(dev); + return 0; +} + +/* Net device start xmit */ +static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + int txq = skb->queue_mapping; + struct tun_file *tfile; + u32 numqueues = 0; + + rcu_read_lock(); + tfile = rcu_dereference(tun->tfiles[txq]); + numqueues = ACCESS_ONCE(tun->numqueues); + + /* Drop packet if interface is not attached */ + if (txq >= numqueues) + goto drop; + +#ifdef CONFIG_RPS + if (numqueues == 1 && static_key_false(&rps_needed)) { + /* Select queue was not called for the skbuff, so we extract the + * RPS hash and save it into the flow_table here. + */ + __u32 rxhash; + + rxhash = skb_get_hash(skb); + if (rxhash) { + struct tun_flow_entry *e; + e = tun_flow_find(&tun->flows[tun_hashfn(rxhash)], + rxhash); + if (e) + tun_flow_save_rps_rxhash(e, rxhash); + } + } +#endif + + tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len); + + BUG_ON(!tfile); + + /* Drop if the filter does not like it. + * This is a noop if the filter is disabled. + * Filter can be enabled only for the TAP devices. */ + if (!check_filter(&tun->txflt, skb)) + goto drop; + + if (tfile->socket.sk->sk_filter && + sk_filter(tfile->socket.sk, skb)) + goto drop; + + /* Limit the number of packets queued by dividing txq length with the + * number of queues. + */ + if (skb_queue_len(&tfile->socket.sk->sk_receive_queue) * numqueues + >= dev->tx_queue_len) + goto drop; + + if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) + goto drop; + + skb_tx_timestamp(skb); + + /* Orphan the skb - required as we might hang on to it + * for indefinite time. + */ + skb_orphan(skb); + + nf_reset(skb); + + if (skb_array_produce(&tfile->tx_array, skb)) + goto drop; + + /* Notify and wake up reader process */ + if (tfile->flags & TUN_FASYNC) + kill_fasync(&tfile->fasync, SIGIO, POLL_IN); + tfile->socket.sk->sk_data_ready(tfile->socket.sk); + + rcu_read_unlock(); + return NETDEV_TX_OK; + +drop: + this_cpu_inc(tun->pcpu_stats->tx_dropped); + skb_tx_error(skb); + kfree_skb(skb); + rcu_read_unlock(); + return NET_XMIT_DROP; +} + +static void tun_net_mclist(struct net_device *dev) +{ + /* + * This callback is supposed to deal with mc filter in + * _rx_ path and has nothing to do with the _tx_ path. + * In rx path we always accept everything userspace gives us. + */ +} + +#define MIN_MTU 68 +#define MAX_MTU 65535 + +static int +tun_net_change_mtu(struct net_device *dev, int new_mtu) +{ + if (new_mtu < MIN_MTU || new_mtu + dev->hard_header_len > MAX_MTU) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + +static netdev_features_t tun_net_fix_features(struct net_device *dev, + netdev_features_t features) +{ + struct tun_struct *tun = netdev_priv(dev); + + return (features & tun->set_features) | (features & ~TUN_USER_FEATURES); +} +#ifdef CONFIG_NET_POLL_CONTROLLER +static void tun_poll_controller(struct net_device *dev) +{ + /* + * Tun only receives frames when: + * 1) the char device endpoint gets data from user space + * 2) the tun socket gets a sendmsg call from user space + * Since both of those are synchronous operations, we are guaranteed + * never to have pending data when we poll for it + * so there is nothing to do here but return. + * We need this though so netpoll recognizes us as an interface that + * supports polling, which enables bridge devices in virt setups to + * still use netconsole + */ + return; +} +#endif + +static void tun_set_headroom(struct net_device *dev, int new_hr) +{ + struct tun_struct *tun = netdev_priv(dev); + + if (new_hr < NET_SKB_PAD) + new_hr = NET_SKB_PAD; + + tun->align = new_hr; +} + +static struct rtnl_link_stats64 * +tun_net_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) +{ + u32 rx_dropped = 0, tx_dropped = 0, rx_frame_errors = 0; + struct tun_struct *tun = netdev_priv(dev); + struct tun_pcpu_stats *p; + int i; + + for_each_possible_cpu(i) { + u64 rxpackets, rxbytes, txpackets, txbytes; + unsigned int start; + + p = per_cpu_ptr(tun->pcpu_stats, i); + do { + start = u64_stats_fetch_begin(&p->syncp); + rxpackets = p->rx_packets; + rxbytes = p->rx_bytes; + txpackets = p->tx_packets; + txbytes = p->tx_bytes; + } while (u64_stats_fetch_retry(&p->syncp, start)); + + stats->rx_packets += rxpackets; + stats->rx_bytes += rxbytes; + stats->tx_packets += txpackets; + stats->tx_bytes += txbytes; + + /* u32 counters */ + rx_dropped += p->rx_dropped; + rx_frame_errors += p->rx_frame_errors; + tx_dropped += p->tx_dropped; + } + stats->rx_dropped = rx_dropped; + stats->rx_frame_errors = rx_frame_errors; + stats->tx_dropped = tx_dropped; + return stats; +} + +static int +tun_change_carrier(struct net_device *dev, bool new_carrier) { + if (new_carrier) + netif_carrier_on(dev); + else + netif_carrier_off(dev); + return 0; +} + +static const struct net_device_ops tun_netdev_ops = { + .ndo_uninit = tun_net_uninit, + .ndo_open = tun_net_open, + .ndo_stop = tun_net_close, + .ndo_start_xmit = tun_net_xmit, + .ndo_change_mtu = tun_net_change_mtu, + .ndo_fix_features = tun_net_fix_features, + .ndo_select_queue = tun_select_queue, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tun_poll_controller, +#endif + .ndo_set_rx_headroom = tun_set_headroom, + .ndo_get_stats64 = tun_net_get_stats64, + .ndo_change_carrier = tun_change_carrier, +}; + +static const struct net_device_ops tap_netdev_ops = { + .ndo_uninit = tun_net_uninit, + .ndo_open = tun_net_open, + .ndo_stop = tun_net_close, + .ndo_start_xmit = tun_net_xmit, + .ndo_change_mtu = tun_net_change_mtu, + .ndo_fix_features = tun_net_fix_features, + .ndo_set_rx_mode = tun_net_mclist, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_select_queue = tun_select_queue, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tun_poll_controller, +#endif + .ndo_features_check = passthru_features_check, + .ndo_set_rx_headroom = tun_set_headroom, + .ndo_get_stats64 = tun_net_get_stats64, + .ndo_change_carrier = tun_change_carrier, +}; + +static void tun_flow_init(struct tun_struct *tun) +{ + int i; + + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) + INIT_HLIST_HEAD(&tun->flows[i]); + + tun->ageing_time = TUN_FLOW_EXPIRE; + setup_timer(&tun->flow_gc_timer, tun_flow_cleanup, (unsigned long)tun); + mod_timer(&tun->flow_gc_timer, + round_jiffies_up(jiffies + tun->ageing_time)); +} + +static void tun_flow_uninit(struct tun_struct *tun) +{ + del_timer_sync(&tun->flow_gc_timer); + tun_flow_flush(tun); +} + +/* Initialize net device. */ +static void tun_net_init(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + switch (tun->flags & TUN_TYPE_MASK) { + case IFF_TUN: + dev->netdev_ops = &tun_netdev_ops; + + /* Point-to-Point TUN Device */ + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->mtu = 1500; + + /* Zero header length */ + dev->type = ARPHRD_NONE; + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + break; + + case IFF_TAP: + dev->netdev_ops = &tap_netdev_ops; + /* Ethernet TAP Device */ + ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + + eth_hw_addr_random(dev); + + break; + } +} + +/* Character device part */ + +/* Poll */ +static unsigned int tun_chr_poll(struct file *file, poll_table *wait) +{ + struct tun_file *tfile = file->private_data; + struct tun_struct *tun = __tun_get(tfile); + struct sock *sk; + unsigned int mask = 0; + + if (!tun) + return POLLERR; + + sk = tfile->socket.sk; + + tun_debug(KERN_INFO, tun, "tun_chr_poll\n"); + + poll_wait(file, sk_sleep(sk), wait); + + if (!skb_array_empty(&tfile->tx_array)) + mask |= POLLIN | POLLRDNORM; + + if (tun->dev->flags & IFF_UP && + (sock_writeable(sk) || + (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags) && + sock_writeable(sk)))) + mask |= POLLOUT | POLLWRNORM; + + if (tun->dev->reg_state != NETREG_REGISTERED) + mask = POLLERR; + + tun_put(tun); + return mask; +} + +/* prepad is the amount to reserve at front. len is length after that. + * linear is a hint as to how much to copy (usually headers). */ +static struct sk_buff *tun_alloc_skb(struct tun_file *tfile, + size_t prepad, size_t len, + size_t linear, int noblock) +{ + struct sock *sk = tfile->socket.sk; + struct sk_buff *skb; + int err; + + /* Under a page? Don't bother with paged skb. */ + if (prepad + len < PAGE_SIZE || !linear) + linear = len; + + skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, + &err, 0); + if (!skb) + return ERR_PTR(err); + + skb_reserve(skb, prepad); + skb_put(skb, linear); + skb->data_len = len - linear; + skb->len += len - linear; + + return skb; +} + +/* Get packet from user space buffer */ +static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + void *msg_control, struct iov_iter *from, + int noblock) +{ + struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; + struct sk_buff *skb; + size_t total_len = iov_iter_count(from); + size_t len = total_len, align = tun->align, linear; + struct virtio_net_hdr gso = { 0 }; + struct tun_pcpu_stats *stats; + int good_linear; + int copylen; + bool zerocopy = false; + int err; + u32 rxhash; + ssize_t n; + + if (!(tun->dev->flags & IFF_UP)) + return -EIO; + + if (!(tun->flags & IFF_NO_PI)) { + if (len < sizeof(pi)) + return -EINVAL; + len -= sizeof(pi); + + n = copy_from_iter(&pi, sizeof(pi), from); + if (n != sizeof(pi)) + return -EFAULT; + } + + if (tun->flags & IFF_VNET_HDR) { + int vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz); + + if (len < vnet_hdr_sz) + return -EINVAL; + len -= vnet_hdr_sz; + + n = copy_from_iter(&gso, sizeof(gso), from); + if (n != sizeof(gso)) + return -EFAULT; + + if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && + tun16_to_cpu(tun, gso.csum_start) + tun16_to_cpu(tun, gso.csum_offset) + 2 > tun16_to_cpu(tun, gso.hdr_len)) + gso.hdr_len = cpu_to_tun16(tun, tun16_to_cpu(tun, gso.csum_start) + tun16_to_cpu(tun, gso.csum_offset) + 2); + + if (tun16_to_cpu(tun, gso.hdr_len) > len) + return -EINVAL; + iov_iter_advance(from, vnet_hdr_sz - sizeof(gso)); + } + + if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP) { + align += NET_IP_ALIGN; + if (unlikely(len < ETH_HLEN || + (gso.hdr_len && tun16_to_cpu(tun, gso.hdr_len) < ETH_HLEN))) + return -EINVAL; + } + + good_linear = SKB_MAX_HEAD(align); + + if (msg_control) { + struct iov_iter i = *from; + + /* There are 256 bytes to be copied in skb, so there is + * enough room for skb expand head in case it is used. + * The rest of the buffer is mapped from userspace. + */ + copylen = gso.hdr_len ? tun16_to_cpu(tun, gso.hdr_len) : GOODCOPY_LEN; + if (copylen > good_linear) + copylen = good_linear; + linear = copylen; + iov_iter_advance(&i, copylen); + if (iov_iter_npages(&i, INT_MAX) <= MAX_SKB_FRAGS) + zerocopy = true; + } + + if (!zerocopy) { + copylen = len; + if (tun16_to_cpu(tun, gso.hdr_len) > good_linear) + linear = good_linear; + else + linear = tun16_to_cpu(tun, gso.hdr_len); + } + + skb = tun_alloc_skb(tfile, align, copylen, linear, noblock); + if (IS_ERR(skb)) { + if (PTR_ERR(skb) != -EAGAIN) + this_cpu_inc(tun->pcpu_stats->rx_dropped); + return PTR_ERR(skb); + } + + if (zerocopy) + err = zerocopy_sg_from_iter(skb, from); + else + err = skb_copy_datagram_from_iter(skb, 0, from, len); + + if (err) { + this_cpu_inc(tun->pcpu_stats->rx_dropped); + kfree_skb(skb); + return -EFAULT; + } + + err = virtio_net_hdr_to_skb(skb, &gso, tun_is_little_endian(tun)); + if (err) { + this_cpu_inc(tun->pcpu_stats->rx_frame_errors); + kfree_skb(skb); + return -EINVAL; + } + + switch (tun->flags & TUN_TYPE_MASK) { + case IFF_TUN: + if (tun->flags & IFF_NO_PI) { + u8 ip_version = skb->len ? (skb->data[0] >> 4) : 0; + + switch (ip_version) { + case 4: + pi.proto = htons(ETH_P_IP); + break; + case 6: + pi.proto = htons(ETH_P_IPV6); + break; + default: + this_cpu_inc(tun->pcpu_stats->rx_dropped); + kfree_skb(skb); + return -EINVAL; + } + } + + skb_reset_mac_header(skb); + skb->protocol = pi.proto; + skb->dev = tun->dev; + break; + case IFF_TAP: + skb->protocol = eth_type_trans(skb, tun->dev); + break; + } + + /* copy skb_ubuf_info for callback when skb has no error */ + if (zerocopy) { + skb_shinfo(skb)->destructor_arg = msg_control; + skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; + skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; + } else if (msg_control) { + struct ubuf_info *uarg = msg_control; + uarg->callback(uarg, false); + } + + skb_reset_network_header(skb); + skb_probe_transport_header(skb, 0); + + rxhash = skb_get_hash(skb); + netif_rx_ni(skb); + + stats = get_cpu_ptr(tun->pcpu_stats); + u64_stats_update_begin(&stats->syncp); + stats->rx_packets++; + stats->rx_bytes += len; + u64_stats_update_end(&stats->syncp); + put_cpu_ptr(stats); + + tun_flow_update(tun, rxhash, tfile); + return total_len; +} + +static ssize_t tun_chr_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + struct file *file = iocb->ki_filp; + struct tun_struct *tun = tun_get(file); + struct tun_file *tfile = file->private_data; + ssize_t result; + + if (!tun) + return -EBADFD; + + result = tun_get_user(tun, tfile, NULL, from, file->f_flags & O_NONBLOCK); + + tun_put(tun); + return result; +} + +/* Put packet to the user space buffer */ +static ssize_t tun_put_user(struct tun_struct *tun, + struct tun_file *tfile, + struct sk_buff *skb, + struct iov_iter *iter) +{ + struct tun_pi pi = { 0, skb->protocol }; + struct tun_pcpu_stats *stats; + ssize_t total; + int vlan_offset = 0; + int vlan_hlen = 0; + int vnet_hdr_sz = 0; + + if (skb_vlan_tag_present(skb)) + vlan_hlen = VLAN_HLEN; + + if (tun->flags & IFF_VNET_HDR) + vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz); + + total = skb->len + vlan_hlen + vnet_hdr_sz; + + if (!(tun->flags & IFF_NO_PI)) { + if (iov_iter_count(iter) < sizeof(pi)) + return -EINVAL; + + total += sizeof(pi); + if (iov_iter_count(iter) < total) { + /* Packet will be striped */ + pi.flags |= TUN_PKT_STRIP; + } + + if (copy_to_iter(&pi, sizeof(pi), iter) != sizeof(pi)) + return -EFAULT; + } + + if (vnet_hdr_sz) { + struct virtio_net_hdr gso = { 0 }; /* no info leak */ + int ret; + + if (iov_iter_count(iter) < vnet_hdr_sz) + return -EINVAL; + + ret = virtio_net_hdr_from_skb(skb, &gso, + tun_is_little_endian(tun), true); + if (ret) { + struct skb_shared_info *sinfo = skb_shinfo(skb); + pr_err("unexpected GSO type: " + "0x%x, gso_size %d, hdr_len %d\n", + sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size), + tun16_to_cpu(tun, gso.hdr_len)); + print_hex_dump(KERN_ERR, "tun: ", + DUMP_PREFIX_NONE, + 16, 1, skb->head, + min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true); + WARN_ON_ONCE(1); + return -EINVAL; + } + + if (copy_to_iter(&gso, sizeof(gso), iter) != sizeof(gso)) + return -EFAULT; + + iov_iter_advance(iter, vnet_hdr_sz - sizeof(gso)); + } + + if (vlan_hlen) { + int ret; + struct { + __be16 h_vlan_proto; + __be16 h_vlan_TCI; + } veth; + + veth.h_vlan_proto = skb->vlan_proto; + veth.h_vlan_TCI = htons(skb_vlan_tag_get(skb)); + + vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); + + ret = skb_copy_datagram_iter(skb, 0, iter, vlan_offset); + if (ret || !iov_iter_count(iter)) + goto done; + + ret = copy_to_iter(&veth, sizeof(veth), iter); + if (ret != sizeof(veth) || !iov_iter_count(iter)) + goto done; + } + + skb_copy_datagram_iter(skb, vlan_offset, iter, skb->len - vlan_offset); + +done: + /* caller is in process context, */ + stats = get_cpu_ptr(tun->pcpu_stats); + u64_stats_update_begin(&stats->syncp); + stats->tx_packets++; + stats->tx_bytes += skb->len + vlan_hlen; + u64_stats_update_end(&stats->syncp); + put_cpu_ptr(tun->pcpu_stats); + + return total; +} + +static struct sk_buff *tun_ring_recv(struct tun_file *tfile, int noblock, + int *err) +{ + DECLARE_WAITQUEUE(wait, current); + struct sk_buff *skb = NULL; + int error = 0; + + skb = skb_array_consume(&tfile->tx_array); + if (skb) + goto out; + if (noblock) { + error = -EAGAIN; + goto out; + } + + add_wait_queue(&tfile->wq.wait, &wait); + current->state = TASK_INTERRUPTIBLE; + + while (1) { + skb = skb_array_consume(&tfile->tx_array); + if (skb) + break; + if (signal_pending(current)) { + error = -ERESTARTSYS; + break; + } + if (tfile->socket.sk->sk_shutdown & RCV_SHUTDOWN) { + error = -EFAULT; + break; + } + + schedule(); + } + + current->state = TASK_RUNNING; + remove_wait_queue(&tfile->wq.wait, &wait); + +out: + *err = error; + return skb; +} + +static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile, + struct iov_iter *to, + int noblock) +{ + struct sk_buff *skb; + ssize_t ret; + int err; + + tun_debug(KERN_INFO, tun, "tun_do_read\n"); + + if (!iov_iter_count(to)) + return 0; + + /* Read frames from ring */ + skb = tun_ring_recv(tfile, noblock, &err); + if (!skb) + return err; + + ret = tun_put_user(tun, tfile, skb, to); + if (unlikely(ret < 0)) + kfree_skb(skb); + else + consume_skb(skb); + + return ret; +} + +static ssize_t tun_chr_read_iter(struct kiocb *iocb, struct iov_iter *to) +{ + struct file *file = iocb->ki_filp; + struct tun_file *tfile = file->private_data; + struct tun_struct *tun = __tun_get(tfile); + ssize_t len = iov_iter_count(to), ret; + + if (!tun) + return -EBADFD; + ret = tun_do_read(tun, tfile, to, file->f_flags & O_NONBLOCK); + ret = min_t(ssize_t, ret, len); + if (ret > 0) + iocb->ki_pos = ret; + tun_put(tun); + return ret; +} + +static void tun_free_netdev(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + BUG_ON(!(list_empty(&tun->disabled))); + free_percpu(tun->pcpu_stats); + tun_flow_uninit(tun); + security_tun_dev_free_security(tun->security); + free_netdev(dev); +} + +static void tun_setup(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + tun->owner = INVALID_UID; + tun->group = INVALID_GID; + + dev->ethtool_ops = &tun_ethtool_ops; + dev->destructor = tun_free_netdev; + /* We prefer our own queue length */ + dev->tx_queue_len = TUN_READQ_SIZE; +} + +/* Trivial set of netlink ops to allow deleting tun or tap + * device with netlink. + */ +static int tun_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + return -EINVAL; +} + +static struct rtnl_link_ops tun_link_ops __read_mostly = { + .kind = DRV_NAME, + .priv_size = sizeof(struct tun_struct), + .setup = tun_setup, + .validate = tun_validate, +}; + +static void tun_sock_write_space(struct sock *sk) +{ + struct tun_file *tfile; + wait_queue_head_t *wqueue; + + if (!sock_writeable(sk)) + return; + + if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags)) + return; + + wqueue = sk_sleep(sk); + if (wqueue && waitqueue_active(wqueue)) + wake_up_interruptible_sync_poll(wqueue, POLLOUT | + POLLWRNORM | POLLWRBAND); + + tfile = container_of(sk, struct tun_file, sk); + kill_fasync(&tfile->fasync, SIGIO, POLL_OUT); +} + +static int tun_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len) +{ + int ret; + struct tun_file *tfile = container_of(sock, struct tun_file, socket); + struct tun_struct *tun = __tun_get(tfile); + + if (!tun) + return -EBADFD; + + ret = tun_get_user(tun, tfile, m->msg_control, &m->msg_iter, + m->msg_flags & MSG_DONTWAIT); + tun_put(tun); + return ret; +} + +static int tun_recvmsg(struct socket *sock, struct msghdr *m, size_t total_len, + int flags) +{ + struct tun_file *tfile = container_of(sock, struct tun_file, socket); + struct tun_struct *tun = __tun_get(tfile); + int ret; + + if (!tun) + return -EBADFD; + + if (flags & ~(MSG_DONTWAIT|MSG_TRUNC|MSG_ERRQUEUE)) { + ret = -EINVAL; + goto out; + } + if (flags & MSG_ERRQUEUE) { + ret = sock_recv_errqueue(sock->sk, m, total_len, + SOL_PACKET, TUN_TX_TIMESTAMP); + goto out; + } + ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT); + if (ret > (ssize_t)total_len) { + m->msg_flags |= MSG_TRUNC; + ret = flags & MSG_TRUNC ? ret : total_len; + } +out: + tun_put(tun); + return ret; +} + +static int tun_peek_len(struct socket *sock) +{ + struct tun_file *tfile = container_of(sock, struct tun_file, socket); + struct tun_struct *tun; + int ret = 0; + + tun = __tun_get(tfile); + if (!tun) + return 0; + + ret = skb_array_peek_len(&tfile->tx_array); + tun_put(tun); + + return ret; +} + +/* Ops structure to mimic raw sockets with tun */ +static const struct proto_ops tun_socket_ops = { + .peek_len = tun_peek_len, + .sendmsg = tun_sendmsg, + .recvmsg = tun_recvmsg, +}; + +static struct proto tun_proto = { + .name = "tun", + .owner = THIS_MODULE, + .obj_size = sizeof(struct tun_file), +}; + +static int tun_flags(struct tun_struct *tun) +{ + return tun->flags & (TUN_FEATURES | IFF_PERSIST | IFF_TUN | IFF_TAP); +} + +static ssize_t tun_show_flags(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return sprintf(buf, "0x%x\n", tun_flags(tun)); +} + +static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return uid_valid(tun->owner)? + sprintf(buf, "%u\n", + from_kuid_munged(current_user_ns(), tun->owner)): + sprintf(buf, "-1\n"); +} + +static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return gid_valid(tun->group) ? + sprintf(buf, "%u\n", + from_kgid_munged(current_user_ns(), tun->group)): + sprintf(buf, "-1\n"); +} + +static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL); +static DEVICE_ATTR(owner, 0444, tun_show_owner, NULL); +static DEVICE_ATTR(group, 0444, tun_show_group, NULL); + +static struct attribute *tun_dev_attrs[] = { + &dev_attr_tun_flags.attr, + &dev_attr_owner.attr, + &dev_attr_group.attr, + NULL +}; + +static const struct attribute_group tun_attr_group = { + .attrs = tun_dev_attrs +}; + +static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) +{ + struct tun_struct *tun; + struct tun_file *tfile = file->private_data; + struct net_device *dev; + int err; + + if (tfile->detached) + return -EINVAL; + + dev = __dev_get_by_name(net, ifr->ifr_name); + if (dev) { + if (ifr->ifr_flags & IFF_TUN_EXCL) + return -EBUSY; + if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops) + tun = netdev_priv(dev); + else if ((ifr->ifr_flags & IFF_TAP) && dev->netdev_ops == &tap_netdev_ops) + tun = netdev_priv(dev); + else + return -EINVAL; + + if (!!(ifr->ifr_flags & IFF_MULTI_QUEUE) != + !!(tun->flags & IFF_MULTI_QUEUE)) + return -EINVAL; + + if (tun_not_capable(tun)) + return -EPERM; + err = security_tun_dev_open(tun->security); + if (err < 0) + return err; + + err = tun_attach(tun, file, ifr->ifr_flags & IFF_NOFILTER); + if (err < 0) + return err; + + if (tun->flags & IFF_MULTI_QUEUE && + (tun->numqueues + tun->numdisabled > 1)) { + /* One or more queue has already been attached, no need + * to initialize the device again. + */ + return 0; + } + } + else { + char *name; + unsigned long flags = 0; + int queues = ifr->ifr_flags & IFF_MULTI_QUEUE ? + MAX_TAP_QUEUES : 1; + + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + return -EPERM; + err = security_tun_dev_create(); + if (err < 0) + return err; + + /* Set dev type */ + if (ifr->ifr_flags & IFF_TUN) { + /* TUN device */ + flags |= IFF_TUN; + name = "tun%d"; + } else if (ifr->ifr_flags & IFF_TAP) { + /* TAP device */ + flags |= IFF_TAP; + name = "tap%d"; + } else + return -EINVAL; + + if (*ifr->ifr_name) + name = ifr->ifr_name; + + dev = alloc_netdev_mqs(sizeof(struct tun_struct), name, + NET_NAME_UNKNOWN, tun_setup, queues, + queues); + + if (!dev) + return -ENOMEM; +#if 0 + err = dev_get_valid_name(net, dev, name); + if (err < 0) + goto err_free_dev; +#endif + dev_net_set(dev, net); + dev->rtnl_link_ops = &tun_link_ops; + dev->ifindex = tfile->ifindex; + dev->sysfs_groups[0] = &tun_attr_group; + + tun = netdev_priv(dev); + tun->dev = dev; + tun->flags = flags; + tun->txflt.count = 0; + tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr); + + tun->align = NET_SKB_PAD; + tun->filter_attached = false; + tun->sndbuf = tfile->socket.sk->sk_sndbuf; + + tun->pcpu_stats = netdev_alloc_pcpu_stats(struct tun_pcpu_stats); + if (!tun->pcpu_stats) { + err = -ENOMEM; + goto err_free_dev; + } + + spin_lock_init(&tun->lock); + + err = security_tun_dev_alloc_security(&tun->security); + if (err < 0) + goto err_free_stat; + + tun_net_init(dev); + tun_flow_init(tun); + + dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | + TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_TX; + dev->features = dev->hw_features | NETIF_F_LLTX; + dev->vlan_features = dev->features & + ~(NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_TX); + + INIT_LIST_HEAD(&tun->disabled); + err = tun_attach(tun, file, false); + if (err < 0) + goto err_free_flow; + + err = register_netdevice(tun->dev); + if (err < 0) + goto err_detach; + } + + netif_carrier_on(tun->dev); + + tun_debug(KERN_INFO, tun, "tun_set_iff\n"); + + tun->flags = (tun->flags & ~TUN_FEATURES) | + (ifr->ifr_flags & TUN_FEATURES); + + /* Make sure persistent devices do not get stuck in + * xoff state. + */ + if (netif_running(tun->dev)) + netif_tx_wake_all_queues(tun->dev); + + strcpy(ifr->ifr_name, tun->dev->name); + return 0; + +err_detach: + tun_detach_all(dev); +err_free_flow: + tun_flow_uninit(tun); + security_tun_dev_free_security(tun->security); +err_free_stat: + free_percpu(tun->pcpu_stats); +err_free_dev: + free_netdev(dev); + return err; +} + +static void tun_get_iff(struct net *net, struct tun_struct *tun, + struct ifreq *ifr) +{ + tun_debug(KERN_INFO, tun, "tun_get_iff\n"); + + strcpy(ifr->ifr_name, tun->dev->name); + + ifr->ifr_flags = tun_flags(tun); + +} + +/* This is like a cut-down ethtool ops, except done via tun fd so no + * privs required. */ +static int set_offload(struct tun_struct *tun, unsigned long arg) +{ + netdev_features_t features = 0; + + if (arg & TUN_F_CSUM) { + features |= NETIF_F_HW_CSUM; + arg &= ~TUN_F_CSUM; + + if (arg & (TUN_F_TSO4|TUN_F_TSO6)) { + if (arg & TUN_F_TSO_ECN) { + features |= NETIF_F_TSO_ECN; + arg &= ~TUN_F_TSO_ECN; + } + if (arg & TUN_F_TSO4) + features |= NETIF_F_TSO; + if (arg & TUN_F_TSO6) + features |= NETIF_F_TSO6; + arg &= ~(TUN_F_TSO4|TUN_F_TSO6); + } + + if (arg & TUN_F_UFO) { + features |= NETIF_F_UFO; + arg &= ~TUN_F_UFO; + } + } + + /* This gives the user a way to test for new features in future by + * trying to set them. */ + if (arg) + return -EINVAL; + + tun->set_features = features; + netdev_update_features(tun->dev); + + return 0; +} + +static void tun_detach_filter(struct tun_struct *tun, int n) +{ + int i; + struct tun_file *tfile; + + for (i = 0; i < n; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + lock_sock(tfile->socket.sk); + sk_detach_filter(tfile->socket.sk); + release_sock(tfile->socket.sk); + } + + tun->filter_attached = false; +} + +static int tun_attach_filter(struct tun_struct *tun) +{ + int i, ret = 0; + struct tun_file *tfile; + + for (i = 0; i < tun->numqueues; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + lock_sock(tfile->socket.sk); + ret = sk_attach_filter(&tun->fprog, tfile->socket.sk); + release_sock(tfile->socket.sk); + if (ret) { + tun_detach_filter(tun, i); + return ret; + } + } + + tun->filter_attached = true; + return ret; +} + +static void tun_set_sndbuf(struct tun_struct *tun) +{ + struct tun_file *tfile; + int i; + + for (i = 0; i < tun->numqueues; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + tfile->socket.sk->sk_sndbuf = tun->sndbuf; + } +} + +static int tun_set_queue(struct file *file, struct ifreq *ifr) +{ + struct tun_file *tfile = file->private_data; + struct tun_struct *tun; + int ret = 0; + + rtnl_lock(); + + if (ifr->ifr_flags & IFF_ATTACH_QUEUE) { + tun = tfile->detached; + if (!tun) { + ret = -EINVAL; + goto unlock; + } + ret = security_tun_dev_attach_queue(tun->security); + if (ret < 0) + goto unlock; + ret = tun_attach(tun, file, false); + } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) { + tun = rtnl_dereference(tfile->tun); + if (!tun || !(tun->flags & IFF_MULTI_QUEUE) || tfile->detached) + ret = -EINVAL; + else + __tun_detach(tfile, false); + } else + ret = -EINVAL; + +unlock: + rtnl_unlock(); + return ret; +} + +static long __tun_chr_ioctl(struct file *file, unsigned int cmd, + unsigned long arg, int ifreq_len) +{ + struct tun_file *tfile = file->private_data; + struct tun_struct *tun; + void __user* argp = (void __user*)arg; + struct ifreq ifr; + kuid_t owner; + kgid_t group; + int sndbuf; + int vnet_hdr_sz; + unsigned int ifindex; + int le; + int ret; + + if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) { + if (copy_from_user(&ifr, argp, ifreq_len)) + return -EFAULT; + } else { + memset(&ifr, 0, sizeof(ifr)); + } + if (cmd == TUNGETFEATURES) { + /* Currently this just means: "what IFF flags are valid?". + * This is needed because we never checked for invalid flags on + * TUNSETIFF. + */ + return put_user(IFF_TUN | IFF_TAP | TUN_FEATURES, + (unsigned int __user*)argp); + } else if (cmd == TUNSETQUEUE) + return tun_set_queue(file, &ifr); + + ret = 0; + rtnl_lock(); + + tun = __tun_get(tfile); + if (cmd == TUNSETIFF && !tun) { + ifr.ifr_name[IFNAMSIZ-1] = '\0'; + + ret = tun_set_iff(sock_net(&tfile->sk), file, &ifr); + + if (ret) + goto unlock; + + if (copy_to_user(argp, &ifr, ifreq_len)) + ret = -EFAULT; + goto unlock; + } + if (cmd == TUNSETIFINDEX) { + ret = -EPERM; + if (tun) + goto unlock; + + ret = -EFAULT; + if (copy_from_user(&ifindex, argp, sizeof(ifindex))) + goto unlock; + + ret = 0; + tfile->ifindex = ifindex; + goto unlock; + } + + ret = -EBADFD; + if (!tun) + goto unlock; + + tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %u\n", cmd); + + ret = 0; + switch (cmd) { + case TUNGETIFF: + tun_get_iff(current->nsproxy->net_ns, tun, &ifr); + + if (tfile->detached) + ifr.ifr_flags |= IFF_DETACH_QUEUE; + if (!tfile->socket.sk->sk_filter) + ifr.ifr_flags |= IFF_NOFILTER; + + if (copy_to_user(argp, &ifr, ifreq_len)) + ret = -EFAULT; + break; + + case TUNSETNOCSUM: + /* Disable/Enable checksum */ + + /* [unimplemented] */ + tun_debug(KERN_INFO, tun, "ignored: set checksum %s\n", + arg ? "disabled" : "enabled"); + break; + + case TUNSETPERSIST: + /* Disable/Enable persist mode. Keep an extra reference to the + * module to prevent the module being unprobed. + */ + if (arg && !(tun->flags & IFF_PERSIST)) { + tun->flags |= IFF_PERSIST; + __module_get(THIS_MODULE); + } + if (!arg && (tun->flags & IFF_PERSIST)) { + tun->flags &= ~IFF_PERSIST; + module_put(THIS_MODULE); + } + + tun_debug(KERN_INFO, tun, "persist %s\n", + arg ? "enabled" : "disabled"); + break; + + case TUNSETOWNER: + /* Set owner of the device */ + owner = make_kuid(current_user_ns(), arg); + if (!uid_valid(owner)) { + ret = -EINVAL; + break; + } + tun->owner = owner; + tun_debug(KERN_INFO, tun, "owner set to %u\n", + from_kuid(&init_user_ns, tun->owner)); + break; + + case TUNSETGROUP: + /* Set group of the device */ + group = make_kgid(current_user_ns(), arg); + if (!gid_valid(group)) { + ret = -EINVAL; + break; + } + tun->group = group; + tun_debug(KERN_INFO, tun, "group set to %u\n", + from_kgid(&init_user_ns, tun->group)); + break; + + case TUNSETLINK: + /* Only allow setting the type when the interface is down */ + if (tun->dev->flags & IFF_UP) { + tun_debug(KERN_INFO, tun, + "Linktype set failed because interface is up\n"); + ret = -EBUSY; + } else { + tun->dev->type = (int) arg; + tun_debug(KERN_INFO, tun, "linktype set to %d\n", + tun->dev->type); + ret = 0; + } + break; + +#ifdef TUN_DEBUG + case TUNSETDEBUG: + tun->debug = arg; + break; +#endif + case TUNSETOFFLOAD: + ret = set_offload(tun, arg); + break; + + case TUNSETTXFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != IFF_TAP) + break; + ret = update_filter(&tun->txflt, (void __user *)arg); + break; + + case SIOCGIFHWADDR: + /* Get hw address */ + memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN); + ifr.ifr_hwaddr.sa_family = tun->dev->type; + if (copy_to_user(argp, &ifr, ifreq_len)) + ret = -EFAULT; + break; + + case SIOCSIFHWADDR: + /* Set hw address */ + tun_debug(KERN_DEBUG, tun, "set hw address: %pM\n", + ifr.ifr_hwaddr.sa_data); + + ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); + break; + + case TUNGETSNDBUF: + sndbuf = tfile->socket.sk->sk_sndbuf; + if (copy_to_user(argp, &sndbuf, sizeof(sndbuf))) + ret = -EFAULT; + break; + + case TUNSETSNDBUF: + if (copy_from_user(&sndbuf, argp, sizeof(sndbuf))) { + ret = -EFAULT; + break; + } + if (sndbuf <= 0) { + ret = -EINVAL; + break; + } + + tun->sndbuf = sndbuf; + tun_set_sndbuf(tun); + break; + + case TUNGETVNETHDRSZ: + vnet_hdr_sz = tun->vnet_hdr_sz; + if (copy_to_user(argp, &vnet_hdr_sz, sizeof(vnet_hdr_sz))) + ret = -EFAULT; + break; + + case TUNSETVNETHDRSZ: + if (copy_from_user(&vnet_hdr_sz, argp, sizeof(vnet_hdr_sz))) { + ret = -EFAULT; + break; + } + if (vnet_hdr_sz < (int)sizeof(struct virtio_net_hdr)) { + ret = -EINVAL; + break; + } + + tun->vnet_hdr_sz = vnet_hdr_sz; + break; + + case TUNGETVNETLE: + le = !!(tun->flags & TUN_VNET_LE); + if (put_user(le, (int __user *)argp)) + ret = -EFAULT; + break; + + case TUNSETVNETLE: + if (get_user(le, (int __user *)argp)) { + ret = -EFAULT; + break; + } + if (le) + tun->flags |= TUN_VNET_LE; + else + tun->flags &= ~TUN_VNET_LE; + break; + + case TUNGETVNETBE: + ret = tun_get_vnet_be(tun, argp); + break; + + case TUNSETVNETBE: + ret = tun_set_vnet_be(tun, argp); + break; + + case TUNATTACHFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != IFF_TAP) + break; + ret = -EFAULT; + if (copy_from_user(&tun->fprog, argp, sizeof(tun->fprog))) + break; + + ret = tun_attach_filter(tun); + break; + + case TUNDETACHFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != IFF_TAP) + break; + ret = 0; + tun_detach_filter(tun, tun->numqueues); + break; + + case TUNGETFILTER: + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != IFF_TAP) + break; + ret = -EFAULT; + if (copy_to_user(argp, &tun->fprog, sizeof(tun->fprog))) + break; + ret = 0; + break; + + default: + ret = -EINVAL; + break; + } + +unlock: + rtnl_unlock(); + if (tun) + tun_put(tun); + return ret; +} + +static long tun_chr_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + return __tun_chr_ioctl(file, cmd, arg, sizeof (struct ifreq)); +} + +#ifdef CONFIG_COMPAT +static long tun_chr_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case TUNSETIFF: + case TUNGETIFF: + case TUNSETTXFILTER: + case TUNGETSNDBUF: + case TUNSETSNDBUF: + case SIOCGIFHWADDR: + case SIOCSIFHWADDR: + arg = (unsigned long)compat_ptr(arg); + break; + default: + arg = (compat_ulong_t)arg; + break; + } + + /* + * compat_ifreq is shorter than ifreq, so we must not access beyond + * the end of that structure. All fields that are used in this + * driver are compatible though, we don't need to convert the + * contents. + */ + return __tun_chr_ioctl(file, cmd, arg, sizeof(struct compat_ifreq)); +} +#endif /* CONFIG_COMPAT */ + +static int tun_chr_fasync(int fd, struct file *file, int on) +{ + struct tun_file *tfile = file->private_data; + int ret; + + if ((ret = fasync_helper(fd, file, on, &tfile->fasync)) < 0) + goto out; + + if (on) { + __f_setown(file, task_pid(current), PIDTYPE_PID, 0); + tfile->flags |= TUN_FASYNC; + } else + tfile->flags &= ~TUN_FASYNC; + ret = 0; +out: + return ret; +} + +static int tun_chr_open(struct inode *inode, struct file * file) +{ + struct net *net = current->nsproxy->net_ns; + struct tun_file *tfile; + + DBG1(KERN_INFO, "tunX: tun_chr_open\n"); + + tfile = (struct tun_file *)sk_alloc(net, AF_UNSPEC, GFP_KERNEL, + &tun_proto, 0); + if (!tfile) + return -ENOMEM; + RCU_INIT_POINTER(tfile->tun, NULL); + tfile->flags = 0; + tfile->ifindex = 0; + + init_waitqueue_head(&tfile->wq.wait); + RCU_INIT_POINTER(tfile->socket.wq, &tfile->wq); + + tfile->socket.file = file; + tfile->socket.ops = &tun_socket_ops; + + sock_init_data(&tfile->socket, &tfile->sk); + + tfile->sk.sk_write_space = tun_sock_write_space; + tfile->sk.sk_sndbuf = INT_MAX; + + file->private_data = tfile; + INIT_LIST_HEAD(&tfile->next); + + sock_set_flag(&tfile->sk, SOCK_ZEROCOPY); + + memset(&tfile->tx_array, 0, sizeof(tfile->tx_array)); + + return 0; +} + +static int tun_chr_close(struct inode *inode, struct file *file) +{ + struct tun_file *tfile = file->private_data; + + tun_detach(tfile, true); + + return 0; +} + +#ifdef CONFIG_PROC_FS +static void tun_chr_show_fdinfo(struct seq_file *m, struct file *f) +{ + struct tun_struct *tun; + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + + rtnl_lock(); + tun = tun_get(f); + if (tun) + tun_get_iff(current->nsproxy->net_ns, tun, &ifr); + rtnl_unlock(); + + if (tun) + tun_put(tun); + + seq_printf(m, "iff:\t%s\n", ifr.ifr_name); +} +#endif + +static const struct file_operations tun_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read_iter = tun_chr_read_iter, + .write_iter = tun_chr_write_iter, + .poll = tun_chr_poll, + .unlocked_ioctl = tun_chr_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tun_chr_compat_ioctl, +#endif + .open = tun_chr_open, + .release = tun_chr_close, + .fasync = tun_chr_fasync, +#ifdef CONFIG_PROC_FS + .show_fdinfo = tun_chr_show_fdinfo, +#endif +}; + +static struct miscdevice tun_miscdev = { + .minor = TUN_MINOR1, + .name = "bf_tun", + .nodename = "net/bf_tun", + .fops = &tun_fops, +}; + +/* ethtool interface */ + +static int tun_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + cmd->supported = 0; + cmd->advertising = 0; + ethtool_cmd_speed_set(cmd, SPEED_10); + cmd->duplex = DUPLEX_FULL; + cmd->port = PORT_TP; + cmd->phy_address = 0; + cmd->transceiver = XCVR_INTERNAL; + cmd->autoneg = AUTONEG_DISABLE; + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 0; + return 0; +} + +static void tun_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct tun_struct *tun = netdev_priv(dev); + + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + + switch (tun->flags & TUN_TYPE_MASK) { + case IFF_TUN: + strlcpy(info->bus_info, "tun", sizeof(info->bus_info)); + break; + case IFF_TAP: + strlcpy(info->bus_info, "tap", sizeof(info->bus_info)); + break; + } +} + +static u32 tun_get_msglevel(struct net_device *dev) +{ +#ifdef TUN_DEBUG + struct tun_struct *tun = netdev_priv(dev); + return tun->debug; +#else + return -EOPNOTSUPP; +#endif +} + +static void tun_set_msglevel(struct net_device *dev, u32 value) +{ +#ifdef TUN_DEBUG + struct tun_struct *tun = netdev_priv(dev); + tun->debug = value; +#endif +} + +static const struct ethtool_ops tun_ethtool_ops = { + .get_settings = tun_get_settings, + .get_drvinfo = tun_get_drvinfo, + .get_msglevel = tun_get_msglevel, + .set_msglevel = tun_set_msglevel, + .get_link = ethtool_op_get_link, + .get_ts_info = ethtool_op_get_ts_info, +}; + +static int tun_queue_resize(struct tun_struct *tun) +{ + struct net_device *dev = tun->dev; + struct tun_file *tfile; + struct skb_array **arrays; + int n = tun->numqueues + tun->numdisabled; + int ret, i; + + arrays = kmalloc(sizeof *arrays * n, GFP_KERNEL); + if (!arrays) + return -ENOMEM; + + for (i = 0; i < tun->numqueues; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + arrays[i] = &tfile->tx_array; + } + list_for_each_entry(tfile, &tun->disabled, next) + arrays[i++] = &tfile->tx_array; + + ret = skb_array_resize_multiple(arrays, n, + dev->tx_queue_len, GFP_KERNEL); + + kfree(arrays); + return ret; +} + +static int tun_device_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct tun_struct *tun = netdev_priv(dev); + + if (dev->rtnl_link_ops != &tun_link_ops) + return NOTIFY_DONE; + + switch (event) { + case NETDEV_CHANGE_TX_QUEUE_LEN: + if (tun_queue_resize(tun)) + return NOTIFY_BAD; + break; + default: + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block tun_notifier_block __read_mostly = { + .notifier_call = tun_device_event, +}; + +static int __init tun_init(void) +{ + int ret = 0; + + pr_info("%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); + pr_info("%s\n", DRV_COPYRIGHT); + + ret = rtnl_link_register(&tun_link_ops); + if (ret) { + pr_err("Can't register link_ops\n"); + goto err_linkops; + } + + ret = misc_register(&tun_miscdev); + if (ret) { + pr_err("Can't register misc device %d\n", TUN_MINOR1); + goto err_misc; + } + + register_netdevice_notifier(&tun_notifier_block); + return 0; +err_misc: + rtnl_link_unregister(&tun_link_ops); +err_linkops: + return ret; +} + +static void tun_cleanup(void) +{ + misc_deregister(&tun_miscdev); + rtnl_link_unregister(&tun_link_ops); + unregister_netdevice_notifier(&tun_notifier_block); +} + +/* Get an underlying socket object from tun file. Returns error unless file is + * attached to a device. The returned object works like a packet socket, it + * can be used for sock_sendmsg/sock_recvmsg. The caller is responsible for + * holding a reference to the file for as long as the socket is in use. */ +struct socket *tun_get_socket(struct file *file) +{ + struct tun_file *tfile; + if (file->f_op != &tun_fops) + return ERR_PTR(-EINVAL); + tfile = file->private_data; + if (!tfile) + return ERR_PTR(-EBADFD); + return &tfile->socket; +} +EXPORT_SYMBOL_GPL(tun_get_socket); + +module_init(tun_init); +module_exit(tun_cleanup); +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR(DRV_COPYRIGHT); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(TUN_MINOR1); +MODULE_ALIAS("devname:net/bf_tun"); diff --git a/platform/barefoot/bfn-platform-ingrasys.mk b/platform/barefoot/bfn-platform-ingrasys.mk new file mode 100644 index 000000000000..20dc5f866f38 --- /dev/null +++ b/platform/barefoot/bfn-platform-ingrasys.mk @@ -0,0 +1,5 @@ +BFN_INGRASYS_PLATFORM = bfnplatform-ingrasys_8.2.0_amd64.deb +$(BFN_INGRASYS_PLATFORM)_URL = "https://github.com/Ingrasys-sonic/packages/raw/master/lib/bfnplatform-ingrasys_8.4.0_8.5.0_amd64.deb" + +SONIC_ONLINE_DEBS += $(BFN_INGRASYS_PLATFORM) # $(BFN_SAI_DEV) +$(BFN_SAI_DEV)_DEPENDS += $(BFN_INGRASYS_PLATFORM) diff --git a/platform/barefoot/bfn-platform-wnc.mk b/platform/barefoot/bfn-platform-wnc.mk new file mode 100644 index 000000000000..e2f45d35b2b8 --- /dev/null +++ b/platform/barefoot/bfn-platform-wnc.mk @@ -0,0 +1,5 @@ +WNC_OSW1800_PLATFORM = bfnplatformwnc_1.0.0_amd64.deb +$(WNC_OSW1800_PLATFORM)_URL = "https://github.com/YaoTien/download/raw/master/sonic/sde/7_0_0_18/bfnplatformwnc_1.0.0_amd64.deb" + +SONIC_ONLINE_DEBS += $(WNC_OSW1800_PLATFORM) # $(BFN_SAI_DEV) +$(BFN_SAI_DEV)_DEPENDS += $(WNC_OSW1800_PLATFORM) diff --git a/platform/barefoot/bfn-platform.mk b/platform/barefoot/bfn-platform.mk new file mode 100644 index 000000000000..72315b1ca553 --- /dev/null +++ b/platform/barefoot/bfn-platform.mk @@ -0,0 +1,5 @@ +BFN_PLATFORM = bfnplatform_1.0.0_amd64.deb +$(BFN_PLATFORM)_URL = "https://github.com/barefootnetworks/sonic-release-pkgs/raw/sde-sai1.3.3/bfnplatform_1.0.0_amd64.deb" + +SONIC_ONLINE_DEBS += $(BFN_PLATFORM) # $(BFN_SAI_DEV) +$(BFN_SAI_DEV)_DEPENDS += $(BFN_PLATFORM) diff --git a/platform/barefoot/bfn-sai.mk b/platform/barefoot/bfn-sai.mk new file mode 100644 index 000000000000..34c9f5ffc244 --- /dev/null +++ b/platform/barefoot/bfn-sai.mk @@ -0,0 +1,5 @@ +BFN_SAI = bfnsdk_1.0.0_amd64.deb +$(BFN_SAI)_URL = "https://github.com/barefootnetworks/sonic-release-pkgs/raw/sde-sai1.3.3/bfnsdk_1.0.0_amd64.deb" + +SONIC_ONLINE_DEBS += $(BFN_SAI) # $(BFN_SAI_DEV) +$(BFN_SAI_DEV)_DEPENDS += $(BFN_SAI) diff --git a/platform/barefoot/docker-orchagent-bfn.mk b/platform/barefoot/docker-orchagent-bfn.mk new file mode 100644 index 000000000000..fefd39691855 --- /dev/null +++ b/platform/barefoot/docker-orchagent-bfn.mk @@ -0,0 +1,24 @@ +# docker image for orchagent + +DOCKER_ORCHAGENT_BFN = docker-orchagent-bfn.gz +$(DOCKER_ORCHAGENT_BFN)_PATH = $(DOCKERS_PATH)/docker-orchagent +$(DOCKER_ORCHAGENT_BFN)_DEPENDS += $(SWSS) $(REDIS_TOOLS) $(IPROUTE2) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_ORCHAGENT_BFN)_DEPENDS += $(SWSS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_ORCHAGENT_BFN)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_BFN) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_BFN) + +$(DOCKER_ORCHAGENT_BFN)_CONTAINER_NAME = swss +$(DOCKER_ORCHAGENT_BFN)_RUN_OPT += --net=host --privileged -t +$(DOCKER_ORCHAGENT_BFN)_RUN_OPT += -v /etc/network/interfaces:/etc/network/interfaces:ro +$(DOCKER_ORCHAGENT_BFN)_RUN_OPT += -v /etc/network/interfaces.d/:/etc/network/interfaces.d/:ro +$(DOCKER_ORCHAGENT_BFN)_RUN_OPT += -v /host/machine.conf:/host/machine.conf:ro +$(DOCKER_ORCHAGENT_BFN)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_ORCHAGENT_BFN)_RUN_OPT += -v /var/log/swss:/var/log/swss:rw + +$(DOCKER_ORCHAGENT_BFN)_BASE_IMAGE_FILES += swssloglevel:/usr/bin/swssloglevel +$(DOCKER_ORCHAGENT_BFN)_FILES += $(ARP_UPDATE_SCRIPT) diff --git a/platform/barefoot/docker-ptf-bfn.mk b/platform/barefoot/docker-ptf-bfn.mk new file mode 100644 index 000000000000..573e9cd9cffa --- /dev/null +++ b/platform/barefoot/docker-ptf-bfn.mk @@ -0,0 +1,5 @@ +# docker image for docker-ptf + +DOCKER_PTF_BFN = docker-ptf-bfn.gz +$(DOCKER_PTF_BFN)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift +$(DOCKER_PTF_BFN)_LOAD_DOCKERS += $(DOCKER_PTF) diff --git a/platform/barefoot/docker-saiserver-bfn/Dockerfile b/platform/barefoot/docker-saiserver-bfn/Dockerfile new file mode 100755 index 000000000000..427a551e0096 --- /dev/null +++ b/platform/barefoot/docker-saiserver-bfn/Dockerfile @@ -0,0 +1,38 @@ +FROM docker-base + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY ["deps/applibs_*.deb", "/deps/applibs-dev_*.deb", "/deps/sx-complib_*.deb", "/deps/sxd-libs_*.deb", "/deps/sx-scew_*.deb", "/deps/sx-examples_*.deb", "/deps/sx-gen-utils_*.deb", "/deps/python-sdk-api_*.deb", "/deps/iproute2_*.deb", "/deps/mlnx-sai_*.deb", "/deps/libthrift-0.9.3_*.deb", "/deps/libnl-3-200_*.deb", "/deps/libnl-genl-3-200_*.deb", "/deps/libnl-route-3-200_*.deb", "/deps/"] + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; \ + 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/iproute2_*.deb \ + && dpkg_apt /deps/mlnx-sai_*.deb \ + && dpkg_apt /deps/libthrift-0.9.3_*.deb \ + && dpkg_apt /deps/libnl-3-200_*.deb \ + && dpkg_apt /deps/libnl-genl-3-200_*.deb \ + && dpkg_apt /deps/libnl-route-3-200_*.deb + +COPY ["deps/saiserver", "start.sh", "/usr/bin/"] + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +COPY ["profile.ini", "portmap.ini", "/etc/sai/"] + + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /deps + +ENTRYPOINT ["/usr/bin/supervisord"] + diff --git a/platform/barefoot/docker-saiserver-bfn/portmap.ini b/platform/barefoot/docker-saiserver-bfn/portmap.ini new file mode 100644 index 000000000000..4d3be08ce5f8 --- /dev/null +++ b/platform/barefoot/docker-saiserver-bfn/portmap.ini @@ -0,0 +1,33 @@ +# alias lanes +Ethernet1 0,1,2,3 +Ethernet2 4,5,6,7 +Ethernet3 8,9,10,11 +Ethernet4 12,13,14,15 +Ethernet5 16,17,18,19 +Ethernet6 20,21,22,23 +Ethernet7 24,25,26,27 +Ethernet8 28,29,30,31 +Ethernet9 32,33,34,35 +Ethernet10 36,37,38,39 +Ethernet11 40,41,42,43 +Ethernet12 44,45,46,47 +Ethernet13 48,49,50,51 +Ethernet14 52,53,54,55 +Ethernet15 56,57,58,59 +Ethernet16 60,61,62,63 +Ethernet17 64,65,66,67 +Ethernet18 68,69,70,71 +Ethernet19 72,73,74,75 +Ethernet20 76,77,78,79 +Ethernet21 80,81,82,83 +Ethernet22 84,85,86,87 +Ethernet23 88,89,90,91 +Ethernet24 92,93,94,95 +Ethernet25 96,97,98,99 +Ethernet26 100,101,102,103 +Ethernet27 104,105,106,107 +Ethernet28 108,109,110,111 +Ethernet29 112,113,114,115 +Ethernet30 116,117,118,119 +Ethernet31 120,121,122,123 +Ethernet32 124,125,126,127 \ No newline at end of file diff --git a/platform/barefoot/docker-saiserver-bfn/profile.ini b/platform/barefoot/docker-saiserver-bfn/profile.ini new file mode 100644 index 000000000000..b20b2c6f0e06 --- /dev/null +++ b/platform/barefoot/docker-saiserver-bfn/profile.ini @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sai_tofino.xml diff --git a/platform/barefoot/docker-saiserver-bfn/sai_tofino.xml b/platform/barefoot/docker-saiserver-bfn/sai_tofino.xml new file mode 100644 index 000000000000..139597f9cb07 --- /dev/null +++ b/platform/barefoot/docker-saiserver-bfn/sai_tofino.xml @@ -0,0 +1,2 @@ + + diff --git a/platform/barefoot/docker-saiserver-bfn/start.sh b/platform/barefoot/docker-saiserver-bfn/start.sh new file mode 100755 index 000000000000..16457d13e03a --- /dev/null +++ b/platform/barefoot/docker-saiserver-bfn/start.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start saiserver + diff --git a/platform/barefoot/docker-saiserver-bfn/supervisord.conf b/platform/barefoot/docker-saiserver-bfn/supervisord.conf new file mode 100644 index 000000000000..e09ac3cbb449 --- /dev/null +++ b/platform/barefoot/docker-saiserver-bfn/supervisord.conf @@ -0,0 +1,29 @@ +[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:saiserver] +command=/usr/bin/saiserver -p /etc/sai/profile.ini -f /etc/sai/portmap.ini +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + diff --git a/platform/barefoot/docker-syncd-bfn-rpc.mk b/platform/barefoot/docker-syncd-bfn-rpc.mk new file mode 100644 index 000000000000..61f5570c1612 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn-rpc.mk @@ -0,0 +1,15 @@ +# docker image for syncd with rpc + +DOCKER_SYNCD_BFN_RPC = docker-syncd-bfn-rpc.gz +$(DOCKER_SYNCD_BFN_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-bfn-rpc +$(DOCKER_SYNCD_BFN_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) +$(DOCKER_SYNCD_BFN_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BFN) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_BFN_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_BFN_RPC) +endif + +$(DOCKER_SYNCD_BFN_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_BFN_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_BFN_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_BFN_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 b/platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..68604d92f6b5 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 @@ -0,0 +1,53 @@ +FROM docker-syncd-bfn + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_bfn_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -P syncd + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_bfn_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + libpython3.4 \ + && wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/bin/supervisord"] + diff --git a/platform/barefoot/docker-syncd-bfn-rpc/ptf_nn_agent.conf b/platform/barefoot/docker-syncd-bfn-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/barefoot/docker-syncd-bfn.mk b/platform/barefoot/docker-syncd-bfn.mk new file mode 100644 index 000000000000..22bb10763e75 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn.mk @@ -0,0 +1,15 @@ +# docker image for syncd + +DOCKER_SYNCD_BFN = docker-syncd-bfn.gz +$(DOCKER_SYNCD_BFN)_PATH = $(PLATFORM_PATH)/docker-syncd-bfn +$(DOCKER_SYNCD_BFN)_DEPENDS += $(SYNCD) +$(DOCKER_SYNCD_BFN)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_BFN) +ifneq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_BFN) +endif + +$(DOCKER_SYNCD_BFN)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_BFN)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_BFN)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_BFN)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/barefoot/docker-syncd-bfn/Dockerfile.j2 b/platform/barefoot/docker-syncd-bfn/Dockerfile.j2 new file mode 100755 index 000000000000..25c7872f6460 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn/Dockerfile.j2 @@ -0,0 +1,29 @@ +FROM docker-config-engine + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_syncd_bfn_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get install -y libxml2 libpcap-dev libusb-1.0-0-dev libcurl3 libcurl4-gnutls-dev libunwind8-dev libpython3.4 + +RUN dpkg -i \ +{% for deb in docker_syncd_bfn_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] + diff --git a/platform/barefoot/docker-syncd-bfn/start.sh b/platform/barefoot/docker-syncd-bfn/start.sh new file mode 100755 index 000000000000..1a39db4a9d83 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn/start.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +. /opt/bfn/install/bin/dma_setup.sh +# . /opt/bfn/install/bin/bf_kdrv_mod_load /opt/bfn/install +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/bfn/install/lib supervisorctl start syncd diff --git a/platform/barefoot/docker-syncd-bfn/supervisord.conf b/platform/barefoot/docker-syncd-bfn/supervisord.conf new file mode 100644 index 000000000000..1e015fef931f --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn/supervisord.conf @@ -0,0 +1,29 @@ +[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:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + diff --git a/platform/barefoot/libsaithrift-dev.mk b/platform/barefoot/libsaithrift-dev.mk new file mode 100644 index 000000000000..c9c8cbb3adca --- /dev/null +++ b/platform/barefoot/libsaithrift-dev.mk @@ -0,0 +1,7 @@ +# libsaithrift-dev package + +LIBSAITHRIFT_DEV_BFN = libsaithrift-dev_0.9.4_amd64.deb +$(LIBSAITHRIFT_DEV_BFN)_SRC_PATH = $(SRC_PATH)/SAI +$(LIBSAITHRIFT_DEV_BFN)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(THRIFT_COMPILER) $(BFN_SAI) $(BFN_SAI_DEV) +$(LIBSAITHRIFT_DEV_BFN)_RDEPENDS += $(LIBTHRIFT) $(BFN_SAI) +#SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV_BFN) diff --git a/platform/barefoot/one-aboot.mk b/platform/barefoot/one-aboot.mk new file mode 100644 index 000000000000..71e3a95da3ab --- /dev/null +++ b/platform/barefoot/one-aboot.mk @@ -0,0 +1,14 @@ +# sonic one aboot installer + +SONIC_ONE_ABOOT_IMAGE = sonic-aboot-barefoot.swi +$(SONIC_ONE_ABOOT_IMAGE)_MACHINE = barefoot +$(SONIC_ONE_ABOOT_IMAGE)_IMAGE_TYPE = aboot +$(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(BFN_MODULE) +$(SONIC_ONE_ABOOT_IMAGE)_LAZY_INSTALLS += $(BFN_PLATFORM_MODULE) +$(SONIC_ONE_ABOOT_IMAGE)_LAZY_INSTALLS += $(BFN_MONTARA_PLATFORM_MODULE) +$(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(ARISTA_PLATFORM_MODULE_DRIVERS) \ + $(ARISTA_PLATFORM_MODULE_PYTHON2) \ + $(ARISTA_PLATFORM_MODULE_PYTHON3) \ + $(ARISTA_PLATFORM_MODULE) +$(SONIC_ONE_ABOOT_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_ONE_ABOOT_IMAGE) diff --git a/platform/barefoot/one-image.mk b/platform/barefoot/one-image.mk new file mode 100644 index 000000000000..fc4e197cd5cb --- /dev/null +++ b/platform/barefoot/one-image.mk @@ -0,0 +1,13 @@ +# sonic one image installer + +SONIC_ONE_IMAGE = sonic-barefoot.bin +$(SONIC_ONE_IMAGE)_MACHINE = barefoot +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(BFN_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(BFN_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(BFN_MONTARA_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(WNC_OSW1800_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(INGRASYS_S9180_32X_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(INGRASYS_S9280_64X_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/barefoot/platform-modules-arista.mk b/platform/barefoot/platform-modules-arista.mk new file mode 100644 index 000000000000..480aa0cf8396 --- /dev/null +++ b/platform/barefoot/platform-modules-arista.mk @@ -0,0 +1,25 @@ +# Arista Platform modules + +ARISTA_PLATFORM_MODULE_VERSION = 1.0 + +export ARISTA_PLATFORM_MODULE_VERSION + +ARISTA_PLATFORM_MODULE = sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_amd64.deb +$(ARISTA_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-arista +$(ARISTA_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_MAKE_DEBS += $(ARISTA_PLATFORM_MODULE) + +ARISTA_PLATFORM_MODULE_PYTHON2 = python-sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_all.deb +$(eval $(call add_extra_package,$(ARISTA_PLATFORM_MODULE),$(ARISTA_PLATFORM_MODULE_PYTHON2))) + +ARISTA_PLATFORM_MODULE_PYTHON3 = python3-sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_all.deb +$(eval $(call add_extra_package,$(ARISTA_PLATFORM_MODULE),$(ARISTA_PLATFORM_MODULE_PYTHON3))) + +ARISTA_PLATFORM_MODULE_DRIVERS = drivers-sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_amd64.deb +$(eval $(call add_extra_package,$(ARISTA_PLATFORM_MODULE),$(ARISTA_PLATFORM_MODULE_DRIVERS))) + +export ARISTA_PLATFORM_MODULE ARISTA_PLATFORM_MODULE_PYTHON2 ARISTA_PLATFORM_MODULE_PYTHON3 ARISTA_PLATFORM_MODULE_DRIVERS + +export ARISTA_SCD_DRIVER_CONFIG=m + +SONIC_STRETCH_DEBS += $(ARISTA_PLATFORM_MODULE) diff --git a/platform/barefoot/platform-modules-bfn-montara.mk b/platform/barefoot/platform-modules-bfn-montara.mk new file mode 100644 index 000000000000..d089218c9454 --- /dev/null +++ b/platform/barefoot/platform-modules-bfn-montara.mk @@ -0,0 +1,13 @@ +# BFN Platform modules + +BFN_MONTARA_PLATFORM_MODULE_VERSION = 1.1 + +export BFN_MONTARA_PLATFORM_MODULE_VERSION + +BFN_MONTARA_PLATFORM_MODULE = sonic-platform-modules-bfn-montara_$(BFN_MONTARA_PLATFORM_MODULE_VERSION)_amd64.deb +$(BFN_MONTARA_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-bfn-montara +$(BFN_MONTARA_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(BFN_MONTARA_PLATFORM_MODULE)_PLATFORM = x86_64-accton_wedge100bf_32x-r0 +SONIC_DPKG_DEBS += $(BFN_MONTARA_PLATFORM_MODULE) + +SONIC_STRETCH_DEBS += $(BFN_MONTARA_PLATFORM_MODULE) diff --git a/platform/barefoot/platform-modules-bfn.mk b/platform/barefoot/platform-modules-bfn.mk new file mode 100644 index 000000000000..1caa92c8f2b3 --- /dev/null +++ b/platform/barefoot/platform-modules-bfn.mk @@ -0,0 +1,13 @@ +# BFN Platform modules + +BFN_PLATFORM_MODULE_VERSION = 1.1 + +export BFN_PLATFORM_MODULE_VERSION + +BFN_PLATFORM_MODULE = sonic-platform-modules-bfn_$(BFN_PLATFORM_MODULE_VERSION)_amd64.deb +$(BFN_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-bfn +$(BFN_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(BFN_PLATFORM_MODULE)_PLATFORM = x86_64-accton_wedge100bf_65x-r0 +SONIC_DPKG_DEBS += $(BFN_PLATFORM_MODULE) + +SONIC_STRETCH_DEBS += $(BFN_PLATFORM_MODULE) diff --git a/platform/barefoot/platform-modules-ingrasys.mk b/platform/barefoot/platform-modules-ingrasys.mk new file mode 100644 index 000000000000..ea8f68c003fc --- /dev/null +++ b/platform/barefoot/platform-modules-ingrasys.mk @@ -0,0 +1,20 @@ +# Ingrasys S9180-32X Platform modules + +INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION = 1.1.0 +INGRASYS_S9280_64X_PLATFORM_MODULE_VERSION = 1.1.0 + +export INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION +export INGRASYS_S9280_64X_PLATFORM_MODULE_VERSION + +INGRASYS_S9180_32X_PLATFORM_MODULE = sonic-platform-ingrasys-s9180-32x_$(INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S9180_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-ingrasys +$(INGRASYS_S9180_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(INGRASYS_S9180_32X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9180_32x-r0 +SONIC_DPKG_DEBS += $(INGRASYS_S9180_32X_PLATFORM_MODULE) + +INGRASYS_S9280_64X_PLATFORM_MODULE = sonic-platform-ingrasys-s9280-64x_$(INGRASYS_S9280_64X_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S9280_64X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9280_64x-r0 + +$(eval $(call add_extra_package,$(INGRASYS_S9180_32X_PLATFORM_MODULE),$(INGRASYS_S9280_64X_PLATFORM_MODULE))) + +SONIC_STRETCH_DEBS += $(INGRASYS_S9180_32X_PLATFORM_MODULE) diff --git a/platform/barefoot/platform-modules-wnc-osw1800.mk b/platform/barefoot/platform-modules-wnc-osw1800.mk new file mode 100644 index 000000000000..5703d069c97e --- /dev/null +++ b/platform/barefoot/platform-modules-wnc-osw1800.mk @@ -0,0 +1,13 @@ +# BFN Platform modules + +WNC_OSW1800_PLATFORM_MODULE_VERSION = 1.0 + +export WNC_OSW1800_PLATFORM_MODULE_VERSION + +WNC_OSW1800_PLATFORM_MODULE = platform-modules-wnc-osw1800_$(WNC_OSW1800_PLATFORM_MODULE_VERSION)_amd64.deb +$(WNC_OSW1800_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-wnc-osw1800 +$(WNC_OSW1800_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(WNC_OSW1800_PLATFORM_MODULE)_PLATFORM = x86_64-wnc_osw1800-r0 +SONIC_DPKG_DEBS += $(WNC_OSW1800_PLATFORM_MODULE) + +SONIC_STRETCH_DEBS += $(WNC_OSW1800_PLATFORM_MODULE) diff --git a/platform/barefoot/platform.conf b/platform/barefoot/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/barefoot/python-saithrift.mk b/platform/barefoot/python-saithrift.mk new file mode 100644 index 000000000000..ba4846402fb8 --- /dev/null +++ b/platform/barefoot/python-saithrift.mk @@ -0,0 +1,6 @@ +# python-saithrift package + +PYTHON_SAITHRIFT_BFN = python-saithrift_0.9.4_amd64.deb +$(PYTHON_SAITHRIFT_BFN)_SRC_PATH = $(SRC_PATH)/SAI +$(PYTHON_SAITHRIFT_BFN)_DEPENDS += $(BFN_SAI_DEV) $(BFN_SAI) $(THRIFT_COMPILER) $(PYTHON_THRIFT) $(LIBTHRIFT_DEV) +#SONIC_DPKG_DEBS += $(PYTHON_SAITHRIFT_BFN) diff --git a/platform/barefoot/rules.mk b/platform/barefoot/rules.mk new file mode 100644 index 000000000000..4937b747c2ed --- /dev/null +++ b/platform/barefoot/rules.mk @@ -0,0 +1,27 @@ +include $(PLATFORM_PATH)/platform-modules-arista.mk +include $(PLATFORM_PATH)/platform-modules-bfn.mk +include $(PLATFORM_PATH)/platform-modules-bfn-montara.mk +include $(PLATFORM_PATH)/platform-modules-wnc-osw1800.mk +include $(PLATFORM_PATH)/platform-modules-ingrasys.mk +include $(PLATFORM_PATH)/bfn-sai.mk +include $(PLATFORM_PATH)/docker-syncd-bfn.mk +include $(PLATFORM_PATH)/docker-syncd-bfn-rpc.mk +include $(PLATFORM_PATH)/docker-orchagent-bfn.mk +include $(PLATFORM_PATH)/one-aboot.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/python-saithrift.mk +include $(PLATFORM_PATH)/docker-ptf-bfn.mk +include $(PLATFORM_PATH)/bfn-platform.mk +include $(PLATFORM_PATH)/bfn-platform-wnc.mk +include $(PLATFORM_PATH)/bfn-platform-ingrasys.mk +include $(PLATFORM_PATH)/bfn-modules.mk + +SONIC_ALL += $(SONIC_ONE_IMAGE) $(SONIC_ONE_ABOOT) \ + $(DOCKER_FPM) + +# Inject sai into sairedis +$(LIBSAIREDIS)_DEPENDS += $(BFN_SAI) $(WNC_OSW1800_PLATFORM) $(BFN_INGRASYS_PLATFORM) $(BFN_PLATFORM) #$(LIBSAITHRIFT_DEV_BFN) + +# Runtime dependency on sai is set only for syncd +$(SYNCD)_RDEPENDS += $(BFN_SAI) $(WNC_OSW1800_PLATFORM) $(BFN_INGRASYS_PLATFORM) $(BFN_PLATFORM) diff --git a/platform/barefoot/sonic-platform-modules-arista b/platform/barefoot/sonic-platform-modules-arista new file mode 160000 index 000000000000..0fc0c23d8bb8 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-arista @@ -0,0 +1 @@ +Subproject commit 0fc0c23d8bb8826d6431f35aff12ad1a5e098395 diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/LICENSE b/platform/barefoot/sonic-platform-modules-bfn-montara/LICENSE new file mode 100644 index 000000000000..676cdeec726b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, 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 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/MAINTAINERS b/platform/barefoot/sonic-platform-modules-bfn-montara/MAINTAINERS new file mode 100644 index 000000000000..6396065f4ab0 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/MAINTAINERS @@ -0,0 +1,3 @@ +# This file describes the maintainers for sonic-platform-modules-bfn-montara +# See the SONiC project governance document for more information +Mailinglist = sonicproject@googlegroups.com diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/README.md b/platform/barefoot/sonic-platform-modules-bfn-montara/README.md new file mode 100644 index 000000000000..ac1fffb7dc43 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-bfn-montara +Device drivers for support of BFN platform for the SONiC project diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/changelog b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/changelog new file mode 100644 index 000000000000..07fbc7081419 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/changelog @@ -0,0 +1,11 @@ +sonic-platform-modules-bfn-montara (1.1) unstable; urgency=low + + * Remove bfn asic kernel modules from platform package + + -- Support Mon, 22 Oct 2018 15:40:00 -0800 + +sonic-platform-modules-bfn-montara (1.0) unstable; urgency=low + + * Initial release + + -- Support Mon, 11 Nov 2015 11:11:11 -0800 diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/compat b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/compat new file mode 100644 index 000000000000..45a4fb75db86 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control new file mode 100644 index 000000000000..d3a1f02495a5 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control @@ -0,0 +1,12 @@ +Source: sonic-platform-modules-bfn-montara +Section: main +Priority: extra +Maintainer: Support +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-modules-bfn-montara +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/copyright b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/copyright new file mode 100644 index 000000000000..ade42b7aa75a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/copyright @@ -0,0 +1,15 @@ +Provides linux kernel driver for BF PCIe devices + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules new file mode 100755 index 000000000000..479f7f489687 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules @@ -0,0 +1,19 @@ +#!/usr/bin/make -f + +PACKAGE_NAME := sonic-platform-modules-bfn-montara +SCRIPT_SRC := $(shell pwd)/scripts + +%: + dh $@ + +override_dh_auto_install: + dh_installdirs -p$(PACKAGE_NAME) usr/local/bin + cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_NAME)/usr/local/bin + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/eeprom b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/eeprom new file mode 100755 index 000000000000..07d98556cbbf --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/eeprom @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd eeprom "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/fancontrol b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/fancontrol new file mode 100755 index 000000000000..515fcbdd69da --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/fancontrol @@ -0,0 +1,11 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd fancontrol "$@" + diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/ps_info b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/ps_info new file mode 100755 index 000000000000..38c9d3330414 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/ps_info @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd ps_info "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sensors b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sensors new file mode 100755 index 000000000000..07af6955321e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sensors @@ -0,0 +1,12 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd sensors "$@" + + diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sfputil b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sfputil new file mode 100755 index 000000000000..3df67614e499 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sfputil @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd sfputil "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/test b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/test new file mode 100755 index 000000000000..38327722c91f --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/test @@ -0,0 +1 @@ +echo "test" diff --git a/platform/barefoot/sonic-platform-modules-bfn/LICENSE b/platform/barefoot/sonic-platform-modules-bfn/LICENSE new file mode 100644 index 000000000000..676cdeec726b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, 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 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn/MAINTAINERS b/platform/barefoot/sonic-platform-modules-bfn/MAINTAINERS new file mode 100644 index 000000000000..b9c62ce01546 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/MAINTAINERS @@ -0,0 +1,4 @@ +# This file describes the maintainers for sonic-platform-modules-bfn +# See the SONiC project governance document for more information + +Mailinglist = sonicproject@googlegroups.com diff --git a/platform/barefoot/sonic-platform-modules-bfn/README.md b/platform/barefoot/sonic-platform-modules-bfn/README.md new file mode 100644 index 000000000000..5dc055a1d9c3 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-bfn +Device drivers for support of BFN platform for the SONiC project diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/changelog b/platform/barefoot/sonic-platform-modules-bfn/debian/changelog new file mode 100644 index 000000000000..984cc0dbfb69 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/changelog @@ -0,0 +1,11 @@ +sonic-platform-modules-bfn (1.1) unstable; urgency=low + + * Remove bfn asic kernel modules from platform package + + -- Support Mon, 22 Oct 2018 15:40:00 -0800 + +sonic-platform-modules-bfn (1.0) unstable; urgency=low + + * Initial release + + -- Support Mon, 11 Nov 2015 11:11:11 -0800 diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/compat b/platform/barefoot/sonic-platform-modules-bfn/debian/compat new file mode 100644 index 000000000000..45a4fb75db86 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/control b/platform/barefoot/sonic-platform-modules-bfn/debian/control new file mode 100644 index 000000000000..fe82a2336d4e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/control @@ -0,0 +1,12 @@ +Source: sonic-platform-modules-bfn +Section: main +Priority: extra +Maintainer: support +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-modules-bfn +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/copyright b/platform/barefoot/sonic-platform-modules-bfn/debian/copyright new file mode 100644 index 000000000000..ade42b7aa75a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/copyright @@ -0,0 +1,15 @@ +Provides linux kernel driver for BF PCIe devices + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/files b/platform/barefoot/sonic-platform-modules-bfn/debian/files new file mode 100644 index 000000000000..1cfb92c60ae1 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/files @@ -0,0 +1 @@ +platform-modules-bfn_1.0_amd64.deb main extra diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/rules b/platform/barefoot/sonic-platform-modules-bfn/debian/rules new file mode 100755 index 000000000000..69946c33571e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/rules @@ -0,0 +1,19 @@ +#!/usr/bin/make -f + +PACKAGE_NAME := sonic-platform-modules-bfn +SCRIPT_SRC := $(shell pwd)/scripts + +%: + dh $@ + +override_dh_auto_install: + dh_installdirs -p$(PACKAGE_NAME) usr/local/bin + cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_NAME)/usr/local/bin + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + diff --git a/platform/barefoot/sonic-platform-modules-bfn/scripts/eeprom b/platform/barefoot/sonic-platform-modules-bfn/scripts/eeprom new file mode 100755 index 000000000000..07d98556cbbf --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/scripts/eeprom @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd eeprom "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn/scripts/fancontrol b/platform/barefoot/sonic-platform-modules-bfn/scripts/fancontrol new file mode 100755 index 000000000000..515fcbdd69da --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/scripts/fancontrol @@ -0,0 +1,11 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd fancontrol "$@" + diff --git a/platform/barefoot/sonic-platform-modules-bfn/scripts/ps_info b/platform/barefoot/sonic-platform-modules-bfn/scripts/ps_info new file mode 100755 index 000000000000..38c9d3330414 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/scripts/ps_info @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd ps_info "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn/scripts/sensors b/platform/barefoot/sonic-platform-modules-bfn/scripts/sensors new file mode 100755 index 000000000000..07af6955321e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/scripts/sensors @@ -0,0 +1,12 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd sensors "$@" + + diff --git a/platform/barefoot/sonic-platform-modules-bfn/scripts/sfputil b/platform/barefoot/sonic-platform-modules-bfn/scripts/sfputil new file mode 100755 index 000000000000..3df67614e499 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/scripts/sfputil @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd sfputil "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn/scripts/test b/platform/barefoot/sonic-platform-modules-bfn/scripts/test new file mode 100755 index 000000000000..38327722c91f --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/scripts/test @@ -0,0 +1 @@ +echo "test" diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/.gitignore b/platform/barefoot/sonic-platform-modules-ingrasys/.gitignore new file mode 100644 index 000000000000..c6127b38c1aa --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/.gitignore @@ -0,0 +1,52 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/LICENSE b/platform/barefoot/sonic-platform-modules-ingrasys/LICENSE new file mode 100644 index 000000000000..9cecc1d4669e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/changelog b/platform/barefoot/sonic-platform-modules-ingrasys/debian/changelog new file mode 100644 index 000000000000..cfbeb17d018a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/changelog @@ -0,0 +1,11 @@ +platform-driver (1.1.0) unstable; urgency=low + + * Add support for s9180-32x s9280-64x + + -- developer Fri, 26 May 2017 11:00:00 +0800 + +platform-driver (1.0.0) unstable; urgency=low + + * Initial release (Closes: #nnnn) + + -- developer Wed, 05 Oct 2016 16:30:45 +0800 diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/compat b/platform/barefoot/sonic-platform-modules-ingrasys/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/control b/platform/barefoot/sonic-platform-modules-ingrasys/debian/control new file mode 100644 index 000000000000..a912ed8ace2e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/control @@ -0,0 +1,14 @@ +Source: platform-driver +Section: unknown +Priority: optional +Maintainer: Wade He +Build-Depends: debhelper (>= 9), dh-systemd +Standards-Version: 1.0.0 + +Package: sonic-platform-ingrasys-s9180-32x +Architecture: amd64 +Description: This package contains S9180-32X platform driver utility for SONiC project. + +Package: sonic-platform-ingrasys-s9280-64x +Architecture: amd64 +Description: This package contains S9280-64X platform driver utility for SONiC project. diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/rules b/platform/barefoot/sonic-platform-modules-ingrasys/debian/rules new file mode 100755 index 000000000000..428b4731eb75 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/rules @@ -0,0 +1,42 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_PRE_NAME := sonic-platform-ingrasys +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= s9180-32x s9280-64x +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CONF_DIR := conf + +%: + dh $@ --with systemd + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/sbin; \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/*.sh \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/sbin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + done) + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.init b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.init new file mode 100644 index 000000000000..9479fa354949 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S9180-32X board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9180-32x.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9280-64x.init b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9280-64x.init new file mode 100644 index 000000000000..545ec8e9987a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9280-64x.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S9280-64X board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9280-64x.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/README.md b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/README.md new file mode 100644 index 000000000000..fa3760ab9ab7 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/README.md @@ -0,0 +1,185 @@ +# Ingrasys S9180-32X Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, 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 . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S9180-32X is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S9180-32X platform. + +### I2C i801 + +The I2C i801 on Ingrasys S9180-32X can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S9180-32X. + +### I2C iSMT + +The I2C iSMT module on S9180-32X can be found in +`/sys/bus/i2c/devices/i2c-1/` + +This is I2C bus for CPLD, HWM, power controller and I2C Switches. + +The i801 module must be loaded third on Ingrasys S9180-32X. + +### I2C PCA9548 +The PCA9548 module on S9180-32X can be found in +`/sys/bus/i2c/devices/i2c-2/` , `/sys/bus/i2c/devices/i2c-3/`, +`/sys/bus/i2c/devices/i2c-4/`, `/sys/bus/i2c/devices/i2c-5/`, +`/sys/bus/i2c/devices/i2c-6/`, `/sys/bus/i2c/devices/i2c-7/`, +`/sys/bus/i2c/devices/i2c-8/`, `/sys/bus/i2c/devices/i2c-9/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S9180-32X. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S9180-32X platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s9180 package is installed on the S9180-32X, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-9/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/9-0054/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber on|off + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon3/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon3/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/Makefile b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/Makefile new file mode 100644 index 000000000000..df7bfd3e770e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m := eeprom_mb.o +obj-m+= cpld_wdt.o + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/cpld_wdt.c b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/cpld_wdt.c new file mode 100644 index 000000000000..4cf70b4b80ab --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/cpld_wdt.c @@ -0,0 +1,296 @@ +/* + * CPLD Watchdog Driver + * + * Copyright (c) 2018 Ingrasys Corp. + * + * Author: Wade He + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * Includes, defines, variables, module parameters, ... + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +/* Module and version information */ +#define DRV_NAME "cpld_wdt" +#define DRV_VERSION "1.0" + +/* Includes */ +#include /* For module specific items */ +#include /* For new moduleparam's */ +#include /* For standard types (like size_t) */ +#include /* For the -ENODEV/... values */ +#include /* For printk/panic/... */ +#include /* For the watchdog specific items */ +#include /* For __init/__exit/... */ +#include /* For file operations */ +#include /* For platform_driver framework */ +#include /* For pci functions */ +#include /* For io-port access */ +#include /* For spin_lock/spin_unlock/... */ +#include /* For copy_to_user/put_user/... */ +#include /* For inb/outb/... */ +#include +#include +#include +#include + + +/* Address definitions for the CPLD */ +/* CPLD base address */ +#define TCOBASE 0x600 +/* SMI Control and Enable Register */ + +#define TCO_RLD (TCOBASE + 0x00) /* TCO Timer Reload and Curr. Value */ +#define TCOv1_TMR (TCOBASE + 0x01) /* TCOv1 Timer Initial Value */ +#define TCO_DAT_IN (TCOBASE + 0x02) /* TCO Data In Register */ +#define TCO_DAT_OUT (TCOBASE + 0x03) /* TCO Data Out Register */ +#define TCO1_STS (TCOBASE + 0x04) /* Control Watchdog Register */ +#define TCO2_STS (TCOBASE + 0x06) /* TCO2 Status Register */ +#define TCO1_CNT (TCOBASE + 0x08) /* TCO1 Control Register */ +#define TCO2_CNT (TCOBASE + 0x0a) /* TCO2 Control Register */ +#define TCOv2_TMR (TCOBASE + 0x12) /* TCOv2 Timer Initial Value */ + +#define DEBUG +#ifdef DEBUG + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define ERROR_MSG(fmt, args...) \ + printk(KERN_ERR "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) + + + +/* internal variables */ +static struct { /* this is private data for the cpld_wdt device */ + /* the lock for io operations */ + spinlock_t io_lock; + struct platform_device *dev; +} cpld_wdt_private; + +static struct task_struct *cpld_wdt_tsk; +static int data; + +static void device_release(struct device *dev) +{ + return; +} + +static struct platform_device cpld_wdt = { + .name = DRV_NAME, + .id = 0, + .dev = { + .platform_data = NULL, + .release = device_release + }, +}; + +/* module parameters */ +#define WATCHDOG_TIMEOUT 15 /* 15 sec default heartbeat */ +static int heartbeat = WATCHDOG_TIMEOUT; /* in seconds */ +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog ping period in seconds. " + "5..20, default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, + "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + + +static int cpld_wdt_check_timeout_range(unsigned int tmrval) +{ + if (tmrval < 5 || tmrval > 20) { + DEBUG_PRINT("heartbeat out of range, using default=%d\n", WATCHDOG_TIMEOUT); + heartbeat = WATCHDOG_TIMEOUT; + } else { + DEBUG_PRINT("heartbeat using %d seconds\n", heartbeat); + } + + return 0; +} + +/* + * Some TCO specific functions + */ + +static int cpld_wdt_stop(void *arg) +{ + + spin_lock(&cpld_wdt_private.io_lock); + + outb(0x1, TCO1_STS); + + DEBUG_PRINT("cpld_wdt_stop done"); + + spin_unlock(&cpld_wdt_private.io_lock); + + return 0; +} + +static int cpld_wdt_ping(void *arg) +{ + spin_lock(&cpld_wdt_private.io_lock); + + /* Reload the timer by writing to the TCO Timer Counter register */ + outb(0x1, TCO1_STS); /* write 1 to clear bit */ + udelay(100); + outb(0x3, TCO1_STS); + + DEBUG_PRINT("cpld_wdt_ping done"); + + spin_unlock(&cpld_wdt_private.io_lock); + return 0; +} + +static int kthread_wdt_ping_loop(void *arg) +{ + int i; + + set_current_state(TASK_INTERRUPTIBLE); + + while(!kthread_should_stop()) { + DEBUG_PRINT("ping start"); + cpld_wdt_ping(NULL); + set_current_state(TASK_INTERRUPTIBLE); + for (i=0;i"); +MODULE_DESCRIPTION("CPLD Watchdog Timer Kernel Driver"); +MODULE_VERSION(DRV_VERSION); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/eeprom_mb.c b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/eeprom_mb.c new file mode 100644 index 000000000000..61f0caf96130 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/eeprom_mb.c @@ -0,0 +1,211 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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 + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + + +/* 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 mb_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 mb_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++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_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, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/qsfp-monitor.service b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/qsfp-monitor.service new file mode 100644 index 000000000000..fde9dcf9f50a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s9180-32x-monitor.service +After=s9180-32x-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/s9180-32x-monitor.service b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/s9180-32x-monitor.service new file mode 100644 index 000000000000..884284b241ad --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/s9180-32x-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s9180_32x_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/i2c_utils.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/i2c_utils.sh new file mode 100755 index 000000000000..d8e5778f4b0e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/i2c_utils.sh @@ -0,0 +1,1721 @@ +#!/bin/bash + +# Copyright (C) 2017 Ingrasys, 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 . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.1.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +QSFP_PORT=${2} +QSFP_ACTION=${2} +MB_EEPROM_ACTION=${2} +COLOR_PORT_LED=${3} +ONOFF_LED=${3} +COLOR_SYS_LED=${2} +BLINK_LED=${4} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_I801_DEVICE=0 # Main I2C +NUM_MUX1_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 1 )) # zQSFP I/O 0-7 +NUM_MUX1_CHAN1_DEVICE=$(( ${NUM_MUX1_CHAN0_DEVICE} + 1 )) # zQSFP I/O 8-15 +NUM_MUX1_CHAN2_DEVICE=$(( ${NUM_MUX1_CHAN1_DEVICE} + 1 )) # zQSFP I/O 16-23 +NUM_MUX1_CHAN3_DEVICE=$(( ${NUM_MUX1_CHAN2_DEVICE} + 1 )) # zQSFP I/O 24-31 +NUM_MUX1_CHAN4_DEVICE=$(( ${NUM_MUX1_CHAN3_DEVICE} + 1 )) # zQSFP I/O ABS#, INT +NUM_MUX1_CHAN5_DEVICE=$(( ${NUM_MUX1_CHAN4_DEVICE} + 1 )) # zQSFP I/O LPMODE, RST, MODSEL +NUM_MUX1_CHAN6_DEVICE=$(( ${NUM_MUX1_CHAN5_DEVICE} + 1 )) # MAC CLK CPLD +NUM_MUX1_CHAN7_DEVICE=$(( ${NUM_MUX1_CHAN6_DEVICE} + 1 )) # P1V0 PWR +NUM_MUX3_CHAN0_DEVICE=$(( ${NUM_MUX1_CHAN7_DEVICE} + 1 )) # zQSFP I/O 0-7 +NUM_MUX4_CHAN0_DEVICE=$(( ${NUM_MUX3_CHAN0_DEVICE} + 8 )) # zQSFP I/O 8-15 +NUM_MUX5_CHAN0_DEVICE=$(( ${NUM_MUX4_CHAN0_DEVICE} + 8 )) # zQSFP I/O 16-23 +NUM_MUX6_CHAN0_DEVICE=$(( ${NUM_MUX5_CHAN0_DEVICE} + 8 )) # zQSFP I/O 24-31 +NUM_MUX7_CHAN0_DEVICE=$(( ${NUM_MUX6_CHAN0_DEVICE} + 8 )) # Temp Sensor 0x48-0x4D +NUM_MAIN_MUX_CHAN0_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 8 )) # System LED HWMON +NUM_MAIN_MUX_CHAN1_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 1 )) # System LED +NUM_MAIN_MUX_CHAN2_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 2 )) # Board ID +NUM_MAIN_MUX_CHAN3_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 3 )) # MAX_Slave +NUM_MAIN_MUX_CHAN4_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 4 )) # TEMP Sensor +NUM_MAIN_MUX_CHAN5_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 5 )) # CLK GEN +NUM_MAIN_MUX_CHAN6_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 6 )) # VDD CORE +NUM_MAIN_MUX_CHAN7_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 7 )) # HWMON +NUM_FRU_MUX_CHAN0_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 8 )) # PSU2 +NUM_FRU_MUX_CHAN1_DEVICE=$(( ${NUM_FRU_MUX_CHAN0_DEVICE} + 1 )) # PSU1 +NUM_FRU_MUX_CHAN2_DEVICE=$(( ${NUM_FRU_MUX_CHAN0_DEVICE} + 2 )) # FAN +NUM_CPLD_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 3 )) # CPLD +NUM_SFP1_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 4 )) # CPLD +NUM_SFP2_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 5 )) # CPLD +NUM_ROV_DEVICE=${NUM_MAIN_MUX_CHAN6_DEVICE} + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon1" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_ISMT_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_ISMT_DEVICE}" +PATH_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" +PATH_MUX_CHAN1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN1_DEVICE}" +PATH_MUX_CHAN2_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN2_DEVICE}" +PATH_MUX_CHAN3_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN3_DEVICE}" +PATH_MUX_CHAN4_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN4_DEVICE}" +PATH_MUX_CHAN5_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN5_DEVICE}" +PATH_MUX_CHAN6_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN6_DEVICE}" +PATH_MUX_CHAN7_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}" +PATH_MUX7_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX7_CHAN0_DEVICE}" +PATH_MAIN_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MAIN_MUX_CHAN0_DEVICE}" + +# i2c address for deviecs +CPLD_I2C_ADDR=0x33 +ROV_I2C_ADDR=0x22 + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +# vdd value for mac +rov_val_array=( 0.85 0.82 0.77 0.87 0.74 0.84 0.79 0.89 ) +rov_reg_array=( 0x24 0x21 0x1c 0x26 0x19 0x23 0x1e 0x28 ) + +#GPIO Offset +GPIO_OFFSET=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "# Version : ${VERSION}" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_temp_init" + echo " : ${0} i2c_fan_init" + echo " : ${0} i2c_volmon_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_gpio_init" + echo " : ${0} i2c_gpio_deinit" + + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_cpu_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [1-34]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_sfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_psu_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [1-34]" + echo " : ${0} i2c_qsfp_type_get [1-34]" + echo " : ${0} i2c_qsfp_ddm_get [1-34]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_port_led_set [1-34] green|yellow|off blink|noblink" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber" + echo " : ${0} i2c_fan_led green|amber on|off" + echo " : ${0} i2c_psu1_led green|amber" + echo " : ${0} i2c_psu2_led green|amber" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + rmmod eeprom + rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + #modprobe cpld_wdt + + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x70' > ${PATH_I801_DEVICE}/new_device" + else + echo "${PATH_I801_DEVICE} 0x70 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX3_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN0_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN0_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX4_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN1_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN1_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX5_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN2_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN2_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX6_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN3_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN3_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX7_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN6_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN6_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MAIN_MUX_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x76' > ${PATH_I801_DEVICE}/new_device" + else + echo "${PATH_MAIN_MUX_CHAN0_DEVICE} 0x76 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9545 0x72' > ${PATH_I801_DEVICE}/new_device" + else + echo "${PATH_MAIN_MUX_CHAN0_DEVICE} 0x72 already init." + fi + + rmmod coretemp + rmmod jc42 + rmmod w83795 + rmmod lm75 + rmmod lm90 + rmmod eeprom + modprobe coretemp + modprobe w83795 + modprobe lm75 + modprobe lm90 + modprobe eeprom_mb + modprobe gpio-pca953x + _i2c_io_exp_init + _i2c_fan_init + _i2c_volmon_init + _i2c_fan_speed_init + _i2c_temp_init + modprobe jc42 + rmmod gpio_ich + _i2c_gpio_init + modprobe gpio_ich + _i2c_mb_eeprom_init "new" + _i2c_qsfp_eeprom_init "new" + _i2c_sfp_eeprom_init "new" + _i2c_psu_eeprom_init "new" + _i2c_led_psu_status_set + _i2c_led_fan_status_set + _i2c_led_fan_tray_status_set + + # rov for mac init + _mac_vdd_init + + #SYS LED set green + COLOR_SYS_LED="green" + _i2c_sys_led + +} + +function _mac_vdd_init { + # read mac vid register value from CPLD + val=`i2cget -y ${NUM_CPLD_DEVICE} ${CPLD_I2C_ADDR} 0x42 2>/dev/null` + + # get vid form register value [0:2] + vid=$(($val & 0x7)) + + # get rov val and reg according to vid + rov_val=${rov_val_array[$vid]} + rov_reg=${rov_reg_array[$vid]} + echo "vid=${vid}, rov_val=${rov_val}, rov_reg=${rov_reg}" + + # write the rov reg to rov + i2cset -y -r ${NUM_ROV_DEVICE} ${ROV_I2C_ADDR} 0x21 ${rov_reg} w + + if [ $? -eq 0 ]; then + echo "set ROV for mac vdd done" + else + echo "set ROV for mac vdd fail" + fi +} + +#I2C Deinit +function _i2c_deinit { + _i2c_gpio_deinit + for mod in coretemp jc42 w83795 lm75 lm90 eeprom eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_ismt i2c_i801; + do + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod + done +} + +#FAN Init +function _i2c_fan_speed_init { + echo -n "FAN INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi + +} + +#VOLMON Init +function _i2c_volmon_init { + echo "VOLMON INIT..." + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x01 0x1C + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x02 0xFF + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x03 0x50 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x04 0x0A + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x01 0x1D + + # add w83795 to sysfs + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MAIN_MUX_CHAN7_DEVICE}-0x2f" + if ! [ -L ${dev_path} ]; then + echo "w83795adg 0x2f" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MAIN_MUX_CHAN7_DEVICE}/new_device #hwmon + else + echo "${dev_path} already exist" + fi + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + + #Golden Finger to active CPLD + i2cget -y ${NUM_CPLD_DEVICE} 0x74 2 + #BMC dummy board reset + echo "BMC dummy board reset" + i2cset -y -r ${NUM_I801_DEVICE} 0x26 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x26 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x26 2 0x3F + i2cset -y -r ${NUM_I801_DEVICE} 0x26 3 0x1F + i2cset -y -r ${NUM_I801_DEVICE} 0x26 6 0xD0 + i2cset -y -r ${NUM_I801_DEVICE} 0x26 7 0x00 + + #CPU Baord + i2cset -y -r ${NUM_I801_DEVICE} 0x77 6 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x77 7 0xFF + + #SMBUS1 + #ABS + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 7 0xFF + + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 7 0xFF + + #Transcevior INT + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 7 0xFF + + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 2 0xCF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 3 0xF0 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 6 0xCF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 7 0xF0 + + #SFP+ PRES, TX FAULT, TX DIS, RX LOS, RS, TS + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 6 0xCF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 7 0xF0 + + + echo "Init ZQSFP IO Expender" + echo "set ZQSFP LP_MODE = 0" + #set ZQSFP LP_MODE = 0 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 7 0x00 + + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 7 0x00 + + echo "set ZQSFP RST = 1" + #set ZQSFP RST = 1 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 2 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 3 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 7 0x00 + + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 2 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 3 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 7 0x00 + + #0.0: TH_RST_L - 0:Reset + #0.1: TH_PCIE_RST_L - 0:Reset + #0.2: LED_CLR - 0: Off, 1:On + #0.3: Host to BMC + #0.4: UART_SEL - 0:Host + #0.5: USB_SEL - 0: Host + #0.[7:6]: TH_CLK_FSEL (00) + #1.0: TH_INT_L + #1.1: QSFP0_INT_L - 0:Interrupt + #1.2: QSFP1_INT_L - 0:Interrupt + #1.3: QSFP2_INT_L - 0:Interrupt + #1.4: QSFP3_INT_L - 0:Interrupt + #1.5: TH_CLK_SEL (0) + #1.6: I210_RST_L - 0:Reset + #1.6: I210_PE_RST_L - 0:Reset + echo "Init HOST GPIO" + i2cset -y -r ${NUM_I801_DEVICE} 0x74 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x74 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x74 2 0x0F + i2cset -y -r ${NUM_I801_DEVICE} 0x74 3 0xDF + i2cset -y -r ${NUM_I801_DEVICE} 0x74 6 0x08 + i2cset -y -r ${NUM_I801_DEVICE} 0x74 7 0x1F + + + #LED board after PVT (BAREFOOT_IO_EXP_LED_ID) + echo "Init LED IO Expender" + echo "LED_CHANNEL=${NUM_MAIN_MUX_CHAN1_DEVICE}" + i2cset -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 4 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 5 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 6 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 7 0xFF + + #Board ID + echo "Init Board ID" + i2cset -y -r ${NUM_MAIN_MUX_CHAN2_DEVICE} 0x27 4 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN2_DEVICE} 0x27 5 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN2_DEVICE} 0x27 6 0xFF + i2cset -y -r ${NUM_MAIN_MUX_CHAN2_DEVICE} 0x27 7 0xFF + + #Board ID of dummy card + echo "Init Board ID of dummy card" + i2cset -y -r ${NUM_I801_DEVICE} 0x24 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x24 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x24 6 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x24 7 0xFF + + #PSU I/O (BAREFOOT_IO_EXP_PSU_ID) + echo "Init PSU IO Expender" + i2cset -y -r ${NUM_I801_DEVICE} 0x25 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x25 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x25 2 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x25 3 0x1D + i2cset -y -r ${NUM_I801_DEVICE} 0x25 6 0xDB + i2cset -y -r ${NUM_I801_DEVICE} 0x25 7 0x03 + + #FAN I/O (BAREFOOT_IO_EXP_FAN_ID) + echo "Init FAN IO Expender" + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 2 0x11 + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 3 0x11 + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 6 0xCC + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 7 0xCC + +} + +#FANIN Init +function _i2c_fan_init { + echo "FANIN INIT..." + # enable fan monitor on w83795 + # 4 fantray with 8 FANIN + # select bank0 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x80 + # enable FANIN1~8 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x06 0xFF + # disable FANIN9~14 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x07 0x00 + + # select bank 2 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x82 + # set PWM mode in FOMC + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x0F 0x00 + + echo "Done" +} + +# To set the global variable GPIO_OFFSET +function _set_gpio_offset { + GPIO_OFFSET=0 + for d in `ls /sys/class/gpio/ | grep gpiochip` + do + gpiochip_no=${d##gpiochip} + if [ $gpiochip_no -gt 255 ]; then + GPIO_OFFSET=256 + break + fi + done + #echo "set GPIO_OFFSET=${GPIO_OFFSET}" +} + +#GPIO Init +function _i2c_gpio_init { + local i=0 + #ABS Port 0-15 + echo "pca9535 0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + _set_gpio_offset + #for i in {240..255}; + for((i=${GPIO_OFFSET}+240;i<=${GPIO_OFFSET}+255;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #ABS Port 16-31 + echo "pca9535 0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + #for i in {224..239}; + for((i=${GPIO_OFFSET}+224;i<=${GPIO_OFFSET}+239;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #INT Port 0-15 + echo "pca9535 0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + #for i in {208..223}; + for((i=${GPIO_OFFSET}+208;i<=${GPIO_OFFSET}+223;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #INT Port 16-31 + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + #for i in {192..207}; + for((i=${GPIO_OFFSET}+192;i<=${GPIO_OFFSET}+207;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #SFP+ + echo "pca9535 0x27" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + #for i in {176..191}; + for((i=${GPIO_OFFSET}+176;i<=${GPIO_OFFSET}+191;i++)); + do + echo $i > /sys/class/gpio/export + case ${i} in + #176|177|178|179|182|183|188|189|190|191) + $((${GPIO_OFFSET}+176)) | \ + $((${GPIO_OFFSET}+177)) | \ + $((${GPIO_OFFSET}+178)) | \ + $((${GPIO_OFFSET}+179)) | \ + $((${GPIO_OFFSET}+182)) | \ + $((${GPIO_OFFSET}+183)) | \ + $((${GPIO_OFFSET}+188)) | \ + $((${GPIO_OFFSET}+189)) | \ + $((${GPIO_OFFSET}+190)) | \ + $((${GPIO_OFFSET}+191)) ) + echo 1 > /sys/class/gpio/gpio${i}/active_low + ;; + #180|181|184|185|186|187) + $((${GPIO_OFFSET}+180)) | \ + $((${GPIO_OFFSET}+181)) | \ + $((${GPIO_OFFSET}+184)) | \ + $((${GPIO_OFFSET}+185)) | \ + $((${GPIO_OFFSET}+186)) | \ + $((${GPIO_OFFSET}+187)) ) + echo out > /sys/class/gpio/gpio${i}/direction + ;; + esac + + done + #echo 176 > /sys/class/gpio/export + #echo 177 > /sys/class/gpio/export + #echo 178 > /sys/class/gpio/export + #echo 179 > /sys/class/gpio/export + #echo 180 > /sys/class/gpio/export + #echo 181 > /sys/class/gpio/export + #echo 182 > /sys/class/gpio/export + #echo 183 > /sys/class/gpio/export + #echo 184 > /sys/class/gpio/export + #echo 185 > /sys/class/gpio/export + #echo 186 > /sys/class/gpio/export + #echo 187 > /sys/class/gpio/export + #echo 188 > /sys/class/gpio/export + #echo 189 > /sys/class/gpio/export + #echo 190 > /sys/class/gpio/export + #echo 191 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio176/active_low #SFP+0 ABS + #echo 1 > /sys/class/gpio/gpio177/active_low #SFP+1 ABS + #echo 1 > /sys/class/gpio/gpio178/active_low #SFP+0 TX_FAULT + #echo 1 > /sys/class/gpio/gpio179/active_low #SFP+1 TX_FAULT + #echo out > /sys/class/gpio/gpio180/direction #SFP+0 TX_DIS + #echo out > /sys/class/gpio/gpio181/direction #SFP+1 TX_DIS + #echo 1 > /sys/class/gpio/gpio182/active_low #SFP+0 RX_LOS + #echo 1 > /sys/class/gpio/gpio183/active_low #SFP+1 RX_LOS + #echo out > /sys/class/gpio/gpio184/direction #SFP+0 RS + #echo out > /sys/class/gpio/gpio185/direction #SFP+1 RS + #echo out > /sys/class/gpio/gpio186/direction #SFP+0 TS + #echo out > /sys/class/gpio/gpio187/direction #SFP+1 TS + #echo 1 > /sys/class/gpio/gpio188/active_low #N/A + #echo 1 > /sys/class/gpio/gpio189/active_low #N/A + #echo 1 > /sys/class/gpio/gpio190/active_low #N/A + #echo 1 > /sys/class/gpio/gpio191/active_low #N/A + + #LP Mode Port 0-15 + echo "pca9535 0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + #for i in {160..175}; + for((i=${GPIO_OFFSET}+160;i<=${GPIO_OFFSET}+175;i++)); + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + done + + #LP Mode Port 16-31 + echo "pca9535 0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + #for i in {144..159}; + for((i=${GPIO_OFFSET}+144;i<=${GPIO_OFFSET}+159;i++)); + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + done + + #RST Port 0-15 + echo "pca9535 0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + #for i in {128..143}; + for((i=${GPIO_OFFSET}+128;i<=${GPIO_OFFSET}+143;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + echo low > /sys/class/gpio/gpio${i}/direction + #echo out > /sys/class/gpio/gpio${i}/direction + #echo 0 > /sys/class/gpio/gpio${i}/value + done + + #RST Port 16-31 + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + #for i in {112..127}; + for((i=${GPIO_OFFSET}+112;i<=${GPIO_OFFSET}+127;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + echo low > /sys/class/gpio/gpio${i}/direction + #echo out > /sys/class/gpio/gpio${i}/direction + #echo 0 > /sys/class/gpio/gpio${i}/value + done + + #PSU I/O on Dummy Board 0x25 + echo "pca9535 0x25" > /sys/bus/i2c/devices/i2c-${NUM_I801_DEVICE}/new_device + #for i in {96..111}; + for((i=${GPIO_OFFSET}+96;i<=${GPIO_OFFSET}+111;i++)); + do + echo $i > /sys/class/gpio/export + case ${i} in + #97|98|100|101|102|105|106|108) + $((${GPIO_OFFSET}+97)) | \ + $((${GPIO_OFFSET}+98)) | \ + $((${GPIO_OFFSET}+100)) | \ + $((${GPIO_OFFSET}+101)) | \ + $((${GPIO_OFFSET}+102)) | \ + $((${GPIO_OFFSET}+105)) | \ + $((${GPIO_OFFSET}+106)) | \ + $((${GPIO_OFFSET}+108)) ) + echo 1 > /sys/class/gpio/gpio${i}/active_low + ;; + #98|101|106|107|108) + $((${GPIO_OFFSET}+98)) | \ + $((${GPIO_OFFSET}+101)) | \ + $((${GPIO_OFFSET}+106)) | \ + $((${GPIO_OFFSET}+107)) | \ + $((${GPIO_OFFSET}+108)) ) + echo out > /sys/class/gpio/gpio${i}/direction + ;; + esac + done +} + +#GPIO DeInit +function _i2c_gpio_deinit { + for((i=${GPIO_OFFSET}+96;i<=${GPIO_OFFSET}+255;i++)); + do + if [ -e "/sys/class/gpio/gpio${i}" ]; then + echo ${i} > /sys/class/gpio/unexport + fi + done + echo "0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x27" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x25" > /sys/bus/i2c/devices/i2c-${NUM_I801_DEVICE}/delete_device +} + +#TMP75 Init +function _i2c_temp_init { + echo "lm86 0x4c" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # ASIC Coretemp and Front MAC + echo "tmp75 0x4f" > ${PATH_I801_DEVICE}/new_device #CPU Board + echo "tmp75 0x48" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # Near PSU1 + echo "tmp75 0x4a" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # Rear MAC + echo "tmp75 0x4b" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # Near Port 32 + echo "tmp75 0x4d" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # Near PSU2 +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + # check if io expander for fan tray exist + #i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x33 + result=`i2cget -y ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 0 2>/dev/null` + err_code=$? + if [ "$err_code" != "0" ]; then + echo "fan tray not exist!" + return + fi + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ]; then + FAN_TRAY=1 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=1 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ]; then + FAN_TRAY=2 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=2 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ]; then + FAN_TRAY=3 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=3 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + FAN_TRAY=4 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=4 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + echo "led_fan setup..." + # all fan ok + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_led + # all fan fail + elif [ "${FAN1_ALARM}" == "1" ] && [ "${FAN2_ALARM}" == "1" ] \ + && [ "${FAN3_ALARM}" == "1" ] && [ "${FAN4_ALARM}" == "1" ] \ + && [ "${FAN5_ALARM}" == "1" ] && [ "${FAN6_ALARM}" == "1" ] \ + && [ "${FAN7_ALARM}" == "1" ] && [ "${FAN8_ALARM}" == "1" ]; then + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_led + # partial fan fail + else + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_led + fi +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + local port=$1 + case ${port} in + 1|2|3|4|5|6|7|8) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x20 + dataAddr=0 + eeprombusbase=${NUM_MUX3_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+240)) + #gpioBase=240 + ;; + 9|10|11|12|13|14|15|16) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x20 + dataAddr=1 + eeprombusbase=${NUM_MUX4_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+240)) + #gpioBase=240 + ;; + 17|18|19|20|21|22|23|24) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x21 + dataAddr=0 + eeprombusbase=${NUM_MUX5_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+224-16)) + #gpioBase=$((224 - 16)) + ;; + 25|26|27|28|29|30|31|32) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x21 + dataAddr=1 + eeprombusbase=${NUM_MUX6_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+224-16)) + #gpioBase=$((224 - 16)) + ;; + 33) + i2cbus=${NUM_MUX1_CHAN7_DEVICE} + regAddr=0x27 + dataAddr=0 + gpioBase=$((${GPIO_OFFSET}+145)) + #gpioBase=145 + ;; + 34) + i2cbus=${NUM_MUX1_CHAN7_DEVICE} + regAddr=0x27 + dataAddr=1 + gpioBase=$((${GPIO_OFFSET}+143)) + #gpioBase=143 + ;; + *) + echo "Please input 1~34" + exit + ;; + esac +} + +#Set QSFP Port variable +function _qsfp_eeprom_var_set { + local port=$1 + if [ ${port} -lt 33 ]; then + eeprombusidx=$(( ${port} % 8)) + case $eeprombusidx in + 1) + eeprombus=$(( $eeprombusbase + 1 )) + eepromAddr=0x50 + ;; + 2) + eeprombus=$(( $eeprombusbase + 0 )) + eepromAddr=0x50 + ;; + 3) + eeprombus=$(( $eeprombusbase + 3 )) + eepromAddr=0x50 + ;; + 4) + eeprombus=$(( $eeprombusbase + 2 )) + eepromAddr=0x50 + ;; + 5) + eeprombus=$(( $eeprombusbase + 5 )) + eepromAddr=0x50 + ;; + 6) + eeprombus=$(( $eeprombusbase + 4 )) + eepromAddr=0x50 + ;; + 7) + eeprombus=$(( $eeprombusbase + 7 )) + eepromAddr=0x50 + ;; + 0) + eeprombus=$(( $eeprombusbase + 6 )) + eepromAddr=0x50 + ;; + esac + else + case $port in + 33) + eeprombus=${NUM_SFP1_DEVICE} + eepromAddr=0x50 + ;; + 34) + eeprombus=${NUM_SFP2_DEVICE} + eepromAddr=0x50 + ;; + esac + fi +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) ^ 1)) ))/value` + echo $status + + if [ $status = 0 ]; then + exit + fi + + _qsfp_eeprom_var_set ${QSFP_PORT} + + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo -n "QSFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-32 ports EEPROM + local i + for i in {1..32}; + do + _qsfp_port_i2c_var_set ${i} + + _qsfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "optoe1 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/delete_device + fi + done + echo "DONE" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + echo -n "Main Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init CPU EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0051 ]; then + echo "mb_eeprom 0x51" > ${PATH_I801_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0051 ]; then + echo "0x51" > ${PATH_I801_DEVICE}/delete_device + fi + #Init MB EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0055 ]; then + echo "mb_eeprom 0x55" > ${PATH_I801_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0055 ]; then + echo "0x55" > ${PATH_I801_DEVICE}/delete_device + fi + echo "DONE" +} + +#Init PSU EEPROM +function _i2c_psu_eeprom_init { + echo -n "PSU EEPROM INIT..." + + ## modprobe eeprom + modprobe eeprom + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init PSU EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN1_DEVICE}-0050 ] || \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN0_DEVICE}-0050 ]; then + ## PUS(0) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN1_DEVICE}/new_device + ## PUS(1) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN0_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN1_DEVICE}-0050 ] || \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN0_DEVICE}-0050 ]; then + ## PUS(0) EEPROM + echo "0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN1_DEVICE}/delete_device + ## PUS(1) EEPROM + echo "0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN0_DEVICE}/delete_device + fi + echo "DONE" +} + +#Init SFP EEPROM +function _i2c_sfp_eeprom_init { + echo -n "SFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 33-34 ports EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP1_DEVICE}-0050 ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP2_DEVICE}-0050 ]; then + #echo "sff8436 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP1_DEVICE}/new_device + #echo "sff8436 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP2_DEVICE}/new_device + echo "optoe1 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP1_DEVICE}/new_device + echo "optoe1 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP2_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP1_DEVICE}-0050 ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP2_DEVICE}-0050 ]; then + echo "0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP1_DEVICE}/delete_device + echo "0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP2_DEVICE}/delete_device + fi + echo "DONE" +} + +#Get MotherBoard EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0055/eeprom | hexdump -C + echo "done..." +} + +#Get CPU EEPROM Information +function _i2c_cpu_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0051/eeprom | hexdump -C + echo "done..." +} + +#get QSFP Status +function _i2c_qsfp_status_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) ^ 1)) ))/value` + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + _qsfp_eeprom_var_set ${QSFP_PORT} + + #Get QSFP EEPROM info + local size=255 + eeprom_path="${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom" + #echo "get ${eeprom_path}" + qsfp_info=$(dd if=${eeprom_path} bs=${size} count=1 2>/dev/null | base64) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Get Board Version and Type +function _i2c_board_type_get { + boardType=`i2cget -y ${NUM_CPLD_DEVICE} 0x33 0x00` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BOARD_ID is 0x%02x, HW Rev %d, Build Rev %d\n" $boardId $boardHwRev $boardBuildRev + +} + +#Get CPLD Version +function _i2c_cpld_version { + cpldRev=`i2cget -y ${NUM_CPLD_DEVICE} 0x33 0x01` + cpldRelease=$((($cpldRev) >> 6 & 0x01)) + cpldVersion=$((($cpldRev) & 0x3F)) + printf "CPLD is %s version(0:RD 1:Release), Revision is 0x%02x\n" $cpldRelease $cpldVersion + +} + +#Set Port LED behavior +function _i2c_port_led_set { + local gy_offset=0x0 + local bl_offset=0x0 + local mask=0x0 + if [ "${QSFP_PORT}" == "" ]; then + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + case ${QSFP_PORT} in + 1|2|3|4) + gy_offset=0x80 + bl_offset=0x90 + ;; + 5|6|7|8) + gy_offset=0x81 + bl_offset=0x90 + ;; + 9|10|11|12) + gy_offset=0x82 + bl_offset=0x91 + ;; + 13|14|15|16) + gy_offset=0x83 + bl_offset=0x91 + ;; + 17|18|19|20) + gy_offset=0x84 + bl_offset=0x92 + ;; + 21|22|23|24) + gy_offset=0x85 + bl_offset=0x92 + ;; + 25|26|27|28) + gy_offset=0x86 + bl_offset=0x93 + ;; + 29|30|31|32) + gy_offset=0x87 + bl_offset=0x93 + ;; + 33) + gy_offset=0x88 + bl_offset=0x94 + mask=0x01 + ;; + 34) + gy_offset=0x88 + bl_offset=0x94 + mask=0x02 + ;; + *) + echo "Please input 1~34" + exit + ;; + esac + + #Set green/yellow/off + if [ ${QSFP_PORT} -lt 33 ]; then + mask=$(( 0x3 << $(( $((${QSFP_PORT} - 0x1)) % 0x4 )) * 0x2 )) + elif [ ${QSFP_PORT} = 33 ]; then + value=1 + elif [ ${QSFP_PORT} = 34 ]; then + value=2 + fi + + if [ ${QSFP_PORT} -lt 33 ]; then + if [ "${COLOR_PORT_LED}" == "green" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} 0x55 + elif [ "${COLOR_PORT_LED}" == "yellow" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} 0xaa + elif [ "${COLOR_PORT_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} 0x00 + return + fi + elif [ ${QSFP_PORT} -ge 33 ]; then + if [ "${COLOR_PORT_LED}" == "green" ] || + [ "${COLOR_PORT_LED}" == "yellow" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} $value + elif [ "${COLOR_PORT_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} $((! ${value} )) + return + fi + fi + + #Set Blink/Unblink + if [ ${QSFP_PORT} -lt 33 ]; then + mask=$(( 0x1 << $(( $((${QSFP_PORT} - 0x1)) % 0x8 )) )) + elif [ ${QSFP_PORT} = 33 ]; then + value=1 + elif [ ${QSFP_PORT} = 34 ]; then + value=2 + fi + + if [ "${BLINK_LED}" == "blink" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${bl_offset} 0x00 + elif [ "${BLINK_LED}" == "noblink" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${bl_offset} 0xff + fi + +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + ## PUS(0) EEPROM + echo "========PSU1=========" + cat ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN1_DEVICE}-0050/eeprom | hexdump -C + + ## PUS(1) EEPROM + echo "========PSU2=========" + cat ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN0_DEVICE}-0050/eeprom | hexdump -C + + echo "done..." +} + +#Set System Status LED +function _i2c_sys_led { + + if [ "${COLOR_SYS_LED}" == "green" ]; then + # set sys_led_g (0.0) = 1 + output_reg=2 + mask=0x01 + value=0x01 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + # set sys_led_g (0.0) = 0 + output_reg=2 + mask=0x01 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + i2cset -m ${mask} -y ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 ${value} + echo "Done" + +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + case ${FAN_TRAY} in + 1) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_SYS_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_SYS_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_SYS_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_SYS_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + if [ "${COLOR_SYS_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_SYS_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x00 + elif [ "${COLOR_SYS_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_SYS_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_SYS_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x06 -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 0x02 + elif [ "${COLOR_SYS_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x06 -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 0x00 + elif [ "${COLOR_SYS_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x06 -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 0x06 + elif [ "${COLOR_SYS_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x06 -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU1 LED +function _i2c_psu1_led { + local value=0 + local mask=8 + + if [ "${COLOR_SYS_LED}" == "green" ]; then + value=0x00 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + value=0xFF + else + echo "Invalid Parameters ${COLOR_SYS_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + i2cset -m ${mask} -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 ${value} +} + +#Set PSU2 LED +function _i2c_psu2_led { + local value=0 + local mask=16 + + if [ "${COLOR_SYS_LED}" == "green" ]; then + value=0x00 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + value=0xFF + else + echo "Invalid Parameters ${COLOR_SYS_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + i2cset -m ${mask} -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 ${value} +} + +#Get PSU Status +function _i2c_psu_status { + psu1_pwgood_gpio=$((${GPIO_OFFSET}+99)) + psu1_exist_gpio=$((${GPIO_OFFSET}+100)) + psu2_pwdgood_gpio=$((${GPIO_OFFSET}+96)) + psu2_exist_gpio=$((${GPIO_OFFSET}+97)) + + psu2PwGood=`cat /sys/class/gpio/gpio${psu2_pwdgood_gpio}/value` # PSU0_PWROK (0.0) + psu2Exist=`cat /sys/class/gpio/gpio${psu2_exist_gpio}/value` # PSU0_PRSNT_L (0.1) + + psu1PwGood=`cat /sys/class/gpio/gpio${psu1_pwgood_gpio}/value` # PSU1_PWROK (0.3) + psu1Exist=`cat /sys/class/gpio/gpio${psu1_exist_gpio}/value` # PSU1_PRSNT_L (0.4) + printf "PSU1 Exist:%d PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +# util function to get logx value +function logx { + v=$1 + n=$2 + logx_res=$(echo "${v} ${n}" | awk '{printf "%f\n",log($1)/log($2)}') +} + +#Set PSU LED on LED Board +function _i2c_led_psu_status_set { + + echo "=========================================================" + echo "# Description: PSU LED Status Setup" + echo "=========================================================" + + #Get PSU Status + _i2c_psu_status + + #PSU1 Status + echo "------------------------------" + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_SYS_LED="green" + _i2c_psu1_led + else + COLOR_SYS_LED="amber" + _i2c_psu1_led + fi + else + COLOR_SYS_LED="amber" + _i2c_psu1_led + fi + echo "set [PSU1 LED] = ${COLOR_SYS_LED}" + + #PSU2 Status + echo "------------------------------" + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_SYS_LED="green" + _i2c_psu2_led + else + COLOR_SYS_LED="amber" + #ONOFF_LED="on" + _i2c_psu2_led + fi + else + COLOR_SYS_LED="amber" + _i2c_psu2_led + fi + echo "set [PSU2 LED] = ${COLOR_SYS_LED}" +} + +# get qsfp ddm data +function _i2c_qsfp_ddm_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + # check if port presence + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) ^ 1)) ))/value` + if [ "${status}" == "0" ]; then + echo "port ${QSFP_PORT} not presence" + return + fi + + _qsfp_eeprom_var_set ${QSFP_PORT} + + # Get QSFP EEPROM info + # only need first 128 bytes (page0) for ddm parsing + local size=128 + eeprom_path="${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom" + #echo "get ${eeprom_path}" + qsfp_info=$(dd if=${eeprom_path} bs=${size} count=1 2>/dev/null | base64) + + # temperature + temp_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s 22 -n 1 -e '"%d"') + temp_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s 23 -n 1 -e '"%d"') + temp=$(echo "$temp_val1 $temp_val2" | awk '{printf "%f\n", $1 + $2/256.0}') + #temp=$(( ${temp_val1} + ${temp_val2}/256.0 )) + echo "temp=$temp" + # voltage + volt_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s 26 -n 1 -e '"%d"') + volt_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s 27 -n 1 -e '"%d"') + #volt=$(((($volt_val1 << 8) | volt_val2) / 10000)) + volt_val3=$(( ($volt_val1 << 8) | $volt_val2 )) + volt=$(echo "$volt_val3" | awk '{printf "%f\n", $1/10000.0}') + echo "volt=$volt" + + # 4 channels + for i in {0..3}; + do + echo "channel $i:" + # txBias + offset=$(( 42 + $i*2 )) + txBias_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + offset=$(( 43 + $i*2 )) + txBias_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + txBias_val3=$(( ($txBias_val1 << 8) | $txBias_val2 )) + txBias=$(echo "$txBias_val3" | awk '{printf "%f\n", (131.0*$1)/65535}') + echo " txBias=$txBias" + # txPower + offset=$(( 50 + $i*2 )) + txPower_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + offset=$(( 51 + $i*2 )) + txPower_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + txPower_val3=$(( ($txPower_val1 << 8) | $txPower_val2 )) + txPower_val4=$(echo "$txPower_val3" | awk '{printf "%f\n", $1*0.0001}') + logx $txPower_val4 10 + txPower=$(echo "$logx_res" | awk '{printf "%f\n", $1*10}') + echo " txPower=$txPower" + # rxPower + offset=$(( 34 + $i*2 )) + rxPower_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + offset=$(( 35 + $i*2 )) + rxPower_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + rxPower_val3=$(( ($rxPower_val1 << 8) | $rxPower_val2 )) + rxPower_val4=$(echo "$rxPower_val3" | awk '{printf "%f\n", $1*0.0001}') + logx $rxPower_val4 10 + rxPower=$(echo "$logx_res" | awk '{printf "%f\n", $1*10}') + echo " rxPower=$rxPower" + done +} + +#Main Function +function _main { + start_time_str=`date` + start_time_sec=$(date +%s) + + _set_gpio_offset + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_fan_init" ]; then + _i2c_fan_init + elif [ "${EXEC_FUNC}" == "i2c_volmon_init" ]; then + _i2c_volmon_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_init" ]; then + _i2c_gpio_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_deinit" ]; then + _i2c_gpio_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_cpu_eeprom_get" ]; then + _i2c_cpu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_sfp_eeprom_init" ]; then + _i2c_sfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_init" ]; then + _i2c_psu_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_qsfp_ddm_get" ]; then + _i2c_qsfp_ddm_get + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_port_led_set" ]; then + _i2c_port_led_set + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_temp_init + _i2c_fan_init + _i2c_io_exp_init + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_cpu_eeprom_get + _i2c_board_type_get + _i2c_cpld_version + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/qsfp_monitor.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/qsfp_monitor.sh new file mode 100755 index 000000000000..249f179216a6 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/qsfp_monitor.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, 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 . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..31}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/s9180_32x_monitor.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/s9180_32x_monitor.sh new file mode 100755 index 000000000000..eedf685b290b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/s9180_32x_monitor.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, 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 . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# TBD: LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + #PSU controlled by dummy board, + #but fan LED and fan tray LED must controlled by this service + _led_monitor + + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/README.md b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/README.md new file mode 100644 index 000000000000..7411603ba608 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/README.md @@ -0,0 +1,175 @@ +# Ingrasys S9280-64X Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, 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 . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S9280-64X is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S9280-64X platform. + +### I2C i801 + +The I2C i801 on Ingrasys S9280-64X can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S9280-64X. + +### I2C PCA9548 +The PCA9548 module on S9280-64X can be found in +`/sys/bus/i2c/devices/i2c-0/` , `/sys/bus/i2c/devices/i2c-17/`, +`/sys/bus/i2c/devices/i2c-18/` , `/sys/bus/i2c/devices/i2c-19/`, +`/sys/bus/i2c/devices/i2c-20/`, `/sys/bus/i2c/devices/i2c-21/`, +`/sys/bus/i2c/devices/i2c-22/`, `/sys/bus/i2c/devices/i2c-23/`, +`/sys/bus/i2c/devices/i2c-24/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S9280-64X. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S9280-64X platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s9280 package is installed on the S9280-64X, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x55" > /sys/bus/i2c/devices/i2c-0/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/0-0055/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber on|off + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon2/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon3/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-64] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_status_get [1-64] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/Makefile b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/Makefile new file mode 100644 index 000000000000..af1a5abe1d12 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m := eeprom_mb.o +obj-m += ingrasys_s9280_64x_i2c_cpld.o +obj-m += ingrasys_s9280_64x_psu.o diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/eeprom_mb.c b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/eeprom_mb.c new file mode 100644 index 000000000000..528864d93382 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/eeprom_mb.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +/* enable dev_dbg print out */ +//#define DEBUG + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { /*0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57,*/ I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 512 + +#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 mb_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 mb_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++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static ssize_t mb_eeprom_write(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); + int ret; + int i; + u8 cmd; + u16 value16; + + dev_dbg(&client->dev, "mb_eeprom_write off=%d, count=%d\n", (int)off, (int)count); + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + mutex_lock(&data->update_lock); + + for(i=0; i < count; i++) { + /* write command */ + cmd = (off >> 8) & 0xff; + value16 = off & 0xff; + value16 |= buf[i] << 8; + ret = i2c_smbus_write_word_data(client, cmd, value16); + + if (ret < 0) { + dev_err(&client->dev, "write address failed at %d \n", (int)off); + goto exit; + } + + off++; + + /* need to wait for write complete */ + udelay(10000); + } +exit: + mutex_unlock(&data->update_lock); + /* force to update client when reading */ + for(i=0; i < SLICE_NUM; i++) { + data->last_updated[i] = 0; + } + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO | S_IWUSR, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, + .write = mb_eeprom_write, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x51 and 0x55. So decline + attaching to addresses >= 0x56 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x56) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_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, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_i2c_cpld.c b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_i2c_cpld.c new file mode 100644 index 000000000000..912060cc93e5 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_i2c_cpld.c @@ -0,0 +1,1618 @@ +/* + * A i2c cpld driver for the ingrasys_s9280_64x + * + * Copyright (C) 2017 Ingrasys Technology Corporation. + * Leo Lin + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s9280_64x_i2c_cpld.h" + +#ifdef DEBUG +#define DEBUG_PRINT(fmt, args...) \ + printk(KERN_INFO "%s:%s[%d]: " fmt "\r\n", \ + __FILE__, __func__, __LINE__, ##args) +#else +#define DEBUG_PRINT(fmt, args...) +#endif + +#define I2C_READ_BYTE_DATA(ret, lock, i2c_client, reg) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_read_byte_data(i2c_client, reg); \ + mutex_unlock(lock); \ +} +#define I2C_WRITE_BYTE_DATA(ret, lock, i2c_client, reg, val) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_write_byte_data(i2c_client, reg, val); \ + mutex_unlock(lock); \ +} + +/* CPLD sysfs attributes index */ +enum s9280_64x_cpld_sysfs_attributes { + CPLD_ACCESS_REG, + CPLD_REGISTER_VAL, + CPLD_PORT_START, + CPLD_PORTS, + CPLD_VERSION, + CPLD_ID, + CPLD_BOARD_TYPE, + CPLD_EXT_BOARD_TYPE, + CPLD_QSFP_PORT_STATUS_1, + CPLD_QSFP_PORT_STATUS_2, + CPLD_QSFP_PORT_STATUS_3, + CPLD_QSFP_PORT_STATUS_4, + CPLD_QSFP_PORT_STATUS_5, + CPLD_QSFP_PORT_STATUS_6, + CPLD_QSFP_PORT_STATUS_7, + CPLD_QSFP_PORT_STATUS_8, + CPLD_QSFP_PORT_STATUS_9, + CPLD_QSFP_PORT_STATUS_10, + CPLD_QSFP_PORT_STATUS_11, + CPLD_QSFP_PORT_STATUS_12, + CPLD_QSFP_PORT_STATUS_13, + CPLD_QSFP_PORT_CONFIG_1, + CPLD_QSFP_PORT_CONFIG_2, + CPLD_QSFP_PORT_CONFIG_3, + CPLD_QSFP_PORT_CONFIG_4, + CPLD_QSFP_PORT_CONFIG_5, + CPLD_QSFP_PORT_CONFIG_6, + CPLD_QSFP_PORT_CONFIG_7, + CPLD_QSFP_PORT_CONFIG_8, + CPLD_QSFP_PORT_CONFIG_9, + CPLD_QSFP_PORT_CONFIG_10, + CPLD_QSFP_PORT_CONFIG_11, + CPLD_QSFP_PORT_CONFIG_12, + CPLD_QSFP_PORT_CONFIG_13, + CPLD_QSFP_PORT_INTERRUPT, + CPLD_SFP_PORT_STATUS, + CPLD_SFP_PORT_CONFIG, + CPLD_10GMUX_CONFIG, + CPLD_BMC_STATUS, + CPLD_BMC_WATCHDOG, + CPLD_USB_STATUS, + CPLD_RESET_CONTROL, + CPLD_SFP_LED, + CPLD_SFP_LED_BLINK, + CPLD_QSFP_LED_1, + CPLD_QSFP_LED_2, + CPLD_QSFP_LED_3, + CPLD_QSFP_LED_4, + CPLD_QSFP_LED_5, + CPLD_QSFP_LED_6, + CPLD_QSFP_LED_7, + CPLD_QSFP_LED_8, + CPLD_QSFP_LED_9, + CPLD_QSFP_LED_10, + CPLD_QSFP_LED_11, + CPLD_QSFP_LED_12, + CPLD_QSFP_LED_13, + CPLD_QSFP_LED_14, + CPLD_QSFP_LED_15, + CPLD_QSFP_LED_16, + CPLD_QSFP_LED_BLINK, + CPLD_RTMR_RESET, + CPLD_ROV_STATUS, + +}; + +/* CPLD sysfs attributes hook functions */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t get_qsfp_port_start(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t get_qsfp_ports(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_cpld_id(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_qsfp_port_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_qsfp_port_config(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_qsfp_port_config(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_qsfp_port_interrupt(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_sfp_port_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_sfp_port_config(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_sfp_port_config(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_10gmux_config(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_10gmux_config(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_bmc_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_bmc_watchdog(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_bmc_watchdog(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_usb_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_reset_control(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_reset_control(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_sfp_led(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_sfp_led(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_sfp_led_blink(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_sfp_led_blink(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_qsfp_led(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_qsfp_led(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_qsfp_led_blink(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_qsfp_led_blink(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_rtmr_reset(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_rtmr_reset(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_rov_status(struct device *dev, + struct device_attribute *da, char *buf); + +static LIST_HEAD(cpld_client_list); /* client list for cpld */ +static struct mutex list_lock; /* mutex for client list */ + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +struct cpld_data { + int index; /* CPLD index */ + struct mutex access_lock; /* mutex for cpld access */ + u8 access_reg; /* register to access */ +}; + +/* CPLD device id and data */ +static const struct i2c_device_id ingrasys_i2c_cpld_id[] = { + { "ingrasys_cpld1", cpld1 }, + { "ingrasys_cpld2", cpld2 }, + { "ingrasys_cpld3", cpld3 }, + { "ingrasys_cpld4", cpld4 }, + { "ingrasys_cpld5", cpld5 }, + {} +}; + +/* Addresses scanned for ingrasys_i2c_cpld */ +static const unsigned short cpld_i2c_addr[] = { 0x33, I2C_CLIENT_END }; + +/* define all support register access of cpld in attribute */ +static SENSOR_DEVICE_ATTR(cpld_access_register, S_IWUSR | S_IRUGO, + read_access_register, write_access_register, CPLD_ACCESS_REG); +static SENSOR_DEVICE_ATTR(cpld_register_value, S_IWUSR | S_IRUGO, + read_register_value, write_register_value, CPLD_REGISTER_VAL); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_start, S_IRUGO, + get_qsfp_port_start, NULL, CPLD_PORT_START); +static SENSOR_DEVICE_ATTR(cpld_qsfp_ports, S_IRUGO, + get_qsfp_ports, NULL, CPLD_PORTS); +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, + read_cpld_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(cpld_id, S_IRUGO, read_cpld_id, NULL, CPLD_ID); +static SENSOR_DEVICE_ATTR(cpld_board_type, S_IRUGO, + read_board_type, NULL, CPLD_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_ext_board_type, S_IRUGO, + read_ext_board_type, NULL, CPLD_EXT_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_1, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_1); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_2, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_2); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_3, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_3); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_4, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_4); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_5, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_5); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_6, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_6); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_7, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_7); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_8, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_8); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_9, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_9); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_10, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_10); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_11, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_11); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_12, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_12); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_13, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_13); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_1, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_1); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_2, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_2); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_3, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_3); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_4, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_4); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_5, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_5); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_6, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_6); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_7, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_7); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_8, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_8); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_9, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_9); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_10, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_10); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_11, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_11); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_12, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_12); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_13, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_13); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_interrupt, S_IRUGO, + read_qsfp_port_interrupt, NULL, CPLD_QSFP_PORT_INTERRUPT); +static SENSOR_DEVICE_ATTR(cpld_sfp_port_status, S_IRUGO, + read_sfp_port_status, NULL, CPLD_SFP_PORT_STATUS); +static SENSOR_DEVICE_ATTR(cpld_sfp_port_config, S_IWUSR | S_IRUGO, + read_sfp_port_config, write_sfp_port_config, CPLD_SFP_PORT_CONFIG); +static SENSOR_DEVICE_ATTR(cpld_10gmux_config, S_IWUSR | S_IRUGO, + read_10gmux_config, write_10gmux_config, + CPLD_10GMUX_CONFIG); +static SENSOR_DEVICE_ATTR(cpld_bmc_status, S_IRUGO, + read_bmc_status, NULL, CPLD_BMC_STATUS); +static SENSOR_DEVICE_ATTR(cpld_bmc_watchdog, S_IWUSR | S_IRUGO, + read_bmc_watchdog, write_bmc_watchdog, + CPLD_BMC_WATCHDOG); +static SENSOR_DEVICE_ATTR(cpld_usb_status, S_IRUGO, + read_usb_status, NULL, CPLD_USB_STATUS); +static SENSOR_DEVICE_ATTR(cpld_reset_control, S_IWUSR | S_IRUGO, + read_reset_control, write_reset_control, + CPLD_BMC_WATCHDOG); +static SENSOR_DEVICE_ATTR(cpld_sfp_led, S_IWUSR | S_IRUGO, + read_sfp_led, write_sfp_led, CPLD_SFP_LED); +static SENSOR_DEVICE_ATTR(cpld_sfp_led_blink, S_IWUSR | S_IRUGO, + read_sfp_led_blink, write_sfp_led_blink, CPLD_SFP_LED_BLINK); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_1, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_1); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_2, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_2); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_3, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_3); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_4, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_4); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_5, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_5); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_6, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_6); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_7, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_7); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_8, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_8); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_9, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_9); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_10, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_10); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_11, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_11); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_12, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_12); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_13, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_13); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_14, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_14); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_15, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_15); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_16, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_16); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_blink, S_IWUSR | S_IRUGO, + read_qsfp_led_blink, write_qsfp_led_blink, CPLD_QSFP_LED_BLINK); +static SENSOR_DEVICE_ATTR(cpld_rtmr_reset, S_IWUSR | S_IRUGO, + read_rtmr_reset, write_rtmr_reset, CPLD_RTMR_RESET); +static SENSOR_DEVICE_ATTR(cpld_rov_status, S_IRUGO, + read_rov_status, NULL, CPLD_ROV_STATUS); + +/* define support attributes of cpldx , total 5 */ +/* cpld 1 */ +static struct attribute *s9280_64x_cpld1_attributes[] = { + &sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_start.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_ports.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_id.dev_attr.attr, + &sensor_dev_attr_cpld_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_ext_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_interrupt.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_port_status.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_port_config.dev_attr.attr, + &sensor_dev_attr_cpld_10gmux_config.dev_attr.attr, + &sensor_dev_attr_cpld_bmc_status.dev_attr.attr, + &sensor_dev_attr_cpld_bmc_watchdog.dev_attr.attr, + &sensor_dev_attr_cpld_usb_status.dev_attr.attr, + &sensor_dev_attr_cpld_reset_control.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_led.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_led_blink.dev_attr.attr, + &sensor_dev_attr_cpld_rtmr_reset.dev_attr.attr, + &sensor_dev_attr_cpld_rov_status.dev_attr.attr, + NULL +}; + +/* cpld 2 / cpld 3 / cpld 4 / cpld 5 */ +static struct attribute *s9280_64x_cpld2345_attributes[] = { +&sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_start.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_ports.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_id.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_interrupt.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_14.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_15.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_16.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_blink.dev_attr.attr, + NULL +}; + +/* cpld 1 attributes group */ +static const struct attribute_group s9280_64x_cpld1_group = { + .attrs = s9280_64x_cpld1_attributes, +}; +/* cpld 2/3/4/5 attributes group */ +static const struct attribute_group s9280_64x_cpld2345_group = { + .attrs = s9280_64x_cpld2345_attributes, +}; + +/* read access register from cpld data */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + + return sprintf(buf, "0x%x\n", reg); +} + +/* write access register to cpld data */ +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + + if (kstrtou8(buf, 0, ®) < 0) + return -EINVAL; + + data->access_reg = reg; + return count; +} + +/* read the value of access register in cpld data */ +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + int reg_val; + + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + + if (reg_val < 0) + return -1; + + return sprintf(buf, "0x%x\n", reg_val); +} + +/* wrtie the value to access register in cpld data */ +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ret = -EIO; + u8 reg = data->access_reg; + u8 reg_val; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, client, reg, reg_val); + + return count; +} + +/* get qsfp port start number of the cpld device */ +/* the start number use to tranlate qsfp port to cpld port */ +/* the cpld port use to access the qsfp port register in cpld */ +static ssize_t get_qsfp_port_start(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int port_base_num; + + if (attr->index == CPLD_PORT_START) { + if (data->index == cpld1) { + port_base_num = 1; + } else { + port_base_num = CPLD_1_PORT_NUM + + CPLD_2_PORT_NUM*(data->index - 1) + 1; + } + return sprintf(buf, "%d\n", port_base_num); + } + return -1; +} + +/* get total qsfp port which contain register in the cpld device */ +static ssize_t get_qsfp_ports(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ports; + + if (attr->index == CPLD_PORTS) { + if (data->index == cpld1) + ports = CPLD_1_PORT_NUM; + else + ports = CPLD_2_PORT_NUM; + return sprintf(buf, "%d\n", ports); + } + return -1; +} + +/* get cpdl version register value */ +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_VERSION) { + reg = CPLD_VERSION_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get cpdl id register value */ +static ssize_t read_cpld_id(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_ID) { + reg = CPLD_ID_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get board type register value */ +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BOARD_TYPE) { + reg = CPLD_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_EXT_BOARD_TYPE) { + reg = CPLD_EXT_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get qsfp port status register value */ +static ssize_t read_qsfp_port_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index >= CPLD_QSFP_PORT_STATUS_1 && + attr->index <= CPLD_QSFP_PORT_STATUS_13) { + reg = CPLD_QSFP_PORT_STATUS_BASE_REG + + (attr->index - CPLD_QSFP_PORT_STATUS_1); + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get qsfp port config register value */ +static ssize_t read_qsfp_port_config(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index >= CPLD_QSFP_PORT_CONFIG_1 && + attr->index <= CPLD_QSFP_PORT_CONFIG_13) { + reg = CPLD_QSFP_PORT_CONFIG_BASE_REG + + (attr->index - CPLD_QSFP_PORT_CONFIG_1); + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to qsfp port config register */ +static ssize_t write_qsfp_port_config(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index >= CPLD_QSFP_PORT_CONFIG_1 && + attr->index <= CPLD_QSFP_PORT_CONFIG_13) { + reg = CPLD_QSFP_PORT_CONFIG_BASE_REG + + (attr->index - CPLD_QSFP_PORT_CONFIG_1); + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get qsfp port interrupt register value */ +static ssize_t read_qsfp_port_interrupt(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_QSFP_PORT_INTERRUPT) { + reg = CPLD_QSFP_PORT_INTERRUPT_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get sfp port status register value */ +static ssize_t read_sfp_port_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_SFP_PORT_STATUS) { + reg = CPLD_SFP_PORT_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get sfp port config register value */ +static ssize_t read_sfp_port_config(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_SFP_PORT_CONFIG) { + reg = CPLD_SFP_PORT_CONFIG_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to sfp port config register */ +static ssize_t write_sfp_port_config(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_SFP_PORT_CONFIG) { + reg = CPLD_SFP_PORT_CONFIG_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get 10g mux config register value */ +static ssize_t read_10gmux_config(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_10GMUX_CONFIG) { + reg = CPLD_10GMUX_CONFIG_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to 10g mux config register */ +static ssize_t write_10gmux_config(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_10GMUX_CONFIG) { + reg = CPLD_10GMUX_CONFIG_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get bmc status register value */ +static ssize_t read_bmc_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BMC_STATUS) { + reg = CPLD_BMC_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get bmc watchdog register value */ +static ssize_t read_bmc_watchdog(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BMC_WATCHDOG) { + reg = CPLD_BMC_WATCHDOG_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to bmc watchdog register */ +static ssize_t write_bmc_watchdog(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_BMC_WATCHDOG) { + reg = CPLD_BMC_WATCHDOG_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get usb status register value */ +static ssize_t read_usb_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_USB_STATUS) { + reg = CPLD_USB_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get reset control register value */ +static ssize_t read_reset_control(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_RESET_CONTROL) { + reg = CPLD_RESET_CONTROL_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to reset control register */ +static ssize_t write_reset_control(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_RESET_CONTROL) { + reg = CPLD_RESET_CONTROL_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get sfp port 0/1 led register */ +static ssize_t read_sfp_led(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_SFP_LED) { + reg = CPLD_SFP_LED_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to sfp 0/1 port led register */ +static ssize_t write_sfp_led(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_SFP_LED) { + reg = CPLD_SFP_LED_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get sfp port 0/1 led blink register */ +static ssize_t read_sfp_led_blink(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_SFP_LED_BLINK) { + reg = CPLD_SFP_LED_BLINK_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to sfp port 0/1 led blink register */ +static ssize_t write_sfp_led_blink(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_SFP_LED_BLINK) { + reg = CPLD_SFP_LED_BLINK_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get qsfp port led register */ +static ssize_t read_qsfp_led(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index >= CPLD_QSFP_LED_1 && + attr->index <= CPLD_QSFP_LED_16) { + reg = CPLD_QSFP_LED_BASE_REG + (attr->index - CPLD_QSFP_LED_1); + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to qsfp port led register */ +static ssize_t write_qsfp_led(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index >= CPLD_QSFP_LED_1 && + attr->index <= CPLD_QSFP_LED_16) { + reg = CPLD_QSFP_LED_BASE_REG + (attr->index - CPLD_QSFP_LED_1); + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get qsfp 16 port led blink register value in 64 bit map */ +/* + each register for 2 port, each port has 4 channel for led blink + bit 64 56 48 40 32 24 16 8 0 + port 16/15 14/13 12/11 10/9 8/7 6/5 4/3 2/1 + */ +static ssize_t read_qsfp_led_blink(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val, i; + u64 bitmap = 0; + + if (attr->index == CPLD_QSFP_LED_BLINK) { + for (i = 0; i <= 7; i++) { + reg = CPLD_QSFP_LED_BLINK_BASE_REG + i; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + reg_val = reg_val & 0xff; + bitmap = bitmap | (reg_val<<(i*8)); + } + return sprintf(buf, "0x%llx\n", bitmap); + } + return -1; +} + +/* set 64 bit map value to qsfp port led blink register */ +/* + each register for 2 port, each port has 4 channel for led blink + bit 63 56 48 40 32 24 16 8 0 + port 16/15 14/13 12/11 10/9 8/7 6/5 4/3 2/1 + */ +static ssize_t write_qsfp_led_blink(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val, i; + int ret; + u64 bitmap = 0; + + if (kstrtou64(buf, 0, &bitmap) < 0) + return -EINVAL; + + if (attr->index == CPLD_QSFP_LED_BLINK) { + for (i = 0; i <= 7; i++) { + reg = CPLD_QSFP_LED_BLINK_BASE_REG + i; + reg_val = (u8)((bitmap >> i*8) & 0xFF); + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + } + return count; +} + +/* get retimer reset register */ +static ssize_t read_rtmr_reset(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_RTMR_RESET) { + reg = CPLD_RTMR_RESET_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to retimer reset register */ +static ssize_t write_rtmr_reset(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_RTMR_RESET) { + reg = CPLD_RTMR_RESET_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get rov status register */ +static ssize_t read_rov_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_ROV_STATUS) { + reg = CPLD_ROV_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* add valid cpld client to list */ +static void ingrasys_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = NULL; + + node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + if (!node) { + dev_info(&client->dev, + "Can't allocate cpld_client_node for index %d\n", + client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +/* remove exist cpld client in list */ +static void ingrasys_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + mutex_unlock(&list_lock); +} + +/* cpld drvier probe */ +static int ingrasys_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct cpld_data *data = NULL; + int ret = -EPERM; + int idx; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* init cpld data for client */ + i2c_set_clientdata(client, data); + mutex_init(&data->access_lock); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_info(&client->dev, + "i2c_check_functionality failed (0x%x)\n", + client->addr); + status = -EIO; + goto exit; + } + + /* get cpld id from device */ + ret = i2c_smbus_read_byte_data(client, CPLD_ID_REG); + + if (ret < 0) { + dev_info(&client->dev, + "fail to get cpld id (0x%x) at addr (0x%x)\n", + CPLD_ID_REG, client->addr); + status = -EIO; + goto exit; + } + + CPLD_ID_ID_GET(ret, idx); + + if (INVALID(idx, cpld1, cpld5)) { + dev_info(&client->dev, + "cpld id %d(device) not valid\n", idx); + //status = -EPERM; + //goto exit; + } + +#if 0 + /* change client name for each cpld with index */ + snprintf(client->name, sizeof(client->name), "%s_%d", client->name, + data->index); +#endif + + data->index = dev_id->driver_data; + + /* register sysfs hooks for different cpld group */ + dev_info(&client->dev, "probe cpld with index %d\n", data->index); + switch (data->index) { + case cpld1: + status = sysfs_create_group(&client->dev.kobj, + &s9280_64x_cpld1_group); + break; + case cpld2: + case cpld3: + case cpld4: + case cpld5: + status = sysfs_create_group(&client->dev.kobj, + &s9280_64x_cpld2345_group); + break; + default: + status = -EINVAL; + } + + if (status) + goto exit; + + dev_info(&client->dev, "chip found\n"); + + /* add probe chip to client list */ + ingrasys_i2c_cpld_add_client(client); + + return 0; +exit: + sysfs_remove_group(&client->dev.kobj, &s9280_64x_cpld2345_group); + return status; +} + +/* cpld drvier remove */ +static int ingrasys_i2c_cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + + switch (data->index) { + case cpld1: + sysfs_remove_group(&client->dev.kobj, &s9280_64x_cpld1_group); + break; + case cpld2: + case cpld3: + case cpld4: + case cpld5: + sysfs_remove_group(&client->dev.kobj, + &s9280_64x_cpld2345_group); + break; + } + + ingrasys_i2c_cpld_remove_client(client); + return 0; +} + +MODULE_DEVICE_TABLE(i2c, ingrasys_i2c_cpld_id); + +static struct i2c_driver ingrasys_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ingrasys_i2c_cpld", + }, + .probe = ingrasys_i2c_cpld_probe, + .remove = ingrasys_i2c_cpld_remove, + .id_table = ingrasys_i2c_cpld_id, + .address_list = cpld_i2c_addr, +}; + +/* provid cpld register read */ +/* cpld_idx indicate the index of cpld device */ +int ingrasys_i2c_cpld_read(u8 cpld_idx, + u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + struct cpld_data *data; + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + data = i2c_get_clientdata(cpld_node->client); + if (data->index == cpld_idx) { + DEBUG_PRINT("cpld_idx=%d, read reg 0x%02x", + cpld_idx, reg); + I2C_READ_BYTE_DATA(ret, &data->access_lock, + cpld_node->client, reg); + DEBUG_PRINT("cpld_idx=%d, read reg 0x%02x = 0x%02x", + cpld_idx, reg, ret); + break; + } + } + + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_read); + +/* provid cpld register write */ +/* cpld_idx indicate the index of cpld device */ +int ingrasys_i2c_cpld_write(u8 cpld_idx, + u8 reg, + u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + struct cpld_data *data; + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + data = i2c_get_clientdata(cpld_node->client); + + if (data->index == cpld_idx) { + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + cpld_node->client, + reg, value); + DEBUG_PRINT("cpld_idx=%d, write reg 0x%02x val 0x%02x, ret=%d", + cpld_idx, reg, value, ret); + break; + } + } + + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_write); + +/* provid qsfp port status register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_qsfp_port_status_val(u8 port_num) +{ + u8 cpld_idx, cpld_port, reg; + int reg_val; + + if (INVALID(port_num, QSFP_MIN_PORT_NUM, QSFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + QSFP_TO_CPLD_IDX(port_num, cpld_idx, cpld_port); + reg = QSFP_PORT_STATUS_REG(cpld_port); + DEBUG_PRINT("port_num=%d, cpld_idx=%d, cpld_port=%d, reg=0x%x", + port_num, cpld_idx, cpld_port, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_qsfp_port_status_val); + +/* provid qsfp port config register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_qsfp_port_config_val(u8 port_num) +{ + u8 cpld_idx, cpld_port, reg; + int reg_val; + + if (INVALID(port_num, QSFP_MIN_PORT_NUM, QSFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + QSFP_TO_CPLD_IDX(port_num, cpld_idx, cpld_port); + reg = QSFP_PORT_CONFIG_REG(cpld_port); + DEBUG_PRINT("port_num=%d, cpld_idx=%d, cpld_port=%d, reg=0x%x", + port_num, cpld_idx, cpld_port, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_qsfp_port_config_val); + +/* provid qsfp port config register write */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_set_qsfp_port_config_val(u8 port_num, + u8 reg_val) +{ + u8 cpld_idx, cpld_port, reg, ret; + + if (INVALID(port_num, QSFP_MIN_PORT_NUM, QSFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + QSFP_TO_CPLD_IDX(port_num, cpld_idx, cpld_port); + reg = QSFP_PORT_CONFIG_REG(cpld_port); + DEBUG_PRINT("port_num=%d, cpld_idx=%d, cpld_port=%d, reg=0x%x", + port_num, cpld_idx, cpld_port, reg); + ret = ingrasys_i2c_cpld_write(cpld_idx, reg, reg_val); + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_set_qsfp_port_config_val); + +/* provid sfp port 0/1 status register read */ +int ingrasys_i2c_cpld_get_sfp_port_status_val(void) +{ + u8 cpld_idx, reg; + int reg_val; + + cpld_idx = cpld1; + reg = CPLD_SFP_PORT_STATUS_REG; + DEBUG_PRINT("cpld_idx=%d, reg=0x%x", + cpld_idx, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_sfp_port_status_val); + +/* provid qsfp port config register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_sfp_port_config_val(void) +{ + u8 cpld_idx, reg; + int reg_val; + + cpld_idx = cpld1; + reg = CPLD_SFP_PORT_CONFIG_REG; + DEBUG_PRINT("cpld_idx=%d, reg=0x%x", + cpld_idx, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_sfp_port_config_val); + +/* provid qsfp port config register write */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_set_sfp_port_config_val(u8 reg_val) +{ + u8 cpld_idx, reg, ret; + + cpld_idx = cpld1; + reg = CPLD_SFP_PORT_CONFIG_REG; + DEBUG_PRINT("cpld_idx=%d, reg=0x%x", + cpld_idx, reg); + ret = ingrasys_i2c_cpld_write(cpld_idx, reg, reg_val); + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_set_sfp_port_config_val); + +static int __init ingrasys_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&ingrasys_i2c_cpld_driver); +} + +static void __exit ingrasys_i2c_cpld_exit(void) +{ + i2c_del_driver(&ingrasys_i2c_cpld_driver); +} + +MODULE_AUTHOR("Leo Lin "); +MODULE_DESCRIPTION("ingrasys_i2c_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(ingrasys_i2c_cpld_init); +module_exit(ingrasys_i2c_cpld_exit); + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_i2c_cpld.h b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_i2c_cpld.h new file mode 100644 index 000000000000..8d1df5dee49d --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_i2c_cpld.h @@ -0,0 +1,338 @@ +/* header file for i2c cpld driver of ingrasys_s9280_64x + * + * Copyright (C) 2017 Ingrasys Technology Corporation. + * Leo Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef INGRASYS_S9280_64X_I2C_CPLD_H +#define INGRASYS_S9280_64X_I2C_CPLD_H + +/* CPLD device index value */ +enum cpld_id { + cpld1, + cpld2, + cpld3, + cpld4, + cpld5 +}; + +enum LED_BLINK { + BLINK, + NOBLINK, +}; + +enum LED_YELLOW { + YELLOW_OFF, + YELLOW_ON, +}; + +enum LED_GREEN { + GREEN_OFF, + GREEN_ON, +}; + +/* port number on CPLD */ +#define CPLD_1_PORT_NUM 12 +#define CPLD_2_PORT_NUM 13 + +/* QSFP port number */ +#define QSFP_MAX_PORT_NUM 64 +#define QSFP_MIN_PORT_NUM 1 + +/* SFP+ port number */ +#define SFP_MAX_PORT_NUM 2 +#define SFP_MIN_PORT_NUM 1 + + +/* CPLD registers */ +#define CPLD_BOARD_TYPE_REG 0x0 +#define CPLD_EXT_BOARD_TYPE_REG 0x7 +#define CPLD_VERSION_REG 0x1 +#define CPLD_ID_REG 0x2 +#define CPLD_QSFP_PORT_STATUS_BASE_REG 0x20 +#define CPLD_QSFP_PORT_CONFIG_BASE_REG 0x30 +#define CPLD_QSFP_PORT_INTERRUPT_REG 0x40 +#define CPLD_SFP_PORT_STATUS_REG 0x2F +#define CPLD_SFP_PORT_CONFIG_REG 0x3F +#define CPLD_QSFP_PORT_INTERRUPT_REG 0x40 +#define CPLD_10GMUX_CONFIG_REG 0x41 +#define CPLD_BMC_STATUS_REG 0x42 +#define CPLD_BMC_WATCHDOG_REG 0x43 +#define CPLD_USB_STATUS_REG 0x44 +#define CPLD_RESET_CONTROL_REG 0x4A +#define CPLD_SFP_LED_REG 0x80 +#define CPLD_SFP_LED_BLINK_REG 0x90 +#define CPLD_QSFP_LED_BASE_REG 0x80 +#define CPLD_QSFP_LED_BLINK_BASE_REG 0x90 +#define CPLD_RTMR_RESET_REG 0x4B +#define CPLD_ROV_STATUS_REG 0x4C + +/* bit definition for register value */ +enum CPLD_QSFP_PORT_STATUS_BITS { + CPLD_QSFP_PORT_STATUS_INT_BIT, + CPLD_QSFP_PORT_STATUS_ABS_BIT, +}; +enum CPLD_QSFP_PORT_CONFIG_BITS { + CPLD_QSFP_PORT_CONFIG_RESET_BIT, + CPLD_QSFP_PORT_CONFIG_RESERVE_BIT, + CPLD_QSFP_PORT_CONFIG_LPMODE_BIT, +}; +enum CPLD_SFP_PORT_STATUS_BITS { + CPLD_SFP0_PORT_STATUS_PRESENT_BIT, + CPLD_SFP0_PORT_STATUS_TXFAULT_BIT, + CPLD_SFP0_PORT_STATUS_RXLOS_BIT, + CPLD_SFP_PORT_STATUS_DUMMY, + CPLD_SFP1_PORT_STATUS_PRESENT_BIT, + CPLD_SFP1_PORT_STATUS_TXFAULT_BIT, + CPLD_SFP1_PORT_STATUS_RXLOS_BIT, +}; +enum CPLD_SFP_PORT_CONFIG_BITS { + CPLD_SFP0_PORT_CONFIG_TXDIS_BIT, + CPLD_SFP0_PORT_CONFIG_RS_BIT, + CPLD_SFP0_PORT_CONFIG_TS_BIT, + CPLD_SFP_PORT_CONFIG_DUMMY, + CPLD_SFP1_PORT_CONFIG_TXDIS_BIT, + CPLD_SFP1_PORT_CONFIG_RS_BIT, + CPLD_SFP1_PORT_CONFIG_TS_BIT, + +}; +enum CPLD_10GMUX_CONFIG_BITS { + CPLD_10GMUX_CONFIG_ENSMB_BIT, + CPLD_10GMUX_CONFIG_ENINPUT_BIT, + CPLD_10GMUX_CONFIG_SEL1_BIT, + CPLD_10GMUX_CONFIG_SEL0_BIT, +}; +enum CPLD_BMC_WATCHDOG_BITS { + CPLD_10GMUX_CONFIG_ENTIMER_BIT, + CPLD_10GMUX_CONFIG_TIMEOUT_BIT, +}; +enum CPLD_RESET_CONTROL_BITS { + CPLD_RESET_CONTROL_SWRST_BIT, + CPLD_RESET_CONTROL_CP2104RST_BIT, + CPLD_RESET_CONTROL_82P33814RST_BIT, + CPLD_RESET_CONTROL_BMCRST_BIT, +}; +enum CPLD_SFP_LED_BITS { + CPLD_SFP_LED_SFP0_GREEN_BIT, + CPLD_SFP_LED_SFP0_YELLOW_BIT, + CPLD_SFP_LED_SFP1_GREEN_BIT, + CPLD_SFP_LED_SFP1_YELLOW_BIT, +}; +enum CPLD_SFP_LED_BLINK_BITS { + CPLD_SFP_LED_BLINK_SFP0_BIT, + CPLD_SFP_LED_BLINK_SFP1_BIT, +}; +enum CPLD_QSFP_LED_BITS { + CPLD_QSFP_LED_CHAN_0_GREEN_BIT, + CPLD_QSFP_LED_CHAN_0_YELLOW_BIT, + CPLD_QSFP_LED_CHAN_1_GREEN_BIT, + CPLD_QSFP_LED_CHAN_1_YELLOW_BIT, + CPLD_QSFP_LED_CHAN_2_GREEN_BIT, + CPLD_QSFP_LED_CHAN_2_YELLOW_BIT, + CPLD_QSFP_LED_CHAN_3_GREEN_BIT, + CPLD_QSFP_LED_CHAN_3_YELLOW_BIT, + +}; +enum CPLD_QSFP_LED_BLINK_BITS { + CPLD_QSFP_LED_BLINK_X_CHAN0_BIT, + CPLD_QSFP_LED_BLINK_X_CHAN1_BIT, + CPLD_QSFP_LED_BLINK_X_CHAN2_BIT, + CPLD_QSFP_LED_BLINK_X_CHAN3_BIT, + CPLD_QSFP_LED_BLINK_XPLUS_CHAN0_BIT, + CPLD_QSFP_LED_BLINK_XPLUS_CHAN1_BIT, + CPLD_QSFP_LED_BLINK_XPLUS_CHAN2_BIT, + CPLD_QSFP_LED_BLINK_XPLUS_CHAN3_BIT, +}; + +/* bit field structure for register value */ +struct cpld_reg_board_type_t { + u8 build_rev:2; + u8 hw_rev:2; + u8 board_id:4; +}; + +struct cpld_reg_version_t { + u8 revision:6; + u8 release:1; + u8 reserve:1; +}; + +struct cpld_reg_id_t { + u8 id:3; + u8 release:5; +}; + +/* common manipulation */ +#define INVALID(i, min, max) ((i < min) || (i > max) ? 1u : 0u) +#define READ_BIT(val, bit) ((0u == (val & (1<bf_name) +#define READ_BF_1(bf_struct, val, bf_name, bf_value) \ + bf_struct bf; \ + bf.data = val; \ + bf_value = bf.bf_name +#define BOARD_TYPE_BUILD_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, build_rev, res) +#define BOARD_TYPE_HW_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, hw_rev, res) +#define BOARD_TYPE_BOARD_ID_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, board_id, res) +#define CPLD_VERSION_REV_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, revision, res) +#define CPLD_VERSION_REL_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, release, res) +#define CPLD_ID_ID_GET(val, res) \ + READ_BF(cpld_reg_id_t, val, id, res) +#define CPLD_ID_REL_GET(val, res) \ + READ_BF(cpld_reg_id_t, val, release, res) +/* SFP/QSFP port led registers manipulation */ +#define SFP_LED_TO_CPLD_IDX(sfp_port) cpld1 +#define SFP_LED_REG(sfp_port) CPLD_SFP_LED_REG +#define SFP_LED_BLINK_REG(sfp_port) CPLD_SFP_LED_BLINK_REG +#define QSFP_LED_TO_CPLD_IDX(qsfp_port) \ + ((qsfp_port - 1) / 16 + 2) +#define QSFP_LED_REG(qsfp_port) \ + ((qsfp_port - 1) % 16 + CPLD_QSFP_LED_BASE_REG) +#define QSFP_LED_BLINK_REG(qsfp_port) \ + (((qsfp_port - 1) % 16) / 2 + CPLD_QSFP_LED_BLINK_BASE_REG) +/* QSFP/SFP port status registers manipulation */ +#define QSFP_TO_CPLD_IDX(qsfp_port, cpld_index, cpld_port) \ +{ \ + if (QSFP_MIN_PORT_NUM <= qsfp_port && qsfp_port <= CPLD_1_PORT_NUM) { \ + cpld_index = cpld1; \ + cpld_port = qsfp_port - 1; \ + } else if (CPLD_1_PORT_NUM < qsfp_port \ + && qsfp_port <= QSFP_MAX_PORT_NUM) { \ + cpld_index = cpld2 + (qsfp_port - 1 - CPLD_1_PORT_NUM) \ + / CPLD_2_PORT_NUM; \ + cpld_port = (qsfp_port - 1 - CPLD_1_PORT_NUM) % \ + CPLD_2_PORT_NUM; \ + } else { \ + cpld_index = 0; \ + cpld_port = 0; \ + } \ +} +#define QSFP_PORT_STATUS_REG(cpld_port) \ + (CPLD_QSFP_PORT_STATUS_BASE_REG + cpld_port) +#define QSFP_PORT_CONFIG_REG(cpld_port) \ + (CPLD_QSFP_PORT_CONFIG_BASE_REG + cpld_port) +#define QSFP_PORT_INT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_INT_BIT) +#define QSFP_PORT_ABS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_ABS_BIT) +#define QSFP_PORT_RESET_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_RESET_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_RESET_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_LPMODE_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define SFP_PORT_PRESENT_BIT_GET(sfp_port, port_status_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + READ_BIT(port_status_value, CPLD_SFP0_PORT_STATUS_PRESENT_BIT); \ + } else { \ + READ_BIT(port_status_value, CPLD_SFP1_PORT_STATUS_PRESENT_BIT); \ + } +#define SFP_PORT_TXFAULT_BIT_GET(sfp_port, port_status_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + READ_BIT(port_status_value, CPLD_SFP0_PORT_STATUS_TXFAULT_BIT); \ + } else { \ + READ_BIT(port_status_value, CPLD_SFP1_PORT_STATUS_TXFAULT_BIT); \ + } +#define SFP_PORT_RXLOS_BIT_GET(sfp_port, port_status_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + READ_BIT(port_status_value, CPLD_SFP0_PORT_STATUS_RXLOS_BIT); \ + } else { \ + READ_BIT(port_status_value, CPLD_SFP1_PORT_STATUS_RXLOS_BIT); \ + } +#define SFP_PORT_TXDIS_BIT_GET(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + READ_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TXDIS_BIT); \ + } else { \ + READ_BIT(port_config_value, CPLD_SFP1_PORT_STATUS_RXLOS_BIT); \ + } +#define SFP_PORT_RS_BIT_GET(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + READ_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_RS_BIT); \ + } else { \ + READ_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_RS_BIT); \ + } +#define SFP_PORT_TS_BIT_GET(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + READ_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TS_BIT); \ + } else { \ + READ_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TS_BIT); \ + } +#define SFP_PORT_TXDIS_BIT_SET(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + SET_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TXDIS_BIT); \ + } else { \ + SET_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_TXDIS_BIT); \ + } +#define SFP_PORT_TXDIS_BIT_CLEAR(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + CLEAR_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TXDIS_BIT); \ + } else { \ + CLEAR_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_TXDIS_BIT); \ + } +#define SFP_PORT_RS_BIT_SET(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + SET_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_RS_BIT); \ + } else { \ + SET_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_RS_BIT); \ + } +#define SFP_PORT_RS_BIT_CLEAR(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + CLEAR_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_RS_BIT); \ + } else { \ + CLEAR_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_RS_BIT); \ + } +#define SFP_PORT_TS_BIT_SET(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + SET_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TS_BIT); \ + } else { \ + SET_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_TS_BIT); \ + } +#define SFP_PORT_TS_BIT_CLEAR(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + CLEAR_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TS_BIT); \ + } else { \ + CLEAR_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_TS_BIT); \ + } + +/* CPLD access functions */ +extern int ingrasys_i2c_cpld_get_qsfp_port_status_val(u8 port_num); +extern int ingrasys_i2c_cpld_get_qsfp_port_config_val(u8 port_num); +extern int ingrasys_i2c_cpld_set_qsfp_port_config_val(u8 port_num, u8 reg_val); +extern int ingrasys_i2c_cpld_get_sfp_port_status_val(void); +extern int ingrasys_i2c_cpld_get_sfp_port_config_val(void); +extern int ingrasys_i2c_cpld_set_sfp_port_config_val(u8 reg_val); +extern u8 fp_port_to_phy_port(u8 fp_port); +#endif + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_platform.h b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_platform.h new file mode 100644 index 000000000000..08f14c0bd96b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_platform.h @@ -0,0 +1,158 @@ +#ifndef _S9230_64X_PLATFORM_H +#define _S9230_64X_PLATFORM_H + +#include + +// remove debug before release +#define DEBUG + +enum bus_order { + I2C_BUS_MAIN, + MUX_9548_0_CH0, + MUX_9548_0_CH1, + MUX_9548_0_CH2, + MUX_9548_0_CH3, + MUX_9548_0_CH4, + MUX_9548_0_CH5, + MUX_9548_0_CH6, + MUX_9548_0_CH7, + MUX_9548_1_CH0, + MUX_9548_1_CH1, + MUX_9548_1_CH2, + MUX_9548_1_CH3, + MUX_9548_1_CH4, + MUX_9548_1_CH5, + MUX_9548_1_CH6, + MUX_9548_1_CH7, + MUX_9548_2_CH0, + MUX_9548_2_CH1, + MUX_9548_2_CH2, + MUX_9548_2_CH3, + MUX_9548_2_CH4, + MUX_9548_2_CH5, + MUX_9548_2_CH6, + MUX_9548_2_CH7, + MUX_9546_0_CH0, + MUX_9546_0_CH1, + MUX_9546_0_CH2, + MUX_9546_0_CH3, + MUX_9546_1_CH0, + MUX_9546_1_CH1, + MUX_9546_1_CH2, + MUX_9546_1_CH3, + MUX_9548_11_CH0, + MUX_9548_11_CH1, + MUX_9548_11_CH2, + MUX_9548_11_CH3, + MUX_9548_11_CH4, + MUX_9548_11_CH5, + MUX_9548_11_CH6, + MUX_9548_11_CH7, + MUX_9548_3_CH0, + MUX_9548_3_CH1, + MUX_9548_3_CH2, + MUX_9548_3_CH3, + MUX_9548_3_CH4, + MUX_9548_3_CH5, + MUX_9548_3_CH6, + MUX_9548_3_CH7, + MUX_9548_4_CH0, + MUX_9548_4_CH1, + MUX_9548_4_CH2, + MUX_9548_4_CH3, + MUX_9548_4_CH4, + MUX_9548_4_CH5, + MUX_9548_4_CH6, + MUX_9548_4_CH7, + MUX_9548_5_CH0, + MUX_9548_5_CH1, + MUX_9548_5_CH2, + MUX_9548_5_CH3, + MUX_9548_5_CH4, + MUX_9548_5_CH5, + MUX_9548_5_CH6, + MUX_9548_5_CH7, + MUX_9548_6_CH0, + MUX_9548_6_CH1, + MUX_9548_6_CH2, + MUX_9548_6_CH3, + MUX_9548_6_CH4, + MUX_9548_6_CH5, + MUX_9548_6_CH6, + MUX_9548_6_CH7, + MUX_9548_7_CH0, + MUX_9548_7_CH1, + MUX_9548_7_CH2, + MUX_9548_7_CH3, + MUX_9548_7_CH4, + MUX_9548_7_CH5, + MUX_9548_7_CH6, + MUX_9548_7_CH7, + MUX_9548_8_CH0, + MUX_9548_8_CH1, + MUX_9548_8_CH2, + MUX_9548_8_CH3, + MUX_9548_8_CH4, + MUX_9548_8_CH5, + MUX_9548_8_CH6, + MUX_9548_8_CH7, + MUX_9548_9_CH0, + MUX_9548_9_CH1, + MUX_9548_9_CH2, + MUX_9548_9_CH3, + MUX_9548_9_CH4, + MUX_9548_9_CH5, + MUX_9548_9_CH6, + MUX_9548_9_CH7, + MUX_9548_10_CH0, + MUX_9548_10_CH1, + MUX_9548_10_CH2, + MUX_9548_10_CH3, + MUX_9548_10_CH4, + MUX_9548_10_CH5, + MUX_9548_10_CH6, + MUX_9548_10_CH7, +}; + +#define I2C_ADDR_MUX_9555_0 (0x20) +#define I2C_ADDR_MUX_9555_1 (0x24) +#define I2C_ADDR_MUX_9555_2 (0x25) +#define I2C_ADDR_MUX_9555_3 (0x26) +#define I2C_ADDR_MUX_9539_0 (0x76) +#define I2C_ADDR_MUX_9539_1 (0x76) +#define I2C_BUS_FAN_STATUS (I2C_BUS_MAIN) +#define I2C_BUS_SYS_LED (MUX_9548_1_CH1) +#define I2C_BUS_PSU_STATUS (I2C_BUS_MAIN) +#define I2C_ADDR_PSU_STATUS (I2C_ADDR_MUX_9555_2) + +#define NUM_OF_I2C_MUX (11) +#define NUM_OF_CPLD (5) +#define NUM_OF_QSFP_PORT (64) +#define NUM_OF_SFP_PORT (2) +#define QSFP_EEPROM_I2C_ADDR (0x50) + +enum gpio_reg { + REG_PORT0_IN, + REG_PORT1_IN, + REG_PORT0_OUT, + REG_PORT1_OUT, + REG_PORT0_POL, + REG_PORT1_POL, + REG_PORT0_DIR, + REG_PORT1_DIR, +}; + +struct ing_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +struct i2c_init_data { + __u16 ch; + __u16 addr; + __u8 reg; + __u8 value; +}; + +#endif diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_psu.c b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_psu.c new file mode 100644 index 000000000000..c2537bf40858 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_psu.c @@ -0,0 +1,394 @@ +/* + * S9280-64x PSU driver + * + * Copyright (C) 2017 Ingrasys, 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 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s9280_64x_platform.h" + +static ssize_t show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf); +static struct s9280_psu_data *s9280_psu_update_status(struct device *dev); +static struct s9280_psu_data *s9280_psu_update_eeprom(struct device *dev); +static int s9280_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len); + + +#define DRIVER_NAME "psu" + +// Addresses scanned +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* PSU EEPROM SIZE */ +#define EEPROM_SZ 256 +#define READ_EEPROM 1 +#define NREAD_EEPROM 0 + +static struct i2c_client pca9555_client; + +/* pca9555 gpio pin mapping */ +#define PSU2_PWROK 0 +#define PSU2_PRSNT_L 1 +#define PSU2_PWRON_L 2 +#define PSU1_PWROK 3 +#define PSU1_PRSNT_L 4 +#define PSU1_PWRON_L 5 +#define TMP_75_INT_L 6 + +/* Driver Private Data */ +struct s9280_psu_data { + struct mutex lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + s32 status; /* IO expander value */ + char eeprom[EEPROM_SZ]; /* psu eeprom data */ + char psuABS; /* PSU absent */ + char psuPG; /* PSU power good */ +}; + +enum psu_index +{ + s9280_psu1, + s9280_psu2 +}; + +/* + * display power good attribute + */ +static ssize_t +show_psu_pg(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9280_psu_data *data = s9280_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuPG; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + +/* + * display power absent attribute + */ +static ssize_t +show_psu_abs(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9280_psu_data *data = s9280_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuABS; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + + +/* + * sysfs attributes for psu + */ +static DEVICE_ATTR(psu_pg, S_IRUGO, show_psu_pg, NULL); +static DEVICE_ATTR(psu_abs, S_IRUGO, show_psu_abs, NULL); +static DEVICE_ATTR(psu_eeprom, S_IRUGO, show_psu_eeprom, NULL); + +static struct attribute *s9280_psu_attributes[] = { + &dev_attr_psu_pg.attr, + &dev_attr_psu_abs.attr, + &dev_attr_psu_eeprom.attr, + NULL +}; + +/* + * display psu eeprom content + */ +static ssize_t +show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct s9280_psu_data *data = s9280_psu_update_eeprom(dev); + + memcpy(buf, (char *)data->eeprom, EEPROM_SZ); + return EEPROM_SZ; +} + +static const struct attribute_group s9280_psu_group = { + .attrs = s9280_psu_attributes, +}; + +/* + * check gpio expander is accessible + */ +static int +pca9555_detect(struct i2c_client *client) +{ + if (i2c_smbus_read_byte_data(client, REG_PORT0_DIR) < 0) { + return -ENODEV; + } + + return 0; +} + +/* + * client init + */ +static void +i2c_devices_client_address_init(struct i2c_client *client) +{ + pca9555_client = *client; + + /* get i2c adapter for the target */ + pca9555_client.adapter = i2c_get_adapter(I2C_BUS_PSU_STATUS); + + /* get the i2c addr for the target */ + pca9555_client.addr = I2C_ADDR_PSU_STATUS; +} + +static int +s9280_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct s9280_psu_data *data; + int status, err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct s9280_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct s9280_psu_data)); + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + i2c_devices_client_address_init(client); + + err = pca9555_detect(&pca9555_client); + if (err) { + return err; + } + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &s9280_psu_group); + if (status) { + goto exit_free; + } + + return 0; + +exit_free: + kfree(data); +exit: + + return status; +} + +static int +s9280_psu_remove(struct i2c_client *client) +{ + struct s9280_psu_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &s9280_psu_group); + kfree(data); + + /* free i2c adapter */ + i2c_put_adapter(pca9555_client.adapter); + + return 0; +} + + +/* + * psu eeprom read utility + */ +static int +s9280_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len) +{ + int i=0, ret=0; + int blk_max = 32; //max block read size + + /* read eeprom, 32 * 8 = 256 bytes */ + for (i=0; i < EEPROM_SZ/blk_max; i++) { + ret = i2c_smbus_read_i2c_block_data(client, (i*blk_max), blk_max, + data + (i*blk_max)); + if (ret < 0) { + return ret; + } + } + return ret; +} + +/* + * update eeprom content + */ +static struct s9280_psu_data +*s9280_psu_update_eeprom(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9280_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + if (time_after(jiffies, data->last_updated + 300 * HZ) + || !data->valid) { + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9280_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + /* Read eeprom */ + if (!data->psuABS) { + //clear local eeprom data + memset(data->eeprom, 0, EEPROM_SZ); + + //read eeprom + status = s9280_psu_read_block(client, 0, data->eeprom, + ARRAY_SIZE(data->eeprom)); + + if (status < 0) { + memset(data->eeprom, 0, EEPROM_SZ); + dev_err(&client->dev, "Read eeprom failed, status=(%d)\n", status); + } else { + data->valid = 1; + } + } else { + memset(data->eeprom, 0, EEPROM_SZ); + } + data->last_updated = jiffies; + } + + mutex_unlock(&data->lock); + + return data; +} + +/* + * update psu status + */ +static struct s9280_psu_data +*s9280_psu_update_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9280_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9280_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + mutex_unlock(&data->lock); + + return data; +} + +static const struct i2c_device_id s9280_psu_id[] = { + { "psu1", s9280_psu1 }, + { "psu2", s9280_psu2 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, s9280_psu_id); + +static struct i2c_driver s9280_psu_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = s9280_psu_probe, + .remove = s9280_psu_remove, + .id_table = s9280_psu_id, + .address_list = normal_i2c, +}; + +static int __init s9280_psu_init(void) +{ + return i2c_add_driver(&s9280_psu_driver); +} + +static void __exit s9280_psu_exit(void) +{ + i2c_del_driver(&s9280_psu_driver); +} + +module_init(s9280_psu_init); +module_exit(s9280_psu_exit); + +MODULE_AUTHOR("Leo Lin "); +MODULE_DESCRIPTION("S9280-64X psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/service/qsfp-monitor.service b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/service/qsfp-monitor.service new file mode 100644 index 000000000000..c801ad68966d --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s9280-64x-monitor.service +After=s9280-64x-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/service/s9280-64x-monitor.service b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/service/s9280-64x-monitor.service new file mode 100644 index 000000000000..5f22b6164dd0 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/service/s9280-64x-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s9280_64x_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/i2c_utils.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/i2c_utils.sh new file mode 100755 index 000000000000..dcd7bf717339 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/i2c_utils.sh @@ -0,0 +1,1928 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, 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 . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +SFP_PORT=${2} +QSFP_ACTION=${2} +SFP_ACTION=${2} +MB_EEPROM_ACTION=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_I801_DEVICE=0 + +# PCA9548#0 0x70 +NUM_MUX_9548_0_CH0=$(( ${NUM_I801_DEVICE} + 1 )) # CPLD1 +NUM_MUX_9548_0_CH1=$(( ${NUM_I801_DEVICE} + 2 )) # CPLD2 +NUM_MUX_9548_0_CH2=$(( ${NUM_I801_DEVICE} + 3 )) # CPLD3 +NUM_MUX_9548_0_CH3=$(( ${NUM_I801_DEVICE} + 4 )) # CPLD4 +NUM_MUX_9548_0_CH4=$(( ${NUM_I801_DEVICE} + 5 )) # CPLD5 +NUM_MUX_9548_0_CH5=$(( ${NUM_I801_DEVICE} + 6 )) # LM75_1 LM75_2 LM86 +NUM_MUX_9548_0_CH6=$(( ${NUM_I801_DEVICE} + 7 )) # LM75_3 LM75_4 + +# PCA9548#1 0x73 +NUM_MUX_9548_1_CH0=$(( ${NUM_I801_DEVICE} + 9 )) # UCD9090 +NUM_MUX_9548_1_CH1=$(( ${NUM_I801_DEVICE} + 10 )) # PCA9539#0 0x76 for FP LED & HW ID +NUM_MUX_9548_1_CH2=$(( ${NUM_I801_DEVICE} + 11 )) # NONE +NUM_MUX_9548_1_CH3=$(( ${NUM_I801_DEVICE} + 12 )) # EEPROM for debug 0x57 +#NUM_MUX_9548_1_CH4=$(( ${NUM_I801_DEVICE} + 13 )) # NONE +NUM_MUX_9548_1_CH5=$(( ${NUM_I801_DEVICE} + 14 )) # CLK gen +NUM_MUX_9548_1_CH6=$(( ${NUM_I801_DEVICE} + 15 )) # ROV +NUM_MUX_9548_1_CH7=$(( ${NUM_I801_DEVICE} + 16 )) # HWM on BMC + +# PCA9546#0 0X72 +NUM_MUX_9546_0_CH0=$(( ${NUM_I801_DEVICE} + 17 )) # PSU1 0x58 +NUM_MUX_9546_0_CH1=$(( ${NUM_I801_DEVICE} + 18 )) # PSU2 0x58 +NUM_MUX_9546_0_CH2=$(( ${NUM_I801_DEVICE} + 19 )) # NONE +NUM_MUX_9546_0_CH3=$(( ${NUM_I801_DEVICE} + 20 )) # NONE + +# PCA9548#2 0X71 +NUM_MUX_9548_2_CH0=$(( ${NUM_I801_DEVICE} + 21 )) # PCA9548#3 0x74 +NUM_MUX_9548_2_CH1=$(( ${NUM_I801_DEVICE} + 22 )) # PCA9548#4 0x74 +NUM_MUX_9548_2_CH2=$(( ${NUM_I801_DEVICE} + 23 )) # PCA9548#5 0x74 +NUM_MUX_9548_2_CH3=$(( ${NUM_I801_DEVICE} + 24 )) # PCA9548#6 0x74 +NUM_MUX_9548_2_CH4=$(( ${NUM_I801_DEVICE} + 25 )) # PCA9548#7 0x74 +NUM_MUX_9548_2_CH5=$(( ${NUM_I801_DEVICE} + 26 )) # PCA9548#8 0x74 +NUM_MUX_9548_2_CH6=$(( ${NUM_I801_DEVICE} + 27 )) # PCA9548#9 0x74 +NUM_MUX_9548_2_CH7=$(( ${NUM_I801_DEVICE} + 28 )) # PCA9548#10 0x74 + + + +# PCA9546#1 0X77 +NUM_MUX_9546_1_CH0=$(( ${NUM_I801_DEVICE} + 29 )) # SFP0 EEPROM 0x50 +NUM_MUX_9546_1_CH1=$(( ${NUM_I801_DEVICE} + 30 )) # SFP1 EEPROM 0x50 +NUM_MUX_9546_1_CH2=$(( ${NUM_I801_DEVICE} + 31 )) # NONE +NUM_MUX_9546_1_CH3=$(( ${NUM_I801_DEVICE} + 32 )) # PCA9539#1 0x76 for sys control + +# PCA9548#11 0X75 +NUM_MUX_9548_11_CH0=$(( ${NUM_I801_DEVICE} + 33 )) # SW upgrade for CPLD1 +NUM_MUX_9548_11_CH1=$(( ${NUM_I801_DEVICE} + 34 )) # SW upgrade for CPLD2 +NUM_MUX_9548_11_CH2=$(( ${NUM_I801_DEVICE} + 35 )) # SW upgrade for CPLD3 +NUM_MUX_9548_11_CH3=$(( ${NUM_I801_DEVICE} + 36 )) # SW upgrade for CPLD4 +NUM_MUX_9548_11_CH4=$(( ${NUM_I801_DEVICE} + 37 )) # SW upgrade for CPLD5 +NUM_MUX_9548_11_CH5=$(( ${NUM_I801_DEVICE} + 38 )) # EEPROM for debug 0x57 +NUM_MUX_9548_11_CH6=$(( ${NUM_I801_DEVICE} + 39 )) # Retimer#0~3 +NUM_MUX_9548_11_CH7=$(( ${NUM_I801_DEVICE} + 40 )) # Retimer#4~7 + +# PCA9548#3~10 0X74 +NUM_MUX_9548_3_CH0=$(( ${NUM_I801_DEVICE} + 41 )) # QSFP 0 EEPROM +NUM_MUX_9548_4_CH0=$(( ${NUM_I801_DEVICE} + 49 )) # QSFP 8 EEPROM +NUM_MUX_9548_5_CH0=$(( ${NUM_I801_DEVICE} + 57 )) # QSFP 16 EEPROM +NUM_MUX_9548_6_CH0=$(( ${NUM_I801_DEVICE} + 65 )) # QSFP 24 EEPROM +NUM_MUX_9548_7_CH0=$(( ${NUM_I801_DEVICE} + 73 )) # QSFP 32 EEPROM +NUM_MUX_9548_8_CH0=$(( ${NUM_I801_DEVICE} + 81 )) # QSFP 40 EEPROM +NUM_MUX_9548_9_CH0=$(( ${NUM_I801_DEVICE} + 89 )) # QSFP 48 EEPROM +NUM_MUX_9548_10_CH0=$(( ${NUM_I801_DEVICE} + 97 )) # QSFP 56 EEPROM + +# MUX Alias +I2C_BUS_MAIN=${NUM_I801_DEVICE} +I2C_BUS_HWM=${NUM_MUX_9548_1_CH7} +I2C_BUS_FAN_STATUS=${I2C_BUS_MAIN} +I2C_BUS_SYS_LED=${NUM_MUX_9548_1_CH1} +I2C_BUS_HW_ID=${NUM_MUX_9548_1_CH1} +I2C_BUS_BMC_HW_ID=${I2C_BUS_MAIN} +I2C_BUS_PSU_STAT=${I2C_BUS_MAIN} +I2C_BUS_FANTRAY_LED=${I2C_BUS_MAIN} +I2C_BUS_MB_EEPROM=${I2C_BUS_MAIN} +I2C_BUS_CB_EEPROM=${I2C_BUS_MAIN} +# TODO: check i2c channel of PSU1/PSU2, it swap in s9230 +I2C_BUS_PSU1_EEPROM=${NUM_MUX_9546_0_CH1} +I2C_BUS_PSU2_EEPROM=${NUM_MUX_9546_0_CH0} +I2C_BUS_CPLD1=${NUM_MUX_9548_0_CH0} +I2C_BUS_CPLD2=${NUM_MUX_9548_0_CH1} +I2C_BUS_CPLD3=${NUM_MUX_9548_0_CH2} +I2C_BUS_CPLD4=${NUM_MUX_9548_0_CH3} +I2C_BUS_CPLD5=${NUM_MUX_9548_0_CH4} +I2C_BUS_ROV=${NUM_MUX_9548_1_CH6} + +# I2C BUS path +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +# TODO: need to verify HWM deivce path after board ready +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon1" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_MUX_9548_0_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH0}" +PATH_MUX_9548_0_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH1}" +PATH_MUX_9548_0_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH2}" +PATH_MUX_9548_0_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH3}" +PATH_MUX_9548_0_CH4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH4}" +PATH_MUX_9548_0_CH5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH5}" +PATH_MUX_9548_0_CH6="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH6}" +PATH_MUX_9548_0_CH7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH7}" +PATH_MUX_9548_1_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH0}" +PATH_MUX_9548_1_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH1}" +PATH_MUX_9548_1_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH2}" +PATH_MUX_9548_1_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH3}" +PATH_MUX_9548_1_CH4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH4}" +PATH_MUX_9548_1_CH5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH5}" +PATH_MUX_9548_1_CH6="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH6}" +PATH_MUX_9548_1_CH7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH7}" +PATH_MUX_9548_2_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH0}" +PATH_MUX_9548_2_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH1}" +PATH_MUX_9548_2_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH2}" +PATH_MUX_9548_2_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH3}" +PATH_MUX_9548_2_CH4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH4}" +PATH_MUX_9548_2_CH5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH5}" +PATH_MUX_9548_2_CH6="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH6}" +PATH_MUX_9548_2_CH7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH7}" +PATH_MUX_9546_0_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH0}" +PATH_MUX_9546_0_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH1}" +PATH_MUX_9546_0_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH2}" +PATH_MUX_9546_0_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH3}" +PATH_MUX_9546_1_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_1_CH0}" +PATH_MUX_9546_1_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_1_CH1}" +PATH_MUX_9546_1_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_1_CH2}" +PATH_MUX_9546_1_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_1_CH3}" +PATH_MUX_9548_11_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_11_CH0}" +PATH_MUX_9548_3_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_3_CH0}" +PATH_MUX_9548_4_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_4_CH0}" +PATH_MUX_9548_5_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_5_CH0}" +PATH_MUX_9548_6_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_6_CH0}" +PATH_MUX_9548_7_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_7_CH0}" +PATH_MUX_9548_8_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_8_CH0}" +PATH_MUX_9548_9_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_9_CH0}" +PATH_MUX_9548_10_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_10_CH0}" +PATH_CPLD1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD1}" +PATH_CPLD2_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD2}" +PATH_CPLD3_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD3}" +PATH_CPLD4_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD4}" +PATH_CPLD5_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD5}" + + +# I2C Address +### I2C MUX +I2C_ADDR_MUX_9548_0=0x70 +I2C_ADDR_MUX_9548_1=0x73 +I2C_ADDR_MUX_9548_2=0x71 +I2C_ADDR_MUX_9546_0=0x72 +I2C_ADDR_MUX_9546_1=0x71 +I2C_ADDR_MUX_9548_11=0x75 +I2C_ADDR_MUX_9548_3=0x74 +I2C_ADDR_MUX_9548_4=0x74 +I2C_ADDR_MUX_9548_5=0x74 +I2C_ADDR_MUX_9548_6=0x74 +I2C_ADDR_MUX_9548_7=0x74 +I2C_ADDR_MUX_9548_8=0x74 +I2C_ADDR_MUX_9548_9=0x74 +I2C_ADDR_MUX_9548_10=0x74 + +### GPIO Expander +I2C_ADDR_MUX_9539_0=0x76 # LED & HW ID +I2C_ADDR_MUX_9539_1=0x76 # SYS config +I2C_ADDR_MUX_9539_2=0x76 # on CPU board, STATUS and ERR from CPLD +I2C_ADDR_MUX_9555_0=0x20 # on FAN board, fan status and led config +I2C_ADDR_MUX_9555_1=0x24 # on BMC board, INT and HW ID +I2C_ADDR_MUX_9555_2=0x25 # on BMC board, PSU status +I2C_ADDR_MUX_9555_3=0x26 # on BMC board, RST and SEL + + +### peripheral +I2C_ADDR_MB_EEPROM=0x55 # on main board +I2C_ADDR_CB_EEPROM=0x51 # on cpu board +I2C_ADDR_UCD9090=0x34 +I2C_ADDR_W83795=0x2F +I2C_ADDR_PSU1_EEPROM=0x50 +I2C_ADDR_PSU2_EEPROM=0x50 +I2C_ADDR_LM75_1=0x4D # Rear Panel +I2C_ADDR_LM75_2=0x4E # Rear MAC +I2C_ADDR_LM86=0x4C # TBD +I2C_ADDR_LM75_3=0x4D # Front Panel +I2C_ADDR_LM75_4=0x4E # Front MAC +I2C_ADDR_TMP75_CB=0x4F # on cpu board +I2C_ADDR_TMP75_BB=0x4A # on bmc board +I2C_ADDR_QSFP_EEPROM=0x50 +I2C_ADDR_SFP_EEPROM=0x50 +I2C_ADDR_CPLD=0x33 +I2C_ADDR_ROV=0x76 + +#sysfs +PATH_SYSFS_PSU1="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU1_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU1_EEPROM)" +PATH_SYSFS_PSU2="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU2_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU2_EEPROM)" + +#ACTIVE LOW enable flag +ACTIVE_LOW_EN=1 +ACTIVE_HIGH_EN=0 +#GPIO Direction In/Out +DIR_IN=in +DIR_OUT=out + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +# IO expander register +# direction +REG_PORT0_DIR=6 +REG_PORT1_DIR=7 +# polarity +REG_PORT0_POL=4 +REG_PORT1_POL=5 +# output +REG_PORT0_OUT=2 +REG_PORT1_OUT=3 +# input +REG_PORT0_IN=0 +REG_PORT1_IN=1 + +# qsfp port number range +MIN_QSFP_PORT_NUM=1 +MAX_QSFP_PORT_NUM=64 + +# sfp+ port number range +MIN_SFP_PORT_NUM=1 +MAX_SFP_PORT_NUM=2 + +# CPLD access +# ROV status +CPLD_ROV_STATUS_KEY=cpld_rov_status +# port status +CPLD_QSFP_STATUS_KEY=cpld_qsfp_port_status +CPLD_SFP_STATUS_KEY=cpld_sfp_port_status +# bit define +CPLD_QSFP_STATUS_ABS_BIT=1 +CPLD_SFP0_STATUS_PRES_BIT=0 +CPLD_SFP1_STATUS_PRES_BIT=4 + +# fp port to phy port mapping +fp2phy_array=( 0 1 4 5 8 9 12 13 16 17 20 21 24 25 28 29 + 32 33 36 37 40 41 44 45 48 49 52 53 56 57 60 61 + 2 3 6 7 10 11 14 15 18 19 22 23 26 27 30 31 + 34 35 38 39 42 43 46 47 50 51 54 55 58 59 62 63) +# fp port to led port mapping +fp2led_array=( 1 2 5 6 9 10 13 14 1 2 5 6 9 10 13 14 + 1 2 5 6 9 10 13 14 1 2 5 6 9 10 13 14 + 3 4 7 8 11 12 15 16 3 4 7 8 11 12 15 16 + 3 4 7 8 11 12 15 16 3 4 7 8 11 12 15 16) +# vdd value for mac +rov_val_array=( 0.85 0.82 0.77 0.87 0.74 0.84 0.79 0.89 ) +rov_reg_array=( 0x79 0x73 0x69 0x7D 0x63 0x77 0x6D 0x81 ) + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_fan_speed_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_cb_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_sfp_eeprom_get [${MIN_SFP_PORT_NUM}-${MAX_SFP_PORT_NUM}]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_sfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_cb_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_sfp_status_get [${MIN_SFP_PORT_NUM}-${MAX_SFP_PORT_NUM}]" + echo " : ${0} i2c_qsfp_type_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_sfp_type_get [${MIN_SFP_PORT_NUM}-${MAX_SFP_PORT_NUM}]" + echo " : ${0} i2c_qsfp_ddm_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_bmc_board_type_get" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber" + echo " : ${0} i2c_fan_led green|amber|off" + echo " : ${0} i2c_psu1_led green|amber|off" + echo " : ${0} i2c_psu2_led green|amber|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + echo "${*}" + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +# front panel port to physical port mapping +function _port_fp2phy { + + local fp_port=$1 + local phy_port=0 + local index=$((${fp_port} - 1)) + # change to 1 base index for internal use + phy_port=$((${fp2phy_array[$index]} + 1)) + #phy_port=${fp2phy_array[$index]} + + echo $phy_port +} + +#front panel port to led port mapping +function _port_fp2led { + + local logic_port=$1 + local led_port=0 + led_port=${fp2led_array[$logic_port]} + + echo $led_port +} + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + #remove optoe module + rmmod optoe + + #rmmod i2c_ismt + _util_rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + # add MUX PCA9548#0 on I801, assume to be i2c-1~8 + if [ ! -e ${PATH_MUX_9548_0_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_0}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_0} already init." + fi + + # add MUX PCA9548#1 on I801, assume to be i2c-9~16 + if [ ! -e ${PATH_MUX_9548_1_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_1}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_1} already init." + fi + + # add MUX PCA9546#0 on I801, assume to be i2c-17~20 + if [ ! -e ${PATH_MUX_9546_0_CH0} ]; then + _retry "echo 'pca9546 ${I2C_ADDR_MUX_9546_0}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9546 ${I2C_ADDR_MUX_9546_0} already init." + fi + + # add MUX PCA9548#2 on I801, assume to be i2c-21~28 + if [ ! -e ${PATH_MUX_9548_2_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_2}' > ${PATH_MUX_9546_0_CH2}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_2} already init." + fi + + # add MUX PCA9546#1 on I801, assume to be i2c-29~32 + if [ ! -e ${PATH_MUX_9546_1_CH0} ]; then + _retry "echo 'pca9546 ${I2C_ADDR_MUX_9546_1}' > ${PATH_MUX_9546_0_CH3}/new_device" + else + echo "pca9546 ${I2C_ADDR_MUX_9546_1} already init." + fi + + # add MUX PCA9548#11 on I801, assume to be i2c-33~40 + if [ ! -e ${PATH_MUX_9548_11_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_11}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_11} already init." + fi + + # add MUX PCA9548#3 on PCA9548#2 CH0, assume to be i2c-41~48 + if [ ! -e ${PATH_MUX_9548_3_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_3}' > ${PATH_MUX_9548_2_CH0}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_4} already init." + fi + + # add MUX PCA9548#4 on PCA9548#2 CH1, assume to be i2c-49~56 + if [ ! -e ${PATH_MUX_9548_4_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_4}' > ${PATH_MUX_9548_2_CH1}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_4} already init." + fi + + # add MUX PCA9548#5 on PCA9548#2 CH2, assume to be i2c-57~64 + if [ ! -e ${PATH_MUX_9548_5_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_5}' > ${PATH_MUX_9548_2_CH2}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_5} already init." + fi + + # add MUX PCA9548#6 on PCA9548#2 CH3, assume to be i2c-65~72 + if [ ! -e ${PATH_MUX_9548_6_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_6}' > ${PATH_MUX_9548_2_CH3}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_6} already init." + fi + + # add MUX PCA9548#7 on PCA9548#2 CH4, assume to be i2c-73~80 + if [ ! -e ${PATH_MUX_9548_7_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_7}' > ${PATH_MUX_9548_2_CH4}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_7} already init." + fi + + # add MUX PCA9548#8 on PCA9548#2 CH5, assume to be i2c-81~88 + if [ ! -e ${PATH_MUX_9548_8_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_8}' > ${PATH_MUX_9548_2_CH5}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_8} already init." + fi + + # add MUX PCA9548#9 on PCA9548#2 CH6, assume to be i2c-89~96 + if [ ! -e ${PATH_MUX_9548_9_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_9}' > ${PATH_MUX_9548_2_CH6}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_9} already init." + fi + + # add MUX PCA9548#10 on PCA9548#2 CH7, assume to be i2c-97~104 + if [ ! -e ${PATH_MUX_9548_10_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_10}' > ${PATH_MUX_9548_2_CH7}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_10} already init." + fi + + _i2c_hwm_init + _util_rmmod eeprom + modprobe eeprom_mb + modprobe gpio-pca953x + _i2c_io_exp_init + _i2c_sensors_init + _i2c_cpld_init + _i2c_psu_init + + _i2c_qsfp_eeprom_init "new" + _i2c_sfp_eeprom_init "new" + _i2c_mb_eeprom_init "new" + _i2c_cb_eeprom_init "new" + _i2c_fan_speed_init + _i2c_led_psu_status_set + _i2c_led_fan_status_set + + # clear port led + _util_port_led_clear + + # rov for mac init + _mac_vdd_init + + # trun on sys led + echo "led_sys setup..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + + _config_rmem +} + +function _mac_vdd_init { + # read mac vid register value from CPLD + cpld_index=1 + _i2c_cpld_reg_read ${cpld_index} ${CPLD_ROV_STATUS_KEY} + # get vid form register value [0:2] + vid=$(($cpld_reg_val & 0x7)) + # get rov val and reg according to vid + rov_val=${rov_val_array[$vid]} + rov_reg=${rov_reg_array[$vid]} + echo "vid=${vid}, rov_val=${rov_val}, rov_reg=${rov_reg}" + + # write the rov reg to rov + i2cset -y -r ${I2C_BUS_ROV} ${I2C_ADDR_ROV} 0x21 ${rov_reg} w + + if [ $? -eq 0 ]; then + echo "set ROV for mac vdd done" + else + echo "set ROV for mac vdd fail" + fi +} + +#I2C Deinit +function _i2c_deinit { + echo "i2c deinit..." + for mod in coretemp jc42 w83795 ingrasys_s9280_64x_psu ingrasys_s9280_64x_i2c_cpld eeprom eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_i801; + do + _util_rmmod $mod + done + echo "Done" +} + +function _i2c_cpld_init { + echo "CPLD init..." + _util_rmmod ingrasys_s9280_64x_i2c_cpld + modprobe ingrasys_s9280_64x_i2c_cpld + + # add cpld 1~5 to sysfs + for i in {1..5}; + do + local cpld_bus="I2C_BUS_CPLD${i}" + local cpld_path="PATH_CPLD${i}_DEVICE" + dev_path="${PATH_SYS_I2C_DEVICES}/${!cpld_bus}-$(printf "%04x" ${I2C_ADDR_CPLD})" + if ! [ -L ${dev_path} ]; then + echo "ingrasys_cpld${i} ${I2C_ADDR_CPLD}" > ${!cpld_path}/new_device + else + echo "${dev_path} already exist" + fi + done + + echo "Done" +} + +function _i2c_sensors_init { + echo "SENSORS init..." + local dev_path + # to make sure hwmon index in sysfs as expected, + # need to remove kernel module and then probe them in expected order + # remove all sensors kernel module + _util_rmmod coretemp + _util_rmmod jc42 + _util_rmmod w83795 + # probe coretemp kernel module + modprobe coretemp #hwmon0 + # probe hwmon kernel module + modprobe w83795 + # add w83795 to sysfs + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_1_CH7}-$(printf "%04x" ${I2C_ADDR_W83795})" + if ! [ -L ${dev_path} ]; then + echo "w83795adg ${I2C_ADDR_W83795}" > ${PATH_MUX_9548_1_CH7}/new_device #hwmon1 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + # add lm75/lm86 to sysfs + ####Main board thermal + ####lm75_1 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH5}-$(printf "%04x" ${I2C_ADDR_LM75_1})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_1}" > ${PATH_MUX_9548_0_CH5}/new_device # hwmon2 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + ####lm75_2 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH5}-$(printf "%04x" ${I2C_ADDR_LM75_2})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_2}" > ${PATH_MUX_9548_0_CH5}/new_device #hwmon3 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + ####lm86 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH5}-$(printf "%04x" ${I2C_ADDR_LM86})" + if ! [ -L ${dev_path} ]; then + echo "lm86 ${I2C_ADDR_LM86}" > ${PATH_MUX_9548_0_CH5}/new_device #hwmon4 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + ####lm75_3 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH6}-$(printf "%04x" ${I2C_ADDR_LM75_3})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_3}" > ${PATH_MUX_9548_0_CH6}/new_device # hwmon5 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + ####lm75_4 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH6}-$(printf "%04x" ${I2C_ADDR_LM75_4})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_4}" > ${PATH_MUX_9548_0_CH6}/new_device #hwmon6 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + ####BMC board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_1_CH7}-$(printf "%04x" ${I2C_ADDR_TMP75_BB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_BB}" > ${PATH_MUX_9548_1_CH7}/new_device #hwmon7 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + ####CPU board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MAIN}-$(printf "%04x" ${I2C_ADDR_TMP75_CB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_CB}" > ${PATH_I801_DEVICE}/new_device #hwmon8 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + + # probe jc42 kernel module + modprobe jc42 #hwmon9 + + echo "Done" +} + +#FAN Speed Init +function _i2c_fan_speed_init { + echo -n "FAN SPEED INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + # init fan speed + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi +} + +# HWM init +function _i2c_hwm_init { + echo "HWM INIT..." + # select bank0 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x80 + # SW reset, Disable monitor + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x01 0x9C + # disable TR5/TR6 DTS + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x04 0x0 + # enable FANIN1~8 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x06 0xFF + # disable FANIN9~14 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x07 0x00 + # CLKIN clock frequency set as 48Mhz + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x01 0x1C + # select bank 2 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x82 + # set PWM mode in FOMC + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x0F 0x00 + # set 25KHz fan output frequency in F1OPFP&F2OPFP + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x18 0x84 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x19 0x84 +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + + # need to init BMC io expander first due to some io expander are reset default + echo "Init BMC INT & HW ID IO Expander" + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT1_POL} 0x00 + + echo "Init BMC PSU status IO Expander" + # PWRON default 0 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT0_OUT} 0x00 + # default 0 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT1_OUT} 0x00 + # I/O 0.2 0.5 output(PWRON), rest input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT0_DIR} 0xDB + # I/O 1.0~1.1 input, 1.2~1.4 output (1.5~1.7 not enable) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT1_DIR} 0xE3 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT1_POL} 0x00 + + echo "Init BMC RST and SEL IO Expander" + # RST default is 1 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT0_OUT} 0x3F + # SEL default is 0 (HOST), EN default is 1 (ACTIVE_HIGH) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT1_OUT} 0x1F + # I/O 0.0~0.5 output, 0.6~0.7 not use + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT0_DIR} 0xD0 + # all output + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT1_POL} 0x00 + + echo "Init System LED & HW ID IO Expander" + # I/O_0.x for System LED default 0, I/O_1.x for HW ID + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_OUT} 0x00 + # System LED => all output + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_DIR} 0x00 + # HW ID => all input + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT1_POL} 0x00 + + echo "Init FAN Board Status IO Expander" + # LED_G_H set to 1, LED_Y_G set to 0 (ACTIVE_HIGH) + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_OUT} 0x11 + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT1_OUT} 0x11 + # DIR/ABS is input, LED_Y/LED_G is output + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_DIR} 0xCC + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT1_DIR} 0xCC + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT1_POL} 0x00 + + echo "Init System SEL and RST IO Expander" + # default 0 (ACTIVE high) + # 0.4~0.5 SEL set to value 0 (host) + # 0.2 LED_CLR set to 0 will clear all switch LED bitmap, set to 1 here + _util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_OUT} 0x04 + # RST 1.6~1.7 default 1 (ACTIVE low), INT 1.0~1.4 default 1 (ACTIVE low) + _util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_OUT} 0xDF + # all output, but ISO_TF_CORE_RST_N 0.0 need to set as input to prevent reboot issue + _util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_DIR} 0x09 + # RST 1.6~1.7 output, rest are input + _util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_DIR} 0x3F + _util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_POL} 0x00 + + echo "Init CPU CPLD IO Expander (FIXME)" + # all input + #echo "NUM_MUX_9546_1_CH3=${NUM_MUX_9546_1_CH3}, I2C_ADDR_MUX_9539_2=${I2C_ADDR_MUX_9539_2}" + #_util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_DIR} 0xFF + # all input + #_util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_DIR} 0xFF + #_util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_POL} 0x00 + #_util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_POL} 0x00 +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + + # check if io expander for fan tray exist + result=`i2cget -y ${I2C_BUS_FANTRAY_LED} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_IN} 2>/dev/null` + err_code=$? + if [ "$err_code" != "0" ]; then + echo "fan tray not exist!" + return + fi + + for FAN_TRAY in {1..4}; + do + FAN_ALARM="FAN${FAN_TRAY}_ALARM" + if [ "${!FAN_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + + echo "set [FAN TRAY ${FAN_TRAY}] [Green]=on [Amber]=off" + else + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + + echo "set [FAN TRAY ${FAN_TRAY}] [Green]=off [Amber]=on" + fi + done +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + + echo "led_fan setup..." + # all fan ok + if [ "${FAN1_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ]; then + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_fan_led + # all fan fail + elif [ "${FAN1_ALARM}" == "1" ] \ + && [ "${FAN3_ALARM}" == "1" ] \ + && [ "${FAN5_ALARM}" == "1" ] \ + && [ "${FAN7_ALARM}" == "1" ] ; then + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_fan_led + # partial fan fail + else + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_fan_led + fi + # if fan not present, no led need to be set +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + echo "led_psu1 setup..." + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_psu1_led + else + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="off" + echo "${COLOR_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + echo "led_psu2 setup..." + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_psu2_led + else + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="off" + echo "${COLOR_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C SYSTEM LED TEST..." + echo "=========================================================" + + #sys led (green) + COLOR_LED="green" + _i2c_sys_led + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + COLOR_LED="amber" + _i2c_sys_led + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + COLOR_LED="green" + _i2c_fan_led + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + COLOR_LED="amber" + _i2c_fan_led + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + COLOR_LED="green" + _i2c_psu1_led + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + COLOR_LED="amber" + _i2c_psu1_led + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + COLOR_LED="green" + _i2c_psu2_led + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + COLOR_LED="amber" + _i2c_psu2_led + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED (can't trun off system led) + COLOR_LED="off" + #_i2c_sys_led + _i2c_fan_led + _i2c_psu1_led + _i2c_psu2_led + _pause 'Check turn off all LEDs (exclude SYS LED) and Press [Enter] key to continue...' + + # restore sys led + COLOR_LED="green" + _i2c_sys_led +} + +#Set QSFP Port cpld variable +function _qsfp_cpld_var_set { + local port=$1 + local reg_port_base + local reg_port_shift + + if [[ $1 -le 12 && $1 -ge 1 ]]; then + cpld_index=1 + reg_port_base=0 + elif [[ $1 -le 25 && $1 -ge 13 ]]; then + cpld_index=2 + reg_port_base=12 + elif [[ $1 -le 38 && $1 -ge 26 ]]; then + cpld_index=3 + reg_port_base=25 + elif [[ $1 -le 51 && $1 -ge 39 ]]; then + cpld_index=4 + reg_port_base=38 + elif [[ $1 -le 64 && $1 -ge 52 ]]; then + cpld_index=5 + reg_port_base=51 + else + echo "invalid port number" + fi + + cpld_port_index=$(( $port - $reg_port_base )) +} + +#Set QSFP Port eeporm variable +function _qsfp_eeprom_var_set { + local port=$1 + local eeprombusbase + local eeprombusshift + # port 1 => zqsfp0 + # port 2 => zqsfp1 + # ... + local port_group=$(( ($port - 1) / 8 )) + + case ${port_group} in + 0) + eeprombusbase=${NUM_MUX_9548_3_CH0} + ;; + 1) + eeprombusbase=${NUM_MUX_9548_4_CH0} + ;; + 2) + eeprombusbase=${NUM_MUX_9548_5_CH0} + ;; + 3) + eeprombusbase=${NUM_MUX_9548_6_CH0} + ;; + 4) + eeprombusbase=${NUM_MUX_9548_7_CH0} + ;; + 5) + eeprombusbase=${NUM_MUX_9548_8_CH0} + ;; + 6) + eeprombusbase=${NUM_MUX_9548_9_CH0} + ;; + 7) + eeprombusbase=${NUM_MUX_9548_10_CH0} + ;; + *) + ;; + esac + + eeprombusshift=$(( (${port} - 1) % 8)) + eepromBus=$(( ${eeprombusbase} + ${eeprombusshift} )) + eepromAddr=${I2C_ADDR_QSFP_EEPROM} +} + + +#Set SFP Port cpld variable +function _sfp_cpld_var_set { + local port=$1 + case ${port} in + 1) + cpld_index=1 + ;; + 2) + cpld_index=1 + ;; + *) + ;; + esac +} + +#Set QSFP Port eeporm variable +function _sfp_eeprom_var_set { + local port=$1 + + case ${port} in + 1) + eepromBus=${NUM_MUX_9546_1_CH0} + ;; + 2) + eepromBus=${NUM_MUX_9546_1_CH1} + ;; + *) + ;; + esac + + eepromAddr=${I2C_ADDR_SFP_EEPROM} +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + local phy_port=0 + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + #get physical port + phy_port=$(_port_fp2phy $QSFP_PORT) + + _qsfp_eeprom_var_set ${phy_port} + + _util_get_qsfp_abs + + if [ $status = 0 ]; then + exit + fi + + # debug + echo "${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf '%04x' $eepromAddr)/eeprom | hexdump -C" + cat ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo "QSFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-64 ports EEPROM + local i + for i in {1..64}; + do + + #get physical port + phy_port=$(_port_fp2phy $i) + + _qsfp_eeprom_var_set ${phy_port} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + #echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/new_device + echo "optoe1 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/delete_device + fi + done + echo "Done" +} + +#Get SFP EEPROM Information +function _i2c_sfp_eeprom_get { + + # input parameter validation + _util_input_check "${SFP_PORT}" "${MIN_SFP_PORT_NUM}" "${MAX_SFP_PORT_NUM}" + _util_get_sfp_pres + + if [ $status = 0 ]; then + exit + fi + + _sfp_eeprom_var_set ${SFP_PORT} + + cat ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init SFP EEPROM +function _i2c_sfp_eeprom_init { + echo "SFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-2 sfp+ EEPROM + local i + for i in {1..2}; + do + _sfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + #echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/new_device + echo "optoe1 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/delete_device + fi + done + echo "Done" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + echo -n "Main Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init mb EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_MB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "$I2C_ADDR_MB_EEPROM" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/delete_device + fi + echo "Done" +} + +#Init CPU Board EEPROM +function _i2c_cb_eeprom_init { + echo -n "CPU Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init cpu EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_CB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM) ]; then + echo "$I2C_ADDR_CB_EEPROM" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CB_EEPROM}/delete_device + fi + echo "Done" +} + +#Init PSU Kernel Module +function _i2c_psu_init { + echo "=========================================================" + echo "# Description: I2C PSU Init" + echo "=========================================================" + modprobe ingrasys_s9280_64x_psu + + echo "psu1 ${I2C_ADDR_PSU1_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/new_device + echo "psu2 ${I2C_ADDR_PSU2_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/new_device +} + +#Deinit PSU Kernel Module +function _i2c_psu_deinit { + echo "${I2C_ADDR_PSU1_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/delete_device + echo "${I2C_ADDR_PSU2_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/delete_device + _util_rmmod ingrasys_s9280_64x_psu +} + +#get QSFP Status +function _i2c_qsfp_status_get { + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + local stat + _util_get_qsfp_abs + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + local phy_port=0 + + phy_port=$(_port_fp2phy ${QSFP_PORT}) + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + _qsfp_eeprom_var_set ${phy_port} + + #Get QSFP EEPROM info + local size=255 + eeprom_path="${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom" + #echo "get ${eeprom_path}" + qsfp_info=$(dd if=${eeprom_path} bs=${size} count=1 2>/dev/null | base64) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +function _i2c_sfp_status_get { + + # input parameter validation + _util_input_check "${SFP_PORT}" "${MIN_SFP_PORT_NUM}" "${MAX_SFP_PORT_NUM}" + + local stat + _util_get_sfp_pres + #status: 0 -> Down, 1 -> Up + if [ $status = 0 ]; then + stat="down" + else + stat="up" + fi + echo "status is $stat" +} + +#get SFP Type +function _i2c_sfp_type_get { + + # input parameter validation + _util_input_check "${SFP_PORT}" "${MIN_SFP_PORT_NUM}" "${MAX_SFP_PORT_NUM}" + + _sfp_eeprom_var_set ${SFP_PORT} + + #Get QSFP EEPROM info + sfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $sfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $sfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $sfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + local eeprom_psu1="" + local eeprom_psu2="" + + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + eeprom_psu1="${PATH_SYSFS_PSU1}/psu_eeprom" + cat ${eeprom_psu1} | hexdump -C + + eeprom_psu2="${PATH_SYSFS_PSU2}/psu_eeprom" + cat ${eeprom_psu2} | hexdump -C +} + +#Get Main Board EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + _i2c_sys_eeprom_get mb +} + +#Get CPU Board EEPROM Information +function _i2c_cb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C CB EEPROM Get..." + echo "=========================================================" + _i2c_sys_eeprom_get cb +} + +#Get system EEPROM Information +##input: "cb" for cpu board, "mb" for main board +function _i2c_sys_eeprom_get { + local eeprom_dev + + if [ "$1" == "cb" ]; then + eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM)/eeprom" + elif [ "$1" == "mb" ]; then + eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom" + else + echo "wrong eeprom type" + return + fi + + # check if eeprom device exist in sysfs + if [ ! -f ${eeprom_dev} ]; then + echo "eeprom device not init" + return + fi + + cat ${eeprom_dev} | hexdump -C + echo "Done" +} + +#sync eeprom content between mb and cb eeprom +function _i2c_eeprom_sync { + echo "=========================================================" + echo "# Description: EEPROM sync..." + echo "=========================================================" + + local mb_eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom" + local cb_eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM)/eeprom" + + # check if eeprom device exist in sysfs + if [[ ! -f ${mb_eeprom_dev} || ! -f ${cb_eeprom_dev} ]]; then + echo "eeprom device not init" + return + fi + + ## check if MB eeprom is empty + if [ ! -z "$(cat ${mb_eeprom_dev} | hexdump -n2 | grep ffff)" ]; then + echo "copy cb eeprom to mb eeprom..." + cat ${cb_eeprom_dev} > ${mb_eeprom_dev} + else + echo "no need to sync" + fi + + echo "Done" +} + +#Set System Status LED +function _i2c_sys_led { + # only green/amber, on/off can't control + if [ "${COLOR_LED}" == "green" ]; then + # set sys_led_g (0.7) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x80 + value=0x80 + elif [ "${COLOR_LED}" == "amber" ]; then + # set sys_led_g (0.7) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x80 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_LED}" == "green" ]; then + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x40 + elif [ "${COLOR_LED}" == "amber" ]; then + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x60 + elif [ "${COLOR_LED}" == "off" ]; then + # set fan_led_en (0.6) = 0 & fan_led_y (0.5) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set PSU1 LED +function _i2c_psu1_led { + if [ "${COLOR_LED}" == "green" ]; then + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x18 + elif [ "${COLOR_LED}" == "off" ]; then + # set psu1_pwr_ok_oe (0.4) = 0 & psu1_led_y (0.3) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set PSU2 LED +function _i2c_psu2_led { + if [ "${COLOR_LED}" == "green" ]; then + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x04 + elif [ "${COLOR_LED}" == "amber" ]; then + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x06 + elif [ "${COLOR_LED}" == "off" ]; then + # set psu0_pwr_ok_oe (0.2) = 0 & psu0_led_y (0.1) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + + i2cAddr=${I2C_ADDR_MUX_9555_0} + output_reg=${REG_PORT0_OUT} + + case ${FAN_TRAY} in + 1) + output_reg=${REG_PORT0_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + output_reg=${REG_PORT0_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + output_reg=${REG_PORT1_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + output_reg=${REG_PORT1_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + # LED PIN value is ACTIVE HIGH + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0xff + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0xff + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "Done" +} + +#Get Board Version and Type +function _i2c_board_type_get { + # read input port 1 value from io expander + input_reg=${REG_PORT1_IN} + boardType=`i2cget -y ${I2C_BUS_HW_ID} ${I2C_ADDR_MUX_9539_0} ${input_reg}` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "MAIN_BOARD BOARD_ID is 0x%02x, HW Rev 0x%02x, Build Rev 0x%02x\n" $boardId $boardHwRev $boardBuildRev +} + +#Get BMC Board Version and Type +function _i2c_bmc_board_type_get { + # read input port 1 value from io expander + input_reg=${REG_PORT1_IN} + boardType=`i2cget -y ${I2C_BUS_BMC_HW_ID} ${I2C_ADDR_MUX_9555_1} ${input_reg}` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BMC_BOARD BOARD_ID is 0x%02x, HW Rev 0x%02x, Build Rev 0x%02x\n" $boardId $boardHwRev $boardBuildRev +} + +#Get CPLD Version +function _i2c_cpld_version { + echo "=========================================================" + echo "# Description: CPLD Version" + echo "=========================================================" + + for i in {1..5}; + do + local cpld_bus="I2C_BUS_CPLD${i}" + local cpld_path="PATH_CPLD${i}_DEVICE" + local file_path="${PATH_SYS_I2C_DEVICES}/${!cpld_bus}-$(printf "%04x" ${I2C_ADDR_CPLD})/cpld_version" + printf "[CPLD %d] %s\n" ${i} $(cat ${file_path}) + done +} + +#Get PSU Status +function _i2c_psu_status { + local psu_abs="" + + psu1PwGood=`cat ${PATH_SYSFS_PSU1}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU1}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu1Exist=1 + else + psu1Exist=0 + fi + + psu2PwGood=`cat ${PATH_SYSFS_PSU2}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU2}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu2Exist=1 + else + psu2Exist=0 + fi + + printf "PSU1 Exist:%x PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Get register value from CPLD +function _i2c_cpld_reg_read { + local idx=$1 + local file_name=$2 + local cpld_i2c_addr=${I2C_ADDR_CPLD} + local reg_file_path + + case ${idx} in + 1) + cpld_i2c_bus=${I2C_BUS_CPLD1} + ;; + 2) + cpld_i2c_bus=${I2C_BUS_CPLD2} + ;; + 3) + cpld_i2c_bus=${I2C_BUS_CPLD3} + ;; + 4) + cpld_i2c_bus=${I2C_BUS_CPLD4} + ;; + 5) + cpld_i2c_bus=${I2C_BUS_CPLD5} + ;; + *) + echo "invalid cpld index" + exit + ;; + esac + + reg_file_path="${PATH_SYS_I2C_DEVICES}/${cpld_i2c_bus}-$(printf "%04x" ${cpld_i2c_addr})/${file_name}" + cpld_reg_val=`cat ${reg_file_path}` +} + +#util functions +function _util_i2cset { + if [ "$DEBUG" == "on" ]; then + i2cset $@ + else + i2cset $@ 1>/dev/null + fi +} + +function _i2c_set { + local i2c_bus=$1 + local i2c_addr=$2 + local reg=$3 + local mask=$4 + local value=$5 + + echo `i2cset -m $mask -y -r ${i2c_bus} ${i2c_addr} ${reg} ${value}` +} + +function _util_rmmod { + local mod=$1 + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod +} + +# get qsfp presence +function _util_get_qsfp_abs { + local phy_port=0 + + #get physical port + phy_port=$(_port_fp2phy $QSFP_PORT) + + # read status from cpld + _qsfp_cpld_var_set ${phy_port} + cpld_reg_file_name="${CPLD_QSFP_STATUS_KEY}_${cpld_port_index}" + _i2c_cpld_reg_read ${cpld_index} ${cpld_reg_file_name} + #status: 0 -> Down, 1 -> Up (ACTIVE_LOW in ABS_BIT) + status=$(( $(( $((${cpld_reg_val})) & (1 << ($CPLD_QSFP_STATUS_ABS_BIT)) ))?0:1 )) +} + +# get sfp presence +function _util_get_sfp_pres { + local pres_bit + # read status from cpld + _sfp_cpld_var_set ${SFP_PORT} + cpld_reg_file_name="${CPLD_SFP_STATUS_KEY}" + _i2c_cpld_reg_read ${cpld_index} ${cpld_reg_file_name} + if [ "${SFP_PORT}" == "1" ]; then + pres_bit=${CPLD_SFP0_STATUS_PRES_BIT} + else + pres_bit=${CPLD_SFP1_STATUS_PRES_BIT} + fi + #status: 0 -> Down, 1 -> Up (ACTIVE_LOW in PRES_BIT) + status=$(( $(( $((${cpld_reg_val})) & (1 << ($pres_bit)) ))?0:1 )) +} + +# valid input number +function _util_input_check { + # input parameter validation + if [[ $1 -lt $2 || $1 -gt $3 ]]; then + echo "Please input number $2~$3" + exit + fi +} + +# clear all switch port led bitmap +function _util_port_led_clear { + echo "port led clear..." + # gpio pin on GPIO MUX PCA9539#1 I/O 0.2 + # pull low to reset bitamp + output_reg=${REG_PORT0_OUT} + mask=0x04 + value=0x00 + _util_i2cset -m ${mask} -y ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_1} ${output_reg} ${value} + sleep 1 + # pull high to out of reset + value=0xFF + _util_i2cset -m ${mask} -y ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_1} ${output_reg} ${value} + echo "Done" +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +# util function to get logx value +function logx { + v=$1 + n=$2 + logx_res=$(echo "${v} ${n}" | awk '{printf "%f\n",log($1)/log($2)}') +} + +# get qsfp ddm data +function _i2c_qsfp_ddm_get { + local phy_port=0 + + phy_port=$(_port_fp2phy ${QSFP_PORT}) + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + # check if port presence + #status: 0 -> Down, 1 -> Up + _util_get_qsfp_abs + if [ "${status}" == "0" ]; then + echo "port ${QSFP_PORT} not presence" + return + fi + + _qsfp_eeprom_var_set ${phy_port} + + # Get QSFP EEPROM info + # only need first 128 bytes (page0) for ddm parsing + local size=128 + eeprom_path="${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom" + #echo "get ${eeprom_path}" + qsfp_info=$(dd if=${eeprom_path} bs=${size} count=1 2>/dev/null | base64) + + # temperature + temp_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s 22 -n 1 -e '"%d"') + temp_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s 23 -n 1 -e '"%d"') + temp=$(echo "$temp_val1 $temp_val2" | awk '{printf "%f\n", $1 + $2/256.0}') + #temp=$(( ${temp_val1} + ${temp_val2}/256.0 )) + echo "temp=$temp" + # voltage + volt_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s 26 -n 1 -e '"%d"') + volt_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s 27 -n 1 -e '"%d"') + #volt=$(((($volt_val1 << 8) | volt_val2) / 10000)) + volt_val3=$(( ($volt_val1 << 8) | $volt_val2 )) + volt=$(echo "$volt_val3" | awk '{printf "%f\n", $1/10000.0}') + echo "volt=$volt" + + # 4 channels + for i in {0..3}; + do + echo "channel $i:" + # txBias + offset=$(( 42 + $i*2 )) + txBias_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + offset=$(( 43 + $i*2 )) + txBias_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + txBias_val3=$(( ($txBias_val1 << 8) | $txBias_val2 )) + txBias=$(echo "$txBias_val3" | awk '{printf "%f\n", (131.0*$1)/65535}') + echo " txBias=$txBias" + # txPower + offset=$(( 50 + $i*2 )) + txPower_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + offset=$(( 51 + $i*2 )) + txPower_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + txPower_val3=$(( ($txPower_val1 << 8) | $txPower_val2 )) + txPower_val4=$(echo "$txPower_val3" | awk '{printf "%f\n", $1*0.0001}') + logx $txPower_val4 10 + txPower=$(echo "$logx_res" | awk '{printf "%f\n", $1*10}') + echo " txPower=$txPower" + # rxPower + offset=$(( 34 + $i*2 )) + rxPower_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + offset=$(( 35 + $i*2 )) + rxPower_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + rxPower_val3=$(( ($rxPower_val1 << 8) | $rxPower_val2 )) + rxPower_val4=$(echo "$rxPower_val3" | awk '{printf "%f\n", $1*0.0001}') + logx $rxPower_val4 10 + rxPower=$(echo "$logx_res" | awk '{printf "%f\n", $1*10}') + echo " rxPower=$rxPower" + done +} + +#Main Function +function _main { + tart_time_str=`date` + start_time_sec=$(date +%s) + + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_fan_speed_init" ]; then + _i2c_fan_speed_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_cb_eeprom_get" ]; then + _i2c_cb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_eeprom_sync" ]; then + _i2c_eeprom_sync + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_sfp_eeprom_get" ]; then + _i2c_sfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_sfp_eeprom_init" ]; then + _i2c_sfp_eeprom_init ${SFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_cb_eeprom_init" ]; then + _i2c_cb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_sfp_status_get" ]; then + _i2c_sfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_sfp_type_get" ]; then + _i2c_sfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_ddm_get" ]; then + _i2c_qsfp_ddm_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_bmc_board_type_get" ]; then + _i2c_bmc_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_cb_eeprom_get + _i2c_board_type_get + _i2c_bmc_board_type_get + _i2c_cpld_version + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/qsfp_monitor.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/qsfp_monitor.sh new file mode 100755 index 000000000000..23a3fd066bee --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/qsfp_monitor.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, 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 . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..63}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/s9280_64x_monitor.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/s9280_64x_monitor.sh new file mode 100755 index 000000000000..eedf685b290b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/s9280_64x_monitor.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, 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 . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# TBD: LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + #PSU controlled by dummy board, + #but fan LED and fan tray LED must controlled by this service + _led_monitor + + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/LICENSE b/platform/barefoot/sonic-platform-modules-wnc-osw1800/LICENSE new file mode 100644 index 000000000000..676cdeec726b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, 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 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/MAINTAINERS b/platform/barefoot/sonic-platform-modules-wnc-osw1800/MAINTAINERS new file mode 100644 index 000000000000..a578b60e24de --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/MAINTAINERS @@ -0,0 +1,7 @@ +# This file describes the maintainers for sonic-platform-modules-wnc-osw1800 +# See the SONiC project governance document for more information + +Name = "WNC" +Email = "wnc@wnc.com.tw" +Github = barefootnetworks +Mailinglist = wnc@wnc.com.tw diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/README.md b/platform/barefoot/sonic-platform-modules-wnc-osw1800/README.md new file mode 100644 index 000000000000..707c1068d6e6 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-wnc-osw1800 +Device drivers for support of BFN platform for the SONiC project diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/changelog b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/changelog new file mode 100644 index 000000000000..466378b892d1 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/changelog @@ -0,0 +1,5 @@ +platform-modules-wnc-osw1800 (1.0) unstable; urgency=low + + * Initial release + + -- WNC Mon, 11 Nov 2015 11:11:11 -0800 diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/compat b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/compat new file mode 100644 index 000000000000..45a4fb75db86 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control new file mode 100644 index 000000000000..6070cf9ad1fc --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control @@ -0,0 +1,12 @@ +Source: platform-modules-wnc-osw1800 +Section: main +Priority: extra +Maintainer: WNC +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-wnc-osw1800 +Architecture: amd64 +Depends: linux-image-3.16.0-5-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/copyright b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/copyright new file mode 100644 index 000000000000..ade42b7aa75a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/copyright @@ -0,0 +1,15 @@ +Provides linux kernel driver for BF PCIe devices + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/rules b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/rules new file mode 100755 index 000000000000..644ab1ade433 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/rules @@ -0,0 +1,38 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_NAME := platform-modules-wnc-osw1800 +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MODULE_SRC := $(shell pwd)/modules +SCRIPT_SRC := $(shell pwd)/scripts +SERVICE_SRC := $(shell pwd)/service + +%: + dh $@ + +override_dh_auto_build: + make -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + +override_dh_auto_install: + dh_installdirs -p$(PACKAGE_NAME) $(KERNEL_SRC)/$(INSTALL_MOD_DIR) + cp $(MODULE_SRC)/*.ko debian/$(PACKAGE_NAME)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) + dh_installdirs -p$(PACKAGE_NAME) usr/local/bin + cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_NAME)/usr/local/bin + dh_installdirs -p$(PACKAGE_NAME) /etc/systemd/system + cp -r $(SERVICE_SRC)/* debian/$(PACKAGE_NAME)/etc/systemd/system + dh_installdirs -p$(PACKAGE_NAME) /etc/systemd/system/multi-user.target.wants + ln -s ../device_node.service debian/$(PACKAGE_NAME)/etc/systemd/system/multi-user.target.wants/device_node.service + ln -s ../driver_load.service debian/$(PACKAGE_NAME)/etc/systemd/system/multi-user.target.wants/driver_load.service + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + rm -f $(MODULE_SRC)/*.o $(MODULE_SRC)/*.ko $(MODULE_SRC)/*.mod.c $(MODULE_SRC)/.*.cmd + rm -f $(MODULE_SRC)/Module.markers $(MODULE_SRC)/Module.symvers $(MODULE_SRC)/modules.order + rm -rf $(MODULE_SRC)/.tmp_versions + diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/Makefile b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/Makefile new file mode 100644 index 000000000000..f01694d73eaf --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/Makefile @@ -0,0 +1,4 @@ +obj-m += i2c-mcp2221.o +obj-m += wnc_cpld.o +obj-m += wnc_cpld3.o +obj-m += wnc_eeprom.o diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/i2c-mcp2221.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/i2c-mcp2221.c new file mode 100644 index 000000000000..fcaa57fbafac --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/i2c-mcp2221.c @@ -0,0 +1,611 @@ +/* + * i2c bus driver for MCP2221 + * + * Derived from: + * i2c-tiny-usb.c + * i2c-diolan-u2c.c + * usb-serial.c + * onetouch.c + * usb-skeleton.c + * + * Copyright (C) 2014 Microchip Technology Inc. + * + * Author: Bogdan Bolocan http://www.microchip.com/support + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "i2c-mcp2221" + +#define USB_VENDOR_ID_MCP2221 0x04d8 +#define USB_DEVICE_ID_MCP2221 0x00dd + +#define MCP2221_OUTBUF_LEN 64 /* USB write packet length */ +#define MCP2221_INBUF_LEN 64 /* USB read packet length */ + +#define MCP2221_MAX_I2C_DATA_LEN 60 + +//#define MCP2221_FREQ_STD 100000 +#define MCP2221_FREQ_STD 400000 +//#define MCP2221_FREQ_STD 50000 +#define MCP2221_FREQ_MAX 500000 + +#define MCP2221_RETRY_MAX 50 +#define MCP2221_STD_DELAY_MS 1 +//#define MCP2221_STD_DELAY_MS 2 + +#define RESP_ERR_NOERR 0x00 +#define RESP_ADDR_NACK 0x25 +#define RESP_READ_ERR 0x7F +#define RESP_READ_COMPL 0x55 +#define RESP_I2C_IDLE 0x00 +#define RESP_I2C_START_TOUT 0x12 +#define RESP_I2C_RSTART_TOUT 0x17 +#define RESP_I2C_WRADDRL_TOUT 0x23 +#define RESP_I2C_WRADDRL_WSEND 0x21 +#define RESP_I2C_WRADDRL_NACK 0x25 +#define RESP_I2C_WRDATA_TOUT 0x44 +#define RESP_I2C_RDDATA_TOUT 0x52 +#define RESP_I2C_STOP_TOUT 0x62 + +#define CMD_MCP2221_STATUS 0x10 +#define SUBCMD_STATUS_CANCEL 0x10 +#define SUBCMD_STATUS_SPEED 0x20 +#define MASK_ADDR_NACK 0x40 + +#define CMD_MCP2221_RDDATA7 0x91 +#define CMD_MCP2221_GET_RDDATA 0x40 + +#define CMD_MCP2221_WRDATA7 0x90 + +/* Structure to hold all of our device specific stuff */ +struct i2c_mcp2221 { + u8 obuffer[MCP2221_OUTBUF_LEN]; /* USB write buffer */ + u8 ibuffer[MCP2221_INBUF_LEN]; /* USB read buffer */ + /* I2C/SMBus data buffer */ + u8 user_data_buffer[MCP2221_MAX_I2C_DATA_LEN]; + int ep_in, ep_out; /* Endpoints */ + struct usb_device *usb_dev; /* the usb device for this device */ + struct usb_interface *interface;/* the interface for this device */ + struct i2c_adapter adapter; /* i2c related things */ + uint frequency; /* I2C/SMBus communication frequency */ + /* Mutex for low-level USB transactions */ + struct mutex mcp2221_usb_op_lock; + /* wq to wait for an ongoing read/write */ + wait_queue_head_t usb_urb_completion_wait; + bool ongoing_usb_ll_op; /* a ll is in progress */ + + struct urb *interrupt_in_urb; + struct urb *interrupt_out_urb; +}; + +static uint frequency = MCP2221_FREQ_STD; /* I2C clock frequency in Hz */ + +module_param(frequency, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(frequency, "I2C clock frequency in hertz"); + +/* usb layer */ + + +/* + * Return list of supported functionality. + */ +static u32 mcp2221_usb_func(struct i2c_adapter *a) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL; +} + +static void mcp2221_usb_cmpl_cbk(struct urb *urb) +{ + struct i2c_mcp2221 *dev = urb->context; + int status = urb->status; + int retval; + + switch (status) { + case 0: /* success */ + break; + case -ECONNRESET: /* unlink */ + case -ENOENT: + case -ESHUTDOWN: + return; + /* -EPIPE: should clear the halt */ + default: /* error */ + goto resubmit; + } + + /* wake up the waitting function + modify the flag indicating the ll status */ + dev->ongoing_usb_ll_op = 0; + wake_up_interruptible(&dev->usb_urb_completion_wait); + return; + +resubmit: + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) { + dev_err(&dev->interface->dev, + "mcp2221(irq): can't resubmit intrerrupt urb, retval %d\n", + retval); + } +} + +static int mcp2221_ll_cmd(struct i2c_mcp2221 *dev) +{ + int rv; + + /* tell everybody to leave the URB alone */ + dev->ongoing_usb_ll_op = 1; + + /* submit the interrupt out ep packet */ + if (usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL)) { + dev_err(&dev->interface->dev, + "mcp2221(ll): usb_submit_urb intr out failed\n"); + dev->ongoing_usb_ll_op = 0; + return -EIO; + } + + /* wait for its completion */ + rv = wait_event_interruptible(dev->usb_urb_completion_wait, + (!dev->ongoing_usb_ll_op)); + if (rv < 0) { + dev_err(&dev->interface->dev, "mcp2221(ll): wait interrupted\n"); + goto ll_exit_clear_flag; + } + + /* tell everybody to leave the URB alone */ + dev->ongoing_usb_ll_op = 1; + + /* submit the interrupt in ep packet */ + if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL)) { + dev_err(&dev->interface->dev, "mcp2221(ll): usb_submit_urb intr in failed\n"); + dev->ongoing_usb_ll_op = 0; + return -EIO; + } + + /* wait for its completion */ + rv = wait_event_interruptible(dev->usb_urb_completion_wait, + (!dev->ongoing_usb_ll_op)); + if (rv < 0) { + dev_err(&dev->interface->dev, "mcp2221(ll): wait interrupted\n"); + goto ll_exit_clear_flag; + } + +ll_exit_clear_flag: + dev->ongoing_usb_ll_op = 0; + return rv; +} + +static int mcp2221_init(struct i2c_mcp2221 *dev) +{ + int ret; + + ret = 0; + if (frequency > MCP2221_FREQ_MAX) + frequency = MCP2221_FREQ_MAX; + + /* initialize the MCP2221 and bring it to "idle/ready" state */ + dev_info(&dev->interface->dev, + "MCP2221 at USB bus %03d address %03d Freq=%dKhz-- mcp2221_init()\n", + dev->usb_dev->bus->busnum, dev->usb_dev->devnum, frequency/1000); + + /* initialize unlocked mutex */ + mutex_init(&dev->mcp2221_usb_op_lock); + + dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->interrupt_out_urb) + goto init_error; + + usb_fill_int_urb(dev->interrupt_out_urb, dev->usb_dev, + usb_sndintpipe(dev->usb_dev, + dev->ep_out), + (void *)&dev->obuffer, MCP2221_OUTBUF_LEN, + mcp2221_usb_cmpl_cbk, dev, + 1); + + dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->interrupt_in_urb) + goto init_error; + + usb_fill_int_urb(dev->interrupt_in_urb, dev->usb_dev, + usb_rcvintpipe(dev->usb_dev, + dev->ep_in), + (void *)&dev->ibuffer, MCP2221_INBUF_LEN, + mcp2221_usb_cmpl_cbk, dev, + 1); + ret = 0; + goto init_no_error; + +init_error: + dev_err(&dev->interface->dev, "mcp2221_init: Error = %d\n", ret); + ret = -ENODEV; + +init_no_error: + dev_info(&dev->interface->dev, "mcp2221_init: Success\n"); + return ret; +} + +static int mcp2221_i2c_readwrite(struct i2c_mcp2221 *dev, + struct i2c_msg *pmsg) +{ + u8 ucI2cDiv, ucCancelXfer, ucXferLen; + int rv, retries; + unsigned int sleepCmd; + u8 *pSrc, *pDst, usbCmdStatus; + + retries = 0; + ucCancelXfer = 0; + /* clock divider for I2C operations */ + ucI2cDiv = (u8)((12000000/frequency) - 3); + + /* determine the best delay value here */ + /* (MCP2221_STD_DELAY_MS * MCP2221_FREQ_MAX)/frequency; */ + sleepCmd = MCP2221_STD_DELAY_MS; + + if (pmsg->len > MCP2221_MAX_I2C_DATA_LEN) + return -EINVAL; + +readwrite_reinit: + dev->obuffer[0] = CMD_MCP2221_STATUS; /* code for STATUS cmd */ + dev->obuffer[1] = 0x00; + dev->obuffer[2] = ucCancelXfer; /* cancel subcmd */ + dev->obuffer[3] = SUBCMD_STATUS_SPEED; /* set the xfer speed */ + dev->obuffer[4] = ucI2cDiv; + dev->obuffer[5] = 0x00; + dev->obuffer[6] = 0x00; + dev->obuffer[7] = 0x00; + + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) + return -EFAULT; + + if (dev->ibuffer[3] != SUBCMD_STATUS_SPEED) { + /* the speed could not be set - wait a while and retry */ + if (retries < MCP2221_RETRY_MAX) { + /* wait a while and retry the operation */ + retries++; + msleep(MCP2221_STD_DELAY_MS); + ucCancelXfer = SUBCMD_STATUS_CANCEL; + goto readwrite_reinit; + } else { + /* max number of retries was reached - return error */ + dev_err(&dev->interface->dev, + "mcp2221 CANCEL ERROR:retries = %d\n", retries); + return -EFAULT; + } + } + + if (pmsg->flags & I2C_M_RD) { + /* I2C read */ + ucXferLen = (u8)pmsg->len; + dev->obuffer[0] = CMD_MCP2221_RDDATA7; + dev->obuffer[1] = ucXferLen; /* LSB of the xfer length */ + dev->obuffer[2] = 0; /* no MSB for the xfer length */ + /* address in 8-bit format */ + dev->obuffer[3] = (u8)((pmsg->addr) << 1); + + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) + return -EFAULT; + + retries = 0; + dev->obuffer[0] = CMD_MCP2221_GET_RDDATA; + dev->obuffer[1] = 0x00; + dev->obuffer[2] = 0x00; + dev->obuffer[3] = 0x00; + + while (retries < MCP2221_RETRY_MAX) { + msleep(sleepCmd); + + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) + return -EFAULT; + + if (dev->ibuffer[2] == RESP_ADDR_NACK) + return -EFAULT; + + /* break the loop - cmd ended ok - used for bus scan */ + if ((dev->ibuffer[3] == 0x00) && + (dev->ibuffer[2] == 0x00)) + break; + + if (dev->ibuffer[3] == RESP_READ_ERR) { + retries++; + continue; + } + + if ((dev->ibuffer[2] == RESP_READ_COMPL) && + (dev->ibuffer[3] == ucXferLen)) { + /* we got the data - copy it */ + pSrc = (u8 *)&dev->ibuffer[4]; + pDst = (u8 *)&pmsg->buf[0]; + memcpy(pDst, pSrc, ucXferLen); + + if (pmsg->flags & I2C_M_RECV_LEN) + pmsg->len = ucXferLen; + + break; + } + + } + if (retries >= MCP2221_RETRY_MAX) + return -EFAULT; + } else { + /* I2C write */ + ucXferLen = (u8)pmsg->len; + dev->obuffer[0] = CMD_MCP2221_WRDATA7; + dev->obuffer[1] = ucXferLen; /* LSB of the xfer length */ + dev->obuffer[2] = 0; /* no MSB for the xfer length */ + /* address in 8-bit format */ + dev->obuffer[3] = (u8)((pmsg->addr) << 1); + /* copy the data we've read back */ + pSrc = (u8 *)&pmsg->buf[0]; + pDst = (u8 *)&dev->obuffer[4]; + memcpy(pDst, pSrc, ucXferLen); + + retries = 0; + + while (retries < MCP2221_RETRY_MAX) { + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) { + usbCmdStatus = dev->ibuffer[2]; + if (usbCmdStatus == RESP_I2C_START_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_NACK) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRDATA_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_STOP_TOUT) + return -EFAULT; + + msleep(sleepCmd); + retries++; + continue; + } else { /* command completed successfully */ + break; + } + } + if (retries >= MCP2221_RETRY_MAX) + return -EFAULT; + + /* now, prepare for the STATUS stage */ + retries = 0; + dev->obuffer[0] = CMD_MCP2221_STATUS; /* code for STATUS cmd */ + dev->obuffer[1] = 0x00; + dev->obuffer[2] = 0x00; + dev->obuffer[3] = 0x00; + dev->obuffer[4] = 0x00; + dev->obuffer[5] = 0x00; + dev->obuffer[6] = 0x00; + dev->obuffer[7] = 0x00; + + while (retries < MCP2221_RETRY_MAX) { + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) + return -EFAULT; + + /* i2c slave address was nack-ed */ + if (dev->ibuffer[20] & MASK_ADDR_NACK) + return -EFAULT; + + usbCmdStatus = dev->ibuffer[8]; + if (usbCmdStatus == RESP_I2C_IDLE) + break; + + if (usbCmdStatus == RESP_I2C_START_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_WSEND) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_NACK) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRDATA_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_STOP_TOUT) + return -EFAULT; + + msleep(sleepCmd); + retries++; + } + if (retries >= MCP2221_RETRY_MAX) + return -EFAULT; + } + + return 0; +} + +/* device layer */ +static int mcp2221_usb_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct i2c_mcp2221 *dev = i2c_get_adapdata(adap); + struct i2c_msg *pmsg; + int ret, count; + + for (count = 0; count < num; count++) { + pmsg = &msgs[count]; + /* no concurrent users of the mcp2221 i2c xfer */ + ret = mutex_lock_interruptible(&dev->mcp2221_usb_op_lock); + if (ret < 0) + goto abort; + + ret = mcp2221_i2c_readwrite(dev, pmsg); + mutex_unlock(&dev->mcp2221_usb_op_lock); + if (ret < 0) + goto abort; + } + + /* if all the messages were transferred ok, return "num" */ + ret = num; + +abort: + return ret; +} + +static const struct i2c_algorithm mcp2221_usb_algorithm = { + .master_xfer = mcp2221_usb_i2c_xfer, + .functionality = mcp2221_usb_func, +}; + +static const struct usb_device_id mcp2221_table[] = { + { USB_DEVICE(USB_VENDOR_ID_MCP2221, USB_DEVICE_ID_MCP2221) }, + { } +}; + +MODULE_DEVICE_TABLE(usb, mcp2221_table); + +static void mcp2221_free(struct i2c_mcp2221 *dev) +{ + usb_put_dev(dev->usb_dev); + kfree(dev); +} + +static int mcp2221_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_host_interface *hostif = interface->cur_altsetting; + struct i2c_mcp2221 *dev; + int ret; + + if ((hostif->desc.bInterfaceNumber != 2) + || (hostif->desc.bInterfaceClass != 3)) { + pr_info("i2c-mcp2221(probe): Interface doesn't match the MCP2221 HID\n"); + return -ENODEV; + } + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + pr_info("i2c-mcp2221(probe): no memory for device state\n"); + ret = -ENOMEM; + goto error; + } + + dev->ep_in = hostif->endpoint[0].desc.bEndpointAddress; + dev->ep_out = hostif->endpoint[1].desc.bEndpointAddress; + + dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); + dev->interface = interface; + + init_waitqueue_head(&dev->usb_urb_completion_wait); + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + + /* setup i2c adapter description */ + dev->adapter.owner = THIS_MODULE; + dev->adapter.class = I2C_CLASS_HWMON; + dev->adapter.algo = &mcp2221_usb_algorithm; + i2c_set_adapdata(&dev->adapter, dev); + + snprintf(dev->adapter.name, sizeof(dev->adapter.name), + DRIVER_NAME " at bus %03d device %03d", + dev->usb_dev->bus->busnum, dev->usb_dev->devnum); + + dev->adapter.dev.parent = &dev->interface->dev; + + /* initialize mcp2221 i2c interface */ + ret = mcp2221_init(dev); + if (ret < 0) { + dev_err(&interface->dev, "failed to initialize adapter\n"); + goto error_free; + } + + /* and finally attach to i2c layer */ + ret = i2c_add_adapter(&dev->adapter); + if (ret < 0) { + dev_err(&interface->dev, "failed to add I2C adapter\n"); + goto error_free; + } + + dev_info(&dev->interface->dev, + "mcp2221_probe() -> chip connected -> Success\n"); + return 0; + +error_free: + usb_set_intfdata(interface, NULL); + mcp2221_free(dev); +error: + return ret; +} + +static void mcp2221_disconnect(struct usb_interface *interface) +{ + struct i2c_mcp2221 *dev = usb_get_intfdata(interface); + + i2c_del_adapter(&dev->adapter); + + usb_kill_urb(dev->interrupt_in_urb); + usb_kill_urb(dev->interrupt_out_urb); + usb_free_urb(dev->interrupt_in_urb); + usb_free_urb(dev->interrupt_out_urb); + + usb_set_intfdata(interface, NULL); + mcp2221_free(dev); + + pr_info("i2c-mcp2221(disconnect) -> chip disconnected"); +} + +static struct usb_driver mcp2221_driver = { + .name = DRIVER_NAME, + .probe = mcp2221_probe, + .disconnect = mcp2221_disconnect, + .id_table = mcp2221_table, +}; + +module_usb_driver(mcp2221_driver); + +MODULE_AUTHOR("Bogdan Bolocan"); +MODULE_DESCRIPTION(DRIVER_NAME "I2C MCP2221"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld.c new file mode 100644 index 000000000000..3a7d40ba9177 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld.c @@ -0,0 +1,198 @@ +/* + * wnc_cpld.c - A driver for control wnc_cpld base on lm75.c + * + * Copyright (c) 1998, 1999 Frodo Looijaard + * Copyright (c) 2017 WNC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Addresses scanned */ +static const unsigned short normal_i2c[] = { 0x31, 0x32, I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define CPLD_SIZE 3 + +/* Each client has this additional data */ +struct cpld_data { + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 data[CPLD_SIZE]; /* Register value */ +}; + +static ssize_t show_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + data->data[0] = i2c_smbus_read_byte_data(client, attr->index); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%02x\n", data->data[0]); +} + +static ssize_t set_value(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 temp; + int error; + + error = kstrtou8(buf, 10, &temp); + if (error) + return error; + + mutex_lock(&data->update_lock); + i2c_smbus_write_byte_data(client, attr->index, temp); + mutex_unlock(&data->update_lock); + + return count; +} + +static SENSOR_DEVICE_ATTR(reset_control, S_IWUSR | S_IRUGO, show_value, set_value, 2); +static SENSOR_DEVICE_ATTR(sfp_mod_abs1, S_IRUGO, show_value, NULL, 3); +static SENSOR_DEVICE_ATTR(sfp_mod_abs2, S_IRUGO, show_value, NULL, 4); +static SENSOR_DEVICE_ATTR(sfp_mod_abs3, S_IRUGO, show_value, NULL, 5); +static SENSOR_DEVICE_ATTR(sfp_mod_abs4, S_IRUGO, show_value, NULL, 6); +static SENSOR_DEVICE_ATTR(qsfp_modprs, S_IRUGO, show_value, NULL, 22); +static SENSOR_DEVICE_ATTR(qsfp_lpmode, S_IWUSR | S_IRUGO, show_value, set_value, 24); + +static struct attribute *cpld2_attributes[] = { + &sensor_dev_attr_reset_control.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs1.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs2.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs3.dev_attr.attr, + &sensor_dev_attr_qsfp_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_lpmode.dev_attr.attr, + NULL +}; + +static struct attribute *cpld1_attributes[] = { + &sensor_dev_attr_sfp_mod_abs1.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs2.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs3.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs4.dev_attr.attr, + NULL +}; + +static const struct attribute_group cpld2_group = { + .attrs = cpld2_attributes, +}; + +static const struct attribute_group cpld1_group = { + .attrs = cpld1_attributes, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int cpld_detect(struct i2c_client *new_client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + int conf; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + /* Unused bits */ + conf = i2c_smbus_read_byte_data(new_client, 0); + if (!conf) + return -ENODEV; + + return 0; +} + + +static int cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; +#if 1 + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); +#endif + + if (client->addr == 49) /* 0x31 */ + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpld1_group); + else if (client->addr == 50) /* 0x32 */ + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpld2_group); + else + status = 1; + + if (status) + return status; + + dev_info(&client->dev, "cpld 0x%x found\n", client->addr); + + return 0; +} + +static int cpld_remove(struct i2c_client *client) +{ + if (client->addr == 49) /* 0x31 */ + sysfs_remove_group(&client->dev.kobj, &cpld1_group); + else if (client->addr == 50) /* 0x32 */ + sysfs_remove_group(&client->dev.kobj, &cpld2_group); + else + return 1; + + return 0; +} + +static const struct i2c_device_id cpld_id[] = { + { "wnc_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "wnc_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, + .detect = cpld_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(cpld_driver); + +MODULE_AUTHOR("WNC "); +MODULE_DESCRIPTION("WNC CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld3.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld3.c new file mode 100644 index 000000000000..a24698aa9cef --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld3.c @@ -0,0 +1,200 @@ +/* + * wnc_cpld.c - A driver for control wnc_cpld3 base on lm75.c + * + * Copyright (c) 1998, 1999 Frodo Looijaard + * Copyright (c) 2017 WNC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Addresses scanned */ +static const unsigned short normal_i2c[] = { 0x33, I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define CPLD_SIZE 3 + +/* Each client has this additional data */ +struct cpld_data { + struct i2c_client *client; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 data[CPLD_SIZE]; /* Register value */ +}; + +static ssize_t show_hwmon_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int index = to_sensor_dev_attr_2(da)->index; + + mutex_lock(&data->update_lock); + data->data[0] = i2c_smbus_read_byte_data(client, index); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", data->data[0]); +} + +static ssize_t show_sysfs_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + data->data[0] = i2c_smbus_read_byte_data(client, attr->index); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%02x\n", data->data[0]); +} + +static ssize_t set_hwmon_value(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int index = to_sensor_dev_attr_2(da)->index; + u8 temp; + int error; + + error = kstrtou8(buf, 10, &temp); + if (error) + return error; + + mutex_lock(&data->update_lock); + i2c_smbus_write_byte_data(client, index, temp); + mutex_unlock(&data->update_lock); + + return count; +} + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_hwmon_value, NULL, 6); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_hwmon_value, NULL, 7); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_hwmon_value, NULL, 8); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_hwmon_value, NULL, 9); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_hwmon_value, NULL, 10); +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 6); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 7); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 8); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 9); +static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 10); + +static struct attribute *cpld3_hwmon_attrs[] = { + &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_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_pwm5.dev_attr.attr, + NULL +}; + +ATTRIBUTE_GROUPS(cpld3_hwmon); + +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, show_sysfs_value, NULL, 1); +static SENSOR_DEVICE_ATTR(power_good, S_IRUGO, show_sysfs_value, NULL, 4); + +static struct attribute *cpld3_sysfs_attrs[] = { + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_power_good.dev_attr.attr, + NULL +}; + +static const struct attribute_group cpld3_sysfs_group = { + .attrs = cpld3_sysfs_attrs, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int cpld_detect(struct i2c_client *new_client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + int conf; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + /* Unused bits */ + conf = i2c_smbus_read_byte_data(new_client, 0); + if (!conf) + return -ENODEV; + + return 0; +} + + +static int cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct device *hwmon_dev; + struct cpld_data *data; + int status; + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + status = sysfs_create_group(&client->dev.kobj, &cpld3_sysfs_group); + hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, client->name, data, cpld3_hwmon_groups); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static int cpld_remove(struct i2c_client *client) +{ + devm_hwmon_device_unregister(&client->dev); + sysfs_remove_group(&client->dev.kobj, &cpld3_sysfs_group); + return 0; +} + +static const struct i2c_device_id cpld_id[] = { + { "wnc_cpld3", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "wnc_cpld3", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, + .detect = cpld_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(cpld_driver); + +MODULE_AUTHOR("WNC "); +MODULE_DESCRIPTION("WNC CPLD3 driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_eeprom.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_eeprom.c new file mode 100644 index 000000000000..8ddf1f2af279 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_eeprom.c @@ -0,0 +1,286 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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 + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, I2C_CLIENT_END }; + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +/* possible types of eeprom devices */ +enum eeprom_nature { + UNKNOWN, + VAIO, +}; + +/* 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[8]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ + enum eeprom_nature nature; +}; + + +static void eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i; + + 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); + + if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + //for (i = slice << 5; i < (slice + 1) << 5; i += 32) + for (i = slice << 5; i < (slice + 1) << 5; i += 24) + if (i2c_smbus_read_i2c_block_data(client, i, + 24, data->data + i) + != 24) + goto exit; + } else { + for (i = slice << 5; i < (slice + 1) << 5; i += 2) { + int word = i2c_smbus_read_word_data(client, i); + if (word < 0) + goto exit; + data->data[i] = word & 0xff; + data->data[i + 1] = word >> 8; + } + } + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t 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; + + data->valid = 0; + + if (off > EEPROM_SIZE) + return 0; + if (off + count > EEPROM_SIZE) + count = EEPROM_SIZE - off; + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++) + eeprom_update_client(client, slice); + + /* Hide Vaio private settings to regular users: + - BIOS passwords: bytes 0x00 to 0x0f + - UUID: bytes 0x10 to 0x1f + - Serial number: 0xc0 to 0xdf */ + if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) { + int i; + + for (i = 0; i < count; i++) { + if ((off + i <= 0x1f) || + (off + i >= 0xc0 && off + i <= 0xdf)) + buf[i] = 0; + else + buf[i] = data->data[off + i]; + } + } else { + memcpy(buf, &data->data[off], count); + } + + return count; +} + +static ssize_t eeprom_write(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 temp; + int error, reg; + + mutex_lock(&data->update_lock); + + error = kstrtou8(buf, 10, &temp); + if (error) + return error; + + if (client->addr == 0x51) { /* SFP AOC cable, page selection byte is 126 */ + reg = 126; + } + else if (client->addr == 0x50) { /* QSFP, page selection byte is 127 */ + data->data[0] = i2c_smbus_read_byte_data(client, 0); + + /* Base on SFF-8024, determine this module is SFP or QSFP by byte 0 (Identifier) */ + switch (data->data[0]){ + case 12: + case 13: + case 17: + case 24: + reg = 127; + break; + + default: + goto exit; + } + } + else + goto exit; + + i2c_smbus_write_byte_data(client, reg, temp); + +exit: + mutex_unlock(&data->update_lock); + + return count; +} + +static struct bin_attribute eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IWUSR | S_IRUGO | S_IWGRP | S_IWOTH, + }, + .size = EEPROM_SIZE, + .read = eeprom_read, + .write = eeprom_write, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) + return -ENODEV; + + /* There are four ways we can read the EEPROM data: + (1) I2C block reads (faster, but unsupported by most adapters) + (2) Word reads (128% overhead) + (3) Consecutive byte reads (88% overhead, unsafe) + (4) Regular byte data reads (265% overhead) + The third and fourth methods are not implemented by this driver + because all known adapters support one of the first two. */ + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) + return -ENODEV; + + strlcpy(info->type, "wnc_eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + 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); + data->nature = UNKNOWN; + + /* Detect the Vaio nature of EEPROMs. + We use the "PCG-" or "VGN-" prefix as the signature. */ + if (client->addr == 0x57 + && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + char name[4]; + + name[0] = i2c_smbus_read_byte_data(client, 0x80); + name[1] = i2c_smbus_read_byte_data(client, 0x81); + name[2] = i2c_smbus_read_byte_data(client, 0x82); + name[3] = i2c_smbus_read_byte_data(client, 0x83); + + if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) { + dev_info(&client->dev, "Vaio EEPROM detected, " + "enabling privacy protection\n"); + data->nature = VAIO; + } + } + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr); + if (err) + goto exit_kfree; + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id eeprom_id[] = { + { "wnc_eeprom", 0 }, + { } +}; + +static struct i2c_driver eeprom_driver = { + .driver = { + .name = "wnc_eeprom", + }, + .probe = eeprom_probe, + .remove = eeprom_remove, + .id_table = eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(eeprom_driver); + +MODULE_AUTHOR("Frodo Looijaard and " + "Philip Edelbrock and " + "Greg Kroah-Hartman "); +MODULE_DESCRIPTION("I2C EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/device_node.sh b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/device_node.sh new file mode 100644 index 000000000000..7e1c7c45a725 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/device_node.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +SEARCH_I2C_BUS=$(ls /sys/bus/i2c/devices) +I2C_BUS=-1 + +for i in $SEARCH_I2C_BUS +do + if [[ -n $(cat /sys/bus/i2c/devices/$i/name | grep i2c-mcp2221) ]]; then + I2C_BUS=$(echo $i | sed 's/i2c-//g') + break + fi +done + +if [[ $I2C_BUS == -1 ]]; then + echo "Can't find i2c-mcp2221" + exit +fi + +TOTAL_MUX=8 +START_NODE_NUM=$((I2C_BUS+1)) + +modprobe i2c_mux_pca954x force_deselect_on_exit=1 + +echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device + +sleep 5 + +/sbin/modprobe wnc_cpld +/sbin/modprobe wnc_cpld3 +/sbin/modprobe wnc_eeprom +/sbin/modprobe eeprom + +# MUX0: i2c-3~i2c-10 +# MUX1: i2c-11~i2c-18 +# MUX2: i2c-19~i2c-26 +# MUX3: i2c-27~i2c-34 +# MUX4: i2c-35~i2c-42 +# MUX5: i2c-43~i2c-50 +# MUX6: i2c-51~i2c-58 +# MUX7: i2c-59~i2c-66 + +# MUX0 channel0 +CHANNEL=0 +echo wnc_cpld 0x31 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel1 +CHANNEL=1 +echo wnc_cpld 0x32 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel2 +CHANNEL=2 +echo wnc_cpld3 0x33 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +echo wnc_eeprom 0x53 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel3 +CHANNEL=3 +echo wnc_eeprom 0x50 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +echo wnc_eeprom 0x51 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel4 +CHANNEL=4 +echo wnc_eeprom 0x54 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +echo tmp421 0x1E > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +sleep 1 +echo tmp75 0x4E > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +sleep 1 +echo tmp421 0x4F > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel5 +CHANNEL=5 +echo wnc_eeprom 0x52 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel7 +CHANNEL=7 +#echo wnc_eeprom 0x5B > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +START_PORT_NUM=$((START_NODE_NUM+8)) +END_PORT_NUM=$((TOTAL_MUX*8+1)) + +for i in $(seq $START_PORT_NUM $END_PORT_NUM) +do + echo wnc_eeprom 0x50 > /sys/bus/i2c/devices/i2c-$i/new_device + echo wnc_eeprom 0x51 > /sys/bus/i2c/devices/i2c-$i/new_device +done diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/driver_load.sh b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/driver_load.sh new file mode 100644 index 000000000000..81cee0383ff2 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/driver_load.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +vid=04d8 +pid=00dd + +#check to see if sysfs is mounted +sysfs_path=`awk '/^sysfs/{ print $2 }' < /proc/mounts` +curr_path=`pwd` + +#if variable is empty, we should exit. No SYSFS found +if [[ -z $sysfs_path ]]; then + echo "No sysfs in this system! Exiting..." + exit 1 +fi + +function load_drivers +{ + modprobe i2c-dev + if [[ $? -ne 0 ]]; then + echo "Cannot load the \"i2c-dev\" driver! Exiting..." + exit 1 + fi + modprobe i2c-mcp2221 + if [[ $? -ne 0 ]]; then + echo "Cannot load the \"i2c-mcp2221\" driver! Exiting..." + exit 1 + fi + echo "I2C related drivers are loaded" +} + +usb_device_path=${sysfs_path}/bus/usb/devices + +cd $usb_device_path + +for usbdev in *; do + idvendor=${usb_device_path}/${usbdev}/idVendor + idproduct=${usb_device_path}/${usbdev}/idProduct + usb_driver=${usb_device_path}/${usbdev}/${usbdev}:1.2/driver + if [[ -f $idvendor ]]; then + dev_vid=`grep -i $vid < $idvendor` + dev_pid=`grep -i $pid < $idproduct` + if [[ -n $dev_vid ]] && [[ -n $dev_pid ]]; then + echo "I found the requested VID/PID: $dev_vid, $dev_pid" + load_drivers + echo -n "${usbdev}:1.2" > ${usb_driver}/unbind + echo -n "${usbdev}:1.2" > ${sysfs_path}/bus/usb/drivers/i2c-mcp2221/bind + fi + fi +done + diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/test b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/test new file mode 100644 index 000000000000..38327722c91f --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/test @@ -0,0 +1 @@ +echo "test" diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/device_node.service b/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/device_node.service new file mode 100644 index 000000000000..fd1bd9b15648 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/device_node.service @@ -0,0 +1,11 @@ +[Unit] +Description=Create device nodes for i2c devices. +Requires=driver_load.service +After=driver_load.service + +[Service] +Type=oneshot +ExecStart=/bin/bash /usr/local/bin/device_node.sh + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/driver_load.service b/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/driver_load.service new file mode 100644 index 000000000000..52ce4d2f4442 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/driver_load.service @@ -0,0 +1,10 @@ +[Unit] +Description=Initialize i2c-mcp2221 driver. +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=/bin/bash /usr/local/bin/driver_load.sh + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/docker-orchagent-brcm.mk b/platform/broadcom/docker-orchagent-brcm.mk new file mode 100644 index 000000000000..dc3c31f43d5b --- /dev/null +++ b/platform/broadcom/docker-orchagent-brcm.mk @@ -0,0 +1,24 @@ +# docker image for orchagent + +DOCKER_ORCHAGENT_BRCM = docker-orchagent-brcm.gz +$(DOCKER_ORCHAGENT_BRCM)_PATH = $(DOCKERS_PATH)/docker-orchagent +$(DOCKER_ORCHAGENT_BRCM)_DEPENDS += $(SWSS) $(REDIS_TOOLS) $(IPROUTE2) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_ORCHAGENT_BRCM)_DEPENDS += $(SWSS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_ORCHAGENT_BRCM)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_BRCM) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_BRCM) + +$(DOCKER_ORCHAGENT_BRCM)_CONTAINER_NAME = swss +$(DOCKER_ORCHAGENT_BRCM)_RUN_OPT += --net=host --privileged -t +$(DOCKER_ORCHAGENT_BRCM)_RUN_OPT += -v /etc/network/interfaces:/etc/network/interfaces:ro +$(DOCKER_ORCHAGENT_BRCM)_RUN_OPT += -v /etc/network/interfaces.d/:/etc/network/interfaces.d/:ro +$(DOCKER_ORCHAGENT_BRCM)_RUN_OPT += -v /host/machine.conf:/host/machine.conf:ro +$(DOCKER_ORCHAGENT_BRCM)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_ORCHAGENT_BRCM)_RUN_OPT += -v /var/log/swss:/var/log/swss:rw + +$(DOCKER_ORCHAGENT_BRCM)_BASE_IMAGE_FILES += swssloglevel:/usr/bin/swssloglevel +$(DOCKER_ORCHAGENT_BRCM)_FILES += $(ARP_UPDATE_SCRIPT) diff --git a/platform/broadcom/docker-ptf-brcm.mk b/platform/broadcom/docker-ptf-brcm.mk new file mode 100644 index 000000000000..510f21e8a436 --- /dev/null +++ b/platform/broadcom/docker-ptf-brcm.mk @@ -0,0 +1,7 @@ +# docker image for docker-ptf-brcm + +DOCKER_PTF_BRCM = docker-ptf-brcm.gz +$(DOCKER_PTF_BRCM)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift +$(DOCKER_PTF_BRCM)_DEPENDS += $(PYTHON_SAITHRIFT) +$(DOCKER_PTF_BRCM)_LOAD_DOCKERS += $(DOCKER_PTF) +SONIC_DOCKER_IMAGES += $(DOCKER_PTF_BRCM) diff --git a/platform/broadcom/docker-saiserver-brcm.mk b/platform/broadcom/docker-saiserver-brcm.mk new file mode 100644 index 000000000000..f0aead6b3d72 --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm.mk @@ -0,0 +1,18 @@ +# docker image for brcm saiserver + +DOCKER_SAISERVER_BRCM = docker-saiserver-brcm.gz +$(DOCKER_SAISERVER_BRCM)_PATH = $(PLATFORM_PATH)/docker-saiserver-brcm +$(DOCKER_SAISERVER_BRCM)_DEPENDS += $(SAISERVER) +$(DOCKER_SAISERVER_BRCM)_FILES += $(DSSERVE) $(BCMCMD) +$(DOCKER_SAISERVER_BRCM)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SAISERVER_BRCM) + +$(DOCKER_SAISERVER_BRCM)_CONTAINER_NAME = saiserver +$(DOCKER_SAISERVER_BRCM)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SAISERVER_BRCM)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SAISERVER_BRCM)_RUN_OPT += -v /var/run/docker-saiserver:/var/run/sswsyncd +$(DOCKER_SAISERVER_BRCM)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SAISERVER_BRCM)_RUN_OPT += -v /host/warmboot:/var/warmboot + +$(DOCKER_SAISERVER_BRCM)_BASE_IMAGE_FILES += bcmcmd:/usr/bin/bcmcmd +$(DOCKER_SAISERVER_BRCM)_BASE_IMAGE_FILES += bcmsh:/usr/bin/bcmsh diff --git a/platform/broadcom/docker-saiserver-brcm/Dockerfile.j2 b/platform/broadcom/docker-saiserver-brcm/Dockerfile.j2 new file mode 100644 index 000000000000..7961aa98fb4e --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm/Dockerfile.j2 @@ -0,0 +1,36 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_saiserver_brcm_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_saiserver_brcm_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +## TODO: add kmod into Depends +RUN apt-get install -yf kmod + +COPY ["files/dsserve", "files/bcmcmd", "start.sh", "bcmsh", "/usr/bin/"] +RUN chmod +x /usr/bin/dsserve /usr/bin/bcmcmd + +COPY ["profile.ini", "portmap.ini", "/etc/sai/"] + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/broadcom/docker-saiserver-brcm/bcmsh b/platform/broadcom/docker-saiserver-brcm/bcmsh new file mode 100755 index 000000000000..7488e63c64fd --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm/bcmsh @@ -0,0 +1,40 @@ +#!/bin/bash +usage="$(basename "$0") [-h] [-q] [-t timeout] -- interactive shell for bcm service + +where: + -h show this help text + -t inactivity timeout in seconds (default 300 seconds, 0 for no timeout) + -q quite, no banner (default: verbose)" + +banner="Press Enter to show prompt. +Press Ctrl+C to exit. +NOTICE: Only one bcmsh or bcmcmd can connect to the shell at same time. +" + +# Default verbose +quiet=false +timeout=300 + +while getopts 'hqt:' option; do + case "$option" in + h) echo "$usage" + exit + ;; + q) quiet=true + ;; + t) timeout=$OPTARG + ;; + \?) printf "illegal option: -%s\n" "$OPTARG" >&2 + echo "$usage" >&2 + exit 1 + ;; + esac +done +shift $((OPTIND - 1)) + +if [ "$quiet" = false ]; then + echo "$banner" +fi + +/usr/bin/socat -T$timeout readline UNIX-CONNECT:/var/run/sswsyncd/sswsyncd.socket + diff --git a/platform/broadcom/docker-saiserver-brcm/portmap.ini b/platform/broadcom/docker-saiserver-brcm/portmap.ini new file mode 100644 index 000000000000..7161416e4d4c --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm/portmap.ini @@ -0,0 +1,33 @@ +# alias lanes +Ethernet0 29,30,31,32 +Ethernet4 25,26,27,28 +Ethernet8 37,38,39,40 +Ethernet12 33,34,35,36 +Ethernet16 41,42,43,44 +Ethernet20 45,46,47,48 +Ethernet24 5,6,7,8 +Ethernet28 1,2,3,4 +Ethernet32 9,10,11,12 +Ethernet36 13,14,15,16 +Ethernet40 21,22,23,24 +Ethernet44 17,18,19,20 +Ethernet48 49,50,51,52 +Ethernet52 53,54,55,56 +Ethernet56 61,62,63,64 +Ethernet60 57,58,59,60 +Ethernet64 65,66,67,68 +Ethernet68 69,70,71,72 +Ethernet72 77,78,79,80 +Ethernet76 73,74,75,76 +Ethernet80 105,106,107,108 +Ethernet84 109,110,111,112 +Ethernet88 117,118,119,120 +Ethernet92 113,114,115,116 +Ethernet96 121,122,123,124 +Ethernet100 125,126,127,128 +Ethernet104 85,86,87,88 +Ethernet108 81,82,83,84 +Ethernet112 89,90,91,92 +Ethernet116 93,94,95,96 +Ethernet120 97,98,99,100 +Ethernet124 101,102,103,104 diff --git a/platform/broadcom/docker-saiserver-brcm/profile.ini b/platform/broadcom/docker-saiserver-brcm/profile.ini new file mode 100644 index 000000000000..b64d997fb451 --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm/profile.ini @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/etc/bcm/td2-s6000-32x40G.config.bcm diff --git a/platform/broadcom/docker-saiserver-brcm/start.sh b/platform/broadcom/docker-saiserver-brcm/start.sh new file mode 100755 index 000000000000..494c0e9126c2 --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm/start.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +start_bcm() +{ + [ -e /dev/linux-bcm-knet ] || mknod /dev/linux-bcm-knet c 122 0 + [ -e /dev/linux-user-bde ] || mknod /dev/linux-user-bde c 126 0 + [ -e /dev/linux-kernel-bde ] || mknod /dev/linux-kernel-bde c 127 0 +} + + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +start_bcm + +supervisorctl start saiserver diff --git a/platform/broadcom/docker-saiserver-brcm/supervisord.conf b/platform/broadcom/docker-saiserver-brcm/supervisord.conf new file mode 100644 index 000000000000..cb67a0fc9a47 --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm/supervisord.conf @@ -0,0 +1,28 @@ +[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:saiserver] +command=/usr/bin/saiserver -p /etc/sai/profile.ini -f /etc/sai/portmap.ini +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/broadcom/docker-syncd-brcm-rpc.mk b/platform/broadcom/docker-syncd-brcm-rpc.mk new file mode 100644 index 000000000000..fa7c0fb797c7 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm-rpc.mk @@ -0,0 +1,17 @@ +# docker image for brcm syncd with rpc + +DOCKER_SYNCD_BRCM_RPC = docker-syncd-brcm-rpc.gz +$(DOCKER_SYNCD_BRCM_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-brcm-rpc +$(DOCKER_SYNCD_BRCM_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) +$(DOCKER_SYNCD_BRCM_RPC)_FILES += $(DSSERVE) $(BCMCMD) +$(DOCKER_SYNCD_BRCM_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BRCM) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_BRCM_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_BRCM_RPC) +endif + +$(DOCKER_SYNCD_BRCM_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd +$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/broadcom/docker-syncd-brcm-rpc/Dockerfile.j2 b/platform/broadcom/docker-syncd-brcm-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..c8f0590023ed --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm-rpc/Dockerfile.j2 @@ -0,0 +1,51 @@ +FROM docker-syncd-brcm + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_brcm_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -P syncd + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_brcm_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + && wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/broadcom/docker-syncd-brcm-rpc/ptf_nn_agent.conf b/platform/broadcom/docker-syncd-brcm-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/broadcom/docker-syncd-brcm.mk b/platform/broadcom/docker-syncd-brcm.mk new file mode 100644 index 000000000000..088437060964 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm.mk @@ -0,0 +1,21 @@ +# docker image for brcm syncd + +DOCKER_SYNCD_BRCM = docker-syncd-brcm.gz +$(DOCKER_SYNCD_BRCM)_PATH = $(PLATFORM_PATH)/docker-syncd-brcm +$(DOCKER_SYNCD_BRCM)_DEPENDS += $(SYNCD) +$(DOCKER_SYNCD_BRCM)_FILES += $(DSSERVE) $(BCMCMD) +$(DOCKER_SYNCD_BRCM)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_BRCM) +ifneq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_BRCM) +endif + +$(DOCKER_SYNCD_BRCM)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_BRCM)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_BRCM)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_BRCM)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd +$(DOCKER_SYNCD_BRCM)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SYNCD_BRCM)_RUN_OPT += -v /host/warmboot:/var/warmboot + +$(DOCKER_SYNCD_BRCM)_BASE_IMAGE_FILES += bcmcmd:/usr/bin/bcmcmd +$(DOCKER_SYNCD_BRCM)_BASE_IMAGE_FILES += bcmsh:/usr/bin/bcmsh diff --git a/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 b/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 new file mode 100755 index 000000000000..78c296d96d92 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 @@ -0,0 +1,34 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_syncd_brcm_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_syncd_brcm_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +## TODO: add kmod into Depends +RUN apt-get install -yf kmod + +COPY ["files/dsserve", "files/bcmcmd", "start.sh", "bcmsh", "/usr/bin/"] +RUN chmod +x /usr/bin/dsserve /usr/bin/bcmcmd + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/broadcom/docker-syncd-brcm/base_image_files/bcmcmd b/platform/broadcom/docker-syncd-brcm/base_image_files/bcmcmd new file mode 100755 index 000000000000..7903db6ed6a3 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/base_image_files/bcmcmd @@ -0,0 +1,3 @@ +#!/bin/bash + +docker exec -i syncd bcmcmd "$@" diff --git a/platform/broadcom/docker-syncd-brcm/base_image_files/bcmsh b/platform/broadcom/docker-syncd-brcm/base_image_files/bcmsh new file mode 100755 index 000000000000..3bb78b0da796 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/base_image_files/bcmsh @@ -0,0 +1,3 @@ +#!/bin/bash + +docker exec -it syncd bcmsh "$@" diff --git a/platform/broadcom/docker-syncd-brcm/bcmsh b/platform/broadcom/docker-syncd-brcm/bcmsh new file mode 100755 index 000000000000..7488e63c64fd --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/bcmsh @@ -0,0 +1,40 @@ +#!/bin/bash +usage="$(basename "$0") [-h] [-q] [-t timeout] -- interactive shell for bcm service + +where: + -h show this help text + -t inactivity timeout in seconds (default 300 seconds, 0 for no timeout) + -q quite, no banner (default: verbose)" + +banner="Press Enter to show prompt. +Press Ctrl+C to exit. +NOTICE: Only one bcmsh or bcmcmd can connect to the shell at same time. +" + +# Default verbose +quiet=false +timeout=300 + +while getopts 'hqt:' option; do + case "$option" in + h) echo "$usage" + exit + ;; + q) quiet=true + ;; + t) timeout=$OPTARG + ;; + \?) printf "illegal option: -%s\n" "$OPTARG" >&2 + echo "$usage" >&2 + exit 1 + ;; + esac +done +shift $((OPTIND - 1)) + +if [ "$quiet" = false ]; then + echo "$banner" +fi + +/usr/bin/socat -T$timeout readline UNIX-CONNECT:/var/run/sswsyncd/sswsyncd.socket + diff --git a/platform/broadcom/docker-syncd-brcm/start.sh b/platform/broadcom/docker-syncd-brcm/start.sh new file mode 100755 index 000000000000..45c4ab92dabf --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/start.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +PLATFORM_DIR=/usr/share/sonic/platform +HWSKU_DIR=/usr/share/sonic/hwsku + +SYNCD_SOCKET_FILE=/var/run/sswsyncd/sswsyncd.socket + +# Function: wait until syncd has created the socket for bcmcmd to connect to +wait_syncd() { + while true; do + if [ -e ${SYNCD_SOCKET_FILE} ]; then + break + fi + sleep 1 + done + + # wait until bcm sdk is ready to get a request + sleep 3 +} + + +# Remove stale files if they exist +rm -f /var/run/rsyslogd.pid +rm -f ${SYNCD_SOCKET_FILE} + +supervisorctl start rsyslogd + +mkdir -p /etc/sai.d/ + +# Create/Copy the sai.profile to /etc/sai.d/sai.profile +if [ -f $HWSKU_DIR/sai.profile.j2 ]; then + sonic-cfggen -d -t $HWSKU_DIR/sai.profile.j2 > /etc/sai.d/sai.profile +else + if [ -f $HWSKU_DIR/sai.profile ]; then + cp $HWSKU_DIR/sai.profile /etc/sai.d/sai.profile + fi +fi + +supervisorctl start syncd + +# If this platform has an initialization file for the Broadcom LED microprocessor, load it +if [[ -r ${PLATFORM_DIR}/led_proc_init.soc && ! -f /var/warmboot/warm-starting ]]; then + wait_syncd + supervisorctl start ledinit +fi diff --git a/platform/broadcom/docker-syncd-brcm/supervisord.conf b/platform/broadcom/docker-syncd-brcm/supervisord.conf new file mode 100644 index 000000000000..fe590ede18c5 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/supervisord.conf @@ -0,0 +1,36 @@ +[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:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:ledinit] +command=/usr/bin/bcmcmd -t 60 "rcload /usr/share/sonic/platform/led_proc_init.soc" +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/broadcom/libsaithrift-dev.mk b/platform/broadcom/libsaithrift-dev.mk new file mode 100644 index 000000000000..b041aa37aa90 --- /dev/null +++ b/platform/broadcom/libsaithrift-dev.mk @@ -0,0 +1,20 @@ +# libsaithrift-dev package + +SAI_VER = 1.3.5 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_amd64.deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(BRCM_SAI) $(BRCM_SAI_DEV) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(BRCM_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_amd64.deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_amd64.deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(BRCM_SAI) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_amd64.deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/broadcom/one-aboot.mk b/platform/broadcom/one-aboot.mk new file mode 100644 index 000000000000..71829fca4013 --- /dev/null +++ b/platform/broadcom/one-aboot.mk @@ -0,0 +1,8 @@ +# sonic broadcom one image installer + +SONIC_ONE_ABOOT_IMAGE = sonic-aboot-broadcom.swi +$(SONIC_ONE_ABOOT_IMAGE)_MACHINE = broadcom +$(SONIC_ONE_ABOOT_IMAGE)_IMAGE_TYPE = aboot +$(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(BRCM_OPENNSL_KERNEL) $(ARISTA_PLATFORM_MODULE_DRIVERS) $(ARISTA_PLATFORM_MODULE_PYTHON2) $(ARISTA_PLATFORM_MODULE_PYTHON3) $(ARISTA_PLATFORM_MODULE) +$(SONIC_ONE_ABOOT_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_ONE_ABOOT_IMAGE) diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk new file mode 100755 index 000000000000..081a83e94ea9 --- /dev/null +++ b/platform/broadcom/one-image.mk @@ -0,0 +1,39 @@ +# sonic broadcom one image installer + +SONIC_ONE_IMAGE = sonic-broadcom.bin +$(SONIC_ONE_IMAGE)_MACHINE = broadcom +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(BRCM_OPENNSL_KERNEL) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ + $(DELL_Z9264F_PLATFORM_MODULE) \ + $(DELL_Z9100_PLATFORM_MODULE) \ + $(DELL_S6100_PLATFORM_MODULE) \ + $(INGRASYS_S8900_54XC_PLATFORM_MODULE) \ + $(INGRASYS_S8900_64XC_PLATFORM_MODULE) \ + $(INGRASYS_S9100_PLATFORM_MODULE) \ + $(INGRASYS_S8810_32Q_PLATFORM_MODULE) \ + $(INGRASYS_S9200_64X_PLATFORM_MODULE) \ + $(ACCTON_AS7712_32X_PLATFORM_MODULE) \ + $(ACCTON_AS5712_54X_PLATFORM_MODULE) \ + $(ACCTON_AS7816_64X_PLATFORM_MODULE) \ + $(ACCTON_AS7716_32X_PLATFORM_MODULE) \ + $(ACCTON_AS7312_54X_PLATFORM_MODULE) \ + $(ACCTON_AS7326_56X_PLATFORM_MODULE) \ + $(ACCTON_AS7716_32XB_PLATFORM_MODULE) \ + $(ACCTON_AS6712_32X_PLATFORM_MODULE) \ + $(ACCTON_AS7726_32X_PLATFORM_MODULE) \ + $(INVENTEC_D7032Q28B_PLATFORM_MODULE) \ + $(INVENTEC_D7054Q28B_PLATFORM_MODULE) \ + $(INVENTEC_D7264Q28B_PLATFORM_MODULE) \ + $(CEL_DX010_PLATFORM_MODULE) \ + $(CEL_HALIBURTON_PLATFORM_MODULE) \ + $(DELTA_AG9032V1_PLATFORM_MODULE) \ + $(DELTA_AG9064_PLATFORM_MODULE) \ + $(DELTA_AG5648_PLATFORM_MODULE) \ + $(DELTA_ET6248BRB_PLATFORM_MODULE) \ + $(QUANTA_IX1B_32X_PLATFORM_MODULE) \ + $(MITAC_LY1200_32X_PLATFORM_MODULE) \ + $(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) \ + $(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/broadcom/platform-modules-accton.mk b/platform/broadcom/platform-modules-accton.mk new file mode 100755 index 000000000000..d9fbf652c4ed --- /dev/null +++ b/platform/broadcom/platform-modules-accton.mk @@ -0,0 +1,61 @@ +# Accton Platform modules + +ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7816_64X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7716_32X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7312_54X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7326_56X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7716_32XB_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS6712_32X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7726_32X_PLATFORM_MODULE_VERSION = 1.1 + +export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION +export ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION +export ACCTON_AS7816_64X_PLATFORM_MODULE_VERSION +export ACCTON_AS7716_32X_PLATFORM_MODULE_VERSION +export ACCTON_AS7312_54X_PLATFORM_MODULE_VERSION +export ACCTON_AS7326_56X_PLATFORM_MODULE_VERSION +export ACCTON_AS7716_32XB_PLATFORM_MODULE_VERSION +export ACCTON_AS6712_32X_PLATFORM_MODULE_VERSION +export ACCTON_AS7726_32X_PLATFORM_MODULE_VERSION + +ACCTON_AS7712_32X_PLATFORM_MODULE = sonic-platform-accton-as7712-32x_$(ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7712_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton +$(ACCTON_AS7712_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(ACCTON_AS7712_32X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7712_32x-r0 +SONIC_DPKG_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE) + +ACCTON_AS5712_54X_PLATFORM_MODULE = sonic-platform-accton-as5712-54x_$(ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS5712_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5712_54x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5712_54X_PLATFORM_MODULE))) + +ACCTON_AS7816_64X_PLATFORM_MODULE = sonic-platform-accton-as7816-64x_$(ACCTON_AS7816_64X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7816_64X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7816_64x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7816_64X_PLATFORM_MODULE))) + +ACCTON_AS7716_32X_PLATFORM_MODULE = sonic-platform-accton-as7716-32x_$(ACCTON_AS7716_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7716_32X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7716_32x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7716_32X_PLATFORM_MODULE))) + +ACCTON_AS7312_54X_PLATFORM_MODULE = sonic-platform-accton-as7312-54x_$(ACCTON_AS7312_54X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7312_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7312_54x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7312_54X_PLATFORM_MODULE))) + +ACCTON_AS7326_56X_PLATFORM_MODULE = sonic-platform-accton-as7326-56x_$(ACCTON_AS7326_56X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7326_56X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7326_56x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7326_56X_PLATFORM_MODULE))) + +ACCTON_AS7716_32XB_PLATFORM_MODULE = sonic-platform-accton-as7716-32xb_$(ACCTON_AS7716_32XB_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7716_32XB_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7716_32xb-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7716_32XB_PLATFORM_MODULE))) + +ACCTON_AS6712_32X_PLATFORM_MODULE = sonic-platform-accton-as6712-32x_$(ACCTON_AS6712_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS6712_32X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as6712_32x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS6712_32X_PLATFORM_MODULE))) + +ACCTON_AS7726_32X_PLATFORM_MODULE = sonic-platform-accton-as7726-32x_$(ACCTON_AS7726_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7726_32X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7726_32x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7726_32X_PLATFORM_MODULE))) + +SONIC_STRETCH_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE) diff --git a/platform/broadcom/platform-modules-alphanetworks.mk b/platform/broadcom/platform-modules-alphanetworks.mk new file mode 100644 index 000000000000..425656e06653 --- /dev/null +++ b/platform/broadcom/platform-modules-alphanetworks.mk @@ -0,0 +1,21 @@ +# Alphanetworks Platform modules + +ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE_VERSION = 1.0 +ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE_VERSION = 1.0 + +export ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE_VERSION +export ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE_VERSION + +ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE = sonic-platform-alphanetworks-snh60a0-320fv2_$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE_VERSION)_amd64.deb +$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-alphanetworks +$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE)_PLATFORM = x86_64-alphanetworks_snh60a0_320fv2-r0 +SONIC_DPKG_DEBS += $(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) + +ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE = sonic-platform-alphanetworks-snh60b0-640f_$(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE_VERSION)_amd64.deb +$(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE)_PLATFORM = x86_64-alphanetworks_snh60b0_640f-r0 +$(eval $(call add_extra_package,$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE),$(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE))) + +SONIC_STRETCH_DEBS += $(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) + + diff --git a/platform/broadcom/platform-modules-arista.mk b/platform/broadcom/platform-modules-arista.mk new file mode 100644 index 000000000000..480aa0cf8396 --- /dev/null +++ b/platform/broadcom/platform-modules-arista.mk @@ -0,0 +1,25 @@ +# Arista Platform modules + +ARISTA_PLATFORM_MODULE_VERSION = 1.0 + +export ARISTA_PLATFORM_MODULE_VERSION + +ARISTA_PLATFORM_MODULE = sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_amd64.deb +$(ARISTA_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-arista +$(ARISTA_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_MAKE_DEBS += $(ARISTA_PLATFORM_MODULE) + +ARISTA_PLATFORM_MODULE_PYTHON2 = python-sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_all.deb +$(eval $(call add_extra_package,$(ARISTA_PLATFORM_MODULE),$(ARISTA_PLATFORM_MODULE_PYTHON2))) + +ARISTA_PLATFORM_MODULE_PYTHON3 = python3-sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_all.deb +$(eval $(call add_extra_package,$(ARISTA_PLATFORM_MODULE),$(ARISTA_PLATFORM_MODULE_PYTHON3))) + +ARISTA_PLATFORM_MODULE_DRIVERS = drivers-sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_amd64.deb +$(eval $(call add_extra_package,$(ARISTA_PLATFORM_MODULE),$(ARISTA_PLATFORM_MODULE_DRIVERS))) + +export ARISTA_PLATFORM_MODULE ARISTA_PLATFORM_MODULE_PYTHON2 ARISTA_PLATFORM_MODULE_PYTHON3 ARISTA_PLATFORM_MODULE_DRIVERS + +export ARISTA_SCD_DRIVER_CONFIG=m + +SONIC_STRETCH_DEBS += $(ARISTA_PLATFORM_MODULE) diff --git a/platform/broadcom/platform-modules-cel.mk b/platform/broadcom/platform-modules-cel.mk new file mode 100644 index 000000000000..1224faaa6750 --- /dev/null +++ b/platform/broadcom/platform-modules-cel.mk @@ -0,0 +1,19 @@ +# Celestica DX010 and Haliburton Platform modules + +CEL_DX010_PLATFORM_MODULE_VERSION = 0.9 +CEL_HALIBURTON_PLATFORM_MODULE_VERSION = 0.9 + +export CEL_DX010_PLATFORM_MODULE_VERSION +export CEL_HALIBURTON_PLATFORM_MODULE_VERSION + +CEL_DX010_PLATFORM_MODULE = platform-modules-dx010_$(CEL_DX010_PLATFORM_MODULE_VERSION)_amd64.deb +$(CEL_DX010_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-cel +$(CEL_DX010_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(CEL_DX010_PLATFORM_MODULE)_PLATFORM = x86_64-cel_seastone-r0 +SONIC_DPKG_DEBS += $(CEL_DX010_PLATFORM_MODULE) + +CEL_HALIBURTON_PLATFORM_MODULE = platform-modules-haliburton_$(CEL_HALIBURTON_PLATFORM_MODULE_VERSION)_amd64.deb +$(CEL_HALIBURTON_PLATFORM_MODULE)_PLATFORM = x86_64-cel_e1031-r0 +$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_HALIBURTON_PLATFORM_MODULE))) + +SONIC_STRETCH_DEBS += $(CEL_DX010_PLATFORM_MODULE) diff --git a/platform/broadcom/platform-modules-dell.mk b/platform/broadcom/platform-modules-dell.mk new file mode 100644 index 000000000000..a2d051ffd911 --- /dev/null +++ b/platform/broadcom/platform-modules-dell.mk @@ -0,0 +1,26 @@ +# Dell Z9100, S6100, Z9264F Platform modules + +DELL_Z9264F_PLATFORM_MODULE_VERSION = 1.1 +DELL_Z9100_PLATFORM_MODULE_VERSION = 1.1 +DELL_S6100_PLATFORM_MODULE_VERSION = 1.1 + +export DELL_Z9264F_PLATFORM_MODULE_VERSION +export DELL_Z9100_PLATFORM_MODULE_VERSION +export DELL_S6100_PLATFORM_MODULE_VERSION + +DELL_Z9100_PLATFORM_MODULE = platform-modules-z9100_$(DELL_Z9100_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_Z9100_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-dell +$(DELL_Z9100_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(DELL_Z9100_PLATFORM_MODULE)_PLATFORM = x86_64-dell_z9100_c2538-r0 +SONIC_DPKG_DEBS += $(DELL_Z9100_PLATFORM_MODULE) + +DELL_S6100_PLATFORM_MODULE = platform-modules-s6100_$(DELL_S6100_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_S6100_PLATFORM_MODULE)_PLATFORM = x86_64-dell_s6100_c2538-r0 +$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S6100_PLATFORM_MODULE))) + +DELL_Z9264F_PLATFORM_MODULE = platform-modules-z9264f_$(DELL_Z9264F_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_Z9264F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_z9264f_c3538-r0 +$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_Z9264F_PLATFORM_MODULE))) + + +SONIC_STRETCH_DEBS += $(DELL_Z9100_PLATFORM_MODULE) diff --git a/platform/broadcom/platform-modules-delta.mk b/platform/broadcom/platform-modules-delta.mk new file mode 100644 index 000000000000..0c186f127a52 --- /dev/null +++ b/platform/broadcom/platform-modules-delta.mk @@ -0,0 +1,31 @@ +# Delta AG9032v1 Platform modules + +DELTA_AG9032V1_PLATFORM_MODULE_VERSION = 1.1 +DELTA_AG9064_PLATFORM_MODULE_VERSION = 1.1 +DELTA_AG5648_PLATFORM_MODULE_VERSION = 1.1 +DELTA_ET6248BRB_PLATFORM_MODULE_VERSION = 1.1 + +export DELTA_AG9032V1_PLATFORM_MODULE_VERSION +export DELTA_AG9064_PLATFORM_MODULE_VERSION +export DELTA_AG5648_PLATFORM_MODULE_VERSION +export DELTA_ET6248BRB_PLATFORM_MODULE_VERSION + +DELTA_AG9032V1_PLATFORM_MODULE = platform-modules-ag9032v1_$(DELTA_AG9032V1_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELTA_AG9032V1_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-delta +$(DELTA_AG9032V1_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(DELTA_AG9032V1_PLATFORM_MODULE)_PLATFORM = x86_64-delta_ag9032v1-r0 +SONIC_DPKG_DEBS += $(DELTA_AG9032V1_PLATFORM_MODULE) + +DELTA_AG9064_PLATFORM_MODULE = platform-modules-ag9064_$(DELTA_AG9064_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELTA_AG9064_PLATFORM_MODULE)_PLATFORM = x86_64-delta_ag9064-r0 +$(eval $(call add_extra_package,$(DELTA_AG9032V1_PLATFORM_MODULE),$(DELTA_AG9064_PLATFORM_MODULE))) + +DELTA_AG5648_PLATFORM_MODULE = platform-modules-ag5648_$(DELTA_AG5648_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELTA_AG5648_PLATFORM_MODULE)_PLATFORM = x86_64-delta_ag5648-r0 +$(eval $(call add_extra_package,$(DELTA_AG9032V1_PLATFORM_MODULE),$(DELTA_AG5648_PLATFORM_MODULE))) + +DELTA_ET6248BRB_PLATFORM_MODULE = platform-modules-et-6248brb_$(DELTA_ET6248BRB_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELTA_ET6248BRB_PLATFORM_MODULE)_PLATFORM = x86_64-delta_et-6248brb-r0 +$(eval $(call add_extra_package,$(DELTA_AG9032V1_PLATFORM_MODULE),$(DELTA_ET6248BRB_PLATFORM_MODULE))) + +SONIC_STRETCH_DEBS += $(DELTA_AG9032V1_PLATFORM_MODULE) \ No newline at end of file diff --git a/platform/broadcom/platform-modules-ingrasys.mk b/platform/broadcom/platform-modules-ingrasys.mk new file mode 100644 index 000000000000..b6195698a1f9 --- /dev/null +++ b/platform/broadcom/platform-modules-ingrasys.mk @@ -0,0 +1,38 @@ +# Ingrasys S9100, S8900-64XC, S8900-54XC and S8810-32Q Platform modules + +INGRASYS_S9100_PLATFORM_MODULE_VERSION = 1.1.0 +INGRASYS_S8900_64XC_PLATFORM_MODULE_VERSION = 1.1.0 +INGRASYS_S8900_54XC_PLATFORM_MODULE_VERSION = 1.1.0 +INGRASYS_S8810_32Q_PLATFORM_MODULE_VERSION = 1.1.0 +INGRASYS_S9200_64X_PLATFORM_MODULE_VERSION = 1.1.0 + +export INGRASYS_S9100_PLATFORM_MODULE_VERSION +export INGRASYS_S8900_64XC_PLATFORM_MODULE_VERSION +export INGRASYS_S8900_54XC_PLATFORM_MODULE_VERSION +export INGRASYS_S8810_32Q_PLATFORM_MODULE_VERSION +export INGRASYS_S9200_64X_PLATFORM_MODULE_VERSION + +INGRASYS_S9100_PLATFORM_MODULE = sonic-platform-ingrasys-s9100_$(INGRASYS_S9100_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S9100_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-ingrasys +$(INGRASYS_S9100_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(INGRASYS_S9100_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9100-r0 +SONIC_DPKG_DEBS += $(INGRASYS_S9100_PLATFORM_MODULE) + +INGRASYS_S8900_64XC_PLATFORM_MODULE = sonic-platform-ingrasys-s8900-64xc_$(INGRASYS_S8900_64XC_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S8900_64XC_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s8900_64xc-r0 + +INGRASYS_S8900_54XC_PLATFORM_MODULE = sonic-platform-ingrasys-s8900-54xc_$(INGRASYS_S8900_54XC_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S8900_54XC_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s8900_54xc-r0 + +INGRASYS_S8810_32Q_PLATFORM_MODULE = sonic-platform-ingrasys-s8810-32q_$(INGRASYS_S8810_32Q_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S8810_32Q_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s8810_32q-r0 + +INGRASYS_S9200_64X_PLATFORM_MODULE = sonic-platform-ingrasys-s9200-64x_$(INGRASYS_S9200_64X_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S9200_64X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9200_64x-r0 + +$(eval $(call add_extra_package,$(INGRASYS_S9100_PLATFORM_MODULE),$(INGRASYS_S8900_64XC_PLATFORM_MODULE))) +$(eval $(call add_extra_package,$(INGRASYS_S9100_PLATFORM_MODULE),$(INGRASYS_S8900_54XC_PLATFORM_MODULE))) +$(eval $(call add_extra_package,$(INGRASYS_S9100_PLATFORM_MODULE),$(INGRASYS_S8810_32Q_PLATFORM_MODULE))) +$(eval $(call add_extra_package,$(INGRASYS_S9100_PLATFORM_MODULE),$(INGRASYS_S9200_64X_PLATFORM_MODULE))) + +SONIC_STRETCH_DEBS += $(INGRASYS_S9100_PLATFORM_MODULE) diff --git a/platform/broadcom/platform-modules-inventec.mk b/platform/broadcom/platform-modules-inventec.mk new file mode 100644 index 000000000000..ead32e75a815 --- /dev/null +++ b/platform/broadcom/platform-modules-inventec.mk @@ -0,0 +1,37 @@ +# Inventec platform modules + +INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION = 1.1.0 +INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION = 1.1.0 +INVENTEC_D6254QS_PLATFORM_MODULE_VERSION = 1.1.0 +INVENTEC_D6556_PLATFORM_MODULE_VERSION = 1.1.0 +INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION = 1.1.0 + +export INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION +export INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION +export INVENTEC_D6254QS_PLATFORM_MODULE_VERSION +export INVENTEC_D6556_PLATFORM_MODULE_VERSION +export INVENTEC_D7264Q28B_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) + +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))) + +INVENTEC_D6254QS_PLATFORM_MODULE = platform-modules-d6254qs_$(INVENTEC_D6254QS_PLATFORM_MODULE_VERSION)_amd64.deb +$(INVENTEC_D6254QS_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d6254qs-r0 +$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D6254QS_PLATFORM_MODULE))) + +INVENTEC_D6556_PLATFORM_MODULE = platform-modules-d6556_$(INVENTEC_D6556_PLATFORM_MODULE_VERSION)_amd64.deb +$(INVENTEC_D6556_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d6556-r0 +$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D6556_PLATFORM_MODULE))) + +INVENTEC_D7264Q28B_PLATFORM_MODULE = platform-modules-d7264q28b_$(INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION)_amd64.deb +$(INVENTEC_D7264Q28B_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d7264q28b-r0 +$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D7264Q28B_PLATFORM_MODULE))) + +SONIC_STRETCH_DEBS += $(INVENTEC_D7032Q28B_PLATFORM_MODULE) \ No newline at end of file diff --git a/platform/broadcom/platform-modules-mitac.mk b/platform/broadcom/platform-modules-mitac.mk new file mode 100644 index 000000000000..6e7e05bf6c57 --- /dev/null +++ b/platform/broadcom/platform-modules-mitac.mk @@ -0,0 +1,13 @@ +# MiTAC Platform modules + +MITAC_LY1200_32X_PLATFORM_MODULE_VERSION = 1.0 + +export MITAC_LY1200_32X_PLATFORM_MODULE_VERSION + +MITAC_LY1200_32X_PLATFORM_MODULE = sonic-platform-mitac-ly1200-32x_$(MITAC_LY1200_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(MITAC_LY1200_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-mitac +$(MITAC_LY1200_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(MITAC_LY1200_32X_PLATFORM_MODULE)_PLATFORM = x86_64-mitac_ly1200_b32h0_c3-r0 +SONIC_DPKG_DEBS += $(MITAC_LY1200_32X_PLATFORM_MODULE) + +SONIC_STRETCH_DEBS += $(MITAC_LY1200_32X_PLATFORM_MODULE) diff --git a/platform/broadcom/platform-modules-quanta.mk b/platform/broadcom/platform-modules-quanta.mk new file mode 100644 index 000000000000..747c41425908 --- /dev/null +++ b/platform/broadcom/platform-modules-quanta.mk @@ -0,0 +1,13 @@ +# Quanta Platform modules + +QUANTA_IX1B_32X_PLATFORM_MODULE_VERSION = 1.0 + +export QUANTA_IX1B_32X_PLATFORM_MODULE_VERSION + +QUANTA_IX1B_32X_PLATFORM_MODULE = sonic-platform-quanta-ix1b-32x_$(QUANTA_IX1B_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(QUANTA_IX1B_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-quanta +$(QUANTA_IX1B_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(QUANTA_IX1B_32X_PLATFORM_MODULE)_PLATFORM = x86_64-quanta_ix1b_rglbmc-r0 +SONIC_DPKG_DEBS += $(QUANTA_IX1B_32X_PLATFORM_MODULE) + +SONIC_STRETCH_DEBS += $(QUANTA_IX1B_32X_PLATFORM_MODULE) diff --git a/platform/broadcom/platform-modules-s6000.mk b/platform/broadcom/platform-modules-s6000.mk new file mode 100644 index 000000000000..00cd2cadf2d3 --- /dev/null +++ b/platform/broadcom/platform-modules-s6000.mk @@ -0,0 +1,13 @@ +# Dell S6000 Platform modules + +DELL_S6000_PLATFORM_MODULE_VERSION = 1.0 + +export DELL_S6000_PLATFORM_MODULE_VERSION + +DELL_S6000_PLATFORM_MODULE = platform-modules-s6000_$(DELL_S6000_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_S6000_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-s6000 +$(DELL_S6000_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(DELL_S6000_PLATFORM_MODULE)_PLATFORM = x86_64-dell_s6000_s1220-r0 +SONIC_DPKG_DEBS += $(DELL_S6000_PLATFORM_MODULE) + +SONIC_STRETCH_DEBS += $(DELL_S6000_PLATFORM_MODULE) diff --git a/platform/broadcom/platform.conf b/platform/broadcom/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/raw-image.mk b/platform/broadcom/raw-image.mk new file mode 100644 index 000000000000..2591d32c1be8 --- /dev/null +++ b/platform/broadcom/raw-image.mk @@ -0,0 +1,9 @@ +# sonic broadcom raw image installer + +SONIC_RAW_IMAGE = sonic-broadcom.raw +$(SONIC_RAW_IMAGE)_MACHINE = broadcom +$(SONIC_RAW_IMAGE)_IMAGE_TYPE = raw +$(SONIC_RAW_IMAGE)_INSTALLS += $(BRCM_OPENNSL_KERNEL) +$(SONIC_RAW_IMAGE)_LAZY_INSTALLS += $($(SONIC_ONE_IMAGE)_LAZY_INSTALLS) +$(SONIC_RAW_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_RAW_IMAGE) diff --git a/platform/broadcom/rules.mk b/platform/broadcom/rules.mk new file mode 100644 index 000000000000..85eb0df51870 --- /dev/null +++ b/platform/broadcom/rules.mk @@ -0,0 +1,39 @@ +include $(PLATFORM_PATH)/sai-modules.mk +include $(PLATFORM_PATH)/sai.mk +include $(PLATFORM_PATH)/platform-modules-s6000.mk +include $(PLATFORM_PATH)/platform-modules-dell.mk +include $(PLATFORM_PATH)/platform-modules-arista.mk +include $(PLATFORM_PATH)/platform-modules-ingrasys.mk +include $(PLATFORM_PATH)/platform-modules-accton.mk +include $(PLATFORM_PATH)/platform-modules-alphanetworks.mk +include $(PLATFORM_PATH)/platform-modules-inventec.mk +include $(PLATFORM_PATH)/platform-modules-cel.mk +include $(PLATFORM_PATH)/platform-modules-delta.mk +include $(PLATFORM_PATH)/platform-modules-quanta.mk +#include $(PLATFORM_PATH)/platform-modules-mitac.mk +include $(PLATFORM_PATH)/docker-orchagent-brcm.mk +include $(PLATFORM_PATH)/docker-syncd-brcm.mk +include $(PLATFORM_PATH)/docker-syncd-brcm-rpc.mk +include $(PLATFORM_PATH)/docker-saiserver-brcm.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/raw-image.mk +include $(PLATFORM_PATH)/one-aboot.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/docker-ptf-brcm.mk + +BCMCMD = bcmcmd +$(BCMCMD)_URL = "https://sonicstorage.blob.core.windows.net/packages/20170518/bcmcmd?sv=2015-04-05&sr=b&sig=OCW4mfmbQ6D0BH8nllpAWrS8XL9uczrw32w3XgL4jws%3D&se=2030-03-31T23%3A06%3A15Z&sp=r" + +DSSERVE = dsserve +$(DSSERVE)_URL = "https://sonicstorage.blob.core.windows.net/packages/20170518/dsserve?sv=2015-04-05&sr=b&sig=gyNbgSL%2FvpMXDdpboVkIJcTKMRdGgEaOR9OukHhEsu8%3D&se=2030-03-31T23%3A06%3A35Z&sp=r" + +SONIC_ONLINE_FILES += $(BCMCMD) $(DSSERVE) + +SONIC_ALL += $(SONIC_ONE_IMAGE) $(SONIC_ONE_ABOOT_IMAGE) \ + $(DOCKER_FPM) + +# Inject brcm sai into sairedis +$(LIBSAIREDIS)_DEPENDS += $(BRCM_SAI) $(BRCM_SAI_DEV) $(LIBSAITHRIFT_DEV) + +# Runtime dependency on brcm sai is set only for syncd +$(SYNCD)_RDEPENDS += $(BRCM_SAI) diff --git a/platform/broadcom/sai-modules.mk b/platform/broadcom/sai-modules.mk new file mode 100644 index 000000000000..f7c449300f8a --- /dev/null +++ b/platform/broadcom/sai-modules.mk @@ -0,0 +1,11 @@ +# Broadcom SAI modules + +KVERSION = 4.9.0-7-amd64 +BRCM_OPENNSL_KERNEL_VERSION = 3.4.1.11-1 + +BRCM_OPENNSL_KERNEL = opennsl-modules-$(KVERSION)_$(BRCM_OPENNSL_KERNEL_VERSION)_amd64.deb +$(BRCM_OPENNSL_KERNEL)_SRC_PATH = $(PLATFORM_PATH)/saibcm-modules +$(BRCM_OPENNSL_KERNEL)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_DPKG_DEBS += $(BRCM_OPENNSL_KERNEL) + +SONIC_STRETCH_DEBS += $(BRCM_OPENNSL_KERNEL) diff --git a/platform/broadcom/sai.mk b/platform/broadcom/sai.mk new file mode 100644 index 000000000000..3ffb9054c7a4 --- /dev/null +++ b/platform/broadcom/sai.mk @@ -0,0 +1,9 @@ +BRCM_SAI = libsaibcm_3.3.3.1-1_amd64.deb +$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.3/libsaibcm_3.3.3.1-1_amd64.deb?sv=2015-04-05&sr=b&sig=Kp6Pjrvt9DD8fThhSjzDJNuVRYuW6aLwi2bgegM0hd8%3D&se=2032-08-09T02%3A22%3A31Z&sp=r" + +BRCM_SAI_DEV = libsaibcm-dev_3.3.3.1-1_amd64.deb +$(eval $(call add_derived_package,$(BRCM_SAI),$(BRCM_SAI_DEV))) +$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.3/libsaibcm-dev_3.3.3.1-1_amd64.deb?sv=2015-04-05&sr=b&sig=fTWUp3gOcNQNT9sS66CSEyP0JkSlPHNRlsvG4L64I0g%3D&se=2032-08-09T02%3A22%3A08Z&sp=r" + +SONIC_ONLINE_DEBS += $(BRCM_SAI) +$(BRCM_SAI_DEV)_DEPENDS += $(BRCM_SAI) diff --git a/platform/broadcom/saibcm-modules/.gitignore b/platform/broadcom/saibcm-modules/.gitignore new file mode 100644 index 000000000000..338005f50ce9 --- /dev/null +++ b/platform/broadcom/saibcm-modules/.gitignore @@ -0,0 +1,4 @@ +*.debhelper.log +*.debhelper +*.substvars +*.ko diff --git a/platform/broadcom/saibcm-modules/debian/changelog b/platform/broadcom/saibcm-modules/debian/changelog new file mode 100644 index 000000000000..5ea7b289ee65 --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/changelog @@ -0,0 +1,48 @@ +opennsl (3.4.1.11-1) unstable; urgency=medium + + * Port Broadcom SAI 3.4.1.11 + * Cherry-pick change from master branch, 3.4.1.11-1 + + -- Ying Xie Fri, 05 Jan 2018 23:21:47 +0000 + +opennsl (3.4.1.10-1) unstable; urgency=medium + + * Upgrade to 3.4.1.10-1 + + -- Ying Xie Tue, 19 Dec 2017 21:33:48 +0000 + +opennsl (3.4.1.9-1) unstable; urgency=medium + + * Upgrade to 3.4.1.9-1 + + -- Ying Xie Thu, 14 Dec 2017 22:04:11 +0000 + +opennsl (3.4.1.7-2) unstable; urgency=medium + + * Add Arista 7260cx3 Rev2 hardware support + + -- Ying Xie Mon, 27 Nov 2017 18:13:50 +0000 + +opennsl (3.4.1.7-1) unstable; urgency=medium + + * Importing opennsl 3.4.1.7 + + -- Ying Xie Mon, 23 Oct 2017 23:47:25 +0000 + +opennsl (3.4.1.5-2) unstable; urgency=medium + + * Importing TD2 changes from opennsl 3.2.2.2 + + -- Ying Xie Tue, 26 Sep 2017 01:28:44 +0000 + +opennsl (3.4.1.5-1) unstable; urgency=medium + + * Importing opennsl 3.4.1.5 + + -- Ying Xie Wed, 20 Sep 2017 16:42:12 +0000 + +opennsl (3.4.1.3-1) unstable; urgency=low + + * Initial release + + -- Guohan Lu Fri, 17 Jul 2015 04:46:01 -0700 diff --git a/platform/broadcom/saibcm-modules/debian/compat b/platform/broadcom/saibcm-modules/debian/compat new file mode 100644 index 000000000000..45a4fb75db86 --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/broadcom/saibcm-modules/debian/control b/platform/broadcom/saibcm-modules/debian/control new file mode 100644 index 000000000000..b3884f80f2e0 --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/control @@ -0,0 +1,14 @@ +Source: opennsl +Section: main +Priority: extra +Maintainer: Guohan Lu +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 +#Vcs-Git: git://git.debian.org/collab-maint/bcmsdk.git +#Vcs-Browser: http://git.debian.org/?p=collab-maint/bcmsdk.git;a=summary + +Package: opennsl-modules-4.9.0-7-amd64 +Architecture: amd64 +Section: main +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for broadcom SAI diff --git a/platform/broadcom/saibcm-modules/debian/opennsl-modules-4.9.0-7-amd64.dirs b/platform/broadcom/saibcm-modules/debian/opennsl-modules-4.9.0-7-amd64.dirs new file mode 100644 index 000000000000..e614841819bc --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/opennsl-modules-4.9.0-7-amd64.dirs @@ -0,0 +1 @@ +lib/modules/4.9.0-7-amd64/extra diff --git a/platform/broadcom/saibcm-modules/debian/opennsl-modules-4.9.0-7-amd64.init b/platform/broadcom/saibcm-modules/debian/opennsl-modules-4.9.0-7-amd64.init new file mode 100755 index 000000000000..30123b1d98bd --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/opennsl-modules-4.9.0-7-amd64.init @@ -0,0 +1,73 @@ +#!/bin/bash +# This script load/unload opennsl kernel modules + +### BEGIN INIT INFO +# Provides: load-opennsl-modules +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Load OpenNSL kernel modules +### END INIT INFO + +function create_devices() +{ + rm -f /dev/linux-knet-cb + rm -f /dev/linux-bcm-knet + rm -f /dev/linux-bcm-bde + rm -f /dev/linux-kernel-bde + + mknod /dev/linux-knet-cb c 121 0 + mknod /dev/linux-bcm-knet c 122 0 + mknod /dev/linux-bcm-bde c 126 0 + mknod /dev/linux-kernel-bde c 127 0 +} + +function load_kernel_modules() +{ + modprobe linux-kernel-bde dmasize=32M maxpayload=128 + modprobe linux-user-bde + modprobe linux-bcm-knet use_rx_skb=1 rx_buffer_size=9238 + modprobe linux-knet-cb +} + +function remove_kernel_modules() +{ + rmmod linux-knet-cb + rmmod linux-bcm-knet + rmmod linux-user-bde + rmmod linux-kernel-bde +} + +case "$1" in +start) + echo -n "Load OpenNSL kernel modules... " + + create_devices + load_kernel_modules + + echo "done." + ;; + +stop) + echo -n "Unload OpenNSL kernel modules... " + + remove_kernel_modules + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/opennsl-modules-4.9.0-7-amd64.init {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/broadcom/saibcm-modules/debian/opennsl-modules-4.9.0-7-amd64.install b/platform/broadcom/saibcm-modules/debian/opennsl-modules-4.9.0-7-amd64.install new file mode 100644 index 000000000000..8eb7db15ba20 --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/opennsl-modules-4.9.0-7-amd64.install @@ -0,0 +1,5 @@ +systems/linux/user/x86-smp_generic_64-2_6/linux-bcm-knet.ko lib/modules/4.9.0-7-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/linux-kernel-bde.ko lib/modules/4.9.0-7-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/linux-user-bde.ko lib/modules/4.9.0-7-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/linux-knet-cb.ko lib/modules/4.9.0-7-amd64/extra +systemd/opennsl-modules-4.9.0-7-amd64.service lib/systemd/system diff --git a/platform/broadcom/saibcm-modules/debian/rules b/platform/broadcom/saibcm-modules/debian/rules new file mode 100755 index 000000000000..59862bf1e556 --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/rules @@ -0,0 +1,183 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. +# +# This version is for a hypothetical package that can build a kernel modules +# architecture-dependant package via make-kpkg, as well as an +# architecture-independent module source package, and other packages +# either dep/indep for things like common files or userspace components +# needed for the kernel modules. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + + + +# some default definitions, important! +# +# Name of the source package +psource:=opennsl-source + +# The short upstream name, used for the module source directory +sname:=opennsl + +### KERNEL SETUP +### Setup the stuff needed for making kernel module packages +### taken from /usr/share/kernel-package/sample.module.rules + +# prefix of the target package name +PACKAGE=opennsl-modules +# modifieable for experiments or debugging m-a +MA_DIR ?= /usr/share/modass +# load generic variable handling +-include $(MA_DIR)/include/generic.make +# load default rules, including kdist, kdist_image, ... +-include $(MA_DIR)/include/common-rules.make + + + +# module assistant calculates all needed things for us and sets +# following variables: +# KSRC (kernel source directory), KVERS (kernel version string), KDREV +# (revision of the Debian kernel-image package), CC (the correct +# compiler), VERSION (the final package version string), PKGNAME (full +# package name with KVERS included), DEB_DESTDIR (path to store DEBs) + +# The kdist_config target is called by make-kpkg modules_config and +# by kdist* rules by dependency. It should configure the module so it is +# ready for compilation (mostly useful for calling configure). +# prep-deb-files from module-assistant creates the neccessary debian/ files +kdist_config: prep-deb-files + +# the kdist_clean target is called by make-kpkg modules_clean and from +# kdist* rules. It is responsible for cleaning up any changes that have +# been made by the other kdist_commands (except for the .deb files created) +kdist_clean: clean + dh_testdir + dh_clean + SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 KERNDIR=/usr/src/linux-headers-4.9.0-7-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-7-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean +# rm -f driver/*.o driver/*.ko +# +### end KERNEL SETUP + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + + touch configure-stamp + + +build-arch: configure-stamp build-arch-stamp +build-arch-stamp: + dh_testdir + + # Add here command to compile/build the package. + SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 KERNDIR=/usr/src/linux-headers-4.9.0-7-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-7-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 + + touch $@ + +#k = $(shell echo $(KVERS) | grep -q ^2.6 && echo k) + +build-indep: configure-stamp build-indep-stamp +build-indep-stamp: + dh_testdir + + # Add here command to compile/build the arch indep package. + # It's ok not to do anything here, if you don't need to build + # anything for this package. + #docbook-to-man debian/opennsl.sgml > opennsl.1 + + touch $@ + +build: build-arch + +clean: + dh_testdir + #dh_testroot + rm -f build-arch-stamp build-indep-stamp configure-stamp + + # Add here commands to clean up after the build process. + SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 KERNDIR=/usr/src/linux-headers-4.9.0-7-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-7-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean + + dh_clean + +install: DH_OPTIONS= +install: build + dh_testdir + dh_testroot + dh_prep + dh_installdirs + dh_install + +# Build architecture-independent files here. +# Pass -i to all debhelper commands in this target to reduce clutter. +binary-indep: build install + dh_testdir -i + dh_testroot -i + dh_installchangelogs -i + dh_installdocs -i + dh_installexamples -i +# dh_install -i +# dh_installmenu -i +# dh_installdebconf -i +# dh_installlogrotate -i +# dh_installemacsen -i +# dh_installpam -i +# dh_installmime -i +# dh_installinit -i +# dh_installcron -i +# dh_installinfo -i + dh_installman -i + dh_link -i + dh_compress -i + dh_fixperms -i + dh_installdeb -i +# dh_perl -i +# dh_makeshlibs -i + dh_installdeb -i + dh_shlibdeps -i + dh_gencontrol -i + dh_md5sums -i + dh_builddeb -i + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir -s + dh_testroot -s +# dh_installdebconf -s + + dh_installdocs -s + dh_installexamples -s + dh_installmenu -s +# dh_installlogrotate -s +# dh_installemacsen -s +# dh_installpam -s +# dh_installmime -s + dh_installmodules -s + dh_systemd_enable -s + dh_installinit -s + dh_systemd_start -s + dh_installcron -s +# dh_installman -s + dh_installinfo -s + dh_installchangelogs -s + dh_strip -s + dh_link -s + dh_compress -s + dh_fixperms -s + dh_makeshlibs -s + dh_installdeb -s +# dh_perl -s + dh_shlibdeps -s + dh_gencontrol -s + dh_md5sums -s + dh_builddeb -s + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure binary-modules kdist kdist_configure kdist_image kdist_clean diff --git a/platform/broadcom/saibcm-modules/include/ibde.h b/platform/broadcom/saibcm-modules/include/ibde.h new file mode 100644 index 000000000000..bfc05e330e03 --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/ibde.h @@ -0,0 +1,158 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: ibde.h,v 1.27 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef __IBDE_H__ +#define __IBDE_H__ + +#include + +/* + * Represents a collection of devices + */ + +typedef struct ibde_dev_s { + uint16 device; + uint8 rev; + sal_vaddr_t base_address; + sal_vaddr_t base_address1; + sal_vaddr_t base_address2; +} ibde_dev_t; + + +typedef struct ibde_s { + + const char *(*name)(void); + + /* Returns the number of devices available */ + /* Each device is is accessed through a handle */ + /* Handles are assumed to index the array of devices */ + + /* Support SWITCH or ETHERNET or CPU devices */ + int (*num_devices)(int type); +#define BDE_ALL_DEVICES 0 +#define BDE_SWITCH_DEVICES 1 +#define BDE_ETHER_DEVICES 2 +#define BDE_CPU_DEVICES 3 + + const ibde_dev_t *(*get_dev)(int d); + + /* + * Get types of underlaying devices. + * A combination of bus type and functional type is returned. + * In case of bus type, support PCI and SPI device types. + * In case of functional type, specify if underlaying device is + * a switching or ethernet device. + */ + uint32 (*get_dev_type)(int d); +#define BDE_PCI_DEV_TYPE SAL_PCI_DEV_TYPE /* PCI device */ +#define BDE_SPI_DEV_TYPE SAL_SPI_DEV_TYPE /* SPI device */ +#define BDE_EB_DEV_TYPE SAL_EB_DEV_TYPE /* EB device */ +#define BDE_ICS_DEV_TYPE SAL_ICS_DEV_TYPE /* ICS device */ +#define BDE_MII_DEV_TYPE SAL_MII_DEV_TYPE /* MII device */ +#define BDE_I2C_DEV_TYPE SAL_I2C_DEV_TYPE /* I2C device */ +#define BDE_AXI_DEV_TYPE SAL_AXI_DEV_TYPE /* AXI device */ +#define BDE_EMMI_DEV_TYPE SAL_EMMI_DEV_TYPE /* EMMI device */ +#define BDE_DEV_BUS_ALT SAL_DEV_BUS_ALT /* Alternate Access */ +#define BDE_DEV_BUS_MSI SAL_DEV_BUS_MSI /* Message-signaled interrupts */ + +#define BDE_DEV_BUS_TYPE_MASK SAL_DEV_BUS_TYPE_MASK + +#define BDE_SWITCH_DEV_TYPE SAL_SWITCH_DEV_TYPE /* Switch device */ +#define BDE_ETHER_DEV_TYPE SAL_ETHER_DEV_TYPE /* Ethernet device */ +#define BDE_CPU_DEV_TYPE SAL_CPU_DEV_TYPE /* CPU device */ + +#define BDE_BYTE_SWAP 0x01000000 /* SW byte swap */ +#define BDE_NO_IPROC 0x02000000 /* Device uses two BARs, but is not iProc */ + +#define BDE_8MB_REG_SPACE 0x10000000 /* 8MB sized CMIC BAR */ +#define BDE_256K_REG_SPACE 0x20000000 /* Map 256K (v 64K) */ +#define BDE_128K_REG_SPACE 0x40000000 /* Map 128K (v 64K) */ +#define BDE_320K_REG_SPACE 0x80000000 /* Map 256K+64K */ + +/* Bus supports only 16bit reads */ +#define BDE_DEV_BUS_RD_16BIT SAL_DEV_BUS_RD_16BIT + +/* Bus supports only 16bit writes */ +#define BDE_DEV_BUS_WR_16BIT SAL_DEV_BUS_WR_16BIT + +/* Backward compatibility */ +#define BDE_ET_DEV_TYPE BDE_MII_DEV_TYPE + +#define BDE_DEV_MEM_MAPPED(_d) \ + ((_d) & (BDE_PCI_DEV_TYPE | BDE_ICS_DEV_TYPE | BDE_EB_DEV_TYPE |\ + BDE_EMMI_DEV_TYPE | BDE_AXI_DEV_TYPE)) + + /* + * PCI Bus Access + */ + uint32 (*pci_conf_read)(int d, uint32 addr); + int (*pci_conf_write)(int d, uint32 addr, uint32 data); + void (*pci_bus_features)(int d, int *be_pio, int *be_packet, + int *be_other); + + uint32 (*read)(int d, uint32 addr); + int (*write)(int d, uint32 addr, uint32 data); + + uint32* (*salloc)(int d, int size, const char *name); + void (*sfree)(int d, void *ptr); + int (*sflush)(int d, void *addr, int length); + int (*sinval)(int d, void *addr, int length); + + int (*interrupt_connect)(int d, void (*)(void*), void *data); + int (*interrupt_disconnect)(int d); + + sal_paddr_t (*l2p)(int d, void *laddr); + void* (*p2l)(int d, sal_paddr_t paddr); + + /* + * SPI Access via SMP + */ + int (*spi_read)(int d, uint32 addr, uint8 *buf, int len); + int (*spi_write)(int d, uint32 addr, uint8 *buf, int len); + /* Special SPI access addresses */ +#define BDE_DEV_OP_EMMI_INIT SAL_DEV_OP_EMMI_INIT + + /* + * iProc register access + */ + uint32 (*iproc_read)(int d, uint32 addr); + int (*iproc_write)(int d, uint32 addr, uint32 data); + + /* + * Shared memory access + */ + uint32 (*shmem_read)(int dev, uint32 addr, uint8 *buf, uint32 len); + void (*shmem_write)(int dev, uint32 addr, uint8 *buf, uint32 len); + sal_vaddr_t (*shmem_map)(int dev, uint32 addr, uint32 size); + + /* + * cmic + */ + int (*get_cmic_ver)(int d, uint32 *ver); + +} ibde_t; + + +/* System BDE */ +extern ibde_t *bde; + + +#endif /* __IBDE_H__ */ diff --git a/platform/broadcom/saibcm-modules/include/kcom.h b/platform/broadcom/saibcm-modules/include/kcom.h new file mode 100644 index 000000000000..f66e382e4d8f --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/kcom.h @@ -0,0 +1,542 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: kcom.h,v 1.9 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + * + * File: kcom.h + * Purpose: User/Kernel message definitions + */ + +#ifndef _KCOM_H +#define _KCOM_H + +#include + +#define KCOM_CHAN_KNET "KCOM_KNET" + +/* + * Message types + */ +#define KCOM_MSG_TYPE_CMD 1 /* Command */ +#define KCOM_MSG_TYPE_RSP 2 /* Command response */ +#define KCOM_MSG_TYPE_EVT 3 /* Unsolicited event */ + +/* + * Message opcodes + */ +#define KCOM_M_NONE 0 /* Should not be used */ +#define KCOM_M_VERSION 1 /* Protocol version */ +#define KCOM_M_STRING 2 /* For debug messages */ +#define KCOM_M_HW_RESET 3 /* H/W not ready */ +#define KCOM_M_HW_INIT 4 /* H/W initialized */ +#define KCOM_M_ETH_HW_CONFIG 5 /* ETH HW config*/ +#define KCOM_M_DETACH 6 /* Detach kernel module */ +#define KCOM_M_NETIF_CREATE 11 /* Create network interface */ +#define KCOM_M_NETIF_DESTROY 12 /* Destroy network interface */ +#define KCOM_M_NETIF_LIST 13 /* Get list of network interface IDs */ +#define KCOM_M_NETIF_GET 14 /* Get network interface info */ +#define KCOM_M_FILTER_CREATE 21 /* Create Rx filter */ +#define KCOM_M_FILTER_DESTROY 22 /* Destroy Rx filter */ +#define KCOM_M_FILTER_LIST 23 /* Get list of Rx filter IDs */ +#define KCOM_M_FILTER_GET 24 /* Get Rx filter info */ +#define KCOM_M_DMA_INFO 31 /* Tx/Rx DMA info */ +#define KCOM_M_DBGPKT_SET 41 /* Enbale debug packet function */ +#define KCOM_M_DBGPKT_GET 42 /* Get debug packet function info */ +#define KCOM_M_WB_CLEANUP 51 /* Clean up for warmbooting */ + +#define KCOM_VERSION 9 /* Protocol version */ + +/* + * Message status codes + */ +#define KCOM_E_NONE 0 /* No errors */ +#define KCOM_E_PARAM 1 /* Invalid/unsupported parameter */ +#define KCOM_E_RESOURCE 2 /* Out of memory or other resource */ +#define KCOM_E_NOT_FOUND 3 /* Requested object not found */ + +typedef struct kcom_msg_hdr_s { + uint8 type; + uint8 opcode; + uint8 seqno; + uint8 status; + uint8 unit; + uint8 reserved; + uint16 id; +} kcom_msg_hdr_t; + +/* + * Object types + */ + +/* + * System network interface + * + * Network interface types: + * + * KCOM_NETIF_T_VLAN + * Transmits to this interface will go to ingress PIPE of switch + * CPU port using specified VLAN ID. Packet will be switched. + * + * KCOM_NETIF_T_PORT + * Transmits to this interface will go to unmodified to specified + * physical switch port. All switching logic is bypassed. + * + * KCOM_NETIF_T_META + * Transmits to this interface will be done using raw meta data + * as DMA descriptors. Currently used for RCPU mode only. + * + * Network interface flags: + * + * KCOM_NETIF_F_ADD_TAG + * Add VLAN tag to packets sent directly to physical port. + * + * KCOM_NETIF_F_RCPU_ENCAP + * Use RCPU encapsulation for packets that enter and exit this + * interface. + */ +#define KCOM_NETIF_T_VLAN 0 +#define KCOM_NETIF_T_PORT 1 +#define KCOM_NETIF_T_META 2 + +#define KCOM_NETIF_F_ADD_TAG (1U << 0) +#define KCOM_NETIF_F_RCPU_ENCAP (1U << 1) +/* If a netif has this flag, the packet sent to the netif can't be stripped tag or added tag */ +#define KCOM_NETIF_F_KEEP_RX_TAG (1U << 2) + +#define KCOM_NETIF_NAME_MAX 16 + +typedef struct kcom_netif_s { + uint16 id; + uint8 type; + uint8 flags; + uint32 cb_user_data; + uint8 port; + uint8 reserved; + uint16 vlan; + uint16 qnum; + uint8 macaddr[6]; + uint8 ptch[2]; + uint8 itmh[4]; + char name[KCOM_NETIF_NAME_MAX]; +} kcom_netif_t; + +/* + * Packet filters + * + * Filters work like software TCAMs where a mask is applied to the + * source data, and the result is then compared to the filter data. + * + * Filters are checked in priority order with the lowest priority + * values being checked first (i.e. 0 is the highest priority). + * + * Filter types: + * + * KCOM_FILTER_T_RX_PKT + * Filter data and mask are applied to the Rx DMA control block + * as well as to the Rx packet contents. + * + * Destination types: + * + * KCOM_DEST_T_NULL + * Packet is dropped. + * + * KCOM_DEST_T_NETIF + * Packet is sent to network interface with ID . + * + * KCOM_DEST_T_API + * Packet is sent to Rx API through queue . + * + * KCOM_DEST_T_CB + * Packet destination is obtained from kernel call-back function. + * + * Filter flags: + * + * KCOM_FILTER_F_ANY_DATA + * When this flags is set the filter will match any packet on + * the associated unit. + * + * KCOM_FILTER_F_STRIP_TAG + * Strip VLAN tag before packet is sent to destination. + * This flag only applies to KCOM_DEST_T_NETIF. + * + */ +#define KCOM_FILTER_BYTES_MAX 256 +#define KCOM_FILTER_WORDS_MAX BYTES2WORDS(KCOM_FILTER_BYTES_MAX) + +#define KCOM_FILTER_T_RX_PKT 1 + +#define KCOM_DEST_T_NULL 0 +#define KCOM_DEST_T_NETIF 1 +#define KCOM_DEST_T_API 2 +#define KCOM_DEST_T_CB 3 + +#define KCOM_FILTER_F_ANY_DATA (1U << 0) +#define KCOM_FILTER_F_STRIP_TAG (1U << 1) + +#define KCOM_FILTER_DESC_MAX 32 + +typedef struct kcom_filter_s { + uint16 id; + uint8 type; + uint8 priority; + char desc[KCOM_FILTER_DESC_MAX]; + uint32 flags; + uint32 cb_user_data; + uint16 dest_type; + uint16 dest_id; + uint16 dest_proto; + uint16 mirror_type; + uint16 mirror_id; + uint16 mirror_proto; + uint16 oob_data_offset; + uint16 oob_data_size; + uint16 pkt_data_offset; + uint16 pkt_data_size; + union { + uint8 b[KCOM_FILTER_BYTES_MAX]; + uint32 w[KCOM_FILTER_WORDS_MAX]; + } data; + union { + uint8 b[KCOM_FILTER_BYTES_MAX]; + uint32 w[KCOM_FILTER_WORDS_MAX]; + } mask; +} kcom_filter_t; + +/* + * DMA buffer information + * + * Cookie field is reserved use by application (32/64-bit pointer). + * + * For Tx operation the application will submit the start address of + * the Tx DCB chain which is queued for transfer by the kernel module. + * Once DMA is done a DMA event is returned to the application with an + * optional sequence number. + * + * For Rx operation the application will submit the start address of + * the Rx DCB chain which should be use for packet reception by the + * kernel module. Once DMA is done a DMA event is returned to the + * application with an optional sequence number. + * + * Cookie field is reserved use by application (32/64-bit pointer). + * + * Packet info types: + * + * KCOM_DMA_INFO_T_TX_DCB + * Data is physical start address of Tx DCB chain. + * + * KCOM_DMA_INFO_T_RX_DCB + * Data is physical start address of Rx DCB chain. + * + * Packet info flags: + * + * KCOM_DMA_INFO_F_TX_DONE + * This flag is set by the kernel module and means that one or more + * packets have been sent. + * + * KCOM_DMA_INFO_F_RX_DONE + * This flag is set by the kernel module and means that one or more + * Rx buffers contain valid packet data. + */ +#define KCOM_DMA_INFO_T_TX_DCB 1 +#define KCOM_DMA_INFO_T_RX_DCB 2 + +#define KCOM_DMA_INFO_F_TX_DONE (1U << 0) +#define KCOM_DMA_INFO_F_RX_DONE (1U << 1) + +typedef struct kcom_dma_info_s { + uint8 type; + uint8 cnt; + uint16 size; + uint16 chan; + uint16 flags; + union { + uint64 dcb_start; + struct { + uint32 tx; + uint32 rx; + } seqno; + } data; + union { + void *p; + uint8 b[8]; + } cookie; + } kcom_dma_info_t; + +/* Default channel configuration */ +#define KCOM_DMA_TX_CHAN 0 +#define KCOM_DMA_RX_CHAN 1 + + +#define KCOM_ETH_HW_T_RESET 1 +#define KCOM_ETH_HW_T_INIT 2 +#define KCOM_ETH_HW_T_OTHER 3 + +#define KCOM_ETH_HW_C_ALL 0xff + +#define KCOM_ETH_HW_RESET_F_TX (1U << 0) +#define KCOM_ETH_HW_RESET_F_RX (1U << 1) +#define KCOM_ETH_HW_RESET_F_TX_RECLAIM (1U << 2) +#define KCOM_ETH_HW_RESET_F_RX_RECLAIM (1U << 3) + +#define KCOM_ETH_HW_INIT_F_TX (1U << 0) +#define KCOM_ETH_HW_INIT_F_RX (1U << 1) +#define KCOM_ETH_HW_INIT_F_RX_FILL (1U << 2) + +#define KCOM_ETH_HW_OTHER_F_FIFO_LOOPBACK (1U << 0) +#define KCOM_ETH_HW_OTHER_F_INTERRUPT (1U << 1) + +typedef struct kcom_eth_hw_config_s { + uint8 type; + uint8 chan; + uint32 flags; + uint32 value; + } kcom_eth_hw_config_t; + +/* + * Message types + */ + +/* + * Request KCOM interface version of kernel module. + */ +typedef struct kcom_msg_version_s { + kcom_msg_hdr_t hdr; + uint32 version; + uint32 netif_max; + uint32 filter_max; +} kcom_msg_version_t; + +/* + * Send literal string to/from kernel module. + * Mainly for debugging purposes. + */ +#define KCOM_MSG_STRING_MAX 128 + +typedef struct kcom_msg_string_s { + kcom_msg_hdr_t hdr; + uint32 len; + char val[KCOM_MSG_STRING_MAX]; +} kcom_msg_string_t; + +/* + * Indicate that eth hardware is about to be reset. Active + * DMA operations should be aborted and DMA and interrupts + * should be disabled. + */ +/* + * Indicate that eth hardware has been properly initialized + * for DMA operation to commence. + */ +typedef struct kcom_msg_eth_hw_config_s { + kcom_msg_hdr_t hdr; + kcom_eth_hw_config_t config; +} kcom_msg_eth_hw_config_t; + +/* + * Indicate that switch hardware is about to be reset. Active + * DMA operations should be aborted and DMA and interrupts + * should be disabled. + */ +typedef struct kcom_msg_hw_reset_s { + kcom_msg_hdr_t hdr; + uint32 channels; +} kcom_msg_hw_reset_t; + +/* + * Indicate that switch hardware has been properly initialized + * for DMA operation to commence. + */ +typedef struct kcom_msg_hw_init_s { + kcom_msg_hdr_t hdr; + uint8 cmic_type; + uint8 dcb_type; + uint8 dcb_size; + uint8 pkt_hdr_size; + uint32 dma_hi; + uint32 cdma_channels; +} kcom_msg_hw_init_t; + +/* + * Release blocked IOCTL threads and clean up as necessary. + */ +typedef struct kcom_msg_detach_s { + kcom_msg_hdr_t hdr; + uint32 flags; +} kcom_msg_detach_t; + +/* + * Enable/Disable debugging packet function. + */ +typedef struct kcom_msg_dbg_pkt_set_s { + kcom_msg_hdr_t hdr; + int enable; +} kcom_msg_dbg_pkt_set_t; + +/* + * Get debugging packet function info. + */ +typedef struct kcom_msg_dbg_pkt_get_s { + kcom_msg_hdr_t hdr; + int value; +} kcom_msg_dbg_pkt_get_t; + +/* + * Clean up warmboot-related resources. + */ +typedef struct kcom_msg_wb_cleanup_s { + kcom_msg_hdr_t hdr; + uint32 flags; +} kcom_msg_wb_cleanup_t; + +/* + * Create new system network interface. The network interface will + * be associated with the specified switch unit number. + * The interface id and name will be assigned by the kernel module. + */ +typedef struct kcom_msg_netif_create_s { + kcom_msg_hdr_t hdr; + kcom_netif_t netif; +} kcom_msg_netif_create_t; + +/* + * Destroy system network interface. + */ +typedef struct kcom_msg_netif_destroy_s { + kcom_msg_hdr_t hdr; +} kcom_msg_netif_destroy_t; + +/* + * Get list of currently defined system network interfaces. + */ +#ifndef KCOM_NETIF_MAX +#define KCOM_NETIF_MAX 128 +#endif + +typedef struct kcom_msg_netif_list_s { + kcom_msg_hdr_t hdr; + uint32 ifcnt; + uint16 id[KCOM_NETIF_MAX]; +} kcom_msg_netif_list_t; + +/* + * Get detailed network interface information. + */ +typedef struct kcom_msg_netif_get_s { + kcom_msg_hdr_t hdr; + kcom_netif_t netif; +} kcom_msg_netif_get_t; + +/* + * Create new packet filter. + * The filter id will be assigned by the kernel module. + */ +typedef struct kcom_msg_filter_create_s { + kcom_msg_hdr_t hdr; + kcom_filter_t filter; +} kcom_msg_filter_create_t; + +/* + * Destroy packet filter. + */ +typedef struct kcom_msg_filter_destroy_s { + kcom_msg_hdr_t hdr; +} kcom_msg_filter_destroy_t; + +/* + * Get list of currently defined packet filters. + */ +#ifndef KCOM_FILTER_MAX +/* SAI_FIXUP - Increased the filters to 1024 from 128 */ +#define KCOM_FILTER_MAX 1024 +#endif + +typedef struct kcom_msg_filter_list_s { + kcom_msg_hdr_t hdr; + uint32 fcnt; + uint16 id[KCOM_FILTER_MAX]; +} kcom_msg_filter_list_t; + +/* + * Get detailed packet filter information. + */ +typedef struct kcom_msg_filter_get_s { + kcom_msg_hdr_t hdr; + kcom_filter_t filter; +} kcom_msg_filter_get_t; + +/* + * DMA info + */ +typedef struct kcom_msg_dma_info_s { + kcom_msg_hdr_t hdr; + kcom_dma_info_t dma_info; +} kcom_msg_dma_info_t; + +/* + * All messages (e.g. for generic receive) + */ +typedef union kcom_msg_s { + kcom_msg_hdr_t hdr; + kcom_msg_version_t version; + kcom_msg_string_t string; + kcom_msg_hw_reset_t hw_reset; + kcom_msg_hw_init_t hw_init; + kcom_msg_eth_hw_config_t eth_hw_config; + kcom_msg_detach_t detach; + kcom_msg_netif_create_t netif_create; + kcom_msg_netif_destroy_t netif_destroy; + kcom_msg_netif_list_t netif_list; + kcom_msg_netif_get_t netif_get; + kcom_msg_filter_create_t filter_create; + kcom_msg_filter_destroy_t filter_destroy; + kcom_msg_filter_list_t filter_list; + kcom_msg_filter_get_t filter_get; + kcom_msg_dma_info_t dma_info; + kcom_msg_dbg_pkt_set_t dbg_pkt_set; + kcom_msg_dbg_pkt_get_t dbg_pkt_get; + kcom_msg_wb_cleanup_t wb_cleanup; +} kcom_msg_t; + +/* + * KCOM communication channel vectors + * + * open + * Open KCOM channel. + * + * close + * Close KCOM channel. + * + * send + * Send KCOM message. If bufsz is non-zero, a synchronous send will be + * performed (if supported) and the function will return the number of + * bytes in the response. + * + * recv + * Receive KCOM message. This function is used t oreceive unsolicited + * messages from the kernel. If synchronous send is not supported, this + * function is also used to retrieve responses to command messages. + */ + +typedef struct kcom_chan_s { + void *(*open)(char *name); + int (*close)(void *handle); + int (*send)(void *handle, void *msg, unsigned int len, unsigned int bufsz); + int (*recv)(void *handle, void *msg, unsigned int bufsz); +} kcom_chan_t; + +#endif /* _KCOM_H */ diff --git a/platform/broadcom/saibcm-modules/include/sal/core/sync.h b/platform/broadcom/saibcm-modules/include/sal/core/sync.h new file mode 100644 index 000000000000..75dd6ce68312 --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/sal/core/sync.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: sync.h,v 1.1 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef _SAL_SYNC_H +#define _SAL_SYNC_H + +typedef struct sal_sem_s{ + char sal_opaque_type; +} *sal_sem_t; + +#define sal_sem_FOREVER (-1) +#define sal_sem_BINARY 1 +#define sal_sem_COUNTING 0 + +sal_sem_t sal_sem_create(char *desc, int binary, int initial_count); +void sal_sem_destroy(sal_sem_t b); +int sal_sem_take(sal_sem_t b, int usec); +int sal_sem_give(sal_sem_t b); + +#endif /* !_SAL_SYNC_H */ diff --git a/platform/broadcom/saibcm-modules/include/sal/core/thread.h b/platform/broadcom/saibcm-modules/include/sal/core/thread.h new file mode 100644 index 000000000000..b7ecb722489f --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/sal/core/thread.h @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: thread.h,v 1.1 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef _SAL_THREAD_H +#define _SAL_THREAD_H + +#include + +void sal_usleep(uint32 usec); +void sal_udelay(uint32 usec); + +#endif /* !_SAL_THREAD_H */ diff --git a/platform/broadcom/saibcm-modules/include/sal/types.h b/platform/broadcom/saibcm-modules/include/sal/types.h new file mode 100644 index 000000000000..b6b40f762939 --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/sal/types.h @@ -0,0 +1,155 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: types.h,v 1.3 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + * + * File: types.h + * Purpose: SAL type definitions + */ + +#ifndef _SAL_TYPES_H +#define _SAL_TYPES_H + +/* + * Define platform-independent types + */ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef DONT_CARE +#define DONT_CARE 0 +#endif + +#define VOL volatile + +/* + * 64-bit type + */ + +#ifdef LONGS_ARE_64BITS + +#define COMPILER_64BIT +#define COMPILER_UINT64 unsigned long +#define u64_H(v) (((uint32 *) &(v))[u64_MSW]) +#define u64_L(v) (((uint32 *) &(v))[u64_LSW]) + +#else /* !LONGS_ARE_64BITS */ + +#define COMPILER_64BIT +#define COMPILER_UINT64 unsigned long long +#define u64_H(v) (((uint32 *) &(v))[u64_MSW]) +#define u64_L(v) (((uint32 *) &(v))[u64_LSW]) + +#endif /* LONGS_ARE_64BITS */ + +/* + * Define unsigned and signed integers with guaranteed sizes. + * Adjust if your compiler uses different sizes for short or int. + */ + +typedef unsigned char uint8; /* 8-bit quantity */ +typedef unsigned short uint16; /* 16-bit quantity */ +typedef unsigned int uint32; /* 32-bit quantity */ +typedef COMPILER_UINT64 uint64; /* 64-bit quantity */ + +typedef signed char int8; /* 8-bit quantity */ +typedef signed short int16; /* 16-bit quantity */ +typedef signed int int32; /* 32-bit quantity */ + +#define BITS2BYTES(x) (((x) + 7) / 8) +#define BITS2WORDS(x) (((x) + 31) / 32) + +#define BYTES2BITS(x) ((x) * 8) +#define BYTES2WORDS(x) (((x) + 3) / 4) + +#define WORDS2BITS(x) ((x) * 32) +#define WORDS2BYTES(x) ((x) * 4) + +#define COUNTOF(ary) ((int) (sizeof (ary) / sizeof ((ary)[0]))) + +typedef uint32 sal_paddr_t; /* Physical address (PCI address) */ + +#ifdef PTRS_ARE_64BITS +typedef uint64 sal_vaddr_t; /* Virtual address (Host address) */ +#define PTR_TO_INT(x) ((uint32)(((sal_vaddr_t)(x))&0xFFFFFFFF)) +#else +typedef uint32 sal_vaddr_t; /* Virtual address (Host address) */ +#define PTR_TO_INT(x) ((uint32)(x)) +#endif + +#define INT_TO_PTR(x) ((void *)((sal_vaddr_t)(x))) + +#define PTR_TO_UINTPTR(x) ((sal_vaddr_t)(x)) +#define UINTPTR_TO_PTR(x) ((void *)(x)) + +typedef union +{ + uint8 u8; + uint16 u16; + uint32 u32; + uint64 u64; + sal_paddr_t paddr; + sal_vaddr_t vaddr; + void *ptr; +} any_t; + +/* Device bus types */ +#define SAL_PCI_DEV_TYPE 0x00001 /* PCI device */ +#define SAL_SPI_DEV_TYPE 0x00002 /* SPI device */ +#define SAL_EB_DEV_TYPE 0x00004 /* EB device */ +#define SAL_ICS_DEV_TYPE 0x00008 /* ICS device */ +#define SAL_MII_DEV_TYPE 0x00010 /* MII device */ +#define SAL_RCPU_DEV_TYPE 0x00020 /* RCPU device */ +#define SAL_I2C_DEV_TYPE 0x00040 /* I2C device */ +#define SAL_AXI_DEV_TYPE 0x00080 /* AXI device */ +#define SAL_EMMI_DEV_TYPE 0x10000 /* EMMI device */ +#define SAL_DEV_BUS_TYPE_MASK 0xf00ff /* Odd for historical reasons */ + +/* Device types */ +#define SAL_SWITCH_DEV_TYPE 0x00100 /* Switch device */ +#define SAL_ETHER_DEV_TYPE 0x00200 /* Ethernet device */ +#define SAL_CPU_DEV_TYPE 0x00400 /* CPU device */ +#define SAL_DEV_TYPE_MASK 0x00f00 + +/* Access types */ +#define SAL_DEV_BUS_RD_16BIT 0x01000 /* 16 bit reads on bus */ +#define SAL_DEV_BUS_WR_16BIT 0x02000 /* 16 bit writes on bus */ +#define SAL_DEV_BUS_ALT 0x04000 /* Alternate access */ +#define SAL_DEV_BUS_MSI 0x08000 /* Message-signaled interrupts */ +#define SAL_DEV_FLAG_MASK 0x0f000 + +/* BDE reserved mask (cannot be used by SAL) */ +#define SAL_DEV_BDE_MASK 0xff000000 + +/* Backward compatibility */ +#define SAL_ET_DEV_TYPE SAL_MII_DEV_TYPE + +/* Special access addresses */ +#define SAL_DEV_OP_EMMI_INIT 0x0fff1000 + +#endif /* !_SAL_TYPES_H */ diff --git a/platform/broadcom/saibcm-modules/include/sdk_config.h b/platform/broadcom/saibcm-modules/include/sdk_config.h new file mode 100644 index 000000000000..9d781114bdf3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/sdk_config.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: sdk_config.h,v 1.5 Broadcom SDK $ + * $Copyright: (c) 2006 Broadcom Corp. + * All Rights Reserved.$ + * + * + */ + +#ifndef __SDK_CONFIG_H__ +#define __SDK_CONFIG_H__ + +/* + * Include custom overrides + */ +#ifdef SDK_INCLUDE_CUSTOM_CONFIG +#include +#endif + + +/* + * Memory Barrier operation if required. + * Defaults to nothing. + */ +#ifndef SDK_CONFIG_MEMORY_BARRIER +#define SDK_CONFIG_MEMORY_BARRIER +#endif + + + +#endif /* __SDK_CONFIG_H__ */ diff --git a/platform/broadcom/saibcm-modules/include/soc/cmic.h b/platform/broadcom/saibcm-modules/include/soc/cmic.h new file mode 100644 index 000000000000..5bf6130237a2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/soc/cmic.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: cmic.h,v 1.1 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + * + * File: cmic.h + * Purpose: Maps out structures used for CMIC operations and + * exports routines and constants. + */ + +#ifndef _SOC_CMIC_H +#define _SOC_CMIC_H + +/* IRQ Register (RO) */ +#define CMIC_IRQ_STAT 0x00000144 + +/* IRQ Mask Registers (R/W) */ +#define CMIC_IRQ_MASK 0x00000148 +#define CMIC_IRQ_MASK_1 0x0000006C +#define CMIC_IRQ_MASK_2 0x00000070 + +#endif /* !_SOC_CMIC_H */ diff --git a/platform/broadcom/saibcm-modules/include/soc/devids.h b/platform/broadcom/saibcm-modules/include/soc/devids.h new file mode 100644 index 000000000000..c1b350f217a5 --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/soc/devids.h @@ -0,0 +1,1986 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * Copyright: (c) 2018 Broadcom. + * All Rights Reserved. + */ + +#ifndef _SOC_DEVIDS_H +#define _SOC_DEVIDS_H + + +#define BROADCOM_VENDOR_ID 0x14e4 + +#define BCM5690_DEVICE_ID 0x5690 +#define BCM5690_A0_REV_ID 1 +#define BCM5690_A1_REV_ID 2 +#define BCM5690_A2_REV_ID 3 + +#define BCM5691_DEVICE_ID 0x5691 +#define BCM5691_A0_REV_ID 1 +#define BCM5691_A1_REV_ID 2 +#define BCM5691_A2_REV_ID 3 + +#define BCM5692_DEVICE_ID 0x5692 +#define BCM5692_A0_REV_ID 1 +#define BCM5692_A1_REV_ID 2 +#define BCM5692_A2_REV_ID 3 + +#define BCM5693_DEVICE_ID 0x5693 +#define BCM5693_A0_REV_ID 1 +#define BCM5693_A1_REV_ID 2 +#define BCM5693_A2_REV_ID 3 + +#define BCM5695_DEVICE_ID 0x5695 +#define BCM5695_A0_REV_ID 1 +#define BCM5695_A1_REV_ID 2 +#define BCM5695_B0_REV_ID 0x11 + +#define BCM5696_DEVICE_ID 0x5696 +#define BCM5696_A0_REV_ID 1 +#define BCM5696_A1_REV_ID 2 +#define BCM5696_B0_REV_ID 0x11 + +#define BCM5697_DEVICE_ID 0x5697 +#define BCM5697_A0_REV_ID 1 +#define BCM5697_A1_REV_ID 2 +#define BCM5697_B0_REV_ID 0x11 + +#define BCM5698_DEVICE_ID 0x5698 +#define BCM5698_A0_REV_ID 1 +#define BCM5698_A1_REV_ID 2 +#define BCM5698_B0_REV_ID 0x11 + +#define BCM5670_DEVICE_ID 0x5670 +#define BCM5670_A0_REV_ID 1 +#define BCM5670_A1_REV_ID 2 + +#define BCM5671_DEVICE_ID 0x5671 +#define BCM5671_A0_REV_ID 1 +#define BCM5671_A1_REV_ID 2 +#define BCM5671_A2_REV_ID 3 + +#define BCM5675_DEVICE_ID 0x5675 +#define BCM5675_A0_REV_ID 1 +#define BCM5675_A1_REV_ID 2 + +#define BCM5676_DEVICE_ID 0x5676 +#define BCM5676_A0_REV_ID 1 +#define BCM5676_A1_REV_ID 2 + +#define BCM5673_DEVICE_ID 0x5673 +#define BCM5673_A0_REV_ID 1 +#define BCM5673_A1_REV_ID 2 +#define BCM5673_A2_REV_ID 3 + +#define BCM5674_DEVICE_ID 0x5674 +#define BCM5674_A0_REV_ID 1 + +#define BCM56100_DEVICE_ID 0xb100 +#define BCM56100_A0_REV_ID 1 +#define BCM56100_A1_REV_ID 2 +#define BCM56101_DEVICE_ID 0xb101 +#define BCM56101_A0_REV_ID 1 +#define BCM56101_A1_REV_ID 2 +#define BCM56102_DEVICE_ID 0xb102 +#define BCM56102_A0_REV_ID 1 +#define BCM56102_A1_REV_ID 2 +#define BCM56105_DEVICE_ID 0xb105 +#define BCM56105_A0_REV_ID 1 +#define BCM56105_A1_REV_ID 2 +#define BCM56106_DEVICE_ID 0xb106 +#define BCM56106_A0_REV_ID 1 +#define BCM56106_A1_REV_ID 2 +#define BCM56107_DEVICE_ID 0xb107 +#define BCM56107_A0_REV_ID 1 +#define BCM56107_A1_REV_ID 2 + +#define BCM56110_DEVICE_ID 0xb110 +#define BCM56110_A0_REV_ID 1 +#define BCM56111_DEVICE_ID 0xb111 +#define BCM56111_A0_REV_ID 1 +#define BCM56112_DEVICE_ID 0xb112 +#define BCM56112_A0_REV_ID 1 +#define BCM56115_DEVICE_ID 0xb115 +#define BCM56115_A0_REV_ID 1 +#define BCM56116_DEVICE_ID 0xb116 +#define BCM56116_A0_REV_ID 1 +#define BCM56117_DEVICE_ID 0xb117 +#define BCM56117_A0_REV_ID 1 + +#define BCM56300_DEVICE_ID 0xb300 +#define BCM56300_A0_REV_ID 1 +#define BCM56300_A1_REV_ID 2 +#define BCM56300_B0_REV_ID 0x11 +#define BCM56300_B1_REV_ID 0x12 +#define BCM56301_DEVICE_ID 0xb301 +#define BCM56301_A0_REV_ID 1 +#define BCM56301_A1_REV_ID 2 +#define BCM56301_B0_REV_ID 0x11 +#define BCM56301_B1_REV_ID 0x12 +#define BCM56302_DEVICE_ID 0xb302 +#define BCM56302_A0_REV_ID 1 +#define BCM56302_A1_REV_ID 2 +#define BCM56302_B0_REV_ID 0x11 +#define BCM56302_B1_REV_ID 0x12 +#define BCM56303_DEVICE_ID 0xb303 +#define BCM56303_A1_REV_ID 2 +#define BCM56303_A0_REV_ID 1 +#define BCM56303_B0_REV_ID 0x11 +#define BCM56303_B1_REV_ID 0x12 +#define BCM56304_DEVICE_ID 0xb304 +#define BCM56304_A0_REV_ID 1 +#define BCM56304_A1_REV_ID 2 +#define BCM56304_B0_REV_ID 0x11 +#define BCM56304_B1_REV_ID 0x12 +#define BCM56404_DEVICE_ID 0xb404 +#define BCM56404_A0_REV_ID 1 +#define BCM56404_A1_REV_ID 2 +#define BCM56305_DEVICE_ID 0xb305 +#define BCM56305_A0_REV_ID 1 +#define BCM56305_A1_REV_ID 2 +#define BCM56305_B0_REV_ID 0x11 +#define BCM56305_B1_REV_ID 0x12 +#define BCM56306_DEVICE_ID 0xb306 +#define BCM56306_A0_REV_ID 1 +#define BCM56306_A1_REV_ID 2 +#define BCM56306_B0_REV_ID 0x11 +#define BCM56306_B1_REV_ID 0x12 +#define BCM56307_DEVICE_ID 0xb307 +#define BCM56307_A0_REV_ID 1 +#define BCM56307_A1_REV_ID 2 +#define BCM56307_B0_REV_ID 0x11 +#define BCM56307_B1_REV_ID 0x12 +#define BCM56308_DEVICE_ID 0xb308 +#define BCM56308_A0_REV_ID 1 +#define BCM56308_A1_REV_ID 2 +#define BCM56308_B0_REV_ID 0x11 +#define BCM56308_B1_REV_ID 0x12 +#define BCM56309_DEVICE_ID 0xb309 +#define BCM56309_A0_REV_ID 1 +#define BCM56309_A1_REV_ID 2 +#define BCM56309_B0_REV_ID 0x11 +#define BCM56309_B1_REV_ID 0x12 + +#define BCM56310_DEVICE_ID 0xb310 +#define BCM56310_A0_REV_ID 1 +#define BCM56311_DEVICE_ID 0xb311 +#define BCM56311_A0_REV_ID 1 +#define BCM56312_DEVICE_ID 0xb312 +#define BCM56312_A0_REV_ID 1 +#define BCM56313_DEVICE_ID 0xb313 +#define BCM56313_A0_REV_ID 1 +#define BCM56314_DEVICE_ID 0xb314 +#define BCM56314_A0_REV_ID 1 +#define BCM56315_DEVICE_ID 0xb315 +#define BCM56315_A0_REV_ID 1 +#define BCM56316_DEVICE_ID 0xb316 +#define BCM56316_A0_REV_ID 1 +#define BCM56317_DEVICE_ID 0xb317 +#define BCM56317_A0_REV_ID 1 +#define BCM56318_DEVICE_ID 0xb318 +#define BCM56318_A0_REV_ID 1 +#define BCM56319_DEVICE_ID 0xb319 +#define BCM56319_A0_REV_ID 1 + +#ifndef EXCLUDE_BCM56324 +#define BCM56322_DEVICE_ID 0xb322 +#define BCM56322_A0_REV_ID 1 +#define BCM56324_DEVICE_ID 0xb324 +#define BCM56324_A0_REV_ID 1 +#endif + +#define BCM53300_DEVICE_ID 0xb006 +#define BCM53300_A0_REV_ID 0x11 +#define BCM53300_A1_REV_ID 0x12 +#define BCM53301_DEVICE_ID 0xb206 +#define BCM53301_A0_REV_ID 0x11 +#define BCM53301_A1_REV_ID 0x12 +#define BCM53302_DEVICE_ID 0xb008 +#define BCM53302_A0_REV_ID 0x11 +#define BCM53302_A1_REV_ID 0x12 + +#define BCM56500_DEVICE_ID 0xb500 +#define BCM56500_A0_REV_ID 1 +#define BCM56500_A1_REV_ID 2 +#define BCM56500_B0_REV_ID 0x11 +#define BCM56500_B1_REV_ID 0x12 +#define BCM56500_B2_REV_ID 0x13 +#define BCM56501_DEVICE_ID 0xb501 +#define BCM56501_A0_REV_ID 1 +#define BCM56501_A1_REV_ID 2 +#define BCM56501_B0_REV_ID 0x11 +#define BCM56501_B1_REV_ID 0x12 +#define BCM56501_B2_REV_ID 0x13 +#define BCM56502_DEVICE_ID 0xb502 +#define BCM56502_A0_REV_ID 1 +#define BCM56502_A1_REV_ID 2 +#define BCM56502_B0_REV_ID 0x11 +#define BCM56502_B1_REV_ID 0x12 +#define BCM56502_B2_REV_ID 0x13 +#define BCM56503_DEVICE_ID 0xb503 +#define BCM56503_A0_REV_ID 1 +#define BCM56503_A1_REV_ID 2 +#define BCM56503_B0_REV_ID 0x11 +#define BCM56503_B1_REV_ID 0x12 +#define BCM56503_B2_REV_ID 0x13 +#define BCM56504_DEVICE_ID 0xb504 +#define BCM56504_A0_REV_ID 1 +#define BCM56504_A1_REV_ID 2 +#define BCM56504_B0_REV_ID 0x11 +#define BCM56504_B1_REV_ID 0x12 +#define BCM56504_B2_REV_ID 0x13 +#define BCM56505_DEVICE_ID 0xb505 +#define BCM56505_A0_REV_ID 1 +#define BCM56505_A1_REV_ID 2 +#define BCM56505_B0_REV_ID 0x11 +#define BCM56505_B1_REV_ID 0x12 +#define BCM56505_B2_REV_ID 0x13 +#define BCM56506_DEVICE_ID 0xb506 +#define BCM56506_A0_REV_ID 1 +#define BCM56506_A1_REV_ID 2 +#define BCM56506_B0_REV_ID 0x11 +#define BCM56506_B1_REV_ID 0x12 +#define BCM56506_B2_REV_ID 0x13 +#define BCM56507_DEVICE_ID 0xb507 +#define BCM56507_A0_REV_ID 1 +#define BCM56507_A1_REV_ID 2 +#define BCM56507_B0_REV_ID 0x11 +#define BCM56507_B1_REV_ID 0x12 +#define BCM56507_B2_REV_ID 0x13 +#define BCM56508_DEVICE_ID 0xb508 +#define BCM56508_A0_REV_ID 1 +#define BCM56508_A1_REV_ID 2 +#define BCM56508_B0_REV_ID 0x11 +#define BCM56508_B1_REV_ID 0x12 +#define BCM56508_B2_REV_ID 0x13 +#define BCM56509_DEVICE_ID 0xb509 +#define BCM56509_A0_REV_ID 1 +#define BCM56509_A1_REV_ID 2 +#define BCM56509_B0_REV_ID 0x11 +#define BCM56509_B1_REV_ID 0x12 +#define BCM56509_B2_REV_ID 0x13 + +#define BCM56600_DEVICE_ID 0xb600 +#define BCM56600_A0_REV_ID 1 +#define BCM56600_B0_REV_ID 0x11 +#define BCM56600_C0_REV_ID 0x21 +#define BCM56601_DEVICE_ID 0xb601 +#define BCM56601_A0_REV_ID 1 +#define BCM56601_B0_REV_ID 0x11 +#define BCM56601_C0_REV_ID 0x21 +#define BCM56602_DEVICE_ID 0xb602 +#define BCM56602_A0_REV_ID 1 +#define BCM56602_B0_REV_ID 0x11 +#define BCM56602_C0_REV_ID 0x21 +#define BCM56603_DEVICE_ID 0xb603 +#define BCM56603_A0_REV_ID 1 +#define BCM56603_B0_REV_ID 0x11 +#define BCM56603_C0_REV_ID 0x21 +#define BCM56605_DEVICE_ID 0xb605 +#define BCM56605_A0_REV_ID 1 +#define BCM56605_B0_REV_ID 0x11 +#define BCM56605_C0_REV_ID 0x21 +#define BCM56606_DEVICE_ID 0xb606 +#define BCM56606_A0_REV_ID 1 +#define BCM56606_B0_REV_ID 0x11 +#define BCM56606_C0_REV_ID 0x21 +#define BCM56607_DEVICE_ID 0xb607 +#define BCM56607_A0_REV_ID 1 +#define BCM56607_B0_REV_ID 0x11 +#define BCM56607_C0_REV_ID 0x21 +#define BCM56608_DEVICE_ID 0xb608 +#define BCM56608_A0_REV_ID 1 +#define BCM56608_B0_REV_ID 0x11 +#define BCM56608_C0_REV_ID 0x21 + +#define BCM56580_DEVICE_ID 0xb580 +#define BCM56580_A0_REV_ID 1 + +#define BCM56700_DEVICE_ID 0xb700 +#define BCM56700_A0_REV_ID 1 +#define BCM56701_DEVICE_ID 0xb701 +#define BCM56701_A0_REV_ID 1 + +#define BCM56800_DEVICE_ID 0xb800 +#define BCM56800_A0_REV_ID 1 +#define BCM56801_DEVICE_ID 0xb801 +#define BCM56801_A0_REV_ID 1 +#define BCM56802_DEVICE_ID 0xb802 +#define BCM56802_A0_REV_ID 1 +#define BCM56803_DEVICE_ID 0xb803 +#define BCM56803_A0_REV_ID 1 + +#define BCM56224_DEVICE_ID 0xb224 +#define BCM56224_A0_REV_ID 1 +#define BCM56224_B0_REV_ID 0x11 +#define BCM56225_DEVICE_ID 0xb225 +#define BCM56225_A0_REV_ID 1 +#define BCM56225_B0_REV_ID 0x11 +#define BCM56226_DEVICE_ID 0xb226 +#define BCM56226_A0_REV_ID 1 +#define BCM56226_B0_REV_ID 0x11 +#define BCM56227_DEVICE_ID 0xb227 +#define BCM56227_A0_REV_ID 1 +#define BCM56227_B0_REV_ID 0x11 +#define BCM56228_DEVICE_ID 0xb228 +#define BCM56228_A0_REV_ID 1 +#define BCM56228_B0_REV_ID 0x11 +#define BCM56229_DEVICE_ID 0xb229 +#define BCM56229_A0_REV_ID 1 +#define BCM56229_B0_REV_ID 0x11 +#define BCM56024_DEVICE_ID 0xb024 +#define BCM56024_A0_REV_ID 1 +#define BCM56024_B0_REV_ID 0x11 +#define BCM56025_DEVICE_ID 0xb025 +#define BCM56025_A0_REV_ID 1 +#define BCM56025_B0_REV_ID 0x11 +#define BCM53724_DEVICE_ID 0xc724 +#define BCM53724_A0_REV_ID 1 +#define BCM53724_B0_REV_ID 0x11 +#define BCM53726_DEVICE_ID 0xc726 +#define BCM53726_A0_REV_ID 1 +#define BCM53726_B0_REV_ID 0x11 + +#define BCM53312_DEVICE_ID 0xc312 +#define BCM53312_A0_REV_ID 1 +#define BCM53312_B0_REV_ID 0x11 +#define BCM53313_DEVICE_ID 0xc313 +#define BCM53313_A0_REV_ID 1 +#define BCM53313_B0_REV_ID 0x11 +#define BCM53314_DEVICE_ID 0xc314 +#define BCM53314_A0_REV_ID 1 +#define BCM53314_B0_REV_ID 0x11 + +#define BCM53322_DEVICE_ID 0xc322 +#define BCM53322_A0_REV_ID 1 +#define BCM53323_DEVICE_ID 0xc323 +#define BCM53323_A0_REV_ID 1 +#define BCM53324_DEVICE_ID 0xc324 +#define BCM53324_A0_REV_ID 1 + + +#define BCM56218_DEVICE_ID 0xB218 +#define BCM56218_A0_REV_ID 1 +#define BCM56218_A1_REV_ID 2 +#define BCM56218_A2_REV_ID 3 +#define BCM56218X_DEVICE_ID 0xc710 +#define BCM56218X_A0_REV_ID 1 +#define BCM56218X_A1_REV_ID 2 +#define BCM56218X_A2_REV_ID 3 +#define BCM56219_DEVICE_ID 0xB219 +#define BCM56219_A0_REV_ID 1 +#define BCM56219_A1_REV_ID 2 +#define BCM56219_A2_REV_ID 3 +#define BCM56218R_DEVICE_ID 0xB21A +#define BCM56218R_A0_REV_ID 1 +#define BCM56218R_A1_REV_ID 2 +#define BCM56218R_A2_REV_ID 3 +#define BCM56219R_DEVICE_ID 0xB21B +#define BCM56219R_A0_REV_ID 1 +#define BCM56219R_A1_REV_ID 2 +#define BCM56219R_A2_REV_ID 3 +#define BCM56214_DEVICE_ID 0xB214 +#define BCM56214_A0_REV_ID 1 +#define BCM56214_A1_REV_ID 2 +#define BCM56214_A2_REV_ID 3 +#define BCM56215_DEVICE_ID 0xB215 +#define BCM56215_A0_REV_ID 1 +#define BCM56215_A1_REV_ID 2 +#define BCM56215_A2_REV_ID 3 +#define BCM56214R_DEVICE_ID 0xB21C +#define BCM56214R_A0_REV_ID 1 +#define BCM56214R_A1_REV_ID 2 +#define BCM56214R_A2_REV_ID 3 +#define BCM56215R_DEVICE_ID 0xB21D +#define BCM56215R_A0_REV_ID 1 +#define BCM56215R_A1_REV_ID 2 +#define BCM56215R_A2_REV_ID 3 +#define BCM56216_DEVICE_ID 0xB216 +#define BCM56216_A0_REV_ID 1 +#define BCM56216_A1_REV_ID 2 +#define BCM56216_A2_REV_ID 3 +#define BCM56217_DEVICE_ID 0xB217 +#define BCM56217_A0_REV_ID 1 +#define BCM56217_A1_REV_ID 2 +#define BCM56217_A2_REV_ID 3 +#define BCM56212_DEVICE_ID 0xB212 +#define BCM56212_A0_REV_ID 1 +#define BCM56212_A1_REV_ID 2 +#define BCM56212_A2_REV_ID 3 +#define BCM56213_DEVICE_ID 0xB213 +#define BCM56213_A0_REV_ID 1 +#define BCM56213_A1_REV_ID 2 +#define BCM56213_A2_REV_ID 3 +#define BCM53718_DEVICE_ID 0xC71A +#define BCM53718_A0_REV_ID 1 +#define BCM53718_A1_REV_ID 2 +#define BCM53718_A2_REV_ID 3 +#define BCM53714_DEVICE_ID 0xC71B +#define BCM53714_A0_REV_ID 1 +#define BCM53714_A1_REV_ID 2 +#define BCM53714_A2_REV_ID 3 +#define BCM53716_DEVICE_ID 0xC716 +#define BCM53716_A0_REV_ID 1 +#define BCM53716_A1_REV_ID 2 +#define BCM53716_A2_REV_ID 3 +#define BCM56018_DEVICE_ID 0xB018 +#define BCM56018_A0_REV_ID 1 +#define BCM56018_A1_REV_ID 2 +#define BCM56018_A2_REV_ID 3 +#define BCM56014_DEVICE_ID 0xB014 +#define BCM56014_A0_REV_ID 1 +#define BCM56014_A1_REV_ID 2 +#define BCM56014_A2_REV_ID 3 + +#define BCM56510_DEVICE_ID 0xb510 +#define BCM56510_A0_REV_ID 1 +#define BCM56511_DEVICE_ID 0xb511 +#define BCM56511_A0_REV_ID 1 +#define BCM56512_DEVICE_ID 0xb512 +#define BCM56512_A0_REV_ID 1 +#define BCM56513_DEVICE_ID 0xb513 +#define BCM56513_A0_REV_ID 1 +#define BCM56514_DEVICE_ID 0xb514 +#define BCM56514_A0_REV_ID 1 +#define BCM56516_DEVICE_ID 0xb516 +#define BCM56516_A0_REV_ID 1 +#define BCM56517_DEVICE_ID 0xb517 +#define BCM56517_A0_REV_ID 1 +#define BCM56518_DEVICE_ID 0xb518 +#define BCM56518_A0_REV_ID 1 +#define BCM56519_DEVICE_ID 0xb519 +#define BCM56519_A0_REV_ID 1 + +#define BCM56620_DEVICE_ID 0xb620 +#define BCM56620_A0_REV_ID 1 +#define BCM56620_A1_REV_ID 2 +#define BCM56620_B0_REV_ID 0x11 +#define BCM56620_B1_REV_ID 0x12 +#define BCM56620_B2_REV_ID 0x13 +#define BCM56624_DEVICE_ID 0xb624 +#define BCM56624_A0_REV_ID 1 +#define BCM56624_A1_REV_ID 2 +#define BCM56624_B0_REV_ID 0x11 +#define BCM56624_B1_REV_ID 0x12 +#define BCM56624_B2_REV_ID 0x13 +#define BCM56626_DEVICE_ID 0xb626 +#define BCM56626_A0_REV_ID 1 +#define BCM56626_A1_REV_ID 2 +#define BCM56626_B0_REV_ID 0x11 +#define BCM56626_B1_REV_ID 0x12 +#define BCM56626_B2_REV_ID 0x13 +#define BCM56628_DEVICE_ID 0xb628 +#define BCM56628_A0_REV_ID 1 +#define BCM56628_A1_REV_ID 2 +#define BCM56628_B0_REV_ID 0x11 +#define BCM56628_B1_REV_ID 0x12 +#define BCM56628_B2_REV_ID 0x13 +#define BCM56629_DEVICE_ID 0xb629 +#define BCM56629_A0_REV_ID 1 +#define BCM56629_A1_REV_ID 2 +#define BCM56629_B0_REV_ID 0x11 +#define BCM56629_B1_REV_ID 0x12 +#define BCM56629_B2_REV_ID 0x13 + +#define BCM56680_DEVICE_ID 0xb680 +#define BCM56680_A0_REV_ID 1 +#define BCM56680_A1_REV_ID 2 +#define BCM56680_B0_REV_ID 0x11 +#define BCM56680_B1_REV_ID 0x12 +#define BCM56680_B2_REV_ID 0x13 +#define BCM56684_DEVICE_ID 0xb684 +#define BCM56684_A0_REV_ID 1 +#define BCM56684_A1_REV_ID 2 +#define BCM56684_B0_REV_ID 0x11 +#define BCM56684_B1_REV_ID 0x12 +#define BCM56684_B2_REV_ID 0x13 +#define BCM56686_DEVICE_ID 0xb686 +#define BCM56686_B0_REV_ID 0x11 +#define BCM56686_B1_REV_ID 0x12 +#define BCM56686_B2_REV_ID 0x13 + +#define BCM56820_DEVICE_ID 0xb820 +#define BCM56820_A0_REV_ID 1 +#define BCM56820_B0_REV_ID 0x11 +#define BCM56821_DEVICE_ID 0xb821 +#define BCM56821_A0_REV_ID 1 +#define BCM56821_B0_REV_ID 0x11 +#define BCM56822_DEVICE_ID 0xb822 +#define BCM56822_A0_REV_ID 1 +#define BCM56822_B0_REV_ID 0x11 +#define BCM56823_DEVICE_ID 0xb823 +#define BCM56823_A0_REV_ID 1 +#define BCM56823_B0_REV_ID 0x11 +#define BCM56825_DEVICE_ID 0xb825 +#define BCM56825_B0_REV_ID 0x11 + +#define BCM56720_DEVICE_ID 0xb720 +#define BCM56720_A0_REV_ID 1 +#define BCM56720_B0_REV_ID 0x11 +#define BCM56721_DEVICE_ID 0xb721 +#define BCM56721_A0_REV_ID 1 +#define BCM56721_B0_REV_ID 0x11 + +#define BCM56725_DEVICE_ID 0xb725 +#define BCM56725_A0_REV_ID 1 +#define BCM56725_B0_REV_ID 0x11 + +#define BCM56630_DEVICE_ID 0xb630 +#define BCM56630_A0_REV_ID 1 +#define BCM56630_B0_REV_ID 0x11 +#define BCM56634_DEVICE_ID 0xb634 +#define BCM56634_A0_REV_ID 1 +#define BCM56634_B0_REV_ID 0x11 +#define BCM56636_DEVICE_ID 0xb636 +#define BCM56636_A0_REV_ID 1 +#define BCM56636_B0_REV_ID 0x11 +#define BCM56638_DEVICE_ID 0xb638 +#define BCM56638_A0_REV_ID 1 +#define BCM56638_B0_REV_ID 0x11 +#define BCM56639_DEVICE_ID 0xb639 +#define BCM56639_A0_REV_ID 1 +#define BCM56639_B0_REV_ID 0x11 + +#define BCM56685_DEVICE_ID 0xb685 +#define BCM56685_A0_REV_ID 1 +#define BCM56685_B0_REV_ID 0x11 +#define BCM56689_DEVICE_ID 0xb689 +#define BCM56689_A0_REV_ID 1 +#define BCM56689_B0_REV_ID 0x11 + +#define BCM56520_DEVICE_ID 0xb520 +#define BCM56520_A0_REV_ID 1 +#define BCM56520_B0_REV_ID 0x11 +#define BCM56521_DEVICE_ID 0xb521 +#define BCM56521_A0_REV_ID 1 +#define BCM56521_B0_REV_ID 0x11 +#define BCM56522_DEVICE_ID 0xb522 +#define BCM56522_A0_REV_ID 1 +#define BCM56522_B0_REV_ID 0x11 +#define BCM56524_DEVICE_ID 0xb524 +#define BCM56524_A0_REV_ID 1 +#define BCM56524_B0_REV_ID 0x11 +#define BCM56526_DEVICE_ID 0xb526 +#define BCM56526_A0_REV_ID 1 +#define BCM56526_B0_REV_ID 0x11 + +#define BCM56534_DEVICE_ID 0xb534 +#define BCM56534_B0_REV_ID 0x11 +#define BCM56538_DEVICE_ID 0xb538 +#define BCM56538_B0_REV_ID 0x11 + +#define BCM56331_DEVICE_ID 0xb331 +#define BCM56331_A0_REV_ID 1 +#define BCM56331_B0_REV_ID 0x11 +#define BCM56331_B1_REV_ID 0x12 +#define BCM56333_DEVICE_ID 0xb333 +#define BCM56333_A0_REV_ID 1 +#define BCM56333_B0_REV_ID 0x11 +#define BCM56333_B1_REV_ID 0x12 +#define BCM56334_DEVICE_ID 0xb334 +#define BCM56334_A0_REV_ID 1 +#define BCM56334_B0_REV_ID 0x11 +#define BCM56334_B1_REV_ID 0x12 +#define BCM56338_DEVICE_ID 0xb338 +#define BCM56338_A0_REV_ID 1 +#define BCM56338_B0_REV_ID 0x11 +#define BCM56338_B1_REV_ID 0x12 + +#define BCM56320_DEVICE_ID 0xb320 +#define BCM56320_A0_REV_ID 1 +#define BCM56320_B0_REV_ID 0x11 +#define BCM56320_B1_REV_ID 0x12 +#define BCM56321_DEVICE_ID 0xb321 +#define BCM56321_A0_REV_ID 1 +#define BCM56321_B0_REV_ID 0x11 +#define BCM56321_B1_REV_ID 0x12 + + +#define BCM56548H_DEVICE_ID 0xB54A +#define BCM56548H_A0_REV_ID 1 +#define BCM56548_DEVICE_ID 0xb548 +#define BCM56548_A0_REV_ID 1 +#define BCM56547_DEVICE_ID 0xb547 +#define BCM56547_A0_REV_ID 1 + +#define BCM56346_DEVICE_ID 0xb346 +#define BCM56346_A0_REV_ID 1 +#define BCM56345_DEVICE_ID 0xb345 +#define BCM56345_A0_REV_ID 1 +#define BCM56344_DEVICE_ID 0xb344 +#define BCM56344_A0_REV_ID 1 +#define BCM56342_DEVICE_ID 0xb342 +#define BCM56342_A0_REV_ID 1 +#define BCM56340_DEVICE_ID 0xb340 +#define BCM56340_A0_REV_ID 1 + +#define BCM56049_DEVICE_ID 0xb049 +#define BCM56049_A0_REV_ID 1 +#define BCM56048_DEVICE_ID 0xb048 +#define BCM56048_A0_REV_ID 1 +#define BCM56047_DEVICE_ID 0xb047 +#define BCM56047_A0_REV_ID 1 + +#define BCM56042_DEVICE_ID 0xb042 +#define BCM56042_A0_REV_ID 1 +#define BCM56041_DEVICE_ID 0xb041 +#define BCM56041_A0_REV_ID 1 +#define BCM56040_DEVICE_ID 0xb040 +#define BCM56040_A0_REV_ID 1 + +#define BCM56132_DEVICE_ID 0xb132 +#define BCM56132_A0_REV_ID 1 +#define BCM56132_B0_REV_ID 0x11 +#define BCM56132_B1_REV_ID 0x12 +#define BCM56134_DEVICE_ID 0xb134 +#define BCM56134_A0_REV_ID 1 +#define BCM56134_B0_REV_ID 0x11 +#define BCM56134_B1_REV_ID 0x12 + +#define BCM56230_DEVICE_ID 0xb230 +#define BCM56230_B1_REV_ID 0x12 +#define BCM56231_DEVICE_ID 0xb231 +#define BCM56231_B1_REV_ID 0x12 + +#define BCM56140_DEVICE_ID 0xb140 +#define BCM56140_A0_REV_ID 1 +#define BCM56142_DEVICE_ID 0xb142 +#define BCM56142_A0_REV_ID 1 +#define BCM56143_DEVICE_ID 0xb143 +#define BCM56143_A0_REV_ID 1 +#define BCM56144_DEVICE_ID 0xb144 +#define BCM56144_A0_REV_ID 1 +#define BCM56146_DEVICE_ID 0xb146 +#define BCM56146_A0_REV_ID 1 +#define BCM56147_DEVICE_ID 0xb147 +#define BCM56147_A0_REV_ID 1 +#define BCM56149_DEVICE_ID 0xb149 +#define BCM56149_A0_REV_ID 1 + +#define BCM56840_DEVICE_ID 0xb840 +#define BCM56840_A0_REV_ID 1 +#define BCM56840_A1_REV_ID 2 +#define BCM56840_A2_REV_ID 3 +#define BCM56840_A3_REV_ID 4 +#define BCM56840_A4_REV_ID 5 +#define BCM56840_B0_REV_ID 0x11 +#define BCM56840_B1_REV_ID 0x12 +#define BCM56841_DEVICE_ID 0xb841 +#define BCM56841_A0_REV_ID 1 +#define BCM56841_A1_REV_ID 2 +#define BCM56841_A2_REV_ID 3 +#define BCM56841_A3_REV_ID 4 +#define BCM56841_A4_REV_ID 5 +#define BCM56841_B0_REV_ID 0x11 +#define BCM56841_B1_REV_ID 0x12 +#define BCM56843_DEVICE_ID 0xb843 +#define BCM56843_A0_REV_ID 1 +#define BCM56843_A1_REV_ID 2 +#define BCM56843_A2_REV_ID 3 +#define BCM56843_A3_REV_ID 4 +#define BCM56843_A4_REV_ID 5 +#define BCM56843_B0_REV_ID 0x11 +#define BCM56843_B1_REV_ID 0x12 +#define BCM56845_DEVICE_ID 0xb845 +#define BCM56845_A0_REV_ID 1 +#define BCM56845_A1_REV_ID 2 +#define BCM56845_A2_REV_ID 3 +#define BCM56845_A3_REV_ID 4 +#define BCM56845_A4_REV_ID 5 +#define BCM56845_B0_REV_ID 0x11 +#define BCM56845_B1_REV_ID 0x12 + +#define BCM56743_DEVICE_ID 0xb743 +#define BCM56743_A0_REV_ID 1 +#define BCM56743_A1_REV_ID 2 +#define BCM56743_A2_REV_ID 3 +#define BCM56743_A3_REV_ID 4 +#define BCM56743_A4_REV_ID 5 +#define BCM56743_B0_REV_ID 0x11 +#define BCM56743_B1_REV_ID 0x12 +#define BCM56745_DEVICE_ID 0xb745 +#define BCM56745_A0_REV_ID 1 +#define BCM56745_A1_REV_ID 2 +#define BCM56745_A2_REV_ID 3 +#define BCM56745_A3_REV_ID 4 +#define BCM56745_A4_REV_ID 5 +#define BCM56745_B0_REV_ID 0x11 +#define BCM56745_B1_REV_ID 0x12 + +#define BCM56260_DEVICE_ID 0xb260 +#define BCM56260_A0_REV_ID 1 +#define BCM56260_B0_REV_ID 0x11 +#define BCM56261_DEVICE_ID 0xb261 +#define BCM56261_A0_REV_ID 1 +#define BCM56261_B0_REV_ID 0x11 +#define BCM56262_DEVICE_ID 0xb262 +#define BCM56262_A0_REV_ID 1 +#define BCM56262_B0_REV_ID 0x11 +#define BCM56263_DEVICE_ID 0xb263 +#define BCM56263_A0_REV_ID 1 +#define BCM56263_B0_REV_ID 0x11 + +#define BCM56265_DEVICE_ID 0xb265 +#define BCM56265_A0_REV_ID 1 +#define BCM56265_B0_REV_ID 0x11 +#define BCM56266_DEVICE_ID 0xb266 +#define BCM56266_A0_REV_ID 1 +#define BCM56266_B0_REV_ID 0x11 +#define BCM56267_DEVICE_ID 0xb267 +#define BCM56267_A0_REV_ID 1 +#define BCM56267_B0_REV_ID 0x11 +#define BCM56268_DEVICE_ID 0xb268 +#define BCM56268_A0_REV_ID 1 +#define BCM56268_B0_REV_ID 0x11 + +#define BCM56233_DEVICE_ID 0xb233 +#define BCM56233_B0_REV_ID 0x11 + +#define BCM56460_DEVICE_ID 0xb460 +#define BCM56460_A0_REV_ID 1 +#define BCM56460_B0_REV_ID 0x11 +#define BCM56461_DEVICE_ID 0xb461 +#define BCM56461_A0_REV_ID 1 +#define BCM56461_B0_REV_ID 0x11 +#define BCM56462_DEVICE_ID 0xb462 +#define BCM56462_A0_REV_ID 1 +#define BCM56462_B0_REV_ID 0x11 +#define BCM56463_DEVICE_ID 0xb463 +#define BCM56463_A0_REV_ID 1 +#define BCM56463_B0_REV_ID 0x11 + +#define BCM56465_DEVICE_ID 0xb465 +#define BCM56465_A0_REV_ID 1 +#define BCM56465_B0_REV_ID 0x11 +#define BCM56466_DEVICE_ID 0xb466 +#define BCM56466_A0_REV_ID 1 +#define BCM56466_B0_REV_ID 0x11 +#define BCM56467_DEVICE_ID 0xb467 +#define BCM56467_A0_REV_ID 1 +#define BCM56467_B0_REV_ID 0x11 +#define BCM56468_DEVICE_ID 0xb468 +#define BCM56468_A0_REV_ID 1 +#define BCM56468_B0_REV_ID 0x11 + +#define BCM56270_DEVICE_ID 0xb270 +#define BCM56270_A0_REV_ID 1 +#define BCM56271_DEVICE_ID 0xb271 +#define BCM56271_A0_REV_ID 1 +#define BCM56272_DEVICE_ID 0xb272 +#define BCM56272_A0_REV_ID 1 + +#define BCM53460_DEVICE_ID 0x8460 +#define BCM53460_A0_REV_ID 1 +#define BCM53461_DEVICE_ID 0x8461 +#define BCM53461_A0_REV_ID 1 + +#define BCM56842_DEVICE_ID 0xb842 +#define BCM56842_A0_REV_ID 1 +#define BCM56842_A1_REV_ID 2 +#define BCM56844_DEVICE_ID 0xb844 +#define BCM56844_A0_REV_ID 1 +#define BCM56844_A1_REV_ID 2 +#define BCM56846_DEVICE_ID 0xb846 +#define BCM56846_A0_REV_ID 1 +#define BCM56846_A1_REV_ID 2 +#define BCM56549_DEVICE_ID 0xb549 +#define BCM56549_A0_REV_ID 1 +#define BCM56549_A1_REV_ID 2 +#define BCM56053_DEVICE_ID 0xb053 +#define BCM56053_A0_REV_ID 1 +#define BCM56053_A1_REV_ID 2 +#define BCM56831_DEVICE_ID 0xb831 +#define BCM56831_A0_REV_ID 1 +#define BCM56831_A1_REV_ID 2 +#define BCM56835_DEVICE_ID 0xb835 +#define BCM56835_A0_REV_ID 1 +#define BCM56835_A1_REV_ID 2 +#define BCM56838_DEVICE_ID 0xb838 +#define BCM56838_A0_REV_ID 1 +#define BCM56838_A1_REV_ID 2 +#define BCM56847_DEVICE_ID 0xb847 +#define BCM56847_A0_REV_ID 1 +#define BCM56847_A1_REV_ID 2 +#define BCM56847_A2_REV_ID 3 +#define BCM56847_A3_REV_ID 4 +#define BCM56847_A4_REV_ID 5 +#define BCM56847_B0_REV_ID 0x11 +#define BCM56847_B1_REV_ID 0x12 +#define BCM56849_DEVICE_ID 0xb849 +#define BCM56849_A0_REV_ID 1 +#define BCM56849_A1_REV_ID 2 + +#define BCM56742_DEVICE_ID 0xb742 +#define BCM56742_A0_REV_ID 1 +#define BCM56742_A1_REV_ID 2 +#define BCM56742_A2_REV_ID 3 +#define BCM56744_DEVICE_ID 0xb744 +#define BCM56744_A0_REV_ID 1 +#define BCM56744_A1_REV_ID 2 +#define BCM56746_DEVICE_ID 0xb746 +#define BCM56746_A0_REV_ID 1 +#define BCM56746_A1_REV_ID 2 + +#define BCM88230_DEVICE_ID 0x0230 +#define BCM88230_A0_REV_ID 1 +#define BCM88230_B0_REV_ID 0x11 +#define BCM88230_C0_REV_ID 0x21 +#define BCM88231_DEVICE_ID 0x0231 +#define BCM88231_A0_REV_ID 1 +#define BCM88231_B0_REV_ID 0x11 +#define BCM88231_C0_REV_ID 0x21 +#define BCM88235_DEVICE_ID 0x0235 +#define BCM88235_A0_REV_ID 1 +#define BCM88235_B0_REV_ID 0x11 +#define BCM88235_C0_REV_ID 0x21 +#define BCM88236_DEVICE_ID 0x0236 +#define BCM88236_A0_REV_ID 1 +#define BCM88236_B0_REV_ID 0x11 +#define BCM88236_C0_REV_ID 0x21 +#define BCM88239_DEVICE_ID 0x0239 +#define BCM88239_A0_REV_ID 1 +#define BCM88239_B0_REV_ID 0x11 +#define BCM88239_C0_REV_ID 0x21 +#define BCM56613_DEVICE_ID 0xb613 +#define BCM56613_A0_REV_ID 1 +#define BCM56613_B0_REV_ID 0x11 +#define BCM56613_C0_REV_ID 0x21 + +#define BCM88732_DEVICE_ID 0x0732 +#define BCM88732_A0_REV_ID 1 +#define BCM88732_A1_REV_ID 2 +#define BCM88732_A2_REV_ID 4 +#define BCM88732_B0_REV_ID 0x11 +#define BCM88732_B1_REV_ID 0x12 +#define BCM88732_B2_REV_ID 0x13 + +#define BCM56640_DEVICE_ID 0xb640 +#define BCM56640_A0_REV_ID 1 +#define BCM56640_A1_REV_ID 2 +#define BCM56640_B0_REV_ID 0x11 +#define BCM56643_DEVICE_ID 0xb643 +#define BCM56643_A0_REV_ID 1 +#define BCM56643_A1_REV_ID 2 +#define BCM56643_B0_REV_ID 0x11 +#define BCM56644_DEVICE_ID 0xb644 +#define BCM56644_A0_REV_ID 1 +#define BCM56644_A1_REV_ID 2 +#define BCM56644_B0_REV_ID 0x11 +#define BCM56648_DEVICE_ID 0xb648 +#define BCM56648_A0_REV_ID 1 +#define BCM56648_A1_REV_ID 2 +#define BCM56648_B0_REV_ID 0x11 +#define BCM56649_DEVICE_ID 0xb649 +#define BCM56649_A0_REV_ID 1 +#define BCM56649_A1_REV_ID 2 +#define BCM56649_B0_REV_ID 0x11 + +#define BCM56540_DEVICE_ID 0xb540 +#define BCM56540_A0_REV_ID 1 +#define BCM56540_A1_REV_ID 2 +#define BCM56540_B0_REV_ID 0x11 +#define BCM56541_DEVICE_ID 0xb541 +#define BCM56541_A0_REV_ID 1 +#define BCM56541_A1_REV_ID 2 +#define BCM56541_B0_REV_ID 0x11 +#define BCM56542_DEVICE_ID 0xb542 +#define BCM56542_A0_REV_ID 1 +#define BCM56542_A1_REV_ID 2 +#define BCM56542_B0_REV_ID 0x11 +#define BCM56543_DEVICE_ID 0xb543 +#define BCM56543_A0_REV_ID 1 +#define BCM56543_A1_REV_ID 2 +#define BCM56543_B0_REV_ID 0x11 +#define BCM56544_DEVICE_ID 0xb544 +#define BCM56544_A0_REV_ID 1 +#define BCM56544_A1_REV_ID 2 +#define BCM56544_B0_REV_ID 0x11 + +#define BCM56545_DEVICE_ID 0xb545 +#define BCM56545_A0_REV_ID 1 +#define BCM56545_A1_REV_ID 2 +#define BCM56545_B0_REV_ID 0x11 +#define BCM56546_DEVICE_ID 0xb546 +#define BCM56546_A0_REV_ID 1 +#define BCM56546_A1_REV_ID 2 +#define BCM56546_B0_REV_ID 0x11 + +#define BCM56044_DEVICE_ID 0xb044 +#define BCM56044_B0_REV_ID 0x11 +#define BCM56045_DEVICE_ID 0xb045 +#define BCM56045_A0_REV_ID 1 +#define BCM56045_A1_REV_ID 2 +#define BCM56045_B0_REV_ID 0x11 +#define BCM56046_DEVICE_ID 0xb046 +#define BCM56046_A0_REV_ID 1 +#define BCM56046_A1_REV_ID 2 +#define BCM56046_B0_REV_ID 0x11 + + +#define BCM56440_DEVICE_ID 0xb440 +#define BCM56440_A0_REV_ID 1 +#define BCM56440_B0_REV_ID 0x11 +#define BCM56441_DEVICE_ID 0xb441 +#define BCM56441_A0_REV_ID 1 +#define BCM56441_B0_REV_ID 0x11 +#define BCM56442_DEVICE_ID 0xb442 +#define BCM56442_A0_REV_ID 1 +#define BCM56442_B0_REV_ID 0x11 +#define BCM56443_DEVICE_ID 0xb443 +#define BCM56443_A0_REV_ID 1 +#define BCM56443_B0_REV_ID 0x11 +#define BCM56445_DEVICE_ID 0xb445 +#define BCM56445_A0_REV_ID 1 +#define BCM56445_B0_REV_ID 0x11 +#define BCM56446_DEVICE_ID 0xb446 +#define BCM56446_A0_REV_ID 1 +#define BCM56446_B0_REV_ID 0x11 +#define BCM56447_DEVICE_ID 0xb447 +#define BCM56447_A0_REV_ID 1 +#define BCM56447_B0_REV_ID 0x11 +#define BCM56448_DEVICE_ID 0xb448 +#define BCM56448_A0_REV_ID 1 +#define BCM56448_B0_REV_ID 0x11 +#define BCM56449_DEVICE_ID 0xb449 +#define BCM56449_A0_REV_ID 1 +#define BCM56449_B0_REV_ID 0x11 +#define BCM56240_DEVICE_ID 0xb240 +#define BCM56240_A0_REV_ID 1 +#define BCM56240_B0_REV_ID 0x11 +#define BCM56241_DEVICE_ID 0xb241 +#define BCM56241_A0_REV_ID 1 +#define BCM56241_B0_REV_ID 0x11 +#define BCM56242_DEVICE_ID 0xb242 +#define BCM56242_A0_REV_ID 1 +#define BCM56242_B0_REV_ID 0x11 +#define BCM56243_DEVICE_ID 0xb243 +#define BCM56243_A0_REV_ID 1 +#define BCM56243_B0_REV_ID 0x11 +#define BCM56245_DEVICE_ID 0xb245 +#define BCM56245_A0_REV_ID 1 +#define BCM56245_B0_REV_ID 0x11 +#define BCM56246_DEVICE_ID 0xb246 +#define BCM56246_A0_REV_ID 1 +#define BCM56246_B0_REV_ID 0x11 +#define BCM55440_DEVICE_ID 0xa440 +#define BCM55440_A0_REV_ID 1 +#define BCM55440_B0_REV_ID 0x11 +#define BCM55441_DEVICE_ID 0xa441 +#define BCM55441_A0_REV_ID 1 +#define BCM55441_B0_REV_ID 0x11 + +#define BCM55450_DEVICE_ID 0xa450 +#define BCM55450_A0_REV_ID 1 +#define BCM55450_B0_REV_ID 0x11 +#define BCM55450_B1_REV_ID 0x12 + +#define BCM55455_DEVICE_ID 0xa455 +#define BCM55455_A0_REV_ID 1 +#define BCM55455_B0_REV_ID 0x11 +#define BCM55455_B1_REV_ID 0x12 + +#define BCM56248_DEVICE_ID 0xb248 +#define BCM56248_A0_REV_ID 1 +#define BCM56248_B0_REV_ID 0x11 +#define BCM56248_B1_REV_ID 0x12 + +#define BCM56450_DEVICE_ID 0xb450 +#define BCM56450_A0_REV_ID 1 +#define BCM56450_B0_REV_ID 0x11 +#define BCM56450_B1_REV_ID 0x12 + +#define BCM56452_DEVICE_ID 0xb452 +#define BCM56452_A0_REV_ID 1 +#define BCM56452_B0_REV_ID 0x11 +#define BCM56452_B1_REV_ID 0x12 + +#define BCM56454_DEVICE_ID 0xb454 +#define BCM56454_A0_REV_ID 1 +#define BCM56454_B0_REV_ID 0x11 +#define BCM56454_B1_REV_ID 0x12 + +#define BCM56455_DEVICE_ID 0xb455 +#define BCM56455_A0_REV_ID 1 +#define BCM56455_B0_REV_ID 0x11 +#define BCM56455_B1_REV_ID 0x12 + +#define BCM56456_DEVICE_ID 0xb456 +#define BCM56456_A0_REV_ID 1 +#define BCM56456_B0_REV_ID 0x11 +#define BCM56456_B1_REV_ID 0x12 + +#define BCM56457_DEVICE_ID 0xb457 +#define BCM56457_A0_REV_ID 1 +#define BCM56457_B0_REV_ID 0x11 +#define BCM56457_B1_REV_ID 0x12 + +#define BCM56458_DEVICE_ID 0xb458 +#define BCM56458_A0_REV_ID 1 +#define BCM56458_B0_REV_ID 0x11 +#define BCM56458_B1_REV_ID 0x12 + +#define BCM56850_DEVICE_ID 0xb850 +#define BCM56850_A0_REV_ID 1 +#define BCM56850_A1_REV_ID 2 +#define BCM56850_A2_REV_ID 3 +#define BCM56851_DEVICE_ID 0xb851 +#define BCM56851_A0_REV_ID 1 +#define BCM56851_A1_REV_ID 2 +#define BCM56851_A2_REV_ID 3 +#define BCM56852_DEVICE_ID 0xb852 +#define BCM56852_A0_REV_ID 1 +#define BCM56852_A1_REV_ID 2 +#define BCM56852_A2_REV_ID 3 +#define BCM56853_DEVICE_ID 0xb853 +#define BCM56853_A0_REV_ID 1 +#define BCM56853_A1_REV_ID 2 +#define BCM56853_A2_REV_ID 3 +#define BCM56854_DEVICE_ID 0xb854 +#define BCM56854_A0_REV_ID 1 +#define BCM56854_A1_REV_ID 2 +#define BCM56854_A2_REV_ID 3 +#define BCM56855_DEVICE_ID 0xb855 +#define BCM56855_A0_REV_ID 1 +#define BCM56855_A1_REV_ID 2 +#define BCM56855_A2_REV_ID 3 +#define BCM56834_DEVICE_ID 0xb834 +#define BCM56834_A0_REV_ID 1 +#define BCM56834_A1_REV_ID 2 +#define BCM56834_A2_REV_ID 3 + +#define BCM56860_DEVICE_ID 0xb860 +#define BCM56860_A0_REV_ID 1 +#define BCM56860_A1_REV_ID 2 +#define BCM56861_DEVICE_ID 0xb861 +#define BCM56861_A0_REV_ID 1 +#define BCM56861_A1_REV_ID 2 +#define BCM56862_DEVICE_ID 0xb862 +#define BCM56862_A0_REV_ID 1 +#define BCM56862_A1_REV_ID 2 +#define BCM56864_DEVICE_ID 0xb864 +#define BCM56864_A0_REV_ID 1 +#define BCM56864_A1_REV_ID 2 +#define BCM56865_DEVICE_ID 0xb865 +#define BCM56865_A0_REV_ID 1 +#define BCM56865_A1_REV_ID 2 +#define BCM56866_DEVICE_ID 0xb866 +#define BCM56866_A0_REV_ID 1 +#define BCM56866_A1_REV_ID 2 +#define BCM56867_DEVICE_ID 0xb867 +#define BCM56867_A0_REV_ID 1 +#define BCM56867_A1_REV_ID 2 +#define BCM56868_DEVICE_ID 0xb868 +#define BCM56868_A0_REV_ID 1 +#define BCM56868_A1_REV_ID 2 +#define BCM56832_DEVICE_ID 0xb832 +#define BCM56832_A0_REV_ID 1 +#define BCM56832_A1_REV_ID 2 +#define BCM56833_DEVICE_ID 0xb833 +#define BCM56833_A0_REV_ID 1 +#define BCM56833_A1_REV_ID 2 +#define BCM56836_DEVICE_ID 0xb836 +#define BCM56836_A0_REV_ID 1 +#define BCM56836_A1_REV_ID 2 + + +#define BCM56750_DEVICE_ID 0xb750 +#define BCM56750_A0_REV_ID 1 +#define BCM56750_A1_REV_ID 2 +#define BCM56750_A2_REV_ID 3 + +#define BCM56830_DEVICE_ID 0xb830 +#define BCM56830_A0_REV_ID 1 +#define BCM56830_A1_REV_ID 2 +#define BCM56830_A2_REV_ID 3 + +#define BCM56150_DEVICE_ID 0xb150 +#define BCM56150_A0_REV_ID 1 +#define BCM56151_DEVICE_ID 0xb151 +#define BCM56151_A0_REV_ID 1 +#define BCM56152_DEVICE_ID 0xb152 +#define BCM56152_A0_REV_ID 1 + +#define BCM53342_DEVICE_ID 0x8342 +#define BCM53342_A0_REV_ID 1 +#define BCM53343_DEVICE_ID 0x8343 +#define BCM53343_A0_REV_ID 1 +#define BCM53344_DEVICE_ID 0x8344 +#define BCM53344_A0_REV_ID 1 +#define BCM53346_DEVICE_ID 0x8346 +#define BCM53346_A0_REV_ID 1 +#define BCM53347_DEVICE_ID 0x8347 +#define BCM53347_A0_REV_ID 1 + +#define BCM53333_DEVICE_ID 0x8333 +#define BCM53333_A0_REV_ID 1 +#define BCM53334_DEVICE_ID 0x8334 +#define BCM53334_A0_REV_ID 1 + +#define BCM53393_DEVICE_ID 0x8393 +#define BCM53393_A0_REV_ID 1 +#define BCM53394_DEVICE_ID 0x8394 +#define BCM53394_A0_REV_ID 1 + +#define BCM53400_DEVICE_ID 0x8400 +#define BCM53400_A0_REV_ID 1 +#define BCM56060_DEVICE_ID 0xb060 +#define BCM56060_A0_REV_ID 1 +#define BCM56062_DEVICE_ID 0xb062 +#define BCM56062_A0_REV_ID 1 +#define BCM56063_DEVICE_ID 0xb063 +#define BCM56063_A0_REV_ID 1 +#define BCM56064_DEVICE_ID 0xb064 +#define BCM56064_A0_REV_ID 1 +#define BCM56065_DEVICE_ID 0xb065 +#define BCM56065_A0_REV_ID 1 +#define BCM56066_DEVICE_ID 0xb066 +#define BCM56066_A0_REV_ID 1 +#define BCM53401_DEVICE_ID 0x8401 +#define BCM53411_DEVICE_ID 0x8411 +#define BCM53401_A0_REV_ID 1 +#define BCM53402_DEVICE_ID 0x8402 +#define BCM53412_DEVICE_ID 0x8412 +#define BCM53402_A0_REV_ID 1 +#define BCM53403_DEVICE_ID 0x8403 +#define BCM53413_DEVICE_ID 0x8413 +#define BCM53403_A0_REV_ID 1 +#define BCM53404_DEVICE_ID 0x8404 +#define BCM53414_DEVICE_ID 0x8414 +#define BCM53404_A0_REV_ID 1 +#define BCM53405_DEVICE_ID 0x8405 +#define BCM53415_DEVICE_ID 0x8415 +#define BCM53405_A0_REV_ID 1 +#define BCM53406_DEVICE_ID 0x8406 +#define BCM53416_DEVICE_ID 0x8416 +#define BCM53406_A0_REV_ID 1 +#define BCM53408_DEVICE_ID 0x8408 +#define BCM53418_DEVICE_ID 0x8418 +#define BCM53408_A0_REV_ID 1 +#define BCM53365_DEVICE_ID 0x8365 +#define BCM53365_A0_REV_ID 1 +#define BCM53369_DEVICE_ID 0x8369 +#define BCM53369_A0_REV_ID 1 + +#define BCM53454_DEVICE_ID 0x8454 +#define BCM53455_DEVICE_ID 0x8455 +#define BCM53454_A0_REV_ID 1 +#define BCM53456_DEVICE_ID 0x8456 +#define BCM53457_DEVICE_ID 0x8457 +#define BCM53456_A0_REV_ID 1 + +#define BCM53422_DEVICE_ID 0x8422 +#define BCM53422_A0_REV_ID 1 +#define BCM53424_DEVICE_ID 0x8424 +#define BCM53424_A0_REV_ID 1 +#define BCM53426_DEVICE_ID 0x8426 +#define BCM53426_A0_REV_ID 1 + +#define BCM56960_DEVICE_ID 0xb960 +#define BCM56960_A0_REV_ID 1 +#define BCM56960_B0_REV_ID 0x11 +#define BCM56960_B1_REV_ID 0x12 +#define BCM56961_DEVICE_ID 0xb961 +#define BCM56961_A0_REV_ID 1 +#define BCM56961_B0_REV_ID 0x11 +#define BCM56961_B1_REV_ID 0x12 +#define BCM56962_DEVICE_ID 0xb962 +#define BCM56962_A0_REV_ID 1 +#define BCM56962_B0_REV_ID 0x11 +#define BCM56962_B1_REV_ID 0x12 +#define BCM56963_DEVICE_ID 0xb963 +#define BCM56963_A0_REV_ID 1 +#define BCM56963_B0_REV_ID 0x11 +#define BCM56963_B1_REV_ID 0x12 +#define BCM56930_DEVICE_ID 0xb930 +#define BCM56930_A0_REV_ID 1 +#define BCM56930_B0_REV_ID 0x11 +#define BCM56930_B1_REV_ID 0x12 +#define BCM56930_C0_REV_ID 0x21 +#define BCM56931_DEVICE_ID 0xb931 +#define BCM56931_A0_REV_ID 1 +#define BCM56931_B0_REV_ID 0x11 +#define BCM56931_C0_REV_ID 0x21 +#define BCM56935_DEVICE_ID 0xb935 +#define BCM56935_A0_REV_ID 1 +#define BCM56935_B0_REV_ID 0x11 +#define BCM56935_C0_REV_ID 0x21 +#define BCM56936_DEVICE_ID 0xb936 +#define BCM56936_A0_REV_ID 1 +#define BCM56936_B0_REV_ID 0x11 +#define BCM56936_C0_REV_ID 0x21 +#define BCM56939_DEVICE_ID 0xb939 +#define BCM56939_A0_REV_ID 1 +#define BCM56939_B0_REV_ID 0x11 +#define BCM56939_C0_REV_ID 0x21 + +#define BCM56168_DEVICE_ID 0xb168 +#define BCM56168_A0_REV_ID 1 +#define BCM56168_B0_REV_ID 0x11 +#define BCM56168_B1_REV_ID 0x12 +#define BCM56169_DEVICE_ID 0xb169 +#define BCM56169_A0_REV_ID 1 +#define BCM56169_B0_REV_ID 0x11 +#define BCM56169_B1_REV_ID 0x12 + +#define BCM56980_DEVICE_ID 0xb980 +#define BCM56980_A0_REV_ID 1 + +#define BCM56968_DEVICE_ID 0xb968 +#define BCM56968_A0_REV_ID 1 +#define BCM56968_B0_REV_ID 0x11 +#define BCM56968_B1_REV_ID 0x12 + +#define BCM56160_DEVICE_ID 0xb160 +#define BCM56160_A0_REV_ID 1 +#define BCM56160_B0_REV_ID 0x11 +#define BCM56162_DEVICE_ID 0xb162 +#define BCM56162_A0_REV_ID 1 +#define BCM56162_B0_REV_ID 0x11 + +#define BCM56163_DEVICE_ID 0xb163 +#define BCM56163_A0_REV_ID 1 +#define BCM56163_B0_REV_ID 0x11 +#define BCM56164_DEVICE_ID 0xb164 +#define BCM56164_A0_REV_ID 1 +#define BCM56164_B0_REV_ID 0x11 +#define BCM56166_DEVICE_ID 0xb166 +#define BCM56166_A0_REV_ID 1 +#define BCM56166_B0_REV_ID 0x11 + +#define BCM53440_DEVICE_ID 0x8440 +#define BCM53440_A0_REV_ID 1 +#define BCM53440_B0_REV_ID 0x11 +#define BCM53442_DEVICE_ID 0x8442 +#define BCM53442_A0_REV_ID 1 +#define BCM53442_B0_REV_ID 0x11 +#define BCM53443_DEVICE_ID 0x8443 +#define BCM53443_A0_REV_ID 1 +#define BCM53443_B0_REV_ID 0x11 + +#define BCM53434_DEVICE_ID 0x8434 +#define BCM53434_A0_REV_ID 1 +#define BCM53434_B0_REV_ID 0x11 + +#define BCM56560_DEVICE_ID 0xb560 +#define BCM56560_A0_REV_ID 1 +#define BCM56560_B0_REV_ID 0x11 + +#define BCM56561_DEVICE_ID 0xb561 +#define BCM56561_A0_REV_ID 1 +#define BCM56561_B0_REV_ID 0x11 + +#define BCM56562_DEVICE_ID 0xb562 +#define BCM56562_A0_REV_ID 1 +#define BCM56562_B0_REV_ID 0x11 + +#define BCM56670_DEVICE_ID 0xb670 +#define BCM56670_A0_REV_ID 1 + +#define BCM56671_DEVICE_ID 0xb671 +#define BCM56671_A0_REV_ID 1 + +#define BCM56672_DEVICE_ID 0xb672 +#define BCM56672_A0_REV_ID 1 + +#define BCM56675_DEVICE_ID 0xb675 +#define BCM56675_A0_REV_ID 1 + +#define BCM56565_DEVICE_ID 0xb565 +#define BCM56565_A0_REV_ID 1 +#define BCM56565_B0_REV_ID 0x11 + +#define BCM56566_DEVICE_ID 0xb566 +#define BCM56566_A0_REV_ID 1 +#define BCM56566_B0_REV_ID 0x11 + +#define BCM56567_DEVICE_ID 0xb567 +#define BCM56567_A0_REV_ID 1 +#define BCM56567_B0_REV_ID 0x11 + +#define BCM56568_DEVICE_ID 0xb568 +#define BCM56568_A0_REV_ID 1 +#define BCM56568_B0_REV_ID 0x11 + +#define BCM56760_DEVICE_ID 0xb760 +#define BCM56760_A0_REV_ID 1 +#define BCM56760_B0_REV_ID 0x11 + +#define BCM56761_DEVICE_ID 0xb761 +#define BCM56761_A0_REV_ID 1 +#define BCM56761_B0_REV_ID 0x11 + +#define BCM56762_DEVICE_ID 0xb762 +#define BCM56762_A0_REV_ID 1 +#define BCM56762_B0_REV_ID 0x11 + +#define BCM56764_DEVICE_ID 0xb764 +#define BCM56764_A0_REV_ID 1 +#define BCM56764_B0_REV_ID 0x11 + +#define BCM56765_DEVICE_ID 0xb765 +#define BCM56765_A0_REV_ID 1 +#define BCM56765_B0_REV_ID 0x11 + +#define BCM56766_DEVICE_ID 0xb766 +#define BCM56766_A0_REV_ID 1 +#define BCM56766_B0_REV_ID 0x11 + +#define BCM56768_DEVICE_ID 0xb768 +#define BCM56768_A0_REV_ID 1 +#define BCM56768_B0_REV_ID 0x11 + +#define BCM56068_DEVICE_ID 0xb068 +#define BCM56068_A0_REV_ID 1 +#define BCM56068_B0_REV_ID 0x11 + +#define BCM56069_DEVICE_ID 0xb069 +#define BCM56069_A0_REV_ID 1 +#define BCM56069_B0_REV_ID 0x11 + +#define BCM56170_DEVICE_ID 0xb170 +#define BCM56170_A0_REV_ID 1 +#define BCM56170_B0_REV_ID 0x11 +#define BCM56172_DEVICE_ID 0xb172 +#define BCM56172_A0_REV_ID 1 +#define BCM56172_B0_REV_ID 0x11 +#define BCM56174_DEVICE_ID 0xb174 +#define BCM56174_A0_REV_ID 1 +#define BCM56174_B0_REV_ID 0x11 + +#define BCM53570_DEVICE_ID 0x8570 +#define BCM53570_A0_REV_ID 1 +#define BCM53570_B0_REV_ID 0x11 +#define BCM53575_DEVICE_ID 0x8575 +#define BCM53575_A0_REV_ID 1 +#define BCM53575_B0_REV_ID 0x11 + + +#define BCM56965_DEVICE_ID 0xb965 +#define BCM56965_A0_REV_ID 1 +#define BCM56965_A1_REV_ID 2 +#define BCM56969_DEVICE_ID 0xb969 +#define BCM56969_A0_REV_ID 1 +#define BCM56966_DEVICE_ID 0xb966 +#define BCM56966_A0_REV_ID 1 +#define BCM56967_DEVICE_ID 0xb967 +#define BCM56967_A0_REV_ID 1 + +#define BCM56970_DEVICE_ID 0xb970 +#define BCM56970_A0_REV_ID 1 +#define BCM56970_B0_REV_ID 0x11 +#define BCM56971_DEVICE_ID 0xb971 +#define BCM56971_A0_REV_ID 1 +#define BCM56971_B0_REV_ID 0x11 +#define BCM56972_DEVICE_ID 0xb972 +#define BCM56972_A0_REV_ID 1 +#define BCM56972_B0_REV_ID 0x11 +#define BCM56974_DEVICE_ID 0xb974 +#define BCM56974_A0_REV_ID 1 +#define BCM56974_B0_REV_ID 0x11 +#define BCM56975_DEVICE_ID 0xb975 +#define BCM56975_A0_REV_ID 1 +#define BCM56975_B0_REV_ID 0x11 + +#define BCM56870_DEVICE_ID 0xb870 +#define BCM56870_A0_REV_ID 1 +#define BCM56873_DEVICE_ID 0xb873 +#define BCM56873_A0_REV_ID 1 + +#define BCM53540_DEVICE_ID 0x8540 +#define BCM53540_A0_REV_ID 1 +#define BCM53547_DEVICE_ID 0x8547 +#define BCM53547_A0_REV_ID 1 +#define BCM53548_DEVICE_ID 0x8548 +#define BCM53548_A0_REV_ID 1 +#define BCM53549_DEVICE_ID 0x8549 +#define BCM53549_A0_REV_ID 1 + +#define BCM5665_DEVICE_ID 0x5665 +#define BCM5665_A0_REV_ID 1 +#define BCM5665_B0_REV_ID 0x11 + + +#define BCM5655_DEVICE_ID 0x5655 +#define BCM5655_A0_REV_ID 1 +#define BCM5655_B0_REV_ID 0x11 + + +#define BCM5650_DEVICE_ID 0x5650 +#define BCM5650_A0_REV_ID 1 +#define BCM5650_B0_REV_ID 0x11 +#define BCM5650_C0_REV_ID 0x21 + +#define BROADCOM_PHYID_HIGH 0x0040 + +#define BCM5338_PHYID_LOW 0x62b0 +#define BCM5338_A0_REV_ID 0 +#define BCM5338_A1_REV_ID 1 +#define BCM5338_B0_REV_ID 3 + +#define BCM5324_PHYID_LOW 0xbc20 +#define BCM5324_PHYID_HIGH 0x143 +#define BCM5324_A1_PHYID_HIGH 0x153 +#define BCM5324_DEVICE_ID 0xbc20 +#define BCM5324_A0_REV_ID 0 +#define BCM5324_A1_REV_ID 1 +#define BCM5324_A2_REV_ID 2 + +#define BCM5380_PHYID_LOW 0x6250 +#define BCM5380_A0_REV_ID 0 + +#define BCM5388_PHYID_LOW 0x6288 +#define BCM5388_A0_REV_ID 0 + +#define BCM5396_PHYID_LOW 0xbd70 +#define BCM5396_PHYID_HIGH 0x143 +#define BCM5396_DEVICE_ID 0x96 +#define BCM5396_A0_REV_ID 0 + +#define BCM5389_PHYID_LOW 0xbd70 +#define BCM5389_PHYID_HIGH 0x143 +#define BCM5389_DEVICE_ID 0x89 +#define BCM5389_A0_REV_ID 0 +#define BCM5389_A1_DEVICE_ID 0x86 +#define BCM5389_A1_REV_ID 1 + +#define BCM5398_PHYID_LOW 0xbcd0 +#define BCM5398_PHYID_HIGH 0x0143 +#define BCM5398_DEVICE_ID 0x98 +#define BCM5398_A0_REV_ID 0 + +#define BCM5325_PHYID_LOW 0xbc30 +#define BCM5325_PHYID_HIGH 0x143 +#define BCM5325_DEVICE_ID 0xbc30 +#define BCM5325_A0_REV_ID 0 +#define BCM5325_A1_REV_ID 1 + +#define BCM5348_PHYID_LOW 0xbe40 +#define BCM5348_PHYID_HIGH 0x0143 +#define BCM5348_DEVICE_ID 0x48 +#define BCM5348_A0_REV_ID 0 +#define BCM5348_A1_REV_ID 1 + +#define BCM5397_PHYID_LOW 0xbcd0 +#define BCM5397_PHYID_HIGH 0x0143 +#define BCM5397_DEVICE_ID 0x97 +#define BCM5397_A0_REV_ID 0 + +#define BCM5347_PHYID_LOW 0xbe40 +#define BCM5347_PHYID_HIGH 0x0143 +#define BCM5347_DEVICE_ID 0x47 +#define BCM5347_A0_REV_ID 0 + +#define BCM5395_PHYID_LOW 0xbcf0 +#define BCM5395_PHYID_HIGH 0x0143 +#define BCM5395_DEVICE_ID 0xbcf0 +#define BCM5395_A0_REV_ID 0 + +#define BCM53242_PHYID_LOW 0xbf10 +#define BCM53242_PHYID_HIGH 0x0143 +#define BCM53242_DEVICE_ID 0xbf10 +#define BCM53242_A0_REV_ID 0 +#define BCM53242_B0_REV_ID 4 +#define BCM53242_B1_REV_ID 5 + +#define BCM53262_PHYID_LOW 0xbf20 +#define BCM53262_PHYID_HIGH 0x0143 +#define BCM53262_DEVICE_ID 0xbf20 +#define BCM53262_A0_REV_ID 0 +#define BCM53262_B0_REV_ID 4 +#define BCM53262_B1_REV_ID 5 + +#define BCM53115_PHYID_LOW 0xbf80 +#define BCM53115_PHYID_HIGH 0x0143 +#define BCM53115_DEVICE_ID 0xbf80 +#define BCM53115_A0_REV_ID 0 +#define BCM53115_A1_REV_ID 1 +#define BCM53115_B0_REV_ID 2 +#define BCM53115_B1_REV_ID 3 +#define BCM53115_C0_REV_ID 8 + +#define BCM53118_PHYID_LOW 0xbfe0 +#define BCM53118_PHYID_HIGH 0x0143 +#define BCM53118_DEVICE_ID 0xbfe0 +#define BCM53118_A0_REV_ID 0 + +#define BCM53118_B0_REV_ID 4 +#define BCM53118_B1_REV_ID 5 + +#define BCM53280_PHYID_LOW 0x5e90 +#define BCM53280_PHYID_HIGH 0x0362 +#define BCM53280_DEVICE_ID (0x4 | BCM53280_PHYID_LOW) +#define BCM53280_A0_REV_ID 0 +#define BCM53280_B0_REV_ID 0x4 +#define BCM53280_B1_REV_ID 0x5 +#define BCM53280_B2_REV_ID 0x6 +#define BCM53286_DEVICE_ID (0x4 | BCM53280_PHYID_LOW) +#define BCM53288_DEVICE_ID (0xc | BCM53280_PHYID_LOW) +#define BCM53284_DEVICE_ID (0x7 | BCM53280_PHYID_LOW) +#define BCM53283_DEVICE_ID (0x6 | BCM53280_PHYID_LOW) +#define BCM53282_DEVICE_ID (0x5 | BCM53280_PHYID_LOW) +#define BCM53101_PHYID_LOW 0x5ed0 +#define BCM53101_PHYID_HIGH 0x0362 +#define BCM53101_DEVICE_ID 0x5ed0 +#define BCM53101_A0_REV_ID 0 +#define BCM53101_B0_REV_ID 4 + +#define BCM53125_PHYID_LOW 0x5f20 +#define BCM53125_PHYID_HIGH 0x0362 +#define BCM53125_DEVICE_ID 0x5f20 +#define BCM53125_A0_REV_ID 0 +#define BCM53125_B0_REV_ID 0x4 +#define BCM53125_MODEL_ID 0x53125 + +#define BCM53134_PHYID_LOW 0x5350 +#define BCM53134_PHYID_HIGH 0xAE02 +#define BCM53134_DEVICE_ID 0x5350 +#define BCM53134_A0_REV_ID 0x0 +#define BCM53134_B0_REV_ID 0x1 +#define BCM53134_B1_REV_ID 0x2 +#define BCM53134_A0_MODEL_ID 0x5035 +#define BCM53134_B0_MODEL_ID 0x5075 + +#define BCM53128_PHYID_LOW 0x5e10 +#define BCM53128_PHYID_HIGH 0x0362 +#define BCM53128_DEVICE_ID 0x5e10 +#define BCM53128_A0_REV_ID 0 +#define BCM53128_B0_REV_ID 0x4 +#define BCM53128_MODEL_ID 0x53128 + +#define BCM53600_PHYID_LOW 0x5f40 +#define BCM53600_PHYID_HIGH 0x0362 +#define BCM53600_DEVICE_ID (0x3 | BCM53600_PHYID_LOW) +#define BCM53600_A0_REV_ID 0 +#define BCM53602_DEVICE_ID (0x1 | BCM53600_PHYID_LOW) +#define BCM53603_DEVICE_ID (0x2 | BCM53600_PHYID_LOW) +#define BCM53604_DEVICE_ID (0x3 | BCM53600_PHYID_LOW) +#define BCM53606_DEVICE_ID (0x7 | BCM53600_PHYID_LOW) + +#define BCM89500_PHYID_LOW 0x5d30 +#define BCM89500_PHYID_HIGH 0x0362 +#define BCM89500_DEVICE_ID 0x9500 +#define BCM89501_DEVICE_ID 0x9501 +#define BCM89200_DEVICE_ID 0x9200 +#define BCM89500_A0_REV_ID 0 +#define BCM89500_B0_REV_ID 0x4 +#define BCM89500_MODEL_ID 0x89500 + +#define BCM53010_PHYID_LOW 0x8760 +#define BCM53010_PHYID_HIGH 0x600d +#define BCM53010_DEVICE_ID 0x3010 +#define BCM53011_DEVICE_ID 0x3011 +#define BCM53012_DEVICE_ID 0x3012 +#define BCM53010_A0_REV_ID 0 +#define BCM53010_A2_REV_ID 0x2 +#define BCM53010_MODEL_ID 0x53010 + +#define BCM53018_PHYID_LOW 0x87c0 +#define BCM53018_PHYID_HIGH 0x600d +#define BCM53017_DEVICE_ID 0x3016 +#define BCM53018_DEVICE_ID 0x3018 +#define BCM53019_DEVICE_ID 0x3019 +#define BCM53018_A0_REV_ID 0 +#define BCM53018_MODEL_ID 0x53016 + +#define BCM53020_PHYID_LOW 0x87f0 +#define BCM53020_PHYID_HIGH 0x600d +#define BCM53020_DEVICE_ID 0x8022 +#define BCM53022_DEVICE_ID 0x8022 +#define BCM53023_DEVICE_ID 0x8023 +#define BCM53025_DEVICE_ID 0x8025 +#define BCM58625_DEVICE_ID 0x8625 +#define BCM58622_DEVICE_ID 0x8622 +#define BCM58623_DEVICE_ID 0x8623 +#define BCM58525_DEVICE_ID 0x8525 +#define BCM58522_DEVICE_ID 0x8522 +#define BCM53020_A0_REV_ID 0 +#define BCM53020_MODEL_ID 0x3025 + +#define BCM4713_DEVICE_ID 0x4713 +#define BCM4713_A0_REV_ID 0 +#define BCM4713_A9_REV_ID 9 + +#define BCM53000_GMAC_DEVICE_ID 0x4715 +#define BCM53000_A0_REV_ID 0 + +#define BCM53010_GMAC_DEVICE_ID 0x4715 + +#define BCM53000PCIE_DEVICE_ID 0x5300 + +#define SANDBURST_VENDOR_ID 0x17ba +#define BME3200_DEVICE_ID 0x0280 +#define BME3200_A0_REV_ID 0x0000 +#define BME3200_B0_REV_ID 0x0001 +#define BM9600_DEVICE_ID 0x0480 +#define BM9600_A0_REV_ID 0x0000 +#define BM9600_B0_REV_ID 0x0010 +#define QE2000_DEVICE_ID 0x0300 +#define QE2000_A1_REV_ID 0x0001 +#define QE2000_A2_REV_ID 0x0002 +#define QE2000_A3_REV_ID 0x0003 +#define QE2000_A4_REV_ID 0x0004 +#define BCM88020_DEVICE_ID 0x0380 +#define BCM88020_A0_REV_ID 0x0000 +#define BCM88020_A1_REV_ID 0x0001 +#define BCM88020_A2_REV_ID 0x0002 +#define BCM88025_DEVICE_ID 0x0580 +#define BCM88025_A0_REV_ID 0x0000 +#define BCM88030_DEVICE_ID 0x0038 +#define BCM88030_A0_REV_ID 0x0001 +#define BCM88030_A1_REV_ID 0x0002 +#define BCM88030_B0_REV_ID 0x0011 +#define BCM88030_B1_REV_ID 0x0012 +#define BCM88034_DEVICE_ID 0x0034 +#define BCM88034_A0_REV_ID (BCM88030_A0_REV_ID) +#define BCM88034_A1_REV_ID (BCM88030_A1_REV_ID) +#define BCM88034_B0_REV_ID (BCM88030_B0_REV_ID) +#define BCM88034_B1_REV_ID (BCM88030_B1_REV_ID) +#define BCM88039_DEVICE_ID 0x0039 +#define BCM88039_A0_REV_ID (BCM88030_A0_REV_ID) +#define BCM88039_A1_REV_ID (BCM88030_A1_REV_ID) +#define BCM88039_B0_REV_ID (BCM88030_B0_REV_ID) +#define BCM88039_B1_REV_ID (BCM88030_B1_REV_ID) +#define BCM88130_DEVICE_ID 0x0480 +#define BCM88130_A0_REV_ID 0x0000 +#define BCM88130_A1_REV_ID 0x0001 +#define BCM88130_B0_REV_ID 0x0010 +#define PLX_VENDOR_ID 0x10b5 +#define PLX9656_DEVICE_ID 0x9656 +#define PLX9656_REV_ID 0x0000 +#define PLX9056_DEVICE_ID 0x9056 +#define PLX9056_REV_ID 0x0000 + +#define TK371X_DEVICE_ID 0x8600 +#define TK371X_A0_REV_ID 0x0 + +#define GEDI_DEVICE_ID 0xa100 +#define GEDI_REV_ID 0x0001 +#define ARAD_DEVICE_ID 0x8650 +#define ARAD_A0_REV_ID 0x0000 +#define ARAD_B0_REV_ID 0x0011 +#define ARAD_B1_REV_ID 0x0012 +#define BCM88650_DEVICE_ID ARAD_DEVICE_ID +#define BCM88650_A0_REV_ID ARAD_A0_REV_ID +#define BCM88650_B0_REV_ID ARAD_B0_REV_ID +#define BCM88650_B1_REV_ID ARAD_B1_REV_ID +#define BCM88750_DEVICE_ID 0x8750 +#define BCM88750_A0_REV_ID 0x0000 +#define BCM88750_B0_REV_ID 0x0011 +#define BCM88753_DEVICE_ID 0x8753 +#define BCM88753_A0_REV_ID 0x0000 +#define BCM88753_B0_REV_ID 0x0011 +#define BCM88754_DEVICE_ID 0x8754 +#define BCM88754_A0_REV_ID 0x0000 +#define BCM88754_ORIGINAL_VENDOR_ID 0x16FC +#define BCM88754_ORIGINAL_DEVICE_ID 0x020F +#define BCM88754_A0_ORIGINAL_REV_ID 0x0001 +#define BCM88755_DEVICE_ID 0x8755 +#define BCM88755_B0_REV_ID 0x0011 +#define BCM88770_DEVICE_ID 0x8770 +#define BCM88770_A1_REV_ID 0x0002 +#define BCM88773_DEVICE_ID 0x8773 +#define BCM88773_A1_REV_ID 0x0002 +#define BCM88774_DEVICE_ID 0x8774 +#define BCM88774_A1_REV_ID 0x0002 +#define BCM88775_DEVICE_ID 0x8775 +#define BCM88775_A1_REV_ID 0x0002 +#define BCM88776_DEVICE_ID 0x8776 +#define BCM88776_A1_REV_ID 0x0002 +#define BCM88777_DEVICE_ID 0x8777 +#define BCM88777_A1_REV_ID 0x0002 +#define BCM88950_DEVICE_ID 0x8950 +#define BCM88950_A0_REV_ID 0x0001 +#define BCM88950_A1_REV_ID 0x0002 +#define BCM88953_DEVICE_ID 0x8953 +#define BCM88953_A1_REV_ID 0x0002 +#define BCM88954_DEVICE_ID 0x8954 +#define BCM88954_A1_REV_ID 0x0002 +#define BCM88955_DEVICE_ID 0x8955 +#define BCM88955_A1_REV_ID 0x0002 +#define BCM88956_DEVICE_ID 0x8956 +#define BCM88956_A1_REV_ID 0x0002 +#define DNXC_A0_REV_ID 0x0001 +#define DNXC_A1_REV_ID 0x0002 +#define DNXC_B0_REV_ID 0x0011 +#define BCM88790_DEVICE_ID 0x8790 +#define BCM88790_A0_REV_ID DNXC_A0_REV_ID +#define BCM88791_DEVICE_ID 0x8791 +#define BCM88792_DEVICE_ID 0x8792 +#define BCM88793_DEVICE_ID 0x8793 +#define BCM88794_DEVICE_ID 0x8794 +#define BCM88795_DEVICE_ID 0x8795 +#define BCM88796_DEVICE_ID 0x8796 +#define BCM88797_DEVICE_ID 0x8797 +#define BCM88798_DEVICE_ID 0x8798 +#define BCM88799_DEVICE_ID 0x8799 +#define BCM8879A_DEVICE_ID 0x879A +#define BCM8879B_DEVICE_ID 0x879B +#define BCM8879C_DEVICE_ID 0x879C +#define BCM8879D_DEVICE_ID 0x879D +#define BCM8879E_DEVICE_ID 0x879E +#define BCM8879F_DEVICE_ID 0x879F +#define BCM_DNXF_DEVID_MASK 0xFFF0 +#define ARADPLUS_DEVICE_ID 0x8660 +#define ARADPLUS_A0_REV_ID 0x0001 +#define BCM88660_DEVICE_ID ARADPLUS_DEVICE_ID +#define BCM88660_A0_REV_ID ARADPLUS_A0_REV_ID +#define JERICHO_DEVICE_ID 0x8675 +#define JERICHO_A0_REV_ID 0x0001 +#define JERICHO_B0_REV_ID 0x0011 +#define JERICHO_A1_REV_ID 0x0002 +#define BCM88670_DEVICE_ID 0x8670 +#define BCM88670_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88670_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88671_DEVICE_ID 0x8671 +#define BCM88671_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88671_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88671M_DEVICE_ID 0x867A +#define BCM88671M_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88671M_A1_REV_ID JERICHO_A1_REV_ID + +#define BCM88670_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88671_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88671M_B0_REV_ID JERICHO_B0_REV_ID + +#define BCM88672_DEVICE_ID 0x8672 +#define BCM88672_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88672_A1_REV_ID JERICHO_A1_REV_ID + +#define BCM88672_B0_REV_ID JERICHO_B0_REV_ID + +#define BCM88673_DEVICE_ID 0x8673 +#define BCM88673_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88673_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88674_DEVICE_ID 0x8674 +#define BCM88674_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88674_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88675_DEVICE_ID JERICHO_DEVICE_ID +#define BCM88675_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88675_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88675M_DEVICE_ID 0x867B +#define BCM88675M_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88675M_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88676_DEVICE_ID 0x8676 +#define BCM88676_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88676_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88676M_DEVICE_ID 0x867C +#define BCM88676M_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88676M_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88677_DEVICE_ID 0x8677 +#define BCM88677_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88677_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88678_DEVICE_ID 0x8678 +#define BCM88678_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88678_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88679_DEVICE_ID 0x8679 +#define BCM88679_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88679_A1_REV_ID JERICHO_A1_REV_ID + +#define BCM88673_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88674_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88675_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88675M_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88676_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88676M_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88677_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88678_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88679_B0_REV_ID JERICHO_B0_REV_ID +#define QMX_DEVICE_ID 0x8375 +#define QMX_A0_REV_ID 0x0001 +#define QMX_B0_REV_ID 0x0011 +#define QMX_A1_REV_ID 0x0002 +#define BCM88370_DEVICE_ID 0x8370 +#define BCM88370_A0_REV_ID QMX_A0_REV_ID +#define BCM88370_A1_REV_ID QMX_A1_REV_ID +#define BCM88371_DEVICE_ID 0x8371 +#define BCM88371_A0_REV_ID QMX_A0_REV_ID +#define BCM88371_A1_REV_ID QMX_A1_REV_ID +#define BCM88371M_DEVICE_ID 0x837A +#define BCM88371M_A0_REV_ID QMX_A0_REV_ID +#define BCM88371M_A1_REV_ID QMX_A1_REV_ID +#define BCM88375_DEVICE_ID QMX_DEVICE_ID +#define BCM88375_A0_REV_ID QMX_A0_REV_ID +#define BCM88375_A1_REV_ID QMX_A1_REV_ID +#define BCM88376_DEVICE_ID 0x8376 +#define BCM88376_A0_REV_ID QMX_A0_REV_ID +#define BCM88376_A1_REV_ID QMX_A1_REV_ID +#define BCM88376M_DEVICE_ID 0x837B +#define BCM88376M_A0_REV_ID QMX_A0_REV_ID +#define BCM88376M_A1_REV_ID QMX_A1_REV_ID +#define BCM88377_DEVICE_ID 0x8377 +#define BCM88377_A0_REV_ID QMX_A0_REV_ID +#define BCM88377_A1_REV_ID QMX_A1_REV_ID +#define BCM88378_DEVICE_ID 0x8378 +#define BCM88378_A0_REV_ID QMX_A0_REV_ID +#define BCM88378_A1_REV_ID QMX_A1_REV_ID +#define BCM88379_DEVICE_ID 0x8379 +#define BCM88379_A0_REV_ID QMX_A0_REV_ID +#define BCM88379_A1_REV_ID QMX_A1_REV_ID + +#define BCM88370_B0_REV_ID QMX_B0_REV_ID +#define BCM88371_B0_REV_ID QMX_B0_REV_ID +#define BCM88371M_B0_REV_ID QMX_B0_REV_ID +#define BCM88375_B0_REV_ID QMX_B0_REV_ID +#define BCM88376_B0_REV_ID QMX_B0_REV_ID +#define BCM88376M_B0_REV_ID QMX_B0_REV_ID +#define BCM88377_B0_REV_ID QMX_B0_REV_ID +#define BCM88378_B0_REV_ID QMX_B0_REV_ID +#define BCM88379_B0_REV_ID QMX_B0_REV_ID + + +#define JERICHO_PLUS_DEVICE_ID 0x8680 +#define JERICHO_PLUS_A0_REV_ID 0x0001 +#define BCM88680_DEVICE_ID JERICHO_PLUS_DEVICE_ID +#define BCM88680_A0_REV_ID JERICHO_PLUS_A0_REV_ID +#define BCM88680_A1_REV_ID 0x0002 + + +#define BCM88681_DEVICE_ID 0x8681 +#define BCM88681_A0_REV_ID JERICHO_PLUS_A0_REV_ID + +#define BCM88682_DEVICE_ID 0x8682 +#define BCM88682_A0_REV_ID JERICHO_PLUS_A0_REV_ID + +#define BCM88683_DEVICE_ID 0x8683 +#define BCM88683_A0_REV_ID JERICHO_PLUS_A0_REV_ID + +#define BCM88684_DEVICE_ID 0x8684 +#define BCM88684_A0_REV_ID JERICHO_PLUS_A0_REV_ID + +#define BCM88685_DEVICE_ID 0x8685 +#define BCM88685_A0_REV_ID JERICHO_PLUS_A0_REV_ID + +#define BCM88380_DEVICE_ID 0x8380 +#define BCM88380_A0_REV_ID JERICHO_PLUS_A0_REV_ID +#define BCM88381_DEVICE_ID 0x8381 +#define BCM88381_A0_REV_ID JERICHO_PLUS_A0_REV_ID + +#define JERICHO_2_DEVICE_ID 0x8690 +#define JERICHO_2_A0_REV_ID 0x0001 +#define BCM88690_DEVICE_ID JERICHO_2_DEVICE_ID +#define BCM88690_A0_REV_ID JERICHO_2_A0_REV_ID + +#define QAX_DEVICE_ID 0x8470 +#define QAX_A0_REV_ID 0x0001 +#define QAX_B0_REV_ID 0x0011 +#define BCM88470_DEVICE_ID QAX_DEVICE_ID +#define BCM88470_B0_REV_ID QAX_B0_REV_ID +#define BCM88470P_DEVICE_ID 0x847C +#define BCM88471_DEVICE_ID 0x8471 +#define BCM88473_DEVICE_ID 0x8473 +#define BCM88474_DEVICE_ID 0x8474 +#define BCM88474H_DEVICE_ID 0x847B +#define BCM88476_DEVICE_ID 0x8476 +#define BCM88477_DEVICE_ID 0x8477 + + + + +#define BCM88470_A0_REV_ID QAX_A0_REV_ID + +#define QUX_DEVICE_ID 0x8270 +#define QUX_A0_REV_ID 0x0001 +#define QUX_A1_REV_ID 0x0002 +#define QUX_B0_REV_ID 0x0011 +#define BCM88270_DEVICE_ID QUX_DEVICE_ID +#define BCM88270_A0_REV_ID QUX_A0_REV_ID +#define BCM88270_A1_REV_ID QUX_A1_REV_ID +#define BCM88272_DEVICE_ID 0x8272 +#define BCM88273_DEVICE_ID 0x8273 +#define BCM88278_DEVICE_ID 0x8278 +#define BCM88279_DEVICE_ID 0x8279 + +#define FLAIR_DEVICE_ID 0xF000 +#define FLAIR_A0_REV_ID 0x0001 +#define BCM8206_DEVICE_ID FLAIR_DEVICE_ID +#define BCM8206_A0_REV_ID FLAIR_A0_REV_ID + +#define ARDON_DEVICE_ID 0x8202 +#define ARDON_A0_REV_ID 0x0000 +#define BCM88202_DEVICE_ID ARDON_DEVICE_ID +#define BCM88202_A0_REV_ID ARDON_A0_REV_ID +#define ARDON_A1_REV_ID 0x0001 +#define BCM88202_A1_REV_ID ARDON_A1_REV_ID +#define ARDON_A2_REV_ID 0x0002 +#define BCM88202_A2_REV_ID ARDON_A2_REV_ID +#define BCM2801PM_DEVICE_ID 0x2801 +#define BCM2801PM_A0_REV_ID 0x0000 +#define BCM88360_DEVICE_ID 0x8360 +#define BCM88360_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88361_DEVICE_ID 0x8361 +#define BCM88361_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88363_DEVICE_ID 0x8363 +#define BCM88363_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88460_DEVICE_ID 0x8460 +#define BCM88460_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88461_DEVICE_ID 0x8461 +#define BCM88461_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88560_DEVICE_ID 0x8560 +#define BCM88560_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88561_DEVICE_ID 0x8561 +#define BCM88561_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88562_DEVICE_ID 0x8562 +#define BCM88562_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88661_DEVICE_ID 0x8661 +#define BCM88661_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88664_DEVICE_ID 0x8664 +#define BCM88664_A0_REV_ID ARADPLUS_A0_REV_ID + + +#define BCM88350_DEVICE_ID 0x8350 +#define BCM88350_B1_REV_ID ARAD_B1_REV_ID +#define BCM88351_DEVICE_ID 0x8351 +#define BCM88351_B1_REV_ID ARAD_B1_REV_ID +#define BCM88450_DEVICE_ID 0x8450 +#define BCM88450_B1_REV_ID ARAD_B1_REV_ID +#define BCM88451_DEVICE_ID 0x8451 +#define BCM88451_B1_REV_ID ARAD_B1_REV_ID +#define BCM88550_DEVICE_ID 0x8550 +#define BCM88550_B1_REV_ID ARAD_B0_REV_ID +#define BCM88551_DEVICE_ID 0x8551 +#define BCM88551_B1_REV_ID ARAD_B1_REV_ID +#define BCM88552_DEVICE_ID 0x8552 +#define BCM88552_B1_REV_ID ARAD_B1_REV_ID +#define BCM88651_DEVICE_ID 0x8651 +#define BCM88651_B1_REV_ID ARAD_B1_REV_ID +#define BCM88654_DEVICE_ID 0x8654 +#define BCM88654_B1_REV_ID ARAD_B1_REV_ID + +#define BCM88772_DEVICE_ID 0x8772 +#define BCM88952_DEVICE_ID 0x8952 +#define BCM88772_A1_REV_ID 0x0002 +#define BCM88952_A0_REV_ID 0x0001 +#define BCM88952_A1_REV_ID 0x0002 + +#define BCM88752_DEVICE_ID 0x8752 +#define BCM88752_A0_REV_ID 0x0000 +#define BCM88752_B0_REV_ID 0x0011 + + +#define BCM83207_DEVICE_ID 0x3207 +#define BCM83208_DEVICE_ID 0x3208 +#define BCM83207_A0_REV_ID 0x0001 +#define BCM83208_A0_REV_ID 1 + +#define PCP_PCI_VENDOR_ID 0x1172 +#define PCP_PCI_DEVICE_ID 0x4 + +#define ACP_PCI_VENDOR_ID 0x10ee +#define ACP_PCI_DEVICE_ID 0x7011 +#define ACP_PCI_REV_ID 0x0001 +#endif + diff --git a/platform/broadcom/saibcm-modules/make/Make.config b/platform/broadcom/saibcm-modules/make/Make.config new file mode 100644 index 000000000000..b8fa17bda119 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.config @@ -0,0 +1,365 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Make.config,v 1.3 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# + +ifneq ($(strip $(override-target)),) +override TARGET=$(override-target) +endif + +export TARGET + +# +# Set up the target name, and the target base variables. +# +# target = The full name of the target such as vxworks-bmw +# targetbase = 1st part of target (e.g. vxworks) +# targetplat = 2nd part of target (e.g. x86) if any; otherwise same as 1st +# +target = ${TARGET} +targetsplt = $(subst -, , ${target}) # change hyphens to spaces +targetbase = $(word 1,${targetsplt}) +targetplat = $(subst ${targetbase}-,,${TARGET}) + +# +# Common configuration for all platforms +# (Additional platform-dependent configurations are in Makefile.xxx) +# + +# +# THIS FILE SHOULD NOT BE MODIFIED LOCALLY, to override, add a file +# $SDK/make/Make.local that sets your local settings, and/or provide +# a path to your settings using the MAKE_LOCAL variable. If +# either of these files exists, their values will override those in this makefile. +# +ifdef MAKE_LOCAL +-include ${MAKE_LOCAL} +endif + +-include ${SDK}/make/Make.local + +ifdef ALL_CHIPS + ROBO_CHIPS = 1 + ESW_CHIPS = 1 +else + ifndef ROBO_CHIPS + ESW_CHIPS = 1 + endif +endif # ALL_CHIPS + +# +# By default, turn off the "changing directory" message. +# +MAKEFLAGS += --no-print-directory + +# +# Use gmake by default +# + +include ${SDK}/make/Make.tools +include ${SDK}/make/Makefile.${target} + +# use QUIET=1 to control printing of compilation lines +ifdef QUIET +Q:=@ +else +Q:= +endif + +# +# Suffix to add to the "target" files to allow local builds with different +# flags. Set "target_suffix" to XXX to cause the build to put built objects +# in ${target}${target_suffix}. This allows things like building a debug +# version with different flags. This may also be set in another Makefile. +# + +#target_suffix := + +# +# Optional suffix to add to the build directory and output binary files +# to allow multiple builds to co-exist for various reasons. +# +#chip_suffix := -$(shell echo $(CHIP) | tr A-Z a-z) + +# +# Combined suffixes +# +all_suffix = ${chip_suffix}${target_suffix} + +# +# Default location to place binaries and make depend files for building +# purposes. +# +ifeq "$(HOSTTYPE)" "Windows2000PC" +BLDROOTWITHDRIVE = ${SDK}/build/${target}${all_suffix}${bldroot_suffix} +BLDROOT = ${SDK_NO_DRIVE_NAME}/build/${target}${all_suffix}${bldroot_suffix} +else # ifeq "$(HOSTTYPE)" "Windows2000PC" + +ifndef SDKBUILD +SDKBUILD :=build +endif + +BLDROOT = ${SDK}/${SDKBUILD}/$(if ${BLDCONFIG},${BLDCONFIG}/)${target}${all_suffix}${bldroot_suffix} + +endif # ifeq "$(HOSTTYPE)" "Windows2000PC" + +# This is needed because we cannot include Make.vxworks before Make.config +ifndef DEST_DIR_SUFFIX +export DEST_DIR_SUFFIX :=$(subst $(realpath $(SDK))/systems,,$(realpath $(CURDIR)/$(dir ($(firstword $(MAKEFILE_LIST)))))) +ifeq ($(MAKELEVEL),0) +endif +endif + +ifeq ($(DEST_DIR),) +export DEST_DIR :=${SDK}/${SDKBUILD}$(if ${BLDCONFIG},/${BLDCONFIG})$(DEST_DIR_SUFFIX) +endif + +ifdef LOCALDIR +BLDDIR = ${BLDROOT}/${LOCALDIR} +ifeq "$(HOSTTYPE)" "Windows2000PC" +BLDDIRWITHDRIVE = ${BLDROOTWITHDRIVE}/${LOCALDIR} +endif +else # ifdef LOCALDIR +BLDDIR = ${BLDROOT} +ifeq "$(HOSTTYPE)" "Windows2000PC" +BLDDIRWITHDRIVE = ${BLDROOTWITHDRIVE} +endif +endif # ifdef LOCALDIR + +LIBDIR = ${BLDROOT} + +# +# Export directory, where build objects used by the outside world are +# placed (exported header files, libs, bins) +# +EXPDIR = ${SDK}/export/${target}${all_suffix} + +# +# Standard include paths +# +INCDIR = ${SDK}/include + +# +# Compilation Flags +# +# Flags may be added to (see below) +# + +INCFLAGS = -I${INCDIR} -I${SDK}/systems + +CFLAGS += ${INCFLAGS} +CXXFLAGS += ${INCFLAGS} +CPPFLAGS += ${INCFLAGS} + +CFLAGS += -DSAI_FIXUP -DBCM_PORT_DEFAULT_DISABLE -DBCM_VLAN_NO_DEFAULT_ETHER -DBCM_VLAN_NO_DEFAULT_CPU -DBCM_WARM_BOOT_SUPPORT -DSAL_CONFIG_FILE_DISABLE -DSAL_THREAD_NAME_PRINT_DISABLE -UKCOM_FILTER_MAX -DKCOM_FILTER_MAX=256 -DALPM_ENABLE -DOPENNSL_PHY_ROUTINES -DTH2_CPU_POOL_SETUP -DINCLUDE_L3 -DSAI_ONLY -DPRINT_TO_SYSLOG -D_SHR_PBMP_WIDTH=256 -DINCLUDE_DIAG_SHELL -DSTATIC=static -DLOG_TEST -DLOG_SAI -D_GNU_SOURCE + +# +# Debug #ifdef control +# +# Compiling out #ifdef DEBUG code saves about 1.3% on executable size. +# It is recommended to leave debug enabled when developing applications. +# +ifndef DEBUG_IFDEFS +DEBUG_IFDEFS=TRUE +endif + +ifeq ($(DEBUG_IFDEFS),TRUE) +CFLAGS += -DBROADCOM_DEBUG +CXXFLAGS += -DBROADCOM_DEBUG +CPPFLAGS += -DBROADCOM_DEBUG +endif + +# +# Debug symbol information control +# +ifndef DEBUG_SYMBOLS +DEBUG_SYMBOLS=TRUE +endif + +ifeq ($(DEBUG_SYMBOLS),TRUE) +CFLAGS += -g +CXXFLAGS += -g +CPPFLAGS += -g +endif + +# +# If DEBUG_CFLAGS is set, add its contents to CFLAGS. +# May be useful for setting on the command line or adding to Make.local. +# Example: gmake DEBUG_CFLAGS=-save-temps system.c +# + +ifneq ($(DEBUG_CFLAGS),) +CFLAGS += $(DEBUG_CFLAGS) +CXXFLAGS += $(DEBUG_CFLAGS) +CPPFLAGS += $(DEBUG_CFLAGS) +endif + +# +# Optimization level +# +# Set DEBUG_OPTIMIZE to TRUE (default) to use a normal optimization +# determined by OPTFLAGS_DEFAULT in the platform Makefile. +# Set DEBUG_OPTIMIZE to FALSE to use no optimization, +# strongly recommended when using any debugger. +# Set DEBUG_OPTIMIZE to any other option string to request specific +# optimization flags (for example -O2). +# +ifndef DEBUG_OPTIMIZE +DEBUG_OPTIMIZE=TRUE +endif + +ifeq ($(DEBUG_OPTIMIZE),TRUE) +OPTFLAGS += $(OPTFLAGS_DEFAULT) +else +ifneq ($(DEBUG_OPTIMIZE),FALSE) +OPTFLAGS += $(DEBUG_OPTIMIZE) +endif +endif + +# +# Debug assertion control. +# +# Compiling out assert() saves about 1.1% on executable size, +# however doing so is VERY MUCH discouraged. +# +ifndef DEBUG_ASSERTS +DEBUG_ASSERTS=TRUE +endif + +ifeq ($(DEBUG_ASSERTS),FALSE) +CFLAGS += -DNDEBUG +CXXFLAGS += -DNDEBUG +CPPFLAGS += -DNDEBUG +endif + +# +# GCC pedantic mode. +# +ifeq ($(DEBUG_PEDANTIC),TRUE) +CFGFLAGS += -D__PEDANTIC__ +CFLAGS += --pedantic +CXXFLAGS += --pedantic +endif + +# +# In each directory, build a list of local sources, objects, and headers +# +LSRCS = $(wildcard *.c *.cpp *.s *.cc *.C) +LOBJS = $(addsuffix .o, $(basename ${LSRCS})) +BOBJS = $(addprefix ${BLDDIR}/,${LOBJS}) +LHDRS = $(wildcard *.h *.H) +LDOTIS = $(wildcard *.i) + + +# +# Rule to create object file (build) directory +# + +.PHONY: all install clean distclean + +.PRECIOUS: ${BLDDIR}/.tree + +%/.tree: + @$(ECHO) 'Creating build directory $(dir $@)' + @$(MKDIR) $(dir $@) + @$(ECHO) "Build Directory for ${LOCALDIR} Created" > $@ + +# Rule allowing build through CPP only, creates .E file from .c file. + +%.E: %.c + $Q${CC} -E ${CFLAGS} $< | sed -e '/^ *$$/d' -e p -e d > $@ + +# Rule allowing build through source only, creates .s file from .c file. + +%.s: %.c + $Q${CC} -S ${CFLAGS} $< + +# +# Default Build rules for .c --> .o, leaving the binary in BLDDIR/X.o, +# even if file not built from directory of source. +# +ifeq ($(FAST),1) +${BLDDIR}/%.o: %.c +else +ifdef GENERATE_C_FILES +${BLDDIR}/%.o: %.c +else +${BLDDIR}/%.o: %.c +endif +endif +ifdef QUIET + @${ECHO} Compiling ${LOCALDIR}/$< +endif +ifdef LOCAL_D_FILE + $Q$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< --write-user-dependencies + -@/bin/cp $*.d $(BLDDIR)/$*.d + -@/bin/rm -f $*.d +else + $Q$(CC) -MD -MF $(BLDDIR)/$*.d $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< +endif + @/bin/cp $(BLDDIR)/$*.d $(BLDDIR)/$*.tmp;\ + /bin/sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' \ + < $(BLDDIR)/$*.d >> $(BLDDIR)/$*.tmp; \ + /bin/sed \ + -e 's| \([0-9a-zA-Z]\)| '$(SDK)/$(LOCALDIR)'\/\1|g' \ + -e 's|^\([0-9a-zA-Z]\)|'$(SDK)/$(LOCALDIR)'/\1|g' \ + -e 's| \(\.\.\/\)| '$(SDK)/$(LOCALDIR)'\/\1|g' \ + -e 's|'$(SDK)'|'$$\{SDK\}'|g' \ + -e 's/\w*\/\.\.\/*//g' \ + -e 's/\w*\/\.\.\/*//g' \ + -e 's/\w*\/\.\.\/*//g' \ + < $(BLDDIR)/$*.tmp > $(BLDDIR)/$*.P; \ + /bin/rm -f $(BLDDIR)/$*.d $(BLDDIR)/$*.tmp + +${BLDDIR}/%.o: %.s +ifdef QUIET + @${ECHO} Assembling ${LOCALDIR}/$< +endif + $Q${CC} ${CFLAGS} ${EXTRA_CFLAGS} -c $< -o $@ + +${BLDDIR}/%.o: %.cpp +ifdef QUIET + @${ECHO} Compiling ${LOCALDIR}/$< +endif + $Q${CXX} -c ${CXXFLAGS} -c $< -o $@ + +${BLDDIR}/%.o: %.cc ${BLDDIR}/.tree +ifdef QUIET + @${ECHO} Compiling ${LOCALDIR}/$< +endif + $Q${CXX} -c ${CXXFLAGS} -c $< -o $@ + +# +# Cause "make foo.o" in any subdirectory to put the object in the build +# directory instead of the local directory. +# +%.o: ${BLDDIR}/%.o + @ + +# +# List of directories where built objects live. +# (we are not making the export directories for now) +# +#DIRS = ${BLDDIR} ${EXPDIR}/lib ${EXPDIR}/bin ${EXPDIR}/include +DIRS = ${BLDDIR} + +ifeq (C_COMPILER,$(MAKECMDGOALS)) +C_COMPILER: + @echo $(CC) +endif diff --git a/platform/broadcom/saibcm-modules/make/Make.depend b/platform/broadcom/saibcm-modules/make/Make.depend new file mode 100644 index 000000000000..de7099387666 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.depend @@ -0,0 +1,108 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Make.depend,v 1.14 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Default rule to build dependencies. This builds a x.d file for each +# x.c file that describes the dependencies. We then conditionally include +# the generated .d files. +# + +# +# If making 'clean', do not include any .d files. If they are included, +# gmake intrinsically tries to remake them all. +# +ifeq (,$(findstring clean,$(MAKECMDGOALS))) + +ZFS :=$(wildcard *.zf) +ZFC := $(ZFS:.zf=.c) + +ifdef GENERATE_C_FILES +ifndef GEN_INCS +$(error "GEN_INCS was not defined") +endif + +ZF_GEN = ${SDK}/tools/zFrameCodeGen.pl + +# 1=.zf +define ZFS_RULE +$(1:.zf=Console.c) : $(1:.zf=.c) + @echo updated $$@ from $$? + +$(1:.zf=.c) : $(1) $(ZF_GEN) + @$(PERL) $(ZF_GEN) -s -z . -p . -g $1 -t c + @echo generated ${LOCALDIR}/$$@ from $(1) + @mv $$(*F).cx $$@ + @if [ -e $$(*F)Console.cx ] ; then \ + mv $$(*F)Console.cx $$(*F)Console.c; \ + echo Created $$(*F)Console.c ;\ + fi + @if [ -e $$(*F)Console.hx ] ; then \ + echo Created $(GEN_INCS)/$$(*F)Console.hx ;\ + mv $$(*F)Console.hx $(GEN_INCS)/ ; \ + fi + @mv $$(*F).hx $(GEN_INCS)/ +endef + +$(foreach zf,$(ZFS),$(eval $(call ZFS_RULE,$(zf)))) + +${BLDDIR}/%.P : ${BLDDIR}/.tree %.c + +.PHONY: GENFILES +GENFILES: $(ZFC) + +$(BOBJS) : $(ZFC) + +else +# +# Attempt to build the depend files. If it fails, the depend file is +# removed so that it is not included in later builds. +# +${BLDDIR}/%.P : %.c ${BLDDIR}/.tree + @$(ECHO) Dependencies for ${LOCALDIR}/$< + +${BLDDIR}/%.P : %.cc ${BLDDIR}/.tree + @$(ECHO) Dependencies for ${LOCALDIR}/$< + +endif + +# +# If there are C or C++ files in this directory, include the +# depend files for them. +# + +ifeq ($(findstring _COMPILER,$(MAKECMDGOALS))$(findstring variable,$(MAKECMDGOALS)),) +ifneq ($(strip ${LSRCS}),) +ifneq (,$(findstring .o,$(MAKECMDGOALS))) +-include $(addprefix ${BLDDIR}/,$(MAKECMDGOALS:.o=.P)) $(addprefix ${BLDDIR}/,$(MAKECMDGOALS:.o=.sig)) +else +-include $(addprefix ${BLDDIR}/,$(addsuffix .P,$(basename $(LSRCS)))) $(addprefix ${BLDDIR}/,$(addsuffix .sig,$(basename $(LSRCS)))) +endif +endif +endif + +endif # !CLEANING + +clean_d:: +ifdef QUIET + @$(ECHO) Cleaning dependencies for ${LOCALDIR} +endif +ifdef GENERATE_C_FILES + $Q$(RM) $(ZFC:%=$(SDK)/$(LOCALDIR)/%) $(ZFC:%.c=$(SDK)/$(LOCALDIR)/%Console.c) +endif + +clean:: clean_d diff --git a/platform/broadcom/saibcm-modules/make/Make.kernlib b/platform/broadcom/saibcm-modules/make/Make.kernlib new file mode 100644 index 000000000000..6ec8a1c8df77 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.kernlib @@ -0,0 +1,69 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Make.kernlib,v 1.7 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Make rules/targets for handling libraries + +.SECONDARY:: ${BOBJS} + +targetlibsoname = ${lib}.so.${SHAREDLIBVER} +targetlibrealname = ${targetlibsoname} +targetlibso = ${LIBDIR}/${targetlibrealname} + +ifeq ($(TOOLS),Borland) + +LIBSUFFIX=lib + +${LIBDIR}/%.lib: ${BORLAND_BOBJS} + $(RM) $@ + $(FOREACH) -subdir "$(LIBDIR)" \ + "tlib $@ $(foreach obj, $(BORLAND_LOBJS), +-$(obj))" + +else # !Borland + +LIBSUFFIX=a + +${LIBDIR}/%.a: ${BOBJS} +ifdef QUIET + @$(ECHO) Building library $(notdir $@) +endif + $Q$(RM) $@ + $Q$(AR) ${ARFLAGS} $@ $(sort ${BOBJS}) +ifeq ($(LINUX_MAKE_SHARED_LIB),1) +ifeq ($(targetbase),unix) + $(CC) -shared -Wl,-soname,${targetlibsoname} -o ${targetlibso} ${BOBJS} -lc +endif +endif # LINUX_MAKE_SHARED_LIB # +endif # !Borland + +targetlib = ${LIBDIR}/${lib}.${LIBSUFFIX} + +all:: ${BLDDIR}/.tree ${targetlib} + +install:: all + +clean:: +ifdef QUIET + @$(ECHO) Cleaning objects for ${LOCALDIR} and ${lib} +endif + $Q$(RM) ${BOBJS} + $Q$(RM) ${targetlib} + $Q$(RM) ${targetlibso} + +distclean:: clean + diff --git a/platform/broadcom/saibcm-modules/make/Make.lib b/platform/broadcom/saibcm-modules/make/Make.lib new file mode 100644 index 000000000000..d67325c5dd2f --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.lib @@ -0,0 +1,80 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Make.lib,v 1.14 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Make rules/targets for handling libraries + +.SECONDARY:: ${BOBJS} + +BOBJS_FAST = ${BOBJS} +BOBJS_MAKE_CMD = + +ifeq ($(FAST),1) + ifneq ($(strip $(BOBJS)),) + BOBJS_FAST = + BOBJS_ARGS = -j9 + BOBJS_MAKE_CMD = pwd && make LSRUN=$(SDK)/tools/lsrun.pl $(BOBJS_ARGS) ${BOBJS} + endif +endif + +ifeq ($(TOOLS),Borland) + +LIBSUFFIX=lib + +${LIBDIR}/%.lib: ${BORLAND_BOBJS} + $(RM) $@ + $(FOREACH) -subdir "$(LIBDIR)" \ + "tlib $@ $(foreach obj, $(BORLAND_LOBJS), +-$(obj))" + +else # !Borland + +ifeq ($(LINUX_MAKE_SHARED_LIB),1) +LIBSUFFIX=so.${SHAREDLIBVER} +else +LIBSUFFIX=a +endif + +targetlib = ${LIBDIR}/${lib}.${LIBSUFFIX} + +all:: ${BLDDIR}/.tree ${targetlib} + +${LIBDIR}/%.${LIBSUFFIX}: ${BOBJS_FAST} + $(BOBJS_MAKE_CMD) +ifdef QUIET + @$(ECHO) Building library $(notdir $@) +endif + $Q$(RM) $@ +ifeq ($(LINUX_MAKE_SHARED_LIB),1) + $(CC) -shared -Wl,-soname,${lib}.${LIBSUFFIX}${EXTRA_LIB_LDFLAGS} -o ${targetlib} ${BOBJS} -lc +else + ${Q}cd $(dir $(word 1,${BOBJS}));$(AR) ${ARFLAGS} $@ $(sort $(notdir ${BOBJS})) +endif + +endif # !Borland + + +install:: all + +clean:: +ifdef QUIET + @$(ECHO) Cleaning objects for ${LOCALDIR} and ${lib} +endif + $Q$(RM) ${BOBJS} + $Q$(RM) ${targetlib} + +distclean:: clean diff --git a/platform/broadcom/saibcm-modules/make/Make.linux b/platform/broadcom/saibcm-modules/make/Make.linux new file mode 100644 index 000000000000..bd86ca351b6e --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.linux @@ -0,0 +1,97 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# $Id: Make.linux,v 1.18 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Common make targets for Linux user and kernel builds included by top +# level Linux makefiles +# +# Variables referenced: +# +# LINUX_MAKE_FLAGS +# Additional flags passed to Make +# +# LINUX_MAKE_USER +# Defined: user build +# Undefined: kernel build +# +# LINUX_MAKE_DIR +# Common makefile location, if it is not ../common +# +# + +export DEST_DIR_SUFFIX :=$(subst $(realpath $(SDK))/systems,,$(realpath $(CURDIR)/$(dir ($(firstword $(MAKEFILE_LIST)))))) + +ifeq (,$(kernel_version)) +kernel_version=2_4 +endif + +ifndef LINUX_MAKE_SHARED_LIB +LINUX_MAKE_SHARED_LIB=0 +endif + +ifeq (,$(SHAREDLIBVER)) +SHAREDLIBVER=1 +endif + +ifndef LINUX_MAKE_DIR +ifdef LINUX_MAKE_USER +LINUX_MAKE_DIR := $(SDK)/systems/linux/user/common +else +LINUX_MAKE_DIR := $(SDK)/systems/linux/kernel/common +endif +endif + +ifdef LINUX_MAKE_USER + CMD = $(LINUX_MAKE_FLAGS) -C $(LINUX_MAKE_DIR) \ + platform=$(platform) bldroot_suffix=/$(platform) kernel_version=$(kernel_version) \ + LINUX_MAKE_SHARED_LIB=$(LINUX_MAKE_SHARED_LIB) SHAREDLIBVER=$(SHAREDLIBVER) +else + export LINUX_MAKE_KERNEL := 1 + CMD = $(LINUX_MAKE_FLAGS) -C $(LINUX_MAKE_DIR) \ + platform=$(platform) kernel_version=$(kernel_version) +endif + +ifneq (,$(MIPS_TOOLS_DIR)) + CMD += MIPS_TOOLS_DIR=$(MIPS_TOOLS_DIR) +endif + +ifneq (,$(MIPS_CROSS_COMPILE)) + CMD += MIPS_CROSS_COMPILE=$(MIPS_CROSS_COMPILE) +endif + +ifneq (,$(LINUX_INCLUDE)) + CMD += LINUX_INCLUDE=$(LINUX_INCLUDE) +endif + +# gmake does not understand $(CMD) to be a submake +# options are to +$(CMD) or $(MAKE) $(CMD) +# trying the latter +build: + $(MAKE) $(CMD) + +DELIVER clean C_COMPILER CXX_COMPILER variable mod bcm user: + $(MAKE) $(CMD) $@ + +clean_d: clean + +distclean: + $(MAKE) $(CMD) $@ + +.PHONY: build clean distclean clean_d DELIVER variable mod bcm user + diff --git a/platform/broadcom/saibcm-modules/make/Make.subdirs b/platform/broadcom/saibcm-modules/make/Make.subdirs new file mode 100644 index 000000000000..1033e296c0a3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.subdirs @@ -0,0 +1,44 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Make.subdirs,v 1.8 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Make rules/targets for handling subdirectories + +.PHONY: ${subdirs} + +all:: ${subdirs} +ifdef QUIET + @$(ECHO) Subdirectory build for ${subdirs} +endif + +${subdirs}:: + $Q$(MAKE) -C $@ kernel_version=$(kernel_version) LINUX_MAKE_SHARED_LIB=${LINUX_MAKE_SHARED_LIB} SHAREDLIBVER=${SHAREDLIBVER} + +ifeq "$(HOSTTYPE)" "Windows2000PC" +clean clean_d install distclean:: +ifdef QUIET + @$(ECHO) Subdirectory $@ for ${subdirs} +endif + $Q$(FOREACH) "$(subdirs)" "${MAKE} -C ## $@" +else +clean clean_d install distclean:: +ifdef QUIET + @$(ECHO) Subdirectory $@ for ${subdirs} +endif + @(for name in $(subdirs); do $(MAKE) -C $$name $@; done) +endif diff --git a/platform/broadcom/saibcm-modules/make/Make.tools b/platform/broadcom/saibcm-modules/make/Make.tools new file mode 100644 index 000000000000..8ed77727fef2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.tools @@ -0,0 +1,38 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Make.tools,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +SYSNAME := $(shell uname -s) +HCC ?=/usr/bin/gcc +SED = /bin/sed +COMPRESS = /usr/bin/compress +PERL = /usr/bin/perl +LN = /bin/ln +HOSTTYPE= i386-linux + +# +# Platform Independent +# +MKTOOL = $(PERL) ${SDK}/tools/mktool.pl +RM = $(MKTOOL) -rm +MKDIR = $(MKTOOL) -md +FOREACH = $(MKTOOL) -foreach +CP = $(MKTOOL) -cp +MAKEDEP = $(MKTOOL) -dep +ECHO = $(MKTOOL) -echo +MKBEEP = ${MKTOOL} -beep diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-bmw-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-bmw-2_6 new file mode 100644 index 000000000000..6fa170fb75e6 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-bmw-2_6 @@ -0,0 +1,122 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-bmw-2_6,v 1.20 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Look for custom tools +ifneq (,$(PPC_TOOLS_DIR)) +ifneq (,$(PPC_CROSS_COMPILE)) +override PATH := $(PPC_TOOLS_DIR):$(PATH) +override CROSS_COMPILE := $(PPC_CROSS_COMPILE) +endif +endif + +# Default tools +ifeq (,$(WRS_LINUX_VERSION)) +WRS_LINUX_VERSION=2.0 +endif + +# Default Linux Kernel directory +ifeq (,$(KERNDIR)) + +ifeq (1.4,$(WRS_LINUX_VERSION)) + +KERNDIR := /projects/ntsw-tools/linux/wrslinux_1.4/bcm98245cpci/build/linux-2.6.14-cgl + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE = powerpc-wrs-linux-gnu-603e-glibc_std- +endif + +WRLINUX_BASE=/tools/windriver/linux_ed/1.4/Linux +export WIND_LIC_PROXY = $(WRLINUX_BASE)/setup/x86-linux2/bin +override PATH := $(WRLINUX_BASE)/gnu/3.4.4-wrlinux-1.4/x86-linux2/bin:$(PATH) + +WRS_SYSROOT_PATH := $(WRLINUX_GNU_PATH)/../lib/gcc/powerpc-wrs-linux-gnu/3.4.4/include +else + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE = powerpc-wrs-linux-gnu-ppc_603e-glibc_std- +endif + +KERNDIR:= /projects/ntsw-tools/linux/wrslinux_2.0/bmw/glibc_std/build/linux-2.6.21-standard + +WRLINUX_BASE=/tools/windriver/linux_ed/2.0_GA/Linux + +TOOLCHAIN_EXEC_PREFIX=$(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2 +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_EXEC_PREFIX) +WIND_LIC_PROXY=$(WRLINUX_BASE)/setup/x86-linux2/bin + +WRLINUX_GNU_PATH = $(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2/bin + +override PATH := $(TOOLCHAIN_EXEC_PREFIX):$(KERNDIR)/../../host-cross/bin:$(KERNDIR)/../../host-cross/powerpc-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) + +export TOOLCHAIN_EXEC_PREFIX TOOLCHAIN_BIN_DIR WIND_LIC_PROXY + +WRS_SYSROOT_PATH := $(WRLINUX_GNU_PATH)/../lib/gcc/powerpc-wrs-linux-gnu/4.1.2/include + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") +endif +endif +endif + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"BMW_MPC8245/PPC603e\" + +ARCH = ppc +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +ifeq (1.4,$(WRS_LINUX_VERSION)) +# From linux/arch/ppc/Makefile + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer -fsigned-char -msoft-float -pipe -ffixed-r2 -Wno-uninitialized -mmultiple -mstring +endif + +else +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -m32 -nostdinc -isystem $(WRS_SYSROOT_PATH) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/autoconf.h -I$(KERNDIR)/arch/ppc -I$(KERNDIR)/arch/ppc/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -msoft-float -pipe -ffixed-r2 -mmultiple -mno-altivec -mstring -fomit-frame-pointer -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign +endif + +endif +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-gto b/platform/broadcom/saibcm-modules/make/Makefile.linux-gto new file mode 100644 index 000000000000..cd5e8fbca195 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-gto @@ -0,0 +1,114 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-gto-4_4,v 1.42 Broadcom SDK $ +# $Copyright: (c) 2015 Broadcom Corp. +# All Rights Reserved.$ + +# User must select one platform from below. +ifeq (,$(BUILD_PLATFORM)) +BUILD_PLATFORM=POWERPC_LINUX +endif + +# TOOLCHAIN_BASE_DIR Toolchain base directory for GTO devices +# TARGET_ARCHITECTURE Compiler for target architecture +# KERNDIR Kernel directory for iPROC-CMICd devices +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/gto +TARGET_ARCHITECTURE := powerpc-broadcom-linux-gnuspe +KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/current + + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := $(TARGET_ARCHITECTURE)- +endif + + +# GTO toolchain +TOOLCHAIN_BIN_DIR := $(TOOLCHAIN_BASE_DIR)/toolchain/host/usr/bin +override PATH := $(TOOLCHAIN_BIN_DIR)/../$(TARGET_ARCHITECTURE)/bin:$(TOOLCHAIN_BIN_DIR):$(PATH) +export TOOLCHAIN_BIN_DIR + + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"GTO_MPC8548\" +CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=32 + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +ARCH = powerpc +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + + +# From linux/arch/ppc/Makefile +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +KFLAG_INCLD = $(TOOLCHAIN_BIN_DIR)/../lib/gcc/$(TARGET_ARCHITECTURE)/4.6.4/include + +ifdef BROADCOM_SVK +ifdef BCM_BME3200_B0 +PLX_PCI2LBUS=1 +endif +ifdef BCM_BM9600_B0 +PLX_PCI2LBUS=1 +endif +ifeq ($PLX_PCI2LBUS, 1) +CFLAGS += -DBCM_PLX9656_LOCAL_BUS -DBDE_LINUX_NON_INTERRUPTIBLE +endif +endif + +ifdef DPP_CHIPS +CFLAGS += -DDUNE_BCM -D__DUNE_GTO_BCM_CPU__ -D__DUNE_LINUX_BCM_CPU_PCIE__ -D__DUNE_LINUX_BCM_CPU_PCP_DMA__ +CFGFLAGS += -DSOC_CM_FUNCTION +endif + +ifdef DFE_CHIPS +CFLAGS += -DDUNE_BCM -D__DUNE_GTO_BCM_CPU__ -D__DUNE_LINUX_BCM_CPU_PCIE__ +CFGFLAGS += -DSOC_CM_FUNCTION +endif + +ifdef SHADOW_PLX +CFLAGS += -DBCM_PLX9656_LOCAL_BUS -DBDE_LINUX_NON_INTERRUPTIBLE -DSHADOW_SVK +endif + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -m32 -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/generated/uapi/linux/version.h -include $(LINUX_INCLUDE)/generated/autoconf.h -I$(KERNDIR)/arch/powerpc -I$(KERNDIR)/arch/powerpc/include -I$(KERNDIR)/include/asm-powerpc -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -msoft-float -pipe -ffixed-r2 -mmultiple -mno-altivec -funit-at-a-time -Wa,-me500 -fomit-frame-pointer -Wdeclaration-after-statement -Wno-pointer-sign +endif + +ifneq (,$(findstring TCL,$(FEATURE_LIST))) +#LINK_STATIC = 0 +#export LINK_STATIC +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-4_4 +endif + diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-gto-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-gto-2_6 new file mode 100644 index 000000000000..4caa4902421f --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-gto-2_6 @@ -0,0 +1,276 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-gto-2_6,v 1.42 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# User must select one platform from below.By default WR_LINUX is selected. . +ifeq (,$(BUILD_PLATFORM)) +#BUILD_PLATFORM=ELDK +BUILD_PLATFORM=WR_LINUX +endif + +# Specify the ELDK version you want to use for building SDK. +ifeq (,$(ELDK_VERSION)) +ifeq (ELDK,$(BUILD_PLATFORM)) +ELDK_VERSION=4.0 +endif +endif + +# Specify the KERNEL VERSION you want to use for building SDK. +ifeq (,$(KERN_VER)) +ifeq (ELDK,$(BUILD_PLATFORM)) +KERN_VER=2.6.21.7 +endif +endif + + +# Specify the Windriver Linux version here.For example '2.0' as shown below. +ifeq (WR_LINUX,$(BUILD_PLATFORM)) +ifeq (,$(WRS_LINUX_VERSION)) +WRS_LINUX_VERSION=2.0 +endif +endif + + +#glibc_small and glibc_std have their own cross-compilation tools and and path for these tools are different as implemented below. To enable glibc_small build, line given below should be uncommented. + +#WRL_GLIBC_SMALL=TRUE + +ifeq (2.0,$(WRS_LINUX_VERSION)) +ifeq ($(WRL_GLIBC_SMALL),TRUE) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := powerpc-wrs-linux-gnu-ppc_e500v2-glibc_small- +endif + +KERNDIR ?=/projects/ntsw-tools/linux/wrslinux_2.0/gto/glibc_small/build/linux-2.6.21-standard + +else + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := powerpc-wrs-linux-gnu-ppc_e500v2-glibc_std- +endif + +KERNDIR ?= /projects/ntsw-tools/linux/wrslinux_2.0/gto/glibc_std/build/linux-2.6.21-standard + +endif + +export WRL_GLIBC_SMALL + +# After this point glibc_std and glibc_small share these flags + +WRLINUX_BASE ?=/tools/windriver/linux_ed/2.0_GA/Linux +TOOLCHAIN_EXEC_PREFIX=$(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2 +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_EXEC_PREFIX) +WIND_LIC_PROXY=$(WRLINUX_BASE)/setup/x86-linux2/bin +WRLINUX_GNU_PATH = $(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2/bin +override PATH := $(TOOLCHAIN_EXEC_PREFIX):$(KERNDIR)/../../host-cross/bin:$(KERNDIR)/../../host-cross/powerpc-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) +export TOOLCHAIN_EXEC_PREFIX TOOLCHAIN_BIN_DIR WIND_LIC_PROXY +endif + + +ifeq (3.0,$(WRS_LINUX_VERSION)) +ifeq ($(WRL_GLIBC_SMALL),TRUE) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := powerpc-wrs-linux-gnu-ppc_e500v2-glibc_small- +endif + +KERNDIR ?=/projects/ntsw-tools/linux/wrslinux_3.0/gto/bcm98548xmc_30_glibc_small/build/linux-broadcom_bcm98548xmc-standard-build +KERNDIR_STD ?=/projects/ntsw-tools/linux/wrslinux_3.0/gto/bcm98548xmc_30_glibc_small/build/linux + +else + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := powerpc-wrs-linux-gnu-ppc_e500v2-glibc_std- +endif + +KERNDIR ?=/projects/ntsw-tools/linux/wrslinux_3.0/gto/bcm98548xmc_30_glibc_std_debug/build/linux-broadcom_bcm98548xmc-standard-build +KERNDIR_STD ?=/projects/ntsw-tools/linux/wrslinux_3.0/gto/bcm98548xmc_30_glibc_std_debug/build/linux + +endif + +export WRL_GLIBC_SMALL + +# After this point glibc_std and glibc_small share these flags + +WRLINUX_BASE ?=/tools/windriver/linux_ed/3.0/Linux +TOOLCHAIN_EXEC_PREFIX=$(WRLINUX_BASE)/wrlinux-3.0/layers/wrll-toolchain-4.3-85/powerpc/toolchain/x86-linux2 +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_EXEC_PREFIX) +WIND_LIC_PROXY=$(WRLINUX_BASE)/setup/x86-linux2/bin +WRLINUX_GNU_PATH = $(WRLINUX_BASE)/wrlinux-3.0/layers/wrll-toolchain-4.3-85/powerpc/toolchain/x86-linux2/bin +override PATH := $(TOOLCHAIN_EXEC_PREFIX):$(KERNDIR_STD)/../../host-cross/bin:$(KERNDIR_STD)/../../host-cross/powerpc-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) +export TOOLCHAIN_EXEC_PREFIX TOOLCHAIN_BIN_DIR WIND_LIC_PROXY + +LINUX_INCLUDE_STD := $(KERNDIR_STD)/include + +endif + +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (2.6.21.7, $(KERN_VER)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := ppc_85xx- +endif + +ifeq (4.0, $(ELDK_VERSION)) +override PATH := /tools/eldk/4.0/usr/bin:$(PATH) +else +override PATH := /tools/eldk/4.1/usr/bin:$(PATH) +endif +KERNDIR ?= /projects/ntsw-tools/linux/eldk/gto_eldk/linux-2.6.21.7 +endif +endif + +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (2.6.24.4, $(KERN_VER)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := ppc_85xx- +endif + +ifeq (4.0, $(ELDK_VERSION)) +override PATH := /tools/eldk/4.0/usr/bin:$(PATH) +else +override PATH := /tools/eldk/4.1/usr/bin:$(PATH) +endif +KERNDIR ?= /projects/ntsw-tools/linux/eldk/gto_eldk/linux-2.6.24.4 +endif +endif + + +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (2.6.25, $(KERN_VER)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := ppc_85xx- +endif + +ifeq (4.0, $(ELDK_VERSION)) +override PATH := /tools/eldk/4.0/usr/bin:$(PATH) +else +override PATH := /tools/eldk/4.1/usr/bin:$(PATH) +endif +KERNDIR ?= /projects/ntsw-tools/linux/eldk/gto_eldk/linux-2.6.25 +endif +endif + + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"GTO_MPC8548\" +CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=32 + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +ARCH = powerpc +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + + +# From linux/arch/ppc/Makefile +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + + +ifeq (,$(KFLAG_INCLD)) +ifeq (4.0,$(ELDK_VERSION)) +ifeq (ELDK,$(BUILD_PLATFORM)) +KFLAG_INCLD = /tools/eldk/4.0/usr/lib/gcc/powerpc-linux/4.0.0/include +endif +endif + +ifeq (4.1,$(ELDK_VERSION)) +ifeq (ELDK,$(BUILD_PLATFORM)) +KFLAG_INCLD = /tools/eldk/4.1/usr/lib/gcc/powerpc-linux/4.0.0/include +endif +endif + +ifeq (2.0,$(WRS_LINUX_VERSION)) +KFLAG_INCLD = $(WRLINUX_GNU_PATH)/../lib/gcc/powerpc-wrs-linux-gnu/4.1.2/include +endif + +ifeq (3.0,$(WRS_LINUX_VERSION)) +KFLAG_INCLD = $(WRLINUX_GNU_PATH)/../lib/gcc/powerpc-wrs-linux-gnu/4.3.2/include +endif +endif + +ifdef BROADCOM_SVK +ifdef BCM_BME3200_B0 +PLX_PCI2LBUS=1 +endif +ifdef BCM_BM9600_B0 +PLX_PCI2LBUS=1 +endif +ifeq ($PLX_PCI2LBUS, 1) +CFLAGS += -DBCM_PLX9656_LOCAL_BUS -DBDE_LINUX_NON_INTERRUPTIBLE +endif +endif + +ifdef DPP_CHIPS +CFLAGS += -DDUNE_BCM -D__DUNE_LINUX_BCM_CPU_PCP_DMA__ +CFGFLAGS += -DSOC_CM_FUNCTION +endif + +ifdef DFE_CHIPS +CFLAGS += -DDUNE_BCM +CFGFLAGS += -DSOC_CM_FUNCTION +endif + +ifdef SAND_CHIPS +CFLAGS += -D__DUNE_GTO_BCM_CPU__ -D__DUNE_LINUX_BCM_CPU_PCIE__ +endif + +ifdef SHADOW_PLX +CFLAGS += -DBCM_PLX9656_LOCAL_BUS -DBDE_LINUX_NON_INTERRUPTIBLE -DSHADOW_SVK +endif + +ifeq (,$(KFLAGS)) +#autoconf.h was moved in later kernels +LINUX_AUTOCONF = $(LINUX_INCLUDE)/generated/autoconf.h +ifeq (,$(shell ls $(LINUX_AUTOCONF) 2>/dev/null)) +LINUX_AUTOCONF = $(LINUX_INCLUDE)/linux/autoconf.h +endif + +KFLAGS := -D__KERNEL__ -m32 -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/version.h -include $(LINUX_AUTOCONF) -I$(KERNDIR)/arch/powerpc -I$(KERNDIR)/arch/powerpc -I$(KERNDIR)/arch/powerpc/include -I$(KERNDIR)/include/asm-powerpc -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -msoft-float -pipe -ffixed-r2 -mmultiple -mno-altivec -funit-at-a-time -Wa,-me500 -fomit-frame-pointer -Wdeclaration-after-statement -Wno-pointer-sign +endif + +#Wind river Linux 3.0 needs addtional flags +ifeq (3.0,$(WRS_LINUX_VERSION)) + +# Use MSI interrupts if kernel is compiled with MSI support. +#CFLAGS += -DBDE_LINUX_USE_MSI_INTERRUPT +KFLAGS += -I$(LINUX_INCLUDE_STD) -I$(KERNDIR_STD)/arch/powerpc -I$(KERNDIR_STD)/arch/powerpc/include -I$(KERNDIR_STD)/include.asm-powerpc -mno-spe +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc new file mode 100644 index 000000000000..7c0f9411f5e2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc @@ -0,0 +1,92 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-iproc Exp $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ +# Makefile for iproc-CMICd + +# User must select one platform from below.By default ARM_LINUX is selected. . +ifeq (,$(BUILD_PLATFORM)) +BUILD_PLATFORM=ARM_LINUX +endif + +# TOOLCHAIN_BASE_DIR Toolchain base directory for iPROC-CMICd devices +# TARGET_ARCHITECTURE Compiler for target architecture +# KERNDIR Kernel directory for iPROC-CMICd devices +ifeq (BE,$(ENDIAN_MODE)) +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/iproc-be/XLDK +TARGET_ARCHITECTURE:=armeb-broadcom-linux-uclibcgnueabi +KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux +else +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/iproc/XLDK +TARGET_ARCHITECTURE:= arm-broadcom-linux-uclibcgnueabi +KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux +endif + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE:= $(TARGET_ARCHITECTURE)- +endif + +# arm9tools +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/bin +override PATH:=$(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/$(TARGET_ARCHITECTURE)/bin:$(TOOLCHAIN_BIN_DIR):$(PATH) +LD_LIBRARY_PATH=$(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/lib + +export TOOLCHAIN_BIN_DIR LD_LIBRARY_PATH + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +ifeq (BE,$(ENDIAN_MODE)) +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +else +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=0 +ENDIAN = LE_HOST=1 +endif + +CFGFLAGS += -D$(ENDIAN) -DIPROC_CMICD +CFGFLAGS += -DBCM_PLATFORM_STRING=\"IPROC_CMICD\" + +ARCH = arm +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +KFLAG_INCLD ?= $(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/lib/gcc/$(TARGET_ARCHITECTURE)/4.9.3/include + +ifeq (,$(KFLAGS)) +KFLAGS := -D__LINUX_ARM_ARCH__=7 -D__KERNEL__ -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/generated/autoconf.h -I$(KERNDIR)/arch/arm/include -I$(KERNDIR)/arch/arm/include/generated -I$(KERNDIR)/arch/arm/mach-iproc/include -Wall -Wstrict-prototypes -Wno-trigraphs -Os -fno-strict-aliasing -fno-common -marm -mabi=aapcs-linux -fno-pic -pipe -msoft-float -ffreestanding -march=armv7-a -mfpu=vfp -mfloat-abi=softfp -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mlong-calls +KFLAGS += -I$(LINUX_INCLUDE)/uapi -I$(LINUX_INCLUDE)/generated/uapi -I$(KERNDIR)/arch/arm/include/uapi -I$(KERNDIR)/arch/arm/include/generated/uapi +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-3_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-3_14 b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-3_14 new file mode 100644 index 000000000000..723fea6c73cf --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-3_14 @@ -0,0 +1,103 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-iproc-3_6,v 1.1 Broadcom SDK $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ +# Makefile for iproc-CMICd + +# User must select one platform from below.By default ARM_LINUX is selected. . +ifeq (,$(BUILD_PLATFORM)) +BUILD_PLATFORM=ARM_LINUX +endif + +# TOOLCHAIN_BASE_DIR Toolchain base directory for iPROC-CMICd devices +# TARGET_ARCHITECTURE Compiler for target architecture +# KERNDIR Kernel directory for iPROC-CMICd devices +ifeq (BE,$(ENDIAN_MODE)) +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk37-be/buildroot-2013.11-gcc48-opt-broadcom +TARGET_ARCHITECTURE:=armeb-buildroot-linux-gnueabi +KERNDIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk37-be/XLDK/kernel/linux +else +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk37/XLDK +TARGET_ARCHITECTURE:= arm-broadcom-linux-uclibcgnueabi +KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux +endif + + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE:= $(TARGET_ARCHITECTURE)- +endif + +# arm9tools +ifeq (BE,$(ENDIAN_MODE)) +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_BASE_DIR)/host/usr/bin +override PATH:=$(TOOLCHAIN_BASE_DIR)/host/usr/$(TARGET_ARCHITECTURE)/bin:$(TOOLCHAIN_BIN_DIR):$(PATH) +LD_LIBRARY_PATH=$(TOOLCHAIN_BASE_DIR)/host/usr/lib +else +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_BASE_DIR)/buildroot/usr/bin +override PATH:=$(TOOLCHAIN_BASE_DIR)/buildroot/usr/$(TARGET_ARCHITECTURE)/bin:$(TOOLCHAIN_BIN_DIR):$(PATH) +LD_LIBRARY_PATH=$(TOOLCHAIN_BASE_DIR)/buildroot/usr/lib +endif + +export TOOLCHAIN_BIN_DIR LD_LIBRARY_PATH + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +ifeq (BE,$(ENDIAN_MODE)) +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +else +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=0 +ENDIAN = LE_HOST=1 +endif + +CFGFLAGS += -D$(ENDIAN) -DIPROC_CMICD +CFGFLAGS += -DBCM_PLATFORM_STRING=\"IPROC_CMICD\" + +ARCH = arm +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +ifeq (BE,$(ENDIAN_MODE)) +KFLAG_INCLD ?= $(TOOLCHAIN_BASE_DIR)/host/usr/lib/gcc/$(TARGET_ARCHITECTURE)/4.8.2/include +else +KFLAG_INCLD ?= $(TOOLCHAIN_BASE_DIR)/buildroot/usr/lib/gcc/$(TARGET_ARCHITECTURE)/4.7.2/include +endif + +ifeq (,$(KFLAGS)) +KFLAGS := -D__LINUX_ARM_ARCH__=7 -D__KERNEL__ -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/generated/autoconf.h -I$(KERNDIR)/arch/arm/include -I$(KERNDIR)/arch/arm/include/generated -I$(KERNDIR)/arch/arm/mach-northstar/include -I$(KERNDIR)/arch/arm/plat-iproc/include -Wall -Wstrict-prototypes -Wno-trigraphs -Os -fno-strict-aliasing -fno-common -marm -mabi=aapcs-linux -fno-pic -pipe -msoft-float -ffreestanding -march=armv7-a -mfpu=vfp -mfloat-abi=softfp -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mlong-calls +KFLAGS += -I$(LINUX_INCLUDE)/uapi -I$(LINUX_INCLUDE)/generated/uapi -I$(KERNDIR)/arch/arm/include/uapi -I$(KERNDIR)/arch/arm/include/generated/uapi +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-3_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-jag-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-jag-2_6 new file mode 100644 index 000000000000..1e89cdab2434 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-jag-2_6 @@ -0,0 +1,166 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-jag-2_6,v 1.20 Broadcom SDK $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ + + +# User must select one platform from below.By default WR_LINUX is selected. . +ifeq (,$(BUILD_PLATFORM)) +#BUILD_PLATFORM=ELDK +BUILD_PLATFORM=WR_LINUX +endif + + +# Specify the KERNEL VERSION you want to use for building SDK. +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (,$(KERN_VER)) +KERN_VER=2.6.21.7 +endif +endif + +# Specify the Windriver Linux version here.For example '2.0' as shown below. +ifeq (WR_LINUX,$(BUILD_PLATFORM)) +ifeq (,$(WRS_LINUX_VERSION)) +WRS_LINUX_VERSION=2.0 +endif +endif + +ifeq (WR_LINUX,$(BUILD_PLATFORM)) +ifeq (1.4,$(WRS_LINUX_VERSION)) + +KERNDIR := /projects/ntsw-tools/linux/wrslinux_1.4/broadcom_bcm95836cpci_be/build/linux-2.6.14-small + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips-wrs-linux-gnu- +endif + +export WIND_LIC_PROXY = /projects/ntsw-tools/wrs/wrs_linux/GPP_LE_1.4_PPR/setup/x86-linux2/bin + +override PATH := /projects/ntsw-tools/wrs/wrs_linux/GPP_LE_1.4_PPR/gnu/3.4.4-wrlinux-1.4/x86-linux2/bin:$(PATH) +endif + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +#CROSS_COMPILE = mips-wrs-linux-gnu- + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips-wrs-linux-gnu-mips_softfp-glibc_std- +endif + +KERNDIR:= /projects/ntsw-tools/linux/wrslinux_2.0/jag/glibc_std/build/linux-2.6.21-standard + +endif + +WRLINUX_BASE=/tools/windriver/linux_ed/2.0_GA/Linux + +TOOLCHAIN_BIN_DIR=$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin +WIND_LIC_PROXY=$(WRLINUX_BASE)/setup/x86-linux2/bin + +WRLINUX_GNU_PATH=$(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2/bin + +override PATH:=$(KERNDIR)/../../host-cross/bin:$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) + +WRS_SYSROOT_PATH := $(WRLINUX_GNU_PATH)/../lib/gcc/mips-wrs-linux-gnu/4.1.2/include + +export TOOLCHAIN_BIN_DIR WIND_LIC_PROXY +endif + +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (2.6.21.7, $(KERN_VER)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips_4KC- +endif + +override PATH := /tools/eldk/4.1/usr/bin:$(PATH) +KERNDIR ?= /projects/ntsw-tools/linux/eldk/jag-ntswics-eldk/linux-2.6.21.7 +endif +endif + + + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=1 -DSYS_BE_OTHER=0 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"JAG_BCM4704\" + +ARCH = mips +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +ifeq (ELDK,$(BUILD_PLATFORM)) +KFLAG_INCLD = /tools/eldk/4.1/usr/lib/gcc/mips-linux/4.0.0/include/ +endif + +ifeq (1.4,$(WRS_LINUX_VERSION)) +# From linux/arch/mips/Makefile + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -Wall -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -g -G 0 -mno-abicalls -fno-pic -pipe -march=mips32 -Wa,-mips32 -Wa,--trap -funit-at-a-time -mlong-calls -Wundef -finline-limit=100000 -mabi=32 +endif + +#-Wdeclaration-after-statement -Wstrict-prototypes +else + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -nostdinc -isystem $(WRS_SYSROOT_PATH) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/autoconf.h -I$(KERNDIR)/arch/mips -I$(KERNDIR)/arch/mips -I$(KERNDIR)/arch/mips/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -ffreestanding -march=mips32 -Wa,-mips32 -Wa,--trap -Iinclude/asm-mips/mach-bcm947xx -Iinclude/asm-mips/mach-generic -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mlong-calls +endif + +endif +endif + +ifeq (ELDK,$(BUILD_PLATFORM)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/autoconf.h -I$(KERNDIR)/arch/mips -I$(KERNDIR)/arch/mips -I$(KERNDIR)/arch/mips/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -ffreestanding -march=mips32 -Wa,-mips32 -Wa,--trap -Iinclude/asm-mips/mach-bcm947xx -Iinclude/asm-mips/mach-generic -fomit-frame-pointer -g -Wdeclaration-after-statement -mlong-calls +endif + +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif + +ifneq (,$(findstring TCL,$(FEATURE_LIST))) +LINK_STATIC=0 +export LINK_STATIC +endif + + + + diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel new file mode 100644 index 000000000000..7cbf8451f91e --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel @@ -0,0 +1,112 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-kernel,v 1.27 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Configuration Flags + +# Filter out features that cannot or should not be supported in kernel mode +_FEATURE_EXCLUDE_LIST += EDITLINE TCL OOB_RCPU CINT APIMODE DUNE_UI C_UNIT +FEATURE_EXCLUDE_LIST = $(sort $(_FEATURE_EXCLUDE_LIST)) +# Tools + +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +LD = $(CROSS_COMPILE)ld +AR = $(CROSS_COMPILE)ar +ARFLAGS = -rc +STRIP = $(CROSS_COMPILE)strip +RANLIB = $(CROSS_COMPILE)ranlib +OBJCOPY = $(CROSS_COMPILE)objcopy + +# Handle differences between gcc 2.x and gcc 3.x +gcc-tune-flag = $(shell if ${CC} -dumpspecs | grep mcpu >/dev/null; then echo cpu; else echo tune; fi) + +# Configuration Variables + +# OSType Defines: This defines the type of RTOS or microkernel which you +# are compiling the SAL (and its associated driver) for. New platforms +# can be created by porting the routines (system.c) to your platform and +# adding the define in this Makefile. + +OSTYPE = LINUX + +# +# ORIGIN is used to Optionally select different CFLAGS. It is used to import +# source from other vendors. If SOURCE=Broadcom, then the BCM_ flags are added +# to those passed to the compiler. If SOURCE != Broadcom, BCM_ flags are NOT +# added. +# +# Default specifies Broadcom +# +ifndef ORIGIN + ORIGIN = Broadcom +endif + +# +# STD_{C|CPP|CXX}FLAGS - Standard flags used by ALL compilations +# BCM_{C|CPP|CXX}FLAGS - Flags used for Broadcom source files +# OPT_{C|CPP|CXX}FLAGS - Defined in local make files BEFORE inclusion of +# this Makefile, to define local "Extra" flags. +# + +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) + +CFGFLAGS += -DNO_FILEIO -DNO_CTRL_C -DNO_MEMTUNE + +CFGFLAGS += -D$(OSTYPE) + +# No user sal for the linux kernel +# NO_SAL_APPL=1 + +STD_CFLAGS = $(KFLAGS) $(CFGFLAGS) + + +STD_CPPFLAGS = ${STD_CFLAGS} +STD_CXXFLAGS = ${STD_CFLAGS} + +BCM_CFLAGS = -Wall -Werror +BCM_CPPFLAGS = ${BCM_CFLAGS} +BCM_CXXFLAGS = ${BCM_CFLAGS} + +ifeq (${ORIGIN}, Broadcom) + CFLAGS += ${STD_CFLAGS} ${BCM_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${BCM_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${BCM_CXXFLAGS} ${OPT_CXXFLAGS} +else + CFLAGS += ${STD_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${OPT_CXXFLAGS} +endif + +# +# Ignore pedantic flag for kernel modules +# +ifdef DEBUG_PEDANTIC +DEBUG_PEDANTIC = FALSE +endif + +# +# DEPEND is used as a command to generate the list of dependencies. +# The format of the output must be +# "file.o : file.c a/b/c.h d/e/f.h ...", +# if it is on multiple lines, each line must end in a backslash. +# The output MUST be on standard out. +# +DEPEND = ${CC} -M $(CFLAGS) $< diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-2_6 new file mode 100644 index 000000000000..559f2ae5e5e5 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-2_6 @@ -0,0 +1,148 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-kernel-2_6,v 1.40 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Configuration Flags + +# Filter out features that cannot or should not be supported in kernel mode + +_FEATURE_EXCLUDE_LIST += EDITLINE TCL OOB_RCPU CINT APIMODE DUNE_UI C_UNIT +FEATURE_EXCLUDE_LIST = $(sort $(_FEATURE_EXCLUDE_LIST)) + +# Tools + +# Conditionally Replaces DEFAULT var +ifeq ($(origin CC),default) +CC = $(LSRUN) $(CROSS_COMPILE)gcc +endif + +ifeq ($(origin CXX),default) +CXX = $(CROSS_COMPILE)g++ +endif + +ifeq ($(origin LD),default) +LD = $(CROSS_COMPILE)ld +endif + +ifeq ($(origin AR),default) +AR = $(CROSS_COMPILE)ar +endif + +ifeq ($(origin AS),default) +AS = $(CROSS_COMPILE)as +endif + +ifeq ($(origin ARFLAGS),default) + ARFLAGS = -rc +endif + +STRIP = $(CROSS_COMPILE)strip +RANLIB = $(CROSS_COMPILE)ranlib +OBJCOPY = $(CROSS_COMPILE)objcopy +NM = $(CROSS_COMPILE)nm + +# Handle differences between gcc 2.x and gcc 3.x +gcc-tune-flag = $(shell if ${CC} -dumpspecs | grep mcpu >/dev/null; then echo cpu; else echo tune; fi) + +# Configuration Variables + +# OSType Defines: This defines the type of RTOS or microkernel which you +# are compiling the SAL (and its associated driver) for. New platforms +# can be created by porting the routines (system.c) to your platform and +# adding the define in this Makefile. + +OSTYPE = LINUX + +# +# ORIGIN is used to Optionally select different CFLAGS. It is used to import +# source from other vendors. If SOURCE=Broadcom, then the BCM_ flags are added +# to those passed to the compiler. If SOURCE != Broadcom, BCM_ flags are NOT +# added. +# +# Default specifies Broadcom +# +ifndef ORIGIN + ORIGIN = Broadcom +endif + +# +# STD_{C|CPP|CXX}FLAGS - Standard flags used by ALL compilations +# BCM_{C|CPP|CXX}FLAGS - Flags used for Broadcom source files +# OPT_{C|CPP|CXX}FLAGS - Defined in local make files BEFORE inclusion of +# this Makefile, to define local "Extra" flags. +# + +ifdef IPROC_BUILD +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) \ + -I$(KERNDIR)/arch/$(ARCH) +else +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) \ + -I$(LINUX_INCLUDE)/asm/gcc \ + -I$(LINUX_INCLUDE)/asm/mach-generic \ + -I$(KERNDIR)/arch/$(ARCH) +endif + +CFGFLAGS += -DNO_FILEIO -DNO_CTRL_C -DNO_MEMTUNE + +CFGFLAGS += -D$(OSTYPE) + +# No user sal for the linux kernel +# NO_SAL_APPL=1 + +STD_CFLAGS = $(KFLAGS) $(CFGFLAGS) + + +STD_CPPFLAGS = ${STD_CFLAGS} +STD_CXXFLAGS = ${STD_CFLAGS} + +ifndef BCM_CFLAGS +BCM_CFLAGS = -Wall -Werror +endif + +BCM_CPPFLAGS = ${BCM_CFLAGS} +BCM_CXXFLAGS = ${BCM_CFLAGS} + +ifeq (${ORIGIN}, Broadcom) + CFLAGS += ${STD_CFLAGS} ${BCM_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${BCM_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${BCM_CXXFLAGS} ${OPT_CXXFLAGS} +else + CFLAGS += ${STD_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${OPT_CXXFLAGS} +endif + +# +# Ignore pedantic flag for kernel modules +# +ifdef DEBUG_PEDANTIC +DEBUG_PEDANTIC = FALSE +endif + +# +# DEPEND is used as a command to generate the list of dependencies. +# The format of the output must be +# "file.o : file.c a/b/c.h d/e/f.h ...", +# if it is on multiple lines, each line must end in a backslash. +# The output MUST be on standard out. +# +DEPEND = ${CC} -M $(CFLAGS) $< diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-3_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-3_6 new file mode 100644 index 000000000000..0d54c4474fc8 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-3_6 @@ -0,0 +1,148 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-kernel-3_6,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Configuration Flags + +# Filter out features that cannot or should not be supported in kernel mode + +_FEATURE_EXCLUDE_LIST += EDITLINE TCL OOB_RCPU CINT APIMODE DUNE_UI +FEATURE_EXCLUDE_LIST = $(sort $(_FEATURE_EXCLUDE_LIST)) + +# Tools + +# Conditionally Replaces DEFAULT var +ifeq ($(origin CC),default) +CC = $(LSRUN) $(CROSS_COMPILE)gcc +endif + +ifeq ($(origin CXX),default) +CXX = $(CROSS_COMPILE)g++ +endif + +ifeq ($(origin LD),default) +LD = $(CROSS_COMPILE)ld +endif + +ifeq ($(origin AR),default) +AR = $(CROSS_COMPILE)ar +endif + +ifeq ($(origin AS),default) +AS = $(CROSS_COMPILE)as +endif + +ifeq ($(origin ARFLAGS),default) + ARFLAGS = -rc +endif + +STRIP = $(CROSS_COMPILE)strip +RANLIB = $(CROSS_COMPILE)ranlib +OBJCOPY = $(CROSS_COMPILE)objcopy +NM = $(CROSS_COMPILE)nm + +# Handle differences between gcc 2.x and gcc 3.x +gcc-tune-flag = $(shell if ${CC} -dumpspecs | grep mcpu >/dev/null; then echo cpu; else echo tune; fi) + +# Configuration Variables + +# OSType Defines: This defines the type of RTOS or microkernel which you +# are compiling the SAL (and its associated driver) for. New platforms +# can be created by porting the routines (system.c) to your platform and +# adding the define in this Makefile. + +OSTYPE = LINUX + +# +# ORIGIN is used to Optionally select different CFLAGS. It is used to import +# source from other vendors. If SOURCE=Broadcom, then the BCM_ flags are added +# to those passed to the compiler. If SOURCE != Broadcom, BCM_ flags are NOT +# added. +# +# Default specifies Broadcom +# +ifndef ORIGIN + ORIGIN = Broadcom +endif + +# +# STD_{C|CPP|CXX}FLAGS - Standard flags used by ALL compilations +# BCM_{C|CPP|CXX}FLAGS - Flags used for Broadcom source files +# OPT_{C|CPP|CXX}FLAGS - Defined in local make files BEFORE inclusion of +# this Makefile, to define local "Extra" flags. +# + +ifdef IPROC_BUILD +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) \ + -I$(KERNDIR)/arch/$(ARCH) +else +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) \ + -I$(LINUX_INCLUDE)/asm/gcc \ + -I$(LINUX_INCLUDE)/asm/mach-generic \ + -I$(KERNDIR)/arch/$(ARCH) +endif + +CFGFLAGS += -DNO_FILEIO -DNO_CTRL_C -DNO_MEMTUNE + +CFGFLAGS += -D$(OSTYPE) + +# No user sal for the linux kernel +# NO_SAL_APPL=1 + +STD_CFLAGS = $(KFLAGS) $(CFGFLAGS) + + +STD_CPPFLAGS = ${STD_CFLAGS} +STD_CXXFLAGS = ${STD_CFLAGS} + +ifndef BCM_CFLAGS +BCM_CFLAGS = -Wall -Werror +endif + +BCM_CPPFLAGS = ${BCM_CFLAGS} +BCM_CXXFLAGS = ${BCM_CFLAGS} + +ifeq (${ORIGIN}, Broadcom) + CFLAGS += ${STD_CFLAGS} ${BCM_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${BCM_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${BCM_CXXFLAGS} ${OPT_CXXFLAGS} +else + CFLAGS += ${STD_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${OPT_CXXFLAGS} +endif + +# +# Ignore pedantic flag for kernel modules +# +ifdef DEBUG_PEDANTIC +DEBUG_PEDANTIC = FALSE +endif + +# +# DEPEND is used as a command to generate the list of dependencies. +# The format of the output must be +# "file.o : file.c a/b/c.h d/e/f.h ...", +# if it is on multiple lines, each line must end in a backslash. +# The output MUST be on standard out. +# +DEPEND = ${CC} -M $(CFLAGS) $< diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-4_4 b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-4_4 new file mode 100644 index 000000000000..0e8e22e1b32d --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-4_4 @@ -0,0 +1,157 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-kernel-2_6,v 1.40 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Configuration Flags + +# Filter out features that cannot or should not be supported in kernel mode + +_FEATURE_EXCLUDE_LIST += EDITLINE TCL OOB_RCPU CINT APIMODE DUNE_UI C_UNIT +FEATURE_EXCLUDE_LIST = $(sort $(_FEATURE_EXCLUDE_LIST)) + +# Tools + +# Conditionally Replaces DEFAULT var +ifeq ($(origin CC),default) +CC = $(LSRUN) $(CROSS_COMPILE)gcc +endif + +ifeq ($(origin CXX),default) +CXX = $(CROSS_COMPILE)g++ +endif + +ifeq ($(origin LD),default) +LD = $(CROSS_COMPILE)ld +endif + +ifeq ($(origin AR),default) +AR = $(CROSS_COMPILE)ar +endif + +ifeq ($(origin AS),default) +AS = $(CROSS_COMPILE)as +endif + +ifeq ($(origin ARFLAGS),default) + ARFLAGS = -rc +endif + +STRIP = $(CROSS_COMPILE)strip +RANLIB = $(CROSS_COMPILE)ranlib +OBJCOPY = $(CROSS_COMPILE)objcopy +NM = $(CROSS_COMPILE)nm + +# Handle differences between gcc 2.x and gcc 3.x +gcc-tune-flag = $(shell if ${CC} -dumpspecs | grep mcpu >/dev/null; then echo cpu; else echo tune; fi) + +# Configuration Variables + +# OSType Defines: This defines the type of RTOS or microkernel which you +# are compiling the SAL (and its associated driver) for. New platforms +# can be created by porting the routines (system.c) to your platform and +# adding the define in this Makefile. +OSTYPE = LINUX + +# +# ORIGIN is used to Optionally select different CFLAGS. It is used to import +# source from other vendors. If SOURCE=Broadcom, then the BCM_ flags are added +# to those passed to the compiler. If SOURCE != Broadcom, BCM_ flags are NOT +# added. +# +# Default specifies Broadcom +# +ifndef ORIGIN + ORIGIN = Broadcom +endif + +# +# STD_{C|CPP|CXX}FLAGS - Standard flags used by ALL compilations +# BCM_{C|CPP|CXX}FLAGS - Flags used for Broadcom source files +# OPT_{C|CPP|CXX}FLAGS - Defined in local make files BEFORE inclusion of +# this Makefile, to define local "Extra" flags. +# +ifdef IPROC_BUILD +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) \ + -I$(LINUX_INCLUDE)/uapi \ + -I$(LINUX_INCLUDE)/generated/uapi \ + -I$(KERNDIR)/arch/$(ARCH) \ + -I$(KERNDIR)/arch/$(ARCH)/include/uapi \ + -I$(KERNDIR)/arch/$(ARCH)/include/generated \ + -I$(KERNDIR)/arch/$(ARCH)/include/generated/uapi +else +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) \ + -I$(LINUX_INCLUDE)/asm/gcc \ + -I$(LINUX_INCLUDE)/asm/mach-generic \ + -I$(LINUX_INCLUDE)/uapi \ + -I$(LINUX_INCLUDE)/generated/uapi \ + -I$(KERNDIR)/arch/$(ARCH) \ + -I$(KERNDIR)/arch/$(ARCH)/include/uapi \ + -I$(KERNDIR)/arch/$(ARCH)/include/generated \ + -I$(KERNDIR)/arch/$(ARCH)/include/generated/uapi +endif + +CFGFLAGS += -DNO_FILEIO -DNO_CTRL_C -DNO_MEMTUNE + +CFGFLAGS += -D$(OSTYPE) + +# No user sal for the linux kernel +# NO_SAL_APPL=1 + +STD_CFLAGS = $(KFLAGS) $(CFGFLAGS) + + +STD_CPPFLAGS = ${STD_CFLAGS} +STD_CXXFLAGS = ${STD_CFLAGS} + +ifndef BCM_CFLAGS +BCM_CFLAGS = -Wall -Werror +endif + +BCM_CPPFLAGS = ${BCM_CFLAGS} +BCM_CXXFLAGS = ${BCM_CFLAGS} + +ifeq (${ORIGIN}, Broadcom) + CFLAGS += ${STD_CFLAGS} ${BCM_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${BCM_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${BCM_CXXFLAGS} ${OPT_CXXFLAGS} +else + CFLAGS += ${STD_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${OPT_CXXFLAGS} +endif + +# +# Ignore pedantic flag for kernel modules +# +ifdef DEBUG_PEDANTIC +DEBUG_PEDANTIC = FALSE +endif + +# +# DEPEND is used as a command to generate the list of dependencies. +# The format of the output must be +# "file.o : file.c a/b/c.h d/e/f.h ...", +# if it is on multiple lines, each line must end in a backslash. +# The output MUST be on standard out. +# +DEPEND = ${CC} -M $(CFLAGS) $< + diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule b/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule new file mode 100644 index 000000000000..3ad11d169c64 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule @@ -0,0 +1,81 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-kmodule-3_6,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2006 Broadcom Corp. +# All Rights Reserved.$ + +# Due to the extensive use of driver libraries, the SDK usually builds +# kernel modules from a precompiled object. To avoid various warnings +# and conflicts, the pre-compiled object must be named differently +# from the target module, and the object file itself should be +# appended with "_shipped". + +# If a module exports any symbols, then the exporting source file must +# be compiled within the kernel source tree for correct generation of +# module symbol versions. The symbol source file should be passed to +# this Makefile via the MODULE_SYM variable. + +MODULE := $(MOD_NAME).o +KMODULE := $(MOD_NAME).ko +PRE_COMPILED_OBJ := obj_$(MOD_NAME).o + +obj-m := $(MODULE) +$(MOD_NAME)-y := $(MODULE_SYM) $(PRE_COMPILED_OBJ) + + +ifeq (,$(CROSS_COMPILE)) + +export CROSS_COMPILE + +endif + +SAVE_CFLAGS := ${CFLAGS} + +include $(SDK)/make/Make.config + +PWD := $(shell pwd) + +ifneq ($(ARCH),) +# ELDK does not seem to `automatically' define ARCH where other gccs may +A := ARCH=$(ARCH) +export ARCH +endif + +# Provide an option in case kernel was built in separate directory +KERNBLDDIR ?= $(KERNDIR) + +# Standard SDK include path for building source files that export +# kernel symbols. + +override EXTRA_CFLAGS = -I${SDK}/include -I${SDK}/systems/linux/kernel/modules/include -I${SDK}/systems/bde/linux/include + +# The precopiled object needs a dummy command file to avoid warnings +# from the Kbuild scripts (modpost stage). +# Kernels before 2.6.17 do not support external module symbols files, +# so we create a dummy to prevent build failures. + +$(KMODULE): + rm -f *.o *.ko .*.cmd + rm -fr .tmp_versions + ln -s $(LIBDIR)/$(MODULE) $(PRE_COMPILED_OBJ)_shipped + echo "suppress warning" > .$(PRE_COMPILED_OBJ).cmd + $(MAKE) -C $(KERNBLDDIR) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules + if [ ! -f Module.symvers ]; then echo "old kernel (pre-2.6.17)" > Module.symvers; fi + cp -f $(KMODULE) $(LIBDIR) + rm -f $(PRE_COMPILED_OBJ)_shipped + +EXTRA_CFLAGS = $(CFLAGS) +CFLAGS := ${SAVE_CFLAGS} diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx-2_6 new file mode 100644 index 000000000000..785619f31fd4 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx-2_6 @@ -0,0 +1,56 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-nsx-2_6,v 1.9 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Look for custom tools +ifneq (,$(MIPS_TOOLS_DIR)) +override PATH := $(MIPS_TOOLS_DIR):$(PATH) +endif +ifneq (,$(MIPS_CROSS_COMPILE)) +override CROSS_COMPILE := $(MIPS_CROSS_COMPILE) +endif + +# Default tools +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips2_fp_be- +override PATH := $(PATH):/projects/ntsw-tools/linux/mvista/mvista-4.0/pro/devkit/mips/mips2_fp_be/bin +endif + +# Default Linux Kernel directory +ifeq (,$(KERNDIR)) +KERNDIR := /projects/ntsw-tools/linux/mvista/mvista-4.0-nsx/linux-2.6.10_dev +endif +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"NSX_BCM1125\" + +# From linux/arch/mips/Makefile + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -O2 -fomit-frame-pointer -fno-strict-aliasing -G 0 -mno-abicalls -fno-pic -mips64 -mtune=sb1 -Wa,--trap -pipe -mlong-calls +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx64 b/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx64 new file mode 100644 index 000000000000..c4f71995be52 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx64 @@ -0,0 +1,54 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-nsx64,v 1.9 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Look for custom tools +ifneq (,$(MIPS_TOOLS_DIR)) +override PATH := $(MIPS_TOOLS_DIR):$(PATH) +endif +ifneq (,$(MIPS_CROSS_COMPILE)) +override CROSS_COMPILE := $(MIPS_CROSS_COMPILE) +endif + +# Default tools +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips64_fp_be- +override PATH := $(PATH):/projects/ntsw-tools/linux/mvista/mips64_be_tools-3.1/bin +endif + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE = /projects/ntsw-tools/linux/headers/mvl-3.1-nsx64/include +endif + +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) -Wa,-xgot -mips64 -mabi=64 -fno-strict-aliasing -DPTRS_ARE_64BITS -DLONGS_ARE_64BITS +CFGFLAGS += -DBCM_PLATFORM_STRING=\"NSX_BCM1125\" + +# From linux/arch/mips/Makefile + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -O2 -fomit-frame-pointer -fno-strict-aliasing -G 0 -mno-abicalls -fno-pic -mips64 -mabi=64 -mtune=sb1 -Wa,--trap -pipe -mlong-calls +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel +endif + +MODULE_LDFLAGS += -m elf64btsmip diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx_wrl-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx_wrl-2_6 new file mode 100644 index 000000000000..7b549038fd24 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx_wrl-2_6 @@ -0,0 +1,127 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-nsx_wrl-2_6,v 1.15 Broadcom SDK $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ + +ifeq (,$(WRS_LINUX_VERSION)) +WRS_LINUX_VERSION=2.0 +endif + +# Look for custom tools +ifneq (,$(MIPS_TOOLS_DIR)) +ifneq (,$(MIPS_CROSS_COMPILE)) +override PATH := $(MIPS_TOOLS_DIR):$(PATH) +override CROSS_COMPILE := $(MIPS_CROSS_COMPILE) +endif +endif + +# Default Linux Kernel directory +ifeq (,$(KERNDIR)) + +ifeq (1.4,$(WRS_LINUX_VERSION)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips-wrs-linux-gnu- +endif + +KERNDIR := /projects/ntsw-tools/linux/wrslinux_1.4/broadcom_bcm91125cpci_32_be_glibc_std/build/linux-2.6.14-cgl + +export WIND_LIC_PROXY = /projects/ntsw-tools/wrs/wrs_linux/GPP_LE_1.4_PPR/setup/x86-linux2/bin +override PATH := /projects/ntsw-tools/wrs/wrs_linux/GPP_LE_1.4_PPR/gnu/3.4.4-wrlinux-1.4/x86-linux2/bin:$(PATH) +else + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips-wrs-linux-gnu-mips-glibc_std- +endif + +KERNDIR:= /projects/ntsw-tools/linux/wrslinux_2.0/nsx/glibc_std/build/linux-2.6.21-standard + +WRLINUX_BASE=/tools/windriver/linux_ed/2.0_GA/Linux + +TOOLCHAIN_BIN_DIR=$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin +WIND_LIC_PROXY=$(WRLINUX_BASE)/setup/x86-linux2/bin + +WRLINUX_GNU_PATH=$(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2/bin +override PATH:=$(KERNDIR)/../../host-cross/bin:$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) + +WRS_SYSROOT_PATH := $(WRLINUX_GNU_PATH)/../lib/gcc/mips-wrs-linux-gnu/4.1.2/include + +export TOOLCHAIN_BIN_DIR WIND_LIC_PROXY + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +endif +endif +endif + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"NSX_BCM1125\" + +ARCH = mips +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +ifeq (1.4,$(WRS_LINUX_VERSION)) +# From Linux Kbuild output + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -Iinclude -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -g -G 0 -mno-abicalls -fno-pic -pipe -finline-limit=100000 -mabi=32 -march=sb1 -Wa,-32 -Wa,-march=sb1 -Wa,-mips64 -Wa,--trap -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL -mlong-calls +#-Wdeclaration-after-statement +endif + +else + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -nostdinc -isystem $(WRS_SYSROOT_PATH) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -ffreestanding -march=sb1 -Wa,--trap -Iinclude/asm-mips/mach-sibyte -Iinclude/asm-mips/mach-generic -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mlong-calls +endif + +endif +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif + + +ifneq (,$(findstring TCL,$(FEATURE_LIST))) +LINK_STATIC=0 +export LINK_STATIC +endif + + diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-raptor b/platform/broadcom/saibcm-modules/make/Makefile.linux-raptor new file mode 100644 index 000000000000..80c51e782bea --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-raptor @@ -0,0 +1,53 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-raptor,v 1.6 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Look for custom tools +ifneq (,$(MIPS_TOOLS_DIR)) +override PATH := $(MIPS_TOOLS_DIR):$(PATH) +endif +ifneq (,$(MIPS_CROSS_COMPILE)) +override CROSS_COMPILE := $(MIPS_CROSS_COMPILE) +endif + +# Default tools +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips_fp_be- +override PATH := $(PATH):/projects/ntsw-tools/linux/mvista/mvista-3.1/pro/devkit/mips/fp_be/bin +endif + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE = /projects/ntsw-tools/linux/headers/mvl-3.1-raptor/include +endif + +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=1 -DSYS_BE_OTHER=0 -DBCM_ICS +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"Raptor_BCM56218\" + + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel +endif + +# From linux/arch/mips/Makefile + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -m$(gcc-tune-flag)=r4600 -mips2 -Wa,--trap -mlong-calls +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-raptor-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-raptor-2_6 new file mode 100644 index 000000000000..0bebdf9564c6 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-raptor-2_6 @@ -0,0 +1,172 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-raptor-2_6,v 1.21 Broadcom SDK $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ + + +# User must select one platform from below.By default WR_LINUX is selected. . +ifeq (,$(BUILD_PLATFORM)) +#BUILD_PLATFORM=ELDK +BUILD_PLATFORM=WR_LINUX +endif + + +# Specify the KERNEL VERSION you want to use for building SDK. +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (,$(KERN_VER)) +KERN_VER=2.6.21.7 +endif +endif + +# Specify the Windriver Linux version here.For example '2.0' as shown below. +ifeq (WR_LINUX,$(BUILD_PLATFORM)) +ifeq (,$(WRS_LINUX_VERSION)) +WRS_LINUX_VERSION=2.0 +endif +endif + + +# Default Linux Kernel directory +ifeq (WR_LINUX,$(BUILD_PLATFORM)) +ifeq (1.4,$(WRS_LINUX_VERSION)) + +KERNDIR ?= /projects/ntsw-tools/linux/wrslinux_1.4/broadcom_bcm95621x_be/build/linux-2.6.14-small + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips-wrs-linux-gnu- +endif + +export WIND_LIC_PROXY = /projects/ntsw-tools/wrs/wrs_linux/GPP_LE_1.4_PPR/setup/x86-linux2/bin + +override PATH := /projects/ntsw-tools/wrs/wrs_linux/GPP_LE_1.4_PPR/gnu/3.4.4-wrlinux-1.4/x86-linux2/bin:$(PATH) +endif + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips-wrs-linux-gnu-mips_softfp-glibc_std- +endif + +KERNDIR ?= /projects/ntsw-tools/linux/wrslinux_2.0/ntswics/glibc_std/build/linux-2.6.21-standard +override PATH:=$(KERNDIR)/../../host-cross/bin:$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) + +endif + +WRLINUX_BASE=/tools/windriver/linux_ed/2.0_GA/Linux + +TOOLCHAIN_BIN_DIR=$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin +WIND_LIC_PROXY=$(WRLINUX_BASE)/setup/x86-linux2/bin + +WRLINUX_GNU_PATH=$(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2/bin + +override PATH:=$(KERNDIR)/../../host-cross/bin:$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) + +WRS_SYSROOT_PATH := $(WRLINUX_GNU_PATH)/../lib/gcc/mips-wrs-linux-gnu/4.1.2/include + +export TOOLCHAIN_BIN_DIR WIND_LIC_PROXY + +endif + +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (2.6.21.7, $(KERN_VER)) +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips_4KC- +endif +override PATH := /tools/eldk/4.1/usr/bin:$(PATH) +KERNDIR ?= /projects/ntsw-tools/linux/eldk/raptor_eldk/linux-2.6.21.7 +endif +endif + + + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=1 -DSYS_BE_OTHER=0 -DBCM_ICS +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) -DRAPTOR +CFGFLAGS += -DBCM_PLATFORM_STRING=\"Raptor_BCM56218\" + + +ARCH = mips +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + + +ifeq (ELDK,$(BUILD_PLATFORM)) +KFLAG_INCLD = /tools/eldk/4.1/usr/lib/gcc/mips-linux/4.0.0/include +endif + + +# From linux/arch/mips/Makefile +ifeq (WR_LINUX,$(BUILD_PLATFORM)) +ifeq (1.4,$(WRS_LINUX_VERSION)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -Wall -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -g -G 0 -mno-abicalls -fno-pic -pipe -march=mips32 -Wa,-mips32 -Wa,--trap -funit-at-a-time -mlong-calls -Wundef -finline-limit=100000 -mabi=32 +endif + +endif + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -nostdinc -isystem $(WRS_SYSROOT_PATH) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/autoconf.h -I$(KERNDIR)/arch/mips/mach-bcm56218 -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -ffreestanding -march=mips32 -Wa,-mips32 -Wa,--trap -Iinclude/asm-mips/mach-bcm56218 -Iinclude/asm-mips/mach-generic -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mlong-calls +endif + +endif +endif + +ifeq (ELDK,$(BUILD_PLATFORM)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/autoconf.h -I$(KERNDIR)/arch/mips/mach-bcm56218 -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -ffreestanding -march=mips32 -Wa,-mips32 -Wa,--trap -Iinclude/asm-mips/mach-bcm56218 -Iinclude/asm-mips/mach-generic -fomit-frame-pointer -g -Wdeclaration-after-statement -mlong-calls +endif + + +endif + + + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif + +ifneq (,$(findstring TCL,$(FEATURE_LIST))) +LINK_STATIC=0 +export LINK_STATIC +endif + + + + + diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 new file mode 100644 index 000000000000..07af2afcc93b --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 @@ -0,0 +1,44 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-x86-common-2_6,v 1.13 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=0 +ENDIAN = LE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"X86\" +ifeq (,$(findstring -DSAL_BDE_DMA_MEM_DEFAULT,$(CFGFLAGS))) +CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=32 +endif + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ +-D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +ifneq ($(targetplat),user) +# By default we exclude -Werror from x86 kernel builds +BCM_CFLAGS = -Wall +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 new file mode 100644 index 000000000000..ab342c12d210 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 @@ -0,0 +1,51 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-x86-generic-common-2_6,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2008 Broadcom Corp. +# All Rights Reserved.$ + +# Default kernel source directory +ifeq (,$(KERNDIR)) +KERNDIR := /lib/modules/$(shell uname -r)/build +export KERNDIR +endif + +# Default architecture +ifeq (,$(ARCH)) +ARCH = $(shell uname -p) +ifneq (x86_64,$(ARCH)) +ARCH = i386 +endif +endif + +# Noisy kernel build +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE KERNDIR + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +# autoconf.h was moved in later kernels +AUTOCONF = $(KERNDIR)/include/generated/autoconf.h +ifeq (,$(shell ls $(AUTOCONF) 2>/dev/null)) +AUTOCONF = $(KERNDIR)/include/linux/autoconf.h +endif + +# gcc system include path +SYSINC = $(shell gcc -print-search-dirs | grep install | cut -c 10-)include diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 new file mode 100644 index 000000000000..bb0bbea536a3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 @@ -0,0 +1,46 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-x86-smp_generic_64-2_6,v 1.5 Broadcom SDK $ +# $Copyright: (c) 2008 Broadcom Corp. +# All Rights Reserved.$ + +CFGFLAGS += -DLONGS_ARE_64BITS +CFGFLAGS += -DPTRS_ARE_64BITS +CFGFLAGS += -DPHYS_ADDRS_ARE_64BITS +CFGFLAGS += -DSAL_SPL_LOCK_ON_IRQ + +include ${SDK}/make/Makefile.linux-x86-generic-common-2_6 + +ifeq (,$(KFLAGS)) +KFLAGS := -nostdinc -isystem $(SYSINC) -I$(KERNDIR)/include -I$(KERNDIR)/arch/x86/include -include $(AUTOCONF) -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -fno-stack-protector -fomit-frame-pointer -g -Wdeclaration-after-statement -Wno-pointer-sign +endif + +ifeq ($(LINUX_MAKE_SHARED_LIB), 1) +KFLAGS += -fPIC -mcmodel=small +else +KFLAGS += -fno-pie -mcmodel=kernel +endif + +LINUX_UAPI = $(LINUX_INCLUDE)/uapi +KFLAGS += -I$(LINUX_INCLUDE)/uapi -I$(LINUX_INCLUDE)/generated/uapi -I$(KERNDIR)/arch/x86/include/generated -I$(KERNDIR)/arch/x86/include/uapi -I$(KERNDIR)/arch/x86/include/generated/uapi + +ifeq (1,$(DEBIAN_LINUX_HEADER)) +KERNDIR_COMMON := $(subst amd64,common,$(KERNDIR)) +KFLAGS += -I$(KERNDIR_COMMON)/include -I$(KERNDIR_COMMON)/include/uapi -I$(KERNDIR_COMMON)/arch/x86/include -I$(KERNDIR_COMMON)/arch/x86/include/uapi +endif + +include ${SDK}/make/Makefile.linux-x86-common-2_6 + diff --git a/platform/broadcom/saibcm-modules/systemd/opennsl-modules-4.9.0-7-amd64.service b/platform/broadcom/saibcm-modules/systemd/opennsl-modules-4.9.0-7-amd64.service new file mode 100644 index 000000000000..12c5ae40db97 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systemd/opennsl-modules-4.9.0-7-amd64.service @@ -0,0 +1,13 @@ +[Unit] +Description=Opennsl kernel modules init +After=local-fs.target +Before=syncd.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/opennsl-modules-4.9.0-7-amd64 start +ExecStop=-/etc/init.d/opennsl-modules-4.9.0-7-amd64 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h new file mode 100644 index 000000000000..927201bc1fd8 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h @@ -0,0 +1,285 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/*********************************************************************** + * + * $Id: linux-bde.h,v 1.24 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + * + * Linux Broadcom Device Enumerators + * + * + * There are two Linux BDEs: + * + * 1. Linux Kernel BDE + * + * This is a kernel module implementing a BDE + * for the driver running as part of the kernel. + * + * It manages the devices through the linux PCI interfaces, + * and manages a chunk of contiguous, boot-time allocated + * DMA memory. This is all that is needed if the BCM driver + * is run as part of the kernel (in another module). + * + * 2. Linux User BDE + * + * This is a kernel module and userland library which implement + * a complete BDE for applications running in userland. + * + * The kernel module relies upon the real kernel bde, + * and allows a user space application (through the user library) + * to talk directly to the devices. It also virtualized the device + * interrupts, so the entire driver can be run as a userspace + * application. + * + * While this causes a significant degradation in performance, + * because the system runs as a user application, the development + * and debugging process is about a gillion times easier. + * After the core logic is debugged, it can be retargeted using + * only the kernel bde and run in the kernel. + * + * + **********************************************************************/ + +#ifndef __LINUX_BDE_H__ +#define __LINUX_BDE_H__ + +#include + +#include + + +/* + * Device Major Numbers + * + * The kernel and user bdes need unique major numbers + * on systems that do not use devfs. + * + * They are defined here, along with the module names, + * to document them if you need to mknod them (or open) them, + * and to keep them unique. + * + */ + +#include + +#ifdef __KERNEL__ +#include +/* Key stone and Raptor has 2.6.21 but don't have definition */ +#if defined(KEYSTONE) || defined(RAPTOR) +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21)) + #ifdef PHYS_ADDRS_ARE_64BITS + typedef u64 phys_addr_t; + #else + typedef u32 phys_addr_t; + #endif + #endif +#endif +#endif + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) +#define LINUX_BDE_DMA_DEVICE_SUPPORT +#endif + +#define LINUX_KERNEL_BDE_NAME "linux-kernel-bde" +#define LINUX_KERNEL_BDE_MAJOR 127 + +#define LINUX_USER_BDE_NAME "linux-user-bde" +#define LINUX_USER_BDE_MAJOR 126 + + +/* Max devices */ +/* 16 switch chips + 2 out-of-band Ethernet + 2 CPUs */ +#define LINUX_BDE_MAX_SWITCH_DEVICES 16 +#define LINUX_BDE_MAX_ETHER_DEVICES 2 +#define LINUX_BDE_MAX_CPU_DEVICES 2 +#define LINUX_BDE_MAX_DEVICES (LINUX_BDE_MAX_SWITCH_DEVICES + \ + LINUX_BDE_MAX_ETHER_DEVICES + \ + LINUX_BDE_MAX_CPU_DEVICES) + +/* + * PCI devices will be initialized by the Linux Kernel, + * regardless of architecture. + * + * You need only provide bus endian settings. + */ + +typedef struct linux_bde_bus_s { + int be_pio; + int be_packet; + int be_other; +} linux_bde_bus_t; + + + +/* Device state used for PCI hot swap case. */ +/* + * BDE_DEV_STATE_NORMAL : A device is probed normally. Or when the device + * resource has been updated after "CHANGED", the state will move back to + * "NORMAL". + */ +#define BDE_DEV_STATE_NORMAL (0) +/* + * BDE_DEV_STATE_REMOVED : A previous probed device was removed. + * We will avoid any device access while the device is in this state. + * The state will be moved to "CHANGED" if the device is re-inserted + * and re-probed. + */ +#define BDE_DEV_STATE_REMOVED (1) +/* + * BDE_DEV_STATE_CHANGED : The device is re-probed after having been removed. + * The resouces assigned to the device might have been changed after + * re-probing, so we need to re-initialize our resource database accordingly. + * The state will change to "NORMAL" when the resource have been updated. + */ +#define BDE_DEV_STATE_CHANGED (2) + +extern int linux_bde_create(linux_bde_bus_t* bus, ibde_t** bde); +extern int linux_bde_destroy(ibde_t* bde); +#ifdef BCM_INSTANCE_SUPPORT +extern int linux_bde_instance_attach(unsigned int dev_mask,unsigned int dma_size); +#endif + +#ifdef __KERNEL__ + +/* + * Backdoors provided by the kernel bde + * + */ + +/* + * The user bde needs to get cpu physical address for + * the userland code to mmap. + * And the second address is bus address, it is either + * identical to cpu physical address or another address + * (IOVA) translated by IOMMU. + */ +extern int lkbde_get_dma_info(phys_addr_t *cpu_pbase, phys_addr_t *dma_pbase, ssize_t *size); +extern uint32 lkbde_get_dev_phys(int d); +extern uint32 lkbde_get_dev_phys_hi(int d); + +/* + * Virtual device address needed by kernel space + * interrupt handler. + */ +extern void *lkbde_get_dev_virt(int d); + +/* + * The user bde needs to get some physical addresses for + * the userland code to mmap. The following functions + * supports multiple resources for a single device. + */ +extern int lkbde_get_dev_resource(int d, int rsrc, uint32 *flags, + uint32 *phys_lo, uint32 *phys_hi); + +/* + * Backdoor to retrieve OS device structure to be used for + * DMA operations. + */ +extern void *lkbde_get_dma_dev(int d); + +/* + * Backdoor to retrieve original hardware/OS device. + */ +extern void *lkbde_get_hw_dev(int d); + +/* + * Backdoor to retrieve number of switch devices probed. + */ +extern int lkbde_get_num_devices(int type); + +/* + * Retrive the device state from Kernel BDE. + * Used for KNET and User BDE for pci hot swap case. + */ +extern int lkbde_dev_state_get(int d, uint32 *state); +extern int lkbde_dev_state_set(int d, uint32 state); + +/* + * Retrive the mapping between emulated HW device and instance id + */ +extern int lkbde_dev_instid_get(int d, uint32 *instid); +extern int lkbde_dev_instid_set(int d, uint32 instid); + +/* + * Functions that allow an interrupt handler in user mode to + * coexist with interrupt handler in kernel module. + */ +extern int lkbde_irq_mask_set(int d, uint32 addr, uint32 mask, uint32 fmask); +extern int lkbde_irq_mask_get(int d, uint32 *mask, uint32 *fmask); + +#if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT)) +extern int lkbde_cpu_write(int d, uint32 addr, uint32 *buf); +extern int lkbde_cpu_read(int d, uint32 addr, uint32 *buf); +extern int lkbde_cpu_pci_register(int d); +#endif + +/* + * This flag must be OR'ed onto the device number when calling + * interrupt_connect/disconnect and irq_mask_set functions from + * a secondary device driver. + */ +#define LKBDE_ISR2_DEV 0x8000 +/* + * This flag should be OR'ed onto the device number when calling + * irq_mask_set functions from a secondary device driver if the + * mask register is iProc register. + */ +#define LKBDE_IPROC_REG 0x4000 + +#if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) +#include +#if defined(__DUNE_LINUX_BCM_CPU_PCIE__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#ifndef _SIMPLE_MEMORY_ALLOCATION_ +#define _SIMPLE_MEMORY_ALLOCATION_ 1 +#endif +#ifndef USE_LINUX_BDE_MMAP +#define USE_LINUX_BDE_MMAP 1 +#endif +#endif +#endif + +#if defined(IPROC_CMICD) && defined(CONFIG_CMA) +#ifndef _SIMPLE_MEMORY_ALLOCATION_ +#define _SIMPLE_MEMORY_ALLOCATION_ 1 +#endif +#endif + +/* Don't use _SIMPLE_MEMORY_ALLOCATION_ method for newer kernel than 3.10.0 */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) +#ifndef _SIMPLE_MEMORY_ALLOCATION_ +#define _SIMPLE_MEMORY_ALLOCATION_ 0 +#endif +#endif + +/* Allocation via dma_alloc_coherent is turned off by default */ +#ifndef _SIMPLE_MEMORY_ALLOCATION_ +#define _SIMPLE_MEMORY_ALLOCATION_ 9 /* compile in the allocation method, but do not use it by default */ +#endif + +/* By default we use our private mmap only if /dev/mem mmap has restrictions */ +#ifndef USE_LINUX_BDE_MMAP +#ifdef CONFIG_STRICT_DEVMEM +#define USE_LINUX_BDE_MMAP 1 +#else +#define USE_LINUX_BDE_MMAP 0 +#endif +#endif + +#endif /* __KERNEL__ */ + +#endif /* __LINUX_BDE_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h new file mode 100644 index 000000000000..bfbbceb2d8e7 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/*********************************************************************** + * + * $Id: linux_dma.h,v 1.24 Broadcom SDK $ + * $Copyright: (c) 2016 Broadcom Corp. + * All Rights Reserved.$ + * + **********************************************************************/ + +#ifndef __LINUX_DMA_H__ +#define __LINUX_DMA_H__ + +#include + +#ifdef __KERNEL__ + +#ifdef SAL_BDE_XLP +#define KMALLOC(size, flags) __kmalloc(size, flags) +#else +#define KMALLOC(size, flags) kmalloc(size, flags) +#endif + +#if defined(CONFIG_IDT_79EB334) || defined(CONFIG_BCM4702) +/* ioremap is broken in kernel */ +#define IOREMAP(addr, size) ((void *)KSEG1ADDR(addr)) +#else +#define IOREMAP(addr, size) ioremap_nocache(addr, size) +#endif + +#if defined (__mips__) +#if defined(CONFIG_NONCOHERENT_IO) || defined(CONFIG_DMA_NONCOHERENT) +/* Use flush/invalidate for cached memory */ +#define NONCOHERENT_DMA_MEMORY +/* Remap virtual DMA addresses to non-cached segment */ +#define REMAP_DMA_NONCACHED +#endif /* CONFIG_NONCOHERENT_IO || CONFIG_DMA_NONCOHERENT */ +#endif /* __mips__ */ + +#if defined(BCM958525) && (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,5)) +#define REMAP_DMA_NONCACHED +#endif + +#ifndef DMA_BIT_MASK +#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) +#endif + +extern void _dma_init(int robo_switch, int dev_index); +extern int _dma_cleanup(void); +extern void _dma_pprint(void); +extern uint32_t *_salloc(int d, int size, const char *name); +extern void _sfree(int d, void *ptr); +extern int _sinval(int d, void *ptr, int length); +extern int _sflush(int d, void *ptr, int length); +extern sal_paddr_t _l2p(int d, void *vaddr); +extern void *_p2l(int d, sal_paddr_t paddr); +extern int _dma_pool_allocated(void); +extern int _dma_range_valid(unsigned long phys_addr, unsigned long size); + +#endif /* __KERNEL__ */ + +#endif /* __LINUX_DMA_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/include/mpool.h b/platform/broadcom/saibcm-modules/systems/bde/linux/include/mpool.h new file mode 100644 index 000000000000..be4d436f8da9 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/include/mpool.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: mpool.h,v 1.2 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef __MPOOL_H__ +#define __MPOOL_H__ + +struct mpool_mem_s; +typedef struct mpool_mem_s* mpool_handle_t; + +extern int mpool_init(void); +extern mpool_handle_t mpool_create(void* base_address, int size); +extern void* mpool_alloc(mpool_handle_t pool, int size); +extern void mpool_free(mpool_handle_t pool, void* ptr); +extern int mpool_destroy(mpool_handle_t pool); + +extern int mpool_usage(mpool_handle_t pool); + +#endif /* __MPOOL_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile new file mode 100644 index 000000000000..3d504a5665fa --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile @@ -0,0 +1,114 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.18 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Makefile for Linux kernel BDE +# +LOCALDIR = systems/bde/linux/kernel + +# Make sure we build for the kernel if this is a user-mode build +ifneq ($(platform), ) +override-target=linux-$(platform) +endif + +include $(SDK)/make/Make.config + +LIBS = $(LIBDIR)/libkern.a + +BDE = linux-kernel-bde.o + +ifdef ROBO_CHIPS +CFLAGS += -I$(ET_ROBO) -I${SDK}/include/shared/et +ET_ROBO = ${SDK}/systems/drv/et +endif + +# need to add vpath sources +VPATH = ../shared $(ET_ROBO) + +# Add the srcs to be found by vpath +LSRCS += mpool.c +ifdef ROBO_CHIPS +platformsplt = $(subst -, , ${platform}) # change hyphens to spaces +platformbase = $(word 1,${platformsplt}) + +ifeq ($(platformbase), keystone) + LSRCS += etc_robo_spi.c aiutils.c +else + ifeq ($(platformbase), keystone_le) + LSRCS += etc_robo_spi.c aiutils.c + else + ifeq ($(platformbase), iproc) + LSRCS += robo_srab.c robo_spi.c aiutils.c + endif + endif +endif # platformbase + +endif # ROBO_CHIPS + +# Add shared BDE sources +VPATH += ../../shared +LSRCS += shbde_pci.c shbde_iproc.c shbde_mdio.c +CFLAGS += -I../../shared/include + +LHDRS += mpool.h +LOBJS = $(addsuffix .o, $(basename $(LSRCS))) +BOBJS = $(addprefix $(BLDDIR)/,$(LOBJS)) + +ifneq ($(kernel_version),2_4) +KERNEL_MODULE_DIR = kernel_module + +THIS_MOD_NAME := linux-kernel-bde +MODULE = $(LIBDIR)/$(THIS_MOD_NAME).o +KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko + +build: kernel_libs $(MODULE) $(KMODULE) +else +MODULE = $(LIBDIR)/linux-kernel-bde.o + +build: kernel_libs $(MODULE) +endif + +$(MODULE): $(BLDDIR)/.tree kernel_libs $(BOBJS) + mkdir -p $(@D) + $(LD) $(MODULE_LDFLAGS) -r -d $(BOBJS) $(LIBS) -o $@ +ifneq ($(kernel_version),2_4) +$(KMODULE): $(MODULE) + rm -fr $(BLDDIR)/$(KERNEL_MODULE_DIR) + mkdir $(BLDDIR)/$(KERNEL_MODULE_DIR) + cp ${SDK}/make/Makefile.linux-kmodule $(BLDDIR)/$(KERNEL_MODULE_DIR)/Makefile + MOD_NAME=$(THIS_MOD_NAME) $(MAKE) -C $(BLDDIR)/$(KERNEL_MODULE_DIR) $(THIS_MOD_NAME).ko +endif + +kernel_libs: + $(MAKE) -C $(SDK)/systems/linux/kernel/modules/shared + +include $(SDK)/make/Make.depend + +# Make.depend is before clean:: so that Make.depend's clean:: runs first. + +clean:: + $(MAKE) -C $(SDK)/systems/linux/kernel/modules/shared $@ + $(RM) $(BOBJS) $(MODULE) + $(RM) $(BLDDIR)/$(KERNEL_MODULE_DIR) + +distclean:: + +ifneq ($(kernel_version),2_4) +.PHONY: build kernel_libs +endif diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c new file mode 100644 index 000000000000..e26d35332cc8 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c @@ -0,0 +1,5209 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: linux-kernel-bde.c,v 1.414 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + * + * Linux Kernel BDE + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "linux_shbde.h" + +#ifdef BCM_ROBO_SUPPORT +/* robo/et related header files */ +#include + +#include + +#if defined(KEYSTONE) +#include +#include +#include +#include +#elif defined(IPROC_CMICD) +#include +#include +#ifdef BCM_STARFIGHTER3_SUPPORT +#include +#endif +#include +#include +#else /* BCM4704 */ +#include +#include +#endif +#endif /* BCM_ROBO_SUPPORT */ + +#define PCI_USE_INT_NONE (-1) +#define PCI_USE_INT_INTX (0) +#define PCI_USE_INT_MSI (1) +#define PCI_USE_INT_MSIX (2) +#ifdef CONFIG_PCI_MSI +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,110)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) +#define msix_table_size(flags) ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) +#endif +#define msi_control_reg(base) (base + PCI_MSI_FLAGS) +#endif +#endif +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("Kernel BDE"); +MODULE_LICENSE("GPL"); + +/* PCIe max payload */ +int maxpayload = 256; +LKM_MOD_PARAM(maxpayload, "i", int, 0); +MODULE_PARM_DESC(maxpayload, +"Limit maximum payload size and request size on PCIe devices"); + +/* Use MSI or MSIX interrupts */ +int usemsi = -1; +LKM_MOD_PARAM(usemsi, "i", int, 0); +MODULE_PARM_DESC(usemsi, +"Use MSI/ MSIX interrupts if supported by kernel"); + +/* Ignore all recognized devices (for debug purposes) */ +int nodevices; +LKM_MOD_PARAM(nodevices, "i", int, 0); +MODULE_PARM_DESC(nodevices, +"Ignore all recognized devices (default no)"); + +/* + * This usually is defined at /usr/include/linux/pci_ids.h + * But this ID is newer. + */ +#ifndef PCI_DEVICE_ID_PLX_9656 +#define PCI_DEVICE_ID_PLX_9656 0x9656 +#endif + +#ifndef PCI_DEVICE_ID_PLX_9056 +#define PCI_DEVICE_ID_PLX_9056 0x9056 +#endif + +/* local defined device IDs, refer to bcmdevs.h */ +#ifndef BCM53000_GMAC_ID +#define BCM53000_GMAC_ID 0x4715 /* 53003 gmac id */ +#endif +#ifndef BCM53010_GMAC_ID +#define BCM53010_GMAC_ID 0x4715 /* 5301x gmac id */ +#endif +#ifndef BCM47XX_ENET_ID +#define BCM47XX_ENET_ID 0x4713 /* 4710 enet */ +#endif +#ifndef BCM53010_CHIP_ID +#define BCM53010_CHIP_ID 0xcf12 /* 53010 chipcommon chipid */ +#endif +#ifndef BCM53018_CHIP_ID +#define BCM53018_CHIP_ID 0xcf1a /* 53018 chipcommon chipid */ +#endif +#ifndef BCM53020_CHIP_ID +#define BCM53020_CHIP_ID 0xcf1e /* 53020 chipcommon chipid */ +#endif + +/* For 2.4.x kernel support */ +#ifndef IRQF_SHARED +#define IRQF_SHARED SA_SHIRQ +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +typedef unsigned long resource_size_t; +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) */ + +#ifdef BCM_ICS +#define BCM_ICS_CMIC_BASE 0x08000000 +#else + +/* Force interrupt line */ +static int forceirq = -1; +static uint32_t forceirqubm = 0xffffffff; +LKM_MOD_PARAM(forceirq, "i", int, 0); +LKM_MOD_PARAM(forceirqubm, "i", uint, 0); +MODULE_PARM_DESC(forceirq, +"Override IRQ line assigned by boot loader"); +MODULE_PARM_DESC(forceirqubm, +"Bitmap for overriding the IRQ line assigned by boot loader for given units"); + +/* Create SPI slave device (cannot be probed) */ +static uint32_t spi_devid = 0; +LKM_MOD_PARAM(spi_devid, "i", uint, 0); +MODULE_PARM_DESC(spi_devid, +"Create SPI slave device using this device ID"); + +/* Select SPI device revision (cannot be probed) */ +static uint32_t spi_revid = 1; +LKM_MOD_PARAM(spi_revid, "i", uint, 0); +MODULE_PARM_DESC(spi_revid, +"Select device revision for SPI slave device"); + +#endif /* BCM_ICS */ + +/* Debug output */ +static int debug; +LKM_MOD_PARAM(debug, "i", int, 0); +MODULE_PARM_DESC(debug, +"Set debug level (default 0"); +/* Use high memory for DMA */ + +/* module param for probing EB devices. */ +static char *eb_bus; +LKM_MOD_PARAM(eb_bus, "s", charp, 0); +MODULE_PARM_DESC(eb_bus, +"List of EB devices on platform. Input format (BA=%x IRQ=%d RD16=%d WR16=%d"); + +#ifdef KEYSTONE +/* Force SPI Frequency */ +static int spifreq = 0; +LKM_MOD_PARAM(spifreq, "i", int, 0); +MODULE_PARM_DESC(spifreq, +"Force SPI Frequency for Keystone CPU (0 for default frequency)"); +#endif + +#if defined(BCM_EA_SUPPORT) +#if defined(BCM_TK371X_SUPPORT) +static int eadevices; +LKM_MOD_PARAM(eadevices, "i", int, 0); +MODULE_PARM_DESC(eadevices, +"Number of TK371X devices"); +#endif /* */ +#endif /* BCM_EA_SUPPORT */ + +/* Compatibility */ +#ifdef LKM_2_4 +#define _ISR_RET void +#define _ISR_PARAMS(_i,_d,_r) int _i, void *_d, struct pt_regs *_r +#define IRQ_NONE +#define IRQ_HANDLED +#define SYNC_IRQ(_i) synchronize_irq() +#else /* LKM_2_6 */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)) +#define _ISR_RET irqreturn_t +#else +#define _ISR_RET int +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) +#define _ISR_PARAMS(_i,_d,_r) int _i, void *_d +#else +#define _ISR_PARAMS(_i,_d,_r) int _i, void *_d, struct pt_regs *_r +#endif +#define SYNC_IRQ(_i) synchronize_irq(_i) +char * ___strtok; +char * strtok(char * s,const char * ct) +{ + char *sbegin, *send; + sbegin = s ? s : ___strtok; + if (!sbegin) { + return NULL; + } + sbegin += strspn(sbegin,ct); + if (*sbegin == '\0') { + ___strtok = NULL; + return( NULL ); + } + send = strpbrk( sbegin, ct); + if (send && *send != '\0') + *send++ = '\0'; + ___strtok = send; + return (sbegin); +} +LKM_EXPORT_SYM(___strtok); +LKM_EXPORT_SYM(strtok); +#endif /* LKM_2_x */ + +/* PCIe capabilities */ +#ifndef PCI_CAP_ID_EXP +#define PCI_CAP_ID_EXP 0x10 +#endif +#ifndef PCI_EXP_DEVCAP +#define PCI_EXP_DEVCAP 4 +#endif +#ifndef PCI_EXP_DEVCTL +#define PCI_EXP_DEVCTL 8 +#endif +#ifndef PCI_EXT_CAP_START +#define PCI_EXT_CAP_START 0x100 +#endif +#ifndef PCI_EXT_CAP_ID +#define PCI_EXT_CAP_ID(_hdr) (_hdr & 0x0000ffff) +#endif +#ifndef PCI_EXT_CAP_VER +#define PCI_EXT_CAP_VER(_hdr) ((_hdr >> 16) & 0xf) +#endif +#ifndef PCI_EXT_CAP_NEXT +#define PCI_EXT_CAP_NEXT(_hdr) ((_hdr >> 20) & 0xffc) +#endif +#ifndef PCI_EXT_CAP_ID_VNDR +#define PCI_EXT_CAP_ID_VNDR 0x0b +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +#define PCI_FIND_DEV(_d, _v, _fr) pci_find_device(_d, _v, _fr) +#else +#define PCI_FIND_DEV(_d, _v, _fr) pci_get_device(_d, _v, _fr) +#endif + +#if defined(CONFIG_RESOURCES_64BIT) || defined(CONFIG_PHYS_ADDR_T_64BIT) +#define PHYS_ADDR_IS_64BIT +#endif + +/* Structure of private SPI device */ +struct spi_dev { + uint8 cid; /* Chip ID */ + uint32 part; /* Part number of the chip */ + uint8 rev; /* Revision of the chip */ + void *robo; /* ptr to robo info required to access SPI */ + unsigned short phyid_high; /* PHYID HIGH in MII regs of detected chip */ + unsigned short phyid_low; /* PHYID LOW in MII regs of detected chip */ +}; + +struct bde_spi_device_id { + unsigned short phyid_high; /* PHYID HIGH in MII regs of detected chip */ + unsigned short phyid_low; /* PHYID LOW in MII regs of detected chip */ + uint32 model_info; + uint32 rev_info; + uint32 spifreq; +}; + +/* Control Data */ +typedef struct bde_ctrl_s { + struct list_head list; + + /* Specify the type of device, pci, spi, switch, ether ... */ + uint32 dev_type; + + int domain_no; + int bus_no; + int be_pio; + int use_msi; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + struct msix_entry *entries; +#endif + int msix_cnt; + union { + /* Linux PCI device pointer */ + struct pci_dev* _pci_dev; + + /* SPI device pointer */ + struct spi_dev* _spi_dev; + } dev; +#define pci_device dev._pci_dev +#define spi_device dev._spi_dev + +#ifdef LINUX_BDE_DMA_DEVICE_SUPPORT + struct device *dma_dev; +#endif + + /* Physical addresses */ + resource_size_t phys_address; + resource_size_t phys_address1; + resource_size_t phys_address2; + + /* Secondary mapped base address */ + sal_vaddr_t alt_base_addr; + + /* BDE device description */ + ibde_dev_t bde_dev; + + /* Interrupt Handling */ + int iLine; /* Interrupt line */ + void (*isr)(void *); + void *isr_data; + + /* + * Controls to allow two drivers to share a single set of + * hardware registers. Typically a kernel driver will handle + * a subset of hardware interrupts and a user mode driver + * will handle the remaining interrupts. + */ + void (*isr2)(void *); + void *isr2_data; + uint32_t fmask; /* Interrupts controlled by secondary handler */ + uint32_t imask; /* Enabled interrupts for primary handler */ + uint32_t imask2; /* Enabled interrupts for secondary handler */ + spinlock_t lock; /* Lock for IRQ mask synchronization */ + + /* Hardware abstraction for shared BDE functions */ + shbde_hal_t shbde; + + /* Device state : BDE_DEV_STATE_REMOVED/CHANGED */ + uint32 dev_state; + + /* inst_id */ + uint32 inst_id; +} bde_ctrl_t; + +static bde_ctrl_t _devices[LINUX_BDE_MAX_DEVICES]; +static int _ndevices = 0; +static int _switch_ndevices = 0; +static int _ether_ndevices = 0; +static int _cpu_ndevices = 0; +static int robo_switch = 0; + +#define VALID_DEVICE(_n) ((_n >= 0) && (_n < _ndevices)) + +/* CPU MMIO area used with CPU cards provided on demo boards */ +#if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)) && (defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_GTO_BCM_CPU__)) +static void *cpu_address = NULL; +#endif + +#ifdef BCM_ROBO_SUPPORT + +/* for SPI access via bcm4710 core */ +static void *robo = NULL; +static void *sbh = NULL; + +#ifdef ALTA_ROBO_SPI + +extern void *alta_eth_spi_ctrl; + +extern int +robo_spi_read(void *cookie, uint16_t reg, uint8_t *buf, int len); + +extern int +robo_spi_write(void *cookie, uint16_t reg, uint8_t *buf, int len); + +#define ROBO_RREG(_robo, _dev, _page, _reg, _buf, _len) \ + robo_spi_read(_dev ? NULL : alta_eth_spi_ctrl, \ + (_page << 8) | (_reg), _buf, _len) +#define ROBO_WREG(_robo, _dev, _page, _reg, _buf, _len) \ + robo_spi_write(_dev ? NULL : alta_eth_spi_ctrl, \ + (_page << 8) | (_reg), _buf, _len) + +#else /* !ALTA_ROBO_SPI */ + +#if defined(KEYSTONE) || defined(IPROC_CMICD) +#define ROBO_RREG(_robo, _dev, _page, _reg, _buf, _len) \ + robo_rreg(_robo, _dev, _page, _reg, _buf, _len) +#define ROBO_WREG(_robo, _dev, _page, _reg, _buf, _len) \ + robo_wreg(_robo, _dev, _page, _reg, _buf, _len) +#else +#define ROBO_RREG(_robo, _dev, _page, _reg, _buf, _len) +#define ROBO_WREG(_robo, _dev, _page, _reg, _buf, _len) +#endif + +#endif /* ALTA_ROBO_SPI */ + +#endif /* BCM_ROBO_SUPPORT */ + +/* Broadcom BCM4704 */ +#define BCM4704_VENDOR_ID 0x14E4 +#define BCM4704_DEVICE_ID 0x4704 + +/* SiByte PCI Host */ +#define SIBYTE_PCI_VENDOR_ID 0x166D +#define SIBYTE_PCI_DEVICE_ID 0x0001 + +/* Intel 21150 PCI-PCI Bridge */ +#define DC21150_VENDOR_ID 0x1011 +#define DC21150_DEVICE_ID 0x0022 + +/* HiNT HB4 PCI-PCI Bridge (21150 clone) */ +#define HINT_HB4_VENDOR_ID 0x3388 +#define HINT_HB4_DEVICE_ID 0x0022 + +/* Pericom PI7C8150 PCI-PCI Bridge (21150 clone) */ +#define PI7C8150_VENDOR_ID 0x12D8 +#define PI7C8150_DEVICE_ID 0x8150 + +/* Pericom PI7C9X130 PCI-PCIE Bridge */ +#define PCI_VNDID_PERICOM 0x12D8 +#define PCI_DEVID_PI7C9X130 0xE130 +#define DEV_CTRL_REG 0xb8 + +#define MAX_PAYLOAD_256B (1 << 5) +#define MAX_PAYLOAD_512B (2 << 5) +#define MAX_READ_REQ_256B (1 << 12) + + +/* Freescale 8548 PCI-E host Bridge */ +#define FSL_VENDOR_ID 0x1957 +#define FSL8548PCIE_DEVICE_ID 0x0013 +#define FSL2020EPCIE_DEVICE_ID 0x0070 +#define FSL8548PCIE_DEV_CTRL_REG 0x54 + +/* 4716 PCI-E host Bridge */ +#define BCM4716_VENDOR_ID 0x14e4 +#define BCM4716PCIE_DEVICE_ID 0x4716 +#define BCM4716PCIE_DEV_CAP_REG 0xd4 +#define BCM4716PCIE_DEV_CTRL_REG 0xd8 +#define BCM53000_VENDOR_ID 0x14e4 +#define BCM53000PCIE_DEVICE_ID 0x5300 + +#define BCM53000PCIE_DEV(port) ((port == 0) ? pcie0 : pcie1) +#define BCM53000PCIE_BASE(port) ((port == 0) ? 0xb8005000 : 0xb800e000) +#define BCM53000PCIE_FUNC0_COFIG_SPACE 0x400 +#define BCM53000PCIE_SROM_SPACE 0x800 +#define BCM53000PCIE_DEV_CAP_REG 0xd4 +#define BCM53000PCIE_DEV_CTRL_REG 0xd8 +#define BCM53000PCIE_MAX_PAYLOAD_MASK 0x7 +#define BCM53000PCIE_CAP_MAX_PAYLOAD_256B (1 << 0) +#define BCM53000PCIE_DEFAULT_STATUS 0x00100146 + +/* 16bit wide register. offset 14, 14*2 = 0x1c */ +#define BCM53000PCIE_SPROM_OFFSET 0x1c +/* bit 15:13 spromData.MaxPayloadSize. 1: 256 bytes */ +#define BCM53000PCIE_SPROM_MAX_PAYLOAD_MASK 0xe000 +#define BCM53000PCIE_SPROM_MAX_PAYLOAD_256B (1 << 13) + + +/* Intel 21150, HiNT HB4 and other 21150-compatible */ +#define PCI_CFG_DEC21150_SEC_CLK 0x68 + +#define BCM4704_ENUM_BASE 0x18000000 +#define BCM4704_MEMC_BASE (BCM4704_ENUM_BASE+0x8000) +#define BCM4704_MEMC_PRIORINV 0x18 + +/* PLX PCI-E Switch */ +#define PLX_PEX8608_DEV_ID 0x8608 +#define PLX_PEX8617_DEV_ID 0x8617 +#define PLX_PEX86XX_DEV_CTRL_REG 0x70 + +/* Broadcom BCM58525 */ +#define BCM58525_PCI_VENDOR_ID 0x14E4 +#define BCM58525_PCI_DEVICE_ID 0x8025 +#define BCM58522_PCI_DEVICE_ID 0x8022 + +/* Broadcom BCM58712 */ +#define BCM58712_PCI_VENDOR_ID 0x14E4 +#define BCM58712_PCI_DEVICE_ID 0x168E + +static uint32_t _read(int d, uint32_t addr); + +#ifdef BCM_ICS +#else +/* Used to determine overall memory limits across all devices */ +static uint32_t _pci_mem_start = 0xFFFFFFFF; +static uint32_t _pci_mem_end = 0; + +/* Used to control MSI interrupts */ +static int use_msi = 0; +#endif + +#ifdef BCM_PLX9656_LOCAL_BUS + +#define CPLD_OFFSET 0x00800000 +#define CPLD_REVISION_REG 0x0000 +#define CPLD_REVISION_MASK 0xffff +#define CPLD_RESET_REG 0x0004 +#define CPLD_RESET_NONE 0x0000 + +#define PL0_OFFSET 0x00800000 +#define PL0_SIZE 0x00040000 +#define PL0_REVISION_REG 0x0000 + +/* Assume there's only one PLX PCI-to-Local bus bridge if any */ +static bde_ctrl_t plx_ctrl; +static int num_plx = 0; + +#endif /* BCM_PLX9656_LOCAL_BUS */ + +static spinlock_t bus_lock; + +static int +_parse_eb_args(char *str, char * format, ...) + __attribute__ ((format (scanf, 2, 3))); + +static int +_parse_eb_args(char *str, char * format, ...) +{ + va_list args; + + va_start(args, format); + vsscanf(str, format, args); + va_end(args); + + return 0; +} + +static void +_bde_add_device(void) +{ + /* + * In order to be backward compatible with the user mode BDE + * (specifically the interrupt IOCTLs) and the CM, switch devices + * *must* come first. If this is not the case (due to the probing + * order), we let the non-switch device(s) drop down to the end of + * the device array. + */ + if (_switch_ndevices > 0) { + bde_ctrl_t tmp_dev; + int i, s = 0; + + while (s < _switch_ndevices) { + if (_devices[s].dev_type & BDE_SWITCH_DEV_TYPE) { + s++; + continue; + } + tmp_dev = _devices[s]; + for (i = s; i < _ndevices - 1; i++) { + _devices[i] = _devices[i+1]; + } + _devices[i] = tmp_dev; + } + } + + /* Initialize device locks and dma */ + if (_ndevices > 0) { + spin_lock_init(&_devices[_ndevices-1].lock); + _dma_init(robo_switch, _ndevices-1); + } +} + +static int +_eb_device_create(resource_size_t paddr, int irq, int rd_hw, int wr_hw) +{ + bde_ctrl_t *ctrl; + uint32 dev_rev_id = 0x0, dev_id; + + dev_id = _ndevices; + + ctrl = _devices + _ndevices++; + _switch_ndevices++; + + ctrl->dev_type |= BDE_EB_DEV_TYPE | BDE_SWITCH_DEV_TYPE; + ctrl->pci_device = NULL; /* No PCI bus */ + + if(rd_hw) { + ctrl->dev_type |= BDE_DEV_BUS_RD_16BIT; + } + + if (wr_hw) { + ctrl->dev_type |= BDE_DEV_BUS_WR_16BIT; + } + + /* Map in the device */ + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(paddr, 0x10000); + ctrl->phys_address = paddr; + + dev_rev_id = _read(dev_id, 0x178); /* CMIC_DEV_REV_ID */ + + ctrl->bde_dev.device = dev_rev_id & 0xFFFF; + ctrl->bde_dev.rev = (dev_rev_id >> 16) & 0xFF; + + ctrl->iLine = irq; + ctrl->isr = NULL; + ctrl->isr_data = NULL; + + _bde_add_device(); + + gprintk("Created EB device at BA=%x IRQ=%d RD16=%d WR16=%d device=0x%x\n", + (unsigned int)paddr, irq, rd_hw, wr_hw, ctrl->bde_dev.device); + + return 0; +} + +#if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) + +#include + +static int +sand_device_create(void) +{ + bde_ctrl_t* ctrl; + + ctrl = _devices; /* FIX_ME: on petra, take first device */ + +#ifndef __DUNE_LINUX_BCM_CPU_PCIE__ + _switch_ndevices++; + _ndevices++; + + ctrl->dev_type |= BDE_PCI_DEV_TYPE | BDE_SWITCH_DEV_TYPE; + ctrl->pci_device = NULL; /* No PCI bus */ + + /* Map in the device */ /* FIX_ME: not realy map anything */ + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(0x40000000, 0x100000); + ctrl->phys_address = 0x40000000; + + ctrl->iLine = 0; + ctrl->isr = NULL; + ctrl->isr_data = NULL; + + ctrl->bde_dev.device = BCM88950_DEVICE_ID; + ctrl->bde_dev.rev = BCM88950_A0_REV_ID; +#endif + + /* Map CPU regs */ +#ifdef __DUNE_WRX_BCM_CPU__ + cpu_address = IOREMAP(0x18000000, 0x4000000); +#elif defined(__DUNE_GTO_BCM_CPU__) + cpu_address = IOREMAP(0xe0000000, 0x100000); +#endif + + if ((ctrl->bde_dev.device == PCP_PCI_DEVICE_ID)) { + ctrl->bde_dev.device = GEDI_DEVICE_ID; + ctrl->bde_dev.rev = GEDI_REV_ID; + } + + if ((ctrl->bde_dev.device == ACP_PCI_DEVICE_ID)) { + ctrl->dev_type |= BDE_PCI_DEV_TYPE | BDE_SWITCH_DEV_TYPE; + } + +#ifndef __DUNE_LINUX_BCM_CPU_PCIE__ + _bde_add_device(); +#endif + + return 0; +} +#endif + +#ifdef IPROC_CMICD +static void +iproc_cmicd_get_irqres(ibde_dev_t bde_dev, struct resource *res_irq) +{ + shbde_iproc_config_t iproc_config, *icfg = &iproc_config; + + /* iProc configuration parameters */ + memset(icfg, 0, sizeof(*icfg)); + shbde_iproc_config_init(icfg, bde_dev.device, bde_dev.rev); + + if ((icfg->iproc_ver == 0) && (debug >= 1)) { + gprintk("Unable to determine iProc version\n"); + } + + if (icfg->iproc_ver == 7) { + res_irq->start = 221; + } else if (icfg->iproc_ver == 10) { + res_irq->start = 184; + } + +} + +#include +#include + +extern void iproc_platform_driver_register(struct platform_driver *drv); +extern void iproc_platform_driver_unregister(struct platform_driver *drv); +extern void iproc_platform_device_register(struct platform_device *drv); +extern void iproc_platform_device_unregister(struct platform_device *drv); + +extern struct resource * +iproc_platform_get_resource(struct platform_device *dev, unsigned int type, + unsigned int num); + +#define IPROC_CHIPCOMMONA_BASE 0x18000000 +#define IPROC_CMICD_BASE 0x48000000 +#define IPROC_CMICD_SIZE 0x40000 +#define IPROC_CMICD_INT 194 + +#define IPROC_CMICD_COMPATIBLE "brcm,iproc-cmicd" + +static int +iproc_cmicd_probe(struct platform_device *pldev) +{ + bde_ctrl_t *ctrl; + uint32 size, dev_rev_id; + struct resource *memres, *irqres; +#ifdef CONFIG_OF + if (debug >= 1) { + gprintk("iproc_cmicd_probe %s\n", pldev->dev.of_node ? "with device node":""); + } +#endif + memres = iproc_platform_get_resource(pldev, IORESOURCE_MEM, 0); + if (memres == NULL) { + gprintk("Unable to retrieve iProc CMIC resources"); + return -1; + } + size = memres->end - memres->start + 1; + + ctrl = _devices + _ndevices++; + _switch_ndevices++; + + ctrl->dev_type = BDE_AXI_DEV_TYPE | BDE_SWITCH_DEV_TYPE | BDE_256K_REG_SPACE; + ctrl->pci_device = NULL; /* No PCI bus */ + + /* Map CMIC block in the AXI memory space into CPU address space */ + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(memres->start, size); + if (!ctrl->bde_dev.base_address) { + gprintk("Error mapping iProc CMIC registers"); + return -1; + } + ctrl->phys_address = memres->start; + + /* Read switch device ID from CMIC */ + dev_rev_id = *((uint32_t*)(ctrl->bde_dev.base_address + 0x10224)); +#if defined(BCM_CMICM_SUPPORT) && defined(BE_HOST) + ctrl->bde_dev.device = ( (((dev_rev_id >> 16) & 0xff) << 8) | + ((dev_rev_id >> 24) & 0xff)); + ctrl->bde_dev.rev = (dev_rev_id >> 8) & 0xff ; +#else + ctrl->bde_dev.device = dev_rev_id & 0xffff; + ctrl->bde_dev.rev = (dev_rev_id >> 16) & 0xff; +#endif + +#ifdef CONFIG_OF + if (!pldev->dev.of_node) +#endif + { + /* Assign locally if not available from device node */ + iproc_cmicd_get_irqres(ctrl->bde_dev, &pldev->resource[0]); + } + irqres = iproc_platform_get_resource(pldev, IORESOURCE_IRQ, 0); + + ctrl->iLine = irqres->start; + + ctrl->isr = NULL; + ctrl ->isr_data = NULL; + +#ifdef LINUX_BDE_DMA_DEVICE_SUPPORT + ctrl->dma_dev = &pldev->dev; +#endif + + /* Let's boogie */ + _bde_add_device(); + return 0; +} + +static int +iproc_cmicd_remove(struct platform_device *pldev) +{ + return 0; +} +#ifdef CONFIG_OF +static const struct of_device_id iproc_cmicd_of_match[] = { + { .compatible = "brcm,iproc-cmicd" }, + {}, +}; +MODULE_DEVICE_TABLE(of, iproc_cmicd_of_match); +#endif +static char iproc_cmicd_string[] = "bcmiproc-cmicd"; + +static struct platform_driver iproc_cmicd_driver = +{ + .probe = iproc_cmicd_probe, + .remove = iproc_cmicd_remove, + .driver = + { + .name = iproc_cmicd_string, + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = iproc_cmicd_of_match, +#endif + }, +}; + +typedef enum { + IPROC_CMICD_RES_INTR = 0, + IPROC_CMICD_RES_MEM +} IPROC_CMICD_RES_E; + +static struct resource iproc_cmicd_resources[] = { + [IPROC_CMICD_RES_INTR] = { + .flags = IORESOURCE_IRQ, + .start = IPROC_CMICD_INT, + }, + [IPROC_CMICD_RES_MEM] = { + .flags = IORESOURCE_MEM, + .start = IPROC_CMICD_BASE, + .end = IPROC_CMICD_BASE+IPROC_CMICD_SIZE-1, + }, +}; + +static void +iproc_cmicd_release(struct device *dev) +{ +} + +static u64 iproc_cmicd_dmamask = DMA_BIT_MASK(32); + +static struct platform_device iproc_cmicd_pdev = { + .name = iproc_cmicd_string, + .id = 0, + .dev = { + .release = iproc_cmicd_release, + .init_name = iproc_cmicd_string, + .dma_mask = &iproc_cmicd_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = iproc_cmicd_resources, + .num_resources = ARRAY_SIZE(iproc_cmicd_resources), +}; + +static int +iproc_has_cmicd(void) +{ + void *iproc_cca_base; + uint32 cca_cid; + + /* Read ChipcommonA chip id register to identify current SOC */ + iproc_cca_base = IOREMAP(IPROC_CHIPCOMMONA_BASE, 0x3000); + if (iproc_cca_base == NULL) { + gprintk("iproc_has_cmicd: ioremap of ChipcommonA registers failed"); + return 0; + } + cca_cid = readl((uint32 *)iproc_cca_base); + cca_cid &= 0xffff; + iounmap(iproc_cca_base); + + /* Only allowed accessing CMICD module if the SOC has it */ + switch (cca_cid) { + case BCM53010_CHIP_ID: + case BCM53018_CHIP_ID: + case BCM53020_CHIP_ID: + return 0; + default: + break; + } + + /* Device has CMIC */ + return 1; +} + +#define IPROC_CHIPCOMMONA_EROM_PTR_OFFSET (0x180000fc) +#define EROM_MAX_SIZE (0x1000) +#define EROM_PARTNUM_CMICD (0x14) + +#define EROM_DESC_COMPIDENT (0x1) +#define EROM_DESC_MASTER (0x3) +#define EROM_DESC_ADDR (0x5) +#define EROM_DESC_END (0xF) +#define EROM_DESC_EMPTY (0) + +#define EROM_IS_DESC_COMPIDENT(x) ((x & 0x7) == EROM_DESC_COMPIDENT) +#define EROM_IS_DESC_MASTER(x) ((x & 0x7) == EROM_DESC_MASTER) +#define EROM_IS_DESC_ADDR(x) ((x & 0x7) == EROM_DESC_ADDR) +#define EROM_IS_DESC_END(x) ((x & 0xF) == EROM_DESC_END) + +#define EROM_GET_PARTNUM(x) ((x >> 8) & (0xFFF)) /* Bit 8~19 */ +#define EROM_GET_ADDRESS(x) ((x >> 12) & (0xFFFFF)) /* Bit 12~31 */ +#define EROM_GET_SIZETYPE(x) ((x >> 4) & (0x3)) /* Bit 4~5 */ +#define EROM_GET_AG32(x) ((x >> 3) & (0x1)) /* Bit 3 */ +#define EROM_GET_SIZE(x) ((x >> 12) & (0xFFFFF)) /* Bit 12~31 */ +#define EROM_GET_SG32(x) ((x >> 3) & (0x1)) /* Bit 3 */ + +#define EROM_ADDR_SIZETYPE_4K (0) +#define EROM_ADDR_SIZETYPE_8K (1) +#define EROM_ADDR_SIZETYPE_16K (2) +#define EROM_ADDR_SIZETYPE_MORE (3) + +#define EROM_ADDR_FLAG_AG32 (1) /* Address space greater than 32 bit */ +#define EROM_ADDR_FLAG_SIZE (2) /* Addition size descriptor */ +#define EROM_ADDR_FLAG_SG32 (4) /* Size descriptor greater than 32 bit */ + +static void +iproc_cmicd_get_memregion(struct resource *res_mem) +{ + void *erom_ptr_oft; + uint32_t erom_phy_addr; + uint32_t *erom_base; + uint32_t i = 0; + uint32_t word = 0; + uint8_t more_addr_word = 0; /* bit 0: AG32; bit 1: SIZE; bit 2: SG32 */ + uint8_t found_cmicd_dev = 0; + uint8_t size_type = 0; + bool is_compident_a = 1; /* 1: CompidentA; o/w: CompidentB */ + + erom_ptr_oft = IOREMAP(IPROC_CHIPCOMMONA_EROM_PTR_OFFSET, 0x100); + + erom_phy_addr = readl((uint32 *)(erom_ptr_oft)); + iounmap(erom_ptr_oft); + + erom_base = IOREMAP(erom_phy_addr, EROM_MAX_SIZE); + + while (1) { + word = readl((uint32 *)(erom_base + i)); + + if (EROM_IS_DESC_ADDR(word) || more_addr_word) { + if (more_addr_word == 0) { /* Normal Addr Desc */ + if (EROM_GET_AG32(word) == 1) { + more_addr_word |= EROM_ADDR_FLAG_AG32; + } + + size_type = EROM_GET_SIZETYPE(word); + if (size_type == EROM_ADDR_SIZETYPE_MORE) { + more_addr_word |= EROM_ADDR_FLAG_SIZE; + } + + if (found_cmicd_dev == 1) { + res_mem->start = EROM_GET_ADDRESS(word) << 12; + if (size_type < EROM_ADDR_SIZETYPE_MORE) { + res_mem->end = res_mem->start + 4096 * (1 << size_type) - 1; + } + } + } + else if (more_addr_word & EROM_ADDR_FLAG_AG32) { /* UpperAddr Desc */ + more_addr_word &= ~EROM_ADDR_FLAG_AG32; + + if (found_cmicd_dev == 1) { + /* res_mem->start |= word << 32; */ + gprintk("Expect cmicd address to be 32-bit\n"); + } + } + else if (more_addr_word & EROM_ADDR_FLAG_SIZE) { /* Size Desc */ + if (EROM_GET_SG32(word) == 1) { + more_addr_word |= EROM_ADDR_FLAG_SG32; + } + + more_addr_word &= ~EROM_ADDR_FLAG_SIZE; + + if (found_cmicd_dev == 1) { + res_mem->end = res_mem->start + (EROM_GET_SIZE(word) << 12) - 1; + } + } + else if (more_addr_word & EROM_ADDR_FLAG_SG32) { /* UpperSize Desc */ + more_addr_word &= ~EROM_ADDR_FLAG_SG32; + + if (found_cmicd_dev == 1) { + /* res_mem->end += (word) << 32; */ + gprintk("Expect cmicd size to be 32-bit\n"); + } + } + + if (found_cmicd_dev == 1 && more_addr_word == 0) { + break; /* We have gotten all necessary information, exit the loop */ + } + } + else if (EROM_IS_DESC_COMPIDENT(word)) { + if (is_compident_a == 1) { + if (EROM_GET_PARTNUM(word) == EROM_PARTNUM_CMICD) { + found_cmicd_dev = 1; + } + } + + is_compident_a = 1 - is_compident_a; + } + else if (EROM_IS_DESC_END(word)) { + break; + } + + i++; + } + iounmap(erom_base); + + if (debug >= 1) { + gprintk("CMICD info by %s: cmicd_mem.start=%x, cmicd_mem.end=%x\n", + found_cmicd_dev ? "EROM" : "Default", + iproc_cmicd_resources[IPROC_CMICD_RES_MEM].start, + iproc_cmicd_resources[IPROC_CMICD_RES_MEM].end); + } +} +#endif /* IPROC_CMICD */ + +#ifdef BCM_ICS +static int +_ics_bde_create(void) +{ + bde_ctrl_t *ctrl; + uint32 dev_rev_id = 0x0; + resource_size_t paddr; + + if (_ndevices == 0) { + ctrl = _devices + _ndevices++; + _switch_ndevices++; + + ctrl->dev_type |= BDE_ICS_DEV_TYPE | BDE_SWITCH_DEV_TYPE; + ctrl->pci_device = NULL; /* No PCI bus */ + + /* Map in the device */ + paddr = BCM_ICS_CMIC_BASE; + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(paddr, 0x10000); + ctrl->phys_address = paddr; + + dev_rev_id = *((unsigned int *)(KSEG1ADDR(paddr + 0x178))); + + ctrl->bde_dev.device = dev_rev_id & 0xFFFF; + ctrl->bde_dev.rev = (dev_rev_id >> 16) & 0xFF; + + ctrl->iLine = 5; /* From raptor linux BSP */ + + ctrl->isr = NULL; + ctrl->isr_data = NULL; + _bde_add_device(); + printk("Created ICS device ..%x\n", ctrl->bde_dev.base_address); + } + + return 0; +} + +#else /* !BCM_ICS */ + +extern struct pci_bus *pci_find_bus(int domain, int busnr); + +/* + * PCI device table. + * Populated from the include/soc/devids.h file. + */ + +static const struct pci_device_id _id_table[] = { + { BROADCOM_VENDOR_ID, BCM5675_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM5676_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56218X_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56218_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56219_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56218R_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56219R_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56214_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56215_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56214R_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56215R_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56216_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56217_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56212_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56213_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56230_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56231_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53718_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53714_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53716_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56018_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56014_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56224_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56225_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56226_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56227_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56228_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56229_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56024_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56025_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53724_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53726_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56100_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56101_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56102_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56105_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56106_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56107_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56110_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56111_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56112_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56115_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56116_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56117_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56300_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56301_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56302_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56303_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56304_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56404_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56305_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56306_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56307_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56308_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56309_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56310_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56311_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56312_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56313_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56314_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56315_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56316_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56317_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56318_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56319_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#ifndef EXCLUDE_BCM56324 + { BROADCOM_VENDOR_ID, BCM56322_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56324_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#endif /* EXCLUDE_BCM56324 */ + { BROADCOM_VENDOR_ID, BCM53312_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53313_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53314_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53324_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53333_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53334_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53342_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53343_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53344_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53346_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53347_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53393_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53394_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53300_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53301_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53302_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56500_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56501_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56502_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56503_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56504_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56505_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56506_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56507_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56508_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56509_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56510_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56511_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56512_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56513_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56514_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56516_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56517_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56518_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56519_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56580_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56620_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56624_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56626_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56628_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56629_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56680_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56684_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56700_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56701_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56720_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56721_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56725_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56800_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56801_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56802_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56803_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56820_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56821_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56822_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56823_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56825_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56630_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56634_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56636_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56638_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56639_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56538_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56520_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56521_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56522_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56524_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56526_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56534_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56685_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56689_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56331_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56333_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56334_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56338_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56320_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56321_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56132_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56134_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88732_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56140_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56142_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56143_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56144_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56146_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56147_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56149_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56150_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56151_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56152_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56613_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56930_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56931_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56935_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56936_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56939_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56840_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56841_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56842_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56843_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56844_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56845_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56846_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56847_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56549_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56053_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56838_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56831_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56835_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56849_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56742_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56743_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56744_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56745_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56746_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56640_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56548_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56547_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56346_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56345_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56344_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56342_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56340_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56049_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56048_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56047_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56042_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56041_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56040_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56643_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56644_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56648_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56649_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56540_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56541_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56542_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56543_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56544_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56545_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56546_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56044_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56045_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56046_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88230_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88030_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88034_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88039_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88231_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88235_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88236_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88239_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM55440_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56440_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56441_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56442_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56443_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56445_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56446_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56447_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56448_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56449_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56240_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56241_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56242_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56243_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56245_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56246_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM55450_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM55455_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56260_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56270_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56271_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56272_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53460_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53461_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56261_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56262_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56263_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56265_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56266_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56267_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56268_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56233_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56460_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56461_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56462_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56463_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56465_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56466_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56467_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56468_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56246_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56248_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56450_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56452_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56454_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56455_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56456_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56457_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56458_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56850_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56851_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56852_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56853_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56854_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56855_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56834_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56750_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56830_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM55440_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM55441_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56060_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56062_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56063_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56064_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56065_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56066_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53401_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53411_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53402_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53412_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53403_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53413_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53404_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53414_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53405_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53415_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53406_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53416_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53408_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53418_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53454_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53455_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53456_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53457_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53422_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53424_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53426_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53365_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53369_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56960_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56961_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56962_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56963_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56930_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56968_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56970_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56971_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56972_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56974_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56975_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56168_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56169_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56560_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56561_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56562_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56565_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56566_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56567_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56670_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56671_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56672_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56675_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56568_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56760_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56761_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56762_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56764_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56765_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56766_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56768_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56069_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56068_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56160_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56162_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56163_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56164_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56166_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53440_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53443_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53442_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53434_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56965_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56969_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56966_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56967_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56170_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56172_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56174_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53570_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53575_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#ifdef BCM_ROBO_SUPPORT + { BROADCOM_VENDOR_ID, BCM47XX_ENET_ID, PCI_ANY_ID, PCI_ANY_ID }, +#ifdef KEYSTONE + { BROADCOM_VENDOR_ID, BCM53000_GMAC_ID, PCI_ANY_ID, PCI_ANY_ID }, +#endif +#endif + { SANDBURST_VENDOR_ID, QE2000_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { SANDBURST_VENDOR_ID, BCM88020_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { SANDBURST_VENDOR_ID, BCM88025_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9656, PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9056, PCI_ANY_ID, PCI_ANY_ID }, + { BCM53000_VENDOR_ID, BCM53000PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#ifdef BCM_PETRA_SUPPORT + { BROADCOM_VENDOR_ID, BCM88650_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88350_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88351_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88450_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88451_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88550_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88551_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88552_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88651_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88654_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { PCP_PCI_VENDOR_ID, PCP_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { ACP_PCI_VENDOR_ID, ACP_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88660_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88670_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88671_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88671M_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88672_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88673_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88674_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88675_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88675M_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88676_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88676M_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88677_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88678_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88679_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88370_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88371_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88371M_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88375_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88470_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88470P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88471_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88473_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88474_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88474H_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88476_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88477_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + + + { BROADCOM_VENDOR_ID, BCM88270_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88272_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88273_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88278_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88279_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + + { BROADCOM_VENDOR_ID, BCM8206_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + + { BROADCOM_VENDOR_ID, BCM88376_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88376M_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88377_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88378_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88379_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88680_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88681_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88682_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88683_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88684_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88685_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88380_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88381_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88690_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88202_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88360_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88361_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88363_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88460_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88461_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88560_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88561_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88562_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88661_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88664_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#endif +#ifdef BCM_DFE_SUPPORT + { BROADCOM_VENDOR_ID, BCM88750_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88753_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88755_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88770_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88773_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88774_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88775_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88776_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88777_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#ifndef DNX_IGNORE_FE3200 + { BROADCOM_VENDOR_ID, BCM88950_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#endif + { BROADCOM_VENDOR_ID, BCM88953_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88954_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88955_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88956_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88752_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88772_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88952_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#endif +#ifdef BCM_DNXF_SUPPORT + { BROADCOM_VENDOR_ID, BCM88790_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88791_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88792_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88793_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88794_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88795_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88796_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88797_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88798_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88799_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8879A_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8879B_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8879C_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8879D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8879F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#endif + { BROADCOM_VENDOR_ID, BCM56860_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56861_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56862_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56864_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56865_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56866_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56867_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56868_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56833_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56832_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56836_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56870_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56980_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56873_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53540_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53547_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53548_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53549_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { 0, 0, 0, 0 } +};; + +MODULE_DEVICE_TABLE(pci, _id_table); + +#define pci_bus_b(n) list_entry(n, struct pci_bus, node) +#define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list) +#define MAX_RC_NUM 4 + +static struct pci_bus * +pci_do_bus_find(struct pci_bus* bus, int rc, int vendor, int device) +{ + struct list_head *tmp; + struct pci_dev *dev; + struct pci_bus *sub_bus; + int func = 0; + + if (unlikely(list_empty(&bus->children))) { + return NULL; + } + list_for_each(tmp, &bus->children) { + sub_bus = pci_bus_b(tmp); + dev = sub_bus->self; + func = dev->devfn & 0x7; + if (dev->vendor == vendor && dev->device == device && rc == func) { + if (debug >= 1) { + gprintk("pci_do_bus_find: dev->vendor = 0x%x, dev->device = 0x%x on rc(%d)\n", + dev->vendor, dev->device, rc); + } + return sub_bus; + } + } + return NULL; +} + +static struct pci_dev * +_pci_do_bus_dev_find(struct pci_bus* bus, unsigned int vendor, unsigned int device) +{ + struct list_head *tmp; + struct pci_dev *dev; + + if (unlikely(list_empty(&bus->devices))) { + return NULL; + } + list_for_each(tmp, &bus->devices) { + dev = pci_dev_b(tmp); + if (dev->vendor == vendor && (device == PCI_ANY_ID || dev->device == device)) { + if (debug >= 1) { + gprintk("_pci_do_rc_dev_find: vendor = %x, device = %x\n", vendor, device); + } + return dev; + } + } + return NULL; +} + +static struct pci_dev * +pci_do_rc_dev_find(int rc) +{ + struct pci_bus *root_bus = pci_find_bus(0,0); + struct pci_bus *bus_rc = NULL; + struct pci_dev *dev_on_rc = NULL; + unsigned int pci_dev_id = 0; + + if(NULL == root_bus) { + if (debug >= 1) gprintk("Not find root bus\n"); + return NULL; + } + bus_rc = pci_do_bus_find(root_bus, rc, 0x184e, 0x1004); + if (NULL == bus_rc) { + if (debug >= 1) { + gprintk("Not find vendor(0x184e) device(0x1004) bus\n"); + } + return NULL; + } + for(pci_dev_id = 0; pci_dev_id < sizeof(_id_table)/sizeof(struct pci_device_id); pci_dev_id++) { + dev_on_rc = _pci_do_bus_dev_find(bus_rc, _id_table[pci_dev_id].vendor, _id_table[pci_dev_id].device); + if (NULL != dev_on_rc) { + return dev_on_rc; + } + } + if (debug >= 1) { + gprintk("Not find device at rc(%d)\n", rc); + } + return NULL; +} + +/* + * Function: p2p_bridge + * + * Purpose: + * Finalize initialization secondary PCI-PCI bridge. + * Parameters: + * membase - start of memory address space for secondary PCI bus + * Returns: + * 0 + * Notes: + * The membase depends on the processor architecture, and is + * derived from the memory space addresses set up by the kernel. + */ +static int +p2p_bridge(void) +{ + struct pci_dev *dev, *dev_on_rc; + uint16 cmd; + uint16 mem_base; + uint16 mem_limit; + uint8 bridge_ctrl; + uint8 rc_index; + + if ((dev = PCI_FIND_DEV(DC21150_VENDOR_ID, DC21150_DEVICE_ID, NULL)) != NULL || + (dev = PCI_FIND_DEV(HINT_HB4_VENDOR_ID, HINT_HB4_DEVICE_ID, NULL)) != NULL || + (dev = PCI_FIND_DEV(PI7C8150_VENDOR_ID, PI7C8150_DEVICE_ID, NULL)) != NULL) { + + if (debug >= 1) gprintk("fixing up PCI-to-PCI bridge\n"); + /* Adjust command register */ + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + /* Disable device */ + pci_write_config_word(dev, PCI_COMMAND, 0); + /* Initialize non-prefetchable memory window if needed */ + pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base); + if (mem_base == 0) { + mem_base = (uint16)((_pci_mem_start & 0xFFF00000) >> 16); + mem_limit = (uint16)((_pci_mem_end & 0xFFF00000) >> 16); + pci_write_config_word(dev, PCI_MEMORY_BASE, mem_base); + pci_write_config_word(dev, PCI_MEMORY_LIMIT, mem_limit); + } + /* Enable PCI clocks on remote end */ + pci_write_config_word(dev, PCI_CFG_DEC21150_SEC_CLK, 0); + /* Re-enable config space */ + pci_write_config_word(dev, PCI_COMMAND, cmd); + + /* Avoid DMA data corruption */ + if (dev->vendor == HINT_HB4_VENDOR_ID) { + /* Fix for HiNT bridge and BCM4704 DMA problem */ + if ((dev = PCI_FIND_DEV(BCM4704_VENDOR_ID, BCM4704_DEVICE_ID, NULL)) != NULL) { + /* Reset PrefetchEn (PE) */ + pci_write_config_dword(dev, 0x8c, 1); + if (debug >= 1) { + gprintk("reset PrefetchEn on BCM4704 when HiNT bridge is present\n"); + } + } + } + } + /* Enable fast back-to-back read/write */ + if ((dev = PCI_FIND_DEV(PI7C8150_VENDOR_ID, PI7C8150_DEVICE_ID, NULL)) != NULL) { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_FAST_BACK; + pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bridge_ctrl); + bridge_ctrl |= PCI_BRIDGE_CTL_FAST_BACK; + pci_write_config_word(dev, PCI_COMMAND, 0); + pci_write_config_byte(dev, PCI_BRIDGE_CONTROL, bridge_ctrl); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + /* Netlogic XLP CPU */ + for(rc_index = 0; rc_index < MAX_RC_NUM; rc_index++) { + dev_on_rc = pci_do_rc_dev_find(rc_index); + if (dev_on_rc != NULL ) { + dev = PCI_FIND_DEV(0x184e, 0x1004, NULL); + if (dev != NULL ) { + pci_write_config_dword(dev,0x78,MAX_PAYLOAD_256B | + MAX_READ_REQ_256B); + } + } + } + if ((dev = PCI_FIND_DEV(0x14e4, 0xb634, NULL)) != NULL) { + pci_write_config_dword(dev,0x78,MAX_PAYLOAD_256B | + MAX_READ_REQ_256B); + } + + if ((dev = PCI_FIND_DEV(PCI_VNDID_PERICOM, PCI_DEVID_PI7C9X130, NULL)) != NULL) { + /* + * Configure the PCIE cap: Max payload size: 256, Max Read + * Request size: 256, disabling relax ordering. + * Writes to the PCIE capability device control register + */ + pci_write_config_dword(dev, DEV_CTRL_REG, + MAX_PAYLOAD_256B | MAX_READ_REQ_256B); + } + + if ((dev = PCI_FIND_DEV(FSL_VENDOR_ID, FSL8548PCIE_DEVICE_ID, NULL)) != NULL || + (dev = PCI_FIND_DEV(FSL_VENDOR_ID, FSL2020EPCIE_DEVICE_ID, NULL)) != NULL) { + /* + * Configure the PCIE cap: Max payload size: 256, Max Read + * Request size: 256, disabling relax ordering. + * Writes to the PCIE capability device control register + */ + pci_write_config_dword(dev, FSL8548PCIE_DEV_CTRL_REG, + MAX_PAYLOAD_256B | MAX_READ_REQ_256B); + } + if ((dev = PCI_FIND_DEV(BCM4716_VENDOR_ID, BCM4716PCIE_DEVICE_ID, NULL)) != NULL || + (dev = PCI_FIND_DEV(BCM53000_VENDOR_ID, BCM53000PCIE_DEVICE_ID, NULL)) != NULL) { + uint32 tmp, maxpayld, device_bmp=0, mask; + unsigned long addr; + uint16 tmp16, tmp161; + int i, bus0 = -1, bus1 = -1, port; + struct pci_dev *pcie0, *pcie1; + + pcie0 = dev; + bus0 = dev->bus->number; + if ((pcie1 = PCI_FIND_DEV(BCM53000_VENDOR_ID, BCM53000PCIE_DEVICE_ID, pcie0)) != NULL) { + bus1 = pcie1->bus->number; + } + + for(i = 0; i < _ndevices; i++) { + bde_ctrl_t *ctrl = _devices + i; + + mask = BDE_SWITCH_DEV_TYPE | BDE_PCI_DEV_TYPE; + if ((ctrl->dev_type & mask) == mask) { + if (ctrl->pci_device->bus->number == bus0) { + device_bmp |= 1 << 0; + } + if (ctrl->pci_device->bus->number == bus1) { + device_bmp |= 1 << 1; + } + } + } + + /* configure the PCIE cap: Max payload size: 256, Max Read + * Request size: 256, disabling relax ordering. + * Writes to the PCIE capability device control register + */ + + i = 0; + while(device_bmp) { + if (device_bmp & (1 << i)){ + port = i ; + pci_read_config_dword(BCM53000PCIE_DEV(port), + BCM53000PCIE_DEV_CAP_REG, &tmp); + maxpayld = (tmp & BCM53000PCIE_MAX_PAYLOAD_MASK); + if (debug >= 1) { + gprintk("port %d\n",port); + gprintk("DevCap (@%x): 0x%x%c\n", BCM53000PCIE_DEV_CAP_REG, tmp, + (maxpayld != BCM53000PCIE_CAP_MAX_PAYLOAD_256B) ? ' ':'\n'); + } + if (maxpayld != BCM53000PCIE_CAP_MAX_PAYLOAD_256B) { + addr = BCM53000PCIE_BASE(port); + addr |= (BCM53000PCIE_SROM_SPACE | BCM53000PCIE_SPROM_OFFSET); + tmp16 = *((uint16 *)addr); + if (debug >= 1){ + gprintk("addr %lx spromData.MaxPayloadSize: 0x%x\n", addr, tmp16); + } + mask = BCM53000PCIE_SPROM_MAX_PAYLOAD_MASK; + if ((tmp16 & mask) != BCM53000PCIE_SPROM_MAX_PAYLOAD_256B) { + tmp161 = (tmp16 & ~mask) | BCM53000PCIE_SPROM_MAX_PAYLOAD_256B; + *((uint16 *)addr) = tmp161; + if (debug >= 1) { + tmp16 = 0; + tmp16 = *((uint16 *)addr); + gprintk("Enable spromData.MaxPayloadSize to 1 (256 bytes): " + "0x%x (%s w/ 0x%x)\n", tmp161, + ((tmp16 & mask) == BCM53000PCIE_SPROM_MAX_PAYLOAD_256B) ? + "Success":"Fail", + tmp16); + } + } + pci_read_config_dword(BCM53000PCIE_DEV(port), + BCM53000PCIE_DEV_CAP_REG, &tmp); + if (debug >= 1){ + gprintk("DevCap (@%x): now is 0x%x\n\n", + BCM53000PCIE_DEV_CAP_REG, tmp); + } + } + + addr = BCM53000PCIE_BASE(port); + addr |= (BCM53000PCIE_FUNC0_COFIG_SPACE | BCM53000PCIE_DEV_CTRL_REG); + tmp16 = *((uint16 *)addr); + if (debug >= 1) { + gprintk("DevControl (@%x): 0x%x\n", BCM53000PCIE_DEV_CTRL_REG, tmp16); + } + if (!(tmp16 & MAX_PAYLOAD_256B) || !(tmp16 & MAX_READ_REQ_256B)) { + tmp161 = tmp16 | MAX_PAYLOAD_256B | MAX_READ_REQ_256B; + *((uint16 *)addr) = tmp161; + if (debug >= 1) { + tmp16 = 0; + tmp16 = *((uint16 *)addr); + gprintk("addr %lx Enable DevControl MaxPayloadSize to 1 (256 bytes): " + "0x%x (%s w/ 0x%x)\n", addr, tmp161, + (tmp16 & MAX_PAYLOAD_256B) ? "Success":"Fail", + tmp16); + gprintk("Enable DevControl MaxReadRequestSize to 1 (256 bytes): " + "0x%x (%s w/ 0x%x)\n\n", tmp161, + (tmp16 & MAX_READ_REQ_256B) ? "Success":"Fail", + tmp16); + } + } + device_bmp &= ~(1 << i); + } + i++; + } + } + + /* + * Configure max payload to 512 on all ports in the PLX8608/PLX8617. + * The device supports 128, 512, and 1024 max payload sizes. + */ + dev = NULL; + while ((dev = PCI_FIND_DEV(PCI_VENDOR_ID_PLX, PCI_ANY_ID, dev)) != NULL) { + if ((dev->device == PLX_PEX8608_DEV_ID) || + (dev->device == PLX_PEX8617_DEV_ID)) { + uint16 ctrl_reg; + pci_read_config_word(dev, PLX_PEX86XX_DEV_CTRL_REG, &ctrl_reg); + ctrl_reg = (ctrl_reg & ~(7<<5)) | MAX_PAYLOAD_512B; + pci_write_config_word(dev, PLX_PEX86XX_DEV_CTRL_REG, ctrl_reg); + } + } + return 0; +} + +#ifdef BCM_PLX9656_LOCAL_BUS + +#define PLX_LAS0_BA 0x00000004 /* LAS0 Local Base Address Remap */ +#define PLX_LAS1_BA 0x000000f4 /* LAS1 Local Base Address Remap */ +#define PLX_LAS_EN 0x00000001 /* Space Enable bit */ + +#define PLX_MMAP_PCIBAR0 0 /* Memory-Mapped Config (PCIBAR0) */ +#define PLX_LAS0_PCIBAR2 2 /* Local Address Space 0 (PCIBAR2) */ +#define PLX_LAS1_PCIBAR3 3 /* Local Address Space 1 (PCIBAR3) */ + +STATIC int +_plx_las_bar_get(struct pci_dev *dev) +{ + void *local_config_addr; + int bar = -1; + + local_config_addr = IOREMAP(pci_resource_start(dev, PLX_MMAP_PCIBAR0), + pci_resource_len(dev, PLX_MMAP_PCIBAR0)); + if (local_config_addr) { + uint32 las_remap_reg; + /* + * Make sure LAS0BA or LAS1BA is enabled before returning + * BAR that will be used to access the Local Bus + */ + las_remap_reg = ioread32(local_config_addr + PLX_LAS0_BA); + if (las_remap_reg & PLX_LAS_EN) { + bar = PLX_LAS0_PCIBAR2; + } else { + las_remap_reg = ioread32(local_config_addr + PLX_LAS1_BA); + if (las_remap_reg & PLX_LAS_EN) { + bar = PLX_LAS1_PCIBAR3; + } + } + } + iounmap(local_config_addr); + return bar; +} +#endif /* BCM_PLX9656_LOCAL_BUS */ + +static void +_shbde_log_func(int level, const char *str, int param) +{ + level = (level >= SHBDE_DBG) ? 1 : 0; + if (debug >= level) { + gprintk("%s (%d)\n", str, param); + } +} +/* + * Function: _device_rescan_validate + * + * Purpose: + * Check if the device is ever probed or not. + * Parameters: + * dev - Linux PCI device structure + * Returns: + * >= 0 : dev is ever probed + * reutrn value is the index point to the _devices[] + * -1 : dev is not probed before. + */ +static int +_device_rescan_validate(struct pci_dev *dev) +{ + bde_ctrl_t *ctrl; + int i; + + if (PCI_FUNC(dev->devfn) > 0) { + return -1; + } + ctrl = NULL; + for (i = 0; i < _ndevices; i ++) { + ctrl = _devices + i; + /* check the device id */ + if (dev->device == ctrl->bde_dev.device) { + /* check the bus number */ + if ((dev->bus)) { + if ((dev->bus->number == ctrl->bus_no) && + (pci_domain_nr(dev->bus) == ctrl->domain_no)) { + return i; + } + } + } + } + return -1; +} + +#ifdef CONFIG_PCI_MSI + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) +/** + * _pci_msix_table_size - return the number of device's MSI-X table entries + * @dev: pointer to the pci_dev data structure of MSI-X device function + */ +static int +_pci_msix_table_size(struct pci_dev *dev) +{ + int nr_entries = 0; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,110)) + u16 control; + int pos; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos) { + pci_read_config_word(dev, msi_control_reg(pos), &control); + nr_entries = msix_table_size(control); + } +#else +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)) +{ + /* Pass large entry value to enable MSIX to get # of entires */ + struct msix_entry *entries; + entries = kmalloc(sizeof(struct msix_entry) * + PCI_MSIX_FLAGS_QSIZE, GFP_KERNEL); + if (entries != NULL) { + nr_entries = pci_enable_msix(dev, + entries, PCI_MSIX_FLAGS_QSIZE); + if (nr_entries < 0) { + nr_entries = 0; + } + kfree(entries); + } +} +#else + nr_entries = pci_msix_vec_count(dev); +#endif +#endif + + return nr_entries; +} +#endif + +static int +_msi_connect(bde_ctrl_t *ctrl) +{ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + int ret; + if (ctrl->use_msi == PCI_USE_INT_MSIX) { + int i; + ret = _pci_msix_table_size(ctrl->pci_device); + + if (ret == 0) { + /* MSI-X failed */ + gprintk("MSI-X not supported.\n"); + goto er_intx; + } + ctrl->entries = kcalloc(ret, sizeof(struct msix_entry)*ret, GFP_KERNEL); + + if (!ctrl->entries) { + goto er_intx; + } + /* We need only that much interrupt vecotrs */ + ctrl->msix_cnt = ret/4; + if (unlikely(debug > 1)) + gprintk("MSIX Table size = %d\n", ctrl->msix_cnt); + for (i = 0; i < ctrl->msix_cnt; i++) + ctrl->entries[i].entry = i; + + ret = pci_enable_msix(ctrl->pci_device, + ctrl->entries, ctrl->msix_cnt); + if (ret > 0) { + /* Not enough vectors available , Retry MSI-X */ + gprintk("Retrying with MSI-X interrupts = %d\n", ret); + ctrl->msix_cnt = ret; + ret = pci_enable_msix(ctrl->pci_device, + ctrl->entries, ctrl->msix_cnt); + if (ret != 0) + goto er_intx_free; + } else if (ret < 0) { + /* Error */ + goto er_intx_free; + } else { + gprintk("Enabled MSI-X interrupts = %d\n", ctrl->msix_cnt); + } + } +#endif + + if (ctrl->use_msi == PCI_USE_INT_MSI) { + if (pci_enable_msi(ctrl->pci_device) == 0) { + ctrl->iLine = ctrl->pci_device->irq; + } else { + /* MSI failed */ + gprintk("Failed to initialize MSI interrupts.\n"); + goto er_intx; + } + } else { + /* failed */ + gprintk("Not MSI/MSIC interrupt.\n"); + goto er_intx; + } + return 0; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) +er_intx_free: + gprintk("Failed to enable MSI-X interrupts = %d\n", ret); + kfree(ctrl->entries); +#endif +er_intx: + return -1; + +} + +static int +_msi_disconnect(bde_ctrl_t *ctrl) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + if (ctrl->use_msi == PCI_USE_INT_MSIX) { + pci_disable_msix(ctrl->pci_device); + kfree(ctrl->entries); + ctrl->msix_cnt = 0; + } +#endif + if (ctrl->use_msi == PCI_USE_INT_MSI) { + pci_disable_msi(ctrl->pci_device); + } else { + gprintk("MSI not used\n"); + } + return 0; +} + +#endif + + +static void +config_pci_intr_type(bde_ctrl_t *ctrl) +{ + +#ifdef CONFIG_PCI_MSI + int ret; + + ctrl->use_msi = use_msi; + if (unlikely(debug > 1)) + gprintk("%s: msi = %d\n", __func__, ctrl->use_msi); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + if (ctrl->use_msi == PCI_USE_INT_MSIX) { + /* check for support MSIX vector */ + ret = _pci_msix_table_size(ctrl->pci_device); + if (ret == 0) { + gprintk("%s: Zero MSIX table size\n", __func__); + ctrl->use_msi = PCI_USE_INT_MSI; + } + } +#endif + + if (ctrl->use_msi == PCI_USE_INT_MSI) { + /* check for support MSI vector */ + ret = pci_enable_msi(ctrl->pci_device); + if (ret < 0) { + ctrl->use_msi = PCI_USE_INT_INTX; + gprintk("%s: Failed to enable MSI\n", __func__); + } else { + pci_disable_msi(ctrl->pci_device); + } + } +#else + ctrl->use_msi = PCI_USE_INT_INTX; +#endif +} + +/* + * Function: _pci_probe + * + * Purpose: + * Device initialization callback used by the Linux PCI + * subsystem. Called as a result of pci_register_driver(). + * Parameters: + * dev - Linux PCI device structure + * Returns: + * 0 + */ +static int +_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) +{ + bde_ctrl_t *ctrl; + resource_size_t paddr; + uint16 cmd = 0; + uint32 bar_len; + int cmic_bar; + int baroff = 0; + int iproc = 0; + uint32 gmac_base = 0; + int plx_dev = 0; + int eth_dev = 0; + int cpu_dev = 0; + int update_devid = 0; + int paxb_core = 0; + int rescan = 0, rescan_idx = -1; + shbde_hal_t shared_bde, *shbde = &shared_bde; + + if (debug >= 4) {gprintk("probing: vendor_id=0x%x, device_id=0x%x\n", dev->vendor, dev->device);} + if (nodevices == 1) { + return 0; + } + + /* Initialize Linux hardware abstraction for shared BDE functions */ + linux_shbde_hal_init(shbde, _shbde_log_func); + + /* + * If an AXI-based switch device has been found already, then it means + * that the AXI bus has been probed, and that we should ignore devices + * found on PCI bus zero. + */ + +#if defined(IPROC_CMICD) + if ((dev->bus) && (dev->bus->number == 0)) { + int i; + uint32 mask = BDE_SWITCH_DEV_TYPE | BDE_AXI_DEV_TYPE; + + for (i = 0; i < _ndevices; i++) { + ctrl = _devices + i; + + if ((ctrl->dev_type & mask) == mask) { + return 0; + } + } + } +#endif /* IPROC_CMICD */ + + /* + * Note that a few supported devices have a non-Broadcom PCI vendor ID, + * but since none of their associated PCI device IDs collide with the + * Broadcom device IDs, the probe code below only checks the device ID. + */ + + switch (dev->device) { + case PCI_DEVICE_ID_PLX_9056: +#ifdef DNX_TEST_BOARD + break; /* a PCIe bridge to a non PCIe device should be treated as the device */ +#endif /* DNX_TEST_BOARD */ + case PCI_DEVICE_ID_PLX_9656: + plx_dev = 1; + break; +#if defined (BCM_ROBO_SUPPORT) && defined(KEYSTONE) + case BCM53000_GMAC_ID: + eth_dev = 1; + gmac_base = SB_ENUM_BASE; + break; +#endif +#if defined (BCM_ROBO_SUPPORT) + case BCM47XX_ENET_ID: + eth_dev = 1; + break; +#endif + case BCM53000PCIE_DEVICE_ID: + cpu_dev = 1; + break; + /* + * The device ID for 56500, 56100 and 56300 family of devices may + * be incorrect just after a PCI HW reset. It needs to be read + * again after stabilization. + */ + case BCM56102_DEVICE_ID: + case BCM56504_DEVICE_ID: + case BCM56304_DEVICE_ID: + case BCM56314_DEVICE_ID: + case BCM56112_DEVICE_ID: + update_devid = 1; + break; + default: + break; + } + + /* Check if the device is ever probed. */ + rescan_idx = _device_rescan_validate(dev); + if (rescan_idx != -1) { + rescan = 1; + } + + ctrl = NULL; + if (plx_dev) { +#if defined(BCM_PLX9656_LOCAL_BUS) + /* PLX chip itself won't be part of _devices[]. */ + baroff = _plx_las_bar_get(dev); + if (baroff == -1) { + gprintk("No Local Address Space enabled in PLX\n"); + return 0; + } + ctrl = &plx_ctrl; + num_plx++; +#endif + } else if (eth_dev) { + if (_ether_ndevices >= LINUX_BDE_MAX_ETHER_DEVICES) { + return 0;; + } + ctrl = _devices + _ndevices++; + _ether_ndevices++; + ctrl->dev_type |= BDE_ETHER_DEV_TYPE; + ctrl->iLine = dev->irq; + if (debug >= 1) + gprintk("Found PCI device %04x:%04x as Ethernet device\n", + dev->vendor, dev->device); + } else if (cpu_dev) { + if (_cpu_ndevices >= LINUX_BDE_MAX_CPU_DEVICES) { + return 0;; + } + ctrl = _devices + _ndevices++; + _cpu_ndevices++; + ctrl->dev_type |= BDE_CPU_DEV_TYPE; + if (debug >= 1) + gprintk("Found PCI device %04x:%04x as CPU device\n", + dev->vendor, dev->device); + } else { + if (PCI_FUNC(dev->devfn) > 0) { + return 0; + } + if (_switch_ndevices >= LINUX_BDE_MAX_SWITCH_DEVICES) { + return 0;; + } + + if (rescan) { + if (debug >= 1) { + gprintk("PCI device %04x:%04x is re-probed \n", + dev->vendor, dev->device); + } + ctrl = _devices + rescan_idx; + ctrl->dev_state = BDE_DEV_STATE_CHANGED; + } else { + ctrl = _devices + _ndevices++; + _switch_ndevices++; + ctrl->dev_type |= BDE_SWITCH_DEV_TYPE; + ctrl->domain_no = pci_domain_nr(dev->bus); + ctrl->bus_no = dev->bus->number; + ctrl->dev_state = BDE_DEV_STATE_NORMAL; + } + + /* Save shared BDE HAL in device structure */ + memcpy(&ctrl->shbde, shbde, sizeof(ctrl->shbde)); + + if (update_devid) { + /* Re-read the device ID */ + pci_read_config_word(dev, + PCI_DEVICE_ID, + &ctrl->bde_dev.device); + dev->device = ctrl->bde_dev.device; + } + + if (debug >= 4) {gprintk("Enabling PCI device : vendor_id=0x%x, device_id=0x%x\n", dev->vendor, dev->device);} + if (pci_enable_device(dev)) { + gprintk("Cannot enable PCI device : vendor_id = %x, device_id = %x\n", + dev->vendor, dev->device); + } + + /* FIXME: "workarounds" previously called "total h_acks" */ + /* + * These are workarounds to get around some existing + * kernel problems :( + */ + + /* + * While probing we determine the overall limits for the PCI + * memory windows across all devices. These limits are used + * later on by the PCI-PCI bridge code. + */ + if (pci_resource_start(dev, baroff) < _pci_mem_start) { + _pci_mem_start = pci_resource_start(dev, baroff); + } + if (pci_resource_end(dev, baroff) > _pci_mem_end) { + _pci_mem_end = pci_resource_end(dev, baroff); + } + +#ifdef CONFIG_SANDPOINT + /* + * Something wrong with the PCI subsystem in the mousse kernel. + * The device is programmed correctly, but the irq in the pci + * structure is hosed. This checks for the hosed-ness and fixes it. + */ + if (dev->irq > 100) { + dev->irq = 2; + gprintk("irq problem: setting irq = %d\n", dev->irq); + } +#endif + +#ifdef CONFIG_BMW + /* + * PCI subsystem does not always program the system correctly. + */ + if (dev->irq < 16 && dev->irq != 2) { + dev->irq = 2; + gprintk("irq problem: setting irq = %d\n", dev->irq); + } +#endif + +#ifdef CONFIG_IDT_79EB334 + /* + * IDT kernel is not currently mapping interrupts correctly + * Hardwired to core mips interrupt, irq 3 for kernel 2.4.18 + */ + if (dev->irq != 3) { + dev->irq = 3; + gprintk("irq problem: setting irq = %d\n", dev->irq); + } +#endif + +#ifdef CONFIG_BCM94702_CPCI + /* + * Hardwired to core mips interrupt irq 6 on MBZ + */ + if (dev->irq != 6) { + dev->irq = 6; + gprintk("irq problem: setting irq = %d\n", dev->irq); + } +#endif + + if ((PCI_FIND_DEV(BCM4704_VENDOR_ID, BCM4704_DEVICE_ID, NULL)) != NULL) { + /* + * Decrease the PCI bus priority for the CPU for better overall + * system performance. This change significantly reduces the + * number of PCI retries from other devices on the PCI bus. + */ + void * _mc_vbase = IOREMAP(BCM4704_MEMC_BASE, 0x1000); + int priorinv = 0x80; + static int done = 0; + if (!done) { + done = 1; + writel(priorinv, _mc_vbase + BCM4704_MEMC_PRIORINV); + if (debug >= 1) + gprintk("set BCM4704 PriorInvTim register to 0x%x\n", priorinv); + iounmap(_mc_vbase); + } + } + + if ((PCI_FIND_DEV(SIBYTE_PCI_VENDOR_ID, SIBYTE_PCI_DEVICE_ID, NULL)) != NULL) { + /* + * The BCM91125CPCI CPU boards with a PCI-PCI bridge use the same + * interrupt line for all switch ships behind the bridge. + */ + if (PCI_FIND_DEV(DC21150_VENDOR_ID, DC21150_DEVICE_ID, NULL) || + PCI_FIND_DEV(HINT_HB4_VENDOR_ID, HINT_HB4_DEVICE_ID, NULL) || + PCI_FIND_DEV(PI7C8150_VENDOR_ID, PI7C8150_DEVICE_ID, NULL)) { + /* + * By default we try to guess the correct IRQ based on the design. + * For now we only look at the bridge vendor, but it may be necessary + * to look at the switch chip configuration as well. + */ + if (forceirq == -1) { + if ((PCI_FIND_DEV(HINT_HB4_VENDOR_ID, HINT_HB4_DEVICE_ID, NULL)) || + ((dev->device == BCM5674_DEVICE_ID) && + (PCI_FIND_DEV(PI7C8150_VENDOR_ID, PI7C8150_DEVICE_ID, NULL)))) { + forceirq = 58; + } else { + forceirq = 56; + } + } + } + } + + if (((PCI_FIND_DEV(BCM58525_PCI_VENDOR_ID, BCM58525_PCI_DEVICE_ID, NULL)) != NULL) || + ((PCI_FIND_DEV(BCM58525_PCI_VENDOR_ID, BCM58522_PCI_DEVICE_ID, NULL)) != NULL) || + ((PCI_FIND_DEV(BCM58712_PCI_VENDOR_ID, BCM58712_PCI_DEVICE_ID, NULL)) != NULL) ) { + /* BCM58525/BCM58712 CPU boards support 128 Max payload size */ + if (maxpayload) { + maxpayload = 128; + if (debug >= 1) gprintk("force max payload size to 128\n"); + } + } + + if (forceirq > 0 && dev->irq != (uint32) forceirq) { + if (forceirqubm & (1U << (_ndevices - 1))) { + dev->irq = forceirq; + if (debug >= 1) gprintk("force irq to %d\n", forceirq); + } + } else if (debug >= 1) gprintk("found irq %d\n", dev->irq); + + ctrl->iLine = dev->irq; + if (unlikely(debug > 1)) + gprintk("%s:irq = %d\n",__func__, ctrl->iLine); + + if (shbde_pci_is_pcie(shbde, dev)) { + /* Set PCIe max payload */ + shbde_pci_max_payload_set(shbde, dev, maxpayload); + } else { + /* Set PCI retry to infinite on non-PCIe switch device */ + pci_write_config_word(dev, 0x40, 0x0080); + if (debug >= 1) gprintk("set DMA retry to infinite on switch device\n"); + } + } + +#if defined(BCM_DFE_SUPPORT) + switch (dev->device) { + case BCM88750_DEVICE_ID: + case BCM88753_DEVICE_ID: + case BCM88755_DEVICE_ID: + case BCM88770_DEVICE_ID: + case BCM88773_DEVICE_ID: + case BCM88774_DEVICE_ID: + case BCM88775_DEVICE_ID: + case BCM88776_DEVICE_ID: + case BCM88777_DEVICE_ID: + case BCM88950_DEVICE_ID: + case BCM88953_DEVICE_ID: + case BCM88954_DEVICE_ID: + case BCM88955_DEVICE_ID: + case BCM88956_DEVICE_ID: + case BCM88752_DEVICE_ID: + case BCM88772_DEVICE_ID: + case BCM88952_DEVICE_ID: + + /* + * For DMA transactions - set Max_Payload_Size and + * Max_Read_Request_Size to 128 bytes. + */ + pci_write_config_byte(dev, 0xb5, 0x0c); + pci_write_config_byte(dev, 0xb4, 0x0); + break; + default: + break; + } +#endif /* BCM_DFE_SUPPORT */ + +#if defined(BCM_DNXF_SUPPORT) + /*All Ramon devices from 0x8790 to 0x879F*/ + if ((dev->device & BCM_DNXF_DEVID_MASK) == BCM88790_DEVICE_ID) { + /* + * For DMA transactions - set Max_Payload_Size and + * Max_Read_Request_Size to 128 bytes. + */ + pci_write_config_byte(dev, 0xb5, 0x0c); + pci_write_config_byte(dev, 0xb4, 0x0); + + } +#endif + + /* Prevent compiler warning */ + if (ctrl == NULL) { + return 0; + } + + ctrl->be_pio = 0; + ctrl->dev_type |= BDE_PCI_DEV_TYPE; + ctrl->pci_device = dev; + pci_set_drvdata(dev, ctrl); + + /* Check for iProc device */ + if (shbde_pci_is_iproc(shbde, dev, &cmic_bar)) { + iproc = 1; + if (cmic_bar >= 0) { + baroff = cmic_bar; + } + } +#ifdef DNX_TEST_BOARD + else if (dev->device == PLX9056_DEVICE_ID && baroff == 0) { + baroff = 2; + ctrl->dev_type |= BDE_NO_IPROC/* | BDE_BYTE_SWAP*/; + } +#endif /* DNX_TEST_BOARD */ + + /* Get the device revision */ + pci_read_config_byte(dev, PCI_REVISION_ID, &ctrl->bde_dev.rev); + + /* Map in the device */ + ctrl->bde_dev.device = dev->device; + paddr = pci_resource_start(dev, baroff); + + switch (dev->device) { +#if defined(BCM_PETRA_SUPPORT) && defined(__DUNE_LINUX_BCM_CPU_PCIE__) + case GEDI_DEVICE_ID: + case PCP_PCI_DEVICE_ID: + bar_len = 0x1000000; + break; +#endif + default: + bar_len = pci_resource_len(dev, baroff); + break; + } + + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(paddr, bar_len); + ctrl->phys_address = paddr; + if (debug >= 3) { + gprintk("BAR %d: kernel addr:0x%lx phys addr:0x%lx length:%lx\n", + baroff, (unsigned long)ctrl->bde_dev.base_address, (unsigned long)paddr, (unsigned long)bar_len); + } + + /* Map secondary address spaces */ + if (iproc +#ifdef DNX_TEST_BOARD + || (dev->device == PLX9056_DEVICE_ID && baroff == 2) +#endif /* DNX_TEST_BOARD */ + ) { + paddr = pci_resource_start(dev, 0); + bar_len = pci_resource_len(dev, 0); + ctrl->bde_dev.base_address1 = (sal_vaddr_t)IOREMAP(paddr, bar_len); + ctrl->phys_address1 = paddr; + if (debug >= 3) { + gprintk("BAR 0: kernel addr:0x%lx phys addr:0x%lx length:%lx\n", + (unsigned long)ctrl->bde_dev.base_address1, (unsigned long)paddr, (unsigned long)bar_len); + } + } + + /* Each device follows global policy by default */ + ctrl->use_msi = use_msi; + + /* Check is MSI is properly supported in kernel for this device */ + if (ctrl->use_msi) { + if (pci_enable_msi(ctrl->pci_device) == 0) { + /* Release MSI resources until interrupt_connect is called */ + pci_disable_msi(ctrl->pci_device); + } else { + gprintk("Could not enable MSI interrupts\n"); + ctrl->use_msi = 0; + } + } + + /* configure interrupt type */ + config_pci_intr_type(ctrl); + + /* Configure iProc PCI-AXI bridge */ + if (iproc && ctrl->bde_dev.base_address1) { + void *iproc_regs; + shbde_iproc_config_t *icfg = &shbde->icfg; + + /* Mapped iProc regs in PCI BAR 0 */ + iproc_regs = (void *)ctrl->bde_dev.base_address1; + + /* iProc configuration parameters */ + (void)shbde_pci_iproc_version_get(shbde, dev, &icfg->iproc_ver, + &icfg->cmic_ver, &icfg->cmic_rev); + shbde_iproc_config_init(icfg, ctrl->bde_dev.device, ctrl->bde_dev.rev); + + if (debug >=2) { + gprintk("iproc version = %x dma_hi_bits = %x\n", icfg->iproc_ver, icfg->dma_hi_bits); + } + icfg->use_msi = ctrl->use_msi; + + /* Call shared function */ + paxb_core = shbde_iproc_paxb_init(shbde, iproc_regs, icfg); + + /* Save PCI core information for CMIC */ + if (paxb_core == 1) { + ctrl->dev_type |= BDE_DEV_BUS_ALT; + } + + /* Save MSI enable state information */ + if (ctrl->use_msi) { + ctrl->dev_type |= BDE_DEV_BUS_MSI; + } + + /* iProc PCIe preemphasis */ + shbde_iproc_pcie_preemphasis_set(shbde, iproc_regs, icfg, dev); + } + + /* Save shared BDE HAL in device structure */ + memcpy(&ctrl->shbde, shbde, sizeof(ctrl->shbde)); + + + /* + * Since the GMAC driver of Robo chips needs access to the + * ChipCommon and Wrapper registers, we set the base address + * as the enumeration base address and its size as 3MB to + * cover all Wrapper register regions. + */ + if (gmac_base) { + uint32_t offset; + + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(gmac_base, 0x300000); + + /* Record the base address of GMAC core */ + offset = ctrl->phys_address - gmac_base; + ctrl->alt_base_addr = ctrl->bde_dev.base_address + offset; + ctrl->phys_address = gmac_base; + } + + /* + * Workaround bug in FE2K A1 part; shows as A0 part in PCI config space, + * read the FE's regs directly to get the true revision + */ + if (ctrl->bde_dev.device == BCM88020_DEVICE_ID && ctrl->bde_dev.rev == 0) { +#define FE2000_REVISION_OFFSET (0x0) + uint32_t fe_rev; + + fe_rev = *((uint32_t*)(ctrl->bde_dev.base_address + FE2000_REVISION_OFFSET)); + if ((fe_rev >> 16) == BCM88020_DEVICE_ID) { + fe_rev &= 0xff; + } else { + fe_rev = (fe_rev >> 24) & 0xff; + } + ctrl->bde_dev.rev = fe_rev; + } + + ctrl->isr = NULL; + ctrl->isr_data = NULL; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (!(cmd & PCI_COMMAND_MEMORY) || !(cmd & PCI_COMMAND_MASTER)) { + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_write_config_word(dev, PCI_COMMAND, cmd); + if (debug >= 1) gprintk("enable PCI resources 0x%x (PCI_COMMAND)\n", cmd); + } + + /* Check if we need 256 KB memory window (default is 64 KB) */ + bar_len = pci_resource_len(dev, baroff); + if (bar_len == 0x40000) { + ctrl->dev_type |= BDE_256K_REG_SPACE; + if (debug >= 1) gprintk("PCI resource len 256K\n"); + } else if (bar_len == 0x800000) { + ctrl->dev_type |= BDE_256K_REG_SPACE | BDE_8MB_REG_SPACE; + if (debug >= 1) gprintk("PCI resource len 8MB\n"); + } + +#if defined (BCM_ROBO_SUPPORT) && !defined(ALTA_ROBO_SPI) + /* MDC/MDIO path for pseudo PHY access to ROBO register on BCM5836/4704 */ + if (dev->device == BCM47XX_ENET_ID) { + ((uint32 *)ctrl->bde_dev.base_address)[0x410 / 4] = 0; + } +#endif + +#ifdef LINUX_BDE_DMA_DEVICE_SUPPORT + ctrl->dma_dev = &dev->dev; +#endif + + if (!rescan) { + _bde_add_device(); + } + + if (debug >= 2) { + gprintk("_pci_probe: configured dev:0x%x rev:0x%x with base_addresses: 0x%lx 0x%lx\n", + (unsigned)ctrl->bde_dev.device, (unsigned)ctrl->bde_dev.rev, + (unsigned long)ctrl->bde_dev.base_address, (unsigned long)ctrl->bde_dev.base_address1); + } + /* Let's boogie */ + + return 0; +} + +/* + * Function: _pci_remove + * + * Purpose: + * Detach driver from device. Called from pci_unregister_driver(). + * Parameters: + * dev - Linux PCI device structure + * Returns: + * 0 + */ +static void +_pci_remove(struct pci_dev* dev) +{ + bde_ctrl_t *ctrl; + + if (nodevices == 1) { + return; + } + +#if defined(BCM_DFE_SUPPORT) + if (dev->device == PCI_DEVICE_ID_PLX_9056) { + return; + } +#endif + + ctrl = (bde_ctrl_t *) pci_get_drvdata(dev); + + if (ctrl == NULL) { + /* Unused device */ + return; + } + ctrl->dev_state = BDE_DEV_STATE_REMOVED; + if (debug >= 1) { + gprintk("PCI device %04x:%04x is removed. \n", + dev->vendor, dev->device); + } + if (ctrl->bde_dev.base_address1) { + iounmap((void *)ctrl->bde_dev.base_address1); + } + if (ctrl->bde_dev.base_address) { + iounmap((void *)ctrl->bde_dev.base_address); + } + + /* Free our interrupt handler, if we have one */ + if (ctrl->isr || ctrl->isr2) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + if (ctrl->use_msi >= PCI_USE_INT_MSIX) { + int i; + for (i = 0; i < ctrl->msix_cnt; i++) + free_irq(ctrl->entries[i].vector, ctrl->pci_device); + } + else +#endif + { + free_irq(ctrl->iLine, ctrl); + } + } +#ifdef CONFIG_PCI_MSI + _msi_disconnect(ctrl); +#endif + ctrl->isr = NULL; + ctrl->isr_data = NULL; + ctrl->isr2 = NULL; + ctrl->isr2_data = NULL; + } + +static struct pci_driver _device_driver = { + probe: _pci_probe, + remove: _pci_remove, + id_table: _id_table, + /* The rest are dynamic */ +}; + +static void +_spi_device_setup(void) { + bde_ctrl_t *ctrl; + ctrl = _devices + _ndevices++; + _switch_ndevices++; + ctrl->dev_type |= BDE_SWITCH_DEV_TYPE; + ctrl->iLine = 0xa3; + ctrl->be_pio = 0; + ctrl->dev_type |= BDE_SPI_DEV_TYPE; + ctrl->bde_dev.device = spi_devid; + ctrl->bde_dev.rev = spi_revid; + if (debug >= 1) { + gprintk("SPI Slave Mode: force ctrl->bde_dev.device=0x%x\n",ctrl->bde_dev.device); + gprintk("SPI Slave Mode: force ctrl->bde_dev.rev=0x%x\n",ctrl->bde_dev.rev); + gprintk("SPI Slave Mode: force ctrl->dev_type=0x%x\n",ctrl->dev_type); + } +} +#endif /* BCM_ICS */ + + +#ifdef BCM_ROBO_SUPPORT + +#ifdef KEYSTONE +#define DEFAULT_FREQ (SPI_FREQ_DEFAULT) +#define FREQ_20MHZ (SPI_FREQ_20MHZ) +#else /* IPROC_CMICD */ +#define DEFAULT_FREQ (0) +#define FREQ_20MHZ (0) +#endif + + +/* +* The model_info /rev_info for Robo devices is defined like this: +* +* 31 28 27 24 23 20 19 16 15 8 7 0 +* +----+---------+------+-----+---------+--------+ +* | op | reserved| mask |len | page |offset | +* +----+---------+------+-----+---------+--------+ +* +* op: 1:OR phyidl, 2: use PCIE device ID +* mlen: mask len (in bytes) 1:means 0xf,2 means 0xff +* len: Size of model/rev ID register (in bytes) +* page: Page containing model ID and revision registers +* offset: Model/rev ID register offset +*/ +static struct bde_spi_device_id _spi_id_table[] = { + { BCM53242_PHYID_HIGH, BCM53242_PHYID_LOW , 0, 0, DEFAULT_FREQ}, + { BCM53262_PHYID_HIGH, BCM53262_PHYID_LOW , 0, 0, DEFAULT_FREQ}, + { BCM53115_PHYID_HIGH, BCM53115_PHYID_LOW , 0, 0, DEFAULT_FREQ}, + { BCM53118_PHYID_HIGH, BCM53118_PHYID_LOW , 0, 0, DEFAULT_FREQ}, + { BCM53280_PHYID_HIGH, BCM53280_PHYID_LOW , 0x101800e8, 0, FREQ_20MHZ}, + { BCM53101_PHYID_HIGH, BCM53101_PHYID_LOW , 0, 0x110240, FREQ_20MHZ}, + { BCM53125_PHYID_HIGH, BCM53125_PHYID_LOW , 0, 0x110240, FREQ_20MHZ}, + { BCM53128_PHYID_HIGH, BCM53128_PHYID_LOW , 0, 0x110240, FREQ_20MHZ}, + { BCM53600_PHYID_HIGH, BCM53600_PHYID_LOW , 0x101800e8, 0, FREQ_20MHZ}, + { BCM89500_PHYID_HIGH, BCM89500_PHYID_LOW ,0x240230, 0x110240, FREQ_20MHZ}, + { BCM53010_PHYID_HIGH, BCM53010_PHYID_LOW ,0x240230, 0x110240, 0}, + { BCM53018_PHYID_HIGH, BCM53018_PHYID_LOW ,0x240230, 0x110240, 0}, + { BCM5389_PHYID_HIGH, BCM5389_PHYID_LOW, 0x110230, 0x110240, DEFAULT_FREQ}, + { BCM53020_PHYID_HIGH, BCM53020_PHYID_LOW ,0x20240230, 0x110240, 0}, + { BCM5396_PHYID_HIGH , BCM5396_PHYID_LOW, 0x110230, 0x110240, DEFAULT_FREQ}, + { BCM53134_PHYID_HIGH, BCM53134_PHYID_LOW , 0, 0x110240, DEFAULT_FREQ}, + { 0, 0, 0, 0, 0 }, +}; +#endif + +#ifdef BCM_ROBO_SUPPORT + +static int +_spi_device_valid_check(unsigned short phyidh,unsigned short phyidl, uint8 check_flag) +{ + struct bde_spi_device_id *_ids; + int idx, match_idx; + + match_idx = -1; + idx = 0; + + if (check_flag == 0){ + /* check_flag == 0 check phyidh only*/ + for (_ids = _spi_id_table; + _ids->phyid_high && _ids->phyid_low; _ids++){ + if (_ids->phyid_high == phyidh) { + return 0; + } + } + /* No valid SPI devices found */ + return 1; + } else { + while(_spi_id_table[idx].phyid_high){ + if (phyidh == _spi_id_table[idx].phyid_high && + phyidl == _spi_id_table[idx].phyid_low) { + /* Found a match */ + match_idx = idx; + break; + } + idx++; + } + return match_idx; + } +} + +#if defined(IPROC_CMICD) || defined(KEYSTONE) +#define ROBO_ATTACH_AVAIL +#endif + +#ifdef ROBO_ATTACH_AVAIL + +#define SOC_ATTACH(_sc)\ + ai_soc_kattach(_sc) + +#if defined(IPROC_CMICD) +#ifdef BCM_STARFIGHTER3_SUPPORT +#define ROBO_ATTACH_SPI(_sih, _ss)\ + robo_attach_spi(_sih) +#define ROBO_DETACH_SPI(robo)\ + robo_detach_spi(robo) +#define ROBO_SPI_RREG(_robo, _dev, _page, _reg, _buf, _len) \ + robo_spi_rreg(_robo, _dev, _page, _reg, _buf, _len) +#define ROBO_SPI_WREG(_robo, _dev, _page, _reg, _buf, _len) \ + robo_spi_wreg(_robo, _dev, _page, _reg, _buf, _len) +#endif +#define ROBO_ATTACH(_sih, _ss)\ + robo_attach(_sih) +#define MAX_BUSTYPE 1 +#define ROBO_SWITCH_BUS(_robo, _bustype) +#define ROBO_SELECT_DEVICE(_robo, _phyidh, _phyidl) +#else /* KEYSTONE */ +#define ROBO_ATTACH(_sih, _ss)\ + robo_attach(_sih, _ss) +/* bustype 2: ROBO_MDCMDIO_BUS, 1: ROBO_SPI_BUS */ +#define MAX_BUSTYPE 2 +#define ROBO_SWITCH_BUS(_robo, _bustype)\ + robo_switch_bus(_robo, _bustype) + +#define ROBO_SELECT_DEVICE(_robo, _phyidh, _phyidl) \ + robo_select_device(_robo, _phyidh, _phyidl) +#endif + +#else + +#define SOC_ATTACH(_sc) (NULL) +#define ROBO_ATTACH(_sih, _ss) (NULL) +#define MAX_BUSTYPE (0) +#define ROBO_SWITCH_BUS(_robo, _bustype) +#define ROBO_SELECT_DEVICE(_robo, _phyidh, _phyidl) +#endif + + +#if defined(IPROC_CMICD) && defined(BCM_STARFIGHTER3_SUPPORT) +static int +probe_robo_switch_iproc_spi(void) +{ + int dev; + int max_devices, max_bustype; + uint8 buf[8]; + unsigned short phyidh = 0, phyidl = 0; + + + /* Get Robo device handle */ + if (robo == NULL) { + robo = (void *)ROBO_ATTACH_SPI(sbh, 0); + } + if (robo == NULL) { + return -ENODEV; + } + + max_bustype = MAX_BUSTYPE + 1; + + while(_spi_device_valid_check(phyidh, 0, 0)) { + max_bustype --; + if(!max_bustype) + return -ENODEV; + buf[0] = buf[1] = 0; + ROBO_SPI_RREG(robo, 0, 0x10, 0x04, buf, (uint)2); + phyidh = buf[0] | (buf[1] << 8); + /* re-try */ + if ((phyidh == 0x0) || (phyidh == 0xffff)) { + ROBO_SPI_RREG(robo, 0, 0x10, 0x04, buf, (uint)2); + phyidh = buf[0] | (buf[1] << 8); + } + } + + /* For psedo_phy access, only support one robo switch*/ + /* For Northstar, only one switch on SRAB interface */ + max_devices = (max_bustype == MAX_BUSTYPE) ? 1 : LINUX_BDE_MAX_SWITCH_DEVICES; + + for (dev = 0; dev < max_devices; dev++) { + bde_ctrl_t *ctrl; + int match_idx, i; + unsigned short phyidl_nr; /* phyidl with revision stripped */ + uint16 model_id; + uint8 rev_id; + uint32 addr, len; + uint32 mlen; + + if (_switch_ndevices >= LINUX_BDE_MAX_SWITCH_DEVICES) { + break; + } + buf[0] = buf[1] = 0; + ROBO_SPI_RREG(robo, dev, 0x10, 0x04, buf, (uint)2); + phyidh = buf[0] | (buf[1] << 8); + + buf[0] = buf[1] = 0; + ROBO_SPI_RREG(robo, dev, 0x10, 0x06, buf, (uint)2); + phyidl = buf[0] | (buf[1] << 8); + + /* Strip revision */ + phyidl_nr = phyidl & 0xfff0; + + match_idx = _spi_device_valid_check(phyidh, phyidl_nr, 1); + if (match_idx == -1) { + if (debug >= 1) gprintk("found %d robo device(s).\n", robo_switch); + break; + } + + model_id = phyidl_nr; + + if(_spi_id_table[match_idx].rev_info){ + addr = _spi_id_table[match_idx].rev_info & 0xffff; + len = (_spi_id_table[match_idx].rev_info >> 16) & 0xf; + ROBO_SPI_RREG(robo, dev, (addr >> 8), (addr & 0xff), buf, (uint)len); + mlen = (_spi_id_table[match_idx].rev_info >> 20) & 0xf; + rev_id = 0; + for (i = 0; i < mlen; i++) + rev_id |= buf[i] << (i << 3); + } else { + rev_id = phyidl & 0xf; + } + + gprintk("found robo device with %d:%04x:%04x:%04x:%02x\n", + dev, phyidh, phyidl, model_id, rev_id); + + ROBO_SELECT_DEVICE(robo, phyidh, phyidl); + + /* Match supported chips */ + ctrl = _devices + _ndevices++; + _switch_ndevices++; + + if (NULL == (ctrl->spi_device = (struct spi_dev *) + KMALLOC(sizeof(struct spi_dev), GFP_KERNEL))) { + gprintk("no memory available"); + return -ENOMEM; + } + ctrl->dev_type = (BDE_SPI_DEV_TYPE | BDE_SWITCH_DEV_TYPE); + ctrl->spi_device->cid = dev; + ctrl->spi_device->part = model_id; + ctrl->spi_device->rev = rev_id; + ctrl->spi_device->robo = robo; + ctrl->spi_device->phyid_high = phyidh; + ctrl->spi_device->phyid_low = phyidl; + ctrl->bde_dev.device = model_id; + ctrl->bde_dev.rev = rev_id; + ctrl->bde_dev.base_address = (sal_vaddr_t)NULL; + ctrl->isr = NULL; + ctrl->isr_data = NULL; + robo_switch++; + _bde_add_device(); + + } + + return robo_switch; + +} + +int spi_device_found = 0; + +#endif /* IPROC_CMICD || SF3 */ + + +static int +probe_robo_switch(void) +{ + int dev; + int max_devices, max_bustype; + uint8 buf[8]; + unsigned short phyidh = 0, phyidl = 0; +#if defined(KEYSTONE) + uint32 spi_freq = 0; +#endif +#if defined(IPROC_CMICD) + sal_vaddr_t addr_base; + uint32 data_reg; +#endif /* IPROC_CMICD */ + + + spin_lock_init(&bus_lock); + + if (_switch_ndevices) { + /* + * Currently skip probe robo if esw chips were found + * FIX this while combined plateform support. + */ + return robo_switch; + } + + /* Get Robo device handle */ + if (robo == NULL) { + sbh = (void *)SOC_ATTACH(NULL); + if (sbh == NULL) { + return -ENODEV; + } + } + +#if defined(IPROC_CMICD) && defined(BCM_STARFIGHTER3_SUPPORT) + robo_switch = probe_robo_switch_iproc_spi(); + + if (robo_switch > 0) { + /* Robo switch found by SPI probe */ + spi_device_found = 1; + gprintk("SPI device found, Skipping SRAB probe\n"); + return robo_switch; + } else { + gprintk("SPI device NOT found, Probe SRAB probe\n"); + ROBO_DETACH_SPI(robo); + } +#endif + + if (robo == NULL) { + robo = (void *)ROBO_ATTACH(sbh, 0); + } + if (robo == NULL) { + return -ENODEV; + } + + max_bustype = MAX_BUSTYPE + 1; + + while(_spi_device_valid_check(phyidh, 0, 0)) { + max_bustype --; + if(!max_bustype) + return -ENODEV; + ROBO_SWITCH_BUS(robo, max_bustype); + buf[0] = buf[1] = 0; + ROBO_RREG(robo, 0, 0x10, 0x04, buf, (uint)2); + phyidh = buf[0] | (buf[1] << 8); + /* re-try */ + if ((phyidh == 0x0) || (phyidh == 0xffff)) { + ROBO_RREG(robo, 0, 0x10, 0x04, buf, (uint)2); + phyidh = buf[0] | (buf[1] << 8); + } + } + + /* For psedo_phy access, only support one robo switch*/ + /* For Northstar, only one switch on SRAB interface */ + max_devices = (max_bustype == MAX_BUSTYPE) ? 1 : LINUX_BDE_MAX_SWITCH_DEVICES; + + for (dev = 0; dev < max_devices; dev++) { + bde_ctrl_t *ctrl; + int match_idx, i; + unsigned short phyidl_nr; /* phyidl with revision stripped */ + uint16 model_id; + uint8 rev_id; +#if defined(KEYSTONE) || defined(IPROC_CMICD) + uint32 addr, len; +#endif + uint32 mlen, op; + + if (_switch_ndevices >= LINUX_BDE_MAX_SWITCH_DEVICES) { + break; + } + buf[0] = buf[1] = 0; + ROBO_RREG(robo, dev, 0x10, 0x04, buf, (uint)2); + phyidh = buf[0] | (buf[1] << 8); + + buf[0] = buf[1] = 0; + ROBO_RREG(robo, dev, 0x10, 0x06, buf, (uint)2); + phyidl = buf[0] | (buf[1] << 8); + + /* Strip revision */ + phyidl_nr = phyidl & 0xfff0; + + match_idx = _spi_device_valid_check(phyidh, phyidl_nr, 1); + if (match_idx == -1) { + if (debug >= 1) gprintk("found %d robo device(s).\n", robo_switch); + break; + } + + if(_spi_id_table[match_idx].model_info){ +#if defined(KEYSTONE) || defined(IPROC_CMICD) + addr = _spi_id_table[match_idx].model_info & 0xffff; + len = (_spi_id_table[match_idx].model_info >> 16) & 0xf; +#endif + ROBO_RREG(robo, dev, (addr >> 8), (addr & 0xff), buf, (uint)len); + mlen = (_spi_id_table[match_idx].model_info >> 20) & 0xf; + model_id = 0; + for (i = 0; i < mlen; i++) + model_id |= buf[i] << (i << 3); + op = (_spi_id_table[match_idx].model_info >> 28) & 0xf; + if(op == 1) { + model_id |= phyidl_nr; +#if defined(IPROC_CMICD) + } else if (op == 2) { + /* The package id of NS+ is determined by : + * Write 0 to 0x18012120 (PAXB_0_CONFIG_IND_ADDR) + * Read 0x18012124 (PAX_B_CONFIG_IND_DATA), + * bits 31:16 will be the device id from OTP space + */ +#define PAXB_ENUM_BASE (0x18012000) +#define PAXB_CONFIG_IND_ADDR_OFFSET (0x120) +#define PAXB_CONFIG_IND_DATA_OFFSET (0x124) + + addr_base = (sal_vaddr_t)IOREMAP(PAXB_ENUM_BASE, 0x1000); + if (!addr_base) { + gprintk("ioremap of PAXB registers failed\n"); + } else { + writel(0x0, (uint32 *)(addr_base + + PAXB_CONFIG_IND_ADDR_OFFSET)); + data_reg = readl((uint32 *)(addr_base + + PAXB_CONFIG_IND_DATA_OFFSET)); + model_id = (data_reg >> 16); + iounmap((void *)addr_base); + + /* + * Some model ID can't be determined by PCIE device ID + * It needs to refer some OTP values. + */ + robo_model_id_adjust_from_otp(robo, &model_id); + } + +#undef PAXB_ENUM_BASE +#undef PAXB_CONFIG_IND_ADDR_OFFSET +#undef PAXB_CONFIG_IND_DATA_OFFSET +#endif /* IPROC_CMICD */ + } + } else { + model_id = phyidl_nr; + } + if(_spi_id_table[match_idx].rev_info){ +#if defined(KEYSTONE) || defined(IPROC_CMICD) + addr = _spi_id_table[match_idx].rev_info & 0xffff; + len = (_spi_id_table[match_idx].rev_info >> 16) & 0xf; +#endif + ROBO_RREG(robo, dev, (addr >> 8), (addr & 0xff), buf, (uint)len); + mlen = (_spi_id_table[match_idx].rev_info >> 20) & 0xf; + rev_id = 0; + for (i = 0; i < mlen; i++) + rev_id |= buf[i] << (i << 3); + } else { + rev_id = phyidl & 0xf; + } + gprintk("found robo device with %d:%04x:%04x:%04x:%02x\n", + dev, phyidh, phyidl, model_id, rev_id); + + ROBO_SELECT_DEVICE(robo, phyidh, phyidl); + + /* Match supported chips */ + ctrl = _devices + _ndevices++; + _switch_ndevices++; + + if (NULL == (ctrl->spi_device = (struct spi_dev *) + KMALLOC(sizeof(struct spi_dev), GFP_KERNEL))) { + gprintk("no memory available"); + return -ENOMEM; + } + ctrl->dev_type = (BDE_SPI_DEV_TYPE | BDE_SWITCH_DEV_TYPE); + ctrl->spi_device->cid = dev; + ctrl->spi_device->part = model_id; + ctrl->spi_device->rev = rev_id; + ctrl->spi_device->robo = robo; + ctrl->spi_device->phyid_high = phyidh; + ctrl->spi_device->phyid_low = phyidl; + ctrl->bde_dev.device = model_id; + ctrl->bde_dev.rev = rev_id; + ctrl->bde_dev.base_address = (sal_vaddr_t)NULL; + ctrl->isr = NULL; + ctrl->isr_data = NULL; + robo_switch++; + +#if defined(KEYSTONE) + spi_freq = _spi_id_table[match_idx].spifreq; +#endif + _bde_add_device(); + } + +#if defined(KEYSTONE) + /* Override the SPI frequency from user configuration */ + if (spifreq != 0) { + spi_freq = spifreq; + } + if (spi_freq != 0) { + /* + * The underlying chip can support the SPI frequency + * higher than default (2MHz). + */ + if (spi_freq != SPI_FREQ_DEFAULT) { + chipc_spi_set_freq(robo, 0, spi_freq); + } + } +#endif + return robo_switch; + +} + +#endif + +#if defined(BCM_METROCORE_LOCAL_BUS) +static bde_ctrl_t* +map_local_bus(uint64_t addr, uint32_t size) +{ + bde_ctrl_t *ctrl; + + ctrl = _devices + _ndevices++; + _switch_ndevices++; + + /* + * For now: use EB type as `local bus' + * (memory mapped, no DMA, no interrupts) + * metrocore local bus supports interrupts, but we don't use them. + */ + ctrl->dev_type |= BDE_EB_DEV_TYPE | BDE_SWITCH_DEV_TYPE + | (size > 64 * 1024 ? BDE_128K_REG_SPACE : 0); + ctrl->pci_device = NULL; /* No PCI bus */ + + /* Map in the device */ + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(addr, size); + ctrl->phys_address = addr; + + _bde_add_device(); + + return(ctrl); +} + +#define BME_REVISION_OFFSET (0x0) + +#endif + + +#ifdef BCM_METROCORE_LOCAL_BUS + /* + * SBX platform has both PCI- and local bus-attached devices + * The local bus devices have fixed address ranges (and don't + * support or require DMA), but are otherwise the same as PCI devices + */ +#define FPGA_IRQ 37 +#define FPGA_PHYS 0x100E0000 +#define BME_PHYS 0x100C0000 +#define SE_PHYS 0x100D0000 +#define FPGA_SIZE 0x00004000 +#define BME_SIZE 0x00004000 +#define MAC0_PHYS 0x100B0000 +#define MAC1_PHYS 0x100B8000 +#define MAC_SIZE 0x800 + + +/* + * Please refer to "Supervisor Fabric Module (SFM) Specification" + * page 23 for the following registers. + */ +#define FPGA_LC_POWER_DISABLE_OFFSET 0x4 +#define FPGA_LC_POWER_DISABLE_ENABLE_ALL_MASK 0x1e + +#define FPGA_LC_POWER_RESET_OFFSET 0x5 +#define FPGA_LC_POWER_RESET_ENABLE_ALL_MASK 0x1e + +#define FPGA_SW_SFM_MASTER_MODE_OFFSET 0x14 +#define FPGA_SW_SFM_MASTER_MODE_ENABLE_MASK 0x10 + + +static int +probe_metrocore_local_bus(void) { + bde_ctrl_t *ctrl; + uint32_t dev_rev_id; + VOL uint8_t *fpga; + + /* + * Write the FPGA on the fabric card, to let metrocore + * line cards out of reset. We actually don't bother to determine whether + * the card is a line card or a fabric card because when we do + * this on the line cards, it has no effect. + */ + fpga = (uint8_t *) IOREMAP(FPGA_PHYS, FPGA_SIZE); + fpga[FPGA_SW_SFM_MASTER_MODE_OFFSET] + |= FPGA_SW_SFM_MASTER_MODE_ENABLE_MASK; + fpga[FPGA_LC_POWER_DISABLE_OFFSET] + |= FPGA_LC_POWER_DISABLE_ENABLE_ALL_MASK; + fpga[FPGA_LC_POWER_RESET_OFFSET] + |= FPGA_LC_POWER_RESET_ENABLE_ALL_MASK; + + ctrl = map_local_bus(BME_PHYS, BME_SIZE); + + dev_rev_id = + *((uint32_t *) + (((uint8_t *) ctrl->bde_dev.base_address) + BME_REVISION_OFFSET)); + ctrl->bde_dev.device = dev_rev_id >> 16; + ctrl->bde_dev.rev = (dev_rev_id & 0xFF); + + if ((ctrl->bde_dev.device != BME3200_DEVICE_ID) && + (ctrl->bde_dev.device != BCM88130_DEVICE_ID)) { + gprintk("probe_metrocore_local_bus: wrong BME type: " + "0x%x (vs 0x%x or 0x%x)\n", + ctrl->bde_dev.device, BME3200_DEVICE_ID, BCM88130_DEVICE_ID); + return -1; + } + + ctrl->iLine = FPGA_IRQ; + ctrl->isr = NULL; + ctrl->isr_data = NULL; + + /* + * + * We start from SE & include the FPGA, which is 128k + */ + ctrl = map_local_bus(SE_PHYS, 128 * 1024); + + dev_rev_id = + *((uint32_t *) + (((uint8_t *) ctrl->bde_dev.base_address) + BME_REVISION_OFFSET)); + ctrl->bde_dev.device = dev_rev_id >> 16; + ctrl->bde_dev.rev = (dev_rev_id & 0xFF); + + if ((ctrl->bde_dev.device != BME3200_DEVICE_ID) && + (ctrl->bde_dev.device != BCM88130_DEVICE_ID)) { + gprintk("probe_metrocore_local_bus: wrong SE (BME) type: " + "0x%x (vs 0x%x)\n", + ctrl->bde_dev.device, BME3200_DEVICE_ID); + return -1; + } + + ctrl->iLine = FPGA_IRQ; + ctrl->isr = NULL; + ctrl->isr_data = NULL; + + return 0; +} +#endif + +#ifdef BCM_PLX9656_LOCAL_BUS + +#if 1 +#define DEV_REG_BASE_OFFSET PL0_OFFSET /* Polaris register base */ +#define DEV_REG_DEVID 0 /* Device ID is first register */ +#endif + +/* + * The difference at map_local_bus2: + * + * The PLX9656 PCI-to-LOCAL bridge chip already has been iomapped the + * whole address space. So the devices off local bus don't need to be + * mapped again. They only need to claim their own sub-space. + */ +static bde_ctrl_t * +map_local_bus2(bde_ctrl_t *plx_ctrl, uint32_t dev_base, uint32_t size) +{ + uint32_t dev_rev_id; + uint8_t *addr; + bde_ctrl_t *ctrl; + + ctrl = _devices + _ndevices++; + _switch_ndevices++; + + /* + * For now: use EB type as `local bus' + * (memory mapped, no DMA, no interrupts) + * metrocore local bus supports interrupts, but we don't use them. + */ + ctrl->dev_type |= BDE_EB_DEV_TYPE | BDE_SWITCH_DEV_TYPE; + ctrl->dev_type |= BDE_320K_REG_SPACE; /* Polaris 18 bits address + FPGA */ + ctrl->pci_device = NULL; /* No PCI bus */ + + /* Map in the device */ + ctrl->bde_dev.base_address = plx_ctrl->bde_dev.base_address + dev_base; + ctrl->phys_address = plx_ctrl->phys_address + (resource_size_t)dev_base; + +#if 1 + addr = (uint8_t *)ctrl->bde_dev.base_address + PL0_REVISION_REG; +#endif + dev_rev_id = readl(addr); + ctrl->bde_dev.device = dev_rev_id >> 16; + ctrl->bde_dev.rev = (dev_rev_id & 0xFF); + + _bde_add_device(); + + switch (ctrl->bde_dev.device) { + case BCM88130_DEVICE_ID: + case BME3200_DEVICE_ID: + break; + default: + gprintk("wrong BME type: 0x%x (vs 0x%x or 0x%x)\n", + ctrl->bde_dev.device, BME3200_DEVICE_ID, BCM88130_DEVICE_ID); + return 0; + } + return(ctrl); +} + +static int +probe_plx_local_bus(void) +{ + bde_ctrl_t *ctrl; + uint32_t val; + uint8_t *addr; + char addr_hi_str[16]; + + if (num_plx > 1) { + printk(KERN_ERR "There's more than one PLX 9656/9056 chip\n"); + return -1; + } + addr_hi_str[0] = 0; +#ifdef PHYS_ADDR_IS_64BIT + sprintf(addr_hi_str, "%08x", (uint32_t)(plx_ctrl.phys_address >> 32)); +#endif + printk(KERN_ERR "Found PLX %04x:%04x vir: 0x%08x phy: 0x%s%08x\n", + plx_ctrl.bde_dev.device, plx_ctrl.bde_dev.rev, + plx_ctrl.bde_dev.base_address, addr_hi_str, + (uint32_t)(plx_ctrl.phys_address)); + + addr = (uint8_t *)plx_ctrl.bde_dev.base_address + CPLD_OFFSET + CPLD_REVISION_REG; + val = readl(addr); + printk(KERN_ERR "plx: CPLD revision %d\n", val & CPLD_REVISION_MASK); +#if 000 + addr = (uint8_t *)plx_ctrl.bde_dev.base_address + CPLD_OFFSET + CPLD_RESET_REG; + writel(CPLD_RESET_NONE, addr); +#endif +#if 1 + ctrl = map_local_bus2(&plx_ctrl, PL0_OFFSET, PL0_SIZE); +#endif + if (ctrl == 0) + return -1; + + /* Uses PLX IRQ for Polaris LC */ + ctrl->iLine = 48; + ctrl->isr = NULL; + ctrl->isr_data = NULL; + + return 0; +} + +#endif /* BCM_PLX9656_LOCAL_BUS */ + +#if defined(BCM_EA_SUPPORT) +#if defined(BCM_TK371X_SUPPORT) +static void +probe_tk371x_dev(void) +{ + bde_ctrl_t *ctrl; + int ea_uid=0; + + /* eadevices is from the argument of insmod */ + for (ea_uid = 0; ea_uid < eadevices; ea_uid++) { + ctrl = _devices + _ndevices++; + _switch_ndevices++; + ctrl->dev_type = (BDE_MII_DEV_TYPE | BDE_SWITCH_DEV_TYPE); + ctrl->bde_dev.device = TK371X_DEVICE_ID; + ctrl->bde_dev.rev = 0x0; + ctrl->bde_dev.base_address = (sal_vaddr_t)NULL; + ctrl->iLine = 0; + } +} +#endif /* BCM_TK371X_SUPPORT*/ +#endif /* BCM_EA_SUPPORT */ + + +#if defined(BCM_ROBO_SUPPORT) +#if defined(IPROC_CMICD) +struct chip_device_info { + uint32 cc_base; /* Chip-common register base */ + uint32 cc_size; /* Chip-common register limit */ + uint32 cid_reg_off; /* Chip id register offset */ +}; + +static struct chip_device_info _chip_table = { +#if defined(IPROC_CMICD) + 0x18000000, 0x00000300, 0x00000000 +#else + 0,0,0 +#endif +}; + +struct gmac_device_info { + uint32 cid; /* chip id */ + uint32 rid; /* revision id */ + uint32 pid; /* package id */ + + uint32 gmac_dev_id; /* gmac core device id */ + uint32 gmac_base_addr; /* gmac core base address */ + int gmac_irq; /* gmac irq number */ +}; + +static struct gmac_device_info _gmac_table[] = { +#if defined(IPROC_CMICD) + {BCM53010_CHIP_ID, 0, 0, BCM53010_GMAC_ID, 0x18026000, 181}, /* BCM53012 */ + {BCM53010_CHIP_ID, 0, 2, BCM53010_GMAC_ID, 0x18026000, 181}, /* BCM53011 */ + {BCM53010_CHIP_ID, 0, 1, BCM53010_GMAC_ID, 0x18026000, 181}, /* BCM53010 */ + {BCM53018_CHIP_ID, 0, 0, BCM53010_GMAC_ID, 0x18026000, 181}, /* BCM53018 */ + {BCM53018_CHIP_ID, 0, 2, BCM53010_GMAC_ID, 0x18026000, 181}, /* BCM53017 */ + {BCM53018_CHIP_ID, 0, 1, BCM53010_GMAC_ID, 0x18026000, 181}, /* BCM53019 */ + {BCM53020_CHIP_ID, 0, 0, BCM53010_GMAC_ID, 0x18024000, 181}, /* BCM53022 */ + {BCM53020_CHIP_ID, 4, 0, BCM53010_GMAC_ID, 0x18023000, 180}, /* BCM53022 */ +#endif + {0,0,0,0,0,0} +}; + +static sal_vaddr_t _cca_base = 0; + +static int +_gmac_dev_create(void) +{ + bde_ctrl_t *ctrl; + uint32 gmac_base = 0; + uint32 offset = 0; + uint32 cca_cid; + uint32 cid, rid, pid; + int i = 0, found; + + if (_chip_table.cc_base == 0) { + gprintk("Create GMAC device failed. Unable to identify CPU.\n"); + return -1; + } + + /* 1. Determine which CPU/GMAC configuration is now */ + _cca_base = (sal_vaddr_t)IOREMAP(_chip_table.cc_base, _chip_table.cc_size); + cca_cid = readl((uint32 *)(_cca_base + _chip_table.cid_reg_off)); + + cid = cca_cid & CID_ID_MASK; + rid = (cca_cid & CID_REV_MASK) >> CID_REV_SHIFT; + pid = (cca_cid & CID_PKG_MASK) >> CID_PKG_SHIFT; + + found = 0; + for (i = 0; ; i++) { + if (_gmac_table[i].cid == 0) { + /* End of table */ + break; + } + if ((_gmac_table[i].cid == cid) && + (_gmac_table[i].rid == rid) && + (_gmac_table[i].pid == pid)) { + /* found */ + found = 1; + break; + } + } + if (!found) { + gprintk("Create GMAC device failed. Unable to identify GMAC device.\n"); + } + + /* 2. Create GMAC device */ + /* fill-in necessary information depends on the CPU/GMAC configuration */ + if ((cid == BCM53010_CHIP_ID) || (cid == BCM53018_CHIP_ID) || + (cid == BCM53020_CHIP_ID)) { + ctrl = _devices + _ndevices++; + _ether_ndevices++; + + ctrl->dev_type |= BDE_ETHER_DEV_TYPE; + ctrl->dev_type |= BDE_PCI_DEV_TYPE; + + ctrl->iLine = _gmac_table[i].gmac_irq; + + ctrl->be_pio = 0; + + ctrl->bde_dev.rev = _gmac_table[i].rid; + ctrl->bde_dev.device = _gmac_table[i].gmac_dev_id; + + gmac_base = 0x18000000; + offset = _gmac_table[i].gmac_base_addr - gmac_base; + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(gmac_base, 0x300000); + ctrl->alt_base_addr = ctrl->bde_dev.base_address + offset; + ctrl->phys_address = gmac_base; + + ctrl->isr = NULL; + ctrl->isr_data = NULL; + } + + return 0; +} +#endif +#endif + +/* + * Generic module functions + */ + +/* + * Function: _init + * + * Purpose: + * Module initialization. + * Attaches to kernel BDE. + * Parameters: + * None + * Returns: + * 0 on success, < 0 on error. + */ +static int +_init(void) +{ + +#ifdef IPROC_CMICD + if (iproc_has_cmicd()) { + iproc_cmicd_get_memregion(&iproc_cmicd_resources[IPROC_CMICD_RES_MEM]); + iproc_platform_driver_register(&iproc_cmicd_driver); +#ifdef CONFIG_OF + if (!of_find_compatible_node(NULL, NULL, IPROC_CMICD_COMPATIBLE)) +#endif + { + /* Register platform device if no device node in dtb */ + iproc_platform_device_register(&iproc_cmicd_pdev); + } + } +#endif /* IPROC_CMICD */ + +#ifdef BCM_ICS + _ics_bde_create(); +#else /* PCI */ + /* Register our goodies */ + _device_driver.name = LINUX_KERNEL_BDE_NAME; + +#if defined(BCM_ROBO_SUPPORT) +#if defined(IPROC_CMICD) + if (_gmac_dev_create()) { + return -ENODEV; + } +#endif +#endif /* defined (BCM_ROBO_SUPPORT) */ + + /* Configure MSI interrupt support */ + use_msi = usemsi; + +#ifdef CONFIG_PCI_MSI + if (use_msi == PCI_USE_INT_NONE) { + /* Compilation flag determines default value */ +#ifdef BDE_LINUX_USE_MSIX_INTERRUPT +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + use_msi = PCI_USE_INT_MSIX; +#else + use_msi = PCI_USE_INT_MSI; +#endif +#elif defined(BDE_LINUX_USE_MSI_INTERRUPT) + use_msi = PCI_USE_INT_MSI; +#else + use_msi = PCI_USE_INT_INTX; +#endif + } +#else + if (use_msi > PCI_USE_INT_INTX) { + /* Warn if invalid configuration */ + gprintk("MSI interrupts not supported by kernel\n"); + } + use_msi = PCI_USE_INT_INTX; +#endif /* CONFIG_PCI_MSI */ + + if (unlikely(debug >= 1)) + gprintk("%s(%d):use_msi = %d\n", __func__, __LINE__, use_msi); + if (spi_devid) { + _spi_device_setup(); + } else { + if (pci_register_driver(&_device_driver) < 0) { + return -ENODEV; + } + } + + /* Note: PCI-PCI bridge uses results from pci_register_driver */ + p2p_bridge(); + +#ifdef BCM_METROCORE_LOCAL_BUS + if (probe_metrocore_local_bus()) { + return -1; + } +#endif +#ifdef BCM_PLX9656_LOCAL_BUS + if (num_plx > 0) { + probe_plx_local_bus(); + } +#endif +#endif /* BCM_ICS */ + +#ifdef BCM_ROBO_SUPPORT + probe_robo_switch(); +#endif + +#if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) + sand_device_create(); +#endif + +#if defined(BCM_TK371X_SUPPORT) + probe_tk371x_dev(); +#endif + /* + * Probe for EB Bus devices. + */ + if (eb_bus) { + char *tok; + uint irq = -1, eb_rd16bit=0, eb_wr16bit =0; + unsigned int eb_ba = 0x0; + + gprintk("EB bus info: %s\n", eb_bus); + tok = strtok(eb_bus,","); + while (tok) { + _parse_eb_args(tok, "BA=%x IRQ=%d RD16=%d WR16=%d", + &eb_ba, &irq, &eb_rd16bit, &eb_wr16bit); + _eb_device_create(eb_ba, irq, eb_rd16bit, eb_wr16bit); + tok = strtok(NULL,","); + } + } + + return 0; +} + +/* + * Function: _cleanup + * + * Purpose: + * Module cleanup function. + * Parameters: + * None + * Returns: + * Always 0 + */ +static int +_cleanup(void) +{ + int i; + + _dma_cleanup(); + +#ifdef IPROC_CMICD + if (iproc_has_cmicd()) { +#ifdef CONFIG_OF + if (!of_find_compatible_node(NULL, NULL, IPROC_CMICD_COMPATIBLE)) +#endif + { + iproc_platform_device_unregister(&iproc_cmicd_pdev); + } + iproc_platform_driver_unregister(&iproc_cmicd_driver); + } +#endif + +#if defined(BCM_ROBO_SUPPORT) +#if defined(IPROC_CMICD) + if (_cca_base) { + iounmap((void *)_cca_base); + } +#endif + + if (robo) { +#if defined(KEYSTONE) || defined(IPROC_CMICD) + robo_detach(robo); +#endif /* KEYSTONE || IPROC_CMICD */ + } + if (sbh) { +#if defined(KEYSTONE) || defined(IPROC_CMICD) + ai_soc_detach(sbh); +#endif /* KEYSTONE || IPROC_CMICD */ + } +#endif + for (i = 0; i < _ndevices; i++) { + bde_ctrl_t *ctrl = _devices + i; + + /* free allocated kernel space memory */ + if (ctrl->dev_type & BDE_SPI_DEV_TYPE) { + if (ctrl->spi_device) { + kfree(ctrl->spi_device); + } + } + } +#if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)) && (defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_GTO_BCM_CPU__)) + if (cpu_address) { /* unmap CPU card MMIO */ + iounmap(cpu_address); + cpu_address = NULL; + } +#endif + +#ifdef BCM_ICS +#else + pci_unregister_driver(&_device_driver); +#endif /* BCM_ICS */ + return 0; +} + +/* + * Function: _pprint + * + * Purpose: + * Print proc filesystem information. + * Parameters: + * None + * Returns: + * Always 0 + */ +static int +_pprint(void) +{ + int i = 0; + + pprintf("Broadcom Device Enumerator (%s)\n", LINUX_KERNEL_BDE_NAME); + + _dma_pprint(); + + if (_ndevices == 0) { + pprintf("No devices found\n"); + } else { + pprintf("Devices:\n"); + } + for (i = 0; i < _ndevices; i++) { + bde_ctrl_t *ctrl = _devices + i; + + if (ctrl->dev_type & BDE_SWITCH_DEV_TYPE) { + pprintf("\t%d (swi) : ", i); + } else if (ctrl->dev_type & BDE_ETHER_DEV_TYPE) { + pprintf("\t%d (eth) : ", i); + } else if (ctrl->dev_type & BDE_CPU_DEV_TYPE) { + pprintf("\t%d (cpu) : ", i); + } else { + pprintf("\t%d (?) : ", i); + } + + if (ctrl->dev_state == BDE_DEV_STATE_REMOVED) { + pprintf("PCI device 0x%x:0x%x:%d REMOVED\n", + ctrl->pci_device->vendor, + ctrl->pci_device->device, + ctrl->bde_dev.rev); + continue; + } + if (ctrl->dev_type & BDE_PCI_DEV_TYPE) { + pprintf("PCI device 0x%x:0x%x:%d:0x%.8lx:0x%.8lx:%d%s\n", + ctrl->pci_device->vendor, + ctrl->pci_device->device, + ctrl->bde_dev.rev, + (unsigned long)pci_resource_start(ctrl->pci_device, 0), + (unsigned long)pci_resource_start(ctrl->pci_device, 2), + ctrl->pci_device->irq, + ctrl->use_msi ? " (MSI)" : ""); + } else if (ctrl->dev_type & BDE_SPI_DEV_TYPE) { + pprintf("SPI Device %d:%x:%x:0x%x:0x%x:%d\n", + ctrl->spi_device->cid, + ctrl->spi_device->part, + ctrl->spi_device->rev, + ctrl->spi_device->phyid_high, + ctrl->spi_device->phyid_low, + ctrl->bde_dev.rev); + } else if (ctrl->dev_type & BDE_ICS_DEV_TYPE) { + pprintf("ICS Device 0x%x:0x%x\n", + ctrl->bde_dev.device, + ctrl->bde_dev.rev); + } else if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + pprintf("AXI Device 0x%x:0x%x:0x%.8lx:%d\n", + ctrl->bde_dev.device, + ctrl->bde_dev.rev, + (unsigned long)ctrl->phys_address, + ctrl->iLine); + } else if (ctrl->dev_type & BDE_EB_DEV_TYPE) { + pprintf("EB Bus Device 0x%x:0x%x\n", + ctrl->bde_dev.device, + ctrl->bde_dev.rev); + } + if (debug >= 1) { + pprintf("\t\timask:imask2:fmask 0x%x:0x%x:0x%x\n", + ctrl->imask, + ctrl->imask2, + ctrl->fmask); + } + } + return 0; +} + +#if USE_LINUX_BDE_MMAP +/* + * Some kernels (mainly x86) prevent mapping of kernel RAM memory to + * user space via the /dev/mem device. The function below provides a + * backdoor to mapping the DMA pool to user space via the + * /dev/linux-kernel-bde device. + */ +static int _mmap(struct file *filp, struct vm_area_struct *vma) +{ + unsigned long phys_addr = vma->vm_pgoff << PAGE_SHIFT; + unsigned long size = vma->vm_end - vma->vm_start; + + if(!_dma_range_valid(phys_addr, size)) { + return -EINVAL; + } + +#ifdef REMAP_DMA_NONCACHED + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +#endif + + if (remap_pfn_range(vma, + vma->vm_start, + vma->vm_pgoff, + size, + vma->vm_page_prot)) { + gprintk("Failed to mmap phys range 0x%lx-0x%lx to 0x%lx-0x%lx\n", + phys_addr, phys_addr + size, vma->vm_start,vma->vm_end); + return -EAGAIN; + } + + return 0; +} +#endif /* USE_LINUX_BDE_MMAP */ + +/* Workaround for broken Busybox/PPC insmod */ +static char _modname[] = LINUX_KERNEL_BDE_NAME; + +static gmodule_t _gmodule = { + name: LINUX_KERNEL_BDE_NAME, + major: LINUX_KERNEL_BDE_MAJOR, + init: _init, + cleanup: _cleanup, + pprint: _pprint, +#if USE_LINUX_BDE_MMAP + mmap: _mmap, +#endif +}; + +gmodule_t * +gmodule_get(void) +{ + _gmodule.name = _modname; + return &_gmodule; +} + + +/* + * BDE Interface + */ + +static const char * +_name(void) +{ + return LINUX_KERNEL_BDE_NAME; +} + +static int +_num_devices(int type) +{ + switch (type) { + case BDE_ALL_DEVICES: + return _ndevices; + case BDE_SWITCH_DEVICES: + return _switch_ndevices; + case BDE_ETHER_DEVICES: + return _ether_ndevices; + case BDE_CPU_DEVICES: + return _cpu_ndevices; + } + + return 0; +} + +static const ibde_dev_t * +_get_dev(int d) +{ + if (!VALID_DEVICE(d)) { + gprintk("_get_dev: Invalid device index %d\n", d); + return NULL; + } + + return &_devices[d].bde_dev; +} + +static uint32 +_get_dev_type(int d) +{ + if (!VALID_DEVICE(d)) { + gprintk("_get_dev: Invalid device index %d\n", d); + return 0; + } + + return _devices[d].dev_type; +} + +static uint32 +_pci_conf_read(int d, uint32 addr) +{ +#ifdef BCM_ICS + return 0xFFFFFFFF; +#else + uint32 rc = 0; + + if (!VALID_DEVICE(d)) { + gprintk("_pci_conf_read: Invalid device index %d\n", d); + return 0xFFFFFFFF; + } + + if (!(_devices[d].dev_type & BDE_PCI_DEV_TYPE)) { + gprintk("_pci_conf_read: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return 0xFFFFFFFF; + } + + pci_read_config_dword(_devices[d].pci_device, addr, &rc); + return rc; +#endif /* BCM_ICS */ +} + +static int +_pci_conf_write(int d, uint32 addr, uint32 data) +{ +#ifdef BCM_ICS + return -1; +#else + if (!VALID_DEVICE(d)) { + gprintk("_pci_conf_write: Invalid device index %d\n", d); + return -1; + } + + if (!(_devices[d].dev_type & BDE_PCI_DEV_TYPE)) { + gprintk("_pci_conf_write: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return -1; + } + + pci_write_config_dword(_devices[d].pci_device, addr, data); + return 0; +#endif /* BCM_ICS */ +} + +/* Initialized when the bde is created */ +static linux_bde_bus_t _bus; + +static void +_pci_bus_features(int unit, int *be_pio, int *be_packet, int *be_other) +{ + if ((_devices[unit].bde_dev.device & 0xFF00) != 0x5600 && + (_devices[unit].bde_dev.device & 0xF000) != 0xc000 && + (_devices[unit].bde_dev.device & 0xF000) != 0xb000 && + (_devices[unit].bde_dev.device & 0xF000) != 0x8000 && + (_devices[unit].bde_dev.device & 0xFFF0) != 0x0230 && + (_devices[unit].bde_dev.device & 0xFFF0) != 0xa440) { + if (be_pio) *be_pio = 0; + if (be_packet) *be_packet = 0; + if (be_other) *be_other = 0; + } else { + if (be_pio) *be_pio = _bus.be_pio; + if (be_packet) *be_packet = _bus.be_packet; + if (be_other) *be_other = _bus.be_other; + } +#if defined(BCM_METROCORE_LOCAL_BUS) + if (_devices[unit].dev_type & BDE_EB_DEV_TYPE && be_pio) { + *be_pio = 1; + } +#endif + +} + +static uint32_t +_read(int d, uint32_t addr) +{ + unsigned long flags; + volatile uint16 msb, lsb; + uint32 sl_addr, data; + + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + return -1; + } + + if (_devices[d].dev_type & BDE_DEV_BUS_RD_16BIT) { + /* + * Adjust the address presented to Eb slave. Move A15:A0 to A16:A1. + */ + sl_addr = (addr & 0xffff0000) | ((addr & 0xffff) << 1); + /* Disable interrupts */ + spin_lock_irqsave(&bus_lock, flags); + + lsb = *((uint16 *)(_devices[d].bde_dev.base_address + sl_addr)); + msb = *((uint16 *)(_devices[d].bde_dev.base_address + sl_addr)); + spin_unlock_irqrestore(&bus_lock, flags); + + return (msb << 16) | lsb; + } else { + data = ((VOL uint32_t *)_devices[d].bde_dev.base_address)[addr / 4]; +#if defined(CMIC_SOFT_BYTE_SWAP) + data = CMIC_SWAP32(data); +#endif + return data; + } +} + +static int +_write(int d, uint32_t addr, uint32_t data) +{ + unsigned long flags; + uint32 sl_addr; + + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + return -1; + } + + if (_devices[d].dev_type & BDE_DEV_BUS_WR_16BIT) { + /* + * Adjust the address presented to Eb slave. Move A15:A0 to A16:A1. + */ + sl_addr = (addr & 0xffff0000) | ((addr & 0xffff) << 1); + + /* Disable interrupts */ + spin_lock_irqsave(&bus_lock, flags); + + *((VOL uint16 *)(_devices[d].bde_dev.base_address + sl_addr)) = + data & 0xffff; + *((VOL uint16 *)(_devices[d].bde_dev.base_address + sl_addr)) = + (data >> 16) & 0xffff; + spin_unlock_irqrestore(&bus_lock, flags); + } else { +#if defined(CMIC_SOFT_BYTE_SWAP) + data = CMIC_SWAP32(data); +#endif + ((VOL uint32_t *)_devices[d].bde_dev.base_address)[addr / 4] = data; +#ifdef KEYSTONE + /* Enforce PCIe transaction ordering. Commit the write transaction */ + __asm__ __volatile__("sync"); +#endif + } + return 0; + +} + +static _ISR_RET +_isr(_ISR_PARAMS(irq, dev_id, iregs)) +{ + bde_ctrl_t *ctrl = (bde_ctrl_t *) dev_id; + + if (ctrl && ctrl->isr) { + ctrl->isr(ctrl->isr_data); + } + if (ctrl && ctrl->isr2) { + ctrl->isr2(ctrl->isr2_data); + } + return IRQ_HANDLED; +} + +static int +_interrupt_connect(int d, + void (*isr)(void *), + void *isr_data) +{ + bde_ctrl_t *ctrl; + unsigned long irq_flags; + int isr2_dev; + int isr_active; + int ret = 0; + + isr2_dev = d & LKBDE_ISR2_DEV; + d &= ~LKBDE_ISR2_DEV; + + if (!VALID_DEVICE(d)) { + gprintk("_interrupt_connect: Invalid device index %d\n", d); + return -1; + } + if (debug >= 1) { + gprintk("_interrupt_connect d %d\n", d); + } + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + gprintk("_interrupt_connect: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return -1; + } + + ctrl = _devices + d; + + isr_active = (ctrl->isr || ctrl->isr2) ? 1 : 0; + + if (unlikely(debug > 1)) + gprintk("%s:isr_active = %d\n", __func__, isr_active); + + if (isr2_dev) { + if (debug >= 1) { + gprintk("connect secondary isr\n"); + } + ctrl->isr2_data = isr_data; + ctrl->isr2 = isr; + if (isr_active) { + /* Main handler (_isr) already installed */ + return 0; + } + } else { + if (debug >= 1) { + gprintk("connect primary isr\n"); + } + ctrl->isr = isr; + ctrl->isr_data = isr_data; + if (isr_active) { + /* Main handler (_isr) already installed */ + return 0; + } + } + + if (ctrl->iLine != -1) { + irq_flags = IRQF_SHARED; +#ifdef CONFIG_PCI_MSI + if (ctrl->use_msi >= PCI_USE_INT_MSI) { + ret = _msi_connect(ctrl); + if(ret != 0) + goto msi_exit; + } +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + if (ctrl->use_msi == PCI_USE_INT_MSIX) { + int i; + for (i = 0; i < ctrl->msix_cnt; i++) { + ret = request_irq(ctrl->entries[i].vector, _isr, + irq_flags, LINUX_KERNEL_BDE_NAME, ctrl); + if (ret < 0) + break; + } + if (ret < 0) { + while (i >= 0) + free_irq(ctrl->entries[i--].vector, ctrl->pci_device); + + goto err_disable_msi; + } + } + else +#endif + { + ret = request_irq(ctrl->iLine, _isr, irq_flags, + LINUX_KERNEL_BDE_NAME, ctrl); + if (ret < 0) + goto err_disable_msi; + + if (unlikely(debug >= 1)) + gprintk("%s(%d):device# = %d, irq_flags = %lu, irq = %d\n", + __func__, __LINE__, d, + irq_flags, ctrl->pci_device ? ctrl->pci_device->irq : ctrl->iLine); + } + } + return 0; + +err_disable_msi: +#ifdef CONFIG_PCI_MSI + _msi_disconnect(ctrl); + +msi_exit: +#endif + gprintk("could not request IRQ\n"); + ctrl->isr = NULL; + ctrl->isr_data = NULL; + ctrl->isr2 = NULL; + ctrl->isr2_data = NULL; + + return -1; + } + +static int +_interrupt_disconnect(int d) +{ + bde_ctrl_t *ctrl; + int isr2_dev; + int isr_active; + + isr2_dev = d & LKBDE_ISR2_DEV; + d &= ~LKBDE_ISR2_DEV; + + if (!VALID_DEVICE(d)) { + return -1; + } + + if (debug >= 1) { + gprintk("_interrupt_disconnect d %d\n", d); + } + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + gprintk("_interrupt_disconnect: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return -1; + } + + ctrl = _devices + d; + + isr_active = (ctrl->isr || ctrl->isr2) ? 1 : 0; + + if (unlikely(debug > 1)) + gprintk("%s: isr_active = %d\n", __func__, isr_active); + + if (isr2_dev) { + if (debug >= 1) { + gprintk("disconnect secondary isr\n"); + } + ctrl->isr2 = NULL; + ctrl->isr2_data = NULL; + ctrl->fmask = 0; + if (ctrl->isr) { + /* Primary handler still active */ + SYNC_IRQ(ctrl->iLine); + return 0; + } + } else { + if (debug >= 1) { + gprintk("disconnect primary isr\n"); + } + ctrl->isr = NULL; + ctrl->isr_data = NULL; + if (ctrl->isr2) { + /* Secondary handler still active */ + SYNC_IRQ(ctrl->iLine); + return 0; + } + } + + if (isr_active) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + if (ctrl->use_msi >= PCI_USE_INT_MSIX) { + int i; + for (i = 0; i < ctrl->msix_cnt; i++) + free_irq(ctrl->entries[i].vector, ctrl->pci_device); + } + else +#endif + { + free_irq(ctrl->iLine, ctrl); + } +#ifdef CONFIG_PCI_MSI + if (ctrl->use_msi >= PCI_USE_INT_MSI) { + _msi_disconnect(ctrl); + } +#endif + } + + return 0; +} + +static uint32_t +_iproc_ihost_read(int d, uint32_t addr) +{ + uint32_t *mapaddr; + uint32_t reg_val; + mapaddr = IOREMAP(addr, sizeof(uint32_t)); + if (mapaddr == NULL) { + return -1; + } + reg_val = readl(mapaddr); + iounmap(mapaddr); + return reg_val; +} + +static int +_iproc_ihost_write(int d, uint32_t addr, uint32_t data) +{ + uint32_t *mapaddr; + mapaddr = IOREMAP(addr, sizeof(uint32_t)); + if (mapaddr == NULL) { + return -1; + } + writel(data, mapaddr); + iounmap(mapaddr); + return 0; +} + +static uint32_t +_iproc_read(int d, uint32_t addr) +{ + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + return -1; + } + + if (_devices[d].dev_type & BDE_AXI_DEV_TYPE) { + return _iproc_ihost_read(d, addr); + } + + return shbde_iproc_pci_read(&_devices[d].shbde, + (void *)_devices[d].bde_dev.base_address1, + addr); +} + +static int +_iproc_write(int d, uint32_t addr, uint32_t data) +{ + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + return -1; + } + + if (_devices[d].dev_type & BDE_AXI_DEV_TYPE) { + return _iproc_ihost_write(d, addr, data); + } + + shbde_iproc_pci_write(&_devices[d].shbde, + (void *)_devices[d].bde_dev.base_address1, + addr, data); + + return 0; +} + +static int +_get_cmic_ver(int d , uint32_t *ver) +{ + + unsigned int cap_base; + uint32_t rval = 0; + + if (!VALID_DEVICE(d)) { + gprintk("%s: Invalid device index %d\n", __func__, d); + return -1; + } + + if (!(_devices[d].dev_type & BDE_PCI_DEV_TYPE)) { + gprintk("%s: Not PCI device %d, type %x\n", __func__, + d, _devices[d].dev_type); + return -1; + } + + /* Look for PCIe vendor-specific extended capability (VSEC) */ + cap_base = PCI_EXT_CAP_START; + while (cap_base) { + pci_read_config_dword(_devices[d].pci_device, cap_base, &rval); + if (rval == 0xffffffff) { + /* Assume PCI HW read error */ + gprintk("%s: PCI HW read error\n", __func__); + return -1; + } + + if (PCI_EXT_CAP_ID(rval) == PCI_EXT_CAP_ID_VNDR) { + break; + } + cap_base = PCI_EXT_CAP_NEXT(rval); + } + if (cap_base) { + /* + * VSEC layout: + * + * 0x00: PCI Express Extended Capability Header + * 0x04: Vendor-Specific Header + * 0x08: Vendor-Specific Register 1 + * 0x0c: Vendor-Specific Register 2 + * ... + * 0x24: Vendor-Specific Register 8 + */ + pci_read_config_dword(_devices[d].pci_device, cap_base + 8, &rval); + if (unlikely(debug > 1)) + gprintk("%s:Found VSEC = %u\n", __func__, rval); + + /* Determine if CMICX */ + rval = ((rval >> 12) & 0xf); + *ver = rval; + + return 0; + } else { + gprintk("%s:VSEC not found\n", __func__); + } + + return -1; +} + +#ifdef BCM_ROBO_SUPPORT +#define SOC_ROBO_PAGE_BP 8 /* for Robo Chip only */ + +#if defined(IPROC_CMICD) +extern int ccb_mii_read(int dev_type, int phy_addr, int reg_off, uint16 *data); +extern int ccb_mii_write(int dev_type, int phy_addr, int reg_off, uint16 data); + +/* device type */ +#define MII_DEV_LOCAL 0 +#define MII_DEV_EXT 1 +#endif + +static int +_spi_read(int d, uint32 addr, uint8 *buf, int len) +{ +#if defined(KEYSTONE) || defined(IPROC_CMICD) + bde_ctrl_t *ctrl; + uint8 page, offset; +#endif +#if defined(IPROC_CMICD) + int rv = 0; + uint16 value = 0; +#endif + + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(_devices[d].dev_type & BDE_SPI_DEV_TYPE)) { + gprintk("_spi_read: Not SPI device %d, type %x\n", + d, _devices[d].dev_type); + return -1; + } + +#if defined(KEYSTONE) || defined(IPROC_CMICD) + ctrl = _devices + d; +#endif + +#if defined(IPROC_CMICD) + if (addr & SOC_EXTERNAL_PHY_BUS_CPUMDIO) { + rv = ccb_mii_read(MII_DEV_EXT, (addr >> 8) & 0xff, addr & 0xff, &value); + memcpy(buf, &value, 2); + return rv; + } +#endif + +#if defined(KEYSTONE) || defined(IPROC_CMICD) + page = (addr >> SOC_ROBO_PAGE_BP) & 0xFF; + offset = addr & 0xFF; +#endif + +#if defined(IPROC_CMICD) && defined(BCM_STARFIGHTER3_SUPPORT) + if (spi_device_found) { + ROBO_SPI_RREG(ctrl->spi_device->robo, ctrl->spi_device->cid, + page, offset, buf, (uint)len); + } else +#endif + { + ROBO_RREG(ctrl->spi_device->robo, ctrl->spi_device->cid, + page, offset, buf, (uint)len); + } + + return 0; +} + +static int +_spi_write(int d, uint32 addr, uint8 *buf, int len) +{ +#if defined(KEYSTONE) || defined(IPROC_CMICD) + bde_ctrl_t *ctrl; + uint8 page, offset; +#endif +#if defined(IPROC_CMICD) + int rv = 0; + uint16 value = 0; +#endif + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(_devices[d].dev_type & BDE_SPI_DEV_TYPE)) { + gprintk("_spi_write: Not SPI device %d, type %x\n", + d, _devices[d].dev_type); + return -1; + } + +#if defined(KEYSTONE) || defined(IPROC_CMICD) + ctrl = _devices + d; +#endif + +#if defined(IPROC_CMICD) + if (addr & SOC_EXTERNAL_PHY_BUS_CPUMDIO) { + memcpy(&value, buf, 2); + rv = ccb_mii_write(MII_DEV_EXT, (addr >> 8) & 0xff, addr & 0xff, value); + return rv; + } +#endif + +#if defined(KEYSTONE) || defined(IPROC_CMICD) + page = (addr >> SOC_ROBO_PAGE_BP) & 0xFF; + offset = addr & 0xFF; +#endif + +#if defined(IPROC_CMICD) && defined(BCM_STARFIGHTER3_SUPPORT) + if (spi_device_found) { + ROBO_SPI_WREG(ctrl->spi_device->robo, ctrl->spi_device->cid, + page, offset, buf, (uint)len); + } else +#endif + { + ROBO_WREG(ctrl->spi_device->robo, ctrl->spi_device->cid, + page, offset, buf, (uint)len); + } + + return 0; +} + +#endif + +#if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) +int +lkbde_cpu_write(int d, uint32 addr, uint32 *buf) +{ +#if defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_GTO_BCM_CPU__) + *((uint32_t*)((uint8_t*)cpu_address + addr)) = *buf; +#endif + + return 0; +} + +int +lkbde_cpu_read(int d, uint32 addr, uint32 *buf) +{ +#if defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_GTO_BCM_CPU__) + *buf = *((uint32_t*)((uint8_t*)cpu_address + addr)); +#else + *buf = (uint32_t)(-1); +#endif + + return 0; +} + +int +lkbde_cpu_pci_register(int d) +{ + bde_ctrl_t* ctrl; + uint16 cmd = 0; + + if (!VALID_DEVICE(d)) { + return -1; + } + + ctrl = &_devices[d]; + + /* enable device */ + if (pci_enable_device(ctrl->pci_device)) { + gprintk("Cannot enable pci device : vendor_id = %x, device_id = %x\n", + ctrl->pci_device->vendor, ctrl->pci_device->device); + } + + /* Add PCI_COMMAND_MEMORY and PCI_COMMAND_MASTER */ + pci_read_config_word(ctrl->pci_device, PCI_COMMAND, &cmd); + if (!(cmd & PCI_COMMAND_MEMORY) || !(cmd & PCI_COMMAND_MASTER)) { + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_write_config_word(ctrl->pci_device, PCI_COMMAND, cmd); + } + + switch (ctrl->bde_dev.device) { + case GEDI_DEVICE_ID: + /* Fix bar 0 address */ /* FIXME: write full phy address */ + pci_write_config_byte(ctrl->pci_device, 0x13, 0x60); + + /* Fix Max payload size */ + pci_write_config_byte(ctrl->pci_device, 0x88, 0x2f); + pci_write_config_byte(ctrl->pci_device, 0x89, 0x10); + break; + case BCM88750_DEVICE_ID: + case BCM88753_DEVICE_ID: + case BCM88755_DEVICE_ID: + case BCM88770_DEVICE_ID: + case BCM88773_DEVICE_ID: + case BCM88774_DEVICE_ID: + case BCM88775_DEVICE_ID: + case BCM88776_DEVICE_ID: + case BCM88777_DEVICE_ID: + case BCM88950_DEVICE_ID: + case BCM88953_DEVICE_ID: + case BCM88954_DEVICE_ID: + case BCM88955_DEVICE_ID: + case BCM88956_DEVICE_ID: + case BCM88752_DEVICE_ID: + case BCM88772_DEVICE_ID: + case BCM88952_DEVICE_ID: + case ACP_PCI_DEVICE_ID: + case BCM88650_DEVICE_ID: + + case BCM88670_DEVICE_ID: + case BCM88671_DEVICE_ID: + case BCM88671M_DEVICE_ID: + case BCM88672_DEVICE_ID: + case BCM88673_DEVICE_ID: + case BCM88674_DEVICE_ID: + case BCM88675_DEVICE_ID: + case BCM88675M_DEVICE_ID: + case BCM88676_DEVICE_ID: + case BCM88676M_DEVICE_ID: + case BCM88677_DEVICE_ID: + case BCM88678_DEVICE_ID: + case BCM88679_DEVICE_ID: + + case BCM88370_DEVICE_ID: + case BCM88371_DEVICE_ID: + case BCM88371M_DEVICE_ID: + case BCM88375_DEVICE_ID: + case BCM88376_DEVICE_ID: + case BCM88376M_DEVICE_ID: + case BCM88377_DEVICE_ID: + case BCM88378_DEVICE_ID: + case BCM88379_DEVICE_ID: + case BCM88681_DEVICE_ID: + case BCM88682_DEVICE_ID: + case BCM88683_DEVICE_ID: + case BCM88684_DEVICE_ID: + case BCM88685_DEVICE_ID: + case BCM88380_DEVICE_ID: + case BCM88381_DEVICE_ID: + case BCM88680_DEVICE_ID: + case BCM88690_DEVICE_ID: + case BCM88470_DEVICE_ID: + case BCM88470P_DEVICE_ID: + case BCM88471_DEVICE_ID: + case BCM88473_DEVICE_ID: + case BCM88474_DEVICE_ID: + case BCM88474H_DEVICE_ID: + case BCM88476_DEVICE_ID: + case BCM88477_DEVICE_ID: + case BCM88270_DEVICE_ID: + case BCM88272_DEVICE_ID: + case BCM88273_DEVICE_ID: + case BCM88278_DEVICE_ID: + case BCM8206_DEVICE_ID: + case BCM88350_DEVICE_ID: + case BCM88351_DEVICE_ID: + case BCM88450_DEVICE_ID: + case BCM88451_DEVICE_ID: + case BCM88550_DEVICE_ID: + case BCM88551_DEVICE_ID: + case BCM88552_DEVICE_ID: + case BCM88651_DEVICE_ID: + case BCM88654_DEVICE_ID: + case BCM88660_DEVICE_ID: + case BCM88360_DEVICE_ID: + case BCM88361_DEVICE_ID: + case BCM88363_DEVICE_ID: + case BCM88460_DEVICE_ID: + case BCM88461_DEVICE_ID: + case BCM88560_DEVICE_ID: + case BCM88561_DEVICE_ID: + case BCM88562_DEVICE_ID: + case BCM88661_DEVICE_ID: + case BCM88664_DEVICE_ID: + /* Fix bar 0 address */ /* FIXME: write full phy address */ + pci_write_config_byte(ctrl->pci_device, 0x12, 0x10); + pci_write_config_byte(ctrl->pci_device, 0x13, 0x60); + + /* + * For DMA transactions - set Max_Payload_Size and + * Max_Read_Request_Size to 128 bytes. + */ + pci_write_config_byte(ctrl->pci_device, 0xb5, 0x0c); + pci_write_config_byte(ctrl->pci_device, 0xb4, 0x0); + break; + default: + break; + } + + /* Redo ioremap */ + if (ctrl->bde_dev.base_address) { + iounmap((void *)ctrl->bde_dev.base_address); + } + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(ctrl->phys_address, 0x1000000); + + if (debug >= 1) { + gprintk("%s, %s(): info:\n", __FILE__, __FUNCTION__); + gprintk("_ndevices=%d, _switch_ndevices=%d\n", + _ndevices, _switch_ndevices); + gprintk("ctrl->dev_type=0x%x, ctrl->phys_address=0x%lx\n", + ctrl->dev_type, (unsigned long)ctrl->phys_address); + gprintk("ctrl->bde_dev.device=0x%x, ctrl->bde_dev.rev=0x%x, " + "ctrl->bde_dev.base_address=0x%lx\n", + ctrl->bde_dev.device, ctrl->bde_dev.rev, + (unsigned long)ctrl->bde_dev.base_address); + } + + return 0; +} + +/* + * Export Low level access function - currently for PCP DMA Kernel module. + */ +int +lkbde_mem_write(int d, uint32 addr, uint32 *buf) +{ + bde_ctrl_t* ctrl; + void *full_addr; + + if (!VALID_DEVICE(d)) return -1; + ctrl = &_devices[d]; + + full_addr = (void *)ctrl->bde_dev.base_address + addr; + *((uint32_t*)full_addr) = *buf; + return 0; +} +LKM_EXPORT_SYM(lkbde_mem_write); + +int +lkbde_mem_read(int d, uint32 addr, uint32 *buf) +{ + bde_ctrl_t* ctrl; + void *full_addr; + + if (!VALID_DEVICE(d)) return -1; + ctrl = &_devices[d]; + + full_addr = (void *)ctrl->bde_dev.base_address + addr; + *buf = *((uint32_t*)full_addr); + return 0; +} +LKM_EXPORT_SYM(lkbde_mem_read); +#endif /* defined(BCM_PETRA_SUPPORT) */ + +static ibde_t _ibde = { + name: _name, + num_devices: _num_devices, + get_dev: _get_dev, + get_dev_type: _get_dev_type, + pci_conf_read: _pci_conf_read, + pci_conf_write: _pci_conf_write, + pci_bus_features: _pci_bus_features, + read: _read, + write: _write, + salloc: _salloc, + sfree: _sfree, + sinval: _sinval, + sflush: _sflush, + interrupt_connect: _interrupt_connect, + interrupt_disconnect: _interrupt_disconnect, + l2p: _l2p, + p2l: _p2l, +#if defined(BCM_ROBO_SUPPORT) + spi_read: _spi_read, + spi_write: _spi_write, +#else + NULL, + NULL, +#endif /* defined(BCM_ROBO_SUPPORT) */ + iproc_read: _iproc_read, + iproc_write: _iproc_write, + get_cmic_ver: _get_cmic_ver, +}; + +/* + * Function: linux_bde_create + * + * Purpose: + * Creator function for this BDE interface. + * Parameters: + * bus - pointer to the bus features structure you want this + * bde to export. Depends on the system. + * ibde - pointer to a location to recieve the bde interface pointer. + * Returns: + * 0 on success + * -1 on failure. + * Notes: + * This is the main BDE create function for this interface. + * Used by the external system initialization code. + */ +int +linux_bde_create(linux_bde_bus_t *bus, ibde_t **ibde) +{ + + memset(&_bus, 0, sizeof(_bus)); + + if (bus) { + _bus = *bus; + } +#ifdef NONCOHERENT_DMA_MEMORY +#ifdef REMAP_DMA_NONCACHED + /* + * If we have a non-cached DMA memory pool + * there is no need to flush and invalidate. + */ + if (_dma_pool_allocated()) { + _ibde.sinval = NULL; + _ibde.sflush = NULL; + } +#endif +#else + _ibde.sinval = NULL; + _ibde.sflush = NULL; +#endif + *ibde = &_ibde; + return 0; +} + +/* + * Function: linux_bde_destroy + * + * Purpose: + * destroy this bde + * Parameters: + * BDE interface pointer + * Returns: + * 0 on success, < 0 on error. + */ +int +linux_bde_destroy(ibde_t *ibde) +{ + /* nothing */ + return 0; +} + +/* + * Backdoors provided by the kernel bde + */ + +uint32_t +lkbde_get_dev_phys(int d) +{ + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + gprintk("lkbde_get_dev_phys: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return 0; + } + return _devices[d].phys_address; +} + +uint32_t +lkbde_get_dev_phys_hi(int d) +{ + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + gprintk("lkbde_get_dev_phys: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return 0; + } +#ifdef PHYS_ADDR_IS_64BIT + return (uint32_t)(_devices[d].phys_address >> 32); +#else + return 0; +#endif +} + +void * +lkbde_get_dev_virt(int d) +{ + if (!VALID_DEVICE(d)) { + return NULL; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + gprintk("lkbde_get_dev_virt: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return 0; + } + + if (_devices[d].alt_base_addr) { + return (void *)_devices[d].alt_base_addr; + } + + return (void *)_devices[d].bde_dev.base_address; +} + +int +lkbde_get_dev_resource(int d, int rsrc, uint32_t *flags, + uint32_t *phys_lo, uint32_t *phys_hi) +{ + if (!VALID_DEVICE(d)) { + return -1; + } + + *flags = 0; + *phys_lo = 0; + *phys_hi = 0; + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + gprintk("lkbde_get_dev_phys: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return 0; + } + + switch (rsrc) { + case 0: + *phys_lo = (uint32_t)(_devices[d].phys_address); +#ifdef PHYS_ADDR_IS_64BIT + *phys_hi = (uint32_t)(_devices[d].phys_address >> 32); +#endif + break; + case 1: + *phys_lo = (uint32_t)(_devices[d].phys_address1); +#ifdef PHYS_ADDR_IS_64BIT + *phys_hi = (uint32_t)(_devices[d].phys_address1 >> 32); +#endif + break; + default: + break; + } + + return 0; +} + +void * +lkbde_get_dma_dev(int d) +{ + if (!VALID_DEVICE(d)) { + return NULL; + } + +#ifdef LINUX_BDE_DMA_DEVICE_SUPPORT + return (void *)_devices[d].dma_dev; +#else + return (void *)_devices[d].pci_device; +#endif +} + +void * +lkbde_get_hw_dev(int d) +{ + if (!VALID_DEVICE(d)) { + return NULL; + } + + return (void *)_devices[d].pci_device; +} + +int +lkbde_dev_state_set(int d, uint32 state) +{ + bde_ctrl_t *ctrl; + + if (!VALID_DEVICE(d)) { + return -1; + } + ctrl = _devices + d; + ctrl->dev_state = state; + return 0; +} + +int +lkbde_dev_state_get(int d, uint32 *state) +{ + bde_ctrl_t *ctrl; + if (!VALID_DEVICE(d)) { + gprintk("_get_dev: Invalid device index %d\n", d); + return -1; + } + ctrl = _devices + d; + + *state = ctrl->dev_state; + return 0; +} + +int +lkbde_dev_instid_set(int d, uint32 instid) +{ + bde_ctrl_t *ctrl; + + if (!VALID_DEVICE(d)) { + return -1; + } + ctrl = _devices + d; + ctrl->inst_id = instid; + + return 0; +} + +int +lkbde_dev_instid_get(int d, uint32 *instid) +{ + bde_ctrl_t *ctrl; + + if (!VALID_DEVICE(d)) { + return -1; + } + ctrl = _devices + d; + *instid = ctrl->inst_id; + + return 0; +} +/* + * When a secondary interrupt handler is installed this function + * is used for synchronizing hardware access to the IRQ mask + * register. The secondary driver will supply a non-zero fmask + * (filter mask) to indicate which interrupt bits it controls. + * The fmask is ignored for the primary driver. + */ +int +lkbde_irq_mask_set(int d, uint32_t addr, uint32_t mask, uint32_t fmask) +{ + bde_ctrl_t *ctrl; + int isr2_dev, iproc_reg; + unsigned long flags; + + isr2_dev = d & LKBDE_ISR2_DEV; + iproc_reg = d & LKBDE_IPROC_REG; + d &= ~(LKBDE_ISR2_DEV | LKBDE_IPROC_REG); + + if (!VALID_DEVICE(d)) { + return -1; + } + + ctrl = _devices + d; + + /* Lock is required to synchronize access from user space */ + spin_lock_irqsave(&ctrl->lock, flags); + + if (isr2_dev) { + /* This is the secondary interrupt handler */ + ctrl->fmask = fmask; + ctrl->imask2 = mask & ctrl->fmask; + } else { + /* This is the primary interrupt handler */ + ctrl->imask = mask & ~ctrl->fmask; + } + + if (iproc_reg) { + _iproc_write(d, addr, ctrl->imask | ctrl->imask2); + } else { + _write(d, addr, ctrl->imask | ctrl->imask2); + } + + spin_unlock_irqrestore(&ctrl->lock, flags); + + return 0; +} + +/* + * When a secondary interrupt handler is installed, this function + * is used to avoid activating the user mode interrupt handler + * thread if all pending interrupts are handled in kernel space. + * + * The mask returned is the mask of all interrupts, it can be used + * to do a logical AND with fmask, the result will tell you if + * the user mode interrupt handler needs to be invoked. + * + * Note that if no secondary handler is installed, the value of + * "mask & fmask" will be zero, and hence there will be no need to read the + * current interrupt status from hardware (from kernel space). + */ +int +lkbde_irq_mask_get(int d, uint32_t *mask, uint32_t *fmask) +{ + bde_ctrl_t *ctrl; + + d &= ~(LKBDE_ISR2_DEV | LKBDE_IPROC_REG); + + if (!VALID_DEVICE(d)) { + return -1; + } + + if (mask == NULL || fmask == NULL) { + return -1; + } + + ctrl = _devices + d; + + *fmask = ctrl->fmask; + *mask = ctrl->imask | ctrl->imask2; + + return 0; +} + +int +lkbde_get_num_devices(int type) +{ + return _num_devices(type); +} + +/* + * Export functions + */ +LKM_EXPORT_SYM(linux_bde_create); +LKM_EXPORT_SYM(linux_bde_destroy); +LKM_EXPORT_SYM(lkbde_get_dev_phys); +LKM_EXPORT_SYM(lkbde_get_dev_virt); +LKM_EXPORT_SYM(lkbde_get_dev_resource); +LKM_EXPORT_SYM(lkbde_get_hw_dev); +LKM_EXPORT_SYM(lkbde_get_dma_dev); +LKM_EXPORT_SYM(lkbde_irq_mask_set); +LKM_EXPORT_SYM(lkbde_irq_mask_get); +LKM_EXPORT_SYM(lkbde_get_dev_phys_hi); +LKM_EXPORT_SYM(lkbde_dev_state_set); +LKM_EXPORT_SYM(lkbde_dev_state_get); +LKM_EXPORT_SYM(lkbde_dev_instid_set); +LKM_EXPORT_SYM(lkbde_dev_instid_get); +#if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT)) +LKM_EXPORT_SYM(lkbde_cpu_write); +LKM_EXPORT_SYM(lkbde_cpu_read); +LKM_EXPORT_SYM(lkbde_cpu_pci_register); +#endif diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c new file mode 100644 index 000000000000..32b769784c2e --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c @@ -0,0 +1,971 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: linux_dma.c,v 1.414 Broadcom SDK $ + * $Copyright: (c) 2016 Broadcom Corp. + * All Rights Reserved.$ + * + * Linux Kernel BDE DMA memory allocation + * + * + * DMA memory allocation modes + * =========================== + * + * 1. Using private pool in kernel memory + * -------------------------------------- + * In this mode the BDE module will try to assemble a physically contiguous + * of memory using the kernel page allocator. This memory block is then + * administered by the mpool allocation functions. Note that once a system + * has been running for a while, the memory fragmentation may prevent the + * allocator from assembling a contiguous memory block, however, if the + * module is loaded shortly after system startup, it is very unlikely to + * fail. + * + * This allocation method is used by default. + * + * 2. Using private pool in high memory + * ------------------------------------ + * In this mode the BDE module will assume that unused physical memory is + * present at the high_memory address, i.e. memory not managed by the Linux + * memory manager. This memory block is mapped into kernel space and + * administered by the mpool allocation functions. High memory must be + * reserved using either the mem=xxx kernel parameter (recommended), or by + * hardcoding the memory limit in the kernel image. + * + * The module parameter himem=1 enables this allocation mode. + * + * 3. Using kernel allocators (kmalloc, __get_free_pages) + * ------------------------------------------------------ + * In this mode all DMA memory is allocated from the kernel on the fly, i.e. + * no private DMA memory pool will be created. If large memory blocks are + * only allocated at system startup (or not at all), this allocation method + * is the most flexible and memory-efficient, however, it is not recommended + * for non-coherent memory platforms due to an overall system performance + * degradation arising from the use of cache flush/invalidate instructions. + * + * The module parameter dmasize=0M enables this allocation mode, however if + * DMA memory is requested from a user mode application, a private memory + * pool will be created and used irrespectively. + */ + +#include +#include +#include +#include +#include + +#ifdef BCM_PLX9656_LOCAL_BUS +#include +#endif + +/* allocation types/methods for the DMA memory pool */ +#define ALLOC_TYPE_CHUNK 0 /* use small allocations and join them */ +#define ALLOC_TYPE_API 1 /* use one allocation */ +#if _SIMPLE_MEMORY_ALLOCATION_ +#include +#if defined(IPROC_CMICD) && defined(CONFIG_CMA) && defined(CONFIG_CMA_SIZE_MBYTES) +#define DMA_MAX_ALLOC_SIZE (CONFIG_CMA_SIZE_MBYTES * 1024 * 1024) +#else +#define DMA_MAX_ALLOC_SIZE (1 << (MAX_ORDER - 1 + PAGE_SHIFT)) /* Maximum size the kernel can allocate in one allocation */ +#endif +#endif /* _SIMPLE_MEMORY_ALLOCATION_ */ + +#if _SIMPLE_MEMORY_ALLOCATION_ == 1 +#define ALLOC_METHOD_DEFAULT ALLOC_TYPE_API +#else +#define ALLOC_METHOD_DEFAULT ALLOC_TYPE_CHUNK +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) +#include +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) +#define VIRT_TO_PAGE(p) virt_to_page((void*)(p)) +#else +#define VIRT_TO_PAGE(p) virt_to_page((p)) +#endif + +#ifndef KMALLOC_MAX_SIZE +#define KMALLOC_MAX_SIZE (1UL << (MAX_ORDER - 1 + PAGE_SHIFT)) +#endif + +/* Compatibility */ +#ifdef LKM_2_4 +#define MEM_MAP_RESERVE mem_map_reserve +#define MEM_MAP_UNRESERVE mem_map_unreserve +#else /* LKM_2_6 */ +#define MEM_MAP_RESERVE SetPageReserved +#define MEM_MAP_UNRESERVE ClearPageReserved +#endif /* LKM_2_x */ + +#ifndef GFP_DMA32 +#define GFP_DMA32 0 +#endif + +/* Flags for memory allocations */ +#ifdef SAL_BDE_XLP +static int mem_flags = GFP_ATOMIC | GFP_KERNEL | GFP_DMA; +#else +#if defined(CONFIG_ZONE_DMA32) +static int mem_flags = GFP_ATOMIC | GFP_DMA32; +#else +static int mem_flags = GFP_ATOMIC | GFP_DMA; +#endif +#endif + +/* Debug output */ +static int dma_debug = 0; +module_param(dma_debug, int, 0); +MODULE_PARM_DESC(dma_debug, +"DMA debug output enable (default 0)."); + +/* DMA memory pool size */ +static char *dmasize; +LKM_MOD_PARAM(dmasize, "s", charp, 0); +MODULE_PARM_DESC(dmasize, +"Specify DMA memory size (default 4MB)"); + +/* Select DMA memory pool allocation method */ +static int dmaalloc = ALLOC_METHOD_DEFAULT; +LKM_MOD_PARAM(dmaalloc, "i", int, 0); +MODULE_PARM_DESC(dmaalloc, "Select DMA memory allocation method"); + +/* Use high memory for DMA */ +static char *himem; +LKM_MOD_PARAM(himem, "s", charp, 0); +MODULE_PARM_DESC(himem, +"Use high memory for DMA (default no)"); + +/* Physical high memory address to use for DMA */ +static char *himemaddr = 0; +LKM_MOD_PARAM(himemaddr, "s", charp, 0); +MODULE_PARM_DESC(himemaddr, +"Physical address to use for high memory DMA"); + +/* DMA memory allocation */ + +#define ONE_KB 1024 +#define ONE_MB (1024*1024) +#define ONE_GB (1024*1024*1024) + +/* Default DMA memory size */ +#ifdef SAL_BDE_DMA_MEM_DEFAULT +#define DMA_MEM_DEFAULT (SAL_BDE_DMA_MEM_DEFAULT * ONE_MB) +#else +#define DMA_MEM_DEFAULT (8 * ONE_MB) +#endif +#define DMA_MEM_DEFAULT_ROBO (4 * ONE_MB) + +/* We try to assemble a contiguous segment from chunks of this size */ +#define DMA_BLOCK_SIZE (512 * ONE_KB) + +typedef struct _dma_segment { + struct list_head list; + unsigned long req_size; /* Requested DMA segment size */ + unsigned long blk_size; /* DMA block size */ + unsigned long blk_order; /* DMA block size in alternate format */ + unsigned long seg_size; /* Current DMA segment size */ + unsigned long seg_begin; /* Logical address of segment */ + unsigned long seg_end; /* Logical end address of segment */ + unsigned long *blk_ptr; /* Array of logical DMA block addresses */ + int blk_cnt_max; /* Maximum number of block to allocate */ + int blk_cnt; /* Current number of blocks allocated */ +} dma_segment_t; + +static unsigned int _dma_mem_size = DMA_MEM_DEFAULT; +static mpool_handle_t _dma_pool = NULL; +static void __iomem *_dma_vbase = NULL; +/* cpu physical address for mmap */ +static phys_addr_t _cpu_pbase = 0; +/* + * DMA bus address, it is either identical to cpu physical address + * or another address(IOVA) translated by IOMMU. + */ +static phys_addr_t _dma_pbase = 0; +static int _use_himem = 0; +static unsigned long _himemaddr = 0; +static int _use_dma_mapping = 0; +static LIST_HEAD(_dma_seg); + +#define DMA_DEV(n) lkbde_get_dma_dev(n) +#define BDE_NUM_DEVICES(t) lkbde_get_num_devices(t) + +/* + * Function: _find_largest_segment + * + * Purpose: + * Find largest contiguous segment from a pool of DMA blocks. + * Parameters: + * dseg - DMA segment descriptor + * Returns: + * 0 on success, < 0 on error. + * Notes: + * Assembly stops if a segment of the requested segment size + * has been obtained. + * + * Lower address bits of the DMA blocks are used as follows: + * 0: Untagged + * 1: Discarded block + * 2: Part of largest contiguous segment + * 3: Part of current contiguous segment + */ +static int +_find_largest_segment(dma_segment_t *dseg) +{ + int i, j, blks, found; + unsigned long b, e, a; + + blks = dseg->blk_cnt; + /* Clear all block tags */ + for (i = 0; i < blks; i++) { + dseg->blk_ptr[i] &= ~3; + } + for (i = 0; i < blks && dseg->seg_size < dseg->req_size; i++) { + /* First block must be an untagged block */ + if ((dseg->blk_ptr[i] & 3) == 0) { + /* Initial segment size is the block size */ + b = dseg->blk_ptr[i]; + e = b + dseg->blk_size; + dseg->blk_ptr[i] |= 3; + /* Loop looking for adjacent blocks */ + do { + found = 0; + for (j = i + 1; j < blks && (e - b) < dseg->req_size; j++) { + a = dseg->blk_ptr[j]; + /* Check untagged blocks only */ + if ((a & 3) == 0) { + if (a == (b - dseg->blk_size)) { + /* Found adjacent block below current segment */ + dseg->blk_ptr[j] |= 3; + b = a; + found = 1; + } else if (a == e) { + /* Found adjacent block above current segment */ + dseg->blk_ptr[j] |= 3; + e += dseg->blk_size; + found = 1; + } + } + } + } while (found); + if ((e - b) > dseg->seg_size) { + /* The current block is largest so far */ + dseg->seg_begin = b; + dseg->seg_end = e; + dseg->seg_size = e - b; + /* Re-tag current and previous largest segment */ + for (j = 0; j < blks; j++) { + if ((dseg->blk_ptr[j] & 3) == 3) { + /* Tag current segment as the largest */ + dseg->blk_ptr[j] &= ~1; + } else if ((dseg->blk_ptr[j] & 3) == 2) { + /* Discard previous largest segment */ + dseg->blk_ptr[j] ^= 3; + } + } + } else { + /* Discard all blocks in current segment */ + for (j = 0; j < blks; j++) { + if ((dseg->blk_ptr[j] & 3) == 3) { + dseg->blk_ptr[j] &= ~2; + } + } + } + } + } + return 0; +} + +/* + * Function: _alloc_dma_blocks + * + * Purpose: + * Allocate DMA blocks and add them to the pool. + * Parameters: + * dseg - DMA segment descriptor + * blks - number of DMA blocks to allocate + * Returns: + * 0 on success, < 0 on error. + * Notes: + * DMA blocks are allocated using the page allocator. + */ +static int +_alloc_dma_blocks(dma_segment_t *dseg, int blks) +{ + int i, start; + unsigned long addr; + + if (dseg->blk_cnt + blks > dseg->blk_cnt_max) { + gprintk("No more DMA blocks\n"); + return -1; + } + start = dseg->blk_cnt; + for (i = 0; i < blks; i++) { + /* + * Note that we cannot use pci_alloc_consistent when we + * want to be able to map DMA memory to user space. + * + * The GFP_DMA flag is omitted as this imposes the ISA + * addressing limitations on x86 platforms. As long as + * we have less than 1GB of memory, we can do PCI DMA + * to all physical RAM locations. + */ + addr = __get_free_pages(mem_flags, dseg->blk_order); + if (addr) { + dseg->blk_ptr[start + i] = addr; + ++dseg->blk_cnt; + } else { + gprintk("DMA allocation failed: allocated %d of %d " + "requested blocks\n", i, blks); + return -1; + } + } + return 0; +} + +/* + * Function: _dma_segment_alloc + * + * Purpose: + * Allocate large physically contiguous DMA segment. + * Parameters: + * size - requested DMA segment size + * blk_size - assemble segment from blocks of this size + * Returns: + * DMA segment descriptor. + * Notes: + * Since we cannot allocate large blocks of contiguous + * memory from the kernel, we simply keep allocating + * smaller chunks until we can assemble a contiguous + * block of the desired size. + * + * When system allowed maximum bytes of memory has been allocated + * without a successful assembly of a contiguous DMA + * segment, the allocation function will return the + * largest contiguous segment found so far. It is up + * to the calling function to decide whether this + * amount is sufficient to proceed. + */ +static dma_segment_t * +_dma_segment_alloc(size_t size, size_t blk_size) +{ + dma_segment_t *dseg; + int i, blk_ptr_size; + unsigned long page_addr; + struct sysinfo si; + + /* Sanity check */ + if (size == 0 || blk_size == 0) { + return NULL; + } + /* Allocate an initialize DMA segment descriptor */ + if ((dseg = kmalloc(sizeof(dma_segment_t), GFP_KERNEL)) == NULL) { + return NULL; + } + memset(dseg, 0, sizeof(dma_segment_t)); + dseg->req_size = size; + dseg->blk_size = PAGE_ALIGN(blk_size); + while ((PAGE_SIZE << dseg->blk_order) < dseg->blk_size) { + dseg->blk_order++; + } + + si_meminfo(&si); + dseg->blk_cnt_max = (si.totalram << PAGE_SHIFT) / dseg->blk_size; + blk_ptr_size = dseg->blk_cnt_max * sizeof(unsigned long); + if (blk_ptr_size > KMALLOC_MAX_SIZE) { + blk_ptr_size = KMALLOC_MAX_SIZE; + dseg->blk_cnt_max = KMALLOC_MAX_SIZE / sizeof(unsigned long); + } + /* Allocate an initialize DMA block pool */ + dseg->blk_ptr = KMALLOC(blk_ptr_size, GFP_KERNEL); + if (dseg->blk_ptr == NULL) { + kfree(dseg); + return NULL; + } + memset(dseg->blk_ptr, 0, blk_ptr_size); + /* Allocate minimum number of blocks */ + if (_alloc_dma_blocks(dseg, dseg->req_size / dseg->blk_size) != 0) { + gprintk("Failed to allocate minimum number of DMA blocks\n"); + /* + * _alloc_dma_blocks() returns -1 if it fails to allocate the requested + * number of blocks, but it may still have allocated something. Fall + * through and return dseg filled in with as much memory as we could + * allocate. + */ + } + /* Allocate more blocks until we have a complete segment */ + do { + _find_largest_segment(dseg); + if (dseg->seg_size >= dseg->req_size) { + break; + } + } while (_alloc_dma_blocks(dseg, 8) == 0); + /* Reserve all pages in the DMA segment and free unused blocks */ + for (i = 0; i < dseg->blk_cnt; i++) { + if ((dseg->blk_ptr[i] & 3) == 2) { + dseg->blk_ptr[i] &= ~3; + for (page_addr = dseg->blk_ptr[i]; + page_addr < dseg->blk_ptr[i] + dseg->blk_size; + page_addr += PAGE_SIZE) { + MEM_MAP_RESERVE(VIRT_TO_PAGE(page_addr)); + } + } else if (dseg->blk_ptr[i]) { + dseg->blk_ptr[i] &= ~3; + free_pages(dseg->blk_ptr[i], dseg->blk_order); + dseg->blk_ptr[i] = 0; + } + } + return dseg; +} + +/* + * Function: _dma_segment_free + * + * Purpose: + * Release resources used by DMA segment. + * Parameters: + * dseg - DMA segment descriptor + * Returns: + * Nothing. + */ +static void +_dma_segment_free(dma_segment_t *dseg) +{ + int i; + unsigned long page_addr; + + if (dseg->blk_ptr) { + for (i = 0; i < dseg->blk_cnt; i++) { + if (dseg->blk_ptr[i]) { + for (page_addr = dseg->blk_ptr[i]; + page_addr < dseg->blk_ptr[i] + dseg->blk_size; + page_addr += PAGE_SIZE) { + MEM_MAP_UNRESERVE(VIRT_TO_PAGE(page_addr)); + } + free_pages(dseg->blk_ptr[i], dseg->blk_order); + } + } + kfree(dseg->blk_ptr); + kfree(dseg); + } +} + +/* + * Function: _pgalloc + * + * Purpose: + * Allocate DMA memory using page allocator + * Parameters: + * size - number of bytes to allocate + * Returns: + * Pointer to allocated DMA memory or NULL if failure. + * Notes: + * For any sizes less than DMA_BLOCK_SIZE, we ask the page + * allocator for the entire memory block, otherwise we try + * to assemble a contiguous segment ourselves. + */ +static void * +_pgalloc(size_t size) +{ + dma_segment_t *dseg; + size_t blk_size; + + blk_size = (size < DMA_BLOCK_SIZE) ? size : DMA_BLOCK_SIZE; + if ((dseg = _dma_segment_alloc(size, blk_size)) == NULL) { + return NULL; + } + if (dseg->seg_size < size) { + /* If we didn't get the full size then forget it */ + gprintk("_pgalloc() failed to get requested size %zu: " + "only got %lu contiguous across %d blocks\n", + size, dseg->seg_size, dseg->blk_cnt); + _dma_segment_free(dseg); + return NULL; + } + list_add(&dseg->list, &_dma_seg); + return (void *)dseg->seg_begin; +} + +/* + * Function: _pgfree + * + * Purpose: + * Free memory allocated by _pgalloc + * Parameters: + * ptr - pointer returned by _pgalloc + * Returns: + * 0 if succesfully freed, otherwise -1. + */ +static int +_pgfree(void *ptr) +{ + struct list_head *pos; + list_for_each(pos, &_dma_seg) { + dma_segment_t *dseg = list_entry(pos, dma_segment_t, list); + if (ptr == (void *)dseg->seg_begin) { + list_del(&dseg->list); + _dma_segment_free(dseg); + return 0; + } + } + return -1; +} + +/* + * Function: _pgcleanup + * + * Purpose: + * Free all memory allocated by _pgalloc + * Parameters: + * None + * Returns: + * Nothing. + */ +static void +_pgcleanup(void) +{ + switch (dmaalloc) { +#if _SIMPLE_MEMORY_ALLOCATION_ + case ALLOC_TYPE_API: + if (_dma_vbase) { + if (dma_debug >= 1) gprintk("freeing v=%p p=0x%lx size=0x%lx\n", _dma_vbase,(unsigned long) _dma_pbase, (unsigned long)_dma_mem_size); + dma_free_coherent(DMA_DEV(0), _dma_mem_size, _dma_vbase, _dma_pbase); + } + break; +#endif /* _SIMPLE_MEMORY_ALLOCATION_ */ + + case ALLOC_TYPE_CHUNK: { + struct list_head *pos, *tmp; + int i, ndevices; + if (_use_dma_mapping) { + ndevices = BDE_NUM_DEVICES(BDE_ALL_DEVICES); + for (i = 0; i < ndevices && DMA_DEV(i); i ++) { + dma_unmap_single(DMA_DEV(i), (dma_addr_t)_dma_pbase, _dma_mem_size, DMA_BIDIRECTIONAL); + } + _use_dma_mapping = 0; + } + list_for_each_safe(pos, tmp, &_dma_seg) { + dma_segment_t *dseg = list_entry(pos, dma_segment_t, list); + list_del(&dseg->list); + _dma_segment_free(dseg); + } + break; + } + + default: + gprintk("DMA memory allocation method dmaalloc=%d is not supported\n", dmaalloc); + } +} + +/* + * Function: _alloc_mpool + * + * Purpose: + * Allocate DMA memory pool + * Parameters: + * size - size of DMA memory pool + * Returns: + * Nothing. + * Notes: + * If set up to use high memory, we simply map the memory into + * kernel space. + * It is assumed there is only one pool. + */ +static void +_alloc_mpool(size_t size) +{ + unsigned long pbase = 0; + +#if defined(__arm__) && !defined(CONFIG_HIGHMEM) + if (_use_himem) { + gprintk("DMA in high memory requires CONFIG_HIGHMEM on ARM CPUs.\n"); + return; + } +#endif + + if (_use_himem) { + /* Use high memory for DMA */ + if (_himemaddr) { + pbase = _himemaddr; + } else { + pbase = virt_to_bus(high_memory); + } + if (((pbase + (size - 1)) >> 16) > DMA_BIT_MASK(16)) { + gprintk("DMA in high memory at 0x%lx size 0x%lx is beyond the 4GB limit and not supported.\n", pbase, (unsigned long)size); + return; + } + _cpu_pbase = _dma_pbase = pbase; + _dma_vbase = IOREMAP(_dma_pbase, size); + } else { + /* Get DMA memory from kernel */ + switch (dmaalloc) { +#if _SIMPLE_MEMORY_ALLOCATION_ + case ALLOC_TYPE_API: { + size_t alloc_size = size; /* size of memory allocated in current iteration */ + if (alloc_size > DMA_MAX_ALLOC_SIZE) { + alloc_size = DMA_MAX_ALLOC_SIZE; + } + /* get a memory allocation from the kernel */ + { + dma_addr_t dma_handle; + if (!(_dma_vbase = dma_alloc_coherent(DMA_DEV(0), alloc_size, &dma_handle, GFP_KERNEL)) || !dma_handle) { + gprintk("failed to allocate the memory pool of size 0x%lx\n", (unsigned long)alloc_size); + return; + } + _cpu_pbase = pbase = dma_handle; + } + + if (alloc_size != size) { + gprintk("allocated 0x%lx bytes instead of 0x%lx bytes.\n", + (unsigned long)alloc_size, (unsigned long)size); + } + size = _dma_mem_size = alloc_size; + break; + } +#endif /* _SIMPLE_MEMORY_ALLOCATION_ */ + + case ALLOC_TYPE_CHUNK: + _dma_vbase = _pgalloc(size); + if (!_dma_vbase) { + gprintk("failed to allocate the memory pool of size 0x%lx\n", (unsigned long)size); + return; + } + _cpu_pbase = virt_to_bus(_dma_vbase); + /* Use dma_map_single to obtain DMA bus address or IOVA if iommu is present. */ + if (DMA_DEV(0)) { + pbase = dma_map_single(DMA_DEV(0), _dma_vbase, size, DMA_BIDIRECTIONAL); + if (dma_mapping_error(DMA_DEV(0), pbase)) { + gprintk("Failed to map memory at %p\n", _dma_vbase); + _pgcleanup(); + _dma_vbase = NULL; + _cpu_pbase = 0; + return; + } + _use_dma_mapping = 1; + } else { + /* Device has not been probed. */ + pbase = _cpu_pbase; + } + break; + default: + _dma_vbase = NULL; + gprintk("DMA memory allocation method dmaalloc=%d is not supported\n", dmaalloc); + return; + } + + if (((pbase + (size - 1)) >> 16) > DMA_BIT_MASK(16)) { + gprintk("DMA memory allocated at 0x%lx size 0x%lx is beyond the 4GB limit and not supported.\n", pbase, (unsigned long)size); + _pgcleanup(); + _dma_vbase = NULL; + _dma_pbase = 0; + return; + } + + _dma_pbase = pbase; +#ifdef REMAP_DMA_NONCACHED + _dma_vbase = IOREMAP(_dma_pbase, size); +#endif + if (dma_debug >= 1) { + gprintk("_use_dma_mapping:%d _dma_vbase:%p _dma_pbase:%lx _cpu_pbase:%lx allocated:%lx dmaalloc:%d\n", + _use_dma_mapping, _dma_vbase, (unsigned long)_dma_pbase, + (unsigned long)_cpu_pbase, (unsigned long)size, dmaalloc); + } + } +} + +/* + * Function: _dma_cleanup + * + * Purpose: + * DMA cleanup function. + * Parameters: + * None + * Returns: + * Always 0 + */ +int +_dma_cleanup(void) +{ + if (_dma_vbase) { + mpool_destroy(_dma_pool); + if (_use_himem) { + iounmap(_dma_vbase); + } else { +#ifdef REMAP_DMA_NONCACHED + iounmap(_dma_vbase); +#endif + _pgcleanup(); + } + _dma_vbase = NULL; + _dma_pbase = 0; + _cpu_pbase = 0; + } + return 0; +} + +void _dma_init(int robo_switch, int dev_index) +{ + unsigned long pbase; + + if (dev_index > 0) { + if ((_use_dma_mapping == 1) && DMA_DEV(dev_index) && _dma_vbase) { + pbase = dma_map_single(DMA_DEV(dev_index), _dma_vbase, _dma_mem_size, DMA_BIDIRECTIONAL); + if (dma_mapping_error(DMA_DEV(dev_index), pbase)) { + gprintk("Failed to map memory for device %d at %p\n", dev_index, _dma_vbase); + } + } + return; + } + + /* DMA Setup */ + if (dmasize) { + if ((dmasize[strlen(dmasize)-1] & ~0x20) == 'M') { + _dma_mem_size = simple_strtoul(dmasize, NULL, 0); + _dma_mem_size *= ONE_MB; + } else { + gprintk("DMA memory size must be specified as e.g. dmasize=8M\n"); + } + if (_dma_mem_size & (_dma_mem_size-1)) { + gprintk("dmasize must be a power of 2 (1M, 2M, 4M, 8M etc.)\n"); + _dma_mem_size = 0; + } + } else { + if(robo_switch){ + _dma_mem_size = DMA_MEM_DEFAULT_ROBO; + } + } + + if (himem) { + if ((himem[0] & ~0x20) == 'Y' || himem[0] == '1') { + _use_himem = 1; + } else if ((himem[0] & ~0x20) == 'N' || himem[0] == '0') { + _use_himem = 0; + } + } + + if (himemaddr && strlen(himemaddr) > 0) { + char suffix = (himemaddr[strlen(himemaddr)-1] & ~0x20); + _himemaddr = simple_strtoul(himemaddr, NULL, 0); + if (suffix == 'M') { + _himemaddr *= ONE_MB; + } else if (suffix == 'G') { + _himemaddr *= ONE_GB; + } else { + gprintk("DMA high memory address must be specified as e.g. himemaddr=8[MG]\n"); + } + } + + if (_dma_mem_size) { + _alloc_mpool(_dma_mem_size); + if (_dma_vbase == NULL) { + gprintk("no DMA memory available\n"); + } + else { + mpool_init(); + _dma_pool = mpool_create(_dma_vbase, _dma_mem_size); + } + } +} + +#if USE_LINUX_BDE_MMAP +/* + * Function: _dma_range_valid + * + * Purpose: + * Check if DMA address range is valid. + * Parameters: + * phys_addr - start physical address + * size - range size + * Returns: + * 0 : not valid + * 1 : valid + */ +int +_dma_range_valid(unsigned long phys_addr, unsigned long size) +{ + unsigned long pool_start = _cpu_pbase; + unsigned long pool_end = pool_start + _dma_mem_size; + + if (phys_addr < pool_start || (phys_addr + size) > pool_end) { + gprintk("range 0x%lx-0x%lx outside DMA pool 0x%lx-0x%lx\n", + phys_addr, phys_addr + size, pool_start, pool_end); + return 0; + } + return 1; +} +#endif + +/* + * Function: _dma_pool_allocated + * + * Purpose: + * Check if DMA pool has been allocated. + * Parameters: + * None + * Returns: + * 0 : not allocated + * 1 : allocated + */ +int +_dma_pool_allocated(void) +{ + return (_dma_vbase) ? 1 : 0; +} + +sal_paddr_t +_l2p(int d, void *vaddr) +{ + if (_dma_mem_size) { + /* dma memory is a contiguous block */ + if (vaddr) { + return _dma_pbase + (PTR_TO_UINTPTR(vaddr) - PTR_TO_UINTPTR(_dma_vbase)); + } + return 0; + } + return ((sal_paddr_t)virt_to_bus(vaddr)); +} + +void * +_p2l(int d, sal_paddr_t paddr) +{ + sal_vaddr_t vaddr = (sal_vaddr_t)_dma_vbase; + + if (_dma_mem_size) { + /* DMA memory is a contiguous block */ + if (paddr == 0) { + return NULL; + } + return (void *)(vaddr + (sal_vaddr_t)(paddr - _dma_pbase)); + } + return bus_to_virt(paddr); +} + +/* + * Some of the driver malloc's are too large for + * kmalloc(), so 'sal_alloc' and 'sal_free' in the + * linux kernel sal cannot be implemented with kmalloc(). + * + * Instead, they expect someone to provide an allocator + * that can handle the gimongous size of some of the + * allocations, and we provide it here, by allocating + * this memory out of the boot-time dma pool. + * + * These are the functions in question: + */ + +void* kmalloc_giant(int sz) +{ + return mpool_alloc(_dma_pool, sz); +} + +void kfree_giant(void* ptr) +{ + return mpool_free(_dma_pool, ptr); +} + +uint32_t * +_salloc(int d, int size, const char *name) +{ + void *ptr; + + if (_dma_mem_size) { + return mpool_alloc(_dma_pool, size); + } + if ((ptr = kmalloc(size, mem_flags)) == NULL) { + ptr = _pgalloc(size); + } + return ptr; +} + +void +_sfree(int d, void *ptr) +{ + if (_dma_mem_size) { + return mpool_free(_dma_pool, ptr); + } + if (_pgfree(ptr) < 0) { + kfree(ptr); + } +} + +int +_sinval(int d, void *ptr, int length) +{ +#if defined(dma_cache_wback_inv) + dma_cache_wback_inv((unsigned long)ptr, length); +#else +#if defined(IPROC_CMICD) || defined(BCM958525) + /* FIXME: need proper function to replace dma_cache_sync */ + dma_sync_single_for_cpu(NULL, (unsigned long)ptr, length, DMA_BIDIRECTIONAL); +#else + dma_cache_sync(NULL, ptr, length, DMA_BIDIRECTIONAL); +#endif +#endif + return 0; +} + +int +_sflush(int d, void *ptr, int length) +{ +#if defined(dma_cache_wback_inv) + dma_cache_wback_inv((unsigned long)ptr, length); +#else +#if defined(IPROC_CMICD) || defined(BCM958525) + /* FIXME: need proper function to replace dma_cache_sync */ + dma_sync_single_for_cpu(NULL, (unsigned long)ptr, length, DMA_BIDIRECTIONAL); +#else + dma_cache_sync(NULL, ptr, length, DMA_BIDIRECTIONAL); +#endif +#endif + + return 0; +} + +int +lkbde_get_dma_info(phys_addr_t* cpu_pbase, phys_addr_t* dma_pbase, ssize_t* size) +{ + if (_dma_vbase == NULL) { + if (_dma_mem_size == 0) { + _dma_mem_size = DMA_MEM_DEFAULT; + } + _alloc_mpool(_dma_mem_size); + } + *cpu_pbase = _cpu_pbase; + *dma_pbase = _dma_pbase; + *size = (_dma_vbase) ? _dma_mem_size : 0; + return 0; +} + +void +_dma_pprint(void) +{ + pprintf("DMA Memory (%s): %d bytes, %d used, %d free%s\n", + (_use_himem) ? "high" : "kernel", + (_dma_vbase) ? _dma_mem_size : 0, + (_dma_vbase) ? mpool_usage(_dma_pool) : 0, + (_dma_vbase) ? _dma_mem_size - mpool_usage(_dma_pool) : 0, + USE_LINUX_BDE_MMAP ? ", local mmap" : ""); +} + +/* + * Export functions + */ +LKM_EXPORT_SYM(kmalloc_giant); +LKM_EXPORT_SYM(kfree_giant); +LKM_EXPORT_SYM(lkbde_get_dma_info); diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.c b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.c new file mode 100644 index 000000000000..a2d58858a5a5 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.c @@ -0,0 +1,120 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#include +#include +#include +#include "linux_shbde.h" + +/* Hardware abstractions for shared BDE functions */ + +static unsigned short +linux_pcic16_read(void *pci_dev, unsigned int addr) +{ + u16 data = 0; + + pci_read_config_word((struct pci_dev *)pci_dev, addr, &data); + + return data; +} + +static void +linux_pcic16_write(void *pci_dev, unsigned int addr, unsigned short data) +{ + pci_write_config_word((struct pci_dev *)pci_dev, addr, (u16)data); +} + +static unsigned int +linux_pcic32_read(void *pci_dev, unsigned int addr) +{ + u32 data = 0; + + pci_read_config_dword((struct pci_dev *)pci_dev, addr, &data); + + return data; +} + +static void +linux_pcic32_write(void *pci_dev, unsigned int addr, unsigned int data) +{ + pci_write_config_dword((struct pci_dev *)pci_dev, addr, (u32)data); +} + +static unsigned int +linux_io32_read(void *addr) +{ + return *((volatile u32 *)addr); +} + +static void +linux_io32_write(void *addr, unsigned int data) +{ + *((volatile u32 *)addr) = data; +} + +static void +linux_usleep(int usec) +{ + udelay(usec); +} + + +/* To get the PCI parent device under linux, from only the device pointer */ +static void * +linux_pci_parent_device_get(void *pci_dev) +{ + return (void *)(((struct pci_dev *)pci_dev)->bus->self); +} + + +/* + * Function: + * linux_shbde_hal_init + * Purpose: + * Initialize hardware abstraction module for Linux kernel. + * Parameters: + * shbde - pointer to uninitialized hardware abstraction module + * log_func - optional log output function + * Returns: + * Always 0 + */ +int +linux_shbde_hal_init(shbde_hal_t *shbde, shbde_log_func_t log_func) +{ + memset(shbde, 0, sizeof(*shbde)); + + shbde->log_func = log_func; + + shbde->pcic16_read = linux_pcic16_read; + shbde->pcic16_write = linux_pcic16_write; + shbde->pcic32_read = linux_pcic32_read; + shbde->pcic32_write = linux_pcic32_write; + + shbde->io32_read = linux_io32_read; + shbde->io32_write = linux_io32_write; + + shbde->usleep = linux_usleep; + + shbde->pci_parent_device_get = linux_pci_parent_device_get; + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.h b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.h new file mode 100644 index 000000000000..5e8a70119e85 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.h @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#ifndef __LINUX_SHBDE_H__ +#define __LINUX_SHBDE_H__ + +#include +#include +#include + +extern int +linux_shbde_hal_init(shbde_hal_t *shbde, shbde_log_func_t log_func); + +#endif /* __LINUX_SHBDE_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c b/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c new file mode 100644 index 000000000000..7a377cd00787 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c @@ -0,0 +1,294 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: mpool.c,v 1.18 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#include + +#ifdef __KERNEL__ + +/* + * Abstractions used when compiling for Linux kernel mode. + */ + +#include + +/* + * We cannot use the linux kernel SAL for MALLOC/FREE because + * the current implementation of sal_alloc() allocates memory + * out of an mpool created by this module... + */ +#define MALLOC(x) kmalloc(x, GFP_ATOMIC) +#define FREE(x) kfree(x) + +static spinlock_t _mpool_lock; +#define MPOOL_LOCK_INIT() spin_lock_init(&_mpool_lock) +#define MPOOL_LOCK() unsigned long flags; spin_lock_irqsave(&_mpool_lock, flags) +#define MPOOL_UNLOCK() spin_unlock_irqrestore(&_mpool_lock, flags) + +#else /* !__KERNEL__*/ + +/* + * Abstractions used when compiling for Linux user mode. + */ + +#include +#include + +#define MALLOC(x) malloc(x) +#define FREE(x) free(x) + +static sal_sem_t _mpool_lock; +#define MPOOL_LOCK_INIT() _mpool_lock = sal_sem_create("mpool_lock", 1, 1) +#define MPOOL_LOCK() sal_sem_take(_mpool_lock, sal_sem_FOREVER) +#define MPOOL_UNLOCK() sal_sem_give(_mpool_lock) + +#endif /* __KERNEL__ */ + +/* Allow external override for system cache line size */ +#ifndef BCM_CACHE_LINE_BYTES +#ifdef L1_CACHE_BYTES +#define BCM_CACHE_LINE_BYTES L1_CACHE_BYTES +#else +#define BCM_CACHE_LINE_BYTES 128 /* Should be fine on most platforms */ +#endif +#endif + +typedef struct mpool_mem_s { + unsigned char *address; + int size; + struct mpool_mem_s *next; +} mpool_mem_t; + +/* + * Function: mpool_init + * + * Purpose: + * Initialize mpool lock. + * Parameters: + * None + * Returns: + * Always 0 + */ +int +mpool_init(void) +{ + MPOOL_LOCK_INIT(); + return 0; +} + +#ifdef TRACK_DMA_USAGE +static int _dma_mem_used = 0; +#endif + +/* + * Function: mpool_alloc + * + * Purpose: + * Allocate memory block from mpool. + * Parameters: + * pool - mpool handle (from mpool_create) + * size - size of memory block to allocate + * Returns: + * Pointer to allocated memory block or NULL if allocation fails. + */ +void * +mpool_alloc(mpool_handle_t pool, int size) +{ + mpool_mem_t *ptr = pool, *newptr = NULL; + int mod; + + MPOOL_LOCK(); + + mod = size & (BCM_CACHE_LINE_BYTES - 1); + if (mod != 0 ) { + size += (BCM_CACHE_LINE_BYTES - mod); + } + while (ptr && ptr->next) { + if (ptr->next->address - (ptr->address + ptr->size) >= size) { + break; + } + ptr = ptr->next; + } + + if (!(ptr && ptr->next)) { + MPOOL_UNLOCK(); + return NULL; + } + newptr = MALLOC(sizeof(mpool_mem_t)); + if (!newptr) { + MPOOL_UNLOCK(); + return NULL; + } + + newptr->address = ptr->address + ptr->size; + newptr->size = size; + newptr->next = ptr->next; + ptr->next = newptr; +#ifdef TRACK_DMA_USAGE + _dma_mem_used += size; +#endif + MPOOL_UNLOCK(); + + return newptr->address; +} + + +/* + * Function: mpool_free + * + * Purpose: + * Free memory block allocated from mpool.. + * Parameters: + * pool - mpool handle (from mpool_create) + * addr - address of memory block to free + * Returns: + * Nothing + */ +void +mpool_free(mpool_handle_t pool, void *addr) +{ + unsigned char *address = (unsigned char *)addr; + mpool_mem_t *ptr = pool, *prev = NULL; + + MPOOL_LOCK(); + + while (ptr && ptr->next) { + if (ptr->next->address == address) { +#ifdef TRACK_DMA_USAGE + _dma_mem_used -= ptr->next->size; +#endif + break; + } + ptr = ptr->next; + } + + if (ptr && ptr->next) { + prev = ptr; + ptr = ptr->next; + prev->next = ptr->next; + FREE(ptr); + } + + MPOOL_UNLOCK(); +} + +/* + * Function: mpool_create + * + * Purpose: + * Create and initialize mpool control structures. + * Parameters: + * base_ptr - pointer to mpool memory block + * size - total size of mpool memory block + * Returns: + * mpool handle + * Notes + * The mpool handle returned must be used for subsequent + * memory allocations from the mpool. + */ +mpool_handle_t +mpool_create(void *base_ptr, int size) +{ + mpool_mem_t *head, *tail; + int mod = (int)(((unsigned long)base_ptr) & (BCM_CACHE_LINE_BYTES - 1)); + + MPOOL_LOCK(); + + if (mod) { + base_ptr = (char*)base_ptr + (BCM_CACHE_LINE_BYTES - mod); + size -= (BCM_CACHE_LINE_BYTES - mod); + } + size &= ~(BCM_CACHE_LINE_BYTES - 1); + + + head = (mpool_mem_t *)MALLOC(sizeof(mpool_mem_t)); + if (head == NULL) { + return NULL; + } + tail = (mpool_mem_t *)MALLOC(sizeof(mpool_mem_t)); + if (tail == NULL) { + FREE(head); + return NULL; + } + + head->size = tail->size = 0; + head->address = base_ptr; + tail->address = head->address + size; + head->next = tail; + tail->next = NULL; + + MPOOL_UNLOCK(); + + return head; +} + +/* + * Function: mpool_destroy + * + * Purpose: + * Free mpool control structures. + * Parameters: + * pool - mpool handle (from mpool_create) + * Returns: + * Always 0 + */ +int +mpool_destroy(mpool_handle_t pool) +{ + mpool_mem_t *ptr, *next; + + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = next) { + next = ptr->next; + FREE(ptr); + } + + MPOOL_UNLOCK(); + + return 0; +} + +/* + * Function: mpool_usage + * + * Purpose: + * Report total sum of allocated mpool memory. + * Parameters: + * pool - mpool handle (from mpool_create) + * Returns: + * Number of bytes currently allocated using mpool_alloc. + */ +int +mpool_usage(mpool_handle_t pool) +{ + int usage = 0; + mpool_mem_t *ptr; + + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = ptr->next) { + usage += ptr->size; + } + + MPOOL_UNLOCK(); + + return usage; +} diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/Makefile b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/Makefile new file mode 100644 index 000000000000..424f2fe24bee --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/Makefile @@ -0,0 +1,70 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.1 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +LOCALDIR = systems/bde/linux/user/kernel + +# Make sure we build for the kernel if this is a user-mode build +ifneq ($(platform), ) +override-target=linux-$(platform) +endif + +include $(SDK)/make/Make.config + +LIBS = $(LIBDIR)/libkern.a + +ifneq ($(kernel_version),2_4) +KERNEL_MODULE_DIR = kernel_module + +THIS_MOD_NAME := linux-user-bde +MODULE = $(LIBDIR)/$(THIS_MOD_NAME).o +KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko + +build: kernel_libs $(MODULE) $(KMODULE) +else +MODULE = $(LIBDIR)/linux-user-bde.o + +build: kernel_libs $(MODULE) +endif + +KBUILD_EXTRA_SYMBOLS := ${BLDDIR}/../../kernel/kernel_module/Module.symvers + +$(MODULE): $(BLDDIR)/.tree $(BOBJS) $(LIBS) + $(LD) $(MODULE_LDFLAGS) -r -d $(BOBJS) $(LIBS) -o $@ +ifneq ($(kernel_version),2_4) +$(KMODULE): $(MODULE) + rm -fr $(BLDDIR)/$(KERNEL_MODULE_DIR) + mkdir $(BLDDIR)/$(KERNEL_MODULE_DIR) + cp ${SDK}/make/Makefile.linux-kmodule $(BLDDIR)/$(KERNEL_MODULE_DIR)/Makefile + cat ${KBUILD_EXTRA_SYMBOLS} > $(BLDDIR)/$(KERNEL_MODULE_DIR)/Module.symvers + MOD_NAME=$(THIS_MOD_NAME) $(MAKE) -C $(BLDDIR)/$(KERNEL_MODULE_DIR) $(THIS_MOD_NAME).ko +endif + +kernel_libs: + $(MAKE) -C $(SDK)/systems/linux/kernel/modules/shared + +include $(SDK)/make/Make.depend + +# Make.depend is before clean:: so that Make.depend's clean:: runs first. + +clean:: + $(MAKE) -C $(SDK)/systems/linux/kernel/modules/shared $@ + $(RM) $(BOBJS) $(MODULE) + +.PHONY: build kernel_libs diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c new file mode 100644 index 000000000000..7fc9fd166bbd --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c @@ -0,0 +1,1446 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: linux-user-bde.c,v 1.80 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + * + * Linux User BDE Helper Module + */ +#include +#include +#include + +#include +#include +#include + +#include "linux-user-bde.h" + +#ifdef KEYSTONE +#include +#endif + + +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("User BDE Helper Module"); +MODULE_LICENSE("GPL"); + +/* CMIC/CMICe defines */ +#define CMIC_IRQ_STAT 0x00000144 +#define CMIC_IRQ_MASK 0x00000148 +#define CMIC_IRQ_MASK_1 0x0000006C +#define CMIC_IRQ_MASK_2 0x00000070 + +/* CMICm defines */ +#define CMIC_CMCx_IRQ_STAT0_OFFSET(x) (0x31400 + (0x1000 * x)) +#define CMIC_CMCx_IRQ_STAT1_OFFSET(x) (0x31404 + (0x1000 * x)) +#define CMIC_CMCx_IRQ_STAT2_OFFSET(x) (0x31408 + (0x1000 * x)) +#define CMIC_CMCx_IRQ_STAT3_OFFSET(x) (0x3140c + (0x1000 * x)) +#define CMIC_CMCx_IRQ_STAT4_OFFSET(x) (0x31410 + (0x1000 * x)) + +#define CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(x) (0x31414 + (0x1000 * x)) +#define CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(x) (0x31418 + (0x1000 * x)) +#define CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(x) (0x3141c + (0x1000 * x)) +#define CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(x) (0x31420 + (0x1000 * x)) +#define CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(x) (0x31424 + (0x1000 * x)) + +/* CMICd defines */ +#define CMIC_CMCx_IRQ_STAT5_OFFSET(x) (0x314b0 + (0x1000 * x)) +#define CMIC_CMCx_IRQ_STAT6_OFFSET(x) (0x314b4 + (0x1000 * x)) +#define CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(x) (0x314b8 + (0x1000 * x)) +#define CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(x) (0x314bc + (0x1000 * x)) +#define CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(x) (0x314c0 + (0x1000 * x)) +#define CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(x) (0x314c4 + (0x1000 * x)) + +#define CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(x) (0x31428 + (0x1000 * x)) +#define CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(x) (0x3142c + (0x1000 * x)) +#define CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(x) (0x31430 + (0x1000 * x)) +#define CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(x) (0x31434 + (0x1000 * x)) +#define CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(x) (0x31438 + (0x1000 * x)) + +/* CMICX defines */ +#define INTC_INTR_REG_NUM (8) + +#define INTC_INTR_ENABLE_REG0 (0x180130f0) +#define INTC_INTR_STATUS_REG0 (0x18013190) +#define INTC_INTR_RAW_STATUS_REG0 (0x18013140) + +#define INTC_INTR_ENABLE_BASE (INTC_INTR_ENABLE_REG0) +#define INTC_INTR_STATUS_BASE (INTC_INTR_STATUS_REG0) +#define INTC_INTR_RAW_STATUS_BASE (INTC_INTR_RAW_STATUS_REG0) + +#define INTC_PDMA_INTR_REG_IND 4 + +#define READ_INTC_INTR(d, reg, v) \ + (v = user_bde->iproc_read(d, reg)) +#define WRITE_INTC_INTR(d, reg, v) \ + (user_bde->iproc_write(d, reg, v)) + +/* Allow override of default CMICm CMC */ +#ifndef BDE_CMICM_PCIE_CMC +#define BDE_CMICM_PCIE_CMC 0 +#endif + +/* Allow override of default CMICm CMC */ +#ifndef BDE_CMICD_PCIE_CMC +#define BDE_CMICD_PCIE_CMC 0 +#endif + +/* Defines used to distinguish CMICe from CMICm */ +#define CMICE_DEV_REV_ID (0x178 / sizeof(uint32)) + +static ibde_t *user_bde = NULL; + +typedef void (*isr_f)(void *); + +typedef struct bde_ctrl_s { + uint32 dev_type; + int irq; + int enabled; + int devid; + isr_f isr; + uint32 *ba; + int inst; /* associate to _bde_inst_resource[] */ +} bde_ctrl_t; + +#define VALID_DEVICE(_n) (_n < LINUX_BDE_MAX_DEVICES) + +static bde_ctrl_t _devices[LINUX_BDE_MAX_DEVICES]; + +static wait_queue_head_t _ether_interrupt_wq; +static atomic_t _ether_interrupt_has_taken_place = ATOMIC_INIT(0); + +/* + * Multiple instance resource data structure. + * To keep the DMA resource per instance. + * And track the DMA pool usage. + */ +static int _bde_multi_inst = 0; + +typedef struct { + unsigned int inst_id; + unsigned int dma_offset; + unsigned int dma_size; + wait_queue_head_t intr_wq; + atomic_t intr; +} bde_inst_resource_t; + +static bde_inst_resource_t _bde_inst_resource[LINUX_BDE_MAX_DEVICES]; + +typedef struct { + phys_addr_t cpu_pbase; /* CPU physical base address of the DMA pool */ + phys_addr_t dma_pbase; /* Bus base address of the DMA pool */ + uint32 total_size; /* Total size of the pool in MB */ + uint32 offset; /* Current offset of the pool in MB */ +}_dma_pool_t; + +static _dma_pool_t _dma_pool; + +#define ONE_MB (1024 * 1024) + +#ifdef KEYSTONE +/* + * Enforce PCIE transaction ordering. Commit the write transaction. + */ + +#define SSOC_WRITEL(val, addr) \ + do { \ + writel((val), (addr)); \ + __asm__ __volatile__("sync"); \ + } while(0) + +#else + +#define SSOC_WRITEL(val, addr) \ + writel((val), (addr)) + +#endif +/* + * Function: _interrupt + * + * Purpose: + * Interrupt Handler. + * Mask all interrupts on device and wake up interrupt + * thread. It is assumed that the interrupt thread unmasks + * interrupts again when interrupt handling is complete. + * Parameters: + * ctrl - BDE control structure for this device. + * Returns: + * Nothing + */ +static void +_cmic_interrupt(bde_ctrl_t *ctrl) +{ + int d; + uint32_t mask = 0, stat, imask = 0, fmask = 0; + bde_inst_resource_t *res; + + d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); + res = &_bde_inst_resource[ctrl->inst]; + + /* Check for secondary interrupt handler */ + if (lkbde_irq_mask_get(d, &mask, &fmask) < 0) { + fmask = 0; + } + + if (fmask != 0) { + imask = mask & ~fmask; + /* Check for pending user mode interrupts */ + stat = user_bde->read(d, CMIC_IRQ_STAT); + if ((stat & imask) == 0) { + /* All handled in kernel mode */ + lkbde_irq_mask_set(d, CMIC_IRQ_MASK, imask, 0); + return; + } + } + + lkbde_irq_mask_set(d, CMIC_IRQ_MASK, 0, 0); + + atomic_set(&res->intr, 1); + +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + +static void +_cmicx_interrupt(bde_ctrl_t *ctrl) +{ + int d, ind; + uint32 stat, iena, mask, fmask; + bde_inst_resource_t *res; + + d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); + res = &_bde_inst_resource[ctrl->inst]; + + lkbde_irq_mask_get(d, &mask, &fmask); + + if (fmask) { + READ_INTC_INTR(d, INTC_INTR_STATUS_BASE + 4 * INTC_PDMA_INTR_REG_IND, stat); + READ_INTC_INTR(d, INTC_INTR_ENABLE_BASE + 4 * INTC_PDMA_INTR_REG_IND, iena); + if (stat & iena) { + WRITE_INTC_INTR(d, INTC_INTR_ENABLE_BASE + 4 * INTC_PDMA_INTR_REG_IND, 0); + for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) { + if (ind == INTC_PDMA_INTR_REG_IND) { + continue; + } + READ_INTC_INTR(d, INTC_INTR_STATUS_BASE + 4 * ind, stat); + READ_INTC_INTR(d, INTC_INTR_ENABLE_BASE + 4 * ind, iena); + if (stat & iena) { + break; + } + } + if (ind >= INTC_INTR_REG_NUM) { + return; + } + } + } + + /* Disable all interrupts.. Re-enable unserviced interrupts later + * So as to avoid getting new interrupts until the user level driver + * enumerates the interrupts to be serviced + */ + for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) { + if (fmask && ind == INTC_PDMA_INTR_REG_IND) { + continue; + } + WRITE_INTC_INTR(d, INTC_INTR_ENABLE_BASE + 4 * ind, 0); + } + + /* Notify */ + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + +static void +_cmicm_interrupt(bde_ctrl_t *ctrl) +{ + int d; + int cmc = BDE_CMICM_PCIE_CMC; + uint32 stat, mask = 0, fmask = 0, imask = 0; + bde_inst_resource_t *res; + + d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); + res = &_bde_inst_resource[ctrl->inst]; + + lkbde_irq_mask_get(d, &mask, &fmask); + + while (fmask) { + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); + imask = mask & ~fmask; + if (stat & imask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + return; + } + + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + lkbde_irq_mask_set(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(cmc), 0, 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(1), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(2), 0); + } + else { + lkbde_irq_mask_set(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), 0, 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(1), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(2), 0); + } + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + +/* some device has cmc0 only */ +static void +_cmicd_cmc0_interrupt(bde_ctrl_t *ctrl) +{ + int d; + int cmc = 0; + uint32 stat, mask = 0, fmask = 0, imask = 0; + bde_inst_resource_t *res; + + d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); + res = &_bde_inst_resource[ctrl->inst]; + lkbde_irq_mask_get(d, &mask, &fmask); + + while (fmask) { + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); + imask = mask & ~fmask; + if (stat & imask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT5_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT6_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + return; + } + + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + lkbde_irq_mask_set(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(cmc), 0, 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc), 0); + } else { + lkbde_irq_mask_set(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), 0, 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc), 0); + } + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + +static void +_cmicd_interrupt(bde_ctrl_t *ctrl) +{ + int d; + int cmc = BDE_CMICD_PCIE_CMC; + uint32 stat, mask = 0, fmask = 0, imask = 0; + bde_inst_resource_t *res; + + d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); + res = &_bde_inst_resource[ctrl->inst]; + lkbde_irq_mask_get(d, &mask, &fmask); + + while (fmask) { + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); + imask = mask & ~fmask; + if (stat & imask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT5_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT6_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + return; + } + + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + lkbde_irq_mask_set(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(cmc), 0, 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(1), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(2), 0); + } else { + lkbde_irq_mask_set(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), 0, 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(1), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(2), 0); + } + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + +static void +_bcm88750_interrupt(bde_ctrl_t *ctrl) +{ + int d; + bde_inst_resource_t *res; + + d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); + res = &_bde_inst_resource[ctrl->inst]; + lkbde_irq_mask_set(d, CMIC_IRQ_MASK, 0, 0); + + lkbde_irq_mask_set(d, CMIC_IRQ_MASK_1, 0, 0); + lkbde_irq_mask_set(d, CMIC_IRQ_MASK_2, 0, 0); + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + +static void +_qe2k_interrupt(bde_ctrl_t *ctrl) +{ + bde_inst_resource_t *res; + + res = &_bde_inst_resource[ctrl->inst]; + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x20/sizeof(uint32)); + + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + +static void +_fe2k_interrupt(bde_ctrl_t *ctrl) +{ + bde_inst_resource_t *res; + + res = &_bde_inst_resource[ctrl->inst]; + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x18/sizeof(uint32)); /* PC_INTERRUPT_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x24/sizeof(uint32)); /* PC_ERROR0_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x2c/sizeof(uint32)); /* PC_ERROR1_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x34/sizeof(uint32)); /* PC_UNIT_MASK */ + + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + +static void +_fe2kxt_interrupt(bde_ctrl_t *ctrl) +{ + bde_inst_resource_t *res; + + res = &_bde_inst_resource[ctrl->inst]; + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x2c/sizeof(uint32)); /* PC_INTERRUPT_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x38/sizeof(uint32)); /* PC_ERROR0_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x40/sizeof(uint32)); /* PC_ERROR1_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x50/sizeof(uint32)); /* PC_UNIT_MASK */ + + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + +static void +_bme3200_interrupt(bde_ctrl_t *ctrl) +{ + bde_inst_resource_t *res; + + res = &_bde_inst_resource[ctrl->inst]; + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x54/sizeof(uint32)); /* PI_PT_ERROR0 */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x5c/sizeof(uint32)); /* PI_PT_ERROR1 */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x64/sizeof(uint32)); /* PI_PT_ERROR2 */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x6c/sizeof(uint32)); /* PI_PT_ERROR3 */ + + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + + +static void +_bm9600_interrupt(bde_ctrl_t *ctrl) +{ + bde_inst_resource_t *res; + + res = &_bde_inst_resource[ctrl->inst]; + + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x5c/sizeof(uint32)); /* PI_INTERRUPT_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0xc/sizeof(uint32)); /* PI_UNIT_INTERRUPT0_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x14/sizeof(uint32)); /* PI_UNIT_INTERRUPT1_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x1c/sizeof(uint32)); /* PI_UNIT_INTERRUPT2_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x24/sizeof(uint32)); /* PI_UNIT_INTERRUPT3_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x2c/sizeof(uint32)); /* PI_UNIT_INTERRUPT4_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x34/sizeof(uint32)); /* PI_UNIT_INTERRUPT5_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x3c/sizeof(uint32)); /* PI_UNIT_INTERRUPT6_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x44/sizeof(uint32)); /* PI_UNIT_INTERRUPT7_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x4c/sizeof(uint32)); /* PI_UNIT_INTERRUPT8_MASK */ + SSOC_WRITEL(0xffffffff, ctrl->ba + 0x54/sizeof(uint32)); /* PI_UNIT_INTERRUPT9_MASK */ + + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + + + +/* The actual interrupt handler of ethernet devices */ +static void +_ether_interrupt(bde_ctrl_t *ctrl) +{ +#ifdef KEYSTONE + /* + * Since the two GMAC cores are sharing the same IRQ. + * Add the checking to handle the interrupt events. + */ + if ((ctrl->devid == BCM53000_GMAC_ID)) { + if ((readl(ctrl->ba + 0x020/4) & readl(ctrl->ba + 0x024/4)) == 0) { + return; + } + } +#endif + SSOC_WRITEL(0, ctrl->ba + 0x024/4); + + atomic_set(&_ether_interrupt_has_taken_place, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&_ether_interrupt_wq); +#else + wake_up_interruptible(&_ether_interrupt_wq); +#endif +} + + +static struct _intr_mode_s { + isr_f isr; + const char *name; +} _intr_mode[] = { + { (isr_f)_cmic_interrupt, "CMIC/CMICe" }, + { (isr_f)_cmicm_interrupt, "CMICm" }, + { (isr_f)_cmicd_interrupt, "CMICd" }, + { (isr_f)_cmicd_cmc0_interrupt, "CMICd CMC0" }, + { (isr_f)_qe2k_interrupt, "QE2K" }, + { (isr_f)_fe2k_interrupt, "FE2K" }, + { (isr_f)_fe2kxt_interrupt, "FE2KXT" }, + { (isr_f)_bme3200_interrupt, "BME3200" }, + { (isr_f)_bm9600_interrupt, "BM9600" }, + { (isr_f)_bcm88750_interrupt, "BCM88750" }, + { (isr_f)_cmicx_interrupt, "CMICx" }, + { NULL, NULL } +}; + +static const char * +_intr_mode_str(void *isr) +{ + int imx; + + imx = 0; + while (_intr_mode[imx].isr != NULL) { + if (isr == _intr_mode[imx].isr) { + return _intr_mode[imx].name; + } + imx++; + } + return NULL; +} + +static void +_devices_init(int d) +{ + bde_ctrl_t *ctrl; + uint32 ver; + uint16 device_id_mask = 0xFFF0; + uint16 device_id; + + ctrl = &_devices[d]; + /* Initialize our control info */ + ctrl->dev_type = user_bde->get_dev_type(d); + ctrl->devid = user_bde->get_dev(d)->device; + ctrl->inst = 0; + + if (BDE_DEV_MEM_MAPPED(ctrl->dev_type)) { + ctrl->enabled = 0; + ctrl->ba = lkbde_get_dev_virt(d); + } + if (ctrl->dev_type & BDE_SWITCH_DEV_TYPE) { + switch (user_bde->get_dev(d)->device) { + case QE2000_DEVICE_ID: + ctrl->isr = (isr_f)_qe2k_interrupt; + break; + case BCM88020_DEVICE_ID: + ctrl->isr = (isr_f)_fe2k_interrupt; + break; + case BCM88025_DEVICE_ID: + ctrl->isr = (isr_f)_fe2kxt_interrupt; + break; + case BME3200_DEVICE_ID: + ctrl->isr = (isr_f)_bme3200_interrupt; + break; + case BM9600_DEVICE_ID: + ctrl->isr = (isr_f)_bm9600_interrupt; + break; + case BCM88750_DEVICE_ID: + case BCM88753_DEVICE_ID: + case BCM88754_DEVICE_ID: + case BCM88755_DEVICE_ID: + case BCM88752_DEVICE_ID: + ctrl->isr = (isr_f)_bcm88750_interrupt; + break; + case BCM53540_DEVICE_ID: + case BCM53547_DEVICE_ID: + case BCM53548_DEVICE_ID: + case BCM53549_DEVICE_ID: + case BCM88670_DEVICE_ID: + case BCM88671_DEVICE_ID: + case BCM88671M_DEVICE_ID: + case BCM88672_DEVICE_ID: + case BCM88673_DEVICE_ID: + case BCM88674_DEVICE_ID: + case BCM88675_DEVICE_ID: + case BCM88675M_DEVICE_ID: + case BCM88676_DEVICE_ID: + case BCM88676M_DEVICE_ID: + case BCM88677_DEVICE_ID: + case BCM88678_DEVICE_ID: + case BCM88679_DEVICE_ID: + case BCM88370_DEVICE_ID: + case BCM88371_DEVICE_ID: + case BCM88371M_DEVICE_ID: + case BCM88375_DEVICE_ID: + case BCM88376_DEVICE_ID: + case BCM88376M_DEVICE_ID: + case BCM88377_DEVICE_ID: + case BCM88378_DEVICE_ID: + case BCM88379_DEVICE_ID: + case BCM88681_DEVICE_ID: + case BCM88682_DEVICE_ID: + case BCM88683_DEVICE_ID: + case BCM88684_DEVICE_ID: + case BCM88685_DEVICE_ID: + case BCM88380_DEVICE_ID: + case BCM88381_DEVICE_ID: + case BCM88680_DEVICE_ID: + case BCM88690_DEVICE_ID: + case BCM88770_DEVICE_ID: + case BCM88773_DEVICE_ID: + case BCM88774_DEVICE_ID: + case BCM88775_DEVICE_ID: + case BCM88776_DEVICE_ID: + case BCM88777_DEVICE_ID: + case BCM88470_DEVICE_ID: + case BCM88470P_DEVICE_ID: + case BCM88471_DEVICE_ID: + case BCM88473_DEVICE_ID: + case BCM88474_DEVICE_ID: + case BCM88474H_DEVICE_ID: + case BCM88476_DEVICE_ID: + case BCM88477_DEVICE_ID: + case BCM88270_DEVICE_ID: + case BCM88272_DEVICE_ID: + case BCM88273_DEVICE_ID: + case BCM88278_DEVICE_ID: + case BCM88279_DEVICE_ID: + case BCM8206_DEVICE_ID: + case BCM88950_DEVICE_ID: + case BCM88953_DEVICE_ID: + case BCM88954_DEVICE_ID: + case BCM88955_DEVICE_ID: + case BCM88956_DEVICE_ID: + case BCM88772_DEVICE_ID: + case BCM88952_DEVICE_ID: + ctrl->isr = (isr_f)_cmicd_cmc0_interrupt; + break; + default: + /* Get CMIC version */ + if (user_bde->get_cmic_ver(d, &ver) != 0) { + ver = -1; + } + device_id = ctrl->devid & device_id_mask; + /* TH/TH+/TH2 should use cmicd interrupt handler */ + if (BCM56960_DEVICE_ID == device_id || + BCM56930_DEVICE_ID == device_id || + BCM56970_DEVICE_ID == device_id) { + ctrl->isr = (isr_f)_cmicd_interrupt; + } + /* check if version is CMICX */ + else if (ver == 0x04) { + ctrl->isr = (isr_f)_cmicx_interrupt; + } else { + ctrl->isr = (isr_f)_cmic_interrupt; + if ((ctrl->dev_type & BDE_256K_REG_SPACE) && +#ifdef BCM_PETRA_SUPPORT /* FIXME remove code when hardware design is fixed */ + ctrl->devid != 0x1234 && +#endif + readl(ctrl->ba + CMICE_DEV_REV_ID) == 0) { + ctrl->isr = (isr_f)_cmicm_interrupt; + } + } + break; + } + /*All Ramon devices from 0x8790 to 0x879F*/ + if ((user_bde->get_dev(d)->device & BCM88790_DEVICE_ID) == BCM88790_DEVICE_ID) { + ctrl->isr = (isr_f)_cmicx_interrupt; + } + if (_intr_mode_str(ctrl->isr) == NULL) { + gprintk("Warning: Unknown interrupt mode\n"); + } + } +} +/* + * Function: _init + * + * Purpose: + * Module initialization. + * Attaches to kernel BDE. + * Parameters: + * None + * Returns: + * Always 0 + */ +static int +_init(void) +{ + int i; + phys_addr_t cpu_pbase, dma_pbase; + ssize_t dmasize; + bde_inst_resource_t *res; + + /* Connect to the kernel bde */ + if ((linux_bde_create(NULL, &user_bde) < 0) || user_bde == NULL) { + return -ENODEV; + } + + init_waitqueue_head(&_ether_interrupt_wq); + + lkbde_get_dma_info(&cpu_pbase, &dma_pbase, &dmasize); + + memset(&_dma_pool, 0, sizeof(_dma_pool)); + _dma_pool.cpu_pbase = cpu_pbase; + _dma_pool.dma_pbase = dma_pbase; + _dma_pool.total_size = dmasize / ONE_MB; + + memset(_devices, 0, sizeof(_devices)); + + /* Use _bde_inst_resource[0] as the default resource */ + memset(_bde_inst_resource, 0, sizeof(_bde_inst_resource)); + res = &_bde_inst_resource[0]; + res->dma_offset = 0; + res->dma_size = _dma_pool.total_size; + init_waitqueue_head(&res->intr_wq); + atomic_set(&res->intr, 0); + + for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { + res->inst_id |= (1 << i); + _devices_init(i); + } + return 0; +} + +/* + * Function: _cleanup + * + * Purpose: + * Module cleanup function. + * Parameters: + * None + * Returns: + * Always 0 + */ +static int +_cleanup(void) +{ + int i; + + if (user_bde) { + for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { + if (_devices[i].enabled && + BDE_DEV_MEM_MAPPED(_devices[i].dev_type)) { + user_bde->interrupt_disconnect(i); + } + lkbde_dev_instid_set(i, 0); + } + linux_bde_destroy(user_bde); + user_bde = NULL; + } + return 0; +} + +/* + * Function: _pprint + * + * Purpose: + * Print proc filesystem information. + * Parameters: + * None + * Returns: + * Always 0 + */ +static int +_pprint(void) +{ + int idx; + const char *name; + bde_inst_resource_t *res; + uint32 state, instid; + + pprintf("Broadcom Device Enumerator (%s)\n", LINUX_USER_BDE_NAME); + for (idx = 0; idx < user_bde->num_devices(BDE_ALL_DEVICES); idx++) { + name = _intr_mode_str(_devices[idx].isr); + if (name == NULL) { + name = "unknown"; + } + pprintf("\t%d: Interrupt mode %s ",idx, name); + (void)lkbde_dev_state_get(idx, &state); + if (state == BDE_DEV_STATE_REMOVED) { + pprintf(" Device REMOVED ! \n"); + } else { + (void)lkbde_dev_instid_get(idx, &instid); + if (instid) { + pprintf("Inst id 0x%x\n",instid); + } else { + pprintf("\n"); + } + } + } + pprintf("Instance resource \n"); + + for (idx = 0; idx < user_bde->num_devices(BDE_ALL_DEVICES); idx++) { + res = &_bde_inst_resource[idx]; + if (res->inst_id) { + pprintf("\tDev mask 0x%x : " + "DMA offset %d size %d MB\n", + res->inst_id, + res->dma_offset, + res->dma_size); + } + } + + return 0; +} + +/* + * Allocate the DMA resource from DMA pool + * Parameter : + * dma_size (IN): allocate dma_size in MB + * dma_offset (OUT): dma offset in MB + */ +static int +_dma_resource_alloc(unsigned int dma_size, unsigned int *dma_offset) +{ + uint32 left; + + left = _dma_pool.total_size - _dma_pool.offset; + if (dma_size > left) { + gprintk("ERROR: Run out the dma resource!\n"); + return -1; + } + *dma_offset = _dma_pool.offset; + _dma_pool.offset += dma_size; + return 0; +} + +static int +_dma_resource_get(int inst_id, phys_addr_t *cpu_pbase, phys_addr_t *dma_pbase, ssize_t* size) +{ + int i; + unsigned int dma_size = 0, dma_offset = 0; + bde_inst_resource_t *res; + + for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { + res = &_bde_inst_resource[i]; + if (res->inst_id == inst_id) { + dma_size = res->dma_size; + dma_offset = res->dma_offset; + break; + } + } + + *cpu_pbase = _dma_pool.cpu_pbase + dma_offset * ONE_MB; + *dma_pbase = _dma_pool.dma_pbase + dma_offset * ONE_MB; + *size = dma_size * ONE_MB; + + return 0; +} + +static int +_instance_validate(unsigned int inst_id, unsigned int dmasize) +{ + int i; + bde_inst_resource_t *res; + + for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { + res = &_bde_inst_resource[i]; + if (res->inst_id == inst_id) { + if (res->dma_size != dmasize) { + if(_devices[i].inst == 0){ + /* Skip _instance_validate (not init yet) */ + return LUBDE_SUCCESS; + } + gprintk("ERROR: dma_size mismatch\n"); + return LUBDE_FAIL; + } + return (1); + } + } + return LUBDE_SUCCESS; +} + +static int +_device_reprobe(void) +{ + int i; + for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { + if (_devices[i].devid == 0) { + _devices_init(i); + } + } + return 0; +} + +static int +_instance_attach(unsigned int inst_id, unsigned int dma_size) +{ + unsigned int dma_offset; + int i, exist; + bde_inst_resource_t *res; + int inst_idx = -1; + uint32 instid; + + /* Reprobe the system for hot-plugged device */ + _device_reprobe(); + + /* Validate the resource with inst_id */ + exist = _instance_validate(inst_id, dma_size); + if (exist < 0) { + return LUBDE_FAIL; + } + if (exist > 0) { + return LUBDE_SUCCESS; + } + if (_dma_resource_alloc(dma_size, &dma_offset) < 0) { + return LUBDE_FAIL; + } + for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { + res = &_bde_inst_resource[i]; + if ((_bde_multi_inst == 0) || (res->inst_id == 0)) { + res->inst_id = inst_id; + res->dma_offset = dma_offset; + res->dma_size = dma_size; + _bde_multi_inst++; + inst_idx = i; + init_waitqueue_head(&res->intr_wq); + atomic_set(&res->intr, 0); + break; + } + } + + for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { + if (inst_id & (1 << i)) { + _devices[i].inst = inst_idx; + /* Pass the instid to the kernel BDE */ + if (lkbde_dev_instid_get(i, &instid) == 0) { + if (!instid) { + lkbde_dev_instid_set(i, inst_id); + } + } + } + } + + return LUBDE_SUCCESS; +} + +/* + * Function: _ioctl + * + * Purpose: + * Handle IOCTL commands from user mode. + * Parameters: + * cmd - IOCTL cmd + * arg - IOCTL parameters + * Returns: + * 0 on success, <0 on error + */ +static int +_ioctl(unsigned int cmd, unsigned long arg) +{ + lubde_ioctl_t io; + phys_addr_t cpu_pbase, dma_pbase; + ssize_t size; + const ibde_dev_t *bde_dev; + int inst_id; + bde_inst_resource_t *res; + + if (copy_from_user(&io, (void *)arg, sizeof(io))) { + return -EFAULT; + } + + io.rc = LUBDE_SUCCESS; + + switch(cmd) { + case LUBDE_VERSION: + io.d0 = KBDE_VERSION; + break; + case LUBDE_GET_NUM_DEVICES: + io.d0 = user_bde->num_devices(io.dev); + break; + case LUBDE_GET_DEVICE: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + bde_dev = user_bde->get_dev(io.dev); + if (bde_dev) { + io.d0 = bde_dev->device; + io.d1 = bde_dev->rev; + if (BDE_DEV_MEM_MAPPED(_devices[io.dev].dev_type)) { + /* Get physical address to map */ + io.d2 = lkbde_get_dev_phys(io.dev); + io.d3 = lkbde_get_dev_phys_hi(io.dev); + } + } else { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_GET_DEVICE_TYPE: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + io.d0 = _devices[io.dev].dev_type; + break; + case LUBDE_GET_BUS_FEATURES: + user_bde->pci_bus_features(io.dev, (int *) &io.d0, (int *) &io.d1, + (int *) &io.d2); + break; + case LUBDE_PCI_CONFIG_PUT32: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + if (_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) { + user_bde->pci_conf_write(io.dev, io.d0, io.d1); + } else { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_PCI_CONFIG_GET32: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + if (_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) { + io.d0 = user_bde->pci_conf_read(io.dev, io.d0); + } else { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_GET_DMA_INFO: + inst_id = io.dev; + if (_bde_multi_inst){ + _dma_resource_get(inst_id, &cpu_pbase, &dma_pbase, &size); + } else { + lkbde_get_dma_info(&cpu_pbase, &dma_pbase, &size); + } + io.d0 = dma_pbase; + io.d1 = size; + /* Optionally enable DMA mmap via /dev/linux-kernel-bde */ + io.d2 = USE_LINUX_BDE_MMAP; + /* Get physical address for mmap */ + io.dx.dw[0] = cpu_pbase; +#ifdef PHYS_ADDRS_ARE_64BITS + io.dx.dw[1] = cpu_pbase >> 32; +#else + io.dx.dw[1] = 0; +#endif + break; + case LUBDE_ENABLE_INTERRUPTS: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + if (_devices[io.dev].dev_type & BDE_SWITCH_DEV_TYPE) { + if (_devices[io.dev].isr && !_devices[io.dev].enabled) { + user_bde->interrupt_connect(io.dev, + _devices[io.dev].isr, + _devices+io.dev); + _devices[io.dev].enabled = 1; + } + } else { + /* Process ethernet device interrupt */ + /* FIXME: for multiple chips */ + if (!_devices[io.dev].enabled) { + user_bde->interrupt_connect(io.dev, + (void(*)(void *))_ether_interrupt, + _devices+io.dev); + _devices[io.dev].enabled = 1; + } + } + break; + case LUBDE_DISABLE_INTERRUPTS: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + if (_devices[io.dev].enabled) { + user_bde->interrupt_disconnect(io.dev); + _devices[io.dev].enabled = 0; + } + break; + case LUBDE_WAIT_FOR_INTERRUPT: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + if (_devices[io.dev].dev_type & BDE_SWITCH_DEV_TYPE) { + res = &_bde_inst_resource[_devices[io.dev].inst]; +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wait_event_timeout(res->intr_wq, + atomic_read(&res->intr) != 0, 100); + +#else + wait_event_interruptible(res->intr_wq, + atomic_read(&res->intr) != 0); +#endif + /* + * Even if we get multiple interrupts, we + * only run the interrupt handler once. + */ + atomic_set(&res->intr, 0); + } else { +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wait_event_timeout(_ether_interrupt_wq, + atomic_read(&_ether_interrupt_has_taken_place) != 0, 100); +#else + wait_event_interruptible(_ether_interrupt_wq, + atomic_read(&_ether_interrupt_has_taken_place) != 0); +#endif + /* + * Even if we get multiple interrupts, we + * only run the interrupt handler once. + */ + atomic_set(&_ether_interrupt_has_taken_place, 0); + } + break; + case LUBDE_USLEEP: + sal_usleep(io.d0); + break; + case LUBDE_UDELAY: + sal_udelay(io.d0); + break; + case LUBDE_SEM_OP: + switch (io.d0) { + case LUBDE_SEM_OP_CREATE: + io.p0 = (bde_kernel_addr_t)sal_sem_create("", io.d1, io.d2); + break; + case LUBDE_SEM_OP_DESTROY: + sal_sem_destroy((sal_sem_t)io.p0); + break; + case LUBDE_SEM_OP_TAKE: + io.rc = sal_sem_take((sal_sem_t)io.p0, io.d2); + break; + case LUBDE_SEM_OP_GIVE: + io.rc = sal_sem_give((sal_sem_t)io.p0); + break; + default: + io.rc = LUBDE_FAIL; + break; + } + break; + case LUBDE_WRITE_IRQ_MASK: + io.rc = lkbde_irq_mask_set(io.dev, io.d0, io.d1, 0); + break; + case LUBDE_SPI_READ_REG: + if (user_bde->spi_read(io.dev, io.d0, io.dx.buf, io.d1) == -1) { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_SPI_WRITE_REG: + if (user_bde->spi_write(io.dev, io.d0, io.dx.buf, io.d1) == -1) { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_READ_REG_16BIT_BUS: + io.d1 = user_bde->read(io.dev, io.d0); + break; + case LUBDE_WRITE_REG_16BIT_BUS: + io.rc = user_bde->write(io.dev, io.d0, io.d1); + break; +#if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT)) + case LUBDE_CPU_WRITE_REG: + { + if (lkbde_cpu_write(io.dev, io.d0, (uint32*)io.dx.buf) == -1) { + io.rc = LUBDE_FAIL; + } + break; + } + case LUBDE_CPU_READ_REG: + { + if (lkbde_cpu_read(io.dev, io.d0, (uint32*)io.dx.buf) == -1) { + io.rc = LUBDE_FAIL; + } + break; + } + case LUBDE_CPU_PCI_REGISTER: + { + if (lkbde_cpu_pci_register(io.dev) == -1) { + io.rc = LUBDE_FAIL; + } + break; + } +#endif + case LUBDE_DEV_RESOURCE: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + bde_dev = user_bde->get_dev(io.dev); + if (bde_dev) { + if (BDE_DEV_MEM_MAPPED(_devices[io.dev].dev_type)) { + /* Get physical address to map */ + io.rc = lkbde_get_dev_resource(io.dev, io.d0, + &io.d1, &io.d2, &io.d3); + } + } else { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_IPROC_READ_REG: + io.d1 = user_bde->iproc_read(io.dev, io.d0); + if (io.d1 == -1) { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_IPROC_WRITE_REG: + if (user_bde->iproc_write(io.dev, io.d0, io.d1) == -1) { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_ATTACH_INSTANCE: + io.rc = _instance_attach(io.d0, io.d1); + break; + case LUBDE_GET_DEVICE_STATE: + io.rc = lkbde_dev_state_get(io.dev, &io.d0); + break; + default: + gprintk("Error: Invalid ioctl (%08x)\n", cmd); + io.rc = LUBDE_FAIL; + break; + } + + if (copy_to_user((void *)arg, &io, sizeof(io))) { + return -EFAULT; + } + + return 0; +} + +/* Workaround for broken Busybox/PPC insmod */ +static char _modname[] = LINUX_USER_BDE_NAME; + +static gmodule_t _gmodule = +{ + name: LINUX_USER_BDE_NAME, + major: LINUX_USER_BDE_MAJOR, + init: _init, + cleanup: _cleanup, + pprint: _pprint, + ioctl: _ioctl, +}; + +gmodule_t* +gmodule_get(void) +{ + _gmodule.name = _modname; + return &_gmodule; +} diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.h b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.h new file mode 100644 index 000000000000..621973b7a7f5 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.h @@ -0,0 +1,112 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: linux-user-bde.h,v 1.23 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef __LINUX_USER_BDE_H__ +#define __LINUX_USER_BDE_H__ + +#include +#include +#include +#ifndef __KERNEL__ +#include +#endif + +#if defined(SAL_BDE_32BIT_USER_64BIT_KERNEL) || defined(PTRS_ARE_64BITS) +typedef uint64_t bde_kernel_addr_t; +#else +typedef uint32_t bde_kernel_addr_t; +#endif + +/* Ioctl control structure */ +typedef struct { + unsigned int dev; /* Device ID */ + unsigned int rc; /* Operation Return Code */ + unsigned int d0; /* Operation specific data */ + unsigned int d1; + unsigned int d2; + unsigned int d3; + bde_kernel_addr_t p0; + union { + unsigned int dw[2]; + unsigned char buf[64]; + } dx; +} lubde_ioctl_t; + + +/* LUBDE ioctls */ +#define LUBDE_MAGIC 'L' + +#define LUBDE_VERSION _IO(LUBDE_MAGIC, 0) +#define LUBDE_GET_NUM_DEVICES _IO(LUBDE_MAGIC, 1) +#define LUBDE_GET_DEVICE _IO(LUBDE_MAGIC, 2) +#define LUBDE_PCI_CONFIG_PUT32 _IO(LUBDE_MAGIC, 3) +#define LUBDE_PCI_CONFIG_GET32 _IO(LUBDE_MAGIC, 4) +#define LUBDE_GET_DMA_INFO _IO(LUBDE_MAGIC, 5) +#define LUBDE_ENABLE_INTERRUPTS _IO(LUBDE_MAGIC, 6) +#define LUBDE_DISABLE_INTERRUPTS _IO(LUBDE_MAGIC, 7) +#define LUBDE_USLEEP _IO(LUBDE_MAGIC, 8) +#define LUBDE_WAIT_FOR_INTERRUPT _IO(LUBDE_MAGIC, 9) +#define LUBDE_SEM_OP _IO(LUBDE_MAGIC, 10) +#define LUBDE_UDELAY _IO(LUBDE_MAGIC, 11) +#define LUBDE_GET_DEVICE_TYPE _IO(LUBDE_MAGIC, 12) +#define LUBDE_SPI_READ_REG _IO(LUBDE_MAGIC, 13) +#define LUBDE_SPI_WRITE_REG _IO(LUBDE_MAGIC, 14) +#define LUBDE_READ_REG_16BIT_BUS _IO(LUBDE_MAGIC, 19) +#define LUBDE_WRITE_REG_16BIT_BUS _IO(LUBDE_MAGIC, 20) +#define LUBDE_GET_BUS_FEATURES _IO(LUBDE_MAGIC, 21) +#define LUBDE_WRITE_IRQ_MASK _IO(LUBDE_MAGIC, 22) +#define LUBDE_CPU_WRITE_REG _IO(LUBDE_MAGIC, 23) +#define LUBDE_CPU_READ_REG _IO(LUBDE_MAGIC, 24) +#define LUBDE_CPU_PCI_REGISTER _IO(LUBDE_MAGIC, 25) +#define LUBDE_DEV_RESOURCE _IO(LUBDE_MAGIC, 26) +#define LUBDE_IPROC_READ_REG _IO(LUBDE_MAGIC, 27) +#define LUBDE_IPROC_WRITE_REG _IO(LUBDE_MAGIC, 28) +#define LUBDE_ATTACH_INSTANCE _IO(LUBDE_MAGIC, 29) +#define LUBDE_GET_DEVICE_STATE _IO(LUBDE_MAGIC, 30) + +#define LUBDE_SEM_OP_CREATE 1 +#define LUBDE_SEM_OP_DESTROY 2 +#define LUBDE_SEM_OP_TAKE 3 +#define LUBDE_SEM_OP_GIVE 4 + +#define LUBDE_SUCCESS 0 +#define LUBDE_FAIL ((unsigned int)-1) + + +/* + * Version history + * 1:add LUBDE_GET_DEVICE_STATE to support PCI hot plug + */ +#define KBDE_VERSION 1 + + +/* This is the signal that will be used + * when an interrupt occurs + */ + +#ifndef __KERNEL__ +#include +#endif + +#define LUBDE_INTERRUPT_SIGNAL SIGUSR1 +#define LUBDE_ETHER_INTERRUPT_SIGNAL SIGUSR2 + +#endif /* __LUBDE_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde.h b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde.h new file mode 100644 index 000000000000..53003a40ce53 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde.h @@ -0,0 +1,76 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#ifndef __SHBDE_H__ +#define __SHBDE_H__ + +typedef void (*shbde_log_func_t)(int level, const char *str, int param); + +#define SHBDE_ERR 0 +#define SHBDE_WARN 1 +#define SHBDE_DBG 2 + +/* iProc configuration (primarily used for PCI-AXI bridge) */ +typedef struct shbde_iproc_config_s { + unsigned int dev_id; + unsigned int dev_rev; + unsigned int use_msi; + unsigned int iproc_ver; + unsigned int cmic_ver; + unsigned int cmic_rev; + unsigned int dma_hi_bits; + unsigned int mdio_base_addr; + unsigned int pcie_phy_addr; + unsigned int adjust_pcie_preemphasis; +} shbde_iproc_config_t; + +/* Hardware abstraction functions */ +typedef struct shbde_hal_s { + + /* Optional log output interface */ + shbde_log_func_t log_func; + + /* PCI configuration access */ + unsigned char (*pcic8_read)(void *pci_dev, unsigned int reg); + void (*pcic8_write)(void *pci_dev, unsigned int reg, unsigned char data); + unsigned short (*pcic16_read)(void *pci_dev, unsigned int reg); + void (*pcic16_write)(void *pci_dev, unsigned int reg, unsigned short data); + unsigned int (*pcic32_read)(void *pci_dev, unsigned int reg); + void (*pcic32_write)(void *pci_dev, unsigned int reg, unsigned int data); + + /* iProc register access */ + unsigned int (*io32_read)(void *addr); + void (*io32_write)(void *addr, unsigned int); + + /* usleep function (optional) */ + void (*usleep)(int usec); + + /* PCI parent device access */ + void *(*pci_parent_device_get)(void *pci_dev); + + /* iProc configuration */ + shbde_iproc_config_t icfg; + +} shbde_hal_t; + + +#endif /* __SHBDE_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_iproc.h b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_iproc.h new file mode 100644 index 000000000000..4b614ba53139 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_iproc.h @@ -0,0 +1,48 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#ifndef __SHBDE_IPROC_H__ +#define __SHBDE_IPROC_H__ + +#include + +extern int +shbde_iproc_config_init(shbde_iproc_config_t *icfg, + unsigned int dev_id, unsigned int dev_rev); + +extern int +shbde_iproc_paxb_init(shbde_hal_t *shbde, void *iproc_regs, + shbde_iproc_config_t *icfg); + +extern unsigned int +shbde_iproc_pci_read(shbde_hal_t *shbde, void *iproc_regs, + unsigned int addr); + +extern void +shbde_iproc_pci_write(shbde_hal_t *shbde, void *iproc_regs, + unsigned int addr, unsigned int data); + +extern int +shbde_iproc_pcie_preemphasis_set(shbde_hal_t *shbde, void *iproc_regs, + shbde_iproc_config_t *icfg, void *pci_dev); + +#endif /* __SHBDE_IPROC_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_mdio.h b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_mdio.h new file mode 100644 index 000000000000..5f8fa63533f4 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_mdio.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: $ + * $Copyright: (c) 2015 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#ifndef __SHBDE_MDIO_H__ +#define __SHBDE_MDIO_H__ + +#include + +typedef struct shbde_mdio_ctrl_s { + + /* Primary HAL*/ + shbde_hal_t *shbde; + + /* Context for iProc MDIO register access */ + void *regs; + + /* Base address for MDIO registers */ + unsigned int base_addr; + + /* iProc MDIO register access */ + unsigned int (*io32_read)(shbde_hal_t *shbde, void *iproc_regs, + unsigned int addr); + void (*io32_write)(shbde_hal_t *shbde, void *iproc_regs, + unsigned int addr, unsigned int data); + +} shbde_mdio_ctrl_t; + + +extern int +shbde_iproc_mdio_init(shbde_mdio_ctrl_t *smc); + +extern int +shbde_iproc_mdio_read(shbde_mdio_ctrl_t *smc, unsigned int phy_addr, + unsigned int reg, unsigned int *val); + +extern int +shbde_iproc_mdio_write(shbde_mdio_ctrl_t *smc, unsigned int phy_addr, + unsigned int reg, unsigned int val); + +#endif /* __SHBDE_MDIO_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_pci.h b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_pci.h new file mode 100644 index 000000000000..1f045d7b02c8 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_pci.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#ifndef __SHBDE_PCI_H__ +#define __SHBDE_PCI_H__ + +#include + +extern unsigned int +shbde_pci_pcie_cap(shbde_hal_t *shbde, void *pci_dev); + +extern int +shbde_pci_is_pcie(shbde_hal_t *shbde, void *pci_dev); + +extern int +shbde_pci_is_iproc(shbde_hal_t *shbde, void *pci_dev, int *cmic_bar); + +extern int +shbde_pci_max_payload_set(shbde_hal_t *shbde, void *pci_dev, int maxpayload); + +extern int +shbde_pci_iproc_version_get(shbde_hal_t *shbde, void *pci_dev, + unsigned int *iproc_ver, + unsigned int *cmic_ver, + unsigned int *cmic_rev); + +#endif /* __SHBDE_PCI_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c new file mode 100644 index 000000000000..d1e95725c5f7 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c @@ -0,0 +1,467 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#include +#include +#include + +/* PAXB register offsets within PCI BAR0 window */ +#define BAR0_PAXB_ENDIANESS 0x2030 +#define BAR0_PAXB_PCIE_EP_AXI_CONFIG 0x2104 +#define BAR0_PAXB_CONFIG_IND_ADDR 0x2120 +#define BAR0_PAXB_CONFIG_IND_DATA 0x2124 + +#define BAR0_PAXB_IMAP0_0 (0x2c00) +#define BAR0_PAXB_IMAP0_1 (0x2c04) +#define BAR0_PAXB_IMAP0_2 (0x2c08) +#define BAR0_PAXB_IMAP0_7 (0x2c1c) + +#define BAR0_PAXB_OARR_FUNC0_MSI_PAGE 0x2d34 +#define BAR0_PAXB_OARR_2 0x2d60 +#define BAR0_PAXB_OARR_2_UPPER 0x2d64 +#define BAR0_DMU_PCU_PCIE_SLAVE_RESET_MODE 0x7024 + +/* Force byte pointer for offset adjustments */ +#define ROFFS(_ptr, _offset) ((unsigned char*)(_ptr) + (_offset)) + +#define PAXB_CONFIG_IND_ADDRr_PROTOCOL_LAYERf_SHFT 11 +#define PAXB_CONFIG_IND_ADDRr_PROTOCOL_LAYERf_MASK 0x3 +#define PAXB_CONFIG_IND_ADDRr_ADDRESSf_SHFT 0 +#define PAXB_CONFIG_IND_ADDRr_ADDRESSf_MASK 0x7ff + +/* Register value set/get by field */ +#define REG_FIELD_SET(_r, _f, _r_val, _f_val) \ + _r_val = ((_r_val) & ~(_r##_##_f##_MASK << _r##_##_f##_SHFT)) | \ + (((_f_val) & _r##_##_f##_MASK) << _r##_##_f##_SHFT) +#define REG_FIELD_GET(_r, _f, _r_val) \ + (((_r_val) >> _r##_##_f##_SHFT) & _r##_##_f##_MASK) + +/* PCIe capabilities definition */ +#ifndef PCI_EXP_LNKSTA +#define PCI_EXP_LNKSTA 0x12 +#endif +/* Current Link Speed 5.0GT/s */ +#ifndef PCI_EXP_LNKSTA_CLS_5_0GB +#define PCI_EXP_LNKSTA_CLS_5_0GB 2 +#endif +#ifndef PCI_EXP_LNKSTA2 +#define PCI_EXP_LNKSTA2 0x32 +#endif +/* Current Deemphasis Level -3.5 dB */ +#ifndef PCI_EXP_LNKSTA2_CDL_3_5DB +#define PCI_EXP_LNKSTA2_CDL_3_5DB 0x1 +#endif + +static unsigned int +iproc32_read(shbde_hal_t *shbde, void *addr) +{ + if (!shbde || !shbde->io32_read) { + return 0; + } + return shbde->io32_read(addr); +} + +static void +iproc32_write(shbde_hal_t *shbde, void *addr, unsigned int data) +{ + if (!shbde || !shbde->io32_write) { + return; + } + shbde->io32_write(addr, data); +} + +static void +wait_usec(shbde_hal_t *shbde, int usec) +{ + if (shbde && shbde->usleep) { + shbde->usleep(usec); + } else { + int idx; + volatile int count; + for (idx = 0; idx < usec; idx++) { + for (count = 0; count < 100; count++); + } + } +} + +/* + * Function: + * shbde_iproc_config_init + * Purpose: + * Initialize iProc configuration parameters + * Parameters: + * icfg - pointer to empty iProc configuration structure + * Returns: + * -1 if error, otherwise 0 + */ +int +shbde_iproc_config_init(shbde_iproc_config_t *icfg, + unsigned int dev_id, unsigned int dev_rev) +{ + if (!icfg) { + return -1; + } + + /* Save device ID and revision */ + icfg->dev_id = dev_id; + icfg->dev_rev = dev_rev; + + /* Check device families first */ + switch (icfg->dev_id & 0xfff0) { + case 0x8400: /* Greyhound Lite */ + case 0x8410: /* Greyhound */ + case 0x8420: /* Bloodhound */ + case 0x8450: /* Elkhound */ + case 0xb060: /* Ranger2(Greyhound) */ + case 0x8360: /* Greyhound 53365 & 53369 */ + case 0xb260: /* saber2 */ + case 0xb460: /* saber2+ */ + case 0xb170: /* Hurricane3-MG */ + case 0x8570: /* Greyhound2 */ + case 0xb070: /* Greyhound2(emulation) */ + case 0x8580: /* Greyhound2(emulation) */ + case 0xb230: /* Dagger2 */ + icfg->iproc_ver = 7; + icfg->dma_hi_bits = 0x2; + break; + case 0xb560: /* Apache */ + case 0xb670: /* MO */ + case 0xb760: /* Maverick */ + icfg->iproc_ver = 0xB; + break; + case 0xb160: /* Hurricane3 */ + case 0x8440: /* Buckhound2 */ + case 0x8430: /* Foxhound2 */ + case 0x8540: /* Wolfhound2 */ + icfg->iproc_ver = 10; + icfg->dma_hi_bits = 0x2; + break; + default: + break; + } + + /* Check for exceptions */ + switch (icfg->dev_id) { + case 0xb069: + case 0xb068: + icfg->iproc_ver = 0xB; /*Ranger2+ Apache Family */ + icfg->dma_hi_bits = 0; + break; + case 0xb168: /* Ranger3+ */ + case 0xb169: + icfg->iproc_ver = 0; + icfg->dma_hi_bits = 0; + break; + default: + break; + } + /* Check for PCIe PHY address that needs PCIe preemphasis and + * assign the MDIO base address + */ + switch (icfg->dev_id & 0xfff0) { + case 0xb150: /* Hurricane2 */ + case 0x8340: /* Wolfhound */ + case 0x8330: /* Foxhound */ + case 0x8390: /* Dearhound */ + icfg->mdio_base_addr = 0x18032000; + icfg->pcie_phy_addr = 0x2; + break; + case 0xb340: /* Helilx4 */ + case 0xb540: /* FireScout */ + case 0xb040: /* Spiral, Ranger */ + icfg->mdio_base_addr = 0x18032000; + icfg->pcie_phy_addr = 0x5; + icfg->adjust_pcie_preemphasis = 1; + break; + case 0xa450: /* Katana2 */ + case 0xb240: + case 0xb450: + icfg->mdio_base_addr = 0x18032000; + icfg->pcie_phy_addr = 0x5; + icfg->adjust_pcie_preemphasis = 1; + break; + default: + break; + } + + /* Check for exceptions */ + switch (icfg->dev_id) { + default: + break; + } + + return 0; +} + +/* + * Function: + * shbde_iproc_paxb_init + * Purpose: + * Initialize iProc PCI-AXI bridge for CMIC access + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * iproc_regs - memory mapped iProc registers in PCI BAR + * icfg - iProc configuration parameters + * Returns: + * -1 if error, otherwise 0 + */ +int +shbde_iproc_paxb_init(shbde_hal_t *shbde, void *iproc_regs, + shbde_iproc_config_t *icfg) +{ + void *reg; + unsigned int data; + int pci_num; + + if (!iproc_regs || !icfg) { + return -1; + } + + /* + * The following code attempts to auto-detect the correct + * iProc PCI endianess configuration by reading a well-known + * register (the endianess configuration register itself). + * Note that the PCI endianess may be different for different + * big endian host processors. + */ + reg = ROFFS(iproc_regs, BAR0_PAXB_ENDIANESS); + /* Select big endian */ + iproc32_write(shbde, reg, 0x01010101); + /* Check if endianess register itself is correct endian */ + if (iproc32_read(shbde, reg) != 1) { + /* If not, then assume little endian */ + iproc32_write(shbde, reg, 0x0); + } + + /* Select which PCI core to use */ + pci_num = 0; + reg = ROFFS(iproc_regs, BAR0_PAXB_IMAP0_2); + data = iproc32_read(shbde, reg); + if (data & 0x1000) { + /* PAXB_1 is mapped to sub-window 2 */ + pci_num = 1; + } + + /* Default DMA mapping if uninitialized */ + if (icfg->dma_hi_bits == 0) { + icfg->dma_hi_bits = 0x1; + if (pci_num == 1) { + icfg->dma_hi_bits = 0x2; + } + } + + /* Enable iProc DMA to external host memory */ + reg = ROFFS(iproc_regs, BAR0_PAXB_PCIE_EP_AXI_CONFIG); + iproc32_write(shbde, reg, 0x0); + if(icfg->cmic_ver < 4) { /* Non-CMICX */ + reg = ROFFS(iproc_regs, BAR0_PAXB_OARR_2); + iproc32_write(shbde, reg, 0x1); + reg = ROFFS(iproc_regs, BAR0_PAXB_OARR_2_UPPER); + iproc32_write(shbde, reg, icfg->dma_hi_bits); + + /* Configure MSI interrupt page */ + if (icfg->use_msi) { + reg = ROFFS(iproc_regs, BAR0_PAXB_OARR_FUNC0_MSI_PAGE); + data = iproc32_read(shbde, reg); + iproc32_write(shbde, reg, data | 0x1); + } + } + return pci_num; +} + +/* + * Function: + * shbde_iproc_pci_read + * Purpose: + * Read iProc register through PCI BAR 0 + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * iproc_regs - memory mapped iProc registers in PCI BAR + * addr - iProc register address in AXI memory space + * Returns: + * Register value + */ +unsigned int +shbde_iproc_pci_read(shbde_hal_t *shbde, void *iproc_regs, + unsigned int addr) +{ + unsigned int subwin_base; + void *reg; + shbde_iproc_config_t *icfg = &shbde->icfg; + + if (!iproc_regs) { + return -1; + } + + /* Sub-window size is 0x1000 (4K) */ + subwin_base = (addr & ~0xfff); + + if((icfg->cmic_ver >= 4) && (subwin_base == 0x18013000)) { + /* Route the INTC block access through IMAP0_6 */ + reg = ROFFS(iproc_regs, 0x6000 + (addr & 0xfff)); + } else { + /* Update base address for sub-window 7 */ + subwin_base |= 1; /* Valid bit */ + reg = ROFFS(iproc_regs, BAR0_PAXB_IMAP0_7); + iproc32_write(shbde, reg, subwin_base); + /* Read it to make sure the write actually goes through */ + subwin_base = iproc32_read(shbde, reg); + + /* Read register through sub-window 7 */ + reg = ROFFS(iproc_regs, 0x7000 + (addr & 0xfff)); + } + + return iproc32_read(shbde, reg); +} + +/* + * Function: + * shbde_iproc_pci_write + * Purpose: + * Write iProc register through PCI BAR 0 + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * iproc_regs - memory mapped iProc registers in PCI BAR + * addr - iProc register address in AXI memory space + * data - data to write to iProc register + * Returns: + * Register value + */ +void +shbde_iproc_pci_write(shbde_hal_t *shbde, void *iproc_regs, + unsigned int addr, unsigned int data) +{ + unsigned int subwin_base; + void *reg; + shbde_iproc_config_t *icfg = &shbde->icfg; + + if (!iproc_regs) { + return; + } + + /* Sub-window size is 0x1000 (4K) */ + subwin_base = (addr & ~0xfff); + + if((icfg->cmic_ver >= 4) && (subwin_base == 0x18013000)) { + /* Route the INTC block access through IMAP0_6 */ + reg = ROFFS(iproc_regs, 0x6000 + (addr & 0xfff)); + } else { + /* Update base address for sub-window 7 */ + subwin_base |= 1; /* Valid bit */ + reg = ROFFS(iproc_regs, BAR0_PAXB_IMAP0_7); + iproc32_write(shbde, reg, subwin_base); + /* Read it to make sure the write actually goes through */ + subwin_base = iproc32_read(shbde, reg); + + /* Read register through sub-window 7 */ + reg = ROFFS(iproc_regs, 0x7000 + (addr & 0xfff)); + } + + iproc32_write(shbde, reg, data); +} + +int +shbde_iproc_pcie_preemphasis_set(shbde_hal_t *shbde, void *iproc_regs, + shbde_iproc_config_t *icfg, void *pci_dev) +{ + shbde_mdio_ctrl_t mdio_ctrl, *smc = &mdio_ctrl; + unsigned int phy_addr, data; + void *reg; + unsigned int pcie_cap_base; + unsigned short link_stat, link_stat2; + + if (!icfg) { + return -1; + } + + /* PHY address for PCIe link */ + phy_addr = icfg->pcie_phy_addr; + if (phy_addr == 0 || icfg->mdio_base_addr == 0) { + return 0; + } + + /* Initialize MDIO control */ + smc->shbde = shbde; + smc->regs = iproc_regs; + smc->base_addr = icfg->mdio_base_addr; + smc->io32_read = shbde_iproc_pci_read; + smc->io32_write = shbde_iproc_pci_write; + shbde_iproc_mdio_init(smc); + + /* PCIe SerDes Gen1/Gen2 CDR Track Bandwidth Adjustment + * for Better Jitter Tolerance + */ + shbde_iproc_mdio_write(smc, phy_addr, 0x1f, 0x8630); + shbde_iproc_mdio_write(smc, phy_addr, 0x13, 0x190); + shbde_iproc_mdio_write(smc, phy_addr, 0x19, 0x191); + + if (!icfg->adjust_pcie_preemphasis) { + return 0; + } + + /* Check to see if the PCIe SerDes deemphasis needs to be changed + * based on the advertisement from the root complex + */ + /* Find PCIe capability base */ + if (!shbde || !shbde->pcic16_read || !pci_dev) { + return -1; + } + pcie_cap_base = shbde_pci_pcie_cap(shbde, pci_dev); + if (pcie_cap_base) { + link_stat = shbde->pcic16_read(pci_dev, + pcie_cap_base + PCI_EXP_LNKSTA); + link_stat2 = shbde->pcic16_read(pci_dev, + pcie_cap_base + PCI_EXP_LNKSTA2); + if (((link_stat & 0xf) == PCI_EXP_LNKSTA_CLS_5_0GB) && + (link_stat2 & PCI_EXP_LNKSTA2_CDL_3_5DB)) { + /* Device is operating at Gen2 speeds and RC requested -3.5dB */ + /* Change the transmitter setting */ + shbde_iproc_mdio_write(smc, phy_addr, 0x1f, 0x8610); + shbde_iproc_mdio_read(smc, phy_addr, 0x17, &data); + data &= ~0xf00; + data |= 0x700; + shbde_iproc_mdio_write(smc, phy_addr, 0x17, data); + + /* Force the PCIe link to retrain */ + data = 0; + REG_FIELD_SET(PAXB_CONFIG_IND_ADDRr, PROTOCOL_LAYERf, data, 0x2); + REG_FIELD_SET(PAXB_CONFIG_IND_ADDRr, ADDRESSf, data, 0x4); + reg = ROFFS(iproc_regs, BAR0_PAXB_CONFIG_IND_ADDR); + iproc32_write(shbde, reg, data); + + reg = ROFFS(iproc_regs, BAR0_PAXB_CONFIG_IND_DATA); + data = iproc32_read(shbde, reg); + data &= ~0x4000; + iproc32_write(shbde, reg, data); + data |= 0x4000; + iproc32_write(shbde, reg, data); + data &= ~0x4000; + iproc32_write(shbde, reg, data); + + /* Wait a short while for the retraining to complete */ + wait_usec(shbde, 1000); + } + } + + return 0; +} + diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_mdio.c b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_mdio.c new file mode 100644 index 000000000000..ef4a72071b33 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_mdio.c @@ -0,0 +1,186 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: $ + * $Copyright: (c) 2015 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#include + +/* iProc MDIO register offset */ +#define MII_MGMT_CTRL 0x0 +#define MII_MGMT_CMD_DATA 0x4 + +/* iProc MII register with fields definition */ +#define MII_MGMT_CTRLr_MDCDIVf_SHFT 0 +#define MII_MGMT_CTRLr_MDCDIVf_MASK 0x7f +#define MII_MGMT_CTRLr_BSYf_SHFT 8 +#define MII_MGMT_CTRLr_BSYf_MASK 0x1 + +#define MII_MGMT_CMD_DATAr_DATAf_SHFT 0 +#define MII_MGMT_CMD_DATAr_DATAf_MASK 0xffff +#define MII_MGMT_CMD_DATAr_TAf_SHFT 16 +#define MII_MGMT_CMD_DATAr_TAf_MASK 0x3 +#define MII_MGMT_CMD_DATAr_RAf_SHFT 18 +#define MII_MGMT_CMD_DATAr_RAf_MASK 0x1f +#define MII_MGMT_CMD_DATAr_PAf_SHFT 23 +#define MII_MGMT_CMD_DATAr_PAf_MASK 0x1f +#define MII_MGMT_CMD_DATAr_OPf_SHFT 28 +#define MII_MGMT_CMD_DATAr_OPf_MASK 0x3 +#define MII_MGMT_CMD_DATAr_SBf_SHFT 30 +#define MII_MGMT_CMD_DATAr_SBf_MASK 0x3 + +/* Register field value set/get */ +#define REG_FIELD_SET(_r, _f, _r_val, _f_val) \ + _r_val = ((_r_val) & ~(_r##_##_f##_MASK << _r##_##_f##_SHFT)) | \ + (((_f_val) & _r##_##_f##_MASK) << _r##_##_f##_SHFT) +#define REG_FIELD_GET(_r, _f, _r_val) \ + (((_r_val) >> _r##_##_f##_SHFT) & _r##_##_f##_MASK) + +#define LOG_OUT(_shbde, _lvl, _str, _prm) \ + if ((_shbde)->log_func) { \ + (_shbde)->log_func(_lvl, _str, _prm); \ + } +#define LOG_ERR(_shbde, _str, _prm) LOG_OUT(_shbde, SHBDE_ERR, _str, _prm) +#define LOG_WARN(_shbde, _str, _prm) LOG_OUT(_shbde, SHBDE_WARN, _str, _prm) +#define LOG_DBG(_shbde, _str, _prm) LOG_OUT(_shbde, SHBDE_DBG, _str, _prm) + +static unsigned int +mdio32_read(shbde_mdio_ctrl_t *smc, unsigned int offset) +{ + if (!smc || !smc->io32_read) { + return 0; + } + return smc->io32_read(smc->shbde, smc->regs, smc->base_addr + offset); +} + +static void +mdio32_write(shbde_mdio_ctrl_t *smc, unsigned int offset, unsigned int data) +{ + if (!smc || !smc->io32_read) { + return; + } + smc->io32_write(smc->shbde, smc->regs, smc->base_addr + offset, data); +} + +static void +wait_usec(shbde_mdio_ctrl_t *smc, int usec) +{ + shbde_hal_t *shbde = smc->shbde; + + if (shbde && shbde->usleep) { + shbde->usleep(usec); + } else { + int idx; + volatile int count; + for (idx = 0; idx < usec; idx++) { + for (count = 0; count < 100; count++); + } + } +} + +static int +iproc_mdio_wait_for_busy(shbde_mdio_ctrl_t *smc) +{ + int mii_busy; + unsigned int reg_val; + int count = 1000; + + /* Wait until MII is not busy */ + do { + reg_val = mdio32_read(smc, MII_MGMT_CTRL); + mii_busy = REG_FIELD_GET(MII_MGMT_CTRLr, BSYf, reg_val); + if (!mii_busy) { + break; + } + wait_usec(smc, 10); + count --; + } while (count > 0); + + return mii_busy; +} + +int +shbde_iproc_mdio_init(shbde_mdio_ctrl_t *smc) +{ + shbde_hal_t *shbde = smc->shbde; + unsigned int reg_val = 0; + + /* Enable the iProc internal MDIO interface */ + REG_FIELD_SET(MII_MGMT_CTRLr, MDCDIVf, reg_val, 0x7f); + mdio32_write(smc, MII_MGMT_CTRL, reg_val); + + if (shbde && !shbde->usleep) { + LOG_DBG(shbde, "shbde_mdio: no registration of usleep vector", 0); + } + + wait_usec(smc, 100); + + return 0; +} + +int +shbde_iproc_mdio_read(shbde_mdio_ctrl_t *smc, unsigned int phy_addr, + unsigned int reg, unsigned int *val) +{ + unsigned int reg_val = 0; + + REG_FIELD_SET(MII_MGMT_CMD_DATAr, SBf, reg_val, 0x1); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, TAf, reg_val, 0x2); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, OPf, reg_val, 0x2); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, PAf, reg_val, phy_addr); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, RAf, reg_val, reg); + mdio32_write(smc, MII_MGMT_CMD_DATA, reg_val); + + if (iproc_mdio_wait_for_busy(smc)) { + *val = 0; + LOG_DBG(smc->shbde, "shbde_iproc_mdio_read busy", reg); + return -1; + } + + reg_val = mdio32_read(smc, MII_MGMT_CMD_DATA); + *val = REG_FIELD_GET(MII_MGMT_CMD_DATAr, DATAf, reg_val); + + return 0; +} + +int +shbde_iproc_mdio_write(shbde_mdio_ctrl_t *smc, unsigned int phy_addr, + unsigned int reg, unsigned int val) +{ + unsigned int reg_val = 0; + + REG_FIELD_SET(MII_MGMT_CMD_DATAr, SBf, reg_val, 0x1); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, TAf, reg_val, 0x2); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, OPf, reg_val, 0x1); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, PAf, reg_val, phy_addr); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, RAf, reg_val, reg); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, DATAf, reg_val, val); + mdio32_write(smc, MII_MGMT_CMD_DATA, reg_val); + + if (iproc_mdio_wait_for_busy(smc)) { + LOG_DBG(smc->shbde, "shbde_iproc_mdio_write busy", reg); + return -1; + } + + /* Wait for some time for the write to take effect */ + wait_usec(smc, 100); + + return 0; +} + diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_pci.c b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_pci.c new file mode 100644 index 000000000000..5cc46d0d463d --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_pci.c @@ -0,0 +1,392 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#include + +/* PCIe capabilities */ +#ifndef PCI_CAPABILITY_LIST +#define PCI_CAPABILITY_LIST 0x34 +#endif +#ifndef PCI_CAP_ID_EXP +#define PCI_CAP_ID_EXP 0x10 +#endif +#ifndef PCI_EXP_DEVCAP +#define PCI_EXP_DEVCAP 4 +#endif +#ifndef PCI_EXP_DEVCTL +#define PCI_EXP_DEVCTL 8 +#endif +#ifndef PCI_EXT_CAP_START +#define PCI_EXT_CAP_START 0x100 +#endif +#ifndef PCI_EXT_CAP_ID +#define PCI_EXT_CAP_ID(_hdr) (_hdr & 0x0000ffff) +#endif +#ifndef PCI_EXT_CAP_VER +#define PCI_EXT_CAP_VER(_hdr) ((_hdr >> 16) & 0xf) +#endif +#ifndef PCI_EXT_CAP_NEXT +#define PCI_EXT_CAP_NEXT(_hdr) ((_hdr >> 20) & 0xffc) +#endif +#ifndef PCI_EXT_CAP_ID_VNDR +#define PCI_EXT_CAP_ID_VNDR 0x0b +#endif + +#define LOG_OUT(_shbde, _lvl, _str, _prm) \ + if ((_shbde)->log_func) { \ + (_shbde)->log_func(_lvl, _str, _prm); \ + } +#define LOG_ERR(_shbde, _str, _prm) LOG_OUT(_shbde, SHBDE_ERR, _str, _prm) +#define LOG_WARN(_shbde, _str, _prm) LOG_OUT(_shbde, SHBDE_WARN, _str, _prm) +#define LOG_DBG(_shbde, _str, _prm) LOG_OUT(_shbde, SHBDE_DBG, _str, _prm) + +#ifndef NULL +#define NULL (void *)0 +#endif + +/* + * Warpper functions with null-pointer checks. + */ +static unsigned int +pcic16_read(shbde_hal_t *shbde, void *pci_dev, + unsigned int addr) +{ + if (!shbde || !shbde->pcic16_read) { + return 0; + } + return shbde->pcic16_read(pci_dev, addr); +} + +static void +pcic16_write(shbde_hal_t *shbde, void *pci_dev, + unsigned int addr, unsigned int data) +{ + if (!shbde || !shbde->pcic16_write) { + return; + } + shbde->pcic16_write(pci_dev, addr, data); +} + +static unsigned int +pcic32_read(shbde_hal_t *shbde, void *pci_dev, + unsigned int addr) +{ + if (!shbde || !shbde->pcic32_read) { + return 0; + } + return shbde->pcic32_read(pci_dev, addr); +} + +static void * +pci_parent_device_get(shbde_hal_t *shbde, void *pci_dev) +{ + if (!shbde || !shbde->pci_parent_device_get) { + return NULL; + } + return shbde->pci_parent_device_get(pci_dev); +} + +/* + * Function: + * shbde_pci_pcie_cap + * Purpose: + * Return offset of PCIe capabilities in PCI configuration space + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * dev - PCI device handle (passed back to PCI HAL functions) + * Returns: + * PCI_CAP_ID_EXP offset in PCI configuration space if PCIe, otherwise 0 + */ +unsigned int +shbde_pci_pcie_cap(shbde_hal_t *shbde, void *pci_dev) +{ + unsigned int cap_base, rval; + + cap_base = pcic16_read(shbde, pci_dev, PCI_CAPABILITY_LIST); + while (cap_base) { + rval = pcic16_read(shbde, pci_dev, cap_base); + if ((rval & 0xff) == PCI_CAP_ID_EXP) { + break; + } + cap_base = (rval >> 8) & 0xff; + } + + return cap_base; +} + +/* + * Function: + * shbde_pci_is_pcie + * Purpose: + * Check if PCI device is PCIe device + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * dev - PCI device handle (passed back to PCI HAL functions) + * Returns: + * 1 if PCIe, otherwise 0 + */ +int +shbde_pci_is_pcie(shbde_hal_t *shbde, void *pci_dev) +{ + return shbde_pci_pcie_cap(shbde, pci_dev) ? 1 : 0; +} + +/* + * Function: + * shbde_pci_is_iproc + * Purpose: + * Check if PCI device is iProc-based + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * dev - PCI device handle (passed back to PCI HAL functions) + * cmic_bar - (OUT) PCI BAR which contains switch CMIC registers + * Returns: + * 1 if iProc-based, otherwise 0 + */ +int +shbde_pci_is_iproc(shbde_hal_t *shbde, void *pci_dev, int *cmic_bar) +{ + unsigned int cap_base, rval; + + if (!shbde_pci_is_pcie(shbde, pci_dev)) { + return 0; + } + + /* Look for PCIe vendor-specific extended capability (VSEC) */ + cap_base = PCI_EXT_CAP_START; + while (cap_base) { + rval = pcic32_read(shbde, pci_dev, cap_base); + if (rval == 0xffffffff) { + /* Assume PCI HW read error */ + return 0; + } + + if (PCI_EXT_CAP_ID(rval) == PCI_EXT_CAP_ID_VNDR) { + break; + } + cap_base = PCI_EXT_CAP_NEXT(rval); + } + if (cap_base) { + /* + * VSEC layout: + * + * 0x00: PCI Express Extended Capability Header + * 0x04: Vendor-Specific Header + * 0x08: Vendor-Specific Register 1 + * 0x0c: Vendor-Specific Register 2 + * ... + * 0x24: Vendor-Specific Register 8 + */ + /* 32'b // 31:12=0 Reserved; 11:08=CMIC BAR; 07:00=iProc Configuration ID */ + rval = pcic32_read(shbde, pci_dev, cap_base + 8); + LOG_DBG(shbde, "Found VSEC", rval); + + /* Determine PCI BAR of CMIC */ + *cmic_bar = 0; + if ((rval & 0x100) == 0x100) { + *cmic_bar = 2; + } + /* Assume iProc device */ + return 1; + } + + return 0; +} + +/* + * Function: + * shbde_pci_iproc_version_get + * Purpose: + * Get iproc, cmic versions and revisions + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * dev - PCI device handle (passed back to PCI HAL functions) + * iproc_ver - (OUT) iProc version + * cmic_ver - (OUT) CMIC version + * cmic_rev - (OUT) CMIC revision + * Returns: + * 1 for no error, otherwise 0 + */ +int +shbde_pci_iproc_version_get(shbde_hal_t *shbde, void *pci_dev, + unsigned int *iproc_ver, + unsigned int *cmic_ver, + unsigned int *cmic_rev) +{ + unsigned int cap_base, rval; + + if (!shbde_pci_is_pcie(shbde, pci_dev)) { + return 0; + } + + /* Look for PCIe vendor-specific extended capability (VSEC) */ + cap_base = PCI_EXT_CAP_START; + while (cap_base) { + rval = pcic32_read(shbde, pci_dev, cap_base); + if (rval == 0xffffffff) { + /* Assume PCI HW read error */ + return 0; + } + + if (PCI_EXT_CAP_ID(rval) == PCI_EXT_CAP_ID_VNDR) { + break; + } + cap_base = PCI_EXT_CAP_NEXT(rval); + } + if (cap_base) { + /* + * VSEC layout: + * + * 0x00: PCI Express Extended Capability Header + * 0x04: Vendor-Specific Header + * 0x08: Vendor-Specific Register 1 + * 0x0c: Vendor-Specific Register 2 + * ... + * 0x24: Vendor-Specific Register 8 + */ + + /* Read PCIe Vendor Specific Register 1 */ + /* VENODR REG FORMAT + * [7:0] iProc Rev = 8'h0E (for P14) + * [11:8] CMIC BAR = 4'h1 (BAR64-1) + * [15:12] CMIC Version = 4'h4 + * [19:16] CMIC Rev = 4'h1 + * [22:20] SBUS Version = 4'h4 + */ + + rval = pcic32_read(shbde, pci_dev, cap_base + 8); + LOG_DBG(shbde, "Found VSEC", rval); + + /* Determine PCI BAR of CMIC */ + *iproc_ver = rval & 0xff; + *cmic_ver = (rval >> 12) & 0xf; + *cmic_rev = (rval >> 16) & 0xf; + return 1; + } + + return 0; +} + +/* + * Function: + * shbde_pci_max_payload_set + * Purpose: + * Set PCIe maximum payload + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * dev - PCI device handle (passed back to PCI HAL functions) + * maxpayload - maximum payload (in byte) + * Returns: + * -1 if error, otherwise 0 + * Notes: + * If not PCIe device, set the PCI retry count to infinte instead. + */ +int +shbde_pci_max_payload_set(shbde_hal_t *shbde, void *pci_dev, int maxpayload) +{ + unsigned int cap_base, parent_cap_base; + unsigned int devcap, devctl, parent_devctl; + int max_val, max_cap, parent_max_val; + void *parent_pci_dev; + + cap_base = shbde_pci_pcie_cap(shbde, pci_dev); + + if (cap_base == 0) { + /* Not PCIe */ + return 0; + } + + /* Get current device control settings */ + devctl = pcic16_read(shbde, pci_dev, cap_base + PCI_EXP_DEVCTL); + + /* Get current max payload setting */ + max_val = (devctl >> 5) & 0x7; + + if (maxpayload) { + /* Get encoding from byte value */ + max_val = 0; + while ((1 << (max_val + 7)) < maxpayload) { + max_val++; + } + LOG_DBG(shbde, "Set max payload size", maxpayload); + LOG_DBG(shbde, "Set max payload val", max_val); + + /* Get max supported payload size */ + devcap = pcic16_read(shbde, pci_dev, cap_base + PCI_EXP_DEVCAP); + max_cap = (devcap & 0x7); + + /* Do not exceed device capabilities */ + if (max_val > max_cap) { + max_val = max_cap; + LOG_DBG(shbde, + "Payload size exceeds device capability", + maxpayload); + } + + /* Get currently set max payload size for the parent device + * in the PCI tree (if it exists). + */ + parent_pci_dev = pci_parent_device_get(shbde, pci_dev); + if (parent_pci_dev != NULL) { + parent_cap_base = shbde_pci_pcie_cap(shbde, parent_pci_dev); + parent_devctl = pcic16_read(shbde, + parent_pci_dev, + parent_cap_base + PCI_EXP_DEVCTL); + parent_max_val = (parent_devctl >> 5) & 0x7; + + /* Do not exceed current parent max payload setting (our device + * should have an MPS setting <= current parent MPS setting in + * the tree of PCIe devices). + */ + if (max_val > parent_max_val) { + max_val = parent_max_val; + LOG_DBG(shbde, + "Payload size exceeds current parent device setting", + maxpayload); + } + } + + /* Update max payload size */ + devctl &= ~(0x7 << 5); + devctl |= (max_val) << 5; + + /* Update max request size */ + devctl &= ~(0x7 << 12); + devctl |= (max_val << 12); + } + + /* Always disable relaxed ordering */ + devctl &= ~(1 << 4); + + /* Update device control settings */ + pcic16_write(shbde, pci_dev, cap_base + PCI_EXP_DEVCTL, devctl); + + /* Warn if non-default setting is used */ + if (max_val > 0) { + LOG_WARN(shbde, + "Selected payload size may not be supported by all " + "PCIe bridges by default.", + (1 << (max_val + 7))); + } + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/Makefile new file mode 100644 index 000000000000..84c677758cac --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/Makefile @@ -0,0 +1,31 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.10 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Makefile for SOC SAL support +# +LOCALDIR = systems/linux/kernel/modules + +include ${SDK}/make/Make.config + +subdirs=shared uk-proxy bcm-diag-full bcm-core bcm-net bcm-diag + +include ${SDK}/make/Make.subdirs + +include ${SDK}/make/Make.depend diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/Makefile new file mode 100644 index 000000000000..ed1a5000e3ca --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/Makefile @@ -0,0 +1,67 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.3 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +LOCALDIR = systems/linux/kernel/modules/bcm-knet + +include ${SDK}/make/Make.config + +LIBS = $(LIBDIR)/libkern.a + +ifeq ($(kernel_version),2_4) +MODULE = $(LIBDIR)/linux-bcm-knet.o +else +KERNEL_MODULE_DIR = kernel_module + +THIS_MOD_NAME := linux-bcm-knet +MODULE = $(LIBDIR)/$(THIS_MOD_NAME).o +KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko + +build: $(MODULE) $(KMODULE) +endif + +KBUILD_EXTRA_SYMBOLS := ${BLDDIR}/../../../../bde/linux/kernel/kernel_module/Module.symvers +ifeq (,$(findstring -DPROXY_SUPPORT=0,$(CFLAGS))) +KBUILD_EXTRA_SYMBOLS += ${BLDDIR}/../uk-proxy/kernel_module/Module.symvers +endif + +# BCM Network Device + +$(MODULE): $(BLDDIR)/.tree $(BOBJS) $(LIBS) + $(LD) $(MODULE_LDFLAGS) -r -d $(BOBJS) $(LIBS) -o $@ +ifneq ($(kernel_version),2_4) +$(KMODULE): $(MODULE) + rm -fr $(BLDDIR)/$(KERNEL_MODULE_DIR) + mkdir $(BLDDIR)/$(KERNEL_MODULE_DIR) + cp ${SDK}/make/Makefile.linux-kmodule $(BLDDIR)/$(KERNEL_MODULE_DIR)/Makefile + cat ${KBUILD_EXTRA_SYMBOLS} > $(BLDDIR)/$(KERNEL_MODULE_DIR)/Module.symvers + MOD_NAME=$(THIS_MOD_NAME) $(MAKE) -C $(BLDDIR)/$(KERNEL_MODULE_DIR) $(THIS_MOD_NAME).ko +endif + +# Make.depend is before clean:: so that Make.depend's clean:: runs first. + +include ${SDK}/make/Make.depend + +clean:: + $(RM) $(BLDDIR)/version.c $(BLDDIR)/version.o + $(RM) $(BOBJS) $(MODULE) + +ifneq ($(kernel_version),2_4) +.PHONY: build +endif diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c new file mode 100644 index 000000000000..801f5d3e406c --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c @@ -0,0 +1,7682 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: bcm-knet.c,v 1.90 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +/* + * This module implements a Linux network driver for Broadcom + * XGS switch devices. The driver simultaneously serves a + * number of vitual Linux network devices and a Tx/Rx API + * implemented in user space. + * + * Packets received from the switch device are sent to either + * a virtual Linux network device or the user mode Rx API + * based on a set of packet filters.susp + * + * Packets from the virtual Linux network devices and the user + * mode Tx API are multiplexed with priority given to the Tx API. + * + * A message-based IOCTL interface is used for managing packet + * filters and virtual Linux network interfaces. + * + * A virtual network interface can be configured to work in RCPU + * mode, which means that packets from the switch device will + * be encasulated with a RCPU header and a block of meta data + * that basically contains the core DCB information. Likewise, + * packets received from the Linux network stack are assumed to + * be RCPU encapsulated when going out on an interface in RCPU + * mode. + * + * The module implements basic Rx DMA rate control. The rate is + * specified in packets per second, and different Rx DMA channels + * can be configured to use different maximum packet rates. + * The packet rate can be configure as a module parameter, and + * it can also be changed dynamically through the proc file + * system (syntax is described in function header comment). + * + * To support multiple instance, each instance has its event queue. + * + * To support pci hot-plug in this module, the resource update + * should be handled when the PCI device is re-plugged. + * NOTE: the KNET detach should be invoked befere removing the + * device. + * + * For a list of supported module parameters, please see below. + */ + +#include /* Must be included first */ +#include +#include +#include + +#include +#include +#include +#include +#include + + +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("Network Device Driver for Broadcom BCM TxRx API"); +MODULE_LICENSE("GPL"); + +static int debug; +LKM_MOD_PARAM(debug, "i", int, 0); +MODULE_PARM_DESC(debug, +"Debug level (default 0)"); + +static char *mac_addr = NULL; +LKM_MOD_PARAM(mac_addr, "s", charp, 0); +MODULE_PARM_DESC(mac_addr, +"Ethernet MAC address (default 02:10:18:xx:xx:xx)"); + +static int rx_buffer_size = 9216; +LKM_MOD_PARAM(rx_buffer_size, "i", int, 0); +MODULE_PARM_DESC(rx_buffer_size, +"Size of RX packet buffers (default 9216)"); + +static int default_mtu = 1500; +LKM_MOD_PARAM(default_mtu, "i", int, 0); +MODULE_PARM_DESC(default_mtu, +"Default MTU for KNET network interfaces (default 1500)"); + +static int rx_sync_retry = 1000; +LKM_MOD_PARAM(rx_sync_retry, "i", int, 0); +MODULE_PARM_DESC(rx_sync_retry, +"Retries if chain is incomplete on interrupt (default 10)"); + +static char *base_dev_name = NULL; +LKM_MOD_PARAM(base_dev_name, "s", charp, 0); +MODULE_PARM_DESC(base_dev_name, +"Base device name (default bcm0, bcm1, etc.)"); + +static int rcpu_mode = 0; +LKM_MOD_PARAM(rcpu_mode, "i", int, 0); +MODULE_PARM_DESC(rcpu_mode, +"Enable RCPU encapsulation (default 0)"); + +static char *rcpu_dmac = NULL; +LKM_MOD_PARAM(rcpu_dmac, "s", charp, 0); +MODULE_PARM_DESC(rcpu_dmac, +"RCPU destination MAC address (by default use L2 destination MAC address)"); + +static char *rcpu_smac = NULL; +LKM_MOD_PARAM(rcpu_smac, "s", charp, 0); +MODULE_PARM_DESC(rcpu_smac, +"RCPU source MAC address (by default use L2 source MAC address)"); + +static int rcpu_ethertype = 0xde08; +LKM_MOD_PARAM(rcpu_ethertype, "i", int, 0); +MODULE_PARM_DESC(rcpu_ethertype, +"RCPU EtherType (default DE08h)"); + +static int rcpu_signature = 0; +LKM_MOD_PARAM(rcpu_signature, "i", int, 0); +MODULE_PARM_DESC(rcpu_signature, +"RCPU Signature (default is PCI device ID)"); + +static int rcpu_vlan = 1; +LKM_MOD_PARAM(rcpu_vlan, "i", int, 0); +MODULE_PARM_DESC(rcpu_vlan, +"RCPU VLAN ID (default 1)"); + +static int use_rx_skb = 0; +LKM_MOD_PARAM(use_rx_skb, "i", int, 0); +MODULE_PARM_DESC(use_rx_skb, +"Use socket buffers for receive operation (default 0)"); + +static int num_rx_prio = 1; +LKM_MOD_PARAM(num_rx_prio, "i", int, 0); +MODULE_PARM_DESC(num_rx_prio, +"Number of filter priorities per Rx DMA channel"); + +static int rx_rate[8] = { 100000, 100000, 100000, 100000, 100000, 100000, 100000, 0 }; +LKM_MOD_PARAM_ARRAY(rx_rate, "1-4i", int, NULL, 0); +MODULE_PARM_DESC(rx_rate, +"Rx rate in packets per second (default 100000)"); + +static int rx_burst[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +LKM_MOD_PARAM_ARRAY(rx_burst, "1-4i", int, NULL, 0); +MODULE_PARM_DESC(rx_burst, +"Rx rate burst maximum in packets (default rx_rate/10)"); + +static int check_rcpu_signature = 0; +LKM_MOD_PARAM(check_rcpu_signature, "i", int, 0); +MODULE_PARM_DESC(check_rcpu_signature, +"Check RCPU Signature for Tx packets from RCPU interfaces"); + +static int basedev_suspend = 0; +LKM_MOD_PARAM(basedev_suspend, "i", int, 0); +MODULE_PARM_DESC(basedev_suspend, +"Pause traffic till base device is up (enabled by default in NAPI mode)"); + +/* Debug levels */ +#define DBG_LVL_VERB 0x1 +#define DBG_LVL_DCB 0x2 +#define DBG_LVL_PKT 0x4 +#define DBG_LVL_SKB 0x8 +#define DBG_LVL_CMD 0x10 +#define DBG_LVL_EVT 0x20 +#define DBG_LVL_IRQ 0x40 +#define DBG_LVL_NAPI 0x80 +#define DBG_LVL_PDMP 0x100 +#define DBG_LVL_FLTR 0x200 +#define DBG_LVL_KCOM 0x400 +#define DBG_LVL_RCPU 0x800 +#define DBG_LVL_WARN 0x1000 +#define DBG_LVL_NDEV 0x2000 +#define DBG_LVL_INST 0x4000 +/* Level to output Dune internal headers Parsing */ +#define DBG_LVL_DUNE 0x8000 +#define DBG_LVL_DCB_TX 0x10000 +#define DBG_LVL_DCB_RX 0x20000 +#define DBG_LVL_PDMP_TX 0x40000 +#define DBG_LVL_PDMP_RX 0x80000 + +#define DBG_VERB(_s) do { if (debug & DBG_LVL_VERB) gprintk _s; } while (0) +#define DBG_PKT(_s) do { if (debug & DBG_LVL_PKT) gprintk _s; } while (0) +#define DBG_SKB(_s) do { if (debug & DBG_LVL_SKB) gprintk _s; } while (0) +#define DBG_CMD(_s) do { if (debug & DBG_LVL_CMD) gprintk _s; } while (0) +#define DBG_EVT(_s) do { if (debug & DBG_LVL_EVT) gprintk _s; } while (0) +#define DBG_IRQ(_s) do { if (debug & DBG_LVL_IRQ) gprintk _s; } while (0) +#define DBG_NAPI(_s) do { if (debug & DBG_LVL_NAPI) gprintk _s; } while (0) +#define DBG_PDMP(_s) do { if (debug & DBG_LVL_PDMP) gprintk _s; } while (0) +#define DBG_FLTR(_s) do { if (debug & DBG_LVL_FLTR) gprintk _s; } while (0) +#define DBG_KCOM(_s) do { if (debug & DBG_LVL_KCOM) gprintk _s; } while (0) +#define DBG_RCPU(_s) do { if (debug & DBG_LVL_RCPU) gprintk _s; } while (0) +#define DBG_WARN(_s) do { if (debug & DBG_LVL_WARN) gprintk _s; } while (0) +#define DBG_NDEV(_s) do { if (debug & DBG_LVL_NDEV) gprintk _s; } while (0) +#define DBG_INST(_s) do { if (debug & DBG_LVL_INST) gprintk _s; } while (0) +#define DBG_DUNE(_s) do { if (debug & DBG_LVL_DUNE) gprintk _s; } while (0) +#define DBG_DCB_TX(_s) do { if (debug & (DBG_LVL_DCB|DBG_LVL_DCB_TX)) \ + gprintk _s; } while (0) +#define DBG_DCB_RX(_s) do { if (debug & (DBG_LVL_DCB|DBG_LVL_DCB_RX)) \ + gprintk _s; } while (0) +#define DBG_DCB(_s) do { if (debug & (DBG_LVL_DCB|DBG_LVL_DCB_TX| \ + DBG_LVL_DCB_RX)) \ + gprintk _s; } while (0) + + +/* This flag is used to indicate if debugging packet function is open or closed */ +static int dbg_pkt_enable = 0; + +/* Module Information */ +#define MODULE_MAJOR 122 +#define MODULE_NAME "linux-bcm-knet" + +#ifndef NAPI_SUPPORT +#define NAPI_SUPPORT 1 +#endif + +#if NAPI_SUPPORT + +static int use_napi = 0; +LKM_MOD_PARAM(use_napi, "i", int, 0); +MODULE_PARM_DESC(use_napi, +"Use NAPI interface (default 0)"); + +static int napi_weight = 64; +LKM_MOD_PARAM(napi_weight, "i", int, 0); +MODULE_PARM_DESC(napi_weight, +"Weight of NAPI interfaces (default 64)"); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +#define bkn_napi_enable(_dev, _napi) netif_poll_enable(_dev) +#define bkn_napi_disable(_dev, _napi) netif_poll_disable(_dev) +#define bkn_napi_schedule(_dev, _napi) netif_rx_schedule(_dev) +#define bkn_napi_schedule_prep(_dev, _napi) netif_rx_schedule_prep(_dev) +#define __bkn_napi_schedule(_dev, _napi) __netif_rx_schedule(_dev) +#define bkn_napi_complete(_dev, _napi) netif_rx_complete(_dev) +#else +#define bkn_napi_enable(_dev, _napi) napi_enable(_napi) +#define bkn_napi_disable(_dev, _napi) napi_disable(_napi) +#define bkn_napi_schedule(_dev, _napi) napi_schedule(_napi) +#define bkn_napi_schedule_prep(_dev, _napi) napi_schedule_prep(_napi) +#define __bkn_napi_schedule(_dev, _napi) __napi_schedule(_napi) +#define bkn_napi_complete(_dev, _napi) napi_complete(_napi) +#endif + +#else + +static int use_napi = 0; +static int napi_weight = 0; + +#define bkn_napi_enable(_dev, _napi) +#define bkn_napi_disable(_dev, _napi) +#define bkn_napi_schedule(_dev, _napi) +#define bkn_napi_schedule_prep(_dev, _napi) (0) +#define __bkn_napi_schedule(_dev, _napi) +#define bkn_napi_complete(_dev, _napi) + +#endif + +/* + * If proxy support is compiled in the module will attempt to use + * the user/kernel message service provided by the linux-uk-proxy + * kernel module, otherwise device IOCTL will be used. + */ +#ifndef PROXY_SUPPORT +#define PROXY_SUPPORT 0 +#endif + +#if PROXY_SUPPORT + +#include + +static int use_proxy = 1; +LKM_MOD_PARAM(use_proxy, "i", int, 0); +MODULE_PARM_DESC(use_proxy, +"Use Linux User/Kernel proxy (default 1)"); + +#define PROXY_SERVICE_CREATE(_s,_q,_f) linux_uk_proxy_service_create(_s,_q,_f) +#define PROXY_SERVICE_DESTROY(_s) linux_uk_proxy_service_destroy(_s); +#define PROXY_SEND(_s,_m,_l) linux_uk_proxy_send(_s,_m,_l) +#define PROXY_RECV(_s,_m,_l) linux_uk_proxy_recv(_s,_m,_l) + +#else + +static int use_proxy = 0; + +#define PROXY_SERVICE_CREATE(_s,_q,_f) +#define PROXY_SERVICE_DESTROY(_s) +#define PROXY_SEND(_s,_m,_l) +#define PROXY_RECV(_s,_m,_l) (-1) + +#endif + +/* Compatibility */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) +#define skb_copy_to_linear_data(_skb, _pkt, _len) \ + eth_copy_and_sum(_skb, _pkt, _len, 0) +struct napi_struct { int not_used; }; +#define netif_napi_add(_dev, _napi, _poll, _weight) do { \ + (_dev)->poll = _poll; \ + (_dev)->weight = _weight; \ +} while(0) +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) +#define SKB_PADTO(_skb,_len) (((_skb = skb_padto(_skb,_len)) == NULL) ? -1 : 0) +#else +#define SKB_PADTO(_skb,_len) skb_padto(_skb,_len) +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)) +#define skb_header_cloned(_skb) \ + skb_cloned(_skb) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) +static inline void *netdev_priv(struct net_device *dev) +{ + return dev->priv; +} +#endif /* KERNEL_VERSION(2,4,27) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) +/* Special check for MontaVista 2.4.20 MIPS */ +#if !(defined(MAX_USER_RT_PRIO) && defined(CONFIG_MIPS)) +static inline void free_netdev(struct net_device *dev) +{ + kfree(dev); +} +#endif +static inline void netif_poll_disable(struct net_device *dev) +{ + while (test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state)) { + /* No hurry. */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } +} +static inline void netif_poll_enable(struct net_device *dev) +{ + clear_bit(__LINK_STATE_RX_SCHED, &dev->state); +} +#endif /* KERNEL_VERSION(2,4,23) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,21) +static struct sk_buff *skb_pad(struct sk_buff *skb, int pad) +{ + struct sk_buff *nskb; + + /* If the skbuff is non linear tailroom is always zero.. */ + if(skb_tailroom(skb) >= pad) + { + memset(skb->data+skb->len, 0, pad); + return skb; + } + + nskb = skb_copy_expand(skb, skb_headroom(skb), skb_tailroom(skb) + pad, GFP_ATOMIC); + kfree_skb(skb); + if(nskb) + memset(nskb->data+nskb->len, 0, pad); + return nskb; +} +static inline struct sk_buff *skb_padto(struct sk_buff *skb, unsigned int len) +{ + unsigned int size = skb->len; + if(likely(size >= len)) + return skb; + return skb_pad(skb, len-size); +} +#endif /* KERNEL_VERSION(2,4,21) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) +#define bkn_vlan_hwaccel_put_tag(_skb, _proto, _tci) \ + __vlan_hwaccel_put_tag(_skb, _tci) +#else +#define bkn_vlan_hwaccel_put_tag(_skb, _proto, _tci) \ + __vlan_hwaccel_put_tag(_skb, htons(_proto), _tci) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) +#define bkn_dma_mapping_error(d, a) \ + dma_mapping_error(a) +#define bkn_pci_dma_mapping_error(d, a) \ + pci_dma_mapping_error(a) +#else +#define bkn_dma_mapping_error(d, a) \ + dma_mapping_error(d, a) +#define bkn_pci_dma_mapping_error(d, a) \ + pci_dma_mapping_error(d, a) +#endif + +#ifdef LINUX_BDE_DMA_DEVICE_SUPPORT +#define DMA_DEV device +#define DMA_FROMDEV DMA_FROM_DEVICE +#define DMA_TODEV DMA_TO_DEVICE +#define DMA_MAP_SINGLE(d,p,s,r) dma_map_single(d,p,s,r) +#define DMA_UNMAP_SINGLE(d,a,s,r) dma_unmap_single(d,a,s,r) +#define DMA_ALLOC_COHERENT(d,s,h) dma_alloc_coherent(d,s,h,GFP_ATOMIC|GFP_DMA32) +#define DMA_FREE_COHERENT(d,s,a,h) dma_free_coherent(d,s,a,h) +#define DMA_MAPPING_ERROR(d,a) bkn_dma_mapping_error(d,a) +#else +#define DMA_DEV pci_dev +#define DMA_FROMDEV PCI_DMA_FROMDEVICE +#define DMA_TODEV PCI_DMA_TODEVICE +#define DMA_MAP_SINGLE(d,p,s,r) pci_map_single(d,p,s,r) +#define DMA_UNMAP_SINGLE(d,a,s,r) pci_unmap_single(d,a,s,r) +#define DMA_ALLOC_COHERENT(d,s,h) pci_alloc_consistent(d,s,h) +#define DMA_FREE_COHERENT(d,s,a,h) pci_free_consistent(d,s,a,h) +#define DMA_MAPPING_ERROR(d,a) bkn_pci_dma_mapping_error(d,a) +#endif + +/* RCPU operations */ +#define RCPU_OPCODE_RX 0x10 +#define RCPU_OPCODE_TX 0x20 + +/* RCPU flags */ +#define RCPU_F_MODHDR 0x4 + +/* RCPU encapsulation */ +#define RCPU_HDR_SIZE 32 +#define RCPU_TX_META_SIZE 32 +#define RCPU_TX_ENCAP_SIZE (RCPU_HDR_SIZE + RCPU_TX_META_SIZE) +#define RCPU_RX_META_SIZE 64 +#define RCPU_RX_ENCAP_SIZE (RCPU_HDR_SIZE + RCPU_RX_META_SIZE) + +#define PKT_TX_HDR_SIZE 16 + +static volatile int module_initialized; + +static ibde_t *kernel_bde = NULL; + +/* Descriptor info */ +typedef struct bkn_desc_info_s { + uint32_t *dcb_mem; + uint64_t dcb_dma; + struct sk_buff *skb; + uint64_t skb_dma; + uint32_t dma_size; +} bkn_desc_info_t; + +/* DCB chain info */ +typedef struct bkn_dcb_chain_s { + struct list_head list; + int dcb_cnt; + int dcb_cur; + uint32_t *dcb_mem; + uint64_t dcb_dma; +} bkn_dcb_chain_t; + +#define MAX_TX_DCBS 64 +#define MAX_RX_DCBS 64 + +#define NUM_DMA_CHAN 8 +#define NUM_RX_CHAN 7 +#define NUM_CMICX_RX_CHAN 7 +#define NUM_CMICM_RX_CHAN 3 + +/* Device control info */ +typedef struct bkn_switch_info_s { + struct list_head list; + struct list_head ndev_list; /* Associated virtual Ethernet interfaces */ + struct net_device **ndevs; /* Indexed array of ndev_list */ + int ndev_max; /* Size of indexed array */ + struct list_head rxpf_list; /* Associated Rx packet filters */ + volatile void *base_addr; /* Base address for PCI register access */ + struct DMA_DEV *dma_dev; /* Required for DMA memory control */ + struct pci_dev *pdev; /* Required for DMA memory control */ + struct net_device *dev; /* Base network device */ + struct napi_struct napi; /* New NAPI */ + struct timer_list timer; /* Retry/resource timer */ + int timer_queued; /* Flag indicating queued timer function */ + uint32_t timer_runs; /* Timer function runs (debug only) */ + struct timer_list rxtick; /* Rx rate control timer */ + uint32_t rxticks_per_sec; /* Rx rate control update frequency */ + uint32_t rxtick_jiffies; /* Time between updates (in jiffies) */ + uint32_t rxticks; /* Rx rate control debug counter */ + uint32_t interrupts; /* Total number of interrupts */ + spinlock_t lock; /* Main lock for device */ + int dev_no; /* Device number (from BDE) */ + int cpu_no; /* Cpu number. 1 for iHost(AXI),0 for others */ + int dcb_type; /* DCB type */ + int dcb_wsize; /* DCB size (in 32-bit words) */ + int pkt_hdr_size; /* Packet header size */ + int rx_chans; /* Number of Rx channels */ + uint32_t dma_hi; /* DMA higher address */ + uint32_t cmic_type; /* CMIC type (CMICe or CMICm) */ + uint32_t irq_mask; /* Active IRQs for DMA control */ + uint32_t napi_poll_mode; /* NAPI is in polling mode */ + uint32_t napi_not_done; /* NAPI poll did not process all packets */ + uint32_t napi_poll_again; /* Used if DCB chain is restarted */ + uint32_t tx_yield; /* Tx schedule for Continuous DMA and Non-NAPI mode */ + void *dcb_mem; /* Logical pointer to DCB memory */ + uint64_t dcb_dma; /* Physical bus address for DCB memory */ + int dcb_mem_size; /* Total size of allocated DCB memory */ + uint32_t dma_events; /* DMA events pending for BCM API */ + uint32_t rcpu_sig; /* RCPU signature */ + uint64_t halt_addr[NUM_DMA_CHAN]; /* DMA halt address */ + uint32_t cdma_channels; /* Active channels for Continuous DMA mode */ + uint32_t inst_id; /* Instance id of this device */ + int evt_idx; /* Event queue index for this device*/ + int basedev_suspended; /* Base device suspended */ + struct { + bkn_desc_info_t desc[MAX_TX_DCBS+1]; + int free; /* Number of free Tx DCBs */ + int cur; /* Index of current Tx DCB */ + int dirty; /* Index of next Tx DCB to complete */ + int api_active; /* BCM Tx API is in progress */ + int suspends; /* Calls to netif_stop_queue (debug only) */ + struct list_head api_dcb_list; /* Tx DCB chains from BCM Tx API */ + bkn_dcb_chain_t *api_dcb_chain; /* Current Tx DCB chain */ + bkn_dcb_chain_t *api_dcb_chain_end; /* Tx DCB chain end */ + uint32_t pkts; /* Tx packet counter */ + uint32_t pkts_d_no_skb; /* Tx drop - skb allocation failed */ + uint32_t pkts_d_rcpu_encap; /* Tx drop - bad RCPU encapsulation */ + uint32_t pkts_d_rcpu_sig; /* Tx drop - bad RCPU signature */ + uint32_t pkts_d_rcpu_meta; /* Tx drop - bad RCPU meta data */ + uint32_t pkts_d_pad_fail; /* Tx drop - pad to minimum size failed */ + uint32_t pkts_d_dma_resrc; /* Tx drop - no DMA resources */ + uint32_t pkts_d_callback; /* Tx drop - consumed by call-back */ + uint32_t pkts_d_no_link; /* Tx drop - software link down */ + uint32_t pkts_d_over_limit; /* Tx drop - length is out of range */ + } tx; + struct { + bkn_desc_info_t desc[MAX_RX_DCBS+1]; + int free; /* Number of free Rx DCBs */ + int cur; /* Index of current Rx DCB */ + int dirty; /* Index of next Rx DCB to complete */ + int running; /* Rx DMA is active */ + int api_active; /* BCM Rx API is active */ + int api_wait; /* Wait BCM Rx API resources */ + int chain_complete; /* All DCBs in chain processed */ + int sync_err; /* Chain done with incomplete DCBs (debug) */ + int sync_retry; /* Total retry times for sync error (debug) */ + int sync_maxloop; /* Max loop times once in recovering sync (debug) */ + int use_rx_skb; /* Use SKBs for DMA */ + uint32_t rate_max; /* Rx rate in packets/sec */ + uint32_t burst_max; /* Rx burst size in number of packets */ + uint32_t tokens; /* Tokens for Rx rate control */ + uint32_t rate; /* Current packet rate */ + unsigned long tok_jif; /* Jiffies at last token update */ + unsigned long rate_jif; /* Jiffies at last rate update */ + struct list_head api_dcb_list; /* Rx DCB chains from BCM Rx API */ + bkn_dcb_chain_t *api_dcb_chain; /* Current Rx DCB chain */ + bkn_dcb_chain_t *api_dcb_chain_end; /* Rx DCB chain end */ + uint32_t pkts; /* Rx packet counter */ + uint32_t pkts_ref; /* Rx packet count for rate calculation */ + uint32_t pkts_f_api; /* Rx packets filtered to API */ + uint32_t pkts_f_netif; /* Rx packets filtered to net interface */ + uint32_t pkts_m_api; /* Rx packets mirrored to API */ + uint32_t pkts_m_netif; /* Rx packets mirrored to net interface */ + uint32_t pkts_d_no_skb; /* Rx drop - skb allocation failed */ + uint32_t pkts_d_no_match; /* Rx drop - no matching filters */ + uint32_t pkts_d_unkn_netif; /* Rx drop - unknown net interface ID */ + uint32_t pkts_d_unkn_dest; /* Rx drop - unknown destination type */ + uint32_t pkts_d_callback; /* Rx drop - consumed by call-back */ + uint32_t pkts_d_no_link; /* Rx drop - software link down */ + uint32_t pkts_d_no_api_buf; /* Rx drop - no API buffers */ + } rx[NUM_RX_CHAN]; +} bkn_switch_info_t; + +#define BKN_DNX_HDR_MAX_SIZE 40 +/* FTMH */ +#define BKN_DNX_FTMH_LB_EXT_EN 0x1 +#define BKN_DNX_FTMH_STACKING_EXT_EN 0x2 +#define BKN_DNX_FTMH_SIZE_BYTE 9 +#define BKN_DNX_FTMH_LB_EXT_SIZE_BYTE 1 +#define BKN_DNX_FTMH_STACKING_SIZE_BYTE 2 +#define BKN_DNX_FTMH_DEST_EXT_SIZE_BYTE 2 +#define BKN_DNX_FTMH_LB_EXT_SIZE_BYTE 1 +#define BKN_DNX_FTMH_PKT_SIZE_MSB 0 +#define BKN_DNX_FTMH_PKT_SIZE_NOF_BITS 14 +#define BKN_DNX_FTMH_TC_MSB 14 +#define BKN_DNX_FTMH_TC_NOF_BITS 3 +#define BKN_DNX_FTMH_SRC_SYS_PORT_MSB 17 +#define BKN_DNX_FTMH_SRC_SYS_PORT_NOF_BITS 16 +#define BKN_DNX_FTMH_EXT_DSP_EXIST_MSB 68 +#define BKN_DNX_FTMH_EXT_DSP_EXIST_NOF_BITS 1 +#define BKN_DNX_FTMH_EXT_MSB 45 +#define BKN_DNX_FTMH_EXT_NOF_BITS 2 +#define BKN_DNX_FTMH_FIRST_EXT_MSB 72 +#define BKN_DNX_FTMH_ACTION_TYPE_MSB 43 +#define BKN_DNX_FTMH_ACTION_TYPE_NOF_BITS 2 +#define BKN_DNX_FTMH_PPH_TYPE_MSB 45 +#define BKN_DNX_FTMH_PPH_TYPE_NOF_BITS 2 +/* PPH */ +#define BKN_DNX_PPH_SIZE_BYTE 7 +#define BKN_DNX_PPH_EEI_EXTENSION_PRESENT_MSB 0 +#define BKN_DNX_PPH_EEI_EXTENSION_PRESENT_NOF_BITS 1 +#define BKN_DNX_PPH_LEARN_EXENSION_PRESENT_MSB 1 +#define BKN_DNX_PPH_LEARN_EXENSION_PRESENT_NOF_BITS 1 +#define BKN_DNX_PPH_FHEI_SIZE_MSB 2 +#define BKN_DNX_PPH_FHEI_SIZE_NOF_BITS 2 +#define BKN_DNX_PPH_FORWARD_CODE_MSB 4 +#define BKN_DNX_PPH_FORWARD_CODE_NOF_BITS 4 +#define BKN_DNX_PPH_VSI_MSB 22 +#define BKN_DNX_PPH_VSI_NOF_BITS 16 +/* FHEI TRAP/SNOOP 3B */ +#define BKN_DNX_PPH_FHEI_3B_SIZE_BYTE 3 +#define BKN_DNX_PPH_FHEI_5B_SIZE_BYTE 5 +#define BKN_DNX_PPH_FHEI_8B_SIZE_BYTE 8 +#define BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_MSB 0 +#define BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_NOF_BITS 16 +#define BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_MSB 16 +#define BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_NOF_BITS 8 +/* PPH extension */ +#define BKN_DNX_PPH_EXPLICIT_EDITING_INFOMATION_EXTENSION_SIZE_BYTE 3 +#define BKN_DNX_PPH_LEARN_EXTENSION_SIZE_BYTE 5 + + +/* ftmh action type. */ +typedef enum bkn_dnx_ftmh_action_type_e { + BKN_DNX_FTMH_ACTION_TYPE_FORWARD = 0, /* TM action is forward */ + BKN_DNX_FTMH_ACTION_TYPE_SNOOP = 1, /* TM action is snoop */ + BKN_DNX_FTMH_ACTION_TYPE_INBOUND_MIRROR = 2, /* TM action is inbound mirror. */ + BKN_DNX_FTMH_ACTION_TYPE_OUTBOUND_MIRROR = 3 /* TM action is outbound mirror. */ +}bkn_dnx_ftmh_action_type_t; + +/* ftmh dest extension. */ +typedef struct bkn_dnx_ftmh_dest_extension_s { + uint8 valid; /* Set if the extension is present */ + uint32_t dst_sys_port; /* Destination System Port */ +} bkn_dnx_ftmh_dest_extension_t; + +/* dnx packet */ +typedef struct bkn_pkt_dnx_s { + uint32_t ntwrk_header_ptr; + struct { + uint32_t packet_size; /* Packet size in bytes */ + uint32_t action_type; /* Indicates if the copy is one of the Forward Snoop or Mirror packet copies */ + uint32_t pph_type; + uint32_t prio; /* Traffic class */ + uint32_t src_sys_port; /* Source System port*/ + } ftmh; + struct { + uint32_t vsi; + uint32_t trap_qualifier; /* RAW Data */ + uint32_t trap_id; /* RAW Data */ + } internal; +} bkn_dnx_packet_info; + + +#define PREV_IDX(_cur, _max) (((_cur) == 0) ? (_max) - 1 : (_cur) - 1) + +#if defined(CMIC_SOFT_BYTE_SWAP) + +#define CMIC_SWAP32(_x) ((((_x) & 0xff000000) >> 24) \ + | (((_x) & 0x00ff0000) >> 8) \ + | (((_x) & 0x0000ff00) << 8) \ + | (((_x) & 0x000000ff) << 24)) + +#define DEV_READ32(_d, _a, _p) \ + do { \ + uint32_t _data; \ + _data = (((volatile uint32_t *)(_d)->base_addr)[(_a)/4]); \ + *(_p) = CMIC_SWAP32(_data); \ + } while(0) + +#define DEV_WRITE32(_d, _a, _v) \ + do { \ + uint32_t _data = CMIC_SWAP32(_v); \ + ((volatile uint32_t *)(_d)->base_addr)[(_a)/4] = (_data); \ + } while(0) + +#else + +#define DEV_READ32(_d, _a, _p) \ + do { \ + *(_p) = (((volatile uint32_t *)(_d)->base_addr)[(_a)/4]); \ + } while(0) + +#define DEV_WRITE32(_d, _a, _v) \ + do { \ + ((volatile uint32_t *)(_d)->base_addr)[(_a)/4] = (_v); \ + } while(0) + +#endif /* defined(CMIC_SOFT_BYTE_SWAP) */ + +#define MEMORY_BARRIER mb() + +/* Default random MAC address has Broadcom OUI with local admin bit set */ +static u8 bkn_dev_mac[6] = { 0x02, 0x10, 0x18, 0x00, 0x00, 0x00 }; + +static u8 bkn_rcpu_dmac[6]; +static u8 bkn_rcpu_smac[6]; + +/* Driver Proc Entry root */ +static struct proc_dir_entry *bkn_proc_root = NULL; + +typedef struct bkn_priv_s { + struct list_head list; + struct net_device_stats stats; + struct net_device *dev; + bkn_switch_info_t *sinfo; + int id; + int type; + int port; + uint8_t itmh[4]; + int qnum; + uint32_t vlan; + uint32_t flags; + uint32_t cb_user_data; +} bkn_priv_t; + +typedef struct bkn_filter_s { + struct list_head list; + int dev_no; + unsigned long hits; + kcom_filter_t kf; +} bkn_filter_t; + + +/* + * Multiple instance support in KNET + */ +static int _bkn_multi_inst = 0; +typedef struct { + wait_queue_head_t evt_wq; + int evt_wq_put; + int evt_wq_get; + uint32_t inst_id; +} bkn_evt_resource_t; + +static bkn_evt_resource_t _bkn_evt[LINUX_BDE_MAX_DEVICES]; + +static int bkn_knet_dev_init(int d); +static int bkn_knet_dev_reinit(int d); + +/* IOCTL debug counters */ +static int ioctl_cmd; +static int ioctl_evt; + +/* Switch devices */ +LIST_HEAD(_sinfo_list); + +/* Reallocation chunk size for netif array */ +#define NDEVS_CHUNK 64 + +/* User call-backs */ +static knet_skb_cb_f knet_rx_cb = NULL; +static knet_skb_cb_f knet_tx_cb = NULL; +static knet_filter_cb_f knet_filter_cb = NULL; + +/* + * Thread management + */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) +/* + * Old style using kernel_thread() + */ +typedef struct { + const char * name; + volatile int pid; + volatile int run; + struct completion completion; + int state; +} bkn_thread_ctrl_t; + +static int +bkn_thread_start(bkn_thread_ctrl_t *tc, const char *name, + int (*threadfn)(void *)) +{ + if (name == NULL) { + return -1; + } + tc->name = name; + tc->pid = kernel_thread(threadfn, tc, 0); + if (tc->pid < 0) { + tc->pid = 0; + return -1; + } + tc->run = 1; + init_completion(&tc->completion); + return 0; +} + +static int +bkn_thread_stop(bkn_thread_ctrl_t *tc) +{ + if (tc->pid == 0) { + return 0; + } + tc->run = 0; + kill_proc(tc->pid, SIGTERM, 1); + wait_for_completion(&tc->completion); + return 0; +} + +static int +bkn_thread_should_stop(bkn_thread_ctrl_t *tc) +{ + if (tc->run) { + return 0; + } + tc->pid = 0; + return 1; +} + +static void +bkn_thread_boot(bkn_thread_ctrl_t *tc) +{ + siginitsetinv(¤t->blocked, sigmask(SIGTERM) | sigmask(SIGKILL)); +} + +static void +bkn_thread_exit(bkn_thread_ctrl_t *tc) +{ + complete_and_exit(&tc->completion, 0); +} + +static void +bkn_sleep(int clicks) +{ + wait_queue_head_t wq; + + init_waitqueue_head(&wq); + sleep_on_timeout(&wq, clicks); +} +#else +/* + * New style using kthread API + */ +#include +typedef struct { + const char * name; + struct task_struct *task; + int state; +} bkn_thread_ctrl_t; + +static int +bkn_thread_start(bkn_thread_ctrl_t *tc, const char *name, + int (*threadfn)(void *)) +{ + if (name == NULL) { + return -1; + } + tc->name = name; + tc->task = kthread_run(threadfn, tc, name); + if (IS_ERR(tc->task)) { + tc->task = NULL; + return -1; + } + return 0; +} + +static int +bkn_thread_stop(bkn_thread_ctrl_t *tc) +{ + if (tc->task == NULL) { + return 0; + } + send_sig(SIGTERM, tc->task, 0); + return kthread_stop(tc->task); +} + +static int +bkn_thread_should_stop(bkn_thread_ctrl_t *tc) +{ + return kthread_should_stop(); +} + +static void +bkn_thread_boot(bkn_thread_ctrl_t *tc) +{ + allow_signal(SIGTERM); + allow_signal(SIGKILL); +} + +static void +bkn_thread_exit(bkn_thread_ctrl_t *tc) +{ +} + +static void +bkn_sleep(int clicks) +{ + wait_queue_head_t wq; + + init_waitqueue_head(&wq); + wait_event_timeout(wq, 0, clicks); +} +#endif + +static bkn_thread_ctrl_t bkn_cmd_ctrl; +static bkn_thread_ctrl_t bkn_evt_ctrl; + +/* + * On XGS devices bit 15 fo the Transferred Bytes field in + * the DCBs is used to indicate that kernel processing is + * complete. Using this bit reduces the theoretically maximum + * supported packet size from 64K to 32K, but this is still + * adequate for 16K jumbo packets. + */ +#define SOC_DCB_KNET_DONE 0x8000 +#define SOC_DCB_KNET_COUNT_MASK 0x7fff +#define SOC_DCB_META_OFFSET 2 + +/* Default channel configuration */ +#define XGS_DMA_TX_CHAN 0 +#define XGS_DMA_RX_CHAN 1 + +/* CMIC registers */ +#define CMIC_DMA_CTRLr 0x00000100 +#define CMIC_DMA_STATr 0x00000104 +#define CMIC_DMA_DESC0r 0x00000110 +#define CMIC_IRQ_STATr 0x00000144 +#define CMIC_IRQ_MASKr 0x00000148 +#define CMIC_DEV_REV_IDr 0x00000178 + +/* CMIC interrupts reserved for kernel handler */ +#define CMIC_TXRX_IRQ_MASK 0x7f80 + +/* CMICm registers */ +#define CMICM_CMC_BASE 0x00031000 +#define CMICM_DMA_CTRLr (CMICM_CMC_BASE + 0x00000140) +#define CMICM_DMA_STATr (CMICM_CMC_BASE + 0x00000150) +#define CMICM_DMA_STAT_CLRr (CMICM_CMC_BASE + 0x000001a4) +#define CMICM_DMA_DESC0r (CMICM_CMC_BASE + 0x00000158) +#define CMICM_DMA_HALT_ADDRr (CMICM_CMC_BASE + 0x00000120) +#define CMICM_IRQ_STATr (CMICM_CMC_BASE + 0x00000400) +#define CMICM_IRQ_PCI_MASKr (CMICM_CMC_BASE + 0x00000414) +#define CMICM_IRQ_UC0_MASKr (CMICM_CMC_BASE + 0x00000428) +#define CMICM_DEV_REV_IDr 0x00010224 + +/* CMICm interrupts reserved for kernel handler */ +#define CMICM_TXRX_IRQ_MASK 0xff00 + +/* CMICd increased interrupts reserved for kernel handler */ +#define CMICD_CTRLD_IRQ_MASK 0x78000000 + +/* CMICx registers */ +#define CMICX_CMC_BASE 0x00000000 +#define CMICX_DMA_CTRLr (CMICX_CMC_BASE + 0x00002100) +#define CMICX_DMA_STATr (CMICX_CMC_BASE + 0x00002114) +#define CMICX_DMA_DESC_HIr (CMICX_CMC_BASE + 0x00002108) +#define CMICX_DMA_DESC_LOr (CMICX_CMC_BASE + 0x00002104) +#define CMICX_DMA_HALT_HIr (CMICX_CMC_BASE + 0x00002110) +#define CMICX_DMA_HALT_LOr (CMICX_CMC_BASE + 0x0000210c) +#define CMICX_IRQ_STATr (CMICX_CMC_BASE + 0x0000106c) +#define CMICX_IRQ_STAT_CLRr (CMICX_CMC_BASE + 0x00001074) +#define CMICX_IRQ_ENABr 0x18013100 + +/* CMICx interrupts reserved for kernel handler */ +#define CMICX_TXRX_IRQ_MASK 0xffffffff + +#define DEV_IS_CMICX(_sinfo) ((_sinfo)->cmic_type == 'x') +#define DEV_IS_CMICM(_sinfo) ((_sinfo)->cmic_type == 'm') +#define CDMA_CH(_d, _ch) ((_d)->cdma_channels & (1 << (_ch))) + +/* + * DMA_STAT: control bits + * + * xxx_SET and xxx_CLR can be WRITTEN to CMIC_DMA_STAT + * xxx_TST can be masked against values read from CMIC_DMA_STAT. + * Argument required: 0 <= ch <= 3 + */ +#define DS_DMA_ACTIVE(ch) (0x00040000 << (ch)) +#define DS_DMA_EN_SET(ch) (0x80|(ch)) +#define DS_DMA_EN_CLR(ch) (0x00|(ch)) +#define DS_DMA_EN_TST(ch) (0x00000001 << (ch)) + +#define DS_CHAIN_DONE_SET(ch) (0x80|(4+(ch))) +#define DS_CHAIN_DONE_CLR(ch) (0x00|(4+(ch))) +#define DS_CHAIN_DONE_TST(ch) (0x00000010 << (ch)) + +#define DS_DESC_DONE_SET(ch) (0x80|(8+(ch))) +#define DS_DESC_DONE_CLR(ch) (0x00|(8+(ch))) +#define DS_DESC_DONE_TST(ch) (0x00000100 << (ch)) + +#define DC_ABORT_DMA(ch) (0x04 << (8 * (ch))) + +#define DS_CMC_DESCRD_CMPLT_CLR(ch) (0x00000001 << (ch)) +#define DS_CMC_CTRLD_INT_CLR(ch) (0x00000100 << (ch)) +#define DS_CMC_DMA_ACTIVE(ch) (0x00000100 << (ch)) + +#define CMICX_DS_CMC_DESC_DONE(ch) (0x00000001 << ((ch) * 4)) +#define CMICX_DS_CMC_CHAIN_DONE(ch) (0x00000002 << ((ch) * 4)) +#define CMICX_DS_CMC_CTRLD_INT(ch) (0x00000008 << ((ch) * 4)) +#define CMICX_DS_CMC_DMA_ACTIVE (0x00000002) + +#define DMA_TO_BUS_HI(dma) ((dma) | sinfo->dma_hi) +#define BUS_TO_DMA_HI(bus) ((bus) & ~sinfo->dma_hi) + +/* + * DMA_CTRL: control bits + */ +#define DC_CMC_DIRECTION (0x00000001) +#define DC_CMC_ENABLE (0x00000002) +#define DC_CMC_ABORT (0x00000004) +#define DC_CMC_CTRLD_INT (0x00000100) +#define DC_CMC_CONTINUOUS (0x00000200) + +#define CMICX_DC_CMC_DIRECTION (0x00000001) +#define CMICX_DC_CMC_ENABLE (0x00000002) +#define CMICX_DC_CMC_ABORT (0x00000004) +#define CMICX_DC_CMC_CTRLD_INT (0x00000080) +#define CMICX_DC_CMC_CONTINUOUS (0x00000100) + +/* + * Per-channel operations. + * These are the basis for the TX/RX functions + */ + +static inline void +xgs_dma_chain_clear(bkn_switch_info_t *sinfo, int chan) +{ + DBG_IRQ(("Clear chain on device %d chan %d\n", + sinfo->dev_no, chan)); + DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_DMA_EN_CLR(chan)); + DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_CHAIN_DONE_CLR(chan)); + + MEMORY_BARRIER; +} + +static inline void +xgs_dma_desc_clear(bkn_switch_info_t *sinfo, int chan) +{ + uint32_t val; + + DBG_IRQ(("Clear desc on device %d chan %d\n", + sinfo->dev_no, chan)); + DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_DESC_DONE_CLR(chan)); + + MEMORY_BARRIER; + + /* Flush write buffer */ + DEV_READ32(sinfo, CMIC_DMA_STATr, &val); + + MEMORY_BARRIER; +} + +static int +xgs_dma_chan_clear(bkn_switch_info_t *sinfo, int chan) +{ + xgs_dma_chain_clear(sinfo, chan); + xgs_dma_desc_clear(sinfo, chan); + + return 0; +} + +static int +xgs_dma_chan_init(bkn_switch_info_t *sinfo, int chan, int dir) +{ + uint32_t cdc; + + DEV_READ32(sinfo, CMIC_DMA_CTRLr, &cdc); + + cdc &= ~(0x9 << (8 * chan)); + if (dir) { + cdc |= 0x1 << (8 * chan); + } else { + cdc |= 0x8 << (8 * chan); + } + + DEV_WRITE32(sinfo, CMIC_DMA_CTRLr, cdc); + + return 0; +} + +static int +xgs_dma_chan_start(bkn_switch_info_t *sinfo, int chan, uint64_t dcb) +{ + /* Write the DCB address to the DESC address for this channel */ + DEV_WRITE32(sinfo, CMIC_DMA_DESC0r + 4 * chan, dcb); + + MEMORY_BARRIER; + + /* Kick it off */ + DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_DMA_EN_SET(chan)); + + MEMORY_BARRIER; + + return 0; +} + +static int +xgs_dma_chan_abort(bkn_switch_info_t *sinfo, int chan, int polls) +{ + uint32_t ctrl, dma_stat; + int p; + + /* Clear enable */ + DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_DMA_EN_CLR(chan)); + + MEMORY_BARRIER; + + /* Abort the channel */ + DEV_READ32(sinfo, CMIC_DMA_CTRLr, &ctrl); + DEV_WRITE32(sinfo, CMIC_DMA_CTRLr, ctrl | DC_ABORT_DMA(chan)); + + MEMORY_BARRIER; + + /* Poll for abort completion */ + for (p = 0; p < polls; p++) { + DEV_READ32(sinfo, CMIC_DMA_STATr, &dma_stat); + if (!(dma_stat & DS_DMA_ACTIVE(chan))) { + /* Restore previous control value */ + DEV_WRITE32(sinfo, CMIC_DMA_CTRLr, ctrl); + + MEMORY_BARRIER; + + /* Clear up channel */ + xgs_dma_chan_clear(sinfo, chan); + + return polls; + } + } + DBG_WARN(("DMA channel %d abort failed\n", chan)); + + return -1; +} + +static inline void +xgs_irq_mask_set(bkn_switch_info_t *sinfo, uint32_t mask) +{ + if (sinfo->napi_poll_mode) { + mask = 0; + } + lkbde_irq_mask_set(sinfo->dev_no | LKBDE_ISR2_DEV, CMIC_IRQ_MASKr, + mask, CMIC_TXRX_IRQ_MASK); +} + +static inline void +xgs_irq_mask_enable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + uint32_t mask; + + if (chan == XGS_DMA_TX_CHAN) { + mask = 0x100; + } else { + mask = 0x180 << (2 * chan); + } + + sinfo->irq_mask |= mask; + + if (update_hw) { + xgs_irq_mask_set(sinfo, sinfo->irq_mask); + } +} + +static inline void +xgs_irq_mask_disable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + uint32_t mask; + + if (chan == XGS_DMA_TX_CHAN) { + mask = 0x100; + } else { + mask = 0x180 << (2 * chan); + } + + sinfo->irq_mask &= ~mask; + + if (update_hw) { + xgs_irq_mask_set(sinfo, sinfo->irq_mask); + } +} + +static inline void +xgsm_dma_chain_clear(bkn_switch_info_t *sinfo, int chan) +{ + uint32_t cdc; + + /* Disabing DMA clears chain done */ + DEV_READ32(sinfo, CMICM_DMA_CTRLr + 4 * chan, &cdc); + cdc &= ~(DC_CMC_ENABLE | DC_CMC_ABORT); + DEV_WRITE32(sinfo, CMICM_DMA_CTRLr + 4 * chan, cdc); + + MEMORY_BARRIER; +} + +static inline void +xgsm_dma_desc_clear(bkn_switch_info_t *sinfo, int chan) +{ + uint32_t val; + + val = DS_CMC_DESCRD_CMPLT_CLR(chan); + if (CDMA_CH(sinfo, chan)) { + val |= DS_CMC_CTRLD_INT_CLR(chan); + } + DEV_WRITE32(sinfo, CMICM_DMA_STAT_CLRr, val); + + MEMORY_BARRIER; + + /* Flush write buffer */ + DEV_READ32(sinfo, CMICM_DMA_STAT_CLRr, &val); + + MEMORY_BARRIER; +} + +static int +xgsm_dma_chan_clear(bkn_switch_info_t *sinfo, int chan) +{ + xgsm_dma_chain_clear(sinfo, chan); + xgsm_dma_desc_clear(sinfo, chan); + + return 0; +} + +static inline void +xgsm_cdma_halt_set(bkn_switch_info_t *sinfo, int chan) +{ + DEV_WRITE32(sinfo, CMICM_DMA_HALT_ADDRr + 4 * chan, + sinfo->halt_addr[chan]); + + MEMORY_BARRIER; +} + +static int +xgsm_dma_chan_init(bkn_switch_info_t *sinfo, int chan, int dir) +{ + uint32_t cdc; + + DEV_READ32(sinfo, CMICM_DMA_CTRLr + 4 * chan, &cdc); + cdc &= ~DC_CMC_DIRECTION; + if (dir) { + cdc |= DC_CMC_DIRECTION; + } + if (CDMA_CH(sinfo, chan)) { + cdc |= DC_CMC_CONTINUOUS | DC_CMC_CTRLD_INT; + xgsm_cdma_halt_set(sinfo, chan); + } + DEV_WRITE32(sinfo, CMICM_DMA_CTRLr + 4 * chan, cdc); + + return 0; +} + +static int +xgsm_dma_chan_start(bkn_switch_info_t *sinfo, int chan, uint64_t dcb) +{ + uint32_t cdc; + + /* Write the DCB address to the DESC address for this channel */ + DEV_WRITE32(sinfo, CMICM_DMA_DESC0r + 4 * chan, dcb); + + MEMORY_BARRIER; + + /* Kick it off */ + DEV_READ32(sinfo, CMICM_DMA_CTRLr + 4 * chan, &cdc); + cdc |= DC_CMC_ENABLE; + DEV_WRITE32(sinfo, CMICM_DMA_CTRLr + 4 * chan, cdc); + + MEMORY_BARRIER; + + return 0; +} + +static int +xgsm_dma_chan_abort(bkn_switch_info_t *sinfo, int chan, int polls) +{ + uint32_t ctrl, dma_stat; + int p; + + /* Skip abort sequence if channel is not active */ + DEV_READ32(sinfo, CMICM_DMA_STATr, &dma_stat); + if (!(dma_stat & DS_CMC_DMA_ACTIVE(chan))) { + return 0; + } + + /* Abort the channel */ + DEV_READ32(sinfo, CMICM_DMA_CTRLr + 4 * chan, &ctrl); + ctrl |= (DC_CMC_ENABLE | DC_CMC_ABORT); + DEV_WRITE32(sinfo, CMICM_DMA_CTRLr + 4 * chan, ctrl); + + MEMORY_BARRIER; + + /* Poll for abort completion */ + for (p = 0; p < polls; p++) { + DEV_READ32(sinfo, CMICM_DMA_STATr, &dma_stat); + if (!(dma_stat & DS_CMC_DMA_ACTIVE(chan))) { + /* Clear up channel */ + xgsm_dma_chan_clear(sinfo, chan); + return polls; + } + } + DBG_WARN(("DMA channel %d abort failed\n", chan)); + + return -1; +} + +static inline void +xgsm_irq_mask_set(bkn_switch_info_t *sinfo, uint32_t mask) +{ + uint32_t irq_mask_reg = CMICM_IRQ_PCI_MASKr; + uint32_t ctrld_mask = 0; + + if (sinfo->napi_poll_mode) { + mask = 0; + } + if (sinfo->cpu_no == 1) { + irq_mask_reg = CMICM_IRQ_UC0_MASKr; + } + + /* Get the Controlled Interrupts mask for Continuous DMA mode */ + ctrld_mask |= (sinfo->cdma_channels << 27) & CMICD_CTRLD_IRQ_MASK; + + lkbde_irq_mask_set(sinfo->dev_no | LKBDE_ISR2_DEV, irq_mask_reg, + mask, CMICM_TXRX_IRQ_MASK | ctrld_mask); +} + +static inline void +xgsm_irq_mask_enable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + uint32_t mask; + + if (CDMA_CH(sinfo, chan)) { + mask = 0x08000000 << chan; + } else { + if (chan == XGS_DMA_TX_CHAN) { + mask = 0x8000; + } else { + mask = 0xc000 >> (2 * chan); + } + } + + sinfo->irq_mask |= mask; + + if (update_hw) { + xgsm_irq_mask_set(sinfo, sinfo->irq_mask); + } +} + +static inline void +xgsm_irq_mask_disable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + uint32_t mask; + + if (CDMA_CH(sinfo, chan)) { + mask = 0x08000000 << chan; + } else { + if (chan == XGS_DMA_TX_CHAN) { + mask = 0x8000; + } else { + mask = 0xc000 >> (2 * chan); + } + } + + sinfo->irq_mask &= ~mask; + + if (update_hw) { + xgsm_irq_mask_set(sinfo, sinfo->irq_mask); + } +} + +static inline void +xgsx_dma_chain_clear(bkn_switch_info_t *sinfo, int chan) +{ + uint32_t ctrl, stat; + + /* Disabing DMA clears chain done */ + DEV_READ32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, &ctrl); + ctrl &= ~(CMICX_DC_CMC_ENABLE | CMICX_DC_CMC_ABORT); + DEV_WRITE32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, ctrl); + + stat = CMICX_DS_CMC_CHAIN_DONE(chan); + DEV_WRITE32(sinfo, CMICX_IRQ_STAT_CLRr, stat); + + MEMORY_BARRIER; + + /* Flush write buffer */ + DEV_READ32(sinfo, CMICX_IRQ_STAT_CLRr, &stat); + + MEMORY_BARRIER; +} + +static inline void +xgsx_dma_desc_clear(bkn_switch_info_t *sinfo, int chan) +{ + uint32_t stat; + + if (CDMA_CH(sinfo, chan)) { + stat = CMICX_DS_CMC_CTRLD_INT(chan); + } else { + stat = CMICX_DS_CMC_DESC_DONE(chan); + } + DEV_WRITE32(sinfo, CMICX_IRQ_STAT_CLRr, stat); + + MEMORY_BARRIER; + + /* Flush write buffer */ + DEV_READ32(sinfo, CMICX_IRQ_STAT_CLRr, &stat); + + MEMORY_BARRIER; +} + +static int +xgsx_dma_chan_clear(bkn_switch_info_t *sinfo, int chan) +{ + xgsx_dma_chain_clear(sinfo, chan); + xgsx_dma_desc_clear(sinfo, chan); + + return 0; +} + +static inline void +xgsx_cdma_halt_set(bkn_switch_info_t *sinfo, int chan) +{ + DEV_WRITE32(sinfo, CMICX_DMA_HALT_LOr + 0x80 * chan, + sinfo->halt_addr[chan]); + DEV_WRITE32(sinfo, CMICX_DMA_HALT_HIr + 0x80 * chan, + DMA_TO_BUS_HI(sinfo->halt_addr[chan] >> 32)); + + MEMORY_BARRIER; +} + +static int +xgsx_dma_chan_init(bkn_switch_info_t *sinfo, int chan, int dir) +{ + uint32_t ctrl; + + DEV_READ32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, &ctrl); + ctrl &= ~CMICX_DC_CMC_DIRECTION; + if (dir) { + ctrl |= CMICX_DC_CMC_DIRECTION; + } + if (CDMA_CH(sinfo, chan)) { + ctrl |= CMICX_DC_CMC_CONTINUOUS | CMICX_DC_CMC_CTRLD_INT; + xgsx_cdma_halt_set(sinfo, chan); + } + DEV_WRITE32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, ctrl); + + MEMORY_BARRIER; + + return 0; +} + +static int +xgsx_dma_chan_start(bkn_switch_info_t *sinfo, int chan, uint64_t dcb) +{ + uint32_t ctrl; + + /* Write the DCB address to the DESC address for this channel */ + DEV_WRITE32(sinfo, CMICX_DMA_DESC_LOr + 0x80 * chan, dcb); + DEV_WRITE32(sinfo, CMICX_DMA_DESC_HIr + 0x80 * chan, DMA_TO_BUS_HI(dcb >> 32)); + + MEMORY_BARRIER; + + /* Kick it off */ + DEV_READ32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, &ctrl); + ctrl |= CMICX_DC_CMC_ENABLE; + DEV_WRITE32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, ctrl); + + MEMORY_BARRIER; + + return 0; +} + +static int +xgsx_dma_chan_abort(bkn_switch_info_t *sinfo, int chan, int polls) +{ + uint32_t ctrl, stat; + int p; + + /* Skip abort sequence if channel is not active */ + DEV_READ32(sinfo, CMICX_DMA_STATr + 0x80 * chan, &stat); + if (!(stat & CMICX_DS_CMC_DMA_ACTIVE)) { + return 0; + } + + /* Abort the channel */ + DEV_READ32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, &ctrl); + ctrl |= CMICX_DC_CMC_ENABLE | CMICX_DC_CMC_ABORT; + DEV_WRITE32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, ctrl); + + MEMORY_BARRIER; + + /* Poll for abort completion */ + for (p = 0; p < polls; p++) { + DEV_READ32(sinfo, CMICX_DMA_STATr + 0x80 * chan, &stat); + if (!(stat & CMICX_DS_CMC_DMA_ACTIVE)) { + /* Clear up channel */ + xgsx_dma_chan_clear(sinfo, chan); + return polls; + } + } + + DBG_WARN(("DMA channel %d abort failed\n", chan)); + + return -1; +} + +static inline void +xgsx_irq_mask_set(bkn_switch_info_t *sinfo, uint32_t mask) +{ + if (sinfo->napi_poll_mode) { + mask = 0; + } + + lkbde_irq_mask_set(sinfo->dev_no | LKBDE_ISR2_DEV | LKBDE_IPROC_REG, + CMICX_IRQ_ENABr, mask, CMICX_TXRX_IRQ_MASK); +} + +static inline void +xgsx_irq_mask_enable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + uint32_t mask; + + if (CDMA_CH(sinfo, chan)) { + mask = CMICX_DS_CMC_CTRLD_INT(chan); + } else { + if (chan == XGS_DMA_TX_CHAN) { + mask = CMICX_DS_CMC_CHAIN_DONE(chan); + } else { + mask = CMICX_DS_CMC_DESC_DONE(chan) | + CMICX_DS_CMC_CHAIN_DONE(chan); + } + } + + sinfo->irq_mask |= mask; + + if (update_hw) { + xgsx_irq_mask_set(sinfo, sinfo->irq_mask); + } +} + +static inline void +xgsx_irq_mask_disable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + uint32_t mask; + + if (CDMA_CH(sinfo, chan)) { + mask = CMICX_DS_CMC_CTRLD_INT(chan); + } else { + if (chan == XGS_DMA_TX_CHAN) { + mask = CMICX_DS_CMC_CHAIN_DONE(chan); + } else { + mask = CMICX_DS_CMC_DESC_DONE(chan) | + CMICX_DS_CMC_CHAIN_DONE(chan); + } + } + + sinfo->irq_mask &= ~mask; + + if (update_hw) { + xgsx_irq_mask_set(sinfo, sinfo->irq_mask); + } +} + +static inline void +dev_dma_chain_clear(bkn_switch_info_t *sinfo, int chan) +{ + if (DEV_IS_CMICX(sinfo)) { + xgsx_dma_chain_clear(sinfo, chan); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_dma_chain_clear(sinfo, chan); + } else { + xgs_dma_chain_clear(sinfo, chan); + } +} + +static inline void +dev_dma_desc_clear(bkn_switch_info_t *sinfo, int chan) +{ + if (DEV_IS_CMICX(sinfo)) { + xgsx_dma_desc_clear(sinfo, chan); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_dma_desc_clear(sinfo, chan); + } else { + xgs_dma_desc_clear(sinfo, chan); + } +} + +static int +dev_dma_chan_clear(bkn_switch_info_t *sinfo, int chan) +{ + if (DEV_IS_CMICX(sinfo)) { + return xgsx_dma_chan_clear(sinfo, chan); + } else if (DEV_IS_CMICM(sinfo)) { + return xgsm_dma_chan_clear(sinfo, chan); + } else { + return xgs_dma_chan_clear(sinfo, chan); + } +} + +static void +dev_cdma_halt_set(bkn_switch_info_t *sinfo, int chan) +{ + if (DEV_IS_CMICX(sinfo)) { + xgsx_cdma_halt_set(sinfo, chan); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_cdma_halt_set(sinfo, chan); + } +} + +static int +dev_dma_chan_init(bkn_switch_info_t *sinfo, int chan, int dir) +{ + if (DEV_IS_CMICX(sinfo)) { + return xgsx_dma_chan_init(sinfo, chan, dir); + } else if (DEV_IS_CMICM(sinfo)) { + return xgsm_dma_chan_init(sinfo, chan, dir); + } else { + return xgs_dma_chan_init(sinfo, chan, dir); + } +} + +static int +dev_dma_chan_start(bkn_switch_info_t *sinfo, int chan, uint64_t dcb) +{ + if (DEV_IS_CMICX(sinfo)) { + return xgsx_dma_chan_start(sinfo, chan, dcb); + } else if (DEV_IS_CMICM(sinfo)) { + return xgsm_dma_chan_start(sinfo, chan, dcb); + } else { + return xgs_dma_chan_start(sinfo, chan, dcb); + } +} + +static int +dev_dma_chan_abort(bkn_switch_info_t *sinfo, int chan, int polls) +{ + if (DEV_IS_CMICX(sinfo)) { + return xgsx_dma_chan_abort(sinfo, chan, polls); + } else if (DEV_IS_CMICM(sinfo)) { + return xgsm_dma_chan_abort(sinfo, chan, polls); + } else { + return xgs_dma_chan_abort(sinfo, chan, polls); + } +} + +static inline void +dev_irq_mask_set(bkn_switch_info_t *sinfo, uint32_t mask) +{ + if (DEV_IS_CMICX(sinfo)) { + xgsx_irq_mask_set(sinfo, mask); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_irq_mask_set(sinfo, mask); + } else { + xgs_irq_mask_set(sinfo, mask); + } +} + +static inline void +dev_irq_mask_enable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + if (DEV_IS_CMICX(sinfo)) { + xgsx_irq_mask_enable(sinfo, chan, update_hw); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_irq_mask_enable(sinfo, chan, update_hw); + } else { + xgs_irq_mask_enable(sinfo, chan, update_hw); + } +} + +static void +dev_irq_mask_disable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + if (DEV_IS_CMICX(sinfo)) { + xgsx_irq_mask_disable(sinfo, chan, update_hw); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_irq_mask_disable(sinfo, chan, update_hw); + } else { + xgs_irq_mask_disable(sinfo, chan, update_hw); + } +} + +static int +bkn_alloc_dcbs(bkn_switch_info_t *sinfo) +{ + int dcb_size; + int tx_ring_size, rx_ring_size; + dma_addr_t dcb_dma = 0; + + dcb_size = sinfo->dcb_wsize * sizeof(uint32_t); + tx_ring_size = dcb_size * (MAX_TX_DCBS + 1); + rx_ring_size = dcb_size * (MAX_RX_DCBS + 1); + sinfo->dcb_mem_size = tx_ring_size + rx_ring_size * sinfo->rx_chans; + + sinfo->dcb_mem = DMA_ALLOC_COHERENT(sinfo->dma_dev, + sinfo->dcb_mem_size, + &dcb_dma); + if (sinfo->dcb_mem == NULL) { + gprintk("DCB memory allocation (%d bytes) failed.\n", + sinfo->dcb_mem_size); + return -ENOMEM; + } + sinfo->dcb_dma = (uint64_t)dcb_dma; + + return 0; +} + +static void +bkn_free_dcbs(bkn_switch_info_t *sinfo) +{ + if (sinfo->dcb_mem != NULL) { + DMA_FREE_COHERENT(sinfo->dma_dev, sinfo->dcb_mem_size, + sinfo->dcb_mem, (dma_addr_t)sinfo->dcb_dma); + sinfo->dcb_mem = NULL; + } +} + +static void +bkn_clean_tx_dcbs(bkn_switch_info_t *sinfo) +{ + bkn_desc_info_t *desc; + + DBG_DCB_TX(("Cleaning Tx DCBs (%d %d).\n", + sinfo->tx.cur, sinfo->tx.dirty)); + while (sinfo->tx.free < MAX_TX_DCBS) { + desc = &sinfo->tx.desc[sinfo->tx.dirty]; + if (desc->skb != NULL) { + DBG_SKB(("Cleaning Tx SKB from DCB %d.\n", + sinfo->tx.dirty)); + DMA_UNMAP_SINGLE(sinfo->dma_dev, + desc->skb_dma, desc->dma_size, + DMA_TODEV); + desc->skb_dma = 0; + dev_kfree_skb_any(desc->skb); + desc->skb = NULL; + } + if (++sinfo->tx.dirty >= MAX_TX_DCBS) { + sinfo->tx.dirty = 0; + } + sinfo->tx.free++; + } + sinfo->tx.api_active = 0; + DBG_DCB_TX(("Cleaned Tx DCBs (%d %d).\n", + sinfo->tx.cur, sinfo->tx.dirty)); +} + +static void +bkn_clean_rx_dcbs(bkn_switch_info_t *sinfo, int chan) +{ + bkn_desc_info_t *desc; + + DBG_DCB_RX(("Cleaning Rx%d DCBs (%d %d).\n", + chan, sinfo->rx[chan].cur, sinfo->rx[chan].dirty)); + while (sinfo->rx[chan].free) { + desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty]; + if (desc->skb != NULL) { + DBG_SKB(("Cleaning Rx%d SKB from DCB %d.\n", + chan, sinfo->rx[chan].dirty)); + DMA_UNMAP_SINGLE(sinfo->dma_dev, + desc->skb_dma, desc->dma_size, + DMA_FROMDEV); + desc->skb_dma = 0; + dev_kfree_skb_any(desc->skb); + desc->skb = NULL; + } + if (++sinfo->rx[chan].dirty >= MAX_RX_DCBS) { + sinfo->rx[chan].dirty = 0; + } + sinfo->rx[chan].free--; + } + sinfo->rx[chan].running = 0; + sinfo->rx[chan].api_active = 0; + sinfo->rx[chan].api_wait = 0; + DBG_DCB_RX(("Cleaned Rx%d DCBs (%d %d).\n", + chan, sinfo->rx[chan].cur, sinfo->rx[chan].dirty)); +} + +static void +bkn_clean_dcbs(bkn_switch_info_t *sinfo) +{ + int chan; + + bkn_clean_tx_dcbs(sinfo); + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + bkn_clean_rx_dcbs(sinfo, chan); + } +} + +static void +bkn_init_dcbs(bkn_switch_info_t *sinfo) +{ + int dcb_size; + uint32_t *dcb_mem; + uint64_t dcb_dma; + bkn_desc_info_t *desc; + int idx; + int chan; + + memset(sinfo->dcb_mem, 0, sinfo->dcb_mem_size); + + dcb_size = sinfo->dcb_wsize * sizeof(uint32_t); + dcb_mem = sinfo->dcb_mem; + dcb_dma = sinfo->dcb_dma; + + for (idx = 0; idx < (MAX_TX_DCBS + 1); idx++) { + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + if (sinfo->cmic_type == 'x') { + dcb_mem[2] |= 1 << 24 | 1 << 16; + } else { + dcb_mem[1] |= 1 << 24 | 1 << 16; + } + if (idx == MAX_TX_DCBS) { + if (sinfo->cmic_type == 'x') { + dcb_mem[0] = sinfo->tx.desc[0].dcb_dma; + dcb_mem[1] = DMA_TO_BUS_HI(sinfo->tx.desc[0].dcb_dma >> 32); + dcb_mem[2] |= 1 << 18; + } else { + dcb_mem[0] = sinfo->tx.desc[0].dcb_dma; + dcb_mem[1] |= 1 << 18; + } + } + } + desc = &sinfo->tx.desc[idx]; + desc->dcb_mem = dcb_mem; + desc->dcb_dma = dcb_dma; + dcb_mem += sinfo->dcb_wsize; + dcb_dma += dcb_size; + } + sinfo->halt_addr[XGS_DMA_TX_CHAN] = sinfo->tx.desc[0].dcb_dma; + sinfo->tx.free = MAX_TX_DCBS; + sinfo->tx.cur = 0; + sinfo->tx.dirty = 0; + + DBG_DCB_TX(("Tx DCBs @ 0x%08x.\n", + (uint32_t)sinfo->tx.desc[0].dcb_dma)); + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + for (idx = 0; idx < (MAX_RX_DCBS + 1); idx++) { + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + if (sinfo->cmic_type == 'x') { + dcb_mem[2] |= 1 << 24 | 1 << 16; + } else { + dcb_mem[1] |= 1 << 24 | 1 << 16; + } + if (idx == MAX_RX_DCBS) { + if (sinfo->cmic_type == 'x') { + dcb_mem[0] = sinfo->rx[chan].desc[0].dcb_dma; + dcb_mem[1] = DMA_TO_BUS_HI(sinfo->rx[chan].desc[0].dcb_dma >> 32); + dcb_mem[2] |= 1 << 18; + } else { + dcb_mem[0] = sinfo->rx[chan].desc[0].dcb_dma; + dcb_mem[1] |= 1 << 18; + } + } + } + desc = &sinfo->rx[chan].desc[idx]; + desc->dcb_mem = dcb_mem; + desc->dcb_dma = dcb_dma; + dcb_mem += sinfo->dcb_wsize; + dcb_dma += dcb_size; + } + sinfo->halt_addr[XGS_DMA_RX_CHAN + chan] = sinfo->rx[chan].desc[MAX_RX_DCBS].dcb_dma; + sinfo->rx[chan].free = 0; + sinfo->rx[chan].cur = 0; + sinfo->rx[chan].dirty = 0; + + DBG_DCB_RX(("Rx%d DCBs @ 0x%08x.\n", + chan, (uint32_t)sinfo->rx[chan].desc[0].dcb_dma)); + } +} + +static void +bkn_dump_dcb(char *prefix, uint32_t *dcb, int wsize, int txrx) +{ + if (XGS_DMA_TX_CHAN == txrx) { + if (wsize > 4) { + DBG_DCB_TX(("%s: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x ... 0x%08x\n", + prefix, dcb[0], dcb[1], dcb[2], dcb[3], dcb[4], dcb[5], + dcb[wsize - 1])); + } else { + DBG_DCB_TX(("%s: 0x%08x 0x%08x 0x%08x 0x%08x\n", + prefix, dcb[0], dcb[1], dcb[2], dcb[3])); + } + } else { + if (wsize > 4) { + DBG_DCB_RX(("%s: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x ... 0x%08x\n", + prefix, dcb[0], dcb[1], dcb[2], dcb[3], dcb[4], dcb[5], + dcb[wsize - 1])); + } else { + DBG_DCB_RX(("%s: 0x%08x 0x%08x 0x%08x 0x%08x\n", + prefix, dcb[0], dcb[1], dcb[2], dcb[3])); + } + } +} + +static void +bkn_dump_pkt(uint8_t *data, int size, int txrx) +{ + int idx; + char str[128]; + + if (!(debug & DBG_LVL_PDMP) && + !(txrx == XGS_DMA_TX_CHAN && debug & DBG_LVL_PDMP_TX) && + !(txrx == XGS_DMA_RX_CHAN && debug & DBG_LVL_PDMP_RX)) { + return; + } + + for (idx = 0; idx < size; idx++) { + if ((idx & 0xf) == 0) { + sprintf(str, "%04x: ", idx); + } + if ((idx & 0xf) == 8) { + sprintf(&str[strlen(str)], "- "); + } + sprintf(&str[strlen(str)], "%02x ", data[idx]); + if ((idx & 0xf) == 0xf) { + sprintf(&str[strlen(str)], "\n"); + gprintk(str); + } + } + if ((idx & 0xf) != 0) { + sprintf(&str[strlen(str)], "\n"); + gprintk(str); + } +} + +static bkn_switch_info_t * +bkn_sinfo_from_unit(int unit) +{ + struct list_head *list; + bkn_switch_info_t *sinfo; + + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + if (sinfo->dev_no == unit || unit == -1) { + return sinfo; + } + } + return NULL; +} + +static void +bkn_cdma_goto(bkn_switch_info_t *sinfo, int chan, uint64_t dcb) +{ + if (sinfo->basedev_suspended) { + return; + } + + /* Set the new halt location */ + sinfo->halt_addr[chan] = dcb; + dev_cdma_halt_set(sinfo, chan); +} + +static void +bkn_api_rx_restart(bkn_switch_info_t *sinfo, int chan) +{ + bkn_dcb_chain_t *dcb_chain; + int start_dma; + + if (sinfo->basedev_suspended) { + return; + } + + /* If resume from basedev suspended, there could be a suspended chain */ + if (sinfo->rx[chan].api_dcb_chain) { + return; + } + + /* Assume that driver lock is held */ + if (!list_empty(&sinfo->rx[chan].api_dcb_list)) { + dcb_chain = list_entry(sinfo->rx[chan].api_dcb_list.next, + bkn_dcb_chain_t, list); + start_dma = 0; + if (sinfo->rx[chan].use_rx_skb == 0) { + sinfo->rx[chan].chain_complete = 0; + start_dma = 1; + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) && + sinfo->rx[chan].api_wait) { + /* HW is running already, so we just move to the next chain */ + start_dma = 0; + } + } + sinfo->rx[chan].api_dcb_chain = dcb_chain; + sinfo->rx[chan].api_active = 1; + if (start_dma) { + DBG_DCB_RX(("Start API Rx DMA, first DCB @ 0x%08x (%d DCBs).\n", + (uint32_t)dcb_chain->dcb_dma, dcb_chain->dcb_cnt)); + dev_dma_chan_clear(sinfo, XGS_DMA_RX_CHAN + chan); + dev_irq_mask_enable(sinfo, XGS_DMA_RX_CHAN + chan, 1); + dev_dma_chan_start(sinfo, XGS_DMA_RX_CHAN + chan, dcb_chain->dcb_dma); + sinfo->rx[chan].api_wait = 1; + } + + list_del(&dcb_chain->list); + } +} + +static void +bkn_api_rx_chain_done(bkn_switch_info_t *sinfo, int chan) +{ + DBG_DCB_RX(("API Rx DMA chain done\n")); + + if (!CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + sinfo->rx[chan].api_active = 0; + } + if (sinfo->rx[chan].api_dcb_chain) { + kfree(sinfo->rx[chan].api_dcb_chain); + sinfo->rx[chan].api_dcb_chain = NULL; + } + bkn_api_rx_restart(sinfo, chan); + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) && + sinfo->rx[chan].api_dcb_chain == NULL) { + sinfo->rx[chan].api_active = 0; + } +} + +static int +bkn_api_rx_copy_from_skb(bkn_switch_info_t *sinfo, + int chan, bkn_desc_info_t *desc) +{ + bkn_dcb_chain_t *dcb_chain; + uint32_t *dcb; + uint32_t dcb_stat; + uint8_t *pkt; + uint64_t pkt_dma; + int pktlen; + int i; + bkn_evt_resource_t *evt; + + dcb_stat = desc->dcb_mem[sinfo->dcb_wsize-1]; + pktlen = dcb_stat & SOC_DCB_KNET_COUNT_MASK; + + dcb_chain = sinfo->rx[chan].api_dcb_chain; + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) && dcb_chain == NULL) { + /* Last chain done, try to get a new one */ + bkn_api_rx_chain_done(sinfo, chan); + dcb_chain = sinfo->rx[chan].api_dcb_chain; + } + if (dcb_chain == NULL) { + DBG_WARN(("No Rx API buffers\n")); + sinfo->rx[chan].pkts_d_no_api_buf++; + return -1; + } + dcb = &dcb_chain->dcb_mem[dcb_chain->dcb_cur * sinfo->dcb_wsize]; + if ((sinfo->cmic_type == 'x' && (dcb[2] & 0xffff) < pktlen) || + (sinfo->cmic_type != 'x' && (dcb[1] & 0xffff) < pktlen)) { + DBG_WARN(("Rx API buffer too small\n")); + return -1; + } + if (sinfo->cmic_type == 'x') { + pkt_dma = BUS_TO_DMA_HI(dcb[1]); + pkt_dma = pkt_dma << 32 | dcb[0]; + } else { + pkt_dma = dcb[0]; + } + pkt = (uint8_t *)kernel_bde->p2l(sinfo->dev_no, (sal_paddr_t)pkt_dma); + if (pkt == NULL) { + DBG_WARN(("Invalid Rx API buffer\n")); + return -1; + } + + /* Copy packet data */ + memcpy(pkt, desc->skb->data, pktlen); + + /* Copy packet metadata and mark as done */ + if (sinfo->cmic_type != 'x') { + for (i = SOC_DCB_META_OFFSET; i < sinfo->dcb_wsize; i++) { + dcb[i] = desc->dcb_mem[i]; + } + } + dcb[sinfo->dcb_wsize-1] = dcb_stat | SOC_DCB_KNET_DONE; + + dcb_chain->dcb_cur++; + + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + dcb = &dcb_chain->dcb_mem[dcb_chain->dcb_cur * sinfo->dcb_wsize]; + if ((sinfo->cmic_type == 'x' && dcb[2] & (1 << 18)) || + (sinfo->cmic_type != 'x' && dcb[1] & (1 << 18))) { + /* Get the next chain if reload done */ + dcb[sinfo->dcb_wsize-1] |= 1 << 31 | SOC_DCB_KNET_DONE; + bkn_api_rx_chain_done(sinfo, chan); + dcb_chain = sinfo->rx[chan].api_dcb_chain; + if (dcb_chain == NULL) { + sinfo->rx[chan].api_dcb_chain_end = NULL; + } + } + } else { + if ((sinfo->cmic_type == 'x' && (dcb[2] & (1 << 16)) == 0) || + (sinfo->cmic_type != 'x' && (dcb[1] & (1 << 16)) == 0)) { + bkn_api_rx_chain_done(sinfo, chan); + } + } + + sinfo->dma_events |= KCOM_DMA_INFO_F_RX_DONE; + + evt = &_bkn_evt[sinfo->evt_idx]; + evt->evt_wq_put++; + wake_up_interruptible(&evt->evt_wq); + + return 0; +} + +static void +bkn_rx_refill(bkn_switch_info_t *sinfo, int chan) +{ + struct sk_buff *skb; + bkn_desc_info_t *desc; + uint32_t *dcb; + uint32_t encap_size = sinfo->cmic_type == 'x' ? RCPU_HDR_SIZE : RCPU_RX_ENCAP_SIZE; + int prev; + + if (sinfo->rx[chan].use_rx_skb == 0) { + /* Rx buffers are provided by BCM Rx API */ + return; + } + + if (!CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) && + sinfo->rx[chan].tokens < MAX_RX_DCBS) { + /* Pause DMA for now */ + return; + } + + while (sinfo->rx[chan].free < MAX_RX_DCBS) { + desc = &sinfo->rx[chan].desc[sinfo->rx[chan].cur]; + if (desc->skb == NULL) { + skb = dev_alloc_skb(rx_buffer_size + encap_size); + if (skb == NULL) { + break; + } + skb_reserve(skb, encap_size); + desc->skb = skb; + } else { + DBG_DCB_RX(("Refill Rx%d SKB in DCB %d recycled.\n", + chan, sinfo->rx[chan].cur)); + } + skb = desc->skb; + desc->dma_size = rx_buffer_size; +#ifdef KNET_NO_AXI_DMA_INVAL + /* + * FIXME: Need to retain this code until iProc customers have been + * migrated to updated u-boot. Old u-boot versions are unable to load + * the kernel into non-ACP memory. + */ + /* + * Cache invalidate may corrupt DMA memory on some iProc-based devices + * if the kernel is mapped to ACP memory. + */ + if (sinfo->pdev == NULL) { + desc->dma_size = 0; + } +#endif + desc->skb_dma = DMA_MAP_SINGLE(sinfo->dma_dev, + skb->data, desc->dma_size, + DMA_FROMDEV); + if (DMA_MAPPING_ERROR(sinfo->dma_dev, desc->skb_dma)) { + dev_kfree_skb_any(skb); + desc->skb = NULL; + break; + } + DBG_DCB_RX(("Refill Rx%d DCB %d (0x%08x).\n", + chan, sinfo->rx[chan].cur, (uint32_t)desc->skb_dma)); + dcb = desc->dcb_mem; + dcb[0] = desc->skb_dma; + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + if (sinfo->cmic_type == 'x') { + dcb[2] |= 1 << 24 | 1 << 16; + } else { + dcb[1] |= 1 << 24 | 1 << 16; + } + } else { + prev = PREV_IDX(sinfo->rx[chan].cur, MAX_RX_DCBS); + if (prev < (MAX_RX_DCBS - 1)) { + if (sinfo->cmic_type == 'x') { + sinfo->rx[chan].desc[prev].dcb_mem[2] |= 1 << 16; + } else { + sinfo->rx[chan].desc[prev].dcb_mem[1] |= 1 << 16; + } + } + } + if (sinfo->cmic_type == 'x') { + dcb[1] = DMA_TO_BUS_HI(desc->skb_dma >> 32); + dcb[2] |= rx_buffer_size; + } else { + dcb[1] |= rx_buffer_size; + } + + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) && + sinfo->rx[chan].tokens > MAX_RX_DCBS) { + /* DMA run to the new halt location */ + bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, desc->dcb_dma); + } + + if (++sinfo->rx[chan].cur >= MAX_RX_DCBS) { + sinfo->rx[chan].cur = 0; + } + sinfo->rx[chan].free++; + sinfo->rx[chan].tokens--; + } +} + +static int +bkn_rx_restart(bkn_switch_info_t *sinfo, int chan) +{ + bkn_desc_info_t *desc; + + if (sinfo->basedev_suspended) { + return 0; + } + + if (sinfo->rx[chan].running) { + return 0; + } + + if (sinfo->rx[chan].free < MAX_RX_DCBS) { + return 1; + } + + desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty]; + sinfo->rx[chan].chain_complete = 0; + DBG_DCB_RX(("Restart Rx%d DMA, DCB @ 0x%08x (%d).\n", + chan, (uint32_t)desc->dcb_dma, sinfo->rx[chan].dirty)); + dev_dma_chan_clear(sinfo, XGS_DMA_RX_CHAN + chan); + dev_irq_mask_enable(sinfo, XGS_DMA_RX_CHAN + chan, 1); + dev_dma_chan_start(sinfo, XGS_DMA_RX_CHAN + chan, desc->dcb_dma); + sinfo->rx[chan].running = 1; + + /* Request one extra poll if chain was restarted during poll */ + if (sinfo->napi_poll_mode) { + sinfo->napi_poll_again = 1; + } + + return 0; +} + +static int +bkn_tx_dma_start(bkn_switch_info_t *sinfo) +{ + bkn_desc_info_t *desc; + + desc = &sinfo->tx.desc[sinfo->tx.cur]; + if (sinfo->tx.free == MAX_TX_DCBS) { + if (!sinfo->tx.api_active) { + DBG_DCB_TX(("Start Tx DMA, DCB @ 0x%08x (%d).\n", + (uint32_t)desc->dcb_dma, sinfo->tx.cur)); + dev_dma_chan_clear(sinfo, XGS_DMA_TX_CHAN); + dev_irq_mask_enable(sinfo, XGS_DMA_TX_CHAN, 1); + dev_dma_chan_start(sinfo, XGS_DMA_TX_CHAN, desc->dcb_dma); + } + } + + return 0; +} + +static int +bkn_dma_init(bkn_switch_info_t *sinfo) +{ + int chan; + + dev_dma_chan_init(sinfo, XGS_DMA_TX_CHAN, 1); + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + bkn_tx_dma_start(sinfo); + } + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + dev_dma_chan_init(sinfo, XGS_DMA_RX_CHAN + chan, 0); + bkn_rx_refill(sinfo, chan); + bkn_rx_restart(sinfo, chan); + } + + return 0; +} + +static int +bkn_dma_abort_tx(bkn_switch_info_t *sinfo) +{ + bkn_dcb_chain_t *dcb_chain; + + DBG_VERB(("Aborting Tx DMA.\n")); + + dev_irq_mask_disable(sinfo, XGS_DMA_TX_CHAN, 1); + + dev_dma_chan_abort(sinfo, XGS_DMA_TX_CHAN, 10000); + + if (sinfo->tx.api_dcb_chain) { + DBG_DCB_TX(("Freeing active Tx DCB chain.\n")); + kfree(sinfo->tx.api_dcb_chain); + sinfo->tx.api_dcb_chain = NULL; + } + while (!list_empty(&sinfo->tx.api_dcb_list)) { + dcb_chain = list_entry(sinfo->tx.api_dcb_list.next, + bkn_dcb_chain_t, list); + list_del(&dcb_chain->list); + DBG_DCB_TX(("Freeing Tx DCB chain.\n")); + kfree(dcb_chain); + } + sinfo->tx.api_dcb_chain_end = NULL; + + return 0; +} + +static int +bkn_dma_abort_rx(bkn_switch_info_t *sinfo, int chan) +{ + bkn_dcb_chain_t *dcb_chain; + + DBG_VERB(("Aborting Rx%d DMA.\n", chan)); + + dev_irq_mask_disable(sinfo, XGS_DMA_RX_CHAN + chan, 1); + + dev_dma_chan_abort(sinfo, XGS_DMA_RX_CHAN + chan, 10000); + + if (sinfo->rx[chan].api_dcb_chain) { + DBG_DCB_RX(("Freeing active Rx%d DCB chain.\n", chan)); + kfree(sinfo->rx[chan].api_dcb_chain); + sinfo->rx[chan].api_dcb_chain = NULL; + } + while (!list_empty(&sinfo->rx[chan].api_dcb_list)) { + dcb_chain = list_entry(sinfo->rx[chan].api_dcb_list.next, + bkn_dcb_chain_t, list); + list_del(&dcb_chain->list); + DBG_DCB_RX(("Freeing Rx%d DCB chain.\n", chan)); + kfree(dcb_chain); + } + sinfo->rx[chan].api_dcb_chain_end = NULL; + + return 0; +} + +static int +bkn_dma_abort(bkn_switch_info_t *sinfo) +{ + int chan; + + bkn_dma_abort_tx(sinfo); + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + bkn_dma_abort_rx(sinfo, chan); + } + + return 0; +} + +static bkn_filter_t * +bkn_match_rx_pkt(bkn_switch_info_t *sinfo, uint8_t *pkt, int pktlen, + void *meta, int chan, bkn_filter_t *cbf) +{ + struct list_head *list; + bkn_filter_t *filter; + kcom_filter_t scratch, *kf; + uint8_t *oob = (uint8_t *)meta; + int size, wsize; + int idx, match; + + list_for_each(list, &sinfo->rxpf_list) { + filter = (bkn_filter_t *)list; + kf = &filter->kf; + memcpy(&scratch.data.b[0], + &oob[kf->oob_data_offset], kf->oob_data_size); + memcpy(&scratch.data.b[kf->oob_data_size], + &pkt[kf->pkt_data_offset], kf->pkt_data_size); + size = kf->oob_data_size + kf->pkt_data_size; + wsize = BYTES2WORDS(size); + DBG_VERB(("Filter: size = %d (%d), data = 0x%08x, mask = 0x%08x\n", + size, wsize, kf->data.w[0], kf->mask.w[0])); + match = 1; + if (match) { + if (kf->priority < (num_rx_prio * sinfo->rx_chans)) { + if (kf->priority < (num_rx_prio * chan) || + kf->priority >= (num_rx_prio * (chan + 1))) { + match = 0; + } + } + } + if (match) { + for (idx = 0; idx < wsize; idx++) { + scratch.data.w[idx] &= kf->mask.w[idx]; + if (scratch.data.w[idx] != kf->data.w[idx]) { + match = 0; + break; + } + } + } + if (match) { + if (kf->dest_type == KCOM_DEST_T_CB) { + /* Check for custom filters */ + if (knet_filter_cb != NULL && cbf != NULL) { + memset(cbf, 0, sizeof(*cbf)); + memcpy(&cbf->kf, kf, sizeof(cbf->kf)); + if (knet_filter_cb(pkt, pktlen, sinfo->dev_no, + meta, chan, &cbf->kf)) { + filter->hits++; + return cbf; + } + } else { + DBG_FLTR(("Match, but not filter callback\n")); + } + } else { + filter->hits++; + return filter; + } + } + } + + return NULL; +} + +static bkn_priv_t * +bkn_netif_lookup(bkn_switch_info_t *sinfo, int id) +{ + struct list_head *list; + bkn_priv_t *priv; + int found; + + /* Fast path */ + if (id < sinfo->ndev_max) { + if (sinfo->ndevs[id] != NULL) { + DBG_NDEV(("Look up netif ID %d successful\n", id)); + return netdev_priv(sinfo->ndevs[id]); + } + } + + /* Slow path - should normally not get here */ + found = 0; + priv = NULL; + list_for_each(list, &sinfo->ndev_list) { + priv = (bkn_priv_t *)list; + if (priv->id == id) { + found = 1; + break; + } + } + if (found && priv != NULL) { + return priv; + } + return NULL; +} + +static int +bkn_add_rcpu_encap(bkn_switch_info_t *sinfo, struct sk_buff *skb, void *meta) +{ + int pktlen = skb->len; + uint32_t *dmeta, *smeta, wsize, psize; + int idx; + + /* Add and clear RCPU encapsulation */ + if (sinfo->cmic_type == 'x') { + psize = RCPU_HDR_SIZE + sinfo->pkt_hdr_size; + skb_push(skb, psize); + memset(skb->data, 0, RCPU_HDR_SIZE); + } else { + psize = RCPU_RX_ENCAP_SIZE; + skb_push(skb, psize); + memset(skb->data, 0, RCPU_RX_ENCAP_SIZE); + } + + /* RCPU Header */ + memcpy(skb->data, &skb->data[psize], 12); + if (rcpu_dmac != NULL) { + memcpy(skb->data, bkn_rcpu_dmac, 6); + } + if (rcpu_smac != NULL) { + memcpy(&skb->data[6], bkn_rcpu_smac, 6); + } + skb->data[12] = 0x81; + skb->data[14] = rcpu_vlan >> 8; + skb->data[15] = rcpu_vlan & 0xff; + skb->data[16] = rcpu_ethertype >> 8; + skb->data[17] = rcpu_ethertype & 0xff; + skb->data[18] = sinfo->rcpu_sig >> 8; + skb->data[19] = sinfo->rcpu_sig & 0xff; + skb->data[20] = RCPU_OPCODE_RX; + skb->data[21] = RCPU_F_MODHDR; + skb->data[24] = pktlen >> 8; + skb->data[25] = pktlen & 0xff; + + /* Meta data */ + dmeta = (uint32_t *)&skb->data[RCPU_HDR_SIZE]; + smeta = sinfo->cmic_type == 'x' ? (uint32_t *)meta : (uint32_t *)meta + 2; + wsize = sinfo->cmic_type == 'x' ? sinfo->pkt_hdr_size / 4 : sinfo->dcb_wsize - 3; + for (idx = 0; idx < wsize; idx++) { + dmeta[idx] = htonl(smeta[idx]); + } + + return 0; +} + +static void +bkn_eth_type_update(struct sk_buff *skb, int ethertype) +{ +#if defined(PM_ETH_TYPE) && defined(PM_FC_TYPE) + /* Optionally override standard protocol */ + skb->protocol = PM_ETH_TYPE; + if (ethertype == ETH_P_FCOE) { + skb->protocol = PM_FC_TYPE; + } +#endif +} + +#define BKN_DNX_BIT(x) (1<<(x)) +#define BKN_DNX_RBIT(x) (~(1<<(x))) +#ifdef __LITTLE_ENDIAN +#define BKN_DNX_BYTE_SWAP(x) (x) +#else +#define BKN_DNX_BYTE_SWAP(x) ((((x) << 24)) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) >> 24))) +#endif + +static int +device_is_dune(bkn_switch_info_t *sinfo) +{ + int is_dune = 0; + + is_dune = (sinfo->dcb_type == 28) ? 1 : 0; + return is_dune; +} + +static int +packet_is_untagged(uint16_t tpid) +{ + int is_untagged = 0; + + /* Fixme SDK-111398 */ + /* 0x8100 is used in 802.1Q */ + /* 0x8848 is used in 802.11ad, the dtag tpid can be set to anything besides 0x8848, 0x9100 is a typical value, but couldn't cover all scenarios. */ + is_untagged = ((tpid != 0x8100) && (tpid != 0x8848) && (tpid != 0x9100)); + return is_untagged; +} + +static void +bkn_dnx_bitstream_set_field(uint32_t *input_buffer, uint32_t start_bit, uint32_t nof_bits, uint32_t field) +{ + uint32_t place; + uint32_t field_bit_i; + uint32_t bit_indicator; + + if( nof_bits > 32) + { + return; + } + + for( place=start_bit, field_bit_i = 0; field_bit_i< nof_bits; ++place, ++field_bit_i) + { + bit_indicator = field & BKN_DNX_BIT(nof_bits-field_bit_i-1); + if(bit_indicator) + { + input_buffer[place>>5] |= (0x80000000 >> (place & 0x0000001F)); + } + else + { + input_buffer[place>>5] &= ~(0x80000000 >> (place & 0x0000001F)); + } + } + return; +} + +static void +bkn_dnx_bitstream_get_field(uint8_t *input_buffer, uint32_t start_bit, uint32_t nof_bits, uint32_t *output_value) +{ + uint32_t idx; + uint32_t buf_sizes=0; + uint32_t tmp_output_value[2]={0}; + uint32_t first_byte_ndx; + uint32_t last_byte_ndx; + uint32_t place; + uint32_t field_bit_i; + uint8_t *tmp_output_value_u8_ptr = (uint8_t*)&tmp_output_value; + uint32_t bit_indicator; + + if (nof_bits > 32) + { + return; + } + + first_byte_ndx = start_bit / 8; + last_byte_ndx = ((start_bit + nof_bits - 1) / 8); + *output_value=0; + + /* get 32 bit value, MSB */ + for (idx = first_byte_ndx; idx <= last_byte_ndx; ++idx) + { + tmp_output_value_u8_ptr[last_byte_ndx - idx] = input_buffer[idx]; + buf_sizes += 8; + } + tmp_output_value[0] = BKN_DNX_BYTE_SWAP(tmp_output_value[0]); + if (last_byte_ndx > 4) + { + tmp_output_value[1] = BKN_DNX_BYTE_SWAP(tmp_output_value[1]); + } + + place = buf_sizes - (start_bit % 8 + nof_bits); + for (field_bit_i = 0; field_bit_i< nof_bits; ++place, ++field_bit_i) + { + uint32_t result; + result = tmp_output_value[place>>5] & BKN_DNX_BIT(place & 0x0000001F); + if (result) + { + bit_indicator = 1; + } else { + bit_indicator = 0; + } + *output_value |= bit_indicator << field_bit_i; + } + return; +} + +static void +bkn_dnx_packet_parse_ftmh(bkn_switch_info_t *sinfo, uint8_t hdr_buff[], bkn_dnx_packet_info *packet_info) +{ + uint32_t header_ptr = 0; + uint32_t dsp_ext_exist=0; + uint32_t fld_val; + + header_ptr = packet_info->ntwrk_header_ptr; + + /* Packet-size */ + bkn_dnx_bitstream_get_field( + &hdr_buff[header_ptr], + BKN_DNX_FTMH_PKT_SIZE_MSB, + BKN_DNX_FTMH_PKT_SIZE_NOF_BITS, + &fld_val); + packet_info->ftmh.packet_size = fld_val; + /* Traffic-class */ + bkn_dnx_bitstream_get_field( + &hdr_buff[header_ptr], + BKN_DNX_FTMH_TC_MSB, + BKN_DNX_FTMH_TC_NOF_BITS, + &fld_val); + packet_info->ftmh.prio = fld_val; + /* Source-system-port-aggregate */ + bkn_dnx_bitstream_get_field( + &hdr_buff[header_ptr], + BKN_DNX_FTMH_SRC_SYS_PORT_MSB, + BKN_DNX_FTMH_SRC_SYS_PORT_NOF_BITS, + &fld_val); + packet_info->ftmh.src_sys_port = fld_val; + /* TM-action-type */ + bkn_dnx_bitstream_get_field( + &hdr_buff[header_ptr], + BKN_DNX_FTMH_ACTION_TYPE_MSB, + BKN_DNX_FTMH_ACTION_TYPE_NOF_BITS, + &fld_val); + packet_info->ftmh.action_type = fld_val; + /* PPH-type */ + bkn_dnx_bitstream_get_field( + &hdr_buff[header_ptr], + BKN_DNX_FTMH_PPH_TYPE_MSB, + BKN_DNX_FTMH_PPH_TYPE_NOF_BITS, + &fld_val); + packet_info->ftmh.pph_type = fld_val; + + packet_info->ntwrk_header_ptr += BKN_DNX_FTMH_SIZE_BYTE; + DBG_DUNE(("FTMH(%d) Packet-size %d Action-type %d PPH-type %d Source-system-port 0x%x Traffic-class %d\n", + packet_info->ntwrk_header_ptr, packet_info->ftmh.packet_size, packet_info->ftmh.action_type, + packet_info->ftmh.pph_type, packet_info->ftmh.src_sys_port, packet_info->ftmh.prio)); + + /* LB-Key ext */ + if ((sinfo->pkt_hdr_size & BKN_DNX_FTMH_LB_EXT_EN) == BKN_DNX_FTMH_LB_EXT_EN) + { + packet_info->ntwrk_header_ptr += BKN_DNX_FTMH_LB_EXT_SIZE_BYTE; + DBG_DUNE(("FTMH(%d) FTMH LB-Key Extension is present\n", packet_info->ntwrk_header_ptr)); + } + /* DSP ext*/ + fld_val = 0; + bkn_dnx_bitstream_get_field( + &hdr_buff[header_ptr], + BKN_DNX_FTMH_EXT_DSP_EXIST_MSB, + BKN_DNX_FTMH_EXT_DSP_EXIST_NOF_BITS, + &dsp_ext_exist); + if (dsp_ext_exist) + { + packet_info->ntwrk_header_ptr += BKN_DNX_FTMH_DEST_EXT_SIZE_BYTE; + DBG_DUNE(("FTMH(%d) DSP-extension-present 1\n", packet_info->ntwrk_header_ptr)); + } + + /* stacking ext */ + if ((sinfo->pkt_hdr_size & BKN_DNX_FTMH_STACKING_EXT_EN) == BKN_DNX_FTMH_STACKING_EXT_EN) + { + packet_info->ntwrk_header_ptr += BKN_DNX_FTMH_STACKING_SIZE_BYTE; + DBG_DUNE(("FTMH(%d) FTMH Stacking Extension is present\n", packet_info->ntwrk_header_ptr)); + } + return; +} + +static void +bkn_dnx_packet_parse_internal(bkn_switch_info_t *sinfo, uint8_t hdr_buff[], bkn_dnx_packet_info *packet_info) +{ + uint32_t header_ptr = 0; + uint32_t fld_val; + uint32_t eei_extension_present = 0; + uint32_t learn_extension_present = 0; + uint32_t fhei_size = 0; + uint32_t forward_code; + uint8_t is_trapped = 0; + + header_ptr = packet_info->ntwrk_header_ptr; + + bkn_dnx_bitstream_get_field( + &hdr_buff[header_ptr], + BKN_DNX_PPH_EEI_EXTENSION_PRESENT_MSB, + BKN_DNX_PPH_EEI_EXTENSION_PRESENT_NOF_BITS, + &eei_extension_present); + bkn_dnx_bitstream_get_field( + &hdr_buff[header_ptr], + BKN_DNX_PPH_LEARN_EXENSION_PRESENT_MSB, + BKN_DNX_PPH_LEARN_EXENSION_PRESENT_NOF_BITS, + &learn_extension_present); + bkn_dnx_bitstream_get_field( + &hdr_buff[header_ptr], + BKN_DNX_PPH_FHEI_SIZE_MSB, + BKN_DNX_PPH_FHEI_SIZE_NOF_BITS, + &fhei_size); + bkn_dnx_bitstream_get_field( + &hdr_buff[header_ptr], + BKN_DNX_PPH_FORWARD_CODE_MSB, + BKN_DNX_PPH_FORWARD_CODE_NOF_BITS, + &forward_code); + /* 7: CPU-Trap */ + is_trapped = (uint8_t)(forward_code == 7); + + bkn_dnx_bitstream_get_field( + &hdr_buff[header_ptr], + BKN_DNX_PPH_VSI_MSB, + BKN_DNX_PPH_VSI_NOF_BITS, + &fld_val); + packet_info->internal.vsi = fld_val; + + /* size of PPH base is 7 */ + packet_info->ntwrk_header_ptr += BKN_DNX_PPH_SIZE_BYTE; + header_ptr = packet_info->ntwrk_header_ptr; + + DBG_DUNE(("PPH(%d) Forward-Code %d EEI-Extension %d Learn-Extension %d VSI %d FHEI-size %d\n", packet_info->ntwrk_header_ptr, + forward_code, eei_extension_present, learn_extension_present, packet_info->internal.vsi, fhei_size)); + + /* PPH extension */ + if (is_trapped && (fhei_size == 1)) + { + /* CPU trap code qualifier */ + bkn_dnx_bitstream_get_field( + &hdr_buff[header_ptr], + BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_MSB, + BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_NOF_BITS, + &fld_val); + packet_info->internal.trap_qualifier = fld_val; + /* CPU trap code */ + bkn_dnx_bitstream_get_field( + &hdr_buff[header_ptr], + BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_MSB, + BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_NOF_BITS, + &fld_val); + packet_info->internal.trap_id = fld_val; + } + switch(fhei_size) { + case 1: + packet_info->ntwrk_header_ptr += BKN_DNX_PPH_FHEI_3B_SIZE_BYTE; + break; + case 2: + packet_info->ntwrk_header_ptr += BKN_DNX_PPH_FHEI_5B_SIZE_BYTE; + break; + case 3: + packet_info->ntwrk_header_ptr += BKN_DNX_PPH_FHEI_8B_SIZE_BYTE; + break; + default: + break; + } + if (eei_extension_present) { + packet_info->ntwrk_header_ptr += BKN_DNX_PPH_EXPLICIT_EDITING_INFOMATION_EXTENSION_SIZE_BYTE; + } + if (learn_extension_present) { + packet_info->ntwrk_header_ptr += BKN_DNX_PPH_LEARN_EXTENSION_SIZE_BYTE; + } + + DBG_DUNE(("FHEI(%d) trap_qualifier 0x%x trap_id 0x%x\n", packet_info->ntwrk_header_ptr, packet_info->internal.trap_qualifier, packet_info->internal.trap_id)); + return; +} + +static int +bkn_dnx_packet_header_parse(bkn_switch_info_t *sinfo, uint8 *buff, uint32_t buff_len, bkn_dnx_packet_info *packet_info) +{ + uint8_t hdr_buff[BKN_DNX_HDR_MAX_SIZE]; + uint32_t hdr_size; + uint8_t has_internal = 0; + + if ((buff == NULL) || (packet_info == NULL)) { + return -1; + } + hdr_size = buff_len < BKN_DNX_HDR_MAX_SIZE ? buff_len: BKN_DNX_HDR_MAX_SIZE; + memcpy(hdr_buff, buff, hdr_size); + + /* FTMH */ + bkn_dnx_packet_parse_ftmh(sinfo, hdr_buff, packet_info); + if (packet_info->ftmh.packet_size != (buff_len + 2)) { + DBG_DUNE(("FTMH packet size verfication failed, %d-%d\n", packet_info->ftmh.packet_size, buff_len)); + memset(packet_info, 0, sizeof(bkn_dnx_packet_info)); + return -1; + } + switch (packet_info->ftmh.pph_type) { + case 0: + has_internal = 0; + break; + case 1: + has_internal = 1; + break; + case 2: /* PPH OAM-TS only */ + case 3: /* PPH Base + OAM-TS */ + /* OTSH immediately follows the FTMH when present */ + packet_info->ntwrk_header_ptr += 6; + DBG_DUNE(("FTMH + OAM-TS(%d)\n", packet_info->ntwrk_header_ptr)); + has_internal = 1; + break; + default: + break; + } + + if (has_internal) { + bkn_dnx_packet_parse_internal(sinfo, &hdr_buff[0], packet_info); + } + + /* FIXME: */ + /* ignore packets with a double set of FTMH,internals */ + /* ignore the user header size */ + return 0; +} + +static int +bkn_do_api_rx(bkn_switch_info_t *sinfo, int chan, int budget) +{ + bkn_priv_t *priv; + bkn_dcb_chain_t *dcb_chain; + struct sk_buff *skb; + bkn_filter_t cbf; + bkn_filter_t *filter; + uint32_t err_woff; + uint32_t *dcb, *meta; + uint8_t *pkt; + uint64_t pkt_dma; + int drop_api; + int ethertype; + int pktlen; + int idx; + int dcbs_done = 0; + bkn_dnx_packet_info packet_info = {0}; + + dcb_chain = sinfo->rx[chan].api_dcb_chain; + if (dcb_chain == NULL) { + /* No active chains */ + return 0; + } + + while (dcb_chain->dcb_cur < dcb_chain->dcb_cnt) { + dcb = &dcb_chain->dcb_mem[dcb_chain->dcb_cur * sinfo->dcb_wsize]; + DBG_VERB(("DCB %2d: 0x%08x\n", + dcb_chain->dcb_cur, dcb[sinfo->dcb_wsize-1])); + if ((dcb[sinfo->dcb_wsize-1] & (1 << 31)) == 0) { + break; + } + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + /* Handle for Continuous DMA mode */ + if (dcbs_done >= budget) { + break; + } + if ((sinfo->cmic_type == 'x' && dcb[2] & (1 << 18)) || + (sinfo->cmic_type != 'x' && dcb[1] & (1 << 18))) { + dcb[sinfo->dcb_wsize-1] |= SOC_DCB_KNET_DONE; + bkn_api_rx_chain_done(sinfo, chan); + dcb_chain = sinfo->rx[chan].api_dcb_chain; + if (dcb_chain == NULL) { + break; + } + continue; + } + } + if ((sinfo->cmic_type == 'x' && (dcb[2] & (1 << 16)) == 0) || + (sinfo->cmic_type != 'x' && (dcb[1] & (1 << 16)) == 0)) { + sinfo->rx[chan].chain_complete = 1; + } + sinfo->rx[chan].pkts++; + if (sinfo->cmic_type == 'x') { + pkt_dma = BUS_TO_DMA_HI(dcb[1]); + pkt_dma = pkt_dma << 32 | dcb[0]; + } else { + pkt_dma = dcb[0]; + } + pkt = (uint8_t *)kernel_bde->p2l(sinfo->dev_no, (sal_paddr_t)pkt_dma); + if (sinfo->cmic_type == 'x') { + meta = (uint32_t *)pkt; + err_woff = sinfo->pkt_hdr_size / sizeof(uint32_t) - 1; + meta[err_woff] = dcb[sinfo->dcb_wsize-1]; + } else { + meta = dcb; + err_woff = sinfo->dcb_wsize - 1; + } + pktlen = dcb[sinfo->dcb_wsize-1] & SOC_DCB_KNET_COUNT_MASK; + bkn_dump_pkt(pkt, pktlen, XGS_DMA_RX_CHAN); + + if (device_is_dune(sinfo)) { + uint16_t tpid = 0; + uint16_t vid = 0; + int res = -1; + + memset(&packet_info, 0, sizeof(bkn_dnx_packet_info)); + res = bkn_dnx_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info); + if (res == 0) { + if (packet_info.ftmh.action_type == 0x2) { + bkn_dnx_bitstream_set_field((uint32_t *)dcb, 192, 32, 0x8); + } else if (packet_info.ftmh.action_type == 0x1) { + bkn_dnx_bitstream_set_field((uint32_t *)dcb, 231, 25, 0x20); + } + bkn_dnx_bitstream_set_field((uint32_t *)dcb, 112, 16, packet_info.ftmh.src_sys_port); + bkn_dnx_bitstream_set_field((uint32_t *)dcb, 296, 12, packet_info.internal.vsi); + bkn_dnx_bitstream_set_field((uint32_t *)dcb, 64, 32, (packet_info.internal.trap_id << 16 | packet_info.internal.trap_qualifier)); + pkt += packet_info.ntwrk_header_ptr; + pktlen -= packet_info.ntwrk_header_ptr; + bkn_dump_pkt(pkt, 32, XGS_DMA_RX_CHAN); + /* check if vlan tag exists */ + tpid = (uint16_t)((pkt[12] << 8) | pkt[13]); + vid = (uint16_t)(packet_info.internal.vsi & 0xfff); + if (packet_is_untagged(tpid)) { + if ((pktlen + 4) < rx_buffer_size) { + DBG_DUNE(("add vlan tag (%d) to untagged packets\n", vid)); + for (idx = (pktlen-1); idx >= 12; idx--) { + pkt[idx+4] = pkt[idx]; + } + pkt[12] = 0x81; + pkt[13] = 0x00; + pkt[14] = (vid >> 8); + pkt[15] = (vid & 0xff); + /* reset packet length in DCB */ + pktlen += 4; + dcb[sinfo->dcb_wsize-1] &= ~SOC_DCB_KNET_COUNT_MASK; + dcb[sinfo->dcb_wsize-1] |= ((pktlen + packet_info.ntwrk_header_ptr) & SOC_DCB_KNET_COUNT_MASK); + bkn_dump_pkt(pkt, 32, XGS_DMA_RX_CHAN); + } + } + } + } + + if (device_is_dune(sinfo)) { + filter = bkn_match_rx_pkt(sinfo, pkt, pktlen + packet_info.ntwrk_header_ptr, + dcb, chan, &cbf); + } else { + filter = bkn_match_rx_pkt(sinfo, pkt + sinfo->pkt_hdr_size, + pktlen - sinfo->pkt_hdr_size, meta, chan, &cbf); + } + if ((dcb[sinfo->dcb_wsize-1] & 0xf0000) != 0x30000) { + /* Fragment or error */ + if (filter && filter->kf.mask.w[err_woff] == 0) { + /* Drop unless DCB status is part of filter */ + filter = NULL; + } + } + drop_api = 1; + if (filter) { + DBG_FLTR(("Match filter ID %d\n", filter->kf.id)); + switch (filter->kf.dest_type) { + case KCOM_DEST_T_API: + DBG_FLTR(("Send to Rx API\n")); + sinfo->rx[chan].pkts_f_api++; + drop_api = 0; + break; + case KCOM_DEST_T_NETIF: + priv = bkn_netif_lookup(sinfo, filter->kf.dest_id); + if (priv) { + /* Check that software link is up */ + if (!netif_carrier_ok(priv->dev)) { + sinfo->rx[chan].pkts_d_no_link++; + break; + } + + if (sinfo->cmic_type == 'x') { + pkt += sinfo->pkt_hdr_size; + pktlen -= sinfo->pkt_hdr_size; + } + + /* Add 2 bytes for IP header alignment (see below) */ + skb = dev_alloc_skb(pktlen + RCPU_RX_ENCAP_SIZE + 2); + if (skb == NULL) { + sinfo->rx[chan].pkts_d_no_skb++; + break; + } + skb_reserve(skb, RCPU_RX_ENCAP_SIZE); + + DBG_FLTR(("Send to netif %d (%s)\n", + priv->id, priv->dev->name)); + sinfo->rx[chan].pkts_f_netif++; + skb->dev = priv->dev; + skb_reserve(skb, 2); /* 16 byte align the IP fields. */ + + /* Save for RCPU before stripping tag */ + ethertype = (pkt[16] << 8) | pkt[17]; + if ((priv->flags & KCOM_NETIF_F_KEEP_RX_TAG) == 0) { + if (filter->kf.flags & KCOM_FILTER_F_STRIP_TAG) { + /* Strip the VLAN tag */ + uint16_t vlan_proto = (uint16_t)((pkt[12] << 8) | pkt[13]); + if (vlan_proto == 0x8100 || vlan_proto == 0x88a8) { + DBG_FLTR(("Strip VLAN tag\n")); + for (idx = 11; idx >= 0; idx--) { + pkt[idx+4] = pkt[idx]; + } + pktlen -= 4; + pkt += 4; + } + } else { + /* + * Mark packet as VLAN-tagged, otherwise newer + * kernels will strip the tag. + */ + uint16_t tci = (pkt[14] << 8) | pkt[15]; + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + bkn_vlan_hwaccel_put_tag(skb, ETH_P_8021Q, tci); + } else { + bkn_vlan_hwaccel_put_tag(skb, + ((skb->data[12] << 8) | skb->data[13]), tci); + } + } + } + + skb_copy_to_linear_data(skb, pkt, pktlen); + if (device_is_dune(sinfo)) { + /* CRC has been stripped */ + skb_put(skb, pktlen); + } else { + skb_put(skb, pktlen - 4); /* Strip CRC */ + } + priv->stats.rx_packets++; + priv->stats.rx_bytes += skb->len; + + /* Optional SKB updates */ + if (knet_rx_cb != NULL) { + KNET_SKB_CB(skb)->netif_user_data = priv->cb_user_data; + KNET_SKB_CB(skb)->filter_user_data = filter->kf.cb_user_data; + KNET_SKB_CB(skb)->dcb_type = sinfo->dcb_type & 0xFFFF; + skb = knet_rx_cb(skb, sinfo->dev_no, meta); + if (skb == NULL) { + /* Consumed by call-back */ + sinfo->rx[chan].pkts_d_callback++; + break; + } + } + + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + bkn_add_rcpu_encap(sinfo, skb, meta); + DBG_PDMP(("After add RCPU ENCAP\n")); + bkn_dump_pkt(skb->data, pktlen + RCPU_RX_ENCAP_SIZE, XGS_DMA_RX_CHAN); + } + skb->protocol = eth_type_trans(skb, skb->dev); + if (filter->kf.dest_proto) { + skb->protocol = filter->kf.dest_proto; + } + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + bkn_eth_type_update(skb, ethertype); + } + DBG_DUNE(("skb protocol 0x%04x\n",skb->protocol)); + + /* Unlock while calling up network stack */ + spin_unlock(&sinfo->lock); + if (use_napi) { + netif_receive_skb(skb); + } else { + netif_rx(skb); + } + spin_lock(&sinfo->lock); + + if (filter->kf.mirror_type == KCOM_DEST_T_API || + dbg_pkt_enable) { + DBG_FLTR(("Mirror to Rx API\n")); + sinfo->rx[chan].pkts_m_api++; + drop_api = 0; + } + } else { + DBG_FLTR(("Unknown netif %d\n", + filter->kf.dest_id)); + sinfo->rx[chan].pkts_d_unkn_netif++; + } + break; + default: + /* Drop packet */ + DBG_FLTR(("Unknown dest type %d\n", + filter->kf.dest_type)); + sinfo->rx[chan].pkts_d_unkn_dest++; + break; + } + } else { + DBG_PKT(("Rx packet dropped.\n")); + sinfo->rx[chan].pkts_d_no_match++; + } + if (drop_api) { + /* If count is zero, the DCB will just be recycled */ + dcb[sinfo->dcb_wsize-1] &= ~SOC_DCB_KNET_COUNT_MASK; + } + dcb[sinfo->dcb_wsize-1] |= SOC_DCB_KNET_DONE; + dcb_chain->dcb_cur++; + dcbs_done++; + } + + return dcbs_done; +} + +static int +bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) +{ + bkn_priv_t *priv; + bkn_desc_info_t *desc; + struct sk_buff *skb; + bkn_filter_t cbf; + bkn_filter_t *filter; + uint32_t err_woff; + uint32_t *dcb, *meta; + int ethertype; + int pktlen; + int idx; + int dcbs_done = 0; + bkn_dnx_packet_info packet_info = {0}; + + if (!sinfo->rx[chan].running) { + /* Rx not ready */ + return 0; + } + + while (dcbs_done < budget) { + char str[32]; + sprintf(str, "Rx DCB (%d)", sinfo->rx[chan].dirty); + desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty]; + dcb = desc->dcb_mem; + bkn_dump_dcb(str, dcb, sinfo->dcb_wsize, XGS_DMA_RX_CHAN); + if ((dcb[sinfo->dcb_wsize-1] & (1 << 31)) == 0) { + break; + } + if ((sinfo->cmic_type == 'x' && (dcb[2] & (1 << 16)) == 0) || + (sinfo->cmic_type != 'x' && (dcb[1] & (1 << 16)) == 0)) { + sinfo->rx[chan].chain_complete = 1; + /* Request one extra poll to check for chain done interrupt */ + if (sinfo->napi_poll_mode) { + sinfo->napi_poll_again = 1; + } + } + sinfo->rx[chan].pkts++; + skb = desc->skb; + if (sinfo->cmic_type == 'x') { + meta = (uint32_t *)skb->data; + err_woff = sinfo->pkt_hdr_size / sizeof(uint32_t) - 1; + meta[err_woff] = dcb[sinfo->dcb_wsize-1]; + } else { + meta = dcb; + err_woff = sinfo->dcb_wsize - 1; + } + pktlen = dcb[sinfo->dcb_wsize-1] & 0xffff; + priv = netdev_priv(sinfo->dev); + DBG_DCB_RX(("Rx%d SKB DMA done (%d).\n", chan, sinfo->rx[chan].dirty)); + DMA_UNMAP_SINGLE(sinfo->dma_dev, + desc->skb_dma, desc->dma_size, + DMA_FROMDEV); + desc->skb_dma = 0; + bkn_dump_pkt(skb->data, pktlen, XGS_DMA_RX_CHAN); + + if (device_is_dune(sinfo)) { + uint16_t tpid = 0; + uint16_t vid = 0; + uint8_t *pkt = skb->data; + int res = 0; + + memset(&packet_info, 0, sizeof(bkn_dnx_packet_info)); + res = bkn_dnx_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info); + if (res == 0) { + if (packet_info.ftmh.action_type == 0x2) { + bkn_dnx_bitstream_set_field((uint32_t *)dcb, 192, 32, 0x8); + } else if (packet_info.ftmh.action_type == 0x1) { + bkn_dnx_bitstream_set_field((uint32_t *)dcb, 231, 25, 0x20); + } + bkn_dnx_bitstream_set_field((uint32_t *)dcb, 112, 16, packet_info.ftmh.src_sys_port); + bkn_dnx_bitstream_set_field((uint32_t *)dcb, 296, 12, packet_info.internal.vsi); + bkn_dnx_bitstream_set_field((uint32_t *)dcb, 64, 32, (packet_info.internal.trap_id << 16 | packet_info.internal.trap_qualifier)); + pkt = skb->data + packet_info.ntwrk_header_ptr; + /* check if vlan tag exists */ + tpid = (uint16_t)((pkt[12] << 8) | pkt[13]); + vid = (uint16_t)(packet_info.internal.vsi & 0xfff); + if (packet_is_untagged(tpid)) { + if ((pktlen + 4) < rx_buffer_size) { + DBG_DUNE(("add vlan tag to untagged packets\n")); + for (idx = (pktlen-packet_info.ntwrk_header_ptr-1); idx >= 12; idx--) { + pkt[idx+4] = pkt[idx]; + } + pkt[12] = 0x81; + pkt[13] = 0x00; + pkt[14] = (vid >> 8); + pkt[15] = (vid & 0xff); + pktlen += 4; + /* reset packet length in DCB */ + dcb[sinfo->dcb_wsize-1] &= ~SOC_DCB_KNET_COUNT_MASK; + dcb[sinfo->dcb_wsize-1] |= (pktlen & SOC_DCB_KNET_COUNT_MASK); + bkn_dump_pkt(pkt, 32, XGS_DMA_RX_CHAN); + } + } + } + } + + if (device_is_dune(sinfo)) { + filter = bkn_match_rx_pkt(sinfo, skb->data + packet_info.ntwrk_header_ptr, + pktlen, dcb, chan, &cbf); + } else { + filter = bkn_match_rx_pkt(sinfo, skb->data + sinfo->pkt_hdr_size, + pktlen - sinfo->pkt_hdr_size, meta, chan, &cbf); + } + if ((dcb[sinfo->dcb_wsize-1] & 0xf0000) != 0x30000) { + /* Fragment or error */ + priv->stats.rx_errors++; + if (filter && filter->kf.mask.w[err_woff] == 0) { + /* Drop unless DCB status is part of filter */ + filter = NULL; + } + } + DBG_PKT(("Rx packet (%d bytes).\n", pktlen)); + if (filter) { + DBG_FLTR(("Match filter ID %d\n", filter->kf.id)); + switch (filter->kf.dest_type) { + case KCOM_DEST_T_API: + DBG_FLTR(("Send to Rx API\n")); + sinfo->rx[chan].pkts_f_api++; + if (bkn_api_rx_copy_from_skb(sinfo, chan, desc) < 0) { + /* Suspend SKB Rx due to no API resources */ + sinfo->rx[chan].api_wait = 1; + return dcbs_done; + } + break; + case KCOM_DEST_T_NETIF: + priv = bkn_netif_lookup(sinfo, filter->kf.dest_id); + if (priv) { + /* Check that software link is up */ + if (!netif_carrier_ok(priv->dev)) { + sinfo->rx[chan].pkts_d_no_link++; + break; + } + DBG_FLTR(("Send to netif %d (%s)\n", + priv->id, priv->dev->name)); + sinfo->rx[chan].pkts_f_netif++; + + if (((filter->kf.mirror_type == KCOM_DEST_T_API) && + (!device_is_dune(sinfo))) || dbg_pkt_enable) { + sinfo->rx[chan].pkts_m_api++; + bkn_api_rx_copy_from_skb(sinfo, chan, desc); + } + + if (device_is_dune(sinfo)) { + if (filter->kf.mirror_type == KCOM_DEST_T_API) { + sinfo->rx[chan].pkts_m_api++; + bkn_api_rx_copy_from_skb(sinfo, chan, desc); + } + /* Strip Dune headers */ + skb->data += packet_info.ntwrk_header_ptr; + pktlen -= packet_info.ntwrk_header_ptr; + bkn_dump_pkt(skb->data, 32, XGS_DMA_RX_CHAN); + /* CRC has been stripped on Dune*/ + skb_put(skb, pktlen); + } else { + skb_put(skb, pktlen - 4); /* Strip CRC */ + } + + if (sinfo->cmic_type == 'x') { + skb_pull(skb, sinfo->pkt_hdr_size); + } + + /* Save for RCPU before stripping tag */ + ethertype = (skb->data[16] << 8) | skb->data[17]; + if ((priv->flags & KCOM_NETIF_F_KEEP_RX_TAG) == 0) { + if (filter->kf.flags & KCOM_FILTER_F_STRIP_TAG) { + /* Strip VLAN tag */ + uint16_t vlan_proto = (uint16_t)((skb->data[12] << 8) | skb->data[13]); + if (vlan_proto == 0x8100 || vlan_proto == 0x88a8) { + DBG_FLTR(("Strip VLAN tag\n")); + ((u32*)skb->data)[3] = ((u32*)skb->data)[2]; + ((u32*)skb->data)[2] = ((u32*)skb->data)[1]; + ((u32*)skb->data)[1] = ((u32*)skb->data)[0]; + skb_pull(skb, 4); + if (sinfo->cmic_type == 'x') { + for (idx = sinfo->pkt_hdr_size / sizeof(uint32_t); idx; idx--) { + meta[idx] = meta[idx - 1]; + } + meta++; + } + } + } else { + /* + * Mark packet as VLAN-tagged, otherwise newer + * kernels will strip the tag. + */ + uint16_t tci = (skb->data[14] << 8) | skb->data[15]; + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + bkn_vlan_hwaccel_put_tag(skb, ETH_P_8021Q, tci); + } else { + bkn_vlan_hwaccel_put_tag(skb, + ((skb->data[12] << 8) | skb->data[13]), tci); + } + } + } + priv->stats.rx_packets++; + priv->stats.rx_bytes += skb->len; + skb->dev = priv->dev; + + /* Optional SKB updates */ + if (knet_rx_cb != NULL) { + KNET_SKB_CB(skb)->netif_user_data = priv->cb_user_data; + KNET_SKB_CB(skb)->filter_user_data = filter->kf.cb_user_data; + KNET_SKB_CB(skb)->dcb_type = sinfo->dcb_type & 0xFFFF; + skb = knet_rx_cb(skb, sinfo->dev_no, meta); + if (skb == NULL) { + /* Consumed by call-back */ + sinfo->rx[chan].pkts_d_callback++; + priv->stats.rx_dropped++; + desc->skb = NULL; + break; + } + } + + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + bkn_add_rcpu_encap(sinfo, skb, meta); + DBG_PDMP(("After add RCPU ENCAP\n")); + bkn_dump_pkt(skb->data, pktlen + RCPU_RX_ENCAP_SIZE, XGS_DMA_RX_CHAN); + } + skb->protocol = eth_type_trans(skb, skb->dev); + if (filter->kf.dest_proto) { + skb->protocol = filter->kf.dest_proto; + } + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + bkn_eth_type_update(skb, ethertype); + } + DBG_DUNE(("skb protocol 0x%04x\n",skb->protocol)); + + if (filter->kf.mirror_type == KCOM_DEST_T_NETIF) { + bkn_priv_t *mpriv; + struct sk_buff *mskb; + mpriv = bkn_netif_lookup(sinfo, filter->kf.mirror_id); + if (mpriv && netif_carrier_ok(mpriv->dev)) { + mskb = skb_clone(skb, GFP_ATOMIC); + if (mskb == NULL) { + sinfo->rx[chan].pkts_d_no_skb++; + } else { + sinfo->rx[chan].pkts_m_netif++; + mpriv->stats.rx_packets++; + mpriv->stats.rx_bytes += mskb->len; + skb->dev = mpriv->dev; + if (filter->kf.mirror_proto) { + skb->protocol = filter->kf.mirror_proto; + } + /* Unlock while calling up network stack */ + spin_unlock(&sinfo->lock); + if (use_napi) { + netif_receive_skb(mskb); + } else { + netif_rx(mskb); + } + spin_lock(&sinfo->lock); + } + } + } + + /* Unlock while calling up network stack */ + spin_unlock(&sinfo->lock); + if (use_napi) { + netif_receive_skb(skb); + } else { + netif_rx(skb); + } + spin_lock(&sinfo->lock); + + /* Ensure that we reallocate SKB for this DCB */ + desc->skb = NULL; + } else { + DBG_FLTR(("Unknown netif %d\n", + filter->kf.dest_id)); + sinfo->rx[chan].pkts_d_unkn_netif++; + } + break; + default: + /* Drop packet */ + DBG_FLTR(("Unknown dest type %d\n", + filter->kf.dest_type)); + sinfo->rx[chan].pkts_d_unkn_dest++; + break; + } + } else { + DBG_PKT(("Rx packet dropped.\n")); + sinfo->rx[chan].pkts_d_no_match++; + priv->stats.rx_dropped++; + } + dcb[sinfo->dcb_wsize-1] &= ~(1 << 31); + if (++sinfo->rx[chan].dirty >= MAX_RX_DCBS) { + sinfo->rx[chan].dirty = 0; + } + sinfo->rx[chan].free--; + dcbs_done++; + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + /* Right now refill for Continuous DMA mode */ + bkn_rx_refill(sinfo, chan); + } + } + + return dcbs_done; +} + +static int +bkn_do_rx(bkn_switch_info_t *sinfo, int chan, int budget) +{ + if (sinfo->rx[chan].use_rx_skb == 0) { + /* Rx buffers are provided by BCM Rx API */ + return bkn_do_api_rx(sinfo, chan, budget); + } else { + /* Rx buffers are provided by Linux kernel */ + return bkn_do_skb_rx(sinfo, chan, budget); + } +} + +static void +bkn_rx_desc_done(bkn_switch_info_t *sinfo, int chan) +{ + bkn_evt_resource_t *evt; + evt = &_bkn_evt[sinfo->evt_idx]; + DBG_IRQ(("Rx%d desc done\n", chan)); + + if (sinfo->rx[chan].use_rx_skb == 0) { + sinfo->dma_events |= KCOM_DMA_INFO_F_RX_DONE; + evt->evt_wq_put++; + wake_up_interruptible(&evt->evt_wq); + } +} + +static void +bkn_rx_chain_done(bkn_switch_info_t *sinfo, int chan) +{ + if (sinfo->rx[chan].use_rx_skb && sinfo->rx[chan].api_wait) { + return; + } + + DBG_IRQ(("Rx%d chain done\n", chan)); + + if (sinfo->rx[chan].chain_complete == 0) { + /* + * In certain environments the DCB memory is updated after + * the corresponding interrupt has been received. + * The following code will ensure that this situation is + * handled properly. + */ + int maxloop = 0; + while (sinfo->rx[chan].chain_complete == 0) { + sinfo->rx[chan].sync_retry++; + if (maxloop == 0) { + sinfo->rx[chan].sync_err++; + } + if (maxloop > sinfo->rx[chan].sync_maxloop) { + sinfo->rx[chan].sync_maxloop = maxloop; + } + if (bkn_do_rx(sinfo, chan, MAX_RX_DCBS) > 0) { + bkn_rx_desc_done(sinfo, chan); + } + if (++maxloop > rx_sync_retry) { + gprintk("Fatal error: Incomplete chain\n"); + sinfo->rx[chan].chain_complete = 1; + break; + } + } + } + + sinfo->rx[chan].running = 0; + + if (sinfo->rx[chan].use_rx_skb == 0) { + bkn_api_rx_chain_done(sinfo, chan); + } else { + bkn_rx_refill(sinfo, chan); + + if (bkn_rx_restart(sinfo, chan) != 0) { + /* Presumably out of resources */ + sinfo->timer.expires = jiffies + 1; + if (!sinfo->timer_queued) { + sinfo->timer_queued = 1; + add_timer(&sinfo->timer); + } + } + } +} + +static void +bkn_suspend_tx(bkn_switch_info_t *sinfo) +{ + struct list_head *list; + bkn_priv_t *priv = netdev_priv(sinfo->dev); + + /* Stop main device */ + netif_stop_queue(priv->dev); + sinfo->tx.suspends++; + /* Stop associated virtual devices */ + list_for_each(list, &sinfo->ndev_list) { + priv = (bkn_priv_t *)list; + netif_stop_queue(priv->dev); + } +} + +static void +bkn_resume_tx(bkn_switch_info_t *sinfo) +{ + struct list_head *list; + bkn_priv_t *priv = netdev_priv(sinfo->dev); + + /* Check main device */ + if (netif_queue_stopped(priv->dev) && sinfo->tx.free > 1) { + netif_wake_queue(priv->dev); + } + /* Check associated virtual devices */ + list_for_each(list, &sinfo->ndev_list) { + priv = (bkn_priv_t *)list; + if (netif_queue_stopped(priv->dev) && sinfo->tx.free > 1) { + netif_wake_queue(priv->dev); + } + } +} + +static int +bkn_do_tx(bkn_switch_info_t *sinfo) +{ + bkn_desc_info_t *desc; + int dcbs_done = 0; + + if (!CDMA_CH(sinfo, XGS_DMA_TX_CHAN) && sinfo->tx.api_active) { + return dcbs_done; + } + + while (dcbs_done < MAX_TX_DCBS) { + char str[32]; + if (sinfo->tx.free == MAX_TX_DCBS) { + break; + } + sprintf(str, "Tx DCB (%d)", sinfo->tx.dirty); + desc = &sinfo->tx.desc[sinfo->tx.dirty]; + bkn_dump_dcb(str, desc->dcb_mem, sinfo->dcb_wsize, XGS_DMA_TX_CHAN); + if ((desc->dcb_mem[sinfo->dcb_wsize-1] & (1 << 31)) == 0) { + break; + } + if (desc->skb) { + DBG_DCB_TX(("Tx SKB DMA done (%d).\n", sinfo->tx.dirty)); + DMA_UNMAP_SINGLE(sinfo->dma_dev, + desc->skb_dma, desc->dma_size, + DMA_TODEV); + dev_kfree_skb_any(desc->skb); + desc->skb = NULL; + desc->skb_dma = 0; + } + desc->dcb_mem[sinfo->dcb_wsize-1] &= ~(1 << 31); + if (++sinfo->tx.dirty >= MAX_TX_DCBS) { + sinfo->tx.dirty = 0; + } + if (++sinfo->tx.free > MAX_TX_DCBS) { + gprintk("Too many free Tx DCBs(%d).\n", sinfo->tx.free); + } + dcbs_done++; + } + + return dcbs_done; +} + +static void +bkn_tx_cdma_chain_switch(bkn_switch_info_t *sinfo) +{ + bkn_dcb_chain_t *dcb_chain = sinfo->tx.api_dcb_chain; + uint32_t *dcb_mem; + uint64_t dcb_dma; + int woffset; + + /* Switch between SKB Tx and API Tx for Continuous DMA mode */ + if (!sinfo->tx.api_active) { + /* + * Set the current SKB DCB as reload DCB and the last DCB of + * the pending API chain as the new halt location. + */ + sinfo->tx.api_active = 1; + dcb_mem = sinfo->tx.desc[sinfo->tx.cur].dcb_mem; + memset(dcb_mem, 0, sinfo->dcb_wsize * sizeof(uint32_t)); + dcb_mem[0] = dcb_chain->dcb_dma; + if (sinfo->cmic_type == 'x') { + dcb_mem[1] = DMA_TO_BUS_HI(dcb_chain->dcb_dma >> 32); + dcb_mem[2] |= 1 << 24 | 1 << 18 | 1 << 16; + } else { + dcb_mem[1] |= 1 << 24 | 1 << 18 | 1 << 16; + } + if (++sinfo->tx.cur >= MAX_TX_DCBS) { + sinfo->tx.cur = 0; + } + sinfo->tx.free--; + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_dma = dcb_chain->dcb_dma + woffset * sizeof(uint32_t); + /* DMA run to the new halt location */ + bkn_cdma_goto(sinfo, XGS_DMA_TX_CHAN, dcb_dma); + } else { + /* Only need to set the current SKB DCB as the new halt location */ + sinfo->tx.api_active = 0; + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_mem = &dcb_chain->dcb_mem[woffset]; + dcb_mem[0] = sinfo->tx.desc[sinfo->tx.dirty].dcb_dma; + if (sinfo->cmic_type == 'x') { + dcb_mem[1] = DMA_TO_BUS_HI(sinfo->tx.desc[sinfo->tx.dirty].dcb_dma >> 32); + } + dcb_dma = sinfo->tx.desc[sinfo->tx.cur].dcb_dma; + /* DMA run to the new halt location */ + bkn_cdma_goto(sinfo, XGS_DMA_TX_CHAN, dcb_dma); + } +} + +static void +bkn_skb_tx(bkn_switch_info_t *sinfo) +{ + if (sinfo->tx.api_active) { + /* Switch from API Tx to SKB Tx */ + bkn_tx_cdma_chain_switch(sinfo); + } +} + +static void +bkn_api_tx(bkn_switch_info_t *sinfo) +{ + bkn_dcb_chain_t *dcb_chain; + uint64_t pkt_dma; + unsigned char *pktdata; + int pktlen; + int i; + + /* Assume that driver lock is held */ + if (list_empty(&sinfo->tx.api_dcb_list)) { + sinfo->tx.api_active = 0; + } else { + sinfo->tx.pkts++; + dcb_chain = list_entry(sinfo->tx.api_dcb_list.next, + bkn_dcb_chain_t, list); + DBG_DCB_TX(("Start API Tx DMA, first DCB @ 0x%08x (%d DCBs).\n", + (uint32_t)dcb_chain->dcb_dma, dcb_chain->dcb_cnt)); + for (i = 0; i < dcb_chain->dcb_cnt && debug & DBG_LVL_PDMP; i++) { + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN) && i == dcb_chain->dcb_cnt - 1) { + break; + } + if (sinfo->cmic_type == 'x') { + pkt_dma = BUS_TO_DMA_HI(dcb_chain->dcb_mem[sinfo->dcb_wsize * i + 1]); + pkt_dma = pkt_dma << 32 | dcb_chain->dcb_mem[sinfo->dcb_wsize * i]; + } else { + pkt_dma = dcb_chain->dcb_mem[sinfo->dcb_wsize * i]; + } + pktdata = kernel_bde->p2l(sinfo->dev_no, pkt_dma); + if (sinfo->cmic_type == 'x') { + pktlen = dcb_chain->dcb_mem[sinfo->dcb_wsize * i + 2] & 0xffff; + } else { + pktlen = dcb_chain->dcb_mem[sinfo->dcb_wsize * i + 1] & 0xffff; + } + bkn_dump_pkt(pktdata, pktlen, XGS_DMA_TX_CHAN); + } + + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + sinfo->tx.api_dcb_chain = dcb_chain; + if (!sinfo->tx.api_active) { + /* Switch from SKB Tx to API Tx */ + bkn_tx_cdma_chain_switch(sinfo); + } + list_del(&dcb_chain->list); + } else { + sinfo->tx.api_active = 1; + dev_dma_chan_clear(sinfo, XGS_DMA_TX_CHAN); + dev_irq_mask_enable(sinfo, XGS_DMA_TX_CHAN, 1); + dev_dma_chan_start(sinfo, XGS_DMA_TX_CHAN, dcb_chain->dcb_dma); + list_del(&dcb_chain->list); + kfree(dcb_chain); + } + } +} + +static void +bkn_tx_cdma_chain_done(bkn_switch_info_t *sinfo, int done) +{ + int woffset; + int dcbs_done = 0; + bkn_evt_resource_t *evt; + + DBG_IRQ(("Tx CDMA chain done \n")); + + evt = &_bkn_evt[sinfo->evt_idx]; + + if (sinfo->tx.api_active) { + /* Drain API Tx chains */ + while (sinfo->tx.api_dcb_chain != sinfo->tx.api_dcb_chain_end) { + woffset = sinfo->tx.api_dcb_chain->dcb_cnt * sinfo->dcb_wsize - 1; + if (!(sinfo->tx.api_dcb_chain->dcb_mem[woffset] & (1 << 31))) { + return; + } + sinfo->tx.api_dcb_chain->dcb_mem[woffset - sinfo->dcb_wsize] |= SOC_DCB_KNET_DONE; + sinfo->dma_events |= KCOM_DMA_INFO_F_TX_DONE; + evt->evt_wq_put++; + wake_up_interruptible(&evt->evt_wq); + kfree(sinfo->tx.api_dcb_chain); + sinfo->tx.api_dcb_chain = NULL; + bkn_api_tx(sinfo); + if ((++dcbs_done + done) >= MAX_TX_DCBS) { + if (sinfo->napi_poll_mode) { + /* Request one extra poll to reschedule Tx */ + sinfo->napi_poll_again = 1; + } else { + /* Request to yield for Continuous DMA mode */ + sinfo->tx_yield = 1; + } + return; + } + } + woffset = (sinfo->tx.api_dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize - 1; + if (!(sinfo->tx.api_dcb_chain->dcb_mem[woffset] & (1 << 31))) { + return; + } + sinfo->tx.api_dcb_chain->dcb_mem[woffset] |= SOC_DCB_KNET_DONE; + /* Try and park at SKB Tx if API Tx done */ + bkn_skb_tx(sinfo); + sinfo->dma_events |= KCOM_DMA_INFO_F_TX_DONE; + evt->evt_wq_put++; + wake_up_interruptible(&evt->evt_wq); + kfree(sinfo->tx.api_dcb_chain); + sinfo->tx.api_dcb_chain = NULL; + sinfo->tx.api_dcb_chain_end = NULL; + if (!sinfo->napi_poll_mode) { + /* Not need to yield for Continuous DMA mode */ + sinfo->tx_yield = 0; + } + } else { + if (sinfo->tx.free == MAX_TX_DCBS) { + /* Try API Tx if SKB Tx done */ + bkn_api_tx(sinfo); + if (sinfo->tx.api_active) { + return; + } + } + } + + /* Resume if netif Tx resources available and API Tx not active */ + bkn_resume_tx(sinfo); +} + +static void +bkn_tx_chain_done(bkn_switch_info_t *sinfo, int done) +{ + bkn_desc_info_t *desc; + int idx, pending; + bkn_evt_resource_t *evt; + + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + return bkn_tx_cdma_chain_done(sinfo, done); + } + + DBG_IRQ(("Tx chain done (%d/%d)\n", sinfo->tx.cur, sinfo->tx.dirty)); + + dev_irq_mask_disable(sinfo, XGS_DMA_TX_CHAN, 0); + + evt = &_bkn_evt[sinfo->evt_idx]; + + if (sinfo->tx.api_active) { + sinfo->dma_events |= KCOM_DMA_INFO_F_TX_DONE; + evt->evt_wq_put++; + wake_up_interruptible(&evt->evt_wq); + /* Check if BCM API has more to send */ + bkn_api_tx(sinfo); + if (sinfo->tx.api_active) { + return; + } + } + + if (sinfo->tx.free == MAX_TX_DCBS) { + /* If netif Tx is idle then allow BCM API to send */ + bkn_api_tx(sinfo); + if (sinfo->tx.api_active) { + return; + } + } else { + /* If two or more DCBs are pending, chain them */ + pending = MAX_TX_DCBS - sinfo->tx.free; + idx = sinfo->tx.dirty; + while (--pending && idx < (MAX_TX_DCBS - 1)) { + if (sinfo->cmic_type == 'x') { + sinfo->tx.desc[idx++].dcb_mem[2] |= 1 << 16; + } else { + sinfo->tx.desc[idx++].dcb_mem[1] |= 1 << 16; + } + DBG_DCB_TX(("Chain Tx DCB %d (%d)\n", idx, pending)); + } + /* Restart DMA from where we stopped */ + desc = &sinfo->tx.desc[sinfo->tx.dirty]; + DBG_DCB_TX(("Restart Tx DMA, DCB @ 0x%08x (%d).\n", + (uint32_t)desc->dcb_dma, sinfo->tx.dirty)); + dev_dma_chan_clear(sinfo, XGS_DMA_TX_CHAN); + dev_irq_mask_enable(sinfo, XGS_DMA_TX_CHAN, 0); + dev_dma_chan_start(sinfo, XGS_DMA_TX_CHAN, desc->dcb_dma); + } + + /* Resume if netif Tx resources available and API Tx not active */ + bkn_resume_tx(sinfo); +} + +static void +bkn_schedule_napi_poll(bkn_switch_info_t *sinfo) +{ + /* Schedule NAPI poll */ + DBG_NAPI(("Schedule NAPI poll on %s.\n", sinfo->dev->name)); + /* Disable interrupts until poll job is complete */ + sinfo->napi_poll_mode = 1; + /* Unlock while calling up network stack */ + spin_unlock(&sinfo->lock); + if (bkn_napi_schedule_prep(sinfo->dev, &sinfo->napi)) { + __bkn_napi_schedule(sinfo->dev, &sinfo->napi); + DBG_NAPI(("Schedule prep OK on %s.\n", sinfo->dev->name)); + } else { + /* Most likely the base device is has not been opened */ + gprintk("Warning: Unable to schedule NAPI - base device not up?\n"); + } + spin_lock(&sinfo->lock); +} + +static void +bkn_napi_poll_complete(bkn_switch_info_t *sinfo) +{ + /* Unlock while calling up network stack */ + spin_unlock(&sinfo->lock); + bkn_napi_complete(sinfo->dev, &sinfo->napi); + spin_lock(&sinfo->lock); + /* Re-enable interrupts */ + sinfo->napi_poll_mode = 0; + dev_irq_mask_set(sinfo, sinfo->irq_mask); +} + +static int +xgs_do_dma(bkn_switch_info_t *sinfo, int budget) +{ + int rx_dcbs_done = 0, tx_dcbs_done = 0; + uint32_t dma_stat; + int chan; + + DEV_READ32(sinfo, CMIC_DMA_STATr, &dma_stat); + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (dma_stat & DS_DESC_DONE_TST(XGS_DMA_RX_CHAN + chan)) { + xgs_dma_desc_clear(sinfo, XGS_DMA_RX_CHAN + chan); + rx_dcbs_done += bkn_do_rx(sinfo, chan, budget - rx_dcbs_done); + bkn_rx_desc_done(sinfo, chan); + } + + if (dma_stat & DS_CHAIN_DONE_TST(XGS_DMA_RX_CHAN + chan)) { + xgs_dma_chain_clear(sinfo, XGS_DMA_RX_CHAN + chan); + bkn_rx_chain_done(sinfo, chan); + } + } + + if (dma_stat & DS_CHAIN_DONE_TST(XGS_DMA_TX_CHAN)) { + xgs_dma_chain_clear(sinfo, XGS_DMA_TX_CHAN); + tx_dcbs_done = bkn_do_tx(sinfo); + bkn_tx_chain_done(sinfo, tx_dcbs_done); + } + + return rx_dcbs_done; +} + +static int +xgsm_do_dma(bkn_switch_info_t *sinfo, int budget) +{ + int rx_dcbs_done = 0, tx_dcbs_done = 0; + uint32_t dma_stat, irq_stat = 0; + int chan; + + /* Get Controlled interrupt states for Continuous DMA mode */ + if (sinfo->cdma_channels) { + DEV_READ32(sinfo, CMICM_IRQ_STATr, &irq_stat); + } + + DEV_READ32(sinfo, CMICM_DMA_STATr, &dma_stat); + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (dma_stat & (0x10 << (XGS_DMA_RX_CHAN + chan)) || + irq_stat & (0x08000000 << (XGS_DMA_RX_CHAN + chan))) { + xgsm_dma_desc_clear(sinfo, XGS_DMA_RX_CHAN + chan); + rx_dcbs_done += bkn_do_rx(sinfo, chan, budget - rx_dcbs_done); + bkn_rx_desc_done(sinfo, chan); + } + + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + continue; + } + + if (dma_stat & (0x1 << (XGS_DMA_RX_CHAN + chan))) { + xgsm_dma_chain_clear(sinfo, XGS_DMA_RX_CHAN + chan); + bkn_rx_chain_done(sinfo, chan); + } + } + + if (dma_stat & (0x1 << XGS_DMA_TX_CHAN) || + irq_stat & (0x08000000 << XGS_DMA_TX_CHAN)) { + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + xgsm_dma_desc_clear(sinfo, XGS_DMA_TX_CHAN); + } else { + xgsm_dma_chain_clear(sinfo, XGS_DMA_TX_CHAN); + } + tx_dcbs_done = bkn_do_tx(sinfo); + bkn_tx_chain_done(sinfo, tx_dcbs_done); + } + + return rx_dcbs_done; +} + +static int +xgsx_do_dma(bkn_switch_info_t *sinfo, int budget) +{ + int rx_dcbs_done = 0, tx_dcbs_done = 0; + uint32_t irq_stat; + int chan; + + DEV_READ32(sinfo, CMICX_IRQ_STATr, &irq_stat); + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if ((irq_stat & CMICX_DS_CMC_CTRLD_INT(XGS_DMA_RX_CHAN + chan)) || + (irq_stat & CMICX_DS_CMC_DESC_DONE(XGS_DMA_RX_CHAN + chan))) { + xgsx_dma_desc_clear(sinfo, XGS_DMA_RX_CHAN + chan); + rx_dcbs_done += bkn_do_rx(sinfo, chan, budget - rx_dcbs_done); + bkn_rx_desc_done(sinfo, chan); + } + + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + continue; + } + + if (irq_stat & CMICX_DS_CMC_CHAIN_DONE(XGS_DMA_RX_CHAN + chan)) { + xgsx_dma_chain_clear(sinfo, XGS_DMA_RX_CHAN + chan); + bkn_rx_chain_done(sinfo, chan); + } + } + + if ((irq_stat & CMICX_DS_CMC_CTRLD_INT(XGS_DMA_TX_CHAN)) || + (irq_stat & CMICX_DS_CMC_CHAIN_DONE(XGS_DMA_TX_CHAN))) { + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + xgsx_dma_desc_clear(sinfo, XGS_DMA_TX_CHAN); + } else { + xgsx_dma_chain_clear(sinfo, XGS_DMA_TX_CHAN); + } + tx_dcbs_done = bkn_do_tx(sinfo); + bkn_tx_chain_done(sinfo, tx_dcbs_done); + } + + return rx_dcbs_done; +} + +static int +dev_do_dma(bkn_switch_info_t *sinfo, int budget) +{ + if (DEV_IS_CMICX(sinfo)) { + return xgsx_do_dma(sinfo, budget); + } else if (DEV_IS_CMICM(sinfo)) { + return xgsm_do_dma(sinfo, budget); + } else { + return xgs_do_dma(sinfo, budget); + } +} + +static void +xgs_isr(bkn_switch_info_t *sinfo) +{ + uint32_t irq_stat; + int rx_dcbs_done; + + DEV_READ32(sinfo, CMIC_IRQ_STATr, &irq_stat); + if ((irq_stat & sinfo->irq_mask) == 0) { + /* Not ours */ + return; + } + sinfo->interrupts++; + + DBG_IRQ(("Got interrupt on device %d (0x%08x)\n", + sinfo->dev_no, irq_stat)); + + if (use_napi) { + bkn_schedule_napi_poll(sinfo); + } else { + xgs_irq_mask_set(sinfo, 0); + do { + rx_dcbs_done = xgs_do_dma(sinfo, MAX_RX_DCBS); + } while (rx_dcbs_done); + } + + xgs_irq_mask_set(sinfo, sinfo->irq_mask); +} + +static void +xgsm_isr(bkn_switch_info_t *sinfo) +{ + uint32_t irq_stat; + int rx_dcbs_done; + + DEV_READ32(sinfo, CMICM_IRQ_STATr, &irq_stat); + if ((irq_stat & sinfo->irq_mask) == 0) { + /* Not ours */ + return; + } + sinfo->interrupts++; + + DBG_IRQ(("Got interrupt on device %d (0x%08x)\n", + sinfo->dev_no, irq_stat)); + + if (use_napi) { + bkn_schedule_napi_poll(sinfo); + } else { + xgsm_irq_mask_set(sinfo, 0); + do { + rx_dcbs_done = xgsm_do_dma(sinfo, MAX_RX_DCBS); + if (sinfo->cdma_channels) { + if (rx_dcbs_done >= MAX_RX_DCBS || sinfo->tx_yield) { + /* Continuous DMA mode requires to yield timely */ + break; + } + } + } while (rx_dcbs_done); + } + + xgsm_irq_mask_set(sinfo, sinfo->irq_mask); +} + +static void +xgsx_isr(bkn_switch_info_t *sinfo) +{ + uint32_t irq_stat; + int rx_dcbs_done; + + DEV_READ32(sinfo, CMICX_IRQ_STATr, &irq_stat); + if ((irq_stat & sinfo->irq_mask) == 0) { + /* Not ours */ + return; + } + sinfo->interrupts++; + + DBG_IRQ(("Got interrupt on device %d (0x%08x)\n", + sinfo->dev_no, irq_stat)); + + if (use_napi) { + bkn_schedule_napi_poll(sinfo); + } else { + xgsx_irq_mask_set(sinfo, 0); + do { + rx_dcbs_done = xgsx_do_dma(sinfo, MAX_RX_DCBS); + if (sinfo->cdma_channels) { + if (rx_dcbs_done >= MAX_RX_DCBS || sinfo->tx_yield) { + /* Continuous DMA mode requires to yield timely */ + break; + } + } + } while (rx_dcbs_done); + } + + xgsx_irq_mask_set(sinfo, sinfo->irq_mask); +} + +static void +bkn_isr(void *isr_data) +{ + bkn_switch_info_t *sinfo = isr_data; + + /* Safe exit on SMP systems */ + if (!module_initialized) { + return; + } + + /* Ensure that we do not touch registers during device reset */ + if (sinfo->irq_mask == 0) { + /* Not ours */ + return; + } + + spin_lock(&sinfo->lock); + + if (sinfo->napi_poll_mode) { + /* Not ours */ + spin_unlock(&sinfo->lock); + return; + } + + if (DEV_IS_CMICX(sinfo)) { + xgsx_isr(sinfo); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_isr(sinfo); + } else { + xgs_isr(sinfo); + } + + spin_unlock(&sinfo->lock); +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void +bkn_poll_controller(struct net_device *dev) +{ + bkn_priv_t *priv = netdev_priv(dev); + + disable_irq(dev->irq); + bkn_isr(priv->sinfo); + enable_irq(dev->irq); +} +#endif + +static void +bkn_resume_rx(bkn_switch_info_t *sinfo) +{ + bkn_desc_info_t *desc; + bkn_dcb_chain_t *dcb_chain; + uint64_t cur_halt, last_dcb, dcb_dma; + int woffset, chan, cdma_running; + + /* Resume Rx DMA on all channels */ + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (sinfo->rx[chan].use_rx_skb) { + cdma_running = 0; + bkn_api_rx_restart(sinfo, chan); + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + cur_halt = sinfo->halt_addr[XGS_DMA_RX_CHAN + chan]; + last_dcb = sinfo->rx[chan].desc[MAX_RX_DCBS].dcb_dma; + if (cur_halt != last_dcb) { + desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty + 1]; + bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, desc->dcb_dma); + cdma_running = 1; + } + } + if (!cdma_running) { + bkn_rx_restart(sinfo, chan); + } + } else { + cdma_running = 0; + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + if (sinfo->rx[chan].api_active) { + dcb_chain = sinfo->rx[chan].api_dcb_chain_end; + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_dma = dcb_chain->dcb_dma + woffset * sizeof(uint32_t); + bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, dcb_dma); + cdma_running = 1; + } + } + if (!cdma_running) { + bkn_api_rx_restart(sinfo, chan); + } + } + } +} + +static int +bkn_open(struct net_device *dev) +{ + bkn_priv_t *priv = netdev_priv(dev); + bkn_switch_info_t *sinfo = priv->sinfo; + unsigned long flags; + + /* Check if base device */ + if (priv->id <= 0) { + /* NAPI used only on base device */ + if (use_napi) { + bkn_napi_enable(dev, &sinfo->napi); + } + + /* Start DMA when base device is started */ + if (sinfo->basedev_suspended) { + spin_lock_irqsave(&sinfo->lock, flags); + dev_do_dma(sinfo, MAX_RX_DCBS); + sinfo->basedev_suspended = 0; + bkn_api_tx(sinfo); + if (!sinfo->tx.api_active) { + bkn_resume_tx(sinfo); + } + bkn_resume_rx(sinfo); + spin_unlock_irqrestore(&sinfo->lock, flags); + } + } + + if (!sinfo->basedev_suspended) { + netif_start_queue(dev); + } + + return 0; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) +static int +bkn_set_mac_address(struct net_device *dev, void *addr) +{ + if (!is_valid_ether_addr(((struct sockaddr *)addr)->sa_data)) { + return -EINVAL; + } + memcpy(dev->dev_addr, ((struct sockaddr *)addr)->sa_data, dev->addr_len); + return 0; +} +#endif + +static int +bkn_change_mtu(struct net_device *dev, int new_mtu) +{ + int max_size = new_mtu + ETH_HLEN + VLAN_HLEN + 4; + + if (new_mtu < 68 || max_size > rx_buffer_size) { + return -EINVAL; + } + dev->mtu = new_mtu; + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +static int +bkn_poll(struct net_device *dev, int *budget) +{ + bkn_priv_t *priv = netdev_priv(dev); + bkn_switch_info_t *sinfo = priv->sinfo; + int cur_budget = *budget; + int poll_again = 0; + int rx_dcbs_done; + unsigned long flags; + + spin_lock_irqsave(&sinfo->lock, flags); + + DBG_NAPI(("NAPI poll on %s.\n", dev->name)); + + sinfo->napi_poll_again = 0; + + if (cur_budget > dev->quota) { + cur_budget = dev->quota; + } + + rx_dcbs_done = dev_do_dma(sinfo, cur_budget); + + *budget -= rx_dcbs_done; + cur_budget -= rx_dcbs_done; + dev->quota -= rx_dcbs_done; + + if (sinfo->napi_poll_again || cur_budget <= 0) { + poll_again = 1; + sinfo->napi_not_done++; + } else { + bkn_napi_poll_complete(sinfo); + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return poll_again; +} +#else +static int +bkn_poll(struct napi_struct *napi, int budget) +{ + bkn_switch_info_t *sinfo = container_of(napi, bkn_switch_info_t, napi); + int rx_dcbs_done; + unsigned long flags; + + spin_lock_irqsave(&sinfo->lock, flags); + + DBG_NAPI(("NAPI poll on %s.\n", sinfo->dev->name)); + + sinfo->napi_poll_again = 0; + + rx_dcbs_done = dev_do_dma(sinfo, budget); + + if (sinfo->napi_poll_again || rx_dcbs_done >= budget) { + /* Force poll again */ + rx_dcbs_done = budget; + sinfo->napi_not_done++; + } else { + bkn_napi_poll_complete(sinfo); + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return rx_dcbs_done; +} +#endif + +static int +bkn_stop(struct net_device *dev) +{ + bkn_priv_t *priv = netdev_priv(dev); + bkn_switch_info_t *sinfo = priv->sinfo; + unsigned long flags; + + netif_stop_queue(dev); + + /* Check if base device */ + if (priv->id <= 0) { + /* NAPI used only on base device */ + if (use_napi) { + bkn_napi_disable(dev, &sinfo->napi); + } + /* Suspend all devices if base device is stopped */ + if (basedev_suspend) { + spin_lock_irqsave(&sinfo->lock, flags); + bkn_suspend_tx(sinfo); + sinfo->basedev_suspended = 1; + spin_unlock_irqrestore(&sinfo->lock, flags); + } + } + + return 0; +} + +/* + * Network Device Statistics. + * Cleared at init time. + */ +static struct net_device_stats * +bkn_get_stats(struct net_device *dev) +{ + bkn_priv_t *priv = netdev_priv(dev); + + return &priv->stats; +} + +/* Fake multicast ability */ +static void +bkn_set_multicast_list(struct net_device *dev) +{ +} + +static int +bkn_tx(struct sk_buff *skb, struct net_device *dev) +{ + bkn_priv_t *priv = netdev_priv(dev); + bkn_switch_info_t *sinfo = priv->sinfo; + struct sk_buff *new_skb = NULL; + unsigned char *pktdata; + int pktlen, hdrlen, taglen, rcpulen, metalen; + int sop, idx; + uint16_t tpid; + uint32_t *metadata; + unsigned long flags; + + DBG_VERB(("Netif Tx: Len=%d\n", skb->len)); + + if (priv->id <= 0) { + /* Do not transmit on base device */ + priv->stats.tx_dropped++; + dev_kfree_skb_any(skb); + return 0; + } + + if (!netif_carrier_ok(dev)) { + DBG_WARN(("Tx drop: Invalid RCPU encapsulation\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_no_link++; + dev_kfree_skb_any(skb); + return 0; + } + + spin_lock_irqsave(&sinfo->lock, flags); + + if (sinfo->tx.free > 1) { + bkn_desc_info_t *desc = &sinfo->tx.desc[sinfo->tx.cur]; + uint32_t *dcb, *meta; + + pktdata = skb->data; + pktlen = skb->len + 4; + hdrlen = sinfo->cmic_type == 'x' ? PKT_TX_HDR_SIZE : 0; + rcpulen = 0; + sop = 0; + + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + rcpulen = RCPU_HDR_SIZE; + if (skb->len < (rcpulen + 14)) { + DBG_WARN(("Tx drop: Invalid RCPU encapsulation\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_rcpu_encap++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + if (check_rcpu_signature && + ((skb->data[18] << 8) | skb->data[19]) != sinfo->rcpu_sig) { + DBG_WARN(("Tx drop: Invalid RCPU signature\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_rcpu_sig++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + if (skb->data[21] & RCPU_F_MODHDR) { + sop = skb->data[RCPU_HDR_SIZE]; + switch (sop) { + case 0xff: + case 0x81: + case 0xfb: + case 0xfc: + break; + default: + DBG_WARN(("Tx drop: Invalid RCPU meta data\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_rcpu_meta++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + if (sinfo->cmic_type != 'x') { + rcpulen += RCPU_TX_META_SIZE; + } + } + /* Skip over RCPU encapsulation */ + pktdata = &skb->data[rcpulen]; + pktlen -= rcpulen; + + /* CPU packets require tag */ + if (sop == 0) { + hdrlen = 0; + tpid = (pktdata[12] << 8) | pktdata[13]; + if (tpid != 0x8100) { + if (skb_header_cloned(skb)) { + /* Current SKB cannot be modified */ + DBG_SKB(("Realloc Tx SKB\n")); + new_skb = dev_alloc_skb(pktlen + 4); + if (new_skb == NULL) { + DBG_WARN(("Tx drop: No SKB memory\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_no_skb++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + memcpy(new_skb->data, pktdata, 12); + memcpy(&new_skb->data[16], &pktdata[12], pktlen - 12); + skb_put(new_skb, pktlen + 4); + dev_kfree_skb_any(skb); + skb = new_skb; + pktdata = skb->data; + } else { + /* Add tag to RCPU header space */ + DBG_SKB(("Expand into unused RCPU header\n")); + pktdata = &skb->data[rcpulen - 4]; + for (idx = 0; idx < 12; idx++) { + pktdata[idx] = pktdata[idx + 4]; + } + } + pktdata[12] = 0x81; + pktdata[13] = 0x00; + pktdata[14] = (priv->vlan >> 8) & 0xf; + pktdata[15] = priv->vlan & 0xff; + pktlen += 4; + } + } + } else { + if (sinfo->cmic_type == 'x' && priv->port >= 0) { + if (skb_header_cloned(skb) || skb_headroom(skb) < hdrlen + 4 || + ((unsigned long)skb->data % 4)) { + /* Current SKB cannot be modified */ + DBG_SKB(("Realloc Tx SKB\n")); + new_skb = dev_alloc_skb(pktlen + hdrlen + 4); + if (new_skb == NULL) { + DBG_WARN(("Tx drop: No SKB memory\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_no_skb++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + skb_reserve(new_skb, 4); + memcpy(new_skb->data + hdrlen, skb->data, pktlen); + skb_put(new_skb, pktlen + hdrlen); + dev_kfree_skb_any(skb); + skb = new_skb; + } else { + DBG_SKB(("Expand Tx SKB\n")); + skb_push(skb, hdrlen); + } + memset(skb->data, 0, hdrlen); + pktdata = skb->data; + pktlen += hdrlen; + } else { + hdrlen = 0; + } + + if (priv->port < 0 || (priv->flags & KCOM_NETIF_F_ADD_TAG)) { + /* Need to add VLAN tag if packet is untagged */ + tpid = (skb->data[hdrlen + 12] << 8) | skb->data[hdrlen + 13]; + if (tpid != 0x8100) { + if (skb_header_cloned(skb) || skb_headroom(skb) < 4) { + /* Current SKB cannot be modified */ + DBG_SKB(("Realloc Tx SKB\n")); + new_skb = dev_alloc_skb(pktlen + 4); + if (new_skb == NULL) { + DBG_WARN(("Tx drop: No SKB memory\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_no_skb++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + memcpy(new_skb->data, skb->data, hdrlen + 12); + memcpy(&new_skb->data[hdrlen + 16], &skb->data[hdrlen + 12], + pktlen - hdrlen - 12); + skb_put(new_skb, pktlen + 4); + dev_kfree_skb_any(skb); + skb = new_skb; + } else { + /* Add tag to existing buffer */ + DBG_SKB(("Expand Tx SKB\n")); + skb_push(skb, 4); + for (idx = 0; idx < hdrlen + 12; idx++) { + skb->data[idx] = skb->data[idx + 4]; + } + } + pktdata = skb->data; + pktdata[hdrlen + 12] = 0x81; + pktdata[hdrlen + 13] = 0x00; + pktdata[hdrlen + 14] = (priv->vlan >> 8) & 0xf; + pktdata[hdrlen + 15] = priv->vlan & 0xff; + pktlen += 4; + } + } + } + + /* Pad packet if needed */ + taglen = 0; + tpid = (pktdata[hdrlen + 12] << 8) | pktdata[hdrlen + 13]; + if (tpid == 0x8100) { + taglen = 4; + } + if (pktlen < (64 + taglen + hdrlen)) { + pktlen = (64 + taglen + hdrlen); + if (SKB_PADTO(skb, pktlen) != 0) { + DBG_WARN(("Tx drop: skb_padto failed\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_pad_fail++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + DBG_SKB(("Packet padded to %d bytes\n", pktlen)); + } + + if (pktlen > SOC_DCB_KNET_COUNT_MASK) { + DBG_WARN(("Tx drop: size of pkt (%d) is out of range(%d)\n", + pktlen, SOC_DCB_KNET_COUNT_MASK)); + sinfo->tx.pkts_d_over_limit++; + priv->stats.tx_dropped++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + + dcb = desc->dcb_mem; + meta = sinfo->cmic_type == 'x' ? (uint32_t *)pktdata : dcb; + memset(dcb, 0, sinfo->dcb_wsize * sizeof(uint32_t)); + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + /* If module header SOP is non-zero, use RCPU meta data */ + if (sop != 0) { + if (sinfo->cmic_type == 'x') { + dcb[2] |= 1 << 19; + } else { + metalen = (sinfo->dcb_wsize - 3) * sizeof(uint32_t); + if (metalen > RCPU_TX_META_SIZE) { + metalen = RCPU_TX_META_SIZE; + } + metadata = (uint32_t *)&skb->data[RCPU_HDR_SIZE]; + for (idx = 0; idx < BYTES2WORDS(metalen); idx++) { + dcb[idx + 2] = ntohl(metadata[idx]); + } + dcb[1] |= 1 << 19; + } + } + } else if (priv->port >= 0) { + /* Send to physical port */ + if (sinfo->cmic_type == 'x') { + dcb[2] |= 1 << 19; + } else { + dcb[1] |= 1 << 19; + } + switch (sinfo->dcb_type) { + case 23: + case 26: + case 30: + case 31: + case 34: + case 37: + dcb[2] = 0x81000000; + dcb[3] = priv->port; + dcb[3] |= (priv->qnum & 0xc00) << 20; + dcb[4] = 0x00040000; + dcb[4] |= (priv->qnum & 0x3ff) << 8; + break; + case 24: + dcb[2] = 0xff000000; + dcb[3] = 0x00000100; + dcb[4] = priv->port; + dcb[4] |= (priv->qnum & 0xfff) << 14; + break; + case 28: + { + if (priv->type == KCOM_NETIF_T_PORT) { + /* add PTCH ITMH header */ + if (skb_header_cloned(skb) || skb_headroom(skb) < 4) { + /* Current SKB cannot be modified */ + DBG_SKB(("Realloc Tx SKB for DNX ITMH header\n")); + new_skb = dev_alloc_skb(pktlen + 4 + 2); + if (new_skb == NULL) { + DBG_WARN(("Tx drop: No SKB memory for DNX ITMH header\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_no_skb++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + memcpy(&new_skb->data[6], skb->data, pktlen); + skb_put(new_skb, pktlen + 6); + dev_kfree_skb_any(skb); + skb = new_skb; + } else { + /* Add tag to existing buffer */ + DBG_SKB(("Expand Tx SKB for DNX ITMH header\n")); + skb_push(skb, 6); + } + pktdata = skb->data; + pktdata[0] = 0x50; + pktdata[1] = 0x00; + memcpy(&pktdata[2], priv->itmh, 4); + pktlen += 6; + } + else if (priv->type == KCOM_NETIF_T_VLAN) { + /* add PTCH header */ + if (skb_header_cloned(skb) || skb_headroom(skb) < 4) { + /* Current SKB cannot be modified */ + DBG_SKB(("Realloc Tx SKB for DNX header\n")); + new_skb = dev_alloc_skb(pktlen + 2); + if (new_skb == NULL) { + DBG_WARN(("Tx drop: No SKB memory for DNX header\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_no_skb++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + memcpy(&new_skb->data[2], skb->data, pktlen); + skb_put(new_skb, pktlen + 2); + dev_kfree_skb_any(skb); + skb = new_skb; + } else { + /* Add tag to existing buffer */ + DBG_SKB(("Expand Tx SKB for DNX header\n")); + skb_push(skb, 2); + } + pktdata = skb->data; + pktdata[0] = 0xd0; + pktdata[1] = priv->port; + pktlen += 2; + } + dcb[1] = pktlen; + break; + } + case 29: + dcb[2] = 0x81000000; + dcb[3] = priv->port; + dcb[4] = 0x00100000; + dcb[4] |= (priv->qnum & 0xfff) << 8; + break; + case 32: + dcb[2] = 0x81000000; + dcb[3] = priv->port; + dcb[4] = 0x00004000; + dcb[4] |= (priv->qnum & 0x3f) << 8; + break; + case 33: + dcb[2] = 0x81000000; + dcb[3] = (priv->port) << 2; + dcb[4] = 0x00100000; + dcb[4] |= (priv->qnum & 0xfff) << 8; + break; + case 35: + dcb[2] = 0x81000000; + dcb[3] = (priv->port) << 4; + dcb[4] = 0x00400000; + dcb[4] |= (priv->qnum & 0x3fff) << 8; + break; + case 36: + if (sinfo->cmic_type == 'x') { + meta[0] = htonl(0x81000000); + meta[1] = htonl(priv->port); + meta[2] = htonl(0x00008000 | (priv->qnum & 0x3f) << 9); + } else { + dcb[2] = 0x81000000; + dcb[3] = priv->port; + dcb[4] = 0x00008000; + dcb[4] |= (priv->qnum & 0x3f) << 9; + } + break; + case 38: + if (sinfo->cmic_type == 'x') { + meta[0] = htonl(0x81000000); + meta[1] = htonl(priv->port); + meta[2] = htonl(0x00004000 | (priv->qnum & 0x3f) << 8); + } else { + dcb[2] = 0x81000000; + dcb[3] = priv->port; + dcb[4] = 0x00004000; + dcb[4] |= (priv->qnum & 0x3f) << 8; + } + break; + default: + dcb[2] = 0xff000000; + dcb[3] = 0x00000100; + dcb[4] = priv->port; + break; + } + } + + /* Optional SKB updates */ + if (knet_tx_cb != NULL) { + KNET_SKB_CB(skb)->netif_user_data = priv->cb_user_data; + KNET_SKB_CB(skb)->dcb_type = sinfo->dcb_type & 0xFFFF; + skb = knet_tx_cb(skb, sinfo->dev_no, meta); + if (skb == NULL) { + /* Consumed by call-back */ + DBG_WARN(("Tx drop: Consumed by call-back\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_callback++; + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + /* Restore (possibly) altered packet variables + * bit0 -bit15 of dcb[1] is used to save requested byte count + */ + if ((skb->len + 4) <= SOC_DCB_KNET_COUNT_MASK) { + pktdata = skb->data; + pktlen = skb->len + 4; + if (pktlen < (64 + taglen + hdrlen)) { + pktlen = (64 + taglen + hdrlen); + if (SKB_PADTO(skb, pktlen) != 0) { + DBG_WARN(("Tx drop: skb_padto failed\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_pad_fail++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + DBG_SKB(("Packet padded to %d bytes after tx callback\n", pktlen)); + } + } else { + DBG_WARN(("Tx drop: size of pkt (%d) is out of range(%d)\n", + pktlen, SOC_DCB_KNET_COUNT_MASK)); + sinfo->tx.pkts_d_over_limit++; + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_callback++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + } + + /* Prepare for DMA */ + desc->skb = skb; + desc->dma_size = pktlen; + desc->skb_dma = DMA_MAP_SINGLE(sinfo->dma_dev, + pktdata, desc->dma_size, + DMA_TODEV); + if (DMA_MAPPING_ERROR(sinfo->dma_dev, desc->skb_dma)) { + priv->stats.tx_dropped++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + dcb[0] = desc->skb_dma; + if (sinfo->cmic_type == 'x') { + dcb[1] = DMA_TO_BUS_HI(desc->skb_dma >> 32); + dcb[2] &= ~SOC_DCB_KNET_COUNT_MASK; + dcb[2] |= pktlen; + } else { + dcb[1] &= ~SOC_DCB_KNET_COUNT_MASK; + dcb[1] |= pktlen; + } + + bkn_dump_dcb("Tx RCPU", dcb, sinfo->dcb_wsize, XGS_DMA_TX_CHAN); + DBG_DCB_TX(("Add Tx DCB @ 0x%08x (%d) [%d free] (%d bytes).\n", + (uint32_t)desc->dcb_dma, sinfo->tx.cur, + sinfo->tx.free, pktlen)); + bkn_dump_pkt(pktdata, pktlen, XGS_DMA_TX_CHAN); + + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + if (sinfo->cmic_type == 'x') { + dcb[2] |= 1 << 24 | 1 << 16; + } else { + dcb[1] |= 1 << 24 | 1 << 16; + } + } else { + bkn_tx_dma_start(sinfo); + } + if (++sinfo->tx.cur >= MAX_TX_DCBS) { + sinfo->tx.cur = 0; + } + sinfo->tx.free--; + + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN) && !sinfo->tx.api_active) { + /* DMA run to the new halt location */ + bkn_cdma_goto(sinfo, XGS_DMA_TX_CHAN, + sinfo->tx.desc[sinfo->tx.cur].dcb_dma); + } + + priv->stats.tx_packets++; + priv->stats.tx_bytes += pktlen; + sinfo->tx.pkts++; + } else { + DBG_WARN(("Tx drop: No DMA resources\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_dma_resrc++; + dev_kfree_skb_any(skb); + } + + /* Check our Tx resources */ + if (sinfo->tx.free <= 1) { + bkn_suspend_tx(sinfo); + } + +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4,6,0)) + dev->trans_start = jiffies; +#else + netif_trans_update(dev); +#endif + spin_unlock_irqrestore(&sinfo->lock, flags); + + return 0; +} + +static void +bkn_timer(unsigned long context) +{ + bkn_switch_info_t *sinfo = (bkn_switch_info_t *)context; + unsigned long flags; + int chan; + int restart_timer; + + spin_lock_irqsave(&sinfo->lock, flags); + + sinfo->timer_runs++; + + restart_timer = 0; + for (chan = 0; chan < sinfo->rx_chans; chan++) { + /* Restart channel if not running */ + if (sinfo->rx[chan].running == 0) { + bkn_rx_refill(sinfo, chan); + if (bkn_rx_restart(sinfo, chan) != 0) { + restart_timer = 1; + } + } + } + + if (restart_timer) { + /* Presumably still out of memory */ + sinfo->timer.expires = jiffies + 1; + add_timer(&sinfo->timer); + } else { + sinfo->timer_queued = 0; + } + + spin_unlock_irqrestore(&sinfo->lock, flags); +} + +static void +bkn_rx_add_tokens(bkn_switch_info_t *sinfo, int chan) +{ + unsigned long cur_jif, ticks; + uint32_t tokens_per_tick; + bkn_desc_info_t *desc; + + tokens_per_tick = sinfo->rx[chan].rate_max / HZ; + cur_jif = jiffies; + ticks = cur_jif - sinfo->rx[chan].tok_jif; + sinfo->rx[chan].tokens += ticks * tokens_per_tick; + sinfo->rx[chan].tok_jif = cur_jif; + if (sinfo->rx[chan].tokens > sinfo->rx[chan].burst_max) { + sinfo->rx[chan].tokens = sinfo->rx[chan].burst_max; + } + + /* Restart channel if Rx is suppressed */ + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + bkn_rx_refill(sinfo, chan); + desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty]; + if (desc->dcb_dma == sinfo->halt_addr[XGS_DMA_RX_CHAN + chan]) { + desc = &sinfo->rx[chan].desc[MAX_RX_DCBS]; + bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, desc->dcb_dma); + } + } else { + if (sinfo->rx[chan].running == 0) { + bkn_rx_refill(sinfo, chan); + bkn_rx_restart(sinfo, chan); + } + } +} + +static void +bkn_rxtick(unsigned long context) +{ + bkn_switch_info_t *sinfo = (bkn_switch_info_t *)context; + unsigned long flags; + unsigned long cur_jif, ticks; + uint32_t pkt_diff; + int chan; + + spin_lock_irqsave(&sinfo->lock, flags); + + sinfo->rxtick.expires = jiffies + sinfo->rxtick_jiffies; + + /* For debug purposes we maintain a rough actual packet rate */ + if (++sinfo->rxticks >= sinfo->rxticks_per_sec) { + for (chan = 0; chan < sinfo->rx_chans; chan++) { + pkt_diff = sinfo->rx[chan].pkts - sinfo->rx[chan].pkts_ref; + cur_jif = jiffies; + ticks = cur_jif - sinfo->rx[chan].rate_jif; + sinfo->rx[chan].rate = (pkt_diff * HZ) / ticks; + sinfo->rx[chan].rate_jif = cur_jif; + sinfo->rx[chan].pkts_ref = sinfo->rx[chan].pkts; + } + sinfo->rxticks = 0; + } + + /* Update tokens for Rx rate control */ + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (sinfo->rx[chan].tokens < sinfo->rx[chan].burst_max) { + bkn_rx_add_tokens(sinfo, chan); + } + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + add_timer(&sinfo->rxtick); +} + +static void +bkn_rx_rate_config(bkn_switch_info_t *sinfo) +{ + unsigned long flags; + int chan; + uint32_t rxticks_per_sec, rps; + uint32_t jiffies_per_rxtick; + uint32_t tokens_per_rxtick; + + spin_lock_irqsave(&sinfo->lock, flags); + + /* Calculate the minimum update frequency across all channels */ + rxticks_per_sec = 1; + for (chan = 0; chan < NUM_RX_CHAN; chan++) { + if (sinfo->rx[chan].burst_max == 0) { + sinfo->rx[chan].burst_max = sinfo->rx[chan].rate_max / 10; + } + rps = sinfo->rx[chan].rate_max / sinfo->rx[chan].burst_max; + if (rxticks_per_sec < rps) { + rxticks_per_sec = rps; + } + } + + /* Convert update frequency to system ticks */ + jiffies_per_rxtick = HZ / rxticks_per_sec; + if (jiffies_per_rxtick == 0) { + jiffies_per_rxtick = 1; + } + rxticks_per_sec = HZ / jiffies_per_rxtick; + + for (chan = 0; chan < NUM_RX_CHAN; chan++) { + /* Ensure that burst size satifies overall rate */ + tokens_per_rxtick = sinfo->rx[chan].rate_max / rxticks_per_sec; + if (sinfo->rx[chan].burst_max < tokens_per_rxtick) { + sinfo->rx[chan].burst_max = tokens_per_rxtick; + } + /* Ensure that rate has a sane value */ + if (sinfo->rx[chan].rate_max != 0) { + if (sinfo->rx[chan].rate_max < rxticks_per_sec) { + sinfo->rx[chan].rate_max = rxticks_per_sec; + } + } + sinfo->rx[chan].tokens = sinfo->rx[chan].burst_max; + } + + /* Update timer controls */ + sinfo->rxticks_per_sec = rxticks_per_sec; + sinfo->rxtick_jiffies = jiffies_per_rxtick; + + spin_unlock_irqrestore(&sinfo->lock, flags); +} + +static void +bkn_destroy_sinfo(bkn_switch_info_t *sinfo) +{ + list_del(&sinfo->list); + bkn_free_dcbs(sinfo); + kfree(sinfo); +} + +static bkn_switch_info_t * +bkn_create_sinfo(int dev_no) +{ + bkn_switch_info_t *sinfo; + int chan; + + if ((sinfo = kmalloc(sizeof(*sinfo), GFP_KERNEL)) == NULL) { + return NULL; + } + memset(sinfo, 0, sizeof(*sinfo)); + INIT_LIST_HEAD(&sinfo->ndev_list); + INIT_LIST_HEAD(&sinfo->rxpf_list); + sinfo->base_addr = lkbde_get_dev_virt(dev_no); + sinfo->dma_dev = lkbde_get_dma_dev(dev_no); + sinfo->pdev = lkbde_get_hw_dev(dev_no); + sinfo->dev_no = dev_no; + sinfo->evt_idx = -1; + + spin_lock_init(&sinfo->lock); + + init_timer(&sinfo->timer); + sinfo->timer.expires = jiffies + 1; + sinfo->timer.data = (unsigned long)sinfo; + sinfo->timer.function = bkn_timer; + + INIT_LIST_HEAD(&sinfo->tx.api_dcb_list); + + for (chan = 0; chan < NUM_RX_CHAN; chan++) { + INIT_LIST_HEAD(&sinfo->rx[chan].api_dcb_list); + sinfo->rx[chan].use_rx_skb = use_rx_skb; + } + + /* + * Check for dual DMA mode where Rx DMA channel 0 uses DMA buffers + * provided by the BCM API, and the remaining Rx DMA channel(s) + * use socket buffers (SKB) provided by the Linux kernel. + */ + if (use_rx_skb == 2) { + sinfo->rx[0].use_rx_skb = 0; + } + + init_timer(&sinfo->rxtick); + sinfo->rxtick.expires = jiffies + 1; + sinfo->rxtick.data = (unsigned long)sinfo; + sinfo->rxtick.function = bkn_rxtick; + + for (chan = 0; chan < NUM_RX_CHAN; chan++) { + sinfo->rx[chan].rate_max = rx_rate[chan]; + sinfo->rx[chan].burst_max = rx_burst[chan]; + } + bkn_rx_rate_config(sinfo); + + add_timer(&sinfo->rxtick); + + list_add_tail(&sinfo->list, &_sinfo_list); + + return sinfo; +} + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) +static const struct net_device_ops bkn_netdev_ops = { + .ndo_open = bkn_open, + .ndo_stop = bkn_stop, + .ndo_start_xmit = bkn_tx, + .ndo_get_stats = bkn_get_stats, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_rx_mode = bkn_set_multicast_list, + .ndo_set_mac_address = bkn_set_mac_address, + .ndo_do_ioctl = NULL, + .ndo_tx_timeout = NULL, + .ndo_change_mtu = bkn_change_mtu, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = bkn_poll_controller, +#endif +}; +#endif + +static struct net_device * +bkn_init_ndev(u8 *mac, char *name) +{ + struct net_device *dev; + + /* Create Ethernet device */ + dev = alloc_etherdev(sizeof(bkn_priv_t)); + + if (dev == NULL) { + DBG_WARN(("Error allocating Ethernet device.\n")); + return NULL; + } +#ifdef SET_MODULE_OWNER + SET_MODULE_OWNER(dev); +#endif + + /* Set the device MAC address */ + memcpy(dev->dev_addr, mac, 6); + + /* Device information -- not available right now */ + dev->irq = 0; + dev->base_addr = 0; + + /* Default MTU should not exceed MTU of switch front-panel ports */ + dev->mtu = default_mtu; + if (dev->mtu == 0) { + dev->mtu = rx_buffer_size; + } + + /* Device vectors */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) + dev->netdev_ops = &bkn_netdev_ops; +#else + dev->open = bkn_open; + dev->hard_start_xmit = bkn_tx; + dev->stop = bkn_stop; + dev->set_multicast_list = bkn_set_multicast_list; + dev->do_ioctl = NULL; + dev->get_stats = bkn_get_stats; + dev->change_mtu = bkn_change_mtu; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = bkn_poll_controller; +#endif +#endif + if (name && *name) { + strncpy(dev->name, name, IFNAMSIZ-1); + } + + /* Register the kernel Ethernet device */ + if (register_netdev(dev)) { + DBG_WARN(("Error registering Ethernet device.\n")); + free_netdev(dev); + return NULL; + } + DBG_VERB(("Created Ethernet device %s.\n", dev->name)); + + return dev; +} + +/* + * Device Link Control Proc Read Entry + */ +static int +bkn_proc_link_show(struct seq_file *m, void *v) +{ + struct list_head *slist, *dlist; + struct net_device *dev; + bkn_priv_t *priv; + bkn_switch_info_t *sinfo; + unsigned long flags; + + seq_printf(m, "Software link status:\n"); + list_for_each(slist, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)slist; + spin_lock_irqsave(&sinfo->lock, flags); + list_for_each(dlist, &sinfo->ndev_list) { + priv = (bkn_priv_t *)dlist; + dev = priv->dev; + if (dev) { + seq_printf(m, " %-14s %s\n", dev->name, + netif_carrier_ok(dev) ? "up" : "down"); + } + } + spin_unlock_irqrestore(&sinfo->lock, flags); + } + return 0; +} + +static int +bkn_proc_link_open(struct inode * inode, struct file * file) +{ + return single_open(file, bkn_proc_link_show, NULL); +} + +/* + * Device Link Control Proc Write Entry + * + * Syntax: + * =up|down + * + * Where is a virtual network interface name. + * + * Examples: + * eth4=up + * eth4=down + */ +static ssize_t +bkn_proc_link_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + struct list_head *slist, *dlist; + struct net_device *dev; + bkn_priv_t *priv; + bkn_switch_info_t *sinfo; + unsigned long flags; + char link_str[40]; + char *ptr; + char *newline; + + if (count > sizeof(link_str)) { + count = sizeof(link_str) - 1; + link_str[count] = '\0'; + } + if (copy_from_user(link_str, buf, count)) { + return -EFAULT; + } + link_str[count] = 0; + newline = strchr(link_str, '\n'); + if (newline) { + /* Chop off the trailing newline */ + *newline = '\0'; + } + + if ((ptr = strchr(link_str, '=')) == NULL && + (ptr = strchr(link_str, ':')) == NULL) { + gprintk("Error: link syntax not recognized: '%s'\n", link_str); + return count; + } + *ptr++ = 0; + + dev = NULL; + list_for_each(slist, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)slist; + spin_lock_irqsave(&sinfo->lock, flags); + list_for_each(dlist, &sinfo->ndev_list) { + priv = (bkn_priv_t *)dlist; + if (priv->dev) { + if (strcmp(priv->dev->name, link_str) == 0) { + dev = priv->dev; + break; + } + } + } + if (dev) { + if (strcmp(ptr, "up") == 0) { + netif_carrier_on(dev); + } else if (strcmp(ptr, "down") == 0) { + netif_carrier_off(dev); + } else { + gprintk("Warning: unknown link state setting: '%s'\n", ptr); + } + spin_unlock_irqrestore(&sinfo->lock, flags); + return count; + } + spin_unlock_irqrestore(&sinfo->lock, flags); + } + + gprintk("Warning: unknown network interface: '%s'\n", link_str); + + return count; +} + +struct file_operations bkn_proc_link_file_ops = { + owner: THIS_MODULE, + open: bkn_proc_link_open, + read: seq_read, + llseek: seq_lseek, + write: bkn_proc_link_write, + release: single_release, +}; + +/* + * Device Rate Control Proc Read Entry + */ +static int +bkn_proc_rate_show(struct seq_file *m, void *v) +{ + int unit = 0; + struct list_head *list; + bkn_switch_info_t *sinfo; + int chan; + + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + + seq_printf(m, "Rate control (unit %d):\n", unit); + for (chan = 0; chan < sinfo->rx_chans; chan++) { + seq_printf(m, " Rx%d max rate %8u\n", + chan, sinfo->rx[chan].rate_max); + seq_printf(m, " Rx%d max burst %8u\n", + chan, sinfo->rx[chan].burst_max); + seq_printf(m, " Rx%d rate %8u\n", + chan, sinfo->rx[chan].rate); + seq_printf(m, " Rx%d tokens %8u\n", + chan, sinfo->rx[chan].tokens); + } + + unit++; + } + return 0; +} + +static int +bkn_proc_rate_open(struct inode * inode, struct file * file) +{ + return single_open(file, bkn_proc_rate_show, NULL); +} + +/* + * Device Rate Control Proc Write Entry + * + * Syntax: + * [:]rx_rate=[,[, is packets/sec for the first Rx DMA channel, + * is packets/sec for the second Rx DMA channel, etc. + * + * Examples: + * rx_rate=5000 + * 0:rx_rate=10000,10000 + * 1:rx_rate=10000,5000 + */ +static ssize_t +bkn_proc_rate_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + bkn_switch_info_t *sinfo; + char rate_str[80]; + char *ptr; + int unit, chan; + + if (count > sizeof(rate_str)) { + count = sizeof(rate_str) - 1; + rate_str[count] = '\0'; + } + if (copy_from_user(rate_str, buf, count)) { + return -EFAULT; + } + + unit = simple_strtol(rate_str, NULL, 10); + sinfo = bkn_sinfo_from_unit(unit); + if (sinfo == NULL) { + gprintk("Warning: unknown unit: %d\n", unit); + return count; + } + + if ((ptr = strstr(rate_str, "rx_rate=")) != NULL) { + ptr += 7; + chan = 0; + do { + ptr++; + sinfo->rx[chan].rate_max = simple_strtol(ptr, NULL, 10); + } while ((ptr = strchr(ptr, ',')) != NULL && ++chan < sinfo->rx_chans); + bkn_rx_rate_config(sinfo); + } else if ((ptr = strstr(rate_str, "rx_burst=")) != NULL) { + ptr += 8; + chan = 0; + do { + ptr++; + sinfo->rx[chan].burst_max = simple_strtol(ptr, NULL, 10); + } while ((ptr = strchr(ptr, ',')) != NULL && ++chan < sinfo->rx_chans); + bkn_rx_rate_config(sinfo); + } else { + gprintk("Warning: unknown configuration setting\n"); + } + + return count; +} + +struct file_operations bkn_proc_rate_file_ops = { + owner: THIS_MODULE, + open: bkn_proc_rate_open, + read: seq_read, + llseek: seq_lseek, + write: bkn_proc_rate_write, + release: single_release, +}; + +/* + * Driver DMA Proc Entry + * + * This output can be rather large (> PAGE_SIZE) so we use the + * seq_file interface to do the output. Special header records + * are indicated by a negative DCB index. + */ +typedef struct { + int dev_no; /* Current unit */ + int rx_dma; /* 0: Tx DMA, 1: Rx DMA*/ + int ch_no; /* DMA channel no. (Rx only) */ + int idx; /* DCB index */ +} bkn_seq_dma_iter_t; + +/* From current record, move forward 'pos' records */ +static int +bkn_seq_dma_next_pos(bkn_seq_dma_iter_t *iter, loff_t pos) +{ + bkn_switch_info_t *sinfo; + + sinfo = bkn_sinfo_from_unit(iter->dev_no); + while (pos) { + if (iter->rx_dma) { + if (++iter->idx >= MAX_RX_DCBS + 1) { + iter->idx = -1; + if (++iter->ch_no >= sinfo->rx_chans) { + iter->rx_dma = 0; + iter->ch_no = 0; + iter->dev_no++; + if ((sinfo = bkn_sinfo_from_unit(iter->dev_no)) == NULL) { + return -1; + } + } + } + } else { + if (++iter->idx >= MAX_TX_DCBS + 1) { + iter->idx = -1; + iter->rx_dma = 1; + } + } + pos--; + } + return 0; +} + +/* Initialize private data and move to requested start record */ +static void * +bkn_seq_dma_start(struct seq_file *s, loff_t *pos) +{ + bkn_seq_dma_iter_t *iter; + + iter = kmalloc(sizeof(bkn_seq_dma_iter_t), GFP_KERNEL); + if (!iter) { + return NULL; + } + memset(iter, 0, sizeof(*iter)); + iter->idx = -2; + if (bkn_seq_dma_next_pos(iter, *pos) < 0) { + kfree(iter); + return NULL; + } + return iter; +} + +/* Move to next record */ +static void * +bkn_seq_dma_next(struct seq_file *s, void *v, loff_t *pos) +{ + bkn_seq_dma_iter_t *iter = (bkn_seq_dma_iter_t *)v; + void *rv = iter; + + if (bkn_seq_dma_next_pos(iter, 1) < 0) { + return NULL; + } + (*pos)++; + return rv; +} + +/* Release private data */ +static void +bkn_seq_dma_stop(struct seq_file *s, void *v) +{ + if (v) { + kfree(v); + } +} + +/* Print current record */ +static int +bkn_seq_dma_show(struct seq_file *s, void *v) +{ + bkn_seq_dma_iter_t *iter = (bkn_seq_dma_iter_t *)v; + bkn_switch_info_t *sinfo; + uint32_t *dcb = NULL; + bkn_dcb_chain_t *dcb_chain = NULL; + struct list_head *curr, *next; + unsigned long flags; + int chan, cnt; + + sinfo = bkn_sinfo_from_unit(iter->dev_no); + if (sinfo == NULL) { + /* Should not happen */ + return 0; + } + + if (iter->rx_dma == 0) { + if (iter->idx == -2) { + seq_printf(s, "Pending events: 0x%x\n", sinfo->dma_events); + } else if (iter->idx == -1) { + spin_lock_irqsave(&sinfo->lock, flags); + curr = &sinfo->tx.api_dcb_list; + dcb_chain = sinfo->tx.api_dcb_chain; + while (dcb_chain) { + seq_printf(s, " [0x%08lx]--->\n", (unsigned long)dcb_chain->dcb_dma); + for (cnt = 0; cnt < dcb_chain->dcb_cnt; cnt++) { + dcb = &dcb_chain->dcb_mem[sinfo->dcb_wsize * cnt]; + if (sinfo->cmic_type == 'x') { + seq_printf(s, " DCB %2d: 0x%08x 0x%08x 0x%08x 0x%08x\n", cnt, + dcb[0], dcb[1], dcb[2], dcb[sinfo->dcb_wsize-1]); + } else { + seq_printf(s, " DCB %2d: 0x%08x 0x%08x ... 0x%08x\n", cnt, + dcb[0], dcb[1], dcb[sinfo->dcb_wsize-1]); + } + } + next = curr->next; + if (next != &sinfo->tx.api_dcb_list) { + dcb_chain = list_entry(next, bkn_dcb_chain_t, list); + curr = next; + } else { + dcb_chain = NULL; + } + } + dcb = NULL; + spin_unlock_irqrestore(&sinfo->lock, flags); + seq_printf(s, + "Tx DCB info (unit %d):\n" + " api: %d\n" + " dirty: %d\n" + " cur: %d\n" + " free: %d\n" + " pause: %s\n", + iter->dev_no, + sinfo->tx.api_active, + sinfo->tx.dirty, + sinfo->tx.cur, + sinfo->tx.free, + netif_queue_stopped(sinfo->dev) ? "yes" : "no"); + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + bkn_desc_info_t *desc = &sinfo->tx.desc[0]; + uint64_t halt = sinfo->halt_addr[XGS_DMA_TX_CHAN]; + seq_printf(s, + " halt: %d\n", + (int)((uint32_t)(halt - desc->dcb_dma) / (sinfo->dcb_wsize * sizeof(uint32_t)))); + } + } else { + dcb = sinfo->tx.desc[iter->idx].dcb_mem; + if (iter->idx == 0) { + seq_printf(s, " [0x%08lx]--->\n", (unsigned long)sinfo->tx.desc[0].dcb_dma); + } + } + } else { + if (iter->idx == -1) { + chan = iter->ch_no; + seq_printf(s, + "Rx%d DCB info (unit %d):\n" + " api: %d\n" + " wait: %d\n" + " dirty: %d\n" + " cur: %d\n" + " free: %d\n" + " run: %d\n", + chan, iter->dev_no, + sinfo->rx[chan].api_active, + sinfo->rx[chan].api_wait, + sinfo->rx[chan].dirty, + sinfo->rx[chan].cur, + sinfo->rx[chan].free, + sinfo->rx[chan].running); + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) && sinfo->rx[chan].use_rx_skb) { + bkn_desc_info_t *desc = &sinfo->rx[chan].desc[0]; + uint64_t halt = sinfo->halt_addr[XGS_DMA_RX_CHAN + chan]; + seq_printf(s, + " halt: %d\n", + (int)((uint32_t)(halt - desc->dcb_dma) / (sinfo->dcb_wsize * sizeof(uint32_t)))); + } + } else if (sinfo->rx[iter->ch_no].use_rx_skb) { + dcb = sinfo->rx[iter->ch_no].desc[iter->idx].dcb_mem; + if (iter->idx == 0) { + seq_printf(s, " [0x%08lx]--->\n", (unsigned long)sinfo->rx[iter->ch_no].desc[0].dcb_dma); + } + } else if (!sinfo->rx[iter->ch_no].use_rx_skb && iter->idx == 0) { + spin_lock_irqsave(&sinfo->lock, flags); + curr = &sinfo->rx[iter->ch_no].api_dcb_list; + dcb_chain = sinfo->rx[iter->ch_no].api_dcb_chain; + while (dcb_chain) { + seq_printf(s, " [0x%08lx]--->\n", (unsigned long)dcb_chain->dcb_dma); + for (cnt = 0; cnt < dcb_chain->dcb_cnt; cnt++) { + dcb = &dcb_chain->dcb_mem[sinfo->dcb_wsize * cnt]; + if (sinfo->cmic_type == 'x') { + seq_printf(s, " DCB %2d: 0x%08x 0x%08x 0x%08x 0x%08x\n", cnt, + dcb[0], dcb[1], dcb[2], dcb[sinfo->dcb_wsize-1]); + } else { + seq_printf(s, " DCB %2d: 0x%08x 0x%08x ... 0x%08x\n", cnt, + dcb[0], dcb[1], dcb[sinfo->dcb_wsize-1]); + } + } + next = curr->next; + if (next != &sinfo->rx[iter->ch_no].api_dcb_list) { + dcb_chain = list_entry(next, bkn_dcb_chain_t, list); + curr = next; + } else { + dcb_chain = NULL; + } + } + dcb = NULL; + spin_unlock_irqrestore(&sinfo->lock, flags); + } + } + if (dcb) { + if (sinfo->cmic_type == 'x') { + seq_printf(s, " DCB %2d: 0x%08x 0x%08x 0x%08x 0x%08x\n", iter->idx, + dcb[0], dcb[1], dcb[2], dcb[sinfo->dcb_wsize-1]); + } else { + seq_printf(s, " DCB %2d: 0x%08x 0x%08x ... 0x%08x\n", iter->idx, + dcb[0], dcb[1], dcb[sinfo->dcb_wsize-1]); + } + } + return 0; +} + +static struct seq_operations bkn_seq_dma_ops = { + .start = bkn_seq_dma_start, + .next = bkn_seq_dma_next, + .stop = bkn_seq_dma_stop, + .show = bkn_seq_dma_show +}; + +static int +bkn_seq_dma_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &bkn_seq_dma_ops); +}; + +static struct file_operations bkn_seq_dma_file_ops = { + .owner = THIS_MODULE, + .open = bkn_seq_dma_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; + +/* + * Device Debug Control Proc Write Entry + * + * Syntax: + * [:]debug= + * + * Where corresponds to the debug module parameter. + * + * Examples: + * debug=0xffff + * 0:debug-0x2000 + */ +static ssize_t +bkn_proc_debug_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + bkn_switch_info_t *sinfo; + char debug_str[40]; + char *ptr; + int unit; + + if (count > sizeof(debug_str)) { + count = sizeof(debug_str) - 1; + debug_str[count] = '\0'; + } + if (copy_from_user(debug_str, buf, count)) { + return -EFAULT; + } + + unit = simple_strtol(debug_str, NULL, 10); + sinfo = bkn_sinfo_from_unit(unit); + if (sinfo == NULL) { + gprintk("Warning: unknown unit: %d\n", unit); + return count; + } + + if ((ptr = strstr(debug_str, "debug=")) != NULL) { + ptr += 6; + debug = simple_strtol(ptr, NULL, 0); + } else { + gprintk("Warning: unknown configuration setting\n"); + } + + return count; +} + +/* + * Driver Debug Proc Entry + */ +static int +bkn_proc_debug_show(struct seq_file *m, void *v) +{ + int unit = 0; + struct list_head *list; + bkn_switch_info_t *sinfo; + + seq_printf(m, "Configuration:\n"); + seq_printf(m, " debug: 0x%x\n", debug); + seq_printf(m, " mac_addr: %02x:%02x:%02x:%02x:%02x:%02x\n", + bkn_dev_mac[0], bkn_dev_mac[1], bkn_dev_mac[2], + bkn_dev_mac[3], bkn_dev_mac[4], bkn_dev_mac[5]); + seq_printf(m, " rx_buffer_size: %d (0x%x)\n", + rx_buffer_size, rx_buffer_size); + seq_printf(m, " rcpu_mode: %d\n", rcpu_mode); + seq_printf(m, " rcpu_dmac: %02x:%02x:%02x:%02x:%02x:%02x\n", + bkn_rcpu_dmac[0], bkn_rcpu_dmac[1], bkn_rcpu_dmac[2], + bkn_rcpu_dmac[3], bkn_rcpu_dmac[4], bkn_rcpu_dmac[5]); + seq_printf(m, " rcpu_smac: %02x:%02x:%02x:%02x:%02x:%02x\n", + bkn_rcpu_smac[0], bkn_rcpu_smac[1], bkn_rcpu_smac[2], + bkn_rcpu_smac[3], bkn_rcpu_smac[4], bkn_rcpu_smac[5]); + seq_printf(m, " rcpu_ethertype: 0x%x\n", rcpu_ethertype); + seq_printf(m, " rcpu_signature: 0x%x\n", rcpu_signature); + seq_printf(m, " rcpu_vlan: %d\n", rcpu_vlan); + seq_printf(m, " use_rx_skb: %d\n", use_rx_skb); + seq_printf(m, " num_rx_prio: %d\n", num_rx_prio); + seq_printf(m, " check_rcpu_sig: %d\n", check_rcpu_signature); + seq_printf(m, " default_mtu: %d\n", default_mtu); + seq_printf(m, " rx_sync_retry: %d\n", rx_sync_retry); + seq_printf(m, " use_napi: %d\n", use_napi); + seq_printf(m, " napi_weight: %d\n", napi_weight); + seq_printf(m, " basedev_susp: %d\n", basedev_suspend); + seq_printf(m, "Thread states:\n"); + seq_printf(m, " Command thread: %d\n", bkn_cmd_ctrl.state); + seq_printf(m, " Event thread: %d\n", bkn_evt_ctrl.state); + seq_printf(m, "Active IOCTLs:\n"); + seq_printf(m, " Command: %d\n", ioctl_cmd); + seq_printf(m, " Event: %d\n", ioctl_evt); + + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + + seq_printf(m, "Device %d:\n", unit); + seq_printf(m, " base_addr: 0x%p\n", sinfo->base_addr); + seq_printf(m, " dev_no: %d\n", sinfo->dev_no); + seq_printf(m, " cmic_type: %c\n", sinfo->cmic_type); + seq_printf(m, " dcb_type: %d\n", sinfo->dcb_type); + seq_printf(m, " dcb_wsize: %d\n", sinfo->dcb_wsize); + seq_printf(m, " pkt_hdr_size: %d\n", sinfo->pkt_hdr_size); + seq_printf(m, " rx_chans: %d\n", sinfo->rx_chans); + seq_printf(m, " cdma_chans: 0x%x\n", sinfo->cdma_channels); + seq_printf(m, " irq_mask: 0x%x\n", sinfo->irq_mask); + seq_printf(m, " dma_events: 0x%x\n", sinfo->dma_events); + seq_printf(m, " dcb_dma: 0x%p\n", (void *)(sal_paddr_t)sinfo->dcb_dma); + seq_printf(m, " dcb_mem_size: 0x%x\n", sinfo->dcb_mem_size); + seq_printf(m, " rcpu_sig: 0x%x\n", sinfo->rcpu_sig); + seq_printf(m, " napi_poll_mode: %d\n", sinfo->napi_poll_mode); + seq_printf(m, " inst_id: 0x%x\n", sinfo->inst_id); + seq_printf(m, " evt_queue: %d\n", sinfo->evt_idx); + + unit++; + } + + return 0; +} + +static int bkn_proc_debug_open(struct inode * inode, struct file * file) +{ + return single_open(file, bkn_proc_debug_show, NULL); +} + +struct file_operations bkn_proc_debug_file_ops = { + owner: THIS_MODULE, + open: bkn_proc_debug_open, + read: seq_read, + llseek: seq_lseek, + write: bkn_proc_debug_write, + release: single_release, +}; + +/* + * Device Statistics Proc Entry + */ +static int +bkn_proc_stats_show(struct seq_file *m, void *v) +{ + int unit = 0; + struct list_head *list, *flist; + bkn_switch_info_t *sinfo; + bkn_filter_t *filter; + int chan; + + + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + + seq_printf(m, "Device stats (unit %d):\n", unit); + seq_printf(m, " Interrupts %10u\n", sinfo->interrupts); + seq_printf(m, " Tx packets %10u\n", sinfo->tx.pkts); + for (chan = 0; chan < sinfo->rx_chans; chan++) { + seq_printf(m, " Rx%d packets %10u\n", chan, sinfo->rx[chan].pkts); + } + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (sinfo->interrupts == 0) { + /* Avoid divide-by-zero */ + seq_printf(m, " Rx%d pkts/intr -\n", chan); + } else { + seq_printf(m, " Rx%d pkts/intr %8u\n", + chan, sinfo->rx[chan].pkts / sinfo->interrupts); + } + } + seq_printf(m, " Timer runs %10u\n", sinfo->timer_runs); + seq_printf(m, " NAPI reruns %10u\n", sinfo->napi_not_done); + + list_for_each(flist, &sinfo->rxpf_list) { + filter = (bkn_filter_t *)flist; + + seq_printf(m, " Filter %d stats:\n", filter->kf.id); + seq_printf(m, " Hits %10lu\n", filter->hits); + } + + unit++; + } + return 0; +} + +static int bkn_proc_stats_open(struct inode * inode, struct file * file) +{ + return single_open(file, bkn_proc_stats_show, NULL); +} + +/* + * Device Statistics Proc Write Entry + * + * Syntax: + * [:]clear[=all] + * + * Where corresponds to the debug module parameter. + * + * Examples: + * clear + * 0:clear=all + */ +static ssize_t +bkn_proc_stats_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + bkn_switch_info_t *sinfo; + struct list_head *flist; + bkn_filter_t *filter; + char debug_str[40]; + char *ptr; + int unit; + int clear_mask; + int chan; + + if (count > sizeof(debug_str)) { + count = sizeof(debug_str) - 1; + debug_str[count] = '\0'; + } + if (copy_from_user(debug_str, buf, count)) { + return -EFAULT; + } + + unit = simple_strtol(debug_str, NULL, 10); + sinfo = bkn_sinfo_from_unit(unit); + if (sinfo == NULL) { + gprintk("Warning: unknown unit: %d\n", unit); + return count; + } + + clear_mask = 0; + if ((ptr = strstr(debug_str, "clear=")) != NULL) { + ptr += 6; + if (strncmp(ptr, "all", 3) == 0) { + clear_mask = ~0; + } + } else if ((ptr = strstr(debug_str, "clear")) != NULL) { + clear_mask = ~0; + } else { + gprintk("Warning: unknown configuration setting\n"); + } + + if (clear_mask) { + sinfo->tx.pkts = 0; + for (chan = 0; chan < sinfo->rx_chans; chan++) { + sinfo->rx[chan].pkts = 0; + } + sinfo->interrupts = 0; + sinfo->timer_runs = 0; + sinfo->napi_not_done = 0; + list_for_each(flist, &sinfo->rxpf_list) { + filter = (bkn_filter_t *)flist; + filter->hits = 0; + } + } + + return count; +} + +struct file_operations bkn_proc_stats_file_ops = { + owner: THIS_MODULE, + open: bkn_proc_stats_open, + read: seq_read, + llseek: seq_lseek, + write: bkn_proc_stats_write, + release: single_release, +}; + +/* + * Device Debug Statistics Proc Entry + */ +static int +bkn_proc_dstats_show(struct seq_file *m, void *v) +{ + int unit = 0; + struct list_head *list; + bkn_switch_info_t *sinfo; + int chan; + + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + + seq_printf(m, "Device debug stats (unit %d):\n", unit); + seq_printf(m, " Tx drop no skb %10u\n", + sinfo->tx.pkts_d_no_skb); + seq_printf(m, " Tx drop rcpu encap %10u\n", + sinfo->tx.pkts_d_rcpu_encap); + seq_printf(m, " Tx drop rcpu sig %10u\n", + sinfo->tx.pkts_d_rcpu_sig); + seq_printf(m, " Tx drop rcpu meta %10u\n", + sinfo->tx.pkts_d_rcpu_meta); + seq_printf(m, " Tx drop pad failed %10u\n", + sinfo->tx.pkts_d_pad_fail); + seq_printf(m, " Tx drop no resource %10u\n", + sinfo->tx.pkts_d_dma_resrc); + seq_printf(m, " Tx drop callback %10u\n", + sinfo->tx.pkts_d_callback); + seq_printf(m, " Tx drop no link %10u\n", + sinfo->tx.pkts_d_no_link); + seq_printf(m, " Tx drop oversized %10u\n", + sinfo->tx.pkts_d_over_limit); + seq_printf(m, " Tx suspends %10u\n", + sinfo->tx.suspends); + for (chan = 0; chan < sinfo->rx_chans; chan++) { + seq_printf(m, " Rx%d filter to api %10u\n", + chan, sinfo->rx[chan].pkts_f_api); + seq_printf(m, " Rx%d filter to netif %10u\n", + chan, sinfo->rx[chan].pkts_f_netif); + seq_printf(m, " Rx%d mirror to api %10u\n", + chan, sinfo->rx[chan].pkts_m_api); + seq_printf(m, " Rx%d mirror to netif %10u\n", + chan, sinfo->rx[chan].pkts_m_netif); + seq_printf(m, " Rx%d drop no skb %10u\n", + chan, sinfo->rx[chan].pkts_d_no_skb); + seq_printf(m, " Rx%d drop no match %10u\n", + chan, sinfo->rx[chan].pkts_d_no_match); + seq_printf(m, " Rx%d drop unkn netif %10u\n", + chan, sinfo->rx[chan].pkts_d_unkn_netif); + seq_printf(m, " Rx%d drop unkn dest %10u\n", + chan, sinfo->rx[chan].pkts_d_unkn_dest); + seq_printf(m, " Rx%d drop callback %10u\n", + chan, sinfo->rx[chan].pkts_d_callback); + seq_printf(m, " Rx%d drop no link %10u\n", + chan, sinfo->rx[chan].pkts_d_no_link); + seq_printf(m, " Rx%d sync error %10u\n", + chan, sinfo->rx[chan].sync_err); + seq_printf(m, " Rx%d sync retry %10u\n", + chan, sinfo->rx[chan].sync_retry); + seq_printf(m, " Rx%d sync maxloop %10u\n", + chan, sinfo->rx[chan].sync_maxloop); + seq_printf(m, " Rx%d drop no buffer %10u\n", + chan, sinfo->rx[chan].pkts_d_no_api_buf); + } + unit++; + } + return 0; +} + +static int bkn_proc_dstats_open(struct inode * inode, struct file * file) +{ + return single_open(file, bkn_proc_dstats_show, NULL); +} + +/* + * Device Debug Statistics Proc Write Entry + * + * Syntax: + * [:]clear[=all|tx|rx[]] + * + * Where corresponds to the debug module parameter. + * + * Examples: + * clear + * 0:clear=rx1 + */ +static ssize_t +bkn_proc_dstats_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + bkn_switch_info_t *sinfo; + char debug_str[40]; + char *ptr; + int unit; + int clear_mask; + int chan; + + if (count > sizeof(debug_str)) { + count = sizeof(debug_str) - 1; + debug_str[count] = '\0'; + } + if (copy_from_user(debug_str, buf, count)) { + return -EFAULT; + } + + unit = simple_strtol(debug_str, NULL, 10); + sinfo = bkn_sinfo_from_unit(unit); + if (sinfo == NULL) { + gprintk("Warning: unknown unit: %d\n", unit); + return count; + } + + clear_mask = 0; + if ((ptr = strstr(debug_str, "clear=")) != NULL) { + ptr += 6; + if (strncmp(ptr, "all", 3) == 0) { + clear_mask = ~0; + } else if (strncmp(ptr, "dev", 3) == 0) { + clear_mask = 0x20; + } else if (strncmp(ptr, "tx", 2) == 0) { + clear_mask = 0x10; + } else if (strncmp(ptr, "rx0", 3) == 0) { + clear_mask = (1 << 0); + } else if (strncmp(ptr, "rx1", 3) == 0) { + clear_mask = (1 << 1); + } else if (strncmp(ptr, "rx", 2) == 0) { + clear_mask = 0xf; + } + } else if ((ptr = strstr(debug_str, "clear")) != NULL) { + clear_mask = ~0; + } else { + gprintk("Warning: unknown configuration setting\n"); + } + + /* Tx counters */ + if (clear_mask & 0x10) { + sinfo->tx.pkts_d_no_skb = 0; + sinfo->tx.pkts_d_rcpu_encap = 0; + sinfo->tx.pkts_d_rcpu_sig = 0; + sinfo->tx.pkts_d_rcpu_meta = 0; + sinfo->tx.pkts_d_pad_fail = 0; + sinfo->tx.pkts_d_over_limit = 0; + sinfo->tx.pkts_d_dma_resrc = 0; + sinfo->tx.suspends = 0; + } + /* Rx counters */ + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (clear_mask & (1 << chan)) { + sinfo->rx[chan].pkts_f_api = 0; + sinfo->rx[chan].pkts_f_netif = 0; + sinfo->rx[chan].pkts_m_api = 0; + sinfo->rx[chan].pkts_m_netif = 0; + sinfo->rx[chan].pkts_d_no_skb = 0; + sinfo->rx[chan].pkts_d_no_match = 0; + sinfo->rx[chan].pkts_d_unkn_netif = 0; + sinfo->rx[chan].pkts_d_unkn_dest = 0; + sinfo->rx[chan].pkts_d_no_api_buf = 0; + sinfo->rx[chan].sync_err = 0; + sinfo->rx[chan].sync_retry = 0; + sinfo->rx[chan].sync_maxloop = 0; + } + } + + return count; +} + +struct file_operations bkn_proc_dstats_file_ops = { + owner: THIS_MODULE, + open: bkn_proc_dstats_open, + read: seq_read, + llseek: seq_lseek, + write: bkn_proc_dstats_write, + release: single_release, +}; + +static int +bkn_proc_init(void) +{ + struct proc_dir_entry *entry; + + PROC_CREATE(entry, "link", 0666, bkn_proc_root, &bkn_proc_link_file_ops); + if (entry == NULL) { + return -1; + } + PROC_CREATE(entry, "rate", 0666, bkn_proc_root, &bkn_proc_rate_file_ops); + if (entry == NULL) { + return -1; + } + PROC_CREATE(entry, "dma", 0, bkn_proc_root, &bkn_seq_dma_file_ops); + if (entry == NULL) { + return -1; + } + PROC_CREATE(entry, "debug", 0666, bkn_proc_root, &bkn_proc_debug_file_ops); + if (entry == NULL) { + return -1; + } + PROC_CREATE(entry, "stats", 0666, bkn_proc_root, &bkn_proc_stats_file_ops); + if (entry == NULL) { + return -1; + } + PROC_CREATE(entry, "dstats", 0666, bkn_proc_root, &bkn_proc_dstats_file_ops); + if (entry == NULL) { + return -1; + } + + return 0; +} + +static int +bkn_proc_cleanup(void) +{ + remove_proc_entry("link", bkn_proc_root); + remove_proc_entry("rate", bkn_proc_root); + remove_proc_entry("dma", bkn_proc_root); + remove_proc_entry("debug", bkn_proc_root); + remove_proc_entry("stats", bkn_proc_root); + remove_proc_entry("dstats", bkn_proc_root); + return 0; +} + +/* + * Generic module functions + */ + +static int +_pprint(void) +{ + pprintf("Broadcom BCM KNET Linux Network Driver\n"); + + return 0; +} + +static int +bkn_knet_dma_info(kcom_msg_dma_info_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_dcb_chain_t *dcb_chain, *dcb_chain_end; + unsigned long flags; + int chan; + uint64_t dcb_dma; + int woffset; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + dcb_chain = kmalloc(sizeof(*dcb_chain), GFP_KERNEL); + if (dcb_chain == NULL) { + gprintk("Fatal error: No memory for dcb_chain\n"); + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_hdr_t); + } + memset(dcb_chain, 0, sizeof(*dcb_chain)); + dcb_chain->dcb_cnt = kmsg->dma_info.cnt; + dcb_chain->dcb_dma = kmsg->dma_info.data.dcb_start; + dcb_chain->dcb_mem = kernel_bde->p2l(sinfo->dev_no, + (sal_paddr_t)dcb_chain->dcb_dma); + + if (kmsg->dma_info.type == KCOM_DMA_INFO_T_TX_DCB) { + spin_lock_irqsave(&sinfo->lock, flags); + + /* Hold back packets from kernel */ + bkn_suspend_tx(sinfo); + + list_add_tail(&dcb_chain->list, &sinfo->tx.api_dcb_list); + + /* Handle for Continuous DMA mode */ + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize + 1; + if (sinfo->cmic_type == 'x') { + woffset += 1; + } + if ((dcb_chain->dcb_mem[woffset] & ((1 << 18) | (1 << 16))) != 0x50000) { + gprintk("Not suitable API DCB chain for Continuous DMA mode\n"); + list_del(&dcb_chain->list); + kfree(dcb_chain); + kmsg->hdr.status = KCOM_E_PARAM; + spin_unlock_irqrestore(&sinfo->lock, flags); + return sizeof(kcom_msg_hdr_t); + } + dcb_chain_end = sinfo->tx.api_dcb_chain_end; + if (dcb_chain_end != NULL) { + /* Stitch this chain */ + woffset = (dcb_chain_end->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_chain_end->dcb_mem[woffset] = dcb_chain->dcb_dma; + if (sinfo->cmic_type == 'x') { + dcb_chain_end->dcb_mem[woffset + 1] = DMA_TO_BUS_HI(dcb_chain->dcb_dma >> 32); + } + } + sinfo->tx.api_dcb_chain_end = dcb_chain; + if (sinfo->tx.api_active) { + /* Set new halt location */ + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_dma = dcb_chain->dcb_dma + woffset * sizeof(uint32_t); + /* DMA run to the new halt location */ + bkn_cdma_goto(sinfo, XGS_DMA_TX_CHAN, dcb_dma); + } + } + + if (sinfo->tx.free == MAX_TX_DCBS && + !sinfo->tx.api_active && + !sinfo->basedev_suspended) { + bkn_api_tx(sinfo); + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + } else if (kmsg->dma_info.type == KCOM_DMA_INFO_T_RX_DCB) { + spin_lock_irqsave(&sinfo->lock, flags); + + chan = kmsg->dma_info.chan - 1; + if ((chan < 0) || (chan > sinfo->rx_chans)) { + gprintk("Invalid RX DMA channel specified: %d\n", + kmsg->dma_info.chan); + kmsg->hdr.status = KCOM_E_PARAM; + spin_unlock_irqrestore(&sinfo->lock, flags); + return sizeof(kcom_msg_hdr_t); + } + + list_add_tail(&dcb_chain->list, &sinfo->rx[chan].api_dcb_list); + + /* Handle for Continuous DMA mode */ + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize + 1; + if (sinfo->cmic_type == 'x') { + woffset += 1; + } + if ((dcb_chain->dcb_mem[woffset] & ((1 << 18) | (1 << 16))) != 0x50000) { + gprintk("Not suitable API DCB chain for Continuous DMA mode\n"); + list_del(&dcb_chain->list); + kfree(dcb_chain); + kmsg->hdr.status = KCOM_E_PARAM; + spin_unlock_irqrestore(&sinfo->lock, flags); + return sizeof(kcom_msg_hdr_t); + } + dcb_chain_end = sinfo->rx[chan].api_dcb_chain_end; + if (dcb_chain_end != NULL) { + /* Stitch this chain */ + woffset = (dcb_chain_end->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_chain_end->dcb_mem[woffset] = dcb_chain->dcb_dma; + if (sinfo->cmic_type == 'x') { + dcb_chain_end->dcb_mem[woffset + 1] = DMA_TO_BUS_HI(dcb_chain->dcb_dma >> 32); + } + } + sinfo->rx[chan].api_dcb_chain_end = dcb_chain; + if (!sinfo->rx[chan].use_rx_skb) { + /* Set new halt location */ + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_dma = dcb_chain->dcb_dma + woffset * sizeof(uint32_t); + /* DMA run to the new halt location */ + bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, dcb_dma); + } + } + + if (sinfo->rx[chan].api_active == 0) { + bkn_api_rx_restart(sinfo, chan); + /* Resume SKB Rx due to refilled API resources */ + if (sinfo->rx[chan].use_rx_skb && sinfo->rx[chan].api_wait) { + sinfo->rx[chan].api_wait = 0; + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + bkn_do_skb_rx(sinfo, chan, 1); + } else { + bkn_do_skb_rx(sinfo, chan, MAX_RX_DCBS); + if (sinfo->rx[chan].chain_complete) { + bkn_rx_chain_done(sinfo, chan); + } + } + } + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + } else { + DBG_DCB(("Unknown DCB_INFO type (%d).\n", kmsg->dma_info.type)); + kfree(dcb_chain); + kmsg->hdr.status = KCOM_E_PARAM; + } + + return sizeof(kcom_msg_hdr_t); +} + +static int +bkn_create_inst(uint32 inst_id) +{ + bkn_switch_info_t *sinfo; + bkn_evt_resource_t *evt; + unsigned long flags; + int i, evt_idx = -1; + + /* multiple instance mode */ + for (i = 0; i < kernel_bde->num_devices(BDE_ALL_DEVICES); i++) { + evt = &_bkn_evt[i]; + if (evt->inst_id == inst_id) { + evt_idx = i; + DBG_INST(("%s evt_idx %d inst_id 0x%x\n",__FUNCTION__, i, inst_id)); + break; + } + if ((_bkn_multi_inst == 0) || (evt->inst_id == 0)) { + _bkn_multi_inst ++; + evt_idx = i; + init_waitqueue_head(&evt->evt_wq); + evt->inst_id = inst_id; + DBG_INST(("%s evt_idx %d inst_id 0x%x\n",__FUNCTION__, i, inst_id)); + break; + } + } + + if (evt_idx == -1) { + DBG_WARN(("Run out the event queue resource !\n")); + return -1; + } + for (i = 0; i < kernel_bde->num_devices(BDE_ALL_DEVICES); i++) { + if (inst_id & (1 << i)) { + sinfo = bkn_sinfo_from_unit(i); + spin_lock_irqsave(&sinfo->lock, flags); + sinfo->evt_idx = evt_idx; + spin_unlock_irqrestore(&sinfo->lock, flags); + DBG_INST(("%s d(%d) evt_idx %d \n",__FUNCTION__, i, evt_idx)); + } + } + return 0; +} + +/* + * Device reprobe driven by application to check if new device is probed or + * existed device is changed after inserting KNET module. + */ +static int +bkn_knet_dev_reprobe(void) +{ + bkn_switch_info_t *sinfo; + int i; + + for (i = 0; i < kernel_bde->num_devices(BDE_ALL_DEVICES); i++) { + sinfo = bkn_sinfo_from_unit(i); + if (sinfo == NULL ) { + /* New device found after re-probe. */ + if (bkn_knet_dev_init(i) < 0) { + return -1; + } + } else { + /* Existed device reinit after re-probe. */ + if (bkn_knet_dev_reinit(i) < 0) { + return -1; + } + } + } + return 0; +} + +/* Assign the inst_id and evt_idx */ +static int +bkn_knet_dev_inst_set(kcom_msg_version_t *kmsg) +{ + bkn_switch_info_t *sinfo; + int d = kmsg->hdr.unit; + uint32 inst = 0; + unsigned long flags; + struct list_head *list; + + sinfo = bkn_sinfo_from_unit(d); + lkbde_dev_instid_get(d, &inst); + + spin_lock_irqsave(&sinfo->lock, flags); + if (sinfo->inst_id != inst) { + /* Instance database changed, reinit the inst_id */ + sinfo->inst_id = 0; + sinfo->evt_idx = -1; + } + spin_unlock_irqrestore(&sinfo->lock, flags); + + if (inst) { + if (sinfo->inst_id == 0) { + if (bkn_create_inst(inst) != 0) { + return -1; + } + } + spin_lock_irqsave(&sinfo->lock, flags); + sinfo->inst_id = inst; + spin_unlock_irqrestore(&sinfo->lock, flags); + } else { + /* legacy mode */ + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + spin_lock_irqsave(&sinfo->lock, flags); + sinfo->evt_idx = 0; + sinfo->inst_id = 0; + spin_unlock_irqrestore(&sinfo->lock, flags); + } + } + return 0; +} + +static int +bkn_knet_version(kcom_msg_version_t *kmsg, int len) +{ + /* Support pci hot plug and multiple instance */ + if ((bkn_knet_dev_reprobe() < 0) || + (bkn_knet_dev_inst_set(kmsg) < 0)) { + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_version_t); + } + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + kmsg->version = KCOM_VERSION; + kmsg->netif_max = KCOM_NETIF_MAX; + kmsg->filter_max = KCOM_FILTER_MAX; + + return sizeof(kcom_msg_version_t); +} + +static int +bkn_knet_hw_reset(kcom_msg_hw_reset_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + unsigned long flags; + int chan; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + if (kmsg->channels == 0) { + /* Clean all if no channels specified */ + bkn_dma_abort(sinfo); + bkn_clean_dcbs(sinfo); + } else { + if (kmsg->channels & (1 << XGS_DMA_TX_CHAN)) { + bkn_dma_abort_tx(sinfo); + bkn_clean_tx_dcbs(sinfo); + } + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (kmsg->channels & (1 << (XGS_DMA_RX_CHAN + chan))) { + bkn_dma_abort_rx(sinfo, chan); + bkn_clean_rx_dcbs(sinfo, chan); + } + } + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return sizeof(kcom_msg_hdr_t); +} + +static int +bkn_knet_hw_init(kcom_msg_hw_init_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + uint32_t dev_type; + unsigned long flags; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + DBG_DCB(("DCB size %d, type %d\n", kmsg->dcb_size, kmsg->dcb_type)); + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + sinfo->cmic_type = kmsg->cmic_type; + sinfo->dcb_type = kmsg->dcb_type; + sinfo->dcb_wsize = BYTES2WORDS(kmsg->dcb_size); + sinfo->pkt_hdr_size = kmsg->pkt_hdr_size; + sinfo->dma_hi = kmsg->dma_hi; + sinfo->rx_chans = sinfo->cmic_type == 'x' ? NUM_CMICX_RX_CHAN : NUM_CMICM_RX_CHAN; + if (sinfo->rx_chans > NUM_RX_CHAN) { + sinfo->rx_chans = NUM_RX_CHAN; + } + + /* Config Continuous DMA mode */ + sinfo->cdma_channels = kmsg->cdma_channels & ~(~0 << (sinfo->rx_chans + 1)); + + /* Ensure 32-bit PCI DMA is mapped properly on 64-bit platforms */ + dev_type = kernel_bde->get_dev_type(sinfo->dev_no); + if (dev_type & BDE_PCI_DEV_TYPE && sinfo->cmic_type != 'x') { + if (pci_set_dma_mask(sinfo->pdev, 0xffffffff)) { + spin_unlock_irqrestore(&sinfo->lock, flags); + gprintk("No suitable DMA available for SKBs\n"); + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_hdr_t); + } + } + + /* First time called we need to allocate DCBs */ + if (sinfo->dcb_mem == NULL) { + if (bkn_alloc_dcbs(sinfo) < 0) { + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_hdr_t); + } + } + + /* Ensure that we restart properly */ + bkn_dma_abort(sinfo); + bkn_clean_dcbs(sinfo); + + if (basedev_suspend) { + if (!netif_running(sinfo->dev)) { + sinfo->basedev_suspended = 1; + } + } + + /* Ensure all interrupts are disabled, e.g. if warmbooting */ + dev_irq_mask_set(sinfo, 0); + + /* Register interrupt handler */ + kernel_bde->interrupt_connect(sinfo->dev_no | LKBDE_ISR2_DEV, + bkn_isr, sinfo); + + /* Init DCBs */ + bkn_init_dcbs(sinfo); + + bkn_dma_init(sinfo); + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return sizeof(kcom_msg_hdr_t); +} + +static int +bkn_knet_detach(kcom_msg_detach_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + unsigned long flags; + bkn_evt_resource_t *evt; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + /* Create dummy event to unblock pending IOCTL */ + sinfo->dma_events |= KCOM_DMA_INFO_F_TX_DONE; + evt = &_bkn_evt[sinfo->evt_idx]; + evt->evt_wq_put++; + wake_up_interruptible(&evt->evt_wq); + + spin_unlock_irqrestore(&sinfo->lock, flags); + + /* Ensure that we return a valid unit number */ + kmsg->hdr.unit = sinfo->dev_no; + + return sizeof(kcom_msg_detach_t); +} + +static int +bkn_knet_netif_create(kcom_msg_netif_create_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + struct net_device *dev; + struct list_head *list; + bkn_priv_t *priv, *lpriv; + unsigned long flags; + int found, id; + uint8 *ma; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + switch (kmsg->netif.type) { + case KCOM_NETIF_T_VLAN: + case KCOM_NETIF_T_PORT: + case KCOM_NETIF_T_META: + break; + default: + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + ma = kmsg->netif.macaddr; + if ((ma[0] | ma[1] | ma[2] | ma[3] | ma[4] | ma[5]) == 0) { + bkn_dev_mac[5]++; + ma = bkn_dev_mac; + } + if ((dev = bkn_init_ndev(ma, kmsg->netif.name)) == NULL) { + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_hdr_t); + } + priv = netdev_priv(dev); + priv->dev = dev; + priv->sinfo = sinfo; + priv->type = kmsg->netif.type; + priv->vlan = kmsg->netif.vlan; + if (priv->type == KCOM_NETIF_T_PORT) { + priv->port = kmsg->netif.port; + memcpy(priv->itmh, kmsg->netif.itmh, 4); + priv->qnum = kmsg->netif.qnum; + } else { + if ((device_is_dune(sinfo)) && (priv->type == KCOM_NETIF_T_VLAN)) { + /* set port as SSP to PTCH */ + priv->port = kmsg->netif.port; + priv->qnum = kmsg->netif.qnum; + } + else { + priv->port = -1; + } + } + priv->flags = kmsg->netif.flags; + priv->cb_user_data = kmsg->netif.cb_user_data; + + /* Force RCPU encapsulation if rcpu_mode */ + if (rcpu_mode) { + priv->flags |= KCOM_NETIF_F_RCPU_ENCAP; + DBG_RCPU(("RCPU auto-enabled\n")); + } + + /* Prevent (incorrect) compiler warning */ + lpriv = NULL; + + spin_lock_irqsave(&sinfo->lock, flags); + + /* + * We insert network interfaces sorted by ID. + * In case an interface is destroyed, we reuse the ID + * the next time an interface is created. + */ + found = 0; + id = 1; + list_for_each(list, &sinfo->ndev_list) { + lpriv = (bkn_priv_t *)list; + if (id < lpriv->id) { + found = 1; + break; + } + id = lpriv->id + 1; + } + priv->id = id; + if (found) { + /* Replace previously removed interface */ + list_add_tail(&priv->list, &lpriv->list); + } else { + /* No holes - add to end of list */ + list_add_tail(&priv->list, &sinfo->ndev_list); + } + + if (id < sinfo->ndev_max) { + DBG_NDEV(("Add netif ID %d to table\n", id)); + sinfo->ndevs[id] = dev; + } else { + int ndev_max = sinfo->ndev_max + NDEVS_CHUNK; + int size = ndev_max * sizeof(struct net_device *); + void *ndevs = kmalloc(size, GFP_ATOMIC); + if (ndevs != NULL) { + DBG_NDEV(("Reallocate netif table for ID %d\n", id)); + memset(ndevs, 0, size); + if (sinfo->ndevs != NULL) { + size = sinfo->ndev_max * sizeof(struct net_device *); + memcpy(ndevs, sinfo->ndevs, size); + kfree(sinfo->ndevs); + } + sinfo->ndevs = ndevs; + sinfo->ndev_max = ndev_max; + sinfo->ndevs[id] = dev; + } + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + DBG_VERB(("Assigned ID %d to Ethernet device %s\n", + priv->id, dev->name)); + + kmsg->netif.id = priv->id; + memcpy(kmsg->netif.macaddr, dev->dev_addr, 6); + memcpy(kmsg->netif.name, dev->name, KCOM_NETIF_NAME_MAX - 1); + + return sizeof(*kmsg); +} + +static int +bkn_knet_netif_destroy(kcom_msg_netif_destroy_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + struct net_device *dev; + bkn_priv_t *priv; + struct list_head *list; + unsigned long flags; + int found; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + found = 0; + list_for_each(list, &sinfo->ndev_list) { + priv = (bkn_priv_t *)list; + if (kmsg->hdr.id == priv->id) { + found = 1; + break; + } + } + + if (!found) { + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_NOT_FOUND; + return sizeof(kcom_msg_hdr_t); + } + + list_del(&priv->list); + + if (priv->id < sinfo->ndev_max) { + sinfo->ndevs[priv->id] = NULL; + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + dev = priv->dev; + DBG_VERB(("Removing virtual Ethernet device %s (%d).\n", + dev->name, priv->id)); + unregister_netdev(dev); + free_netdev(dev); + + return sizeof(kcom_msg_hdr_t); +} + +static int +bkn_knet_netif_list(kcom_msg_netif_list_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_priv_t *priv; + struct list_head *list; + unsigned long flags; + int idx; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + idx = 0; + list_for_each(list, &sinfo->ndev_list) { + if (idx >= KCOM_NETIF_MAX) { + DBG_WARN(("Too many network interfaces to list (max %d).\n", + KCOM_NETIF_MAX)); + break; + } + priv = (bkn_priv_t *)list; + kmsg->id[idx] = priv->id; + idx++; + } + kmsg->ifcnt = idx; + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return sizeof(*kmsg) - sizeof(kmsg->id) + (idx * sizeof(kmsg->id[0])); +} + +static int +bkn_knet_netif_get(kcom_msg_netif_get_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_priv_t *priv; + unsigned long flags; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + priv = bkn_netif_lookup(sinfo, kmsg->hdr.id); + + if (priv == NULL) { + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_NOT_FOUND; + return sizeof(kcom_msg_hdr_t); + } + + memcpy(kmsg->netif.macaddr, priv->dev->dev_addr, 6); + memcpy(kmsg->netif.name, priv->dev->name, KCOM_NETIF_NAME_MAX - 1); + kmsg->netif.vlan = priv->vlan; + kmsg->netif.type = priv->type; + kmsg->netif.id = priv->id; + kmsg->netif.flags = priv->flags; + + if (priv->port < 0) { + kmsg->netif.port = 0; + } else { + kmsg->netif.port = priv->port; + } + kmsg->netif.qnum = priv->qnum; + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return sizeof(*kmsg); +} + +static int +bkn_knet_filter_create(kcom_msg_filter_create_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + struct list_head *list; + bkn_filter_t *filter, *lfilter; + unsigned long flags; + int found, id; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + switch (kmsg->filter.type) { + case KCOM_FILTER_T_RX_PKT: + break; + default: + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + /* + * Find available ID + */ + found = 1; + id = 0; + while (found && ++id < KCOM_FILTER_MAX) { + found = 0; + list_for_each(list, &sinfo->rxpf_list) { + lfilter = (bkn_filter_t *)list; + if (id == lfilter->kf.id) { + found = 1; + break; + } + } + } + if (found) { + /* Too many filters */ + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_hdr_t); + } + + filter = kmalloc(sizeof(*filter), GFP_ATOMIC); + if (filter == NULL) { + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + memset(filter, 0, sizeof(*filter)); + memcpy(&filter->kf, &kmsg->filter, sizeof(filter->kf)); + filter->kf.id = id; + + /* Add according to priority */ + found = 0; + list_for_each(list, &sinfo->rxpf_list) { + lfilter = (bkn_filter_t *)list; + if (filter->kf.priority < lfilter->kf.priority) { + list_add_tail(&filter->list, &lfilter->list); + found = 1; + break; + } + } + if (!found) { + list_add_tail(&filter->list, &sinfo->rxpf_list); + } + + kmsg->filter.id = filter->kf.id; + + spin_unlock_irqrestore(&sinfo->lock, flags); + + DBG_VERB(("Created filter ID %d (%s).\n", + filter->kf.id, filter->kf.desc)); + + return len; +} + +static int +bkn_knet_filter_destroy(kcom_msg_filter_destroy_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_filter_t *filter; + struct list_head *list; + unsigned long flags; + int found; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + found = 0; + list_for_each(list, &sinfo->rxpf_list) { + filter = (bkn_filter_t *)list; + if (kmsg->hdr.id == filter->kf.id) { + found = 1; + break; + } + } + + if (!found) { + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_NOT_FOUND; + return sizeof(kcom_msg_hdr_t); + } + + list_del(&filter->list); + + spin_unlock_irqrestore(&sinfo->lock, flags); + + DBG_VERB(("Removing filter ID %d.\n", filter->kf.id)); + kfree(filter); + + return sizeof(kcom_msg_hdr_t); +} + +static int +bkn_knet_filter_list(kcom_msg_filter_list_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_filter_t *filter; + struct list_head *list; + unsigned long flags; + int idx; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + idx = 0; + list_for_each(list, &sinfo->rxpf_list) { + if (idx >= KCOM_FILTER_MAX) { + DBG_WARN(("Too many filters to list (max %d).\n", + KCOM_FILTER_MAX)); + break; + } + filter = (bkn_filter_t *)list; + kmsg->id[idx] = filter->kf.id; + idx++; + } + kmsg->fcnt = idx; + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return sizeof(*kmsg) - sizeof(kmsg->id) + (idx * sizeof(kmsg->id[0])); +} + +static int +bkn_knet_filter_get(kcom_msg_filter_get_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_filter_t *filter; + struct list_head *list; + unsigned long flags; + int found; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + found = 0; + list_for_each(list, &sinfo->rxpf_list) { + filter = (bkn_filter_t *)list; + if (kmsg->hdr.id == filter->kf.id) { + found = 1; + break; + } + } + + if (!found) { + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_NOT_FOUND; + return sizeof(kcom_msg_hdr_t); + } + + memcpy(&kmsg->filter, &filter->kf, sizeof(kmsg->filter)); + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return sizeof(*kmsg); +} + +static int +bkn_knet_dbg_pkt_set(kcom_msg_dbg_pkt_set_t *kmsg, int len) +{ + dbg_pkt_enable = kmsg->enable; + return sizeof(kcom_msg_dbg_pkt_set_t); +} + +static int +bkn_knet_dbg_pkt_get(kcom_msg_dbg_pkt_get_t *kmsg, int len) +{ + kmsg->value = dbg_pkt_enable; + return sizeof(kcom_msg_dbg_pkt_get_t); +} + +static int +bkn_knet_wb_cleanup(kcom_msg_wb_cleanup_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_dcb_chain_t *dcb_chain; + unsigned long flags; + int chan; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (sinfo->rx[chan].api_dcb_chain) { + DBG_DCB_RX(("Freeing active Rx%d DCB chain.\n", chan)); + kfree(sinfo->rx[chan].api_dcb_chain); + sinfo->rx[chan].api_dcb_chain = NULL; + } + while (!list_empty(&sinfo->rx[chan].api_dcb_list)) { + dcb_chain = list_entry(sinfo->rx[chan].api_dcb_list.next, + bkn_dcb_chain_t, list); + list_del(&dcb_chain->list); + DBG_DCB_RX(("Freeing Rx%d DCB chain.\n", chan)); + kfree(dcb_chain); + } + sinfo->rx[chan].api_dcb_chain_end = NULL; + sinfo->rx[chan].api_active = 0; + sinfo->rx[chan].api_wait = 0; + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return sizeof(kcom_msg_hdr_t); +} + +static int +bkn_handle_cmd_req(kcom_msg_t *kmsg, int len) +{ + /* Silently drop events and unrecognized message types */ + if (kmsg->hdr.type != KCOM_MSG_TYPE_CMD) { + if (kmsg->hdr.opcode == KCOM_M_STRING) { + DBG_VERB(("Debug string: '%s'\n", kmsg->string.val)); + return 0; + } + DBG_WARN(("Unsupported message (type=%d, opcode=%d)\n", + kmsg->hdr.type, kmsg->hdr.opcode)); + return 0; + } + + switch (kmsg->hdr.opcode) { + case KCOM_M_DMA_INFO: + DBG_CMD(("KCOM_M_DMA_INFO\n")); + /* Packet buffer */ + len = bkn_knet_dma_info(&kmsg->dma_info, len); + break; + case KCOM_M_VERSION: + DBG_CMD(("KCOM_M_VERSION\n")); + /* Return procotol version */ + len = bkn_knet_version(&kmsg->version, len); + break; + case KCOM_M_HW_RESET: + DBG_CMD(("KCOM_M_HW_RESET\n")); + /* Shut down DMA and release buffers */ + len = bkn_knet_hw_reset(&kmsg->hw_reset, len); + break; + case KCOM_M_HW_INIT: + DBG_CMD(("KCOM_M_HW_INIT\n")); + /* Initialize DMA */ + len = bkn_knet_hw_init(&kmsg->hw_init, len); + break; + case KCOM_M_DETACH: + DBG_CMD(("KCOM_M_DETACH\n")); + /* Detach kernel module */ + len = bkn_knet_detach(&kmsg->detach, len); + break; + case KCOM_M_NETIF_CREATE: + DBG_CMD(("KCOM_M_NETIF_CREATE\n")); + /* Create network interface */ + len = bkn_knet_netif_create(&kmsg->netif_create, len); + break; + case KCOM_M_NETIF_DESTROY: + DBG_CMD(("KCOM_M_NETIF_DESTROY\n")); + /* Destroy network interface */ + len = bkn_knet_netif_destroy(&kmsg->netif_destroy, len); + break; + case KCOM_M_NETIF_LIST: + DBG_CMD(("KCOM_M_NETIF_LIST\n")); + /* Return list of IDs of installed network interfaces */ + len = bkn_knet_netif_list(&kmsg->netif_list, len); + break; + case KCOM_M_NETIF_GET: + DBG_CMD(("KCOM_M_NETIF_GET\n")); + /* Return network interface info */ + len = bkn_knet_netif_get(&kmsg->netif_get, len); + break; + case KCOM_M_FILTER_CREATE: + DBG_CMD(("KCOM_M_FILTER_CREATE\n")); + /* Create packet filter */ + len = bkn_knet_filter_create(&kmsg->filter_create, len); + break; + case KCOM_M_FILTER_DESTROY: + DBG_CMD(("KCOM_M_FILTER_DESTROY\n")); + /* Destroy packet filter */ + len = bkn_knet_filter_destroy(&kmsg->filter_destroy, len); + break; + case KCOM_M_FILTER_LIST: + DBG_CMD(("KCOM_M_FILTER_LIST\n")); + /* Return list of IDs of installed packet filters */ + len = bkn_knet_filter_list(&kmsg->filter_list, len); + break; + case KCOM_M_FILTER_GET: + DBG_CMD(("KCOM_M_FILTER_GET\n")); + /* Return packet filter info */ + len = bkn_knet_filter_get(&kmsg->filter_get, len); + break; + case KCOM_M_DBGPKT_SET: + DBG_CMD(("KCOM_M_DBGPKT_SET\n")); + /* Set debugging packet function */ + len = bkn_knet_dbg_pkt_set(&kmsg->dbg_pkt_set, len); + break; + case KCOM_M_DBGPKT_GET: + DBG_CMD(("KCOM_M_DBGPKT_GET\n")); + /* Get debugging packet function info */ + len = bkn_knet_dbg_pkt_get(&kmsg->dbg_pkt_get, len); + break; + case KCOM_M_WB_CLEANUP: + DBG_CMD(("KCOM_M_WB_CLEANUP\n")); + /* Clean up for warmbooting */ + len = bkn_knet_wb_cleanup(&kmsg->wb_cleanup, len); + break; + default: + DBG_WARN(("Unsupported command (type=%d, opcode=%d)\n", + kmsg->hdr.type, kmsg->hdr.opcode)); + kmsg->hdr.opcode = 0; + len = sizeof(kcom_msg_hdr_t); + break; + } + return len; +} + +static int +bkn_cmd_thread(void *context) +{ + bkn_thread_ctrl_t *tc = (bkn_thread_ctrl_t *)context; + kcom_msg_t kmsg; + unsigned int len, rlen; + + bkn_thread_boot(tc); + + DBG_VERB(("Command thread starting\n")); + tc->state = 1; + while (!bkn_thread_should_stop(tc)) { + len = sizeof(kmsg); + tc->state = 2; + if (PROXY_RECV(KCOM_CHAN_KNET, &kmsg, &len) >= 0) { + DBG_VERB(("Received %d bytes from KCOM_CHAN_CMD\n", len)); + tc->state = 3; + rlen = bkn_handle_cmd_req(&kmsg, len); + tc->state = 4; + if (rlen > 0) { + PROXY_SEND(KCOM_CHAN_KNET, &kmsg, rlen); + } + } else { + /* Thread interrupted */ + bkn_sleep(1); + } + } + DBG_VERB(("Command thread done\n")); + + bkn_thread_exit(tc); + return 0; +} + +static int +bkn_get_next_dma_event(kcom_msg_dma_info_t *kmsg) +{ + static int last_dev_no = 0; + bkn_switch_info_t *sinfo; + unsigned long flags; + int dev_no, dev_evt; + bkn_evt_resource_t *evt; + + dev_evt = kmsg->hdr.unit; + sinfo = bkn_sinfo_from_unit(dev_evt); + if (sinfo == NULL) { + /* The device is not probed or initialized yet.*/ + return 0; + } + if (sinfo->evt_idx == -1) { + /* Event queue is not ready yet */ + return 0; + } + + DBG_INST(("%s dev %d evt_idx %d\n",__FUNCTION__, dev_evt, sinfo->evt_idx)); + evt = &_bkn_evt[sinfo->evt_idx]; + dev_no = last_dev_no = dev_evt; + while (1) { + dev_no++; + sinfo = bkn_sinfo_from_unit(dev_no); + if (sinfo == NULL) { + dev_no = 0; + sinfo = bkn_sinfo_from_unit(dev_no); + } + + if (sinfo && (sinfo->inst_id != 0) && + ((sinfo->inst_id & (1 << dev_evt)) == 0)) { + DBG_INST((" %s skip dev(%d)\n",__FUNCTION__,dev_evt)); + continue; + } + + if (sinfo && sinfo->dma_events) { + DBG_EVT(("Next DMA events (0x%08x)\n", sinfo->dma_events)); + kmsg->hdr.unit = sinfo->dev_no; + + spin_lock_irqsave(&sinfo->lock, flags); + kmsg->dma_info.flags = sinfo->dma_events; + sinfo->dma_events = 0; + spin_unlock_irqrestore(&sinfo->lock, flags); + + last_dev_no = dev_no; + break; + } + + if (dev_no == last_dev_no) { + DBG_INST(("wait queue index %d\n",sinfo->evt_idx)); + wait_event_interruptible(evt->evt_wq, + evt->evt_wq_get != evt->evt_wq_put); + DBG_VERB(("Event thread wakeup\n")); + + /* Thread interrupted */ + if (signal_pending(current)) { + return 0; + } + + evt->evt_wq_get = evt->evt_wq_put; + } + } + return sizeof(*kmsg); +} + +static int +bkn_evt_thread(void *context) +{ + bkn_thread_ctrl_t *tc = (bkn_thread_ctrl_t *)context; + kcom_msg_dma_info_t kmsg; + int len; + + bkn_thread_boot(tc); + + memset(&kmsg, 0, sizeof(kmsg)); + kmsg.hdr.type = KCOM_MSG_TYPE_EVT; + kmsg.hdr.opcode = KCOM_M_DMA_INFO; + + DBG_VERB(("Event thread starting\n")); + tc->state = 1; + while (!bkn_thread_should_stop(tc)) { + tc->state = 2; + len = bkn_get_next_dma_event(&kmsg); + tc->state = 3; + if (len) { + PROXY_SEND(KCOM_CHAN_KNET, &kmsg, len); + } else { + /* Thread interrupted */ + bkn_sleep(1); + } + } + DBG_VERB(("Event thread done\n")); + + bkn_thread_exit(tc); + return 0; +} + +static int +_cleanup(void) +{ + struct list_head *list; + struct net_device *dev; + bkn_filter_t *filter; + bkn_priv_t *priv; + bkn_switch_info_t *sinfo; + unsigned long flags; + + /* Inidicate that we are shutting down */ + module_initialized = 0; + + /* Shut down event thread */ + bkn_thread_stop(&bkn_evt_ctrl); + + /* Shut down command thread */ + bkn_thread_stop(&bkn_cmd_ctrl); + + /* Remove KCOM channel */ + PROXY_SERVICE_DESTROY(KCOM_CHAN_KNET); + + bkn_proc_cleanup(); + remove_proc_entry("bcm/knet", NULL); + remove_proc_entry("bcm", NULL); + + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + + del_timer_sync(&sinfo->timer); + del_timer_sync(&sinfo->rxtick); + + spin_lock_irqsave(&sinfo->lock, flags); + bkn_dma_abort(sinfo); + dev_irq_mask_set(sinfo, 0); + spin_unlock_irqrestore(&sinfo->lock, flags); + + DBG_IRQ(("Unregister ISR.\n")); + kernel_bde->interrupt_disconnect(sinfo->dev_no | LKBDE_ISR2_DEV); + + if (use_napi) { + while (sinfo->napi_poll_mode) { + bkn_sleep(1); + } + } + + spin_lock_irqsave(&sinfo->lock, flags); + bkn_clean_dcbs(sinfo); + spin_unlock_irqrestore(&sinfo->lock, flags); + } + + /* Destroy all switch devices */ + while (!list_empty(&_sinfo_list)) { + sinfo = list_entry(_sinfo_list.next, bkn_switch_info_t, list); + + /* Destroy all associated Rx packet filters */ + while (!list_empty(&sinfo->rxpf_list)) { + filter = list_entry(sinfo->rxpf_list.next, bkn_filter_t, list); + list_del(&filter->list); + DBG_VERB(("Removing filter ID %d.\n", filter->kf.id)); + kfree(filter); + } + + /* Destroy all associated virtual net devices */ + while (!list_empty(&sinfo->ndev_list)) { + priv = list_entry(sinfo->ndev_list.next, bkn_priv_t, list); + list_del(&priv->list); + dev = priv->dev; + DBG_VERB(("Removing virtual Ethernet device %s.\n", dev->name)); + unregister_netdev(dev); + free_netdev(dev); + } + if (sinfo->ndevs != NULL) { + kfree(sinfo->ndevs); + } + + /* Destroy base net device */ + if (sinfo->dev) { + DBG_VERB(("Removing Ethernet device %s.\n", sinfo->dev->name)); + unregister_netdev(sinfo->dev); + free_netdev(sinfo->dev); + } + + DBG_VERB(("Removing switch device.\n")); + bkn_destroy_sinfo(sinfo); + } + + return 0; +} + +static int +bkn_knet_dev_reinit(int d) +{ + bkn_switch_info_t *sinfo; + uint32 dev_state; + unsigned long flags; + + if (lkbde_dev_state_get(d, &dev_state) < 0) { + return -1; + } + DBG_VERB(("%s dev %d dev_state %d\n",__FUNCTION__, d, dev_state)); + if (dev_state == BDE_DEV_STATE_CHANGED) { + sinfo = bkn_sinfo_from_unit(d); + spin_lock_irqsave(&sinfo->lock, flags); + sinfo->base_addr = lkbde_get_dev_virt(d); + sinfo->dma_dev = lkbde_get_dma_dev(d); + sinfo->pdev = lkbde_get_hw_dev(d); + spin_unlock_irqrestore(&sinfo->lock, flags); + + dev_state = 0; + lkbde_dev_state_set(d, dev_state); + } + return 0; +} + +static int +bkn_knet_dev_init(int d) +{ + uint32_t dev_type; + struct net_device *dev; + bkn_switch_info_t *sinfo; + bkn_priv_t *priv; + char *bdev_name; + const ibde_dev_t *bde_dev; + + DBG_VERB(("%s dev %d\n",__FUNCTION__, d)); + /* Base network device name */ + bdev_name = "bcm%d"; + if (base_dev_name) { + if (strlen(base_dev_name) < IFNAMSIZ) { + bdev_name = base_dev_name; + } else { + DBG_WARN(("Base device name too long\n")); + } + } + + dev_type = kernel_bde->get_dev_type(d); + DBG_VERB(("Found device type 0x%x\n", dev_type)); + if ((dev_type & BDE_SWITCH_DEV_TYPE) == 0) { + DBG_WARN(("Not switch device - skipping\n")); + return 0; + } + switch (dev_type & BDE_DEV_BUS_TYPE_MASK) { + case BDE_PCI_DEV_TYPE: + case BDE_ICS_DEV_TYPE: + case BDE_AXI_DEV_TYPE: + break; + default: + DBG_WARN(("Not PCI/ICS/AXI device - skipping\n")); + return 0; + } + + if ((sinfo = bkn_create_sinfo(d)) == NULL) { + _cleanup(); + return -ENOMEM; + } + + /* Initialize the cpu_no.*/ + if (dev_type & BDE_AXI_DEV_TYPE) { + /* AXI device type implies the activated iProc iHost */ + sinfo->cpu_no = 1; + } + /* Initialize default RCPU signature */ + if ((bde_dev = kernel_bde->get_dev(d)) != NULL) { + sinfo->rcpu_sig = bde_dev->device & ~0xf; + } + /* Check for override */ + if (rcpu_signature) { + sinfo->rcpu_sig = rcpu_signature; + } + + /* Create base virtual net device */ + bkn_dev_mac[5]++; + if ((dev = bkn_init_ndev(bkn_dev_mac, bdev_name)) == NULL) { + _cleanup(); + return -ENOMEM; + } else { + sinfo->dev = dev; + priv = netdev_priv(dev); + priv->dev = dev; + priv->sinfo = sinfo; + priv->vlan = 1; + priv->port = -1; + memset(priv->itmh, 0, sizeof(priv->itmh)); + priv->id = -1; + } + + if (use_napi) { + netif_napi_add(dev, &sinfo->napi, bkn_poll, napi_weight); + } + return 0; +} + +static int +_init(void) +{ + int idx; + int num_dev; + int rv; + bkn_evt_resource_t *evt; + + /* Connect to the kernel bde */ + if ((linux_bde_create(NULL, &kernel_bde) < 0) || kernel_bde == NULL) { + return -ENODEV; + } + + /* Randomize Lower 3 bytes of the MAC address (TESTING ONLY) */ + get_random_bytes(&bkn_dev_mac[3], 3); + + /* Check for user-supplied MAC address (recommended) */ + if (mac_addr != NULL && strlen(mac_addr) == 17) { + for (idx = 0; idx < 6; idx++) { + bkn_dev_mac[idx] = simple_strtoul(&mac_addr[idx*3], NULL, 16); + } + /* Do not allow multicast address */ + bkn_dev_mac[0] &= ~0x01; + } + + /* Optional RCPU MAC addresses */ + if (rcpu_dmac != NULL && strlen(rcpu_dmac) == 17) { + for (idx = 0; idx < 6; idx++) { + bkn_rcpu_dmac[idx] = simple_strtoul(&rcpu_dmac[idx*3], NULL, 16); + } + } + if (rcpu_smac != NULL && strlen(rcpu_smac) == 17) { + for (idx = 0; idx < 6; idx++) { + bkn_rcpu_smac[idx] = simple_strtoul(&rcpu_smac[idx*3], NULL, 16); + } + } + + /* NAPI implies that base device must be up before we can pass traffic */ + if (use_napi) { + basedev_suspend = 1; + } + + num_dev = kernel_bde->num_devices(BDE_ALL_DEVICES); + for (idx = 0; idx < num_dev; idx++) { + rv = bkn_knet_dev_init(idx); + if (rv) { + return rv; + } + } + + /* Initialize proc files */ + proc_mkdir("bcm", NULL); + bkn_proc_root = proc_mkdir("bcm/knet", NULL); + + bkn_proc_init(); + + /* Initialize event queue */ + for (idx = 0; idx < LINUX_BDE_MAX_DEVICES; idx++) { + memset(&_bkn_evt[idx], 0, sizeof(bkn_evt_resource_t)); + } + evt = &_bkn_evt[0]; + init_waitqueue_head(&evt->evt_wq); + + if (use_proxy) { + PROXY_SERVICE_CREATE(KCOM_CHAN_KNET, 1, 0); + + DBG_VERB(("Starting command thread\n")); + bkn_thread_start(&bkn_cmd_ctrl, "bkncmd", bkn_cmd_thread); + + DBG_VERB(("Starting event thread\n")); + bkn_thread_start(&bkn_evt_ctrl, "bknevt", bkn_evt_thread); + } + + module_initialized = 1; + + return 0; +} + +static int +_ioctl(unsigned int cmd, unsigned long arg) +{ + bkn_ioctl_t io; + kcom_msg_t kmsg; + + if (!module_initialized) { + return -EFAULT; + } + + if (copy_from_user(&io, (void*)arg, sizeof(io))) { + return -EFAULT; + } + + if (io.len > sizeof(kmsg)) { + return -EINVAL; + } + + io.rc = 0; + + switch(cmd) { + case 0: + if (io.len > 0) { + if (copy_from_user(&kmsg, (void *)(unsigned long)io.buf, io.len)) { + return -EFAULT; + } + ioctl_cmd++; + io.len = bkn_handle_cmd_req(&kmsg, io.len); + ioctl_cmd--; + } else { + memset(&kmsg, 0, sizeof(kcom_msg_dma_info_t)); + /* + * Retrive the kmsg.hdr.unit from user space. The dma event queue + * selection is based the instance derived from unit. + */ + if (copy_from_user(&kmsg, (void *)(unsigned long)io.buf, sizeof(kmsg))) { + return -EFAULT; + } + kmsg.hdr.type = KCOM_MSG_TYPE_EVT; + kmsg.hdr.opcode = KCOM_M_DMA_INFO; + ioctl_evt++; + io.len = bkn_get_next_dma_event((kcom_msg_dma_info_t *)&kmsg); + ioctl_evt--; + } + if (io.len > 0) { + if (copy_to_user((void *)(unsigned long)io.buf, &kmsg, io.len)) { + return -EFAULT; + } + } + break; + default: + gprintk("Invalid IOCTL"); + io.rc = -1; + break; + } + + if (copy_to_user((void*)arg, &io, sizeof(io))) { + return -EFAULT; + } + + return 0; +} + +static gmodule_t _gmodule = { + name: MODULE_NAME, + major: MODULE_MAJOR, + init: _init, + cleanup: _cleanup, + pprint: _pprint, + ioctl: _ioctl, + open: NULL, + close: NULL, +}; + +gmodule_t * +gmodule_get(void) +{ + EXPORT_NO_SYMBOLS; + return &_gmodule; +} + +/* + * Call-back interfaces for other Linux kernel drivers. + * + * The Rx call-back allows an external module to modify SKB contents + * before it is handed off to the Linux network stack. + * + * The Tx call-back allows an external module to modify SKB contents + * before it is injected inot the switch. + */ + +int +bkn_rx_skb_cb_register(knet_skb_cb_f rx_cb) +{ + if (knet_rx_cb != NULL) { + return -1; + } + knet_rx_cb = rx_cb; + return 0; +} + +int +bkn_rx_skb_cb_unregister(knet_skb_cb_f rx_cb) +{ + if (rx_cb != NULL && knet_rx_cb != rx_cb) { + return -1; + } + knet_rx_cb = NULL; + return 0; +} + +int +bkn_tx_skb_cb_register(knet_skb_cb_f tx_cb) +{ + if (knet_tx_cb != NULL) { + return -1; + } + knet_tx_cb = tx_cb; + return 0; +} + +int +bkn_tx_skb_cb_unregister(knet_skb_cb_f tx_cb) +{ + if (tx_cb != NULL && knet_tx_cb != tx_cb) { + return -1; + } + knet_tx_cb = NULL; + return 0; +} + +int +bkn_filter_cb_register(knet_filter_cb_f filter_cb) +{ + if (knet_filter_cb != NULL) { + return -1; + } + knet_filter_cb = filter_cb; + return 0; +} + +int +bkn_filter_cb_unregister(knet_filter_cb_f filter_cb) +{ + if (filter_cb != NULL && knet_filter_cb != filter_cb) { + return -1; + } + knet_filter_cb = NULL; + return 0; +} + +LKM_EXPORT_SYM(bkn_rx_skb_cb_register); +LKM_EXPORT_SYM(bkn_rx_skb_cb_unregister); +LKM_EXPORT_SYM(bkn_tx_skb_cb_register); +LKM_EXPORT_SYM(bkn_tx_skb_cb_unregister); +LKM_EXPORT_SYM(bkn_filter_cb_register); +LKM_EXPORT_SYM(bkn_filter_cb_unregister); diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h new file mode 100644 index 000000000000..760690b3fb9d --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h @@ -0,0 +1,78 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: bcm-knet.h,v 1.4 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ +#ifndef __LINUX_BCM_KNET_H__ +#define __LINUX_BCM_KNET_H__ + +#ifndef __KERNEL__ +#include +#endif + +typedef struct { + int rc; + int len; + int bufsz; + int reserved; + uint64_t buf; +} bkn_ioctl_t; + +#ifdef __KERNEL__ + +/* + * Call-back interfaces for other Linux kernel drivers. + */ +#include + +typedef struct { + uint32 netif_user_data; + uint32 filter_user_data; + uint16 dcb_type; +} knet_skb_cb_t; + +#define KNET_SKB_CB(__skb) ((knet_skb_cb_t *)&((__skb)->cb[0])) + +typedef struct sk_buff * +(*knet_skb_cb_f)(struct sk_buff *skb, int dev_no, void *meta); + +typedef int +(*knet_filter_cb_f)(uint8_t *pkt, int size, int dev_no, void *meta, + int chan, kcom_filter_t *filter); + +extern int +bkn_rx_skb_cb_register(knet_skb_cb_f rx_cb); + +extern int +bkn_rx_skb_cb_unregister(knet_skb_cb_f rx_cb); + +extern int +bkn_tx_skb_cb_register(knet_skb_cb_f tx_cb); + +extern int +bkn_tx_skb_cb_unregister(knet_skb_cb_f tx_cb); + +extern int +bkn_filter_cb_register(knet_filter_cb_f filter_cb); + +extern int +bkn_filter_cb_unregister(knet_filter_cb_f filter_cb); + +#endif + +#endif /* __LINUX_BCM_KNET_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/gmodule.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/gmodule.h new file mode 100644 index 000000000000..22cef82a8ddc --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/gmodule.h @@ -0,0 +1,65 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: gmodule.h,v 1.9 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef __COMMON_LINUX_KRN_GMODULE_H__ +#define __COMMON_LINUX_KRN_GMODULE_H__ + +#include + +typedef struct gmodule_s { + + const char* name; + int major; + int minor; + + int (*init)(void); + int (*cleanup)(void); + + int (*pprint)(void); + + int (*open)(void); + int (*ioctl)(unsigned int cmd, unsigned long arg); + int (*close)(void); + int (*mmap) (struct file *filp, struct vm_area_struct *vma); + +} gmodule_t; + + +/* The framework will ask for your module definition */ +extern gmodule_t* gmodule_get(void); + + +/* Proc Filesystem information */ +extern int pprintf(const char* fmt, ...) + __attribute__ ((format (printf, 1, 2))); +extern int gmodule_vpprintf(char** page, const char* fmt, va_list args) + __attribute__ ((format (printf, 2, 0))); +extern int gmodule_pprintf(char** page, const char* fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +extern int gprintk(const char* fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +extern int gdbg(const char* fmt, ...) + __attribute__ ((format (printf, 1, 2))); +#define GDBG gdbg + +#endif /* __COMMON_LINUX_KRN_GMODULE_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/lkm.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/lkm.h new file mode 100644 index 000000000000..d1977076850b --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/lkm.h @@ -0,0 +1,179 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: lkm.h,v 1.22 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef __COMMON_LINUX_KRN_LKM_H__ +#define __COMMON_LINUX_KRN_LKM_H__ + +#ifndef __KERNEL__ +# define __KERNEL__ +#endif +#ifndef MODULE +# define MODULE +#endif + +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) +#include +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +#include +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) +#include +#endif +#include + +/* Helper defines for multi-version kernel support */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#define LKM_2_4 +#else +#define LKM_2_6 +#endif + +#include /* printk() */ +#include /* everything... */ +#include /* error codes */ +#include /* size_t */ +#include +#include /* O_ACCMODE */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_DEVFS_FS +#include +#endif + +#define PROC_INTERFACE_KERN_VER_3_10 (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + +/* Compatibility Macros */ + +#ifdef LKM_2_4 + +#include +#include +#define LKM_MOD_PARAM(n,ot,nt,d) MODULE_PARM(n,ot) +#define LKM_MOD_PARAM_ARRAY(n,ot,nt,c,d) MODULE_PARM(n,ot) +#define LKM_EXPORT_SYM(s) +#define _free_netdev kfree + +#else /* LKM_2_6 */ + +#define LKM_MOD_PARAM(n,ot,nt,d) module_param(n,nt,d) +#define LKM_MOD_PARAM_ARRAY(n,ot,nt,c,d) module_param_array(n,nt,c,d) +#define LKM_EXPORT_SYM(s) EXPORT_SYMBOL(s) +#define _free_netdev free_netdev + +#endif /* LKM_2_x */ + +#ifndef list_for_each_safe +#define list_for_each_safe(l,t,i) t = 0; list_for_each((l),(i)) +#endif + +#ifndef reparent_to_init +#define reparent_to_init() +#endif + +#ifndef MODULE_LICENSE +#define MODULE_LICENSE(str) +#endif + +#ifndef EXPORT_NO_SYMBOLS +#define EXPORT_NO_SYMBOLS +#endif + +#ifndef DEFINE_SPINLOCK +#define DEFINE_SPINLOCK(_lock) spinlock_t _lock = SPIN_LOCK_UNLOCKED +#endif + +#ifndef __SPIN_LOCK_UNLOCKED +#define __SPIN_LOCK_UNLOCKED(_lock) SPIN_LOCK_UNLOCKED +#endif + +#ifndef lock_kernel +#ifdef preempt_disable +#define lock_kernel() preempt_disable() +#else +#define lock_kernel() +#endif +#endif + +#ifndef unlock_kernel +#ifdef preempt_enable +#define unlock_kernel() preempt_enable() +#else +#define unlock_kernel() +#endif +#endif + +#ifndef init_MUTEX_LOCKED +#define init_MUTEX_LOCKED(_sem) sema_init(_sem, 0) +#endif + +#ifdef CONFIG_BCM98245 +#define CONFIG_BMW +#endif + +#if PROC_INTERFACE_KERN_VER_3_10 +#define PROC_CREATE(_entry, _name, _acc, _path, _fops) \ + do { \ + _entry = proc_create(_name, _acc, _path, _fops); \ + } while (0) + +#define PROC_CREATE_DATA(_entry, _name, _acc, _path, _fops, _data) \ + do { \ + _entry = proc_create_data(_name, _acc, _path, _fops, _data); \ + } while (0) + +#define PROC_PDE_DATA(_node) PDE_DATA(_node) + +#else +#define PROC_CREATE(_entry, _name, _acc, _path, _fops) \ + do { \ + _entry = create_proc_entry(_name, _acc, _path); \ + if (_entry) { \ + _entry->proc_fops = _fops; \ + } \ + } while (0) + +#define PROC_CREATE_DATA(_entry, _name, _acc, _path, _fops, _data) \ + do { \ + _entry = create_proc_entry(_name, _acc, _path); \ + if (_entry) { \ + _entry->proc_fops = _fops; \ + _entry->data=_data; \ + } \ + } while (0) + +#define PROC_PDE_DATA(_node) PROC_I(_node)->pde->data +#endif + +#endif /* __COMMON_LINUX_KRN_LKM_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile new file mode 100644 index 000000000000..d7ca56cd5701 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile @@ -0,0 +1,64 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.3 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +LOCALDIR = systems/linux/kernel/modules/knet-cb + +include ${SDK}/make/Make.config + +LIBS = $(LIBDIR)/libkern.a + +ifeq ($(kernel_version),2_4) +MODULE = $(LIBDIR)/linux-knet-cb.o +else +KERNEL_MODULE_DIR = kernel_module + +THIS_MOD_NAME := linux-knet-cb +MODULE = $(LIBDIR)/$(THIS_MOD_NAME).o +KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko + +build: $(MODULE) $(KMODULE) +endif + +KBUILD_EXTRA_SYMBOLS := ${BLDDIR}/../bcm-knet/kernel_module/Module.symvers + +# BCM Network Device + +$(MODULE): $(BLDDIR)/.tree $(BOBJS) $(LIBS) + $(LD) $(MODULE_LDFLAGS) -r -d $(BOBJS) $(LIBS) -o $@ +ifneq ($(kernel_version),2_4) +$(KMODULE): $(MODULE) + rm -fr $(BLDDIR)/$(KERNEL_MODULE_DIR) + mkdir $(BLDDIR)/$(KERNEL_MODULE_DIR) + cp ${SDK}/make/Makefile.linux-kmodule $(BLDDIR)/$(KERNEL_MODULE_DIR)/Makefile + cat ${KBUILD_EXTRA_SYMBOLS} > $(BLDDIR)/$(KERNEL_MODULE_DIR)/Module.symvers + MOD_NAME=$(THIS_MOD_NAME) $(MAKE) -C $(BLDDIR)/$(KERNEL_MODULE_DIR) $(THIS_MOD_NAME).ko +endif + +# Make.depend is before clean:: so that Make.depend's clean:: runs first. + +include ${SDK}/make/Make.depend + +clean:: + $(RM) $(BLDDIR)/version.c $(BLDDIR)/version.o + $(RM) $(BOBJS) $(MODULE) + +ifneq ($(kernel_version),2_4) +.PHONY: build +endif diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c new file mode 100644 index 000000000000..da221f9f453a --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c @@ -0,0 +1,310 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: $ + * $Copyright: (c) 2017 Broadcom Corp. + * All Rights Reserved.$ + */ + +/* + * Driver for call-back functions for Linux KNET driver. + * + * This is sample code that demonstrates how to selectively strip VLAN tags + * from an incoming packet based on tag information in the DMA control block + * (DCB). The switch will automatically add a VLAN tag to packets that ingress + * without an outer VLAN tag. Outer tagged and double tagged packets are + * not modified. The call back defined here determines which packets have + * had tags added by those and strips only those tags from the packet. + * + * This is sample code, the customer is responsible for maintaining and + * modifying this code as necessary. + * + * The module can be built from the standard Linux user mode target + * directories using the following command (assuming bash), e.g. + * + * cd $SDK/systems/linux/user/ + * make BUILD_KNET_CB=1 + * + */ + +#include /* Must be included first */ +#include +#include +#include + +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("Broadcom Linux KNET Call-Back Driver"); +MODULE_LICENSE("GPL"); + + +static int debug; +LKM_MOD_PARAM(debug, "i", int, 0); +MODULE_PARM_DESC(debug, +"Debug level (default 0)"); + + +/* Module Information */ +#define MODULE_MAJOR 121 +#define MODULE_NAME "linux-knet-cb" + +/* set KNET_CB_DEBUG for debug info */ +#define KNET_CB_DEBUG + +#define FILTER_TAG_STRIP 0 +#define FILTER_TAG_KEEP 1 + +/* Maintain tag strip statistics */ +struct strip_stats_s { + unsigned long stripped; /* Number of packets that have been stripped */ + unsigned long checked; + unsigned long skipped; +}; + +static struct strip_stats_s strip_stats; + +/* Local function prototypes */ +static void strip_vlan_tag(struct sk_buff *skb); +static int get_tag_status(int dcb_type, void *meta); +static struct sk_buff *strip_tag_rx_cb(struct sk_buff *skb, int dev_no, void *meta); +static struct sk_buff *strip_tag_tx_cb(struct sk_buff *skb, int dev_no, void *meta); +static int strip_tag_filter_cb(uint8_t * pkt, int size, int dev_no, void *meta, + int chan, kcom_filter_t * kf); +static int _pprint(void); +static int _cleanup(void); +static int _init(void); + +/* Remove VLAN tag for select TPIDs */ +static void +strip_vlan_tag(struct sk_buff *skb) +{ + uint16_t vlan_proto = (uint16_t) ((skb->data[12] << 8) | skb->data[13]); + if ((vlan_proto == 0x8100) || (vlan_proto == 0x88a8) || (vlan_proto == 0x9100)) { + /* Move first 12 bytes of packet back by 4 */ + ((u32 *) skb->data)[3] = ((u32 *) skb->data)[2]; + ((u32 *) skb->data)[2] = ((u32 *) skb->data)[1]; + ((u32 *) skb->data)[1] = ((u32 *) skb->data)[0]; + skb_pull(skb, 4); /* Remove 4 bytes from start of buffer */ + } +} + +/* + * Location of tagging status in select DCB types found below: + * + * DCB type 14: word 12, bits 10.11 + * DCB type 19, 20, 21, 22, 30: word 12, bits 10..11 + * DCB type 23, 29: word 13, bits 0..1 + * DCB type 31, 34, 37: word 13, bits 0..1 + * DCB type 26, 32, 33, 35: word 13, bits 0..1 + * + * The function get_tag_status() returns the tag status for known DCB types. + * 0 = Untagged + * 1 = Single inner-tag + * 2 = Single outer-tag + * 3 = Double tagged. + * -1 = Unsupported DCB type + */ +static int +get_tag_status(int dcb_type, void *meta) +{ + uint32 *dcb = (uint32 *) meta; + int tag_status; + switch (dcb_type) { + case 14: + case 19: + case 20: + case 21: + case 22: + case 30: + tag_status = (dcb[12] > 10) & 0x3; + break; + case 23: + case 29: + case 31: + case 34: + case 37: + case 26: + case 32: + case 33: + case 35: + tag_status = dcb[13] & 0x3; + break; + case 36: + /* TD3 */ + tag_status = ((dcb[13] >> 9) & 0x3); + break; + break; + case 38: + { + /* untested */ + /* TH3 only parses outer tag. */ + const int tag_map[4] = { 0, 2, -1, -1 }; + tag_status = tag_map[(dcb[9] >> 13) & 0x3]; + } + break; + default: + tag_status = -1; + break; + } +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + gprintk("%s; DCB Type: %d; tag status: %d\n", __func__, dcb_type, tag_status); + } +#endif + return tag_status; +} + +/* Rx packet callback function */ +static struct sk_buff * +strip_tag_rx_cb(struct sk_buff *skb, int dev_no, void *meta) +{ + unsigned netif_flags = KNET_SKB_CB(skb)->netif_user_data; + unsigned filter_flags = KNET_SKB_CB(skb)->filter_user_data; + unsigned dcb_type; + int tag_status; + unsigned int strip_tag = 0; + /* Currently not using filter flags: + * unsigned filter_flags = KNET_SKB_CB(skb)->filter_user_data; + */ + +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + gprintk("%s Enter; netif Flags: %08X filter_flags %08X \n", + __func__, netif_flags, filter_flags); + } +#endif + + /* KNET implements this already */ + if (filter_flags == FILTER_TAG_KEEP) + { + strip_stats.skipped++; + return skb; + } + + /* SAI strip implies always strip. If the packet is untagged or + inner taged, SDK adds a .1q tag, so we need to strip tag + anyway */ + if (filter_flags == FILTER_TAG_STRIP) + { + strip_tag = 1; + } + /* Get DCB type for this packet, passed by KNET driver */ + dcb_type = KNET_SKB_CB(skb)->dcb_type; + + /* Get tag status from DCB */ + tag_status = get_tag_status(dcb_type, meta); + +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + gprintk("%s; DCB Type: %d; tag status: %d\n", __func__, dcb_type, tag_status); + } +#endif + + if (tag_status < 0) { + /* Unsupported DCB type */ + return skb; + } + + strip_stats.checked++; + + if (strip_tag) { +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + gprintk("%s; Stripping VLAN\n", __func__); + } +#endif + strip_stats.stripped++; + strip_vlan_tag(skb); + } +#ifdef KNET_CB_DEBUG + else { + if (debug & 0x1) { + gprintk("%s; Preserve VLAN\n", __func__); + } + } +#endif + + return skb; +} + +/* Tx callback not used */ +static struct sk_buff * +strip_tag_tx_cb(struct sk_buff *skb, int dev_no, void *meta) +{ + /* Pass through for now */ + return skb; +} + +/* Filter callback not used */ +static int +strip_tag_filter_cb(uint8_t * pkt, int size, int dev_no, void *meta, + int chan, kcom_filter_t *kf) +{ + /* Pass through for now */ + return 0; +} + +/* + * Get statistics. + * % cat /proc/linux-knet-cb + */ +static int +_pprint(void) +{ + pprintf("Broadcom Linux KNET Call-Back: Untagged VLAN Stripper\n"); + pprintf(" %lu stripped packets\n", strip_stats.stripped); + pprintf(" %lu packets checked\n", strip_stats.checked); + pprintf(" %lu packets skipped\n", strip_stats.skipped); + + return 0; +} + +static int +_cleanup(void) +{ + bkn_rx_skb_cb_unregister(strip_tag_rx_cb); + bkn_tx_skb_cb_unregister(strip_tag_tx_cb); + bkn_filter_cb_unregister(strip_tag_filter_cb); + + return 0; +} + +static int +_init(void) +{ + bkn_rx_skb_cb_register(strip_tag_rx_cb); + bkn_tx_skb_cb_register(strip_tag_tx_cb); + bkn_filter_cb_register(strip_tag_filter_cb); + + return 0; +} + +static gmodule_t _gmodule = { + name: MODULE_NAME, + major: MODULE_MAJOR, + init: _init, + cleanup: _cleanup, + pprint: _pprint, + ioctl: NULL, + open: NULL, + close: NULL, +}; + +gmodule_t* +gmodule_get(void) +{ + EXPORT_NO_SYMBOLS; + return &_gmodule; +} diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/Makefile new file mode 100644 index 000000000000..5e97a3a32123 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/Makefile @@ -0,0 +1,29 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +LOCALDIR = systems/linux/kernel/modules/shared + +include ${SDK}/make/Make.config + +lib = libkern + +include ${SDK}/make/Make.kernlib + +include ${SDK}/make/Make.depend diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/gmodule.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/gmodule.c new file mode 100644 index 000000000000..cdfaf089674a --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/gmodule.c @@ -0,0 +1,427 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: gmodule.c,v 1.20 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + * + * Generic Linux Module Framework + * + * Hooks up your driver to the kernel + */ + +#include +#include +#include +#include + +/* Module Vector Table */ +static gmodule_t* _gmodule = NULL; + + +/* Allow DEVFS Support on 2.4 Kernels */ +#if defined(LKM_2_4) && defined(CONFIG_DEVFS_FS) +#define GMODULE_CONFIG_DEVFS_FS +#endif + + +#ifdef GMODULE_CONFIG_DEVFS_FS +devfs_handle_t devfs_handle = NULL; +#endif + +/* FIXME: support dynamic debugging */ + +static int _dbg_enable = 0; + +static int +gvprintk(const char* fmt, va_list args) + __attribute__ ((format (printf, 1, 0))); + +static int +gvprintk(const char* fmt, va_list args) +{ + static char _buf[256]; + + strcpy(_buf, ""); + sprintf(_buf, "%s (%d): ", _gmodule->name, current->pid); + vsprintf(_buf+strlen(_buf), fmt, args); + printk("%s",_buf); + + return 0; +} + +int +gprintk(const char* fmt, ...) +{ + int rv; + + va_list args; + va_start(args, fmt); + rv = gvprintk(fmt, args); + va_end(args); + return rv; +} + +int +gdbg(const char* fmt, ...) +{ + int rv = 0; + + va_list args; + va_start(args, fmt); + if(_dbg_enable) { + rv = gvprintk(fmt, args); + } + va_end(args); + return rv; +} + + +/* + * Proc FS Utilities + */ +#if PROC_INTERFACE_KERN_VER_3_10 +static struct seq_file* _proc_buf = NULL; + +int +pprintf(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + seq_vprintf(_proc_buf, fmt, args); + va_end(args); + return 0; +} + +static int _gmodule_proc_show(struct seq_file *m, void *v){ + _proc_buf = m; + _gmodule->pprint(); + return 0; +} + +static int +_gmodule_proc_open(struct inode * inode, struct file * file) { + if(_gmodule->open) { + _gmodule->open(); + } + + return single_open(file, _gmodule_proc_show, NULL); +} + +static ssize_t +_gmodule_proc_write(struct file *file, const char *buffer, + size_t count, loff_t *loff) +{ + /* Workaround to toggle debugging */ + if(count > 2) { + if(buffer[0] == 'd') { + _dbg_enable = buffer[1] - '0'; + GDBG("Debugging Enabled"); + } + } + return count; +} + +static int _gmodule_proc_release(struct inode * inode, struct file * file) { + if(_gmodule->close) { + _gmodule->close(); + } + + return single_release(inode, file); +} + +struct file_operations _gmodule_proc_fops = { + owner: THIS_MODULE, + open: _gmodule_proc_open, + read: seq_read, + llseek: seq_lseek, + write: _gmodule_proc_write, + release: _gmodule_proc_release, +}; +#else +int +gmodule_vpprintf(char** page_ptr, const char* fmt, va_list args) +{ + *page_ptr += vsprintf(*page_ptr, fmt, args); + return 0; +} + +int +gmodule_pprintf(char** page_ptr, const char* fmt, ...) +{ + int rv; + + va_list args; + va_start(args, fmt); + rv = gmodule_vpprintf(page_ptr, fmt, args); + va_end(args); + return rv; +} + +static char* _proc_buf = NULL; + +int +pprintf(const char* fmt, ...) +{ + int rv; + + va_list args; + va_start(args, fmt); + rv = gmodule_vpprintf(&_proc_buf, fmt, args); + va_end(args); + return rv; +} + +#define PSTART(b) _proc_buf = b +#define PPRINT proc_print +#define PEND(b) (_proc_buf-b) + +static int +_gmodule_pprint(char* buf) +{ + PSTART(buf); + _gmodule->pprint(); + return PEND(buf); +} + +static int +_gmodule_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + *eof = 1; + return _gmodule_pprint(page); +} + +static int +_gmodule_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + /* Workaround to toggle debugging */ + if(count > 2) { + if(buffer[0] == 'd') { + _dbg_enable = buffer[1] - '0'; + GDBG("Debugging Enabled"); + } + } + return count; +} +#endif + +static int +_gmodule_create_proc(void) +{ + struct proc_dir_entry* ent; +#if PROC_INTERFACE_KERN_VER_3_10 + if((ent = proc_create(_gmodule->name, + S_IRUGO | S_IWUGO, + NULL, + &_gmodule_proc_fops)) != NULL) { + return 0; + } +#else + if((ent = create_proc_entry(_gmodule->name, S_IRUGO | S_IWUGO, NULL)) != NULL) { + ent->read_proc = _gmodule_read_proc; + ent->write_proc = _gmodule_write_proc; + return 0; + } +#endif + return -1; +} + +static void +_gmodule_remove_proc(void) +{ + remove_proc_entry(_gmodule->name, NULL); +} + +static int +_gmodule_open(struct inode *inode, struct file *filp) +{ + if(_gmodule->open) { + _gmodule->open(); + } + return 0; +} + +static int +_gmodule_release(struct inode *inode, struct file *filp) +{ + if(_gmodule->close) { + _gmodule->close(); + } + return 0; +} + +#ifdef HAVE_UNLOCKED_IOCTL +static long +_gmodule_unlocked_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + if(_gmodule->ioctl) { + return _gmodule->ioctl(cmd, arg); + } else { + return -1; + } +} +#else +static int +_gmodule_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + if(_gmodule->ioctl) { + return _gmodule->ioctl(cmd, arg); + } else { + return -1; + } +} +#endif + +#ifdef HAVE_COMPAT_IOCTL +static long +_gmodule_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + if(_gmodule->ioctl) { + return _gmodule->ioctl(cmd, arg); + } else { + return -1; + } +} +#endif + + +static int +_gmodule_mmap(struct file *filp, struct vm_area_struct *vma) +{ + if (_gmodule->mmap) { + return _gmodule->mmap(filp, vma); + } +#ifdef BCM_PLX9656_LOCAL_BUS + vma->vm_flags |= VM_RESERVED | VM_IO; + pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED; + + if (io_remap_pfn_range( vma, + vma->vm_start, + vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) { + return (-EAGAIN); + } + return (0); +#else/* BCM_PLX9656_LOCAL_BUS */ + return -EPERM; +#endif/* BCM_PLX9656_LOCAL_BUS */ +} + +/* FILE OPERATIONS */ + +struct file_operations _gmodule_fops = { +#ifdef HAVE_UNLOCKED_IOCTL + unlocked_ioctl: _gmodule_unlocked_ioctl, +#else + ioctl: _gmodule_ioctl, +#endif + open: _gmodule_open, + release: _gmodule_release, + mmap: _gmodule_mmap, +#ifdef HAVE_COMPAT_IOCTL + compat_ioctl: _gmodule_compat_ioctl, +#endif +}; + + +void __exit +cleanup_module(void) +{ + if(!_gmodule) return; + + /* Specific Cleanup */ + if(_gmodule->cleanup) { + _gmodule->cleanup(); + } + + /* Remove any proc entries */ + if(_gmodule->pprint) { + _gmodule_remove_proc(); + } + + /* Finally, remove ourselves from the universe */ +#ifdef GMODULE_CONFIG_DEVFS_FS + if(devfs_handle) devfs_unregister(devfs_handle); +#else + unregister_chrdev(_gmodule->major, _gmodule->name); +#endif +} + +int __init +init_module(void) +{ + int rc; + + /* Get our definition */ + _gmodule = gmodule_get(); + if(!_gmodule) return -ENODEV; + + + /* Register ourselves */ +#ifdef GMODULE_CONFIG_DEVFS_FS + devfs_handle = devfs_register(NULL, + _gmodule->name, + DEVFS_FL_NONE, + _gmodule->major, + _gmodule->minor, + S_IFCHR | S_IRUGO | S_IWUGO, + &_gmodule_fops, + NULL); + if(!devfs_handle) { + printk(KERN_WARNING "%s: can't register device with devfs", + _gmodule->name); + } + rc = 0; +#else + rc = register_chrdev(_gmodule->major, + _gmodule->name, + &_gmodule_fops); + if (rc < 0) { + printk(KERN_WARNING "%s: can't get major %d", + _gmodule->name, _gmodule->major); + return rc; + } + + if(_gmodule->major == 0) { + _gmodule->major = rc; + } +#endif + + /* Specific module Initialization */ + if(_gmodule->init) { + int rc; + if((rc = _gmodule->init()) < 0) { +#ifdef GMODULE_CONFIG_DEVFS_FS + if(devfs_handle) devfs_unregister(devfs_handle); +#else + unregister_chrdev(_gmodule->major, _gmodule->name); +#endif + return rc; + } + } + + /* Add a /proc entry, if valid */ + if(_gmodule->pprint) { + _gmodule_create_proc(); + } + + return 0; /* succeed */ +} diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/ksal.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/ksal.c new file mode 100644 index 000000000000..d1caf871f0e2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/ksal.c @@ -0,0 +1,249 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: ksal.c,v 1.1 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#include +#include + +#include "lkm.h" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else +#include +#endif +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) +#include +#endif +#include + +#ifdef MAX_USER_RT_PRIO +/* Assume 2.6 scheduler */ +#define SAL_YIELD(task) \ + yield() +#else +/* Assume 2.4 scheduler */ +#define SAL_YIELD(task) \ +do { \ + task->policy |= SCHED_YIELD; \ + schedule(); \ +} while (0) +#endif + +#define SECOND_USEC (1000000) +#define USECS_PER_JIFFY (SECOND_USEC / HZ) +#define USEC_TO_JIFFIES(usec) ((usec + (USECS_PER_JIFFY - 1)) / USECS_PER_JIFFY) + +#define sal_alloc(size, desc) kmalloc(size, GFP_KERNEL) +#define sal_free(ptr) kfree(ptr) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) +#define WQ_SLEEP(a, b) wait_event_interruptible_timeout(a, NULL, b) +#else +#define WQ_SLEEP(a, b) interruptible_sleep_on_timeout(&(a), b) +#endif +/* + * sem_ctrl_t + * + * The semaphore control type uses the binary property to implement + * timed semaphores with improved performance using wait queues. + */ + +typedef struct sem_ctrl_s { + struct semaphore sem; + int binary; + int cnt; + wait_queue_head_t wq; +} sem_ctrl_t; + +sal_sem_t +sal_sem_create(char *desc, int binary, int initial_count) +{ + sem_ctrl_t *s; + + if ((s = sal_alloc(sizeof(*s), desc)) != 0) { + sema_init(&s->sem, initial_count); + s->binary = binary; + if (s->binary) { + init_waitqueue_head(&s->wq); + } + } + + return (sal_sem_t) s; +} + +void +sal_sem_destroy(sal_sem_t b) +{ + sem_ctrl_t *s = (sem_ctrl_t *) b; + + if (s == NULL) { + return; + } + + /* + * the linux kernel does not have a sema_destroy(s) + */ + sal_free(s); +} + +int +sal_sem_take(sal_sem_t b, int usec) +{ + sem_ctrl_t *s = (sem_ctrl_t *) b; + int err; + + if (usec == sal_sem_FOREVER && !in_interrupt()) { + err = down_interruptible(&s->sem); + } else { + int time_wait = 1; + int cnt = s->cnt; + + for (;;) { + if (down_trylock(&s->sem) == 0) { + err = 0; + break; + } + + if (s->binary) { + + /* Wait for event or timeout */ + + if (time_wait > 1) { + err = 1; + break; + } + err = wait_event_interruptible_timeout(s->wq, cnt != s->cnt, + USEC_TO_JIFFIES(usec)); + if (err < 0) { + break; + } + time_wait++; + + } else { + + /* Retry algorithm with exponential backoff */ + + if (time_wait > usec) { + time_wait = usec; + } + + sal_usleep(time_wait); + + usec -= time_wait; + + if (usec == 0) { + err = ETIMEDOUT; + break; + } + + if ((time_wait *= 2) > 100000) { + time_wait = 100000; + } + } + } + } + return err ? -1 : 0; +} + +int +sal_sem_give(sal_sem_t b) +{ + sem_ctrl_t *s = (sem_ctrl_t *) b; + + up(&s->sem); + if (s->binary) { + s->cnt++; + wake_up_interruptible(&s->wq); + } + return 0; +} + +uint32 +sal_time_usecs(void) +{ + struct timeval ltv; + do_gettimeofday(<v); + return (ltv.tv_sec * SECOND_USEC + ltv.tv_usec); +} + +void +sal_usleep(uint32 usec) +{ + uint32 start_usec; + wait_queue_head_t queue; + + if (usec <= SECOND_USEC / HZ) { + start_usec = sal_time_usecs(); + do { + SAL_YIELD(current); + } while ((sal_time_usecs() - start_usec) < usec); + } else { + init_waitqueue_head(&queue); + WQ_SLEEP(queue, USEC_TO_JIFFIES(usec)); + } +} + +void +sal_udelay(uint32 usec) +{ + static volatile int _sal_udelay_counter; + static int loops = 0; + int ix, iy; + + if (loops == 0 || usec == 0) { /* Need calibration? */ + int max_loops; + int start = 0, stop = 0; + int mpt = USECS_PER_JIFFY; /* usec/tick */ + + for (loops = 1; loops < 0x1000 && stop == start; loops <<= 1) { + /* Wait for clock turn over */ + for (stop = start = jiffies; start == stop; start = jiffies) { + /* Empty */ + } + sal_udelay(mpt); /* Single recursion */ + stop = jiffies; + } + + max_loops = loops / 2; /* Loop above overshoots */ + + start = stop = 0; + + if (loops < 4) { + loops = 4; + } + + for (loops /= 4; loops < max_loops && stop == start; loops++) { + /* Wait for clock turn over */ + for (stop = start = jiffies; start == stop; start = jiffies) { + /* Empty */ + } + sal_udelay(mpt); /* Single recursion */ + stop = jiffies; + } + } + + for (iy = 0; iy < usec; iy++) { + for (ix = 0; ix < loops; ix++) { + _sal_udelay_counter++; /* Prevent optimizations */ + } + } +} diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/bmw-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/bmw-2_6/Makefile new file mode 100644 index 000000000000..899c7b405374 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/bmw-2_6/Makefile @@ -0,0 +1,63 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.4 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# PPC_TOOLS_DIR - path to build tools (if not in PATH already) +# PPC_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=bmw-$(kernel_version) + +# Windriver linux version +#WRS_LINUX_VERSION=1.4 +#WRS_LINUX_VERSION=2.0 + +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile new file mode 100644 index 000000000000..0e6226544334 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile @@ -0,0 +1,235 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.4 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override-target=linux-$(platform) + +ifeq ($(LINUX_MAKE_SHARED_LIB),1) +libext = so.$(SHAREDLIBVER) +else +libext = a +endif + +ifeq (,$(platform)) +$(error Internal error: platform variable is not set) +endif + +include $(SDK)/make/Make.config +LOCALDIR=systems/linux/user/common +include $(SDK)/make/Make.depend +kernel-override=linux-$(platform) +ifdef BLDCONFIG +KERN_BLDROOT=${SDK}/${SDKBUILD}/${BLDCONFIG}/$(kernel-override)$(bldroot_suffix) +else +KERN_BLDROOT=${SDK}/${SDKBUILD}/$(kernel-override)$(bldroot_suffix) +endif + +ifeq (,$(kernel_version)) +kernel_version=2_4 +endif + +ifeq ($(kernel_version),2_6) +KOBJ=ko +else +KOBJ=o +endif + +ifneq (,$(TOOLS_DIR)) +override PATH := $(TOOLS_DIR):$(PATH) +endif + +ifeq ($(DEST_DIR),) +DEST_DIR=${BLDDIR} +endif + +KERNEL_BDE_LOCAL :=linux-kernel-bde.$(KOBJ) +KERNEL_BDE :=$(DEST_DIR)/$(KERNEL_BDE_LOCAL) + +USER_BDE_LOCAL :=linux-user-bde.$(KOBJ) +USER_BDE=$(DEST_DIR)/$(USER_BDE_LOCAL) + +KNET_CB_LOCAL := linux-knet-cb.$(KOBJ) +KNET_CB := $(DEST_DIR)/$(KNET_CB_LOCAL) + +BCM_KNET_LOCAL :=linux-bcm-knet.$(KOBJ) +BCM_KNET=$(DEST_DIR)/$(BCM_KNET_LOCAL) + +ifeq (,$(findstring DELIVER,$(MAKECMDGOALS))) +.DEFAULT_GOAL := all +all_targets := kernel_modules $(KERNEL_BDE) $(USER_BDE) + +LOCAL_TARGETS := + +ifeq ($(NO_LOCAL_TARGETS),) +LOCAL_TARGETS +=$(patsubst %,$(realpath ..)/$(platform)/%,$(KERNEL_BDE_LOCAL) $(USER_BDE_LOCAL)) + +all_targets +=$(LOCAL_TARGETS) +endif + +# Build all by default +ifndef BUILD_KNET +BUILD_KNET = 1 +endif + +ifeq ($(BUILD_KNET),1) +# Kernel network support +all_targets += $(BCM_KNET) + +ifeq ($(NO_LOCAL_TARGETS),) +LOCAL_TARGETS +=$(patsubst %,../$(platform)/%,$(BCM_KNET_LOCAL)) +all_targets +=$(LOCAL_TARGETS) +endif + +ifdef BUILD_KNET_CB +all_targets += $(KNET_CB) + +ifeq ($(NO_LOCAL_TARGETS),) +LOCAL_TARGETS +=$(patsubst %,../$(platform)/%,$(KNET_CB_LOCAL)) +all_targets +=$(LOCAL_TARGETS) +endif +endif + +ADD_TO_CFLAGS += -I$(SDK)/systems/linux/kernel/modules/include +COND_KNET_LIBS = libuser.$(libext) +endif + +#SAI_FIXUP +.NOTPARALLEL: + +all: $(BLDDIR)/.tree $(all_targets) + +ifeq ($(NO_LOCAL_TARGETS),) +define LOCAL_TARGET_DEF +$(1) : $(DEST_DIR)/$(notdir $(1)) + cp $$? $$@ +endef +endif + +# User BDE libraries +ADD_TO_CFLAGS += -I$(SDK)/systems/bde/linux/include + +# Use raw IOCTL for KNET +ADD_TO_CFLAGS += -DPROXY_SUPPORT=0 + +CFLAGS += $(ADD_TO_CFLAGS) +#SAI_FIXUP +CFLAGS:=$(filter-out -fPIC, $(CFLAGS)) + + +kernel_modules: + $(MAKE) -C $(SDK)/systems/bde/linux/kernel kernel_version=$(kernel_version) + $(MAKE) -C $(SDK)/systems/bde/linux/user/kernel kernel_version=$(kernel_version) +ifeq ($(BUILD_KNET),1) + $(MAKE) -j1 -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \ + subdirs="shared bcm-knet" override-target=linux-$(platform) CFLAGS="$(CFLAGS)" +ifdef BUILD_KNET_CB + $(MAKE) -j1 -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \ + subdirs="knet-cb" override-target=linux-$(platform) CFLAGS="$(CFLAGS)" +endif +endif + +$(KERNEL_BDE): $(KERN_BLDROOT)/linux-kernel-bde.$(KOBJ) + mkdir -p $(@D) + $(OBJCOPY) --strip-debug $< $@ + +$(USER_BDE): $(KERN_BLDROOT)/linux-user-bde.$(KOBJ) + $(OBJCOPY) --strip-debug $< $@ + +$(BCM_KNET): $(KERN_BLDROOT)/linux-bcm-knet.$(KOBJ) + $(OBJCOPY) --strip-debug $< $@ + +$(KNET_CB): $(KERN_BLDROOT)/linux-knet-cb.$(KOBJ) + $(OBJCOPY) --strip-debug $< $@ + +ifeq ($(NO_LOCAL_TARGETS),) +$(foreach targ,$(LOCAL_TARGETS),$(eval $(call LOCAL_TARGET_DEF,$(targ)))) +endif + +clean:: + $(MAKE) -C $(SDK)/systems/bde/linux/kernel $@ + $(MAKE) -C $(SDK)/systems/bde/linux/user/kernel $@ + $(MAKE) -C $(SDK)/systems/linux/kernel/modules \ + subdirs="shared bcm-knet knet-cb" \ + override-target=linux-$(platform) $@ + $(RM) $(KERNEL_BDE) $(USER_BDE) + $(RM) $(BCM_KNET) $(KNET_CB) + $(RM) $(KERN_BLDROOT)/linux-kernel-bde.$(KOBJ) + $(RM) $(KERN_BLDROOT)/linux-user-bde.$(KOBJ) + $(RM) $(KERN_BLDROOT)/linux-bcm-knet.$(KOBJ) + $(RM) $(KERN_BLDROOT)/linux-knet-cb.$(KOBJ) + $(RM) $(LOCAL_TARGETS) + +distclean:: clean + +.PHONY: variable + +# +# Echo variable values used for configuration +# usage: make VAR=CC variable +# +variable:: + @echo $($(VAR)) + +else +ifndef DELIVERY +$(error DELIVERY required) +endif + +DELIVERABLES := $(KERNEL_BDE) $(USER_BDE) +# 1= source +define DELIVERY_RULE +_DEL_TARG += $(DELIVERY)/$(notdir $(1)) +$(DELIVERY)/$(notdir $(1)) : $(1) + @mkdir -p $(DELIVERY) +ifeq ($(filter $(notdir $(BCM)) $(notdir $(BCM).dbg),$(notdir $1)),) + $(OBJCOPY) --strip-debug $$< $$@ +else + $(CP) -p $$< $$@ +endif +endef + +$(foreach f,$(DELIVERABLES),$(eval $(call DELIVERY_RULE,$(f)))) + +DELIVER: $(_DEL_TARG) +endif + +# Make.config defines remaining phony targets +.PHONY: build kernel_modules DELIVER + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/gto-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/gto-2_6/Makefile new file mode 100644 index 000000000000..c157f9ff35fc --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/gto-2_6/Makefile @@ -0,0 +1,84 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.9 Broadcom SDK $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# PPC_TOOLS_DIR - path to build tools (if not in PATH already) +# PPC_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=gto-$(kernel_version) +LINUX_MAKE_USER=1 +export LINKER_RELAX=1 + +# Select the build environment +#BUILD_PLATFORM=ELDK +#BUILD_PLATFORM=WR_LINUX + +#Select the LINUX KERNEL VERSION +#KERN_VER = 2.6.21.7 +#KERN_VER = 2.6.24.4 +#KERN_VER = 2.6.25 + + +# Select the ELDK version +#ELDK_VERSION=4.1 +#ELDK_VERSION=4.0 + +#Select WRS Linux version +#WRS_LINUX_VERSION=2.0 +#WRS_LINUX_VERSION=3.0 + + +export KERN_VER +export ELDK_VERSION +export BUILD_PLATFORM +export WRS_LINUX_VERSION + +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/gto/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/gto/Makefile new file mode 100644 index 000000000000..fd98f6d2f963 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/gto/Makefile @@ -0,0 +1,60 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.9 Broadcom SDK $ +# $Copyright: (c) 2015 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# PPC_TOOLS_DIR - path to build tools (if not in PATH already) +# PPC_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=4_4 +platform=gto +LINUX_MAKE_USER=1 +export LINKER_RELAX=1 + +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/iproc-3_14/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/iproc-3_14/Makefile new file mode 100644 index 000000000000..c9f538802f6d --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/iproc-3_14/Makefile @@ -0,0 +1,65 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.7 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=3_14 +platform=iproc-$(kernel_version) + +IPROC_BUILD=1 +export IPROC_BUILD +export BUILD_PLATFORM +export ARM_LINUX_VERSION + +LINUX_MAKE_USER=1 +export ADD_TO_CFLAGS + +include ${SDK}/make/Make.linux diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile new file mode 100644 index 000000000000..7a8b4a8b0c4d --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile @@ -0,0 +1,59 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.7 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=4_4 +platform=iproc + +IPROC_BUILD=1 +export IPROC_BUILD +export BUILD_PLATFORM +export ARM_LINUX_VERSION + +LINUX_MAKE_USER=1 +export ADD_TO_CFLAGS +export BR_NO_CCACHE + +include ${SDK}/make/Make.linux diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/jag-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/jag-2_6/Makefile new file mode 100644 index 000000000000..26a7f520f2d2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/jag-2_6/Makefile @@ -0,0 +1,79 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.4 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=jag-$(kernel_version) + +# Select the build environment +#BUILD_PLATFORM=ELDK +#BUILD_PLATFORM=WR_LINUX + +#Select the LINUX KERNEL VERSION +#KERN_VER = 2.6.21.7 + + +# Select the ELDK version +#ELDK_VERSION=4.1 + +# Windriver linux version +#WRS_LINUX_VERSION=1.4 +#WRS_LINUX_VERSION=2.0 + +export KERN_VER +export ELDK_VERSION +export BUILD_PLATFORM +export WRS_LINUX_VERSION + +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/nsx-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/nsx-2_6/Makefile new file mode 100644 index 000000000000..881ec34c2d36 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/nsx-2_6/Makefile @@ -0,0 +1,58 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.4 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=nsx-$(kernel_version) +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/nsx64/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/nsx64/Makefile new file mode 100644 index 000000000000..9e79d90fa992 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/nsx64/Makefile @@ -0,0 +1,57 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.3 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +platform=nsx64 +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/nsx_wrl-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/nsx_wrl-2_6/Makefile new file mode 100644 index 000000000000..4e86843cdc7c --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/nsx_wrl-2_6/Makefile @@ -0,0 +1,65 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.3 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=nsx_wrl-$(kernel_version) + +# Windriver linux version +#WRS_LINUX_VERSION=1.4 +#WRS_LINUX_VERSION=2.0 + +export WRS_LINUX_VERSION + +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/raptor-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/raptor-2_6/Makefile new file mode 100644 index 000000000000..10ab1a1cc259 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/raptor-2_6/Makefile @@ -0,0 +1,79 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.5 Broadcom SDK $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=raptor-$(kernel_version) + +# Select the build environment +#BUILD_PLATFORM=ELDK +#BUILD_PLATFORM=WR_LINUX + +#Select the LINUX KERNEL VERSION +#KERN_VER = 2.6.21.7 + + +# Select the ELDK version +#ELDK_VERSION=4.1 + +# Windriver linux version +#WRS_LINUX_VERSION=1.4 +#WRS_LINUX_VERSION=2.0 + +export KERN_VER +export ELDK_VERSION +export BUILD_PLATFORM +export WRS_LINUX_VERSION + +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/raptor/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/raptor/Makefile new file mode 100644 index 000000000000..df8800a1a786 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/raptor/Makefile @@ -0,0 +1,58 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.1 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +platform=raptor +LINUX_MAKE_USER=1 +CFGFLAGS += -DBCM_ICS +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/x86-smp_generic_64-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/x86-smp_generic_64-2_6/Makefile new file mode 100644 index 000000000000..29717b3af42a --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/x86-smp_generic_64-2_6/Makefile @@ -0,0 +1,45 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=x86-smp_generic_64-$(kernel_version) + +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux diff --git a/platform/broadcom/saibcm-modules/tools/mktool.pl b/platform/broadcom/saibcm-modules/tools/mktool.pl new file mode 100644 index 000000000000..8800c00613d8 --- /dev/null +++ b/platform/broadcom/saibcm-modules/tools/mktool.pl @@ -0,0 +1,292 @@ +# +# Copyright 2017 Broadcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# mktool.pl +# +# $Id: mktool.pl,v 1.5 Broadcom SDK $ +# +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved. $ + +use File::Path; +use File::Find; +use File::Copy; +use Cwd; + +($prog = $0) =~ s/.*\///; + +SWITCH: +{ + $op = shift; + + if ($op eq "-rm") { mktool_rm(@ARGV); last SWITCH; } + if ($op eq "-cp") { mktool_cp(@ARGV); last SWITCH; } + if ($op eq "-md") { mktool_md(@ARGV); last SWITCH; } + if ($op eq "-ln") { mktool_ln(@ARGV); last SWITCH; } + if ($op eq "-foreach") { mktool_foreach(@ARGV); last SWITCH; } + if ($op eq "-dep") { mktool_makedep(@ARGV); last SWITCH; } + if ($op eq "-echo") { mktool_echo(@ARGV); last SWITCH; } + if ($op eq "-beep") { mktool_beep(@ARGV); last SWITCH; } + die("$prog: unknown option '$op'\n"); +} + +exit 0; + + + + +# +# mktool_execute +# +# Executes a command, returns exist status. +# Performs token special translation before execution. +# + +sub mktool_execute +{ + my $token = shift; + my @cmds = @_; + +# printf("mktool_execute: token = '$token'\n"); + foreach $cmd (@cmds) + { + #printf("mktool_execute: cmd = '$cmd'\n"); + $cmd =~ s/\#\#/$token/g; + if($cmd =~ /^-p/) + { + $cmd =~ s/^-p//; + printf("$cmd\n"); + } + else + { + system($cmd); + my $excode = ($? >> 8); + exit $excode if $excode; + } + } +} + + +$find_regexp = ""; +@find_cmd; + +# +# mktool_foreach +# +sub mktool_foreach +{ + if($_[0] eq "-find") + { + shift; + $find_dir = shift; + $find_regexp = shift; + @find_cmds = @_; + + if(!($find_dir =~ /^\//)) + { + $find_dir = cwd() . "/" . $find_dir; + } + find(\&_mktool_foreach_find_wanted, $find_dir); + } + else + { + my $subdir = 0; + if($_[0] eq "-subdir") + { + $subdir = 1; + shift; + } + + my @thingies = split(' ', shift); + + foreach $thingy (@thingies) + { + chdir $thingy unless $subdir == 0; + mktool_execute($thingy, @_); + chdir ".." unless $subdir == 0; + } + } +} + + + +sub _mktool_foreach_find_wanted +{ + my $expr = "\$File::Find::name =~ /\^$find_regexp\$/"; + + if(eval($expr)) + { + mktool_execute($File::Find::name, @find_cmds); + exit $excode if $excode; + } +} + + +# +# rm +# +# Removes a list of objects +# +sub mktool_rm +{ + my($f); + + foreach $f (@_) { + eval { rmtree($f) }; + if ($@) { + die "$prog $op: failed to remove $f: $@\n"; + } + } +} + +# +# md +# +# Makes a list of directories +# +sub mktool_md +{ + my($dir); + + foreach $dir (@_) { + $dir =~ s!/+$!!; + eval { mkpath($dir) }; + if ($@) { + die "$prog $op: failed to make directory $dir: $@\n"; + } + } +} + + +sub mktool_cp +{ + my($from, $to) = @_; + + if (@_ != 2) { + die "$prog $op: must have two arguments\n"; + } + copy($from, $to) || + die "$prog $op: failed to copy $from to $to: $!\n"; +} + +sub mktool_ln +{ + my($old, $new) = @_; + + if (@_ != 2) { + die "$prog $op: must have two arguments\n"; + } + link ($old, $new) || + die "$prog $op: failed to link $new to $old: $!\n"; +} + + +# @echo "$@ \\" > ${BLDDIR}/$(notdir $@) +# @if ($(DEPEND)) >> $(BLDDIR)/$(notdir $@); then \ +# exit 0; \ +# else \ +# rm -f ${BLDDIR}/$(notdir $@); \ +# exit 1; \ +# fi + +# $(MAKEDEP) "$@" "$(BLDDIR)/$(notdir $@)" "$(DEPEND)" + +sub mktool_makedep +{ + my ($source, $target, $cmd, $curdir) = @_; + my @result = `$cmd`; + my $sdk = $ENV{'SDK'}; + my $count; + my $tmp; + local $resultant; + +## Comman $cmd +#Command $cmd +print <-1) & ($count < 20) ) + { + $line=~s/\/\w+\/\.\.//; + # if we hit a major recursion, revert the line, report + # this to the output and drop out of the loop, but do + # continue, this should not halt generation + if($count++>19) + { + print "mktool.pl: could not process $line \n\n"; + print ":: curdir $curdir\n"; + print ":: target $target\n"; + print ":: cmd $cmd\n"; + $line=$tmp; + } + } + + # set all the paths to use the $SDK variable + $line =~ s/$ENV{'SDK'}/\$\{SDK\}/g; + $resultant=$resultant . $line; + } + + # some compilers return extra newlines + $resultant=~s/\n//g; + + # now clean up the result + $resultant=~s/\\/\\\n/g; + + mktool_md($dirName) unless (-d $dirName); + open (TARGET, ">$target") || + die("$prog $op: cannot open '$target' for writing: $!\n"); + print TARGET "$resultant\n"; + close(TARGET); + } +} + +sub mktool_echo +{ + print "@_\n"; +} + +sub mktool_beep +{ + -t STDOUT && defined $ENV{MAKEBEEP} && print "\007"; +} diff --git a/platform/broadcom/sonic-platform-modules-accton/.gitignore b/platform/broadcom/sonic-platform-modules-accton/.gitignore new file mode 100644 index 000000000000..7f287d538227 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/.gitignore @@ -0,0 +1,50 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-accton/LICENSE b/platform/broadcom/sonic-platform-modules-accton/LICENSE new file mode 100644 index 000000000000..bc693f7a4c40 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2017 Accton Technology Corporation + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-accton/README.md b/platform/broadcom/sonic-platform-modules-accton/README.md new file mode 100644 index 000000000000..0ff20bb2d21b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/README.md @@ -0,0 +1 @@ +platform drivers of Accton products for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/fanutil.py new file mode 100755 index 000000000000..c16771e214e4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/fanutil.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 5 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + + FAN_NODE_NUM_OF_MAP = 6 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 3 + FAN_NODE_DUTY_IDX_OF_MAP = 4 + FANR_NODE_FAULT_IDX_OF_MAP = 5 + FANR_NODE_SPEED_IDX_OF_MAP = 6 + + BASE_VAL_PATH = '/sys/devices/platform/as5712_54x_fan/{0}' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan1_speed_rpm', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + (FAN_NUM_1_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan1_duty_cycle_percentage', + (FAN_NUM_1_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr1_fault', + (FAN_NUM_1_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr1_speed_rpm', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan2_speed_rpm', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + (FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + (FAN_NUM_2_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr2_fault', + (FAN_NUM_2_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr2_speed_rpm', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan3_speed_rpm', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + (FAN_NUM_3_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan3_duty_cycle_percentage', + (FAN_NUM_3_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr3_fault', + (FAN_NUM_3_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr3_speed_rpm', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan4_speed_rpm', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + (FAN_NUM_4_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan4_duty_cycle_percentage', + (FAN_NUM_4_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr4_fault', + (FAN_NUM_4_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr4_speed_rpm', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan5_speed_rpm', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + (FAN_NUM_5_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan5_duty_cycle_percentage', + (FAN_NUM_5_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr5_fault', + (FAN_NUM_5_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr5_speed_rpm', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + def get_fan_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) + + def set_fan_duty_cycle(self, fan_num, val): + return self._set_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP, val) + + def get_fanr_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + logging.debug('GET. FANR fault. fan_num, %d', fan_num) + return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/thermalutil.py new file mode 100755 index 000000000000..5b8f890e8819 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/thermalutil.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD + + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['61', '48'], + THERMAL_NUM_2_IDX: ['62', '49'], + THERMAL_NUM_3_IDX: ['63', '4a'], + } + + def __init__(self): + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1): + self._thermal_to_device_path_mapping[x] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/Makefile new file mode 100755 index 000000000000..39fe78bf8cae --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/Makefile @@ -0,0 +1,17 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= i2c-mux-accton_as5712_54x_cpld.o \ + accton_as5712_54x_fan.o leds-accton_as5712_54x.o accton_as5712_54x_psu.o \ + cpr_4011_4mxx.o ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +$(error KERNEL_SRC is not defined) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_fan.c new file mode 100755 index 000000000000..db81a1a8ca97 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_fan.c @@ -0,0 +1,437 @@ +/* + * A hwmon driver for the Accton as5710 54x fan contrl + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FAN_MAX_NUMBER 5 +#define FAN_SPEED_CPLD_TO_RPM_STEP 150 +#define FAN_SPEED_PRECENT_TO_CPLD_STEP 5 +#define FAN_DUTY_CYCLE_MIN 0 /* 10% ??*/ +#define FAN_DUTY_CYCLE_MAX 100 /* 100% */ + +#define CPLD_REG_FAN_STATUS_OFFSET 0xC +#define CPLD_REG_FANR_STATUS_OFFSET 0x1F +#define CPLD_REG_FAN_DIRECTION_OFFSET 0x1E + +#define CPLD_FAN1_REG_SPEED_OFFSET 0x10 +#define CPLD_FAN2_REG_SPEED_OFFSET 0x11 +#define CPLD_FAN3_REG_SPEED_OFFSET 0x12 +#define CPLD_FAN4_REG_SPEED_OFFSET 0x13 +#define CPLD_FAN5_REG_SPEED_OFFSET 0x14 + +#define CPLD_FANR1_REG_SPEED_OFFSET 0x18 +#define CPLD_FANR2_REG_SPEED_OFFSET 0x19 +#define CPLD_FANR3_REG_SPEED_OFFSET 0x1A +#define CPLD_FANR4_REG_SPEED_OFFSET 0x1B +#define CPLD_FANR5_REG_SPEED_OFFSET 0x1C + +#define CPLD_REG_FAN_PWM_CYCLE_OFFSET 0xD + +#define CPLD_FAN1_INFO_BIT_MASK 0x1 +#define CPLD_FAN2_INFO_BIT_MASK 0x2 +#define CPLD_FAN3_INFO_BIT_MASK 0x4 +#define CPLD_FAN4_INFO_BIT_MASK 0x8 +#define CPLD_FAN5_INFO_BIT_MASK 0x10 + +#define PROJECT_NAME + +#define LOCAL_DEBUG 0 + +static struct accton_as5712_54x_fan *fan_data = NULL; + +struct accton_as5712_54x_fan { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[FAN_MAX_NUMBER]; /* inner first fan status */ + u32 speed[FAN_MAX_NUMBER]; /* inner first fan speed */ + u8 direction[FAN_MAX_NUMBER]; /* reconrd the direction of inner first and second fans */ + u32 duty_cycle[FAN_MAX_NUMBER]; /* control the speed of inner first and second fans */ + u8 r_status[FAN_MAX_NUMBER]; /* inner second fan status */ + u32 r_speed[FAN_MAX_NUMBER]; /* inner second fan speed */ +}; + +/*******************/ +#define MAKE_FAN_MASK_OR_REG(name,type) \ + CPLD_FAN##type##1_##name, \ + CPLD_FAN##type##2_##name, \ + CPLD_FAN##type##3_##name, \ + CPLD_FAN##type##4_##name, \ + CPLD_FAN##type##5_##name, + +/* fan related data + */ +static const u8 fan_info_mask[] = { + MAKE_FAN_MASK_OR_REG(INFO_BIT_MASK,) +}; + +static const u8 fan_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,) +}; + +static const u8 fanr_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,R) +}; + +/*******************/ +#define DEF_FAN_SET(id) \ + FAN##id##_FAULT, \ + FAN##id##_SPEED, \ + FAN##id##_DUTY_CYCLE, \ + FAN##id##_DIRECTION, \ + FANR##id##_FAULT, \ + FANR##id##_SPEED, + +enum sysfs_fan_attributes { + DEF_FAN_SET(1) + DEF_FAN_SET(2) + DEF_FAN_SET(3) + DEF_FAN_SET(4) + DEF_FAN_SET(5) +}; +/*******************/ +static void accton_as5712_54x_fan_update_device(struct device *dev); +static int accton_as5712_54x_fan_read_value(u8 reg); +static int accton_as5712_54x_fan_write_value(u8 reg, u8 value); + +static ssize_t fan_set_duty_cycle(struct device *dev, + struct device_attribute *da,const char *buf, size_t count); +static ssize_t fan_show_value(struct device *dev, + struct device_attribute *da, char *buf); + +extern int as5712_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5712_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + + +/*******************/ +#define _MAKE_SENSOR_DEVICE_ATTR(prj, id) \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, \ + fan_set_duty_cycle, FAN##id##_DUTY_CYCLE); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_direction, S_IRUGO, fan_show_value, NULL, FAN##id##_DIRECTION); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_fault, S_IRUGO, fan_show_value, NULL, FANR##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED); + +#define MAKE_SENSOR_DEVICE_ATTR(prj,id) _MAKE_SENSOR_DEVICE_ATTR(prj,id) + +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 1) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 2) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 3) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 4) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 5) +/*******************/ + +#define _MAKE_FAN_ATTR(prj, id) \ + &sensor_dev_attr_##prj##fan##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_duty_cycle_percentage.dev_attr.attr,\ + &sensor_dev_attr_##prj##fan##id##_direction.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_speed_rpm.dev_attr.attr, + +#define MAKE_FAN_ATTR(prj, id) _MAKE_FAN_ATTR(prj, id) + +static struct attribute *accton_as5712_54x_fan_attributes[] = { + /* fan related attributes */ + MAKE_FAN_ATTR(PROJECT_NAME,1) + MAKE_FAN_ATTR(PROJECT_NAME,2) + MAKE_FAN_ATTR(PROJECT_NAME,3) + MAKE_FAN_ATTR(PROJECT_NAME,4) + MAKE_FAN_ATTR(PROJECT_NAME,5) + NULL +}; +/*******************/ + +/* fan related functions + */ +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + ssize_t ret = 0; + int data_index, type_index; + + accton_as5712_54x_fan_update_device(dev); + + if (fan_data->valid == 0) { + return ret; + } + + type_index = attr->index%FAN2_FAULT; + data_index = attr->index/FAN2_FAULT; + + switch (type_index) { + case FAN1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->status[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->speed[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DUTY_CYCLE: + ret = sprintf(buf, "%d\n", fan_data->duty_cycle[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DIRECTION: + ret = sprintf(buf, "%d\n", fan_data->direction[data_index]); /* presnet, need to modify*/ + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->r_status[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->r_speed[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + default: + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d] \n", __FUNCTION__, __LINE__); + break; + } + + return ret; +} +/*******************/ +static ssize_t fan_set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { + + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < FAN_DUTY_CYCLE_MIN || value > FAN_DUTY_CYCLE_MAX) + return -EINVAL; + + accton_as5712_54x_fan_write_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET, value/FAN_SPEED_PRECENT_TO_CPLD_STEP); + + fan_data->valid = 0; + + return count; +} + +static const struct attribute_group accton_as5712_54x_fan_group = { + .attrs = accton_as5712_54x_fan_attributes, +}; + +static int accton_as5712_54x_fan_read_value(u8 reg) +{ + return as5712_54x_cpld_read(0x60, reg); +} + +static int accton_as5712_54x_fan_write_value(u8 reg, u8 value) +{ + return as5712_54x_cpld_write(0x60, reg, value); +} + +static void accton_as5712_54x_fan_update_device(struct device *dev) +{ + int speed, r_speed, fault, r_fault, ctrl_speed, direction; + int i; + + mutex_lock(&fan_data->update_lock); + + if (LOCAL_DEBUG) + printk ("Starting accton_as5712_54x_fan update \n"); + + if (!(time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) || !fan_data->valid)) { + /* do nothing */ + goto _exit; + } + + fan_data->valid = 0; + + if (LOCAL_DEBUG) + printk ("Starting accton_as5712_54x_fan update 2 \n"); + + fault = accton_as5712_54x_fan_read_value(CPLD_REG_FAN_STATUS_OFFSET); + r_fault = accton_as5712_54x_fan_read_value(CPLD_REG_FANR_STATUS_OFFSET); + direction = accton_as5712_54x_fan_read_value(CPLD_REG_FAN_DIRECTION_OFFSET); + ctrl_speed = accton_as5712_54x_fan_read_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET); + + if ( (fault < 0) || (r_fault < 0) || (direction < 0) || (ctrl_speed < 0) ) + { + if (LOCAL_DEBUG) + printk ("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + + if (LOCAL_DEBUG) + printk ("[fan:] fault:%d, r_fault=%d, direction=%d, ctrl_speed=%d \n",fault, r_fault, direction, ctrl_speed); + + for (i=0; istatus[i] = (fault & fan_info_mask[i]) >> i; + if (LOCAL_DEBUG) + printk ("[fan%d:] fail=%d \n",i, fan_data->status[i]); + + fan_data->r_status[i] = (r_fault & fan_info_mask[i]) >> i; + fan_data->direction[i] = (direction & fan_info_mask[i]) >> i; + fan_data->duty_cycle[i] = ctrl_speed * FAN_SPEED_PRECENT_TO_CPLD_STEP; + + /* fan speed + */ + speed = accton_as5712_54x_fan_read_value(fan_speed_reg[i]); + r_speed = accton_as5712_54x_fan_read_value(fanr_speed_reg[i]); + if ( (speed < 0) || (r_speed < 0) ) + { + if (LOCAL_DEBUG) + printk ("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + + if (LOCAL_DEBUG) + printk ("[fan%d:] speed:%d, r_speed=%d \n", i, speed, r_speed); + + fan_data->speed[i] = speed * FAN_SPEED_CPLD_TO_RPM_STEP; + fan_data->r_speed[i] = r_speed * FAN_SPEED_CPLD_TO_RPM_STEP; + } + + /* finish to update */ + fan_data->last_updated = jiffies; + fan_data->valid = 1; + +_exit: + mutex_unlock(&fan_data->update_lock); +} + +static int accton_as5712_54x_fan_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &accton_as5712_54x_fan_group); + if (status) { + goto exit; + + } + + fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(fan_data->hwmon_dev)) { + status = PTR_ERR(fan_data->hwmon_dev); + goto exit_remove; + } + + dev_info(&pdev->dev, "accton_as5712_54x_fan\n"); + + return 0; + +exit_remove: + sysfs_remove_group(&pdev->dev.kobj, &accton_as5712_54x_fan_group); +exit: + return status; +} + +static int accton_as5712_54x_fan_remove(struct platform_device *pdev) +{ + hwmon_device_unregister(fan_data->hwmon_dev); + sysfs_remove_group(&fan_data->pdev->dev.kobj, &accton_as5712_54x_fan_group); + + return 0; +} + +#define DRVNAME "as5712_54x_fan" + +static struct platform_driver accton_as5712_54x_fan_driver = { + .probe = accton_as5712_54x_fan_probe, + .remove = accton_as5712_54x_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as5712_54x_fan_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as5712_54x_fan_driver); + if (ret < 0) { + goto exit; + } + + fan_data = kzalloc(sizeof(struct accton_as5712_54x_fan), GFP_KERNEL); + if (!fan_data) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as5712_54x_fan_driver); + goto exit; + } + + mutex_init(&fan_data->update_lock); + fan_data->valid = 0; + + fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(fan_data->pdev)) { + ret = PTR_ERR(fan_data->pdev); + platform_driver_unregister(&accton_as5712_54x_fan_driver); + kfree(fan_data); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as5712_54x_fan_exit(void) +{ + platform_device_unregister(fan_data->pdev); + platform_driver_unregister(&accton_as5712_54x_fan_driver); + kfree(fan_data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as5712_54x_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_as5712_54x_fan_init); +module_exit(accton_as5712_54x_fan_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_psu.c new file mode 100755 index 000000000000..9a0d1dae58ba --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_psu.c @@ -0,0 +1,371 @@ +/* + * An hwmon driver for accton as5712_54x Power Module + * + * Copyright (C) 2015 Accton Technology Corporation. + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +static ssize_t show_index(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as5712_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as5712_54x_cpld_read(unsigned short cpld_addr, u8 reg); +static int as5712_54x_psu_model_name_get(struct device *dev); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as5712_54x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[14]; /* Model name, read from eeprom */ +}; + +static struct as5712_54x_psu_data *as5712_54x_psu_update_device(struct device *dev); + +enum as5712_54x_psu_sysfs_attributes { + PSU_INDEX, + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_index, S_IRUGO, show_index, NULL, PSU_INDEX); +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as5712_54x_psu_attributes[] = { + &sensor_dev_attr_psu_index.dev_attr.attr, + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_index(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_psu_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", data->index); +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5712_54x_psu_data *data = as5712_54x_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as5712_54x_psu_data *data = as5712_54x_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!IS_PRESENT(data->index, data->status)) { + return 0; + } + + if (as5712_54x_psu_model_name_get(dev) < 0) { + return -ENXIO; + } + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as5712_54x_psu_group = { + .attrs = as5712_54x_psu_attributes, +}; + +static int as5712_54x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5712_54x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5712_54x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5712_54x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5712_54x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5712_54x_psu_remove(struct i2c_client *client) +{ + struct as5712_54x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5712_54x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as5712_54x_psu1, + as5712_54x_psu2 +}; + +static const struct i2c_device_id as5712_54x_psu_id[] = { + { "as5712_54x_psu1", as5712_54x_psu1 }, + { "as5712_54x_psu2", as5712_54x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as5712_54x_psu_id); + +static struct i2c_driver as5712_54x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as5712_54x_psu", + }, + .probe = as5712_54x_psu_probe, + .remove = as5712_54x_psu_remove, + .id_table = as5712_54x_psu_id, + .address_list = normal_i2c, +}; + +static int as5712_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +enum psu_type { + PSU_YM_2401_JCR, /* AC110V - F2B */ + PSU_YM_2401_JDR, /* AC110V - B2F */ + PSU_CPR_4011_4M11, /* AC110V - F2B */ + PSU_CPR_4011_4M21, /* AC110V - B2F */ + PSU_CPR_6011_2M11, /* AC110V - F2B */ + PSU_CPR_6011_2M21, /* AC110V - B2F */ + PSU_UM400D_01G, /* DC48V - F2B */ + PSU_UM400D01_01G /* DC48V - B2F */ +}; + +struct model_name_info { + enum psu_type type; + u8 offset; + u8 length; + char* model_name; +}; + +struct model_name_info models[] = { +{PSU_YM_2401_JCR, 0x20, 11, "YM-2401JCR"}, +{PSU_YM_2401_JDR, 0x20, 11, "YM-2401JDR"}, +{PSU_CPR_4011_4M11, 0x26, 13, "CPR-4011-4M11"}, +{PSU_CPR_4011_4M21, 0x26, 13, "CPR-4011-4M21"}, +{PSU_CPR_6011_2M11, 0x26, 13, "CPR-6011-2M11"}, +{PSU_CPR_6011_2M21, 0x26, 13, "CPR-6011-2M21"}, +{PSU_UM400D_01G, 0x50, 9, "um400d01G"}, +{PSU_UM400D01_01G, 0x50, 12, "um400d01-01G"}, +}; + +static int as5712_54x_psu_model_name_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_psu_data *data = i2c_get_clientdata(client); + int i, status; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + memset(data->model_name, 0, sizeof(data->model_name)); + + status = as5712_54x_psu_read_block(client, models[i].offset, + data->model_name, models[i].length); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x%x)\n", + client->addr, models[i].offset); + return status; + } + else { + data->model_name[models[i].length] = '\0'; + } + + if (i == PSU_YM_2401_JCR || i == PSU_YM_2401_JDR) { + /* Skip the meaningless data byte 8*/ + data->model_name[8] = data->model_name[9]; + data->model_name[9] = data->model_name[10]; + data->model_name[10] = '\0'; + } + + /* Determine if the model name is known, if not, read next index + */ + if (strncmp(data->model_name, models[i].model_name, models[i].length) == 0) { + return 0; + } + else { + data->model_name[0] = '\0'; + } + } + + return -ENODATA; +} + +static struct as5712_54x_psu_data *as5712_54x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + + dev_dbg(&client->dev, "Starting as5712_54x update\n"); + data->valid = 0; + + + /* Read psu status */ + status = as5712_54x_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as5712_54x_psu_init(void) +{ + return i2c_add_driver(&as5712_54x_psu_driver); +} + +static void __exit as5712_54x_psu_exit(void) +{ + i2c_del_driver(&as5712_54x_psu_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as5712_54x_psu driver"); +MODULE_LICENSE("GPL"); + +module_init(as5712_54x_psu_init); +module_exit(as5712_54x_psu_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_sfp.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_sfp.c new file mode 100755 index 000000000000..d236057c4e59 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_sfp.c @@ -0,0 +1,825 @@ +/* + * An hwmon driver for accton as5712_54x sfp + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUM_OF_SFF_PORT 54 +#define SFP_PORT_MAX 48 +#define I2C_ADDR_CPLD1 0x60 +#define I2C_ADDR_CPLD2 0x61 +#define I2C_ADDR_CPLD3 0x62 +#define CPLD3_OFFSET_QSFP_MOD_RST 0x15 +#define CPLD3_OFFSET_QSFP_LPMODE 0x16 + + +#define BIT_INDEX(i) (1ULL << (i)) + +#if 0 +static ssize_t show_status(struct device *dev, struct device_attribute *da,char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf); +static int as5712_54x_sfp_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as5712_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5712_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +#endif + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as5712_54x_sfp_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + int port; /* Front port index */ + char eeprom[256]; /* eeprom data */ + u64 status[4]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => is_present + 1 => tx_fail + 2 => tx_disable + 3 => rx_loss */ +}; + +/* The table maps active port to cpld port. + * Array index 0 is for active port 1, + * index 1 for active port 2, and so on. + * The array content implies cpld port index. + */ +static const u8 cpld_to_front_port_table[] = +{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 52, 50, 53, 51, 54}; + +#define CPLD_PORT_TO_FRONT_PORT(port) (cpld_to_front_port_table[port]) + +static struct as5712_54x_sfp_data *as5712_54x_sfp_update_device(struct device *dev, int update_eeprom); +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_lp_mode(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_lp_mode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +extern int as5712_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5712_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +enum as5712_54x_sfp_sysfs_attributes { + SFP_IS_PRESENT, + SFP_TX_FAULT, + SFP_TX_DISABLE, + SFP_RX_LOSS, + SFP_PORT_NUMBER, + SFP_EEPROM, + SFP_RX_LOS_ALL, + SFP_IS_PRESENT_ALL, + SFP_LP_MODE, + SFP_MOD_RST, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_status, NULL, SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, show_status, NULL, SFP_TX_FAULT); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, show_status, set_tx_disable, SFP_TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_rx_loss, S_IRUGO, show_status,NULL, SFP_RX_LOSS); +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, SFP_PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_eeprom, S_IRUGO, show_eeprom, NULL, SFP_EEPROM); +static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, show_status,NULL, SFP_RX_LOS_ALL); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_status,NULL, SFP_IS_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_lp_mode, S_IWUSR | S_IRUGO, get_lp_mode, set_lp_mode, SFP_LP_MODE); +static SENSOR_DEVICE_ATTR(sfp_mod_rst, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, SFP_MOD_RST); + +static struct attribute *as5712_54x_sfp_attributes[] = { + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_eeprom.dev_attr.attr, + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_lp_mode.dev_attr.attr, + &sensor_dev_attr_sfp_mod_rst.dev_attr.attr, + NULL +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5712_54x_sfp_data *data; + u8 val; + int values[7]; + + /* Error-check the CPLD read results. */ +#define VALIDATED_READ(_buf, _rv, _read_expr, _invert) \ + do { \ + _rv = (_read_expr); \ + if(_rv < 0) { \ + return sprintf(_buf, "READ ERROR\n"); \ + } \ + if(_invert) { \ + _rv = ~_rv; \ + } \ + _rv &= 0xFF; \ + } while(0) + + if(attr->index == SFP_RX_LOS_ALL) { + /* + * Report the RX_LOS status for all ports. + * This does not depend on the currently active SFP selector. + */ + + /* RX_LOS Ports 1-8 */ + VALIDATED_READ(buf, values[0], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x0F), 0); + /* RX_LOS Ports 9-16 */ + VALIDATED_READ(buf, values[1], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x10), 0); + /* RX_LOS Ports 17-24 */ + VALIDATED_READ(buf, values[2], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x11), 0); + /* RX_LOS Ports 25-32 */ + VALIDATED_READ(buf, values[3], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x0F), 0); + /* RX_LOS Ports 33-40 */ + VALIDATED_READ(buf, values[4], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x10), 0); + /* RX_LOS Ports 41-48 */ + VALIDATED_READ(buf, values[5], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x11), 0); + + /** Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5]); + } + + if(attr->index == SFP_IS_PRESENT_ALL) { + /* + * Report the SFP_PRESENCE status for all ports. + * This does not depend on the currently active SFP selector. + */ + + /* SFP_PRESENT Ports 1-8 */ + VALIDATED_READ(buf, values[0], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x6), 1); + /* SFP_PRESENT Ports 9-16 */ + VALIDATED_READ(buf, values[1], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x7), 1); + /* SFP_PRESENT Ports 17-24 */ + VALIDATED_READ(buf, values[2], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x8), 1); + /* SFP_PRESENT Ports 25-32 */ + VALIDATED_READ(buf, values[3], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x6), 1); + /* SFP_PRESENT Ports 33-40 */ + VALIDATED_READ(buf, values[4], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x7), 1); + /* SFP_PRESENT Ports 41-48 */ + VALIDATED_READ(buf, values[5], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x8), 1); + /* QSFP_PRESENT Ports 49-54 */ + VALIDATED_READ(buf, values[6], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x14), 1); + + /* Return values 1 -> 54 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5], + values[6] & 0x3F); + } + /* + * The remaining attributes are gathered on a per-selected-sfp basis. + */ + data = as5712_54x_sfp_update_device(dev, 0); + if (attr->index == SFP_IS_PRESENT) { + val = (data->status[attr->index] & BIT_INDEX(data->port)) ? 0 : 1; + } + else { + val = (data->status[attr->index] & BIT_INDEX(data->port)) ? 1 : 0; + } + + return sprintf(buf, "%d", val); +} + +static ssize_t get_lp_mode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + int port_bit; + int status = -EINVAL; + + /* Low power mode is not supported for SFP ports(1-48) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + mutex_lock(&data->update_lock); + + port_bit = data->port - SFP_PORT_MAX; + cpld_val = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_LPMODE); + cpld_val = cpld_val & 0x3F; + cpld_val = cpld_val & BIT_INDEX(port_bit); + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", cpld_val>>port_bit); + + mutex_unlock(&data->update_lock); + + return status; +} + +static ssize_t set_lp_mode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + long mode; + int error, port_bit; + + /* Tx disable is not supported for QSFP ports(49-54) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + port_bit = data->port - SFP_PORT_MAX; + error = kstrtol(buf, 10, &mode); + if (error) { + return error; + } + mutex_lock(&data->update_lock); + + cpld_val = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_LPMODE); + /* Update lp_mode status */ + if (mode) + { + cpld_val |= BIT_INDEX(port_bit); + } + else + { + cpld_val &=~BIT_INDEX(port_bit); + } + as5712_54x_i2c_cpld_write(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_LPMODE, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + int port_bit; + int status = -EINVAL; + + /* Low power mode is not supported for SFP ports(1-48) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + mutex_lock(&data->update_lock); + + port_bit = data->port - SFP_PORT_MAX; + cpld_val = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_MOD_RST); + cpld_val = cpld_val & 0x3F; + cpld_val = cpld_val & BIT_INDEX(port_bit); + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", cpld_val>>port_bit); + + mutex_unlock(&data->update_lock); + + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + long reset; + int error, port_bit; + + /* Tx disable is not supported for QSFP ports(49-54) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + port_bit = data->port - SFP_PORT_MAX; + error = kstrtol(buf, 10, &reset); + if (error) { + return error; + } + mutex_lock(&data->update_lock); + + cpld_val = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_MOD_RST); + /* Update lp_mode status */ + if (reset) + { + cpld_val |= BIT_INDEX(port_bit); + } + else + { + cpld_val &=~BIT_INDEX(port_bit); + } + as5712_54x_i2c_cpld_write(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_MOD_RST, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + unsigned short cpld_addr = 0; + u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; + long disable; + int error; + + /* Tx disable is not supported for QSFP ports(49-54) */ + if (data->port >= SFP_PORT_MAX) { + return -EINVAL; + } + + error = kstrtol(buf, 10, &disable); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + if(data->port < 24) { + cpld_addr = I2C_ADDR_CPLD2; + cpld_reg = 0xC + data->port / 8; + cpld_bit = 1 << (data->port % 8); + } + else { + cpld_addr = I2C_ADDR_CPLD3; + cpld_reg = 0xC + (data->port - 24) / 8; + cpld_bit = 1 << (data->port % 8); + } + + cpld_val = as5712_54x_i2c_cpld_read(cpld_addr, cpld_reg); + + /* Update tx_disable status */ + if (disable) { + data->status[SFP_TX_DISABLE] |= BIT_INDEX(data->port); + cpld_val |= cpld_bit; + } + else { + data->status[SFP_TX_DISABLE] &= ~BIT_INDEX(data->port); + cpld_val &= ~cpld_bit; + } + + as5712_54x_i2c_cpld_write(cpld_addr, cpld_reg, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as5712_54x_sfp_data *data = as5712_54x_sfp_update_device(dev, 1); + + if (!data->valid) { + return 0; + } + + if ((data->status[SFP_IS_PRESENT] & BIT_INDEX(data->port)) != 0) { + return 0; + } + + memcpy(buf, data->eeprom, sizeof(data->eeprom)); + + return sizeof(data->eeprom); +} + +static const struct attribute_group as5712_54x_sfp_group = { + .attrs = as5712_54x_sfp_attributes, +}; + +static int as5712_54x_sfp_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5712_54x_sfp_data *data; + int status; + + extern int platform_accton_as5712_54x(void); + if(!platform_accton_as5712_54x()) { + return -ENODEV; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5712_54x_sfp_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + i2c_set_clientdata(client, data); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5712_54x_sfp_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: sfp '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5712_54x_sfp_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5712_54x_sfp_remove(struct i2c_client *client) +{ + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5712_54x_sfp_group); + kfree(data); + + return 0; +} + +enum port_numbers { +as5712_54x_sfp1, as5712_54x_sfp2, as5712_54x_sfp3, as5712_54x_sfp4, +as5712_54x_sfp5, as5712_54x_sfp6, as5712_54x_sfp7, as5712_54x_sfp8, +as5712_54x_sfp9, as5712_54x_sfp10, as5712_54x_sfp11,as5712_54x_sfp12, +as5712_54x_sfp13, as5712_54x_sfp14, as5712_54x_sfp15,as5712_54x_sfp16, +as5712_54x_sfp17, as5712_54x_sfp18, as5712_54x_sfp19,as5712_54x_sfp20, +as5712_54x_sfp21, as5712_54x_sfp22, as5712_54x_sfp23,as5712_54x_sfp24, +as5712_54x_sfp25, as5712_54x_sfp26, as5712_54x_sfp27,as5712_54x_sfp28, +as5712_54x_sfp29, as5712_54x_sfp30, as5712_54x_sfp31,as5712_54x_sfp32, +as5712_54x_sfp33, as5712_54x_sfp34, as5712_54x_sfp35,as5712_54x_sfp36, +as5712_54x_sfp37, as5712_54x_sfp38, as5712_54x_sfp39,as5712_54x_sfp40, +as5712_54x_sfp41, as5712_54x_sfp42, as5712_54x_sfp43,as5712_54x_sfp44, +as5712_54x_sfp45, as5712_54x_sfp46, as5712_54x_sfp47,as5712_54x_sfp48, +as5712_54x_sfp49, as5712_54x_sfp52, as5712_54x_sfp50,as5712_54x_sfp53, +as5712_54x_sfp51, as5712_54x_sfp54 +}; + +static const struct i2c_device_id as5712_54x_sfp_id[] = { +{ "as5712_54x_sfp1", as5712_54x_sfp1 }, { "as5712_54x_sfp2", as5712_54x_sfp2 }, +{ "as5712_54x_sfp3", as5712_54x_sfp3 }, { "as5712_54x_sfp4", as5712_54x_sfp4 }, +{ "as5712_54x_sfp5", as5712_54x_sfp5 }, { "as5712_54x_sfp6", as5712_54x_sfp6 }, +{ "as5712_54x_sfp7", as5712_54x_sfp7 }, { "as5712_54x_sfp8", as5712_54x_sfp8 }, +{ "as5712_54x_sfp9", as5712_54x_sfp9 }, { "as5712_54x_sfp10", as5712_54x_sfp10 }, +{ "as5712_54x_sfp11", as5712_54x_sfp11 }, { "as5712_54x_sfp12", as5712_54x_sfp12 }, +{ "as5712_54x_sfp13", as5712_54x_sfp13 }, { "as5712_54x_sfp14", as5712_54x_sfp14 }, +{ "as5712_54x_sfp15", as5712_54x_sfp15 }, { "as5712_54x_sfp16", as5712_54x_sfp16 }, +{ "as5712_54x_sfp17", as5712_54x_sfp17 }, { "as5712_54x_sfp18", as5712_54x_sfp18 }, +{ "as5712_54x_sfp19", as5712_54x_sfp19 }, { "as5712_54x_sfp20", as5712_54x_sfp20 }, +{ "as5712_54x_sfp21", as5712_54x_sfp21 }, { "as5712_54x_sfp22", as5712_54x_sfp22 }, +{ "as5712_54x_sfp23", as5712_54x_sfp23 }, { "as5712_54x_sfp24", as5712_54x_sfp24 }, +{ "as5712_54x_sfp25", as5712_54x_sfp25 }, { "as5712_54x_sfp26", as5712_54x_sfp26 }, +{ "as5712_54x_sfp27", as5712_54x_sfp27 }, { "as5712_54x_sfp28", as5712_54x_sfp28 }, +{ "as5712_54x_sfp29", as5712_54x_sfp29 }, { "as5712_54x_sfp30", as5712_54x_sfp30 }, +{ "as5712_54x_sfp31", as5712_54x_sfp31 }, { "as5712_54x_sfp32", as5712_54x_sfp32 }, +{ "as5712_54x_sfp33", as5712_54x_sfp33 }, { "as5712_54x_sfp34", as5712_54x_sfp34 }, +{ "as5712_54x_sfp35", as5712_54x_sfp35 }, { "as5712_54x_sfp36", as5712_54x_sfp36 }, +{ "as5712_54x_sfp37", as5712_54x_sfp37 }, { "as5712_54x_sfp38", as5712_54x_sfp38 }, +{ "as5712_54x_sfp39", as5712_54x_sfp39 }, { "as5712_54x_sfp40", as5712_54x_sfp40 }, +{ "as5712_54x_sfp41", as5712_54x_sfp41 }, { "as5712_54x_sfp42", as5712_54x_sfp42 }, +{ "as5712_54x_sfp43", as5712_54x_sfp43 }, { "as5712_54x_sfp44", as5712_54x_sfp44 }, +{ "as5712_54x_sfp45", as5712_54x_sfp45 }, { "as5712_54x_sfp46", as5712_54x_sfp46 }, +{ "as5712_54x_sfp47", as5712_54x_sfp47 }, { "as5712_54x_sfp48", as5712_54x_sfp48 }, +{ "as5712_54x_sfp49", as5712_54x_sfp49 }, { "as5712_54x_sfp50", as5712_54x_sfp50 }, +{ "as5712_54x_sfp51", as5712_54x_sfp51 }, { "as5712_54x_sfp52", as5712_54x_sfp52 }, +{ "as5712_54x_sfp53", as5712_54x_sfp53 }, { "as5712_54x_sfp54", as5712_54x_sfp54 }, + +{} +}; +MODULE_DEVICE_TABLE(i2c, as5712_54x_sfp_id); + +static struct i2c_driver as5712_54x_sfp_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as5712_54x_sfp", + }, + .probe = as5712_54x_sfp_probe, + .remove = as5712_54x_sfp_remove, + .id_table = as5712_54x_sfp_id, + .address_list = normal_i2c, +}; + +static int as5712_54x_sfp_read_byte(struct i2c_client *client, u8 command, u8 *data) +{ + int result = i2c_smbus_read_byte_data(client, command); + + if (unlikely(result < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result); + goto abort; + } + + *data = (u8)result; + result = 0; + +abort: + return result; +} + +#define ALWAYS_UPDATE_DEVICE 1 + +static struct as5712_54x_sfp_data *as5712_54x_sfp_update_device(struct device *dev, int update_eeprom) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (ALWAYS_UPDATE_DEVICE || time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + int i = 0, j = 0; + + data->valid = 0; + //dev_dbg(&client->dev, "Starting as5712_54x sfp status update\n"); + memset(data->status, 0, sizeof(data->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 12; j++) { + status = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2+i, 0x6+j); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + goto exit; + } + + data->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* + * Bring QSFPs out of reset, + * This is a temporary fix until the QSFP+_MOD_RST register + * can be exposed through the driver. + */ + as5712_54x_i2c_cpld_write(I2C_ADDR_CPLD3, 0x15, 0x3F); + + /* Read present status of port 49-54(QSFP port) */ + status = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x14); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + } + else { + data->status[SFP_IS_PRESENT] |= (u64)status << 48; + } + + if (update_eeprom) { + /* Read eeprom data based on port number */ + memset(data->eeprom, 0, sizeof(data->eeprom)); + + /* Check if the port is present */ + if ((data->status[SFP_IS_PRESENT] & BIT_INDEX(data->port)) == 0) { + /* read eeprom */ + for (i = 0; i < sizeof(data->eeprom); i++) { + status = as5712_54x_sfp_read_byte(client, i, data->eeprom + i); + + if (status < 0) { + dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n", + CPLD_PORT_TO_FRONT_PORT(data->port)); + goto exit; + } + } + } + } + + data->valid = 1; + data->last_updated = jiffies; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as5712_54x_sfp_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as5712_54x_sfp driver"); +MODULE_LICENSE("GPL"); + +#if 0 + int i = 0, j = 0; + + data->valid = 0; + //dev_dbg(&client->dev, "Starting as5712_54x sfp update\n"); + memset(data->status, 0, sizeof(data->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 12; j++) { + status = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2+i, 0x6+j); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + continue; + } + + data->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* Read present status of port 49-54(QSFP port) */ + status = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x14); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + } + else { + data->status[SFP_IS_PRESENT] |= (u64)status << 48; + } +#endif + +/* Reserver to prevent from CPLD port mapping is changed + */ +#if 0 +BIT_INDEX(port_present_index[data->port]) +/* The bit index of is_present field read from CPLD + * Array index 0 is for as5712_54x_sfp1, + * index 1 is for as5712_54x_sfp2, and so on. + */ +static const int port_present_index[] = { + 4, 5, 6, 7, 9, 8, 11, 10, + 0, 1, 2, 3, 12, 13, 14, 15, +16, 17, 18, 19, 28, 29, 30, 31, +20, 21, 22, 23, 24, 25, 26, 27 +}; +#endif + +#if 0 +static struct as5712_54x_sfp_data *as5712_54x_sfp_update_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + int status = -1; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->status_last_updated + HZ + HZ / 2) + || !data->status_valid) { + int status = -1; + int i = 0, j = 0; + + data->status_valid = 0; + //dev_dbg(&client->dev, "Starting as5712_54x sfp status update\n"); + memset(data->status, 0, sizeof(data->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 12; j++) { + status = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2+i, 0x6+j); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + goto exit; + } + + data->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* + * Bring QSFPs out of reset, + * This is a temporary fix until the QSFP+_MOD_RST register + * can be exposed through the driver. + */ + as5712_54x_i2c_cpld_write(I2C_ADDR_CPLD3, 0x15, 0x3F); + + /* Read present status of port 49-54(QSFP port) */ + status = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x14); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + } + else { + data->status[SFP_IS_PRESENT] |= (u64)status << 48; + } + + data->status_valid = 1; + data->status_last_updated = jiffies; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static struct as5712_54x_sfp_data *as5712_54x_sfp_update_eeprom(struct device *dev) +{ + struct as5712_54x_sfp_data *data = NULL; + + data = as5712_54x_sfp_update_status(dev); + + if (data == NULL || data->status_valid == 0) { + data->eeprom_valid = 0; + return data; + } + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->eeprom_last_updated + HZ + HZ / 2) + || !data->eeprom_valid) { + int status = -1; + int i = 0; + + /* Read eeprom data based on port number */ + memset(data->eeprom, 0, sizeof(data->eeprom)); + + /* Check if the port is present */ + if ((data->status[SFP_IS_PRESENT] & BIT_INDEX(data->port)) == 0) { + /* read eeprom */ + for (i = 0; i < sizeof(data->eeprom)/I2C_SMBUS_BLOCK_MAX; i++) { + status = as5712_54x_sfp_read_block(client, i*I2C_SMBUS_BLOCK_MAX, + data->eeprom+(i*I2C_SMBUS_BLOCK_MAX), + I2C_SMBUS_BLOCK_MAX); + if (status < 0) { + dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n", + CPLD_PORT_TO_FRONT_PORT(data->port)); + goto exit; + } + } + } + + data->eeprom_last_updated = jiffies; + data->eeprom_valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} +#endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/cpr_4011_4mxx.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/cpr_4011_4mxx.c new file mode 100755 index 000000000000..30bea914d589 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/cpr_4011_4mxx.c @@ -0,0 +1,400 @@ +/* + * An hwmon driver for the CPR-4011-4Mxx Redundant Power Module + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x3c, 0x3d, 0x3e, 0x3f, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct cpr_4011_4mxx_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[2]; /* Register value */ + u8 fan_fault; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u16 fan_speed[2]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value); +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev); + +enum cpr_4011_4mxx_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); + +static struct attribute *cpr_4011_4mxx_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + cpr_4011_4mxx_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static const struct attribute_group cpr_4011_4mxx_group = { + .attrs = cpr_4011_4mxx_attributes, +}; + +static int cpr_4011_4mxx_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct cpr_4011_4mxx_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct cpr_4011_4mxx_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpr_4011_4mxx_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int cpr_4011_4mxx_remove(struct i2c_client *client) +{ + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id cpr_4011_4mxx_id[] = { + { "cpr_4011_4mxx", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpr_4011_4mxx_id); + +static struct i2c_driver cpr_4011_4mxx_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "cpr_4011_4mxx", + }, + .probe = cpr_4011_4mxx_probe, + .remove = cpr_4011_4mxx_remove, + .id_table = cpr_4011_4mxx_id, + .address_list = normal_i2c, +}; + +static int cpr_4011_4mxx_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int cpr_4011_4mxx_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + struct reg_data_byte regs_byte[] = { {0x20, &data->vout_mode}, + {0x81, &data->fan_fault}}; + struct reg_data_word regs_word[] = { {0x88, &data->v_in}, + {0x8b, &data->v_out}, + {0x89, &data->i_in}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x97, &data->p_in}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &(data->fan_speed[0])}, + {0x91, &(data->fan_speed[1])}}; + + dev_dbg(&client->dev, "Starting cpr_4011_4mxx update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = cpr_4011_4mxx_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = cpr_4011_4mxx_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init cpr_4011_4mxx_init(void) +{ + return i2c_add_driver(&cpr_4011_4mxx_driver); +} + +static void __exit cpr_4011_4mxx_exit(void) +{ + i2c_del_driver(&cpr_4011_4mxx_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("CPR_4011_4MXX driver"); +MODULE_LICENSE("GPL"); + +module_init(cpr_4011_4mxx_init); +module_exit(cpr_4011_4mxx_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/i2c-mux-accton_as5712_54x_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/i2c-mux-accton_as5712_54x_cpld.c new file mode 100755 index 000000000000..ed097e6b30e8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/i2c-mux-accton_as5712_54x_cpld.c @@ -0,0 +1,1270 @@ +/* + * An I2C multiplexer dirver for accton as5712 CPLD + * + * Copyright (C) 2015 Accton Technology Corporation. + * Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as5712_54x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define NUM_OF_CPLD1_CHANS 0x0 +#define NUM_OF_CPLD2_CHANS 0x18 +#define NUM_OF_CPLD3_CHANS 0x1E +#define CPLD_CHANNEL_SELECT_REG 0x2 +#define CPLD_DESELECT_CHANNEL 0xFF + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_mux_type { + as5712_54x_cpld2, + as5712_54x_cpld3, + as5712_54x_cpld1 +}; + +struct as5712_54x_cpld_data { + enum cpld_mux_type type; + struct i2c_client *client; + u8 last_chan; /* last register value */ + + struct device *hwmon_dev; + struct mutex update_lock; +}; + +struct chip_desc { + u8 nchans; + u8 deselectChan; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = { + [as5712_54x_cpld1] = { + .nchans = NUM_OF_CPLD1_CHANS, + .deselectChan = CPLD_DESELECT_CHANNEL, + }, + [as5712_54x_cpld2] = { + .nchans = NUM_OF_CPLD2_CHANS, + .deselectChan = CPLD_DESELECT_CHANNEL, + }, + [as5712_54x_cpld3] = { + .nchans = NUM_OF_CPLD3_CHANS, + .deselectChan = CPLD_DESELECT_CHANNEL, + } +}; + +static const struct i2c_device_id as5712_54x_cpld_mux_id[] = { + { "as5712_54x_cpld1", as5712_54x_cpld1 }, + { "as5712_54x_cpld2", as5712_54x_cpld2 }, + { "as5712_54x_cpld3", as5712_54x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as5712_54x_cpld_mux_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index + +enum as5712_54x_cpld1_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_TXDISABLE_ATTR_ID(5), + TRANSCEIVER_TXDISABLE_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(7), + TRANSCEIVER_TXDISABLE_ATTR_ID(8), + TRANSCEIVER_TXDISABLE_ATTR_ID(9), + TRANSCEIVER_TXDISABLE_ATTR_ID(10), + TRANSCEIVER_TXDISABLE_ATTR_ID(11), + TRANSCEIVER_TXDISABLE_ATTR_ID(12), + TRANSCEIVER_TXDISABLE_ATTR_ID(13), + TRANSCEIVER_TXDISABLE_ATTR_ID(14), + TRANSCEIVER_TXDISABLE_ATTR_ID(15), + TRANSCEIVER_TXDISABLE_ATTR_ID(16), + TRANSCEIVER_TXDISABLE_ATTR_ID(17), + TRANSCEIVER_TXDISABLE_ATTR_ID(18), + TRANSCEIVER_TXDISABLE_ATTR_ID(19), + TRANSCEIVER_TXDISABLE_ATTR_ID(20), + TRANSCEIVER_TXDISABLE_ATTR_ID(21), + TRANSCEIVER_TXDISABLE_ATTR_ID(22), + TRANSCEIVER_TXDISABLE_ATTR_ID(23), + TRANSCEIVER_TXDISABLE_ATTR_ID(24), + TRANSCEIVER_TXDISABLE_ATTR_ID(25), + TRANSCEIVER_TXDISABLE_ATTR_ID(26), + TRANSCEIVER_TXDISABLE_ATTR_ID(27), + TRANSCEIVER_TXDISABLE_ATTR_ID(28), + TRANSCEIVER_TXDISABLE_ATTR_ID(29), + TRANSCEIVER_TXDISABLE_ATTR_ID(30), + TRANSCEIVER_TXDISABLE_ATTR_ID(31), + TRANSCEIVER_TXDISABLE_ATTR_ID(32), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(35), + TRANSCEIVER_TXDISABLE_ATTR_ID(36), + TRANSCEIVER_TXDISABLE_ATTR_ID(37), + TRANSCEIVER_TXDISABLE_ATTR_ID(38), + TRANSCEIVER_TXDISABLE_ATTR_ID(39), + TRANSCEIVER_TXDISABLE_ATTR_ID(40), + TRANSCEIVER_TXDISABLE_ATTR_ID(41), + TRANSCEIVER_TXDISABLE_ATTR_ID(42), + TRANSCEIVER_TXDISABLE_ATTR_ID(43), + TRANSCEIVER_TXDISABLE_ATTR_ID(44), + TRANSCEIVER_TXDISABLE_ATTR_ID(45), + TRANSCEIVER_TXDISABLE_ATTR_ID(46), + TRANSCEIVER_TXDISABLE_ATTR_ID(47), + TRANSCEIVER_TXDISABLE_ATTR_ID(48), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(5), + TRANSCEIVER_RXLOS_ATTR_ID(6), + TRANSCEIVER_RXLOS_ATTR_ID(7), + TRANSCEIVER_RXLOS_ATTR_ID(8), + TRANSCEIVER_RXLOS_ATTR_ID(9), + TRANSCEIVER_RXLOS_ATTR_ID(10), + TRANSCEIVER_RXLOS_ATTR_ID(11), + TRANSCEIVER_RXLOS_ATTR_ID(12), + TRANSCEIVER_RXLOS_ATTR_ID(13), + TRANSCEIVER_RXLOS_ATTR_ID(14), + TRANSCEIVER_RXLOS_ATTR_ID(15), + TRANSCEIVER_RXLOS_ATTR_ID(16), + TRANSCEIVER_RXLOS_ATTR_ID(17), + TRANSCEIVER_RXLOS_ATTR_ID(18), + TRANSCEIVER_RXLOS_ATTR_ID(19), + TRANSCEIVER_RXLOS_ATTR_ID(20), + TRANSCEIVER_RXLOS_ATTR_ID(21), + TRANSCEIVER_RXLOS_ATTR_ID(22), + TRANSCEIVER_RXLOS_ATTR_ID(23), + TRANSCEIVER_RXLOS_ATTR_ID(24), + TRANSCEIVER_RXLOS_ATTR_ID(25), + TRANSCEIVER_RXLOS_ATTR_ID(26), + TRANSCEIVER_RXLOS_ATTR_ID(27), + TRANSCEIVER_RXLOS_ATTR_ID(28), + TRANSCEIVER_RXLOS_ATTR_ID(29), + TRANSCEIVER_RXLOS_ATTR_ID(30), + TRANSCEIVER_RXLOS_ATTR_ID(31), + TRANSCEIVER_RXLOS_ATTR_ID(32), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(35), + TRANSCEIVER_RXLOS_ATTR_ID(36), + TRANSCEIVER_RXLOS_ATTR_ID(37), + TRANSCEIVER_RXLOS_ATTR_ID(38), + TRANSCEIVER_RXLOS_ATTR_ID(39), + TRANSCEIVER_RXLOS_ATTR_ID(40), + TRANSCEIVER_RXLOS_ATTR_ID(41), + TRANSCEIVER_RXLOS_ATTR_ID(42), + TRANSCEIVER_RXLOS_ATTR_ID(43), + TRANSCEIVER_RXLOS_ATTR_ID(44), + TRANSCEIVER_RXLOS_ATTR_ID(45), + TRANSCEIVER_RXLOS_ATTR_ID(46), + TRANSCEIVER_RXLOS_ATTR_ID(47), + TRANSCEIVER_RXLOS_ATTR_ID(48), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(5), + TRANSCEIVER_TXFAULT_ATTR_ID(6), + TRANSCEIVER_TXFAULT_ATTR_ID(7), + TRANSCEIVER_TXFAULT_ATTR_ID(8), + TRANSCEIVER_TXFAULT_ATTR_ID(9), + TRANSCEIVER_TXFAULT_ATTR_ID(10), + TRANSCEIVER_TXFAULT_ATTR_ID(11), + TRANSCEIVER_TXFAULT_ATTR_ID(12), + TRANSCEIVER_TXFAULT_ATTR_ID(13), + TRANSCEIVER_TXFAULT_ATTR_ID(14), + TRANSCEIVER_TXFAULT_ATTR_ID(15), + TRANSCEIVER_TXFAULT_ATTR_ID(16), + TRANSCEIVER_TXFAULT_ATTR_ID(17), + TRANSCEIVER_TXFAULT_ATTR_ID(18), + TRANSCEIVER_TXFAULT_ATTR_ID(19), + TRANSCEIVER_TXFAULT_ATTR_ID(20), + TRANSCEIVER_TXFAULT_ATTR_ID(21), + TRANSCEIVER_TXFAULT_ATTR_ID(22), + TRANSCEIVER_TXFAULT_ATTR_ID(23), + TRANSCEIVER_TXFAULT_ATTR_ID(24), + TRANSCEIVER_TXFAULT_ATTR_ID(25), + TRANSCEIVER_TXFAULT_ATTR_ID(26), + TRANSCEIVER_TXFAULT_ATTR_ID(27), + TRANSCEIVER_TXFAULT_ATTR_ID(28), + TRANSCEIVER_TXFAULT_ATTR_ID(29), + TRANSCEIVER_TXFAULT_ATTR_ID(30), + TRANSCEIVER_TXFAULT_ATTR_ID(31), + TRANSCEIVER_TXFAULT_ATTR_ID(32), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(35), + TRANSCEIVER_TXFAULT_ATTR_ID(36), + TRANSCEIVER_TXFAULT_ATTR_ID(37), + TRANSCEIVER_TXFAULT_ATTR_ID(38), + TRANSCEIVER_TXFAULT_ATTR_ID(39), + TRANSCEIVER_TXFAULT_ATTR_ID(40), + TRANSCEIVER_TXFAULT_ATTR_ID(41), + TRANSCEIVER_TXFAULT_ATTR_ID(42), + TRANSCEIVER_TXFAULT_ATTR_ID(43), + TRANSCEIVER_TXFAULT_ATTR_ID(44), + TRANSCEIVER_TXFAULT_ATTR_ID(45), + TRANSCEIVER_TXFAULT_ATTR_ID(46), + TRANSCEIVER_TXFAULT_ATTR_ID(47), + TRANSCEIVER_TXFAULT_ATTR_ID(48), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as5712_54x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as5712_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(35); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(36); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(37); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(38); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(39); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(40); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(41); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(42); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(43); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(44); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(45); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(46); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(47); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(48); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); + +static struct attribute *as5712_54x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5712_54x_cpld1_group = { + .attrs = as5712_54x_cpld1_attributes, +}; + +static struct attribute *as5712_54x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + DECLARE_SFP_TRANSCEIVER_ATTR(5), + DECLARE_SFP_TRANSCEIVER_ATTR(6), + DECLARE_SFP_TRANSCEIVER_ATTR(7), + DECLARE_SFP_TRANSCEIVER_ATTR(8), + DECLARE_SFP_TRANSCEIVER_ATTR(9), + DECLARE_SFP_TRANSCEIVER_ATTR(10), + DECLARE_SFP_TRANSCEIVER_ATTR(11), + DECLARE_SFP_TRANSCEIVER_ATTR(12), + DECLARE_SFP_TRANSCEIVER_ATTR(13), + DECLARE_SFP_TRANSCEIVER_ATTR(14), + DECLARE_SFP_TRANSCEIVER_ATTR(15), + DECLARE_SFP_TRANSCEIVER_ATTR(16), + DECLARE_SFP_TRANSCEIVER_ATTR(17), + DECLARE_SFP_TRANSCEIVER_ATTR(18), + DECLARE_SFP_TRANSCEIVER_ATTR(19), + DECLARE_SFP_TRANSCEIVER_ATTR(20), + DECLARE_SFP_TRANSCEIVER_ATTR(21), + DECLARE_SFP_TRANSCEIVER_ATTR(22), + DECLARE_SFP_TRANSCEIVER_ATTR(23), + DECLARE_SFP_TRANSCEIVER_ATTR(24), + NULL +}; + +static const struct attribute_group as5712_54x_cpld2_group = { + .attrs = as5712_54x_cpld2_attributes, +}; + +static struct attribute *as5712_54x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_TRANSCEIVER_PRESENT_ATTR(35), + DECLARE_TRANSCEIVER_PRESENT_ATTR(36), + DECLARE_TRANSCEIVER_PRESENT_ATTR(37), + DECLARE_TRANSCEIVER_PRESENT_ATTR(38), + DECLARE_TRANSCEIVER_PRESENT_ATTR(39), + DECLARE_TRANSCEIVER_PRESENT_ATTR(40), + DECLARE_TRANSCEIVER_PRESENT_ATTR(41), + DECLARE_TRANSCEIVER_PRESENT_ATTR(42), + DECLARE_TRANSCEIVER_PRESENT_ATTR(43), + DECLARE_TRANSCEIVER_PRESENT_ATTR(44), + DECLARE_TRANSCEIVER_PRESENT_ATTR(45), + DECLARE_TRANSCEIVER_PRESENT_ATTR(46), + DECLARE_TRANSCEIVER_PRESENT_ATTR(47), + DECLARE_TRANSCEIVER_PRESENT_ATTR(48), + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_SFP_TRANSCEIVER_ATTR(25), + DECLARE_SFP_TRANSCEIVER_ATTR(26), + DECLARE_SFP_TRANSCEIVER_ATTR(27), + DECLARE_SFP_TRANSCEIVER_ATTR(28), + DECLARE_SFP_TRANSCEIVER_ATTR(29), + DECLARE_SFP_TRANSCEIVER_ATTR(30), + DECLARE_SFP_TRANSCEIVER_ATTR(31), + DECLARE_SFP_TRANSCEIVER_ATTR(32), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(35), + DECLARE_SFP_TRANSCEIVER_ATTR(36), + DECLARE_SFP_TRANSCEIVER_ATTR(37), + DECLARE_SFP_TRANSCEIVER_ATTR(38), + DECLARE_SFP_TRANSCEIVER_ATTR(39), + DECLARE_SFP_TRANSCEIVER_ATTR(40), + DECLARE_SFP_TRANSCEIVER_ATTR(41), + DECLARE_SFP_TRANSCEIVER_ATTR(42), + DECLARE_SFP_TRANSCEIVER_ATTR(43), + DECLARE_SFP_TRANSCEIVER_ATTR(44), + DECLARE_SFP_TRANSCEIVER_ATTR(45), + DECLARE_SFP_TRANSCEIVER_ATTR(46), + DECLARE_SFP_TRANSCEIVER_ATTR(47), + DECLARE_SFP_TRANSCEIVER_ATTR(48), + NULL +}; + +static const struct attribute_group as5712_54x_cpld3_group = { + .attrs = as5712_54x_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status, num_regs = 0; + u8 values[4] = {0}; + u8 regs[] = {0x6, 0x7, 0x8, 0x14}; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + + mutex_lock(&data->update_lock); + + num_regs = (data->type == as5712_54x_cpld2) ? 3 : 4; + + for (i = 0; i < num_regs; i++) { + status = as5712_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 54 in order */ + if (data->type == as5712_54x_cpld2) { + status = sprintf(buf, "%.2x %.2x %.2x\n", + values[0], values[1], values[2]); + } + else { /* as5712_54x_cpld3 */ + values[3] &= 0x3F; + status = sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + } + + return status; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[3] = {0}; + u8 regs[] = {0xF, 0x10, 0x11}; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as5712_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 24 in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", values[0], values[1], values[2]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x8; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33 ... MODULE_PRESENT_40: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_PRESENT_33); + break; + case MODULE_PRESENT_41 ... MODULE_PRESENT_48: + reg = 0x8; + mask = 0x1 << (attr->index - MODULE_PRESENT_41); + break; + case MODULE_PRESENT_49: + reg = 0x14; + mask = 0x1; + break; + case MODULE_PRESENT_50: + reg = 0x14; + mask = 0x4; + break; + case MODULE_PRESENT_51: + reg = 0x14; + mask = 0x10; + break; + case MODULE_PRESENT_52: + reg = 0x14; + mask = 0x2; + break; + case MODULE_PRESENT_53: + reg = 0x14; + mask = 0x8; + break; + case MODULE_PRESENT_54: + reg = 0x14; + mask = 0x20; + break; + case MODULE_TXFAULT_1 ... MODULE_TXFAULT_8: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_TXFAULT_1); + break; + case MODULE_TXFAULT_9 ... MODULE_TXFAULT_16: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_TXFAULT_9); + break; + case MODULE_TXFAULT_17 ... MODULE_TXFAULT_24: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_TXFAULT_17); + break; + case MODULE_TXFAULT_25 ... MODULE_TXFAULT_32: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_TXFAULT_25); + break; + case MODULE_TXFAULT_33 ... MODULE_TXFAULT_40: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_TXFAULT_33); + break; + case MODULE_TXFAULT_41 ... MODULE_TXFAULT_48: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_TXFAULT_41); + break; + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + case MODULE_RXLOS_1 ... MODULE_RXLOS_8: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_RXLOS_1); + break; + case MODULE_RXLOS_9 ... MODULE_RXLOS_16: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_RXLOS_9); + break; + case MODULE_RXLOS_17 ... MODULE_RXLOS_24: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_RXLOS_17); + break; + case MODULE_RXLOS_25 ... MODULE_RXLOS_32: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_RXLOS_25); + break; + case MODULE_RXLOS_33 ... MODULE_RXLOS_40: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_RXLOS_33); + break; + case MODULE_RXLOS_41 ... MODULE_RXLOS_48: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_RXLOS_41); + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_54) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as5712_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5712_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5712_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + int status; + u32 addr, val; + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as5712_54x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int as5712_54x_cpld_mux_reg_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 val) +{ + unsigned long orig_jiffies; + unsigned short flags; + union i2c_smbus_data data; + int try; + s32 res = -EIO; + + data.byte = val; + flags = client->flags; + flags &= I2C_M_TEN | I2C_CLIENT_PEC; + + if (adap->algo->smbus_xfer) { + /* Retry automatically on arbitration loss */ + orig_jiffies = jiffies; + for (res = 0, try = 0; try <= adap->retries; try++) { + res = adap->algo->smbus_xfer(adap, client->addr, flags, + I2C_SMBUS_WRITE, CPLD_CHANNEL_SELECT_REG, + I2C_SMBUS_BYTE_DATA, &data); + if (res != -EAGAIN) + break; + if (time_after(jiffies, + orig_jiffies + adap->timeout)) + break; + } + } + + return res; +} + +static int as5712_54x_cpld_mux_select_chan(struct i2c_mux_core *muxc, + u32 chan) +{ + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + u8 regval; + int ret = 0; + + regval = chan; + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) { + ret = as5712_54x_cpld_mux_reg_write(muxc->parent, client, regval); + data->last_chan = regval; + } + + return ret; +} + +static int as5712_54x_cpld_mux_deselect_mux(struct i2c_mux_core *muxc, + u32 chan) +{ + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + + /* Deselect active channel */ + data->last_chan = chips[data->type].deselectChan; + + return as5712_54x_cpld_mux_reg_write(muxc->parent, client, data->last_chan); +} + +static void as5712_54x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as5712_54x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as5712_54x_cpld_mux_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + int num, force, class; + struct i2c_mux_core *muxc; + struct as5712_54x_cpld_data *data; + int ret = 0; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + return -ENODEV; + + muxc = i2c_mux_alloc(adap, &client->dev, + chips[id->driver_data].nchans, sizeof(*data), 0, + as5712_54x_cpld_mux_select_chan, as5712_54x_cpld_mux_deselect_mux); + if (!muxc) + return -ENOMEM; + + i2c_set_clientdata(client, muxc); + data = i2c_mux_priv(muxc); + data->client = client; + data->type = id->driver_data; + data->last_chan = chips[data->type].deselectChan; /* force the first selection */ + mutex_init(&data->update_lock); + + /* Now create an adapter for each channel */ + for (num = 0; num < chips[data->type].nchans; num++) { + force = 0; /* dynamic adap number */ + class = 0; /* no class by default */ + + ret = i2c_mux_add_adapter(muxc, force, num, class); + + if (ret) { + dev_err(&client->dev, + "failed to register multiplexed adapter" + " %d as bus %d\n", num, force); + goto add_mux_failed; + } + } + + /* Register sysfs hooks */ + switch (data->type) { + case as5712_54x_cpld1: + group = &as5712_54x_cpld1_group; + break; + case as5712_54x_cpld2: + group = &as5712_54x_cpld2_group; + break; + case as5712_54x_cpld3: + group = &as5712_54x_cpld3_group; + + /* Bring QSFPs out of reset */ + as5712_54x_cpld_write_internal(client, 0x15, 0x3F); + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto add_mux_failed; + } + } + + if (chips[data->type].nchans) { + dev_info(&client->dev, + "registered %d multiplexed busses for I2C %s\n", + num, client->name); + } + else { + dev_info(&client->dev, + "device %s registered\n", client->name); + } + + as5712_54x_cpld_add_client(client); + + return 0; + +add_mux_failed: + i2c_mux_del_adapters(muxc); + return ret; +} + +static int as5712_54x_cpld_mux_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + const struct attribute_group *group = NULL; + + as5712_54x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as5712_54x_cpld1: + group = &as5712_54x_cpld1_group; + break; + case as5712_54x_cpld2: + group = &as5712_54x_cpld2_group; + break; + case as5712_54x_cpld3: + group = &as5712_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + i2c_mux_del_adapters(muxc); + + return 0; +} + +static int as5712_54x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as5712_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as5712_54x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as5712_54x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5712_54x_cpld_read); + +int as5712_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as5712_54x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5712_54x_cpld_write); + +static struct i2c_driver as5712_54x_cpld_mux_driver = { + .driver = { + .name = "as5712_54x_cpld", + .owner = THIS_MODULE, + }, + .probe = as5712_54x_cpld_mux_probe, + .remove = as5712_54x_cpld_mux_remove, + .id_table = as5712_54x_cpld_mux_id, +}; + +static int __init as5712_54x_cpld_mux_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as5712_54x_cpld_mux_driver); +} + +static void __exit as5712_54x_cpld_mux_exit(void) +{ + i2c_del_driver(&as5712_54x_cpld_mux_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton as5712-54x CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as5712_54x_cpld_mux_init); +module_exit(as5712_54x_cpld_mux_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/leds-accton_as5712_54x.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/leds-accton_as5712_54x.c new file mode 100755 index 000000000000..cdea927368ae --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/leds-accton_as5712_54x.c @@ -0,0 +1,594 @@ +/* + * A LED driver for the accton_as5712_54x_led + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include + +extern int as5712_54x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as5712_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "as5712_54x_led" + +struct accton_as5712_54x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[4]; /* Register value, 0 = LOC/DIAG/FAN LED + 1 = PSU1/PSU2 LED + 2 = FAN1-4 LED + 3 = FAN5-6 LED */ +}; + +static struct accton_as5712_54x_led_data *ledctl = NULL; + +/* LED related data + */ +#define LED_TYPE_PSU1_REG_MASK 0x03 +#define LED_MODE_PSU1_GREEN_MASK 0x02 +#define LED_MODE_PSU1_AMBER_MASK 0x01 +#define LED_MODE_PSU1_OFF_MASK 0x03 +#define LED_MODE_PSU1_AUTO_MASK 0x00 + +#define LED_TYPE_PSU2_REG_MASK 0x0C +#define LED_MODE_PSU2_GREEN_MASK 0x08 +#define LED_MODE_PSU2_AMBER_MASK 0x04 +#define LED_MODE_PSU2_OFF_MASK 0x0C +#define LED_MODE_PSU2_AUTO_MASK 0x00 + +#define LED_TYPE_DIAG_REG_MASK 0x0C +#define LED_MODE_DIAG_GREEN_MASK 0x08 +#define LED_MODE_DIAG_AMBER_MASK 0x04 +#define LED_MODE_DIAG_OFF_MASK 0x0C + +#define LED_TYPE_FAN_REG_MASK 0x03 +#define LED_MODE_FAN_GREEN_MASK 0x02 +#define LED_MODE_FAN_AMBER_MASK 0x01 +#define LED_MODE_FAN_OFF_MASK 0x03 +#define LED_MODE_FAN_AUTO_MASK 0x00 + +#define LED_TYPE_FAN1_REG_MASK 0x03 +#define LED_TYPE_FAN2_REG_MASK 0x0C +#define LED_TYPE_FAN3_REG_MASK 0x30 +#define LED_TYPE_FAN4_REG_MASK 0xC0 +#define LED_TYPE_FAN5_REG_MASK 0x03 +#define LED_TYPE_FAN6_REG_MASK 0x0C + +#define LED_MODE_FANX_GREEN_MASK 0x01 +#define LED_MODE_FANX_RED_MASK 0x02 +#define LED_MODE_FANX_OFF_MASK 0x00 + +#define LED_TYPE_LOC_REG_MASK 0x30 +#define LED_MODE_LOC_ON_MASK 0x00 +#define LED_MODE_LOC_OFF_MASK 0x10 +#define LED_MODE_LOC_BLINK_MASK 0x20 + +static const u8 led_reg[] = { + 0xA, /* LOC/DIAG/FAN LED*/ + 0xB, /* PSU1/PSU2 LED */ + 0x16, /* FAN1-4 LED */ + 0x17, /* FAN4-6 LED */ +}; + +enum led_type { + LED_TYPE_PSU1, + LED_TYPE_PSU2, + LED_TYPE_DIAG, + LED_TYPE_FAN, + LED_TYPE_FAN1, + LED_TYPE_FAN2, + LED_TYPE_FAN3, + LED_TYPE_FAN4, + LED_TYPE_FAN5, + LED_TYPE_LOC +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_AMBER, + LED_MODE_RED, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_RED_BLINK, + LED_MODE_AUTO, +}; + +struct led_type_mode { + enum led_type type; + int type_mask; + enum led_light_mode mode; + int mode_mask; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU1_GREEN_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU1_AMBER_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU1_AUTO_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_OFF, LED_MODE_PSU1_OFF_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU2_GREEN_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU2_AMBER_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU2_AUTO_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_OFF, LED_MODE_PSU2_OFF_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_GREEN, LED_MODE_FAN_GREEN_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AMBER, LED_MODE_FAN_AMBER_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AUTO, LED_MODE_FAN_AUTO_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_OFF, LED_MODE_FAN_OFF_MASK}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 2}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 4}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 6}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_GREEN, LED_MODE_DIAG_GREEN_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_AMBER, LED_MODE_DIAG_AMBER_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_OFF, LED_MODE_DIAG_OFF_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER, LED_MODE_LOC_ON_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_OFF, LED_MODE_LOC_OFF_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER_BLINK, LED_MODE_LOC_BLINK_MASK} +}; + + +struct fanx_info_s { + u8 cname; /* device name */ + enum led_type type; + u8 reg_id; /* map to led_reg & reg_val */ +}; + +static struct fanx_info_s fanx_info[] = { + {'1', LED_TYPE_FAN1, 2}, + {'2', LED_TYPE_FAN2, 2}, + {'3', LED_TYPE_FAN3, 2}, + {'4', LED_TYPE_FAN4, 2}, + {'5', LED_TYPE_FAN5, 3} +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_mask) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + reg_val = led_type_mode_data[i].mode_mask | + (reg_val & (~led_type_mode_data[i].type_mask)); + } + + return reg_val; +} + +static int accton_as5712_54x_led_read_value(u8 reg) +{ + return as5712_54x_cpld_read(0x60, reg); +} + +static int accton_as5712_54x_led_write_value(u8 reg, u8 value) +{ + return as5712_54x_cpld_write(0x60, reg, value); +} + +static void accton_as5712_54x_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as5712_54x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as5712_54x_led_read_value(led_reg[i]); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as5712_54x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + + reg_val = accton_as5712_54x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as5712_54x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as5712_54x_led_psu_1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5712_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1); +} + +static enum led_brightness accton_as5712_54x_led_psu_1_get(struct led_classdev *cdev) +{ + accton_as5712_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void accton_as5712_54x_led_psu_2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5712_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2); +} + +static enum led_brightness accton_as5712_54x_led_psu_2_get(struct led_classdev *cdev) +{ + accton_as5712_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static void accton_as5712_54x_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5712_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_FAN); +} + +static enum led_brightness accton_as5712_54x_led_fan_get(struct led_classdev *cdev) +{ + accton_as5712_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + + +static void accton_as5712_54x_led_fanx_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (led_cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as5712_54x_led_set(led_cdev, led_light_mode, led_reg[reg_id], led_type1); + return; + } + } +} + + +static enum led_brightness accton_as5712_54x_led_fanx_get(struct led_classdev *cdev) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as5712_54x_led_update(); + return led_reg_val_to_light_mode(led_type1, ledctl->reg_val[reg_id]); + } + } + + + return led_reg_val_to_light_mode(LED_TYPE_FAN1, ledctl->reg_val[2]); +} + + +static void accton_as5712_54x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5712_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} + +static enum led_brightness accton_as5712_54x_led_diag_get(struct led_classdev *cdev) +{ + accton_as5712_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as5712_54x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5712_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static enum led_brightness accton_as5712_54x_led_loc_get(struct led_classdev *cdev) +{ + accton_as5712_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static struct led_classdev accton_as5712_54x_leds[] = { + [LED_TYPE_PSU1] = { + .name = "accton_as5712_54x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_psu_1_set, + .brightness_get = accton_as5712_54x_led_psu_1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as5712_54x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_psu_2_set, + .brightness_get = accton_as5712_54x_led_psu_2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "accton_as5712_54x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_fan_set, + .brightness_get = accton_as5712_54x_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN1] = { + .name = "accton_as5712_54x_led::fan1", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_fanx_set, + .brightness_get = accton_as5712_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN2] = { + .name = "accton_as5712_54x_led::fan2", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_fanx_set, + .brightness_get = accton_as5712_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN3] = { + .name = "accton_as5712_54x_led::fan3", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_fanx_set, + .brightness_get = accton_as5712_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN4] = { + .name = "accton_as5712_54x_led::fan4", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_fanx_set, + .brightness_get = accton_as5712_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN5] = { + .name = "accton_as5712_54x_led::fan5", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_fanx_set, + .brightness_get = accton_as5712_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_DIAG] = { + .name = "accton_as5712_54x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_diag_set, + .brightness_get = accton_as5712_54x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_LOC] = { + .name = "accton_as5712_54x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_loc_set, + .brightness_get = accton_as5712_54x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as5712_54x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as5712_54x_leds); i++) { + led_classdev_suspend(&accton_as5712_54x_leds[i]); + } + + return 0; +} + +static int accton_as5712_54x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as5712_54x_leds); i++) { + led_classdev_resume(&accton_as5712_54x_leds[i]); + } + + return 0; +} + +static int accton_as5712_54x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as5712_54x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as5712_54x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as5712_54x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as5712_54x_leds[i]); + } + } + + return ret; +} + +static int accton_as5712_54x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as5712_54x_leds); i++) { + led_classdev_unregister(&accton_as5712_54x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as5712_54x_led_driver = { + .probe = accton_as5712_54x_led_probe, + .remove = accton_as5712_54x_led_remove, + .suspend = accton_as5712_54x_led_suspend, + .resume = accton_as5712_54x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as5712_54x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as5712_54x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as5712_54x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as5712_54x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as5712_54x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as5712_54x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as5712_54x_led_driver); + kfree(ledctl); +} + +module_init(accton_as5712_54x_led_init); +module_exit(accton_as5712_54x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as5712_54x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/ym2651y.c new file mode 100755 index 000000000000..519530387e29 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/ym2651y.c @@ -0,0 +1,683 @@ +/* + * An hwmon driver for the 3Y Power YM-2651Y Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +enum chips { + YM2651, + YM2401, +}; + +/* Each client has this additional data + */ +struct ym2651y_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 chip; /* chip id */ + u8 capability; /* Register value */ + u16 status_word; /* Register value */ + u8 fan_fault; /* Register value */ + u8 over_temp; /* Register value */ + u16 v_out; /* Register value */ + u16 i_out; /* Register value */ + u16 p_out; /* Register value */ + u8 vout_mode; /* Register value */ + u16 temp; /* Register value */ + u16 fan_speed; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u8 fan_dir[5]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[16]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u16 mfr_vin_min; /* Register value */ + u16 mfr_vin_max; /* Register value */ + u16 mfr_iin_max; /* Register value */ + u16 mfr_iout_max; /* Register value */ + u16 mfr_pin_max; /* Register value */ + u16 mfr_pout_max; /* Register value */ + u16 mfr_vout_min; /* Register value */ + u16 mfr_vout_max; /* Register value */ +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static struct ym2651y_data *ym2651y_update_device(struct device *dev); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value); + +enum ym2651y_sysfs_attributes { + PSU_POWER_ON = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD, + PSU_FAN1_FAULT, + PSU_FAN_DIRECTION, + PSU_OVER_TEMP, + PSU_V_OUT, + PSU_I_OUT, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_SPEED, + PSU_FAN1_DUTY_CYCLE, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_VIN_MIN, + PSU_MFR_VIN_MAX, + PSU_MFR_VOUT_MIN, + PSU_MFR_VOUT_MAX, + PSU_MFR_IIN_MAX, + PSU_MFR_IOUT_MAX, + PSU_MFR_PIN_MAX, + PSU_MFR_POUT_MAX +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision,S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); + +static struct attribute *ym2651y_attributes[] = { + &sensor_dev_attr_psu_power_on.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_over_temp.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, + NULL +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + if (!data->valid) { + return 0; + } + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u16 status = 0; + + if (!data->valid) { + return 0; + } + + switch (attr->index) { + case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */ + status = (data->status_word & 0x40) ? 0 : 1; + break; + case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */ + status = (data->status_word & 0x4) >> 2; + break; + case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */ + status = (data->status_word & 0x800) ? 0 : 1; + break; + } + + return sprintf(buf, "%d\n", status); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + if (!data->valid) { + return 0; + } + + switch (attr->index) { + case PSU_V_OUT: + value = data->v_out; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp; + break; + case PSU_FAN1_SPEED: + value = data->fan_speed; + multiplier = 1; + break; + case PSU_FAN1_DUTY_CYCLE: + value = data->fan_duty_cycle[0]; + multiplier = 1; + break; + case PSU_MFR_VIN_MIN: + value = data->mfr_vin_min; + break; + case PSU_MFR_VIN_MAX: + value = data->mfr_vin_max; + break; + case PSU_MFR_VOUT_MIN: + value = data->mfr_vout_min; + break; + case PSU_MFR_VOUT_MAX: + value = data->mfr_vout_max; + break; + case PSU_MFR_PIN_MAX: + value = data->mfr_pin_max; + break; + case PSU_MFR_POUT_MAX: + value = data->mfr_pout_max; + break; + case PSU_MFR_IOUT_MAX: + value = data->mfr_iout_max; + break; + case PSU_MFR_IIN_MAX: + value = data->mfr_iin_max; + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u8 shift; + + if (!data->valid) { + return 0; + } + + shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct ym2651y_data *data = ym2651y_update_device(dev); + + if (!data->valid) { + return 0; + } + + return sprintf(buf, "%d\n", data->over_temp >> 7); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) { + return 0; + } + + switch (attr->index) { + case PSU_FAN_DIRECTION: /* psu_fan_dir */ + ptr = data->fan_dir + 1; /* Skip the first byte since it is the length of string. */ + break; + case PSU_MFR_ID: /* psu_mfr_id */ + ptr = data->mfr_id + 1; /* The first byte is the count byte of string. */; + break; + case PSU_MFR_MODEL: /* psu_mfr_model */ + ptr = data->mfr_model + 1; /* The first byte is the count byte of string. */ + break; + case PSU_MFR_REVISION: /* psu_mfr_revision */ + ptr = data->mfr_revsion + 1; /* The first byte is the count byte of string. */ + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + +static ssize_t show_vout_by_mode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct ym2651y_data *data = ym2651y_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + if (!data->valid) { + return 0; + } + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + if (data->chip == YM2401) { + return show_vout_by_mode(dev, da, buf); + } + + return show_linear(dev, da, buf); +} + +static const struct attribute_group ym2651y_group = { + .attrs = ym2651y_attributes, +}; + +static int ym2651y_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct ym2651y_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->chip = dev_id->driver_data; + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &ym2651y_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int ym2651y_remove(struct i2c_client *client) +{ + struct ym2651y_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id ym2651y_id[] = { + { "ym2651", YM2651 }, + { "ym2401", YM2401 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ym2651y_id); + +static struct i2c_driver ym2651y_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ym2651", + }, + .probe = ym2651y_probe, + .remove = ym2651y_remove, + .id_table = ym2651y_id, + .address_list = normal_i2c, +}; + +static int ym2651y_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int ym2651y_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct ym2651y_data *ym2651y_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status, length; + u8 command, buf; + struct reg_data_byte regs_byte[] = { {0x19, &data->capability}, + {0x20, &data->vout_mode}, + {0x7d, &data->over_temp}, + {0x81, &data->fan_fault}, + {0x98, &data->pmbus_revision}}; + struct reg_data_word regs_word[] = { {0x79, &data->status_word}, + {0x8b, &data->v_out}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x8d, &data->temp}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &data->fan_speed}, + {0xa0, &data->mfr_vin_min}, + {0xa1, &data->mfr_vin_max}, + {0xa2, &data->mfr_iin_max}, + {0xa3, &data->mfr_pin_max}, + {0xa4, &data->mfr_vout_min}, + {0xa5, &data->mfr_vout_max}, + {0xa6, &data->mfr_iout_max}, + {0xa7, &data->mfr_pout_max}}; + + dev_dbg(&client->dev, "Starting ym2651 update\n"); + data->valid = 0; + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = ym2651y_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + goto exit; + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = ym2651y_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + goto exit; + } + else { + *(regs_word[i].value) = status; + } + } + + /* Read fan_direction */ + command = 0xC3; + status = ym2651y_read_block(client, command, data->fan_dir, + ARRAY_SIZE(data->fan_dir)-1); + data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + /* Read mfr_id */ + command = 0x99; + status = ym2651y_read_block(client, command, data->mfr_id, + ARRAY_SIZE(data->mfr_id)-1); + data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + /* Read mfr_model */ + command = 0x9a; + length = 1; + + /* Read first byte to determine the length of data */ + status = ym2651y_read_block(client, command, &buf, length); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + status = ym2651y_read_block(client, command, data->mfr_model, buf+1); + data->mfr_model[buf+1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + /* Read mfr_revsion */ + command = 0x9b; + status = ym2651y_read_block(client, command, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)-1); + data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init ym2651y_init(void) +{ + return i2c_add_driver(&ym2651y_driver); +} + +static void __exit ym2651y_exit(void) +{ + i2c_del_driver(&ym2651y_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("3Y Power YM-2651Y driver"); +MODULE_LICENSE("GPL"); + +module_init(ym2651y_init); +module_exit(ym2651y_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/service/as5712-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/service/as5712-platform-monitor.service new file mode 100755 index 000000000000..da5d283a6d61 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/service/as5712-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS5712-54X Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as5712_util.py install +ExecStart=/usr/local/bin/accton_as5712_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/setup.py new file mode 100755 index 000000000000..f4cb5f960a4d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as5712_54x', + version='1.0', + description='Module to initialize Accton AS5712-54X platforms', + + packages=['as5712_54x'], + package_dir={'as5712_54x': 'as5712-54x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/README new file mode 100755 index 000000000000..44e03cab5f52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program is free software: you can redistribute it and/or modify +It under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as5712_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as5712-fan-psu-cpld.patch + for as5712's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS5712-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as5712 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS5712-54X.patch" from patch/installer. + - Change setting for AS5712-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS5712-54X.patch" + !!NOTICE, patching onie_installer-accton-AS5712-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5712-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as5712-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as5712_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS5712-54X.patch. + It's done by patching onie_installer-accton-AS5712-54X.patch at build-image. + Run "accton_as5712_util.py install" to install drivers. + +To initialize the system, run "accton_as5712_util.py install". +To clean up the drivers & devices, run "accton_as5712_util.py clean". +To dump information of sensors, run "accton_as5712_util.py show". +To dump SFP EEPROM, run "accton_as5712_util.py sff". +To set fan speed, run "accton_as5712_util.py set fan". +To enable/disable SFP emission, run "accton_as5712_util.py set sfp". +To set system LEDs' color, run "accton_as5712_util.py set led" +For more information, run "accton_as5712_util.py --help". + +==================================================================== +Besides applying accton_as5712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_monitor.py new file mode 100755 index 000000000000..84ab2d83bab4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_monitor.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + from as5712_54x.fanutil import FanUtil + from as5712_54x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as5712_monitor' + +global log_file +global log_level + +# Make a class we can use to capture stdout and sterr in the log +class accton_as5712_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + FAN_LEV1_UP_TEMP = 57500 # temperature + FAN_LEV1_DOWN_TEMP = 0 # unused + FAN_LEV1_SPEED_PERC = 100 # percentage*/ + + FAN_LEV2_UP_TEMP = 53000 + FAN_LEV2_DOWN_TEMP = 52700 + FAN_LEV2_SPEED_PERC = 80 + + FAN_LEV3_UP_TEMP = 49500 + FAN_LEV3_DOWN_TEMP = 47700 + FAN_LEV3_SPEED_PERC = 65 + + FAN_LEV4_UP_TEMP = 0 # unused + FAN_LEV4_DOWN_TEMP = 42700 + FAN_LEV4_SPEED_PERC = 40 + + + thermal = ThermalUtil() + fan = FanUtil() + + temp1 = thermal.get_thermal_1_val() + if temp1 is None: + return False + + temp2 = thermal.get_thermal_2_val() + if temp2 is None: + return False + + new_temp = (temp1 + temp2) / 2 + + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_stat = fan.get_fan_status(x) + if fan_stat is None: + return False + if fan_stat is False: + self._new_perc = FAN_LEV1_SPEED_PERC + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', self._new_perc, x) + break + logging.debug('INFO. fan_stat is True (fan_num:%d)', x) + + if fan_stat is not None and fan_stat is not False: + diff = new_temp - self._ori_temp + if diff == 0: + logging.debug('INFO. RETURN. THERMAL temp not changed. %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + return True + else: + if diff >= 0: + is_up = True + logging.debug('INFO. THERMAL temp UP %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + else: + is_up = False + logging.debug('INFO. THERMAL temp DOWN %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + + if is_up is True: + if new_temp >= FAN_LEV1_UP_TEMP: + self._new_perc = FAN_LEV1_SPEED_PERC + elif new_temp >= FAN_LEV2_UP_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + elif new_temp >= FAN_LEV3_UP_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + else: + self._new_perc = FAN_LEV4_SPEED_PERC + logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + else: + if new_temp <= FAN_LEV4_DOWN_TEMP: + self._new_perc = FAN_LEV4_SPEED_PERC + elif new_temp <= FAN_LEV3_DOWN_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + elif new_temp <= FAN_LEV2_DOWN_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + else: + self._new_perc = FAN_LEV1_SPEED_PERC + logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + + if self._ori_perc == self._new_perc: + logging.debug('INFO. RETURN. FAN speed not changed. %d / %d (new_perc / ori_perc)', self._new_perc, self._ori_perc) + return True + + set_stat = fan.set_fan_duty_cycle(fan.get_idx_fan_start(), self._new_perc) + if set_stat is True: + logging.debug('INFO: PASS. set_fan_duty_cycle (%d)', self._new_perc) + else: + logging.debug('INFO: FAIL. set_fan_duty_cycle (%d)', self._new_perc) + + logging.debug('INFO: GET. ori_perc is %d. ori_temp is %d', self._ori_perc, self._ori_temp) + self._ori_perc = self._new_perc + self._ori_temp = new_temp + logging.debug('INFO: UPDATE. ori_perc to %d. ori_temp to %d', self._ori_perc, self._ori_temp) + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + monitor = accton_as5712_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(1) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_util.py b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_util.py new file mode 100755 index 000000000000..791409913448 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_util.py @@ -0,0 +1,686 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +import pickle +from collections import namedtuple + +PROJECT_NAME = 'as5712_54x' +version = '0.2.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':54} + + +led_prefix ='/sys/devices/platform/as5712_54x_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as5712_54x_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan1_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan2_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan3_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan4_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan5_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'thermal': ['61-0048','62-0049', '63-004a'] , + 'psu': ['57-0050','58-0053'], + 'sfp': ['-0050']} +i2c_nodes = { + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable']} + +QSFP_START = 48 +I2C_BUS_ORDER = -1 + +sfp_map = [2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 52, 54, 51, 53, 55] + +port_cpld_path = [ "/sys/bus/i2c/devices/0-0061/" + ,'/sys/bus/i2c/devices/0-0062/'] + +mknod =[ +'echo as5712_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as5712_54x_cpld2 0x61 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as5712_54x_cpld3 0x62 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', + +# PSU-1 +'echo as5712_54x_psu1 0x38 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-57/new_device', +'echo as5712_54x_psu1 0x50 > /sys/bus/i2c/devices/i2c-57/new_device', + +# PSU-2 +'echo as5712_54x_psu2 0x3b > /sys/bus/i2c/devices/i2c-58/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-58/new_device', +'echo as5712_54x_psu2 0x53 > /sys/bus/i2c/devices/i2c-58/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-61/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-62/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-63/new_device', + +#EERPOM +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', +] + +mknod2 =[ +'echo as5712_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as5712_54x_cpld2 0x61 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as5712_54x_cpld3 0x62 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', + +# PSU-1 +'echo as5712_54x_psu1 0x38 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-57/new_device', +'echo as5712_54x_psu1 0x50 > /sys/bus/i2c/devices/i2c-57/new_device', + +# PSU-2 +'echo as5712_54x_psu2 0x3b > /sys/bus/i2c/devices/i2c-58/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-58/new_device', +'echo as5712_54x_psu2 0x53 > /sys/bus/i2c/devices/i2c-58/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-61/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-62/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-63/new_device', + +#EERPOM +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', +] + +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-48 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + + + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x', +'modprobe optoe', +'modprobe i2c-mux-accton_as5712_54x_cpld', +'modprobe cpr_4011_4mxx', +'modprobe ym2651y', +'modprobe accton_as5712_54x_fan', +'modprobe leds-accton_as5712_54x', +'modprobe accton_as5712_54x_psu'] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x70 is exist @ i2c-0 + tmp = "echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x70 > /sys/bus/i2c/devices/i2c-1/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def update_i2c_order(): + global I2C_BUS_ORDER + + order = i2c_order_check() + pickle.dump(order, open("/tmp/accton_util.p", "wb")) # save it + I2C_BUS_ORDER = order + print "[%s]Detected I2C_BUS_ORDER:%d" % (os.path.basename(__file__), I2C_BUS_ORDER) + +def get_i2c_order(): + global I2C_BUS_ORDER + if I2C_BUS_ORDER < 0: + if os.path.exists("/tmp/accton_util.p"): + I2C_BUS_ORDER = pickle.load(open("/tmp/accton_util.p", "rb")) + else: + update_i2c_order() + +def device_install(): + global FORCE + global I2C_BUS_ORDER + + update_i2c_order() + order = I2C_BUS_ORDER + # if 0x76 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + if i < QSFP_START: + status, output =log_os_system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + else: + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + global I2C_BUS_ORDER + + get_i2c_order() + order = I2C_BUS_ORDER + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if order == 0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_inserted() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + + +def get_cpld_path(index): + global I2C_BUS_ORDER + + if I2C_BUS_ORDER < 0: + get_i2c_order() + + if I2C_BUS_ORDER !=0 : + return port_cpld_path[index].replace("0-", "1-") + else: + return port_cpld_path[index] + +def cpld_path_of_port(port_index): + if port_index < 1 and port_index > DEVICE_NO['sfp']: + return None + if port_index < 25: + return get_cpld_path(0) + else: + return get_cpld_path(1) + +def get_path_sfp_tx_dis(port_index): + cpld_p = cpld_path_of_port(port_index) + if cpld_p == None: + return False, '' + else: + dev = cpld_p+"module_tx_disable_"+str(port_index) + return True, dev + +def get_path_sfp_presence(port_index): + cpld_p = cpld_path_of_port(port_index) + if cpld_p == None: + return False, '' + else: + dev = cpld_p+"module_present_"+str(port_index) + return True, dev + + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + #if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + #There no tx_disable for QSFP port + if int(args[1]) > QSFP_START or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + port_index = int(args[1]) + ret, dev = get_path_sfp_tx_dis(port_index) + if ret == False: + return False + else: + ret, log = log_os_system("echo "+args[2]+" >"+ dev, 1) + return ret + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def print_1_device_traversal(i, j, k): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + return func+"="+log+" " + else: + return func+"="+"X"+" " + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + if i == 'sfp': + port_index = int(filter(str.isdigit, j)) + for k in (ALL_DEVICE[i][j]): + if k.find('tx_disable')!= -1: + ret, k = get_path_sfp_tx_dis(port_index) + if ret == False: + continue + log = print_1_device_traversal(i, j, k) + print log, + if k.find('present')!= -1: + ret, k = get_path_sfp_presence(port_index) + if ret == False: + continue + log = print_1_device_traversal(i, j, k) + print log, + + else: + for k in (ALL_DEVICE[i][j]): + log = print_1_device_traversal(i, j, k) + print log, + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/Makefile new file mode 100644 index 000000000000..697dcff656c3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/Makefile @@ -0,0 +1,4 @@ +obj-m:=accton_i2c_cpld.o x86-64-accton-as5812-54t-fan.o \ + x86-64-accton-as5812-54t-leds.o x86-64-accton-as5812-54t-psu.o \ + x86-64-accton-as5812-54t-sfp.o ym2651y.o + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/accton_i2c_cpld.c new file mode 100644 index 000000000000..c01d6bcca228 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/accton_i2c_cpld.c @@ -0,0 +1,330 @@ +/* + * A hwmon driver for the accton_i2c_cpld + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for accton_i2c_cpld + */ +static const unsigned short normal_i2c[] = { 0x31, 0x35, 0x60, 0x61, 0x62, 0x64, I2C_CLIENT_END }; + +static ssize_t show_cpld_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +static struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, NULL); + +static void accton_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void accton_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int accton_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + status = sysfs_create_file(&client->dev.kobj, &ver.attr); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + accton_i2c_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int accton_i2c_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_file(&client->dev.kobj, &ver.attr); + accton_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id accton_i2c_cpld_id[] = { + { "accton_i2c_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id); + +static struct i2c_driver accton_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "accton_i2c_cpld", + }, + .probe = accton_i2c_cpld_probe, + .remove = accton_i2c_cpld_remove, + .id_table = accton_i2c_cpld_id, + .address_list = normal_i2c, +}; + +int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_read); + +int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_write); + +static int __init accton_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&accton_i2c_cpld_driver); +} + +static void __exit accton_i2c_cpld_exit(void) +{ + i2c_del_driver(&accton_i2c_cpld_driver); +} + +static struct dmi_system_id as7512_dmi_table[] = { + { + .ident = "Accton AS7512", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS7512"), + }, + }, + { + .ident = "Accton AS7512", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS7512"), + }, + }, +}; + +int platform_accton_as7512_32x(void) +{ + return dmi_check_system(as7512_dmi_table); +} +EXPORT_SYMBOL(platform_accton_as7512_32x); + +static struct dmi_system_id as7712_dmi_table[] = { + { + .ident = "Accton AS7712", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS7712"), + }, + }, + { + .ident = "Accton AS7712", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS7712"), + }, + }, +}; + +int platform_accton_as7712_32x(void) +{ + return dmi_check_system(as7712_dmi_table); +} +EXPORT_SYMBOL(platform_accton_as7712_32x); + +static struct dmi_system_id as5812_54t_dmi_table[] = { + { + .ident = "Accton AS5812 54t", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS5812-54T"), + }, + }, + { + .ident = "Accton AS5812 54t", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS5812-54T"), + }, + }, +}; + +int platform_accton_as5812_54t(void) +{ + return dmi_check_system(as5812_54t_dmi_table); +} +EXPORT_SYMBOL(platform_accton_as5812_54t); + +static struct dmi_system_id as5512_54x_dmi_table[] = { + { + .ident = "Accton AS5512", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS5512"), + }, + }, + { + .ident = "Accton AS5512", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS5512"), + }, + }, +}; + +int platform_accton_as5512_54x(void) +{ + return dmi_check_system(as5512_54x_dmi_table); +} +EXPORT_SYMBOL(platform_accton_as5512_54x); + +static struct dmi_system_id as7716_dmi_table[] = { + { + .ident = "Accton AS7716", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS7716"), + }, + }, + { + .ident = "Accton AS7716", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS7716"), + }, + }, +}; + +int platform_accton_as7716_32x(void) +{ + return dmi_check_system(as7716_dmi_table); +} +EXPORT_SYMBOL(platform_accton_as7716_32x); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_i2c_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_i2c_cpld_init); +module_exit(accton_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-fan.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-fan.c new file mode 100644 index 000000000000..bad9245e93ac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-fan.c @@ -0,0 +1,442 @@ +/* + * A hwmon driver for the Accton as5812 54t fan + * + * Copyright (C) 2015 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FAN_MAX_NUMBER 5 +#define FAN_SPEED_CPLD_TO_RPM_STEP 150 +#define FAN_SPEED_PRECENT_TO_CPLD_STEP 5 +#define FAN_DUTY_CYCLE_MIN 0 +#define FAN_DUTY_CYCLE_MAX 100 /* 100% */ + +#define CPLD_REG_FAN_STATUS_OFFSET 0xC +#define CPLD_REG_FANR_STATUS_OFFSET 0x1F +#define CPLD_REG_FAN_DIRECTION_OFFSET 0x1E + +#define CPLD_FAN1_REG_SPEED_OFFSET 0x10 +#define CPLD_FAN2_REG_SPEED_OFFSET 0x11 +#define CPLD_FAN3_REG_SPEED_OFFSET 0x12 +#define CPLD_FAN4_REG_SPEED_OFFSET 0x13 +#define CPLD_FAN5_REG_SPEED_OFFSET 0x14 + +#define CPLD_FANR1_REG_SPEED_OFFSET 0x18 +#define CPLD_FANR2_REG_SPEED_OFFSET 0x19 +#define CPLD_FANR3_REG_SPEED_OFFSET 0x1A +#define CPLD_FANR4_REG_SPEED_OFFSET 0x1B +#define CPLD_FANR5_REG_SPEED_OFFSET 0x1C + +#define CPLD_REG_FAN_PWM_CYCLE_OFFSET 0xD + +#define CPLD_FAN1_INFO_BIT_MASK 0x1 +#define CPLD_FAN2_INFO_BIT_MASK 0x2 +#define CPLD_FAN3_INFO_BIT_MASK 0x4 +#define CPLD_FAN4_INFO_BIT_MASK 0x8 +#define CPLD_FAN5_INFO_BIT_MASK 0x10 + +#define PROJECT_NAME + +#define LOCAL_DEBUG 0 + +static struct accton_as5812_54t_fan *fan_data = NULL; + +struct accton_as5812_54t_fan { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[FAN_MAX_NUMBER]; /* inner first fan status */ + u32 speed[FAN_MAX_NUMBER]; /* inner first fan speed */ + u8 direction[FAN_MAX_NUMBER]; /* reconrd the direction of inner first and second fans */ + u32 duty_cycle[FAN_MAX_NUMBER]; /* control the speed of inner first and second fans */ + u8 r_status[FAN_MAX_NUMBER]; /* inner second fan status */ + u32 r_speed[FAN_MAX_NUMBER]; /* inner second fan speed */ +}; + +/*******************/ +#define MAKE_FAN_MASK_OR_REG(name,type) \ + CPLD_FAN##type##1_##name, \ + CPLD_FAN##type##2_##name, \ + CPLD_FAN##type##3_##name, \ + CPLD_FAN##type##4_##name, \ + CPLD_FAN##type##5_##name, + +/* fan related data + */ +static const u8 fan_info_mask[] = { + MAKE_FAN_MASK_OR_REG(INFO_BIT_MASK,) +}; + +static const u8 fan_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,) +}; + +static const u8 fanr_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,R) +}; + +/*******************/ +#define DEF_FAN_SET(id) \ + FAN##id##_FAULT, \ + FAN##id##_SPEED, \ + FAN##id##_DUTY_CYCLE, \ + FAN##id##_DIRECTION, \ + FANR##id##_FAULT, \ + FANR##id##_SPEED, + +enum sysfs_fan_attributes { + DEF_FAN_SET(1) + DEF_FAN_SET(2) + DEF_FAN_SET(3) + DEF_FAN_SET(4) + DEF_FAN_SET(5) +}; +/*******************/ +static void accton_as5812_54t_fan_update_device(struct device *dev); +static int accton_as5812_54t_fan_read_value(u8 reg); +static int accton_as5812_54t_fan_write_value(u8 reg, u8 value); + +static ssize_t fan_set_duty_cycle(struct device *dev, + struct device_attribute *da,const char *buf, size_t count); +static ssize_t fan_show_value(struct device *dev, + struct device_attribute *da, char *buf); + +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + + +/*******************/ +#define _MAKE_SENSOR_DEVICE_ATTR(prj, id) \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, \ + fan_set_duty_cycle, FAN##id##_DUTY_CYCLE); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_direction, S_IRUGO, fan_show_value, NULL, FAN##id##_DIRECTION); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_fault, S_IRUGO, fan_show_value, NULL, FANR##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED); + +#define MAKE_SENSOR_DEVICE_ATTR(prj,id) _MAKE_SENSOR_DEVICE_ATTR(prj,id) + +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 1) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 2) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 3) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 4) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 5) +/*******************/ + +#define _MAKE_FAN_ATTR(prj, id) \ + &sensor_dev_attr_##prj##fan##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_duty_cycle_percentage.dev_attr.attr,\ + &sensor_dev_attr_##prj##fan##id##_direction.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_speed_rpm.dev_attr.attr, + +#define MAKE_FAN_ATTR(prj, id) _MAKE_FAN_ATTR(prj, id) + +static struct attribute *accton_as5812_54t_fan_attributes[] = { + /* fan related attributes */ + MAKE_FAN_ATTR(PROJECT_NAME,1) + MAKE_FAN_ATTR(PROJECT_NAME,2) + MAKE_FAN_ATTR(PROJECT_NAME,3) + MAKE_FAN_ATTR(PROJECT_NAME,4) + MAKE_FAN_ATTR(PROJECT_NAME,5) + NULL +}; +/*******************/ + +/* fan related functions + */ +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + ssize_t ret = 0; + int data_index, type_index; + + accton_as5812_54t_fan_update_device(dev); + + if (fan_data->valid == 0) { + return ret; + } + + type_index = attr->index%FAN2_FAULT; + data_index = attr->index/FAN2_FAULT; + + switch (type_index) { + case FAN1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->status[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->speed[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DUTY_CYCLE: + ret = sprintf(buf, "%d\n", fan_data->duty_cycle[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DIRECTION: + ret = sprintf(buf, "%d\n", fan_data->direction[data_index]); /* presnet, need to modify*/ + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->r_status[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->r_speed[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + default: + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d] \n", __FUNCTION__, __LINE__); + break; + } + + return ret; +} +/*******************/ +static ssize_t fan_set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { + + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < FAN_DUTY_CYCLE_MIN || value > FAN_DUTY_CYCLE_MAX) + return -EINVAL; + + accton_as5812_54t_fan_write_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET, value/FAN_SPEED_PRECENT_TO_CPLD_STEP); + + fan_data->valid = 0; + + return count; +} + +static const struct attribute_group accton_as5812_54t_fan_group = { + .attrs = accton_as5812_54t_fan_attributes, +}; + +static int accton_as5812_54t_fan_read_value(u8 reg) +{ + return accton_i2c_cpld_read(0x60, reg); +} + +static int accton_as5812_54t_fan_write_value(u8 reg, u8 value) +{ + return accton_i2c_cpld_write(0x60, reg, value); +} + +static void accton_as5812_54t_fan_update_device(struct device *dev) +{ + int speed, r_speed, fault, r_fault, ctrl_speed, direction; + int i; + + mutex_lock(&fan_data->update_lock); + + if (LOCAL_DEBUG) + printk ("Starting accton_as5812_54t_fan update \n"); + + if (!(time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) || !fan_data->valid)) { + /* do nothing */ + goto _exit; + } + + fan_data->valid = 0; + + if (LOCAL_DEBUG) + printk ("Starting accton_as5812_54t_fan update 2 \n"); + + fault = accton_as5812_54t_fan_read_value(CPLD_REG_FAN_STATUS_OFFSET); + r_fault = accton_as5812_54t_fan_read_value(CPLD_REG_FANR_STATUS_OFFSET); + direction = accton_as5812_54t_fan_read_value(CPLD_REG_FAN_DIRECTION_OFFSET); + ctrl_speed = accton_as5812_54t_fan_read_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET); + + if ( (fault < 0) || (r_fault < 0) || (direction < 0) || (ctrl_speed < 0) ) + { + if (LOCAL_DEBUG) + printk ("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + + if (LOCAL_DEBUG) + printk ("[fan:] fault:%d, r_fault=%d, direction=%d, ctrl_speed=%d \n",fault, r_fault, direction, ctrl_speed); + + for (i=0; istatus[i] = (fault & fan_info_mask[i]) >> i; + if (LOCAL_DEBUG) + printk ("[fan%d:] fail=%d \n",i, fan_data->status[i]); + + fan_data->r_status[i] = (r_fault & fan_info_mask[i]) >> i; + fan_data->direction[i] = (direction & fan_info_mask[i]) >> i; + fan_data->duty_cycle[i] = ctrl_speed * FAN_SPEED_PRECENT_TO_CPLD_STEP; + + /* fan speed + */ + speed = accton_as5812_54t_fan_read_value(fan_speed_reg[i]); + r_speed = accton_as5812_54t_fan_read_value(fanr_speed_reg[i]); + if ( (speed < 0) || (r_speed < 0) ) + { + if (LOCAL_DEBUG) + printk ("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + + if (LOCAL_DEBUG) + printk ("[fan%d:] speed:%d, r_speed=%d \n", i, speed, r_speed); + + fan_data->speed[i] = speed * FAN_SPEED_CPLD_TO_RPM_STEP; + fan_data->r_speed[i] = r_speed * FAN_SPEED_CPLD_TO_RPM_STEP; + } + + /* finish to update */ + fan_data->last_updated = jiffies; + fan_data->valid = 1; + +_exit: + mutex_unlock(&fan_data->update_lock); +} + +static int accton_as5812_54t_fan_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &accton_as5812_54t_fan_group); + if (status) { + goto exit; + + } + + fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(fan_data->hwmon_dev)) { + status = PTR_ERR(fan_data->hwmon_dev); + goto exit_remove; + } + + dev_info(&pdev->dev, "accton_as5812_54t_fan\n"); + + return 0; + +exit_remove: + sysfs_remove_group(&pdev->dev.kobj, &accton_as5812_54t_fan_group); +exit: + return status; +} + +static int accton_as5812_54t_fan_remove(struct platform_device *pdev) +{ + hwmon_device_unregister(fan_data->hwmon_dev); + sysfs_remove_group(&fan_data->pdev->dev.kobj, &accton_as5812_54t_fan_group); + + return 0; +} + +#define DRVNAME "as5812_54t_fan" + +static struct platform_driver accton_as5812_54t_fan_driver = { + .probe = accton_as5812_54t_fan_probe, + .remove = accton_as5812_54t_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as5812_54t_fan_init(void) +{ + int ret; + + extern int platform_accton_as5812_54t(void); + if (!platform_accton_as5812_54t()) { + return -ENODEV; + } + + ret = platform_driver_register(&accton_as5812_54t_fan_driver); + if (ret < 0) { + goto exit; + } + + fan_data = kzalloc(sizeof(struct accton_as5812_54t_fan), GFP_KERNEL); + if (!fan_data) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as5812_54t_fan_driver); + goto exit; + } + + mutex_init(&fan_data->update_lock); + fan_data->valid = 0; + + fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(fan_data->pdev)) { + ret = PTR_ERR(fan_data->pdev); + platform_driver_unregister(&accton_as5812_54t_fan_driver); + kfree(fan_data); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as5812_54t_fan_exit(void) +{ + platform_device_unregister(fan_data->pdev); + platform_driver_unregister(&accton_as5812_54t_fan_driver); + kfree(fan_data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as5812_54t_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_as5812_54t_fan_init); +module_exit(accton_as5812_54t_fan_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-leds.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-leds.c new file mode 100644 index 000000000000..011f62e76c06 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-leds.c @@ -0,0 +1,601 @@ +/* + * A LED driver for the accton_as5812_54t_led + * + * Copyright (C) 2015 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include + +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "as5812_54t_led" + +struct accton_as5812_54t_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[4]; /* Register value, 0 = LOC/DIAG/FAN LED + 1 = PSU1/PSU2 LED + 2 = FAN1-4 LED + 3 = FAN5-6 LED */ +}; + +static struct accton_as5812_54t_led_data *ledctl = NULL; + +/* LED related data + */ +#define LED_TYPE_PSU1_REG_MASK 0x03 +#define LED_MODE_PSU1_GREEN_MASK 0x02 +#define LED_MODE_PSU1_AMBER_MASK 0x01 +#define LED_MODE_PSU1_OFF_MASK 0x03 +#define LED_MODE_PSU1_AUTO_MASK 0x00 + +#define LED_TYPE_PSU2_REG_MASK 0x0C +#define LED_MODE_PSU2_GREEN_MASK 0x08 +#define LED_MODE_PSU2_AMBER_MASK 0x04 +#define LED_MODE_PSU2_OFF_MASK 0x0C +#define LED_MODE_PSU2_AUTO_MASK 0x00 + +#define LED_TYPE_DIAG_REG_MASK 0x0C +#define LED_MODE_DIAG_GREEN_MASK 0x08 +#define LED_MODE_DIAG_AMBER_MASK 0x04 +#define LED_MODE_DIAG_OFF_MASK 0x0C + +#define LED_TYPE_FAN_REG_MASK 0x03 +#define LED_MODE_FAN_GREEN_MASK 0x02 +#define LED_MODE_FAN_AMBER_MASK 0x01 +#define LED_MODE_FAN_OFF_MASK 0x03 +#define LED_MODE_FAN_AUTO_MASK 0x00 + +#define LED_TYPE_FAN1_REG_MASK 0x03 +#define LED_TYPE_FAN2_REG_MASK 0x0C +#define LED_TYPE_FAN3_REG_MASK 0x30 +#define LED_TYPE_FAN4_REG_MASK 0xC0 +#define LED_TYPE_FAN5_REG_MASK 0x03 +#define LED_TYPE_FAN6_REG_MASK 0x0C + +#define LED_MODE_FANX_GREEN_MASK 0x01 +#define LED_MODE_FANX_RED_MASK 0x02 +#define LED_MODE_FANX_OFF_MASK 0x00 + +#define LED_TYPE_LOC_REG_MASK 0x30 +#define LED_MODE_LOC_ON_MASK 0x00 +#define LED_MODE_LOC_OFF_MASK 0x10 +#define LED_MODE_LOC_BLINK_MASK 0x20 + +static const u8 led_reg[] = { + 0xA, /* LOC/DIAG/FAN LED*/ + 0xB, /* PSU1/PSU2 LED */ + 0x16, /* FAN1-4 LED */ + 0x17, /* FAN4-6 LED */ +}; + +enum led_type { + LED_TYPE_PSU1, + LED_TYPE_PSU2, + LED_TYPE_DIAG, + LED_TYPE_FAN, + LED_TYPE_FAN1, + LED_TYPE_FAN2, + LED_TYPE_FAN3, + LED_TYPE_FAN4, + LED_TYPE_FAN5, + LED_TYPE_LOC +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER, + LED_MODE_AMBER_BLINK, + LED_MODE_RED, + LED_MODE_RED_BLINK, + LED_MODE_BLUE, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +struct led_type_mode { + enum led_type type; + int type_mask; + enum led_light_mode mode; + int mode_mask; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU1_GREEN_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU1_AMBER_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU1_AUTO_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_OFF, LED_MODE_PSU1_OFF_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU2_GREEN_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU2_AMBER_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU2_AUTO_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_OFF, LED_MODE_PSU2_OFF_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_GREEN, LED_MODE_FAN_GREEN_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AMBER, LED_MODE_FAN_AMBER_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AUTO, LED_MODE_FAN_AUTO_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_OFF, LED_MODE_FAN_OFF_MASK}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 2}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 4}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 6}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_GREEN, LED_MODE_DIAG_GREEN_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_AMBER, LED_MODE_DIAG_AMBER_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_OFF, LED_MODE_DIAG_OFF_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER, LED_MODE_LOC_ON_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_OFF, LED_MODE_LOC_OFF_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER_BLINK, LED_MODE_LOC_BLINK_MASK} +}; + + +struct fanx_info_s { + u8 cname; /* device name */ + enum led_type type; + u8 reg_id; /* map to led_reg & reg_val */ +}; + +static struct fanx_info_s fanx_info[] = { + {'1', LED_TYPE_FAN1, 2}, + {'2', LED_TYPE_FAN2, 2}, + {'3', LED_TYPE_FAN3, 2}, + {'4', LED_TYPE_FAN4, 2}, + {'5', LED_TYPE_FAN5, 3} +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_mask) + { + return led_type_mode_data[i].mode; + } + } + + return LED_MODE_UNKNOWN; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + reg_val = led_type_mode_data[i].mode_mask | + (reg_val & (~led_type_mode_data[i].type_mask)); + } + + return reg_val; +} + +static int accton_as5812_54t_led_read_value(u8 reg) +{ + return accton_i2c_cpld_read(0x60, reg); +} + +static int accton_as5812_54t_led_write_value(u8 reg, u8 value) +{ + return accton_i2c_cpld_write(0x60, reg, value); +} + +static void accton_as5812_54t_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as5812_54t_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as5812_54t_led_read_value(led_reg[i]); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as5812_54t_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + + reg_val = accton_as5812_54t_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as5812_54t_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as5812_54t_led_psu_1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54t_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1); +} + +static enum led_brightness accton_as5812_54t_led_psu_1_get(struct led_classdev *cdev) +{ + accton_as5812_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void accton_as5812_54t_led_psu_2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54t_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2); +} + +static enum led_brightness accton_as5812_54t_led_psu_2_get(struct led_classdev *cdev) +{ + accton_as5812_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static void accton_as5812_54t_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54t_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_FAN); +} + +static enum led_brightness accton_as5812_54t_led_fan_get(struct led_classdev *cdev) +{ + accton_as5812_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + + +static void accton_as5812_54t_led_fanx_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (led_cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as5812_54t_led_set(led_cdev, led_light_mode, led_reg[reg_id], led_type1); + return; + } + } +} + + +static enum led_brightness accton_as5812_54t_led_fanx_get(struct led_classdev *cdev) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as5812_54t_led_update(); + return led_reg_val_to_light_mode(led_type1, ledctl->reg_val[reg_id]); + } + } + + + return led_reg_val_to_light_mode(LED_TYPE_FAN1, ledctl->reg_val[2]); +} + + +static void accton_as5812_54t_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54t_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} + +static enum led_brightness accton_as5812_54t_led_diag_get(struct led_classdev *cdev) +{ + accton_as5812_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as5812_54t_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54t_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static enum led_brightness accton_as5812_54t_led_loc_get(struct led_classdev *cdev) +{ + accton_as5812_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static struct led_classdev accton_as5812_54t_leds[] = { + [LED_TYPE_PSU1] = { + .name = "accton_as5812_54t_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_psu_1_set, + .brightness_get = accton_as5812_54t_led_psu_1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as5812_54t_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_psu_2_set, + .brightness_get = accton_as5812_54t_led_psu_2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "accton_as5812_54t_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_fan_set, + .brightness_get = accton_as5812_54t_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN1] = { + .name = "accton_as5812_54t_led::fan1", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_fanx_set, + .brightness_get = accton_as5812_54t_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN2] = { + .name = "accton_as5812_54t_led::fan2", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_fanx_set, + .brightness_get = accton_as5812_54t_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN3] = { + .name = "accton_as5812_54t_led::fan3", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_fanx_set, + .brightness_get = accton_as5812_54t_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN4] = { + .name = "accton_as5812_54t_led::fan4", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_fanx_set, + .brightness_get = accton_as5812_54t_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN5] = { + .name = "accton_as5812_54t_led::fan5", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_fanx_set, + .brightness_get = accton_as5812_54t_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_DIAG] = { + .name = "accton_as5812_54t_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_diag_set, + .brightness_get = accton_as5812_54t_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_LOC] = { + .name = "accton_as5812_54t_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_loc_set, + .brightness_get = accton_as5812_54t_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as5812_54t_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as5812_54t_leds); i++) { + led_classdev_suspend(&accton_as5812_54t_leds[i]); + } + + return 0; +} + +static int accton_as5812_54t_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as5812_54t_leds); i++) { + led_classdev_resume(&accton_as5812_54t_leds[i]); + } + + return 0; +} + +static int accton_as5812_54t_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as5812_54t_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as5812_54t_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as5812_54t_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as5812_54t_leds[i]); + } + } + + return ret; +} + +static int accton_as5812_54t_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as5812_54t_leds); i++) { + led_classdev_unregister(&accton_as5812_54t_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as5812_54t_led_driver = { + .probe = accton_as5812_54t_led_probe, + .remove = accton_as5812_54t_led_remove, + .suspend = accton_as5812_54t_led_suspend, + .resume = accton_as5812_54t_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as5812_54t_led_init(void) +{ + int ret; + + extern int platform_accton_as5812_54t(void); + if (!platform_accton_as5812_54t()) { + return -ENODEV; + } + + ret = platform_driver_register(&accton_as5812_54t_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as5812_54t_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as5812_54t_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as5812_54t_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as5812_54t_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as5812_54t_led_driver); + kfree(ledctl); +} + +module_init(accton_as5812_54t_led_init); +module_exit(accton_as5812_54t_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as5812_54t_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-psu.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-psu.c new file mode 100644 index 000000000000..a77014e877ca --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-psu.c @@ -0,0 +1,372 @@ +/* + * An hwmon driver for accton as5812_54t Power Module + * + * Copyright (C) 2015 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +static ssize_t show_index(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as5812_54t_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +static int as5812_54t_psu_model_name_get(struct device *dev); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as5812_54t_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[14]; /* Model name, read from eeprom */ +}; + +static struct as5812_54t_psu_data *as5812_54t_psu_update_device(struct device *dev); + +enum as5812_54t_psu_sysfs_attributes { + PSU_INDEX, + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_index, S_IRUGO, show_index, NULL, PSU_INDEX); +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as5812_54t_psu_attributes[] = { + &sensor_dev_attr_psu_index.dev_attr.attr, + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_index(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54t_psu_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", data->index); +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5812_54t_psu_data *data = as5812_54t_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as5812_54t_psu_data *data = as5812_54t_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!IS_PRESENT(data->index, data->status)) { + return 0; + } + + if (as5812_54t_psu_model_name_get(dev) < 0) { + return -ENXIO; + } + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as5812_54t_psu_group = { + .attrs = as5812_54t_psu_attributes, +}; + +static int as5812_54t_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5812_54t_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5812_54t_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5812_54t_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5812_54t_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5812_54t_psu_remove(struct i2c_client *client) +{ + struct as5812_54t_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5812_54t_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as5812_54t_psu1, + as5812_54t_psu2 +}; + +static const struct i2c_device_id as5812_54t_psu_id[] = { + { "as5812_54t_psu1", as5812_54t_psu1 }, + { "as5812_54t_psu2", as5812_54t_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as5812_54t_psu_id); + +static struct i2c_driver as5812_54t_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as5812_54t_psu", + }, + .probe = as5812_54t_psu_probe, + .remove = as5812_54t_psu_remove, + .id_table = as5812_54t_psu_id, + .address_list = normal_i2c, +}; + +static int as5812_54t_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +enum psu_type { + PSU_YM_2401_JCR, /* AC110V - F2B */ + PSU_YM_2401_JDR, /* AC110V - B2F */ + PSU_CPR_4011_4M11, /* AC110V - F2B */ + PSU_CPR_4011_4M21, /* AC110V - B2F */ + PSU_CPR_6011_2M11, /* AC110V - F2B */ + PSU_CPR_6011_2M21, /* AC110V - B2F */ + PSU_UM400D_01G, /* DC48V - F2B */ + PSU_UM400D01_01G /* DC48V - B2F */ +}; + +struct model_name_info { + enum psu_type type; + u8 offset; + u8 length; + char* model_name; +}; + +struct model_name_info models[] = { +{PSU_YM_2401_JCR, 0x20, 11, "YM-2401JCR"}, +{PSU_YM_2401_JDR, 0x20, 11, "YM-2401JDR"}, +{PSU_CPR_4011_4M11, 0x26, 13, "CPR-4011-4M11"}, +{PSU_CPR_4011_4M21, 0x26, 13, "CPR-4011-4M21"}, +{PSU_CPR_6011_2M11, 0x26, 13, "CPR-6011-2M11"}, +{PSU_CPR_6011_2M21, 0x26, 13, "CPR-6011-2M21"}, +{PSU_UM400D_01G, 0x50, 9, "um400d01G"}, +{PSU_UM400D01_01G, 0x50, 12, "um400d01-01G"}, +}; + +static int as5812_54t_psu_model_name_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54t_psu_data *data = i2c_get_clientdata(client); + int i, status; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + memset(data->model_name, 0, sizeof(data->model_name)); + + status = as5812_54t_psu_read_block(client, models[i].offset, + data->model_name, models[i].length); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x%x)\n", + client->addr, models[i].offset); + return status; + } + else { + data->model_name[models[i].length] = '\0'; + } + + if (i == PSU_YM_2401_JCR || i == PSU_YM_2401_JDR) { + /* Skip the meaningless data byte 8*/ + data->model_name[8] = data->model_name[9]; + data->model_name[9] = data->model_name[10]; + data->model_name[10] = '\0'; + } + + /* Determine if the model name is known, if not, read next index + */ + if (strncmp(data->model_name, models[i].model_name, models[i].length) == 0) { + return 0; + } + else { + data->model_name[0] = '\0'; + } + } + + return -ENODATA; +} + +static struct as5812_54t_psu_data *as5812_54t_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54t_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + + dev_dbg(&client->dev, "Starting as5812_54t update\n"); + data->valid = 0; + + /* Read psu status */ + status = accton_i2c_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as5812_54t_psu_init(void) +{ + extern int platform_accton_as5812_54t(void); + if (!platform_accton_as5812_54t()) { + return -ENODEV; + } + + return i2c_add_driver(&as5812_54t_psu_driver); +} + +static void __exit as5812_54t_psu_exit(void) +{ + i2c_del_driver(&as5812_54t_psu_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as5812_54t_psu driver"); +MODULE_LICENSE("GPL"); + +module_init(as5812_54t_psu_init); +module_exit(as5812_54t_psu_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-sfp.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-sfp.c new file mode 100644 index 000000000000..88bf552de0f0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-sfp.c @@ -0,0 +1,318 @@ +/* + * An hwmon driver for accton as5812_54t sfp + * + * Copyright (C) 2015 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define QSFP_PORT_START_INDEX 49 +#define BIT_INDEX(i) (1ULL << (i)) + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as5812_54t_sfp_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + int port; /* Front port index */ + char eeprom[256]; /* eeprom data */ + u8 status; /* bit0:port49, bit1:port50 and so on */ +}; + +static struct as5812_54t_sfp_data *as5812_54t_sfp_update_device(struct device *dev, int update_eeprom); +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +enum as5812_54t_sfp_sysfs_attributes { + SFP_IS_PRESENT, + SFP_PORT_NUMBER, + SFP_EEPROM, + SFP_IS_PRESENT_ALL, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_status, NULL, SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, SFP_PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_eeprom, S_IRUGO, show_eeprom, NULL, SFP_EEPROM); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_status,NULL, SFP_IS_PRESENT_ALL); + +static struct attribute *as5812_54t_sfp_attributes[] = { + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_eeprom.dev_attr.attr, + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + NULL +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54t_sfp_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n",data->port); +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5812_54t_sfp_data *data = as5812_54t_sfp_update_device(dev, 0); + + if (attr->index == SFP_IS_PRESENT) { + u8 val; + + val = (data->status & BIT_INDEX(data->port - QSFP_PORT_START_INDEX)) ? 0 : 1; + return sprintf(buf, "%d", val); + } + else { /* SFP_IS_PRESENT_ALL */ + return sprintf(buf, "%.2x\n", ~data->status); + } +} + +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as5812_54t_sfp_data *data = as5812_54t_sfp_update_device(dev, 1); + + if (!data->valid) { + return 0; + } + + if ((data->status & BIT_INDEX(data->port - QSFP_PORT_START_INDEX)) != 0) { + return 0; + } + + memcpy(buf, data->eeprom, sizeof(data->eeprom)); + + return sizeof(data->eeprom); +} + +static const struct attribute_group as5812_54t_sfp_group = { + .attrs = as5812_54t_sfp_attributes, +}; + +static int as5812_54t_sfp_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5812_54t_sfp_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5812_54t_sfp_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + i2c_set_clientdata(client, data); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5812_54t_sfp_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: sfp '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5812_54t_sfp_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5812_54t_sfp_remove(struct i2c_client *client) +{ + struct as5812_54t_sfp_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5812_54t_sfp_group); + kfree(data); + + return 0; +} + +enum port_numbers { +as5812_54t_qsfp49 = 49, +as5812_54t_qsfp50, +as5812_54t_qsfp51, +as5812_54t_qsfp52, +as5812_54t_qsfp53, +as5812_54t_qsfp54 +}; + +static const struct i2c_device_id as5812_54t_sfp_id[] = { +{ "as5812_54t_qsfp49", as5812_54t_qsfp49 }, { "as5812_54t_qsfp50", as5812_54t_qsfp50 }, +{ "as5812_54t_qsfp51", as5812_54t_qsfp51 }, { "as5812_54t_qsfp52", as5812_54t_qsfp52 }, +{ "as5812_54t_qsfp53", as5812_54t_qsfp53 }, { "as5812_54t_qsfp54", as5812_54t_qsfp54 }, +{} +}; +MODULE_DEVICE_TABLE(i2c, as5812_54t_sfp_id); + +static struct i2c_driver as5812_54t_sfp_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as5812_54t_sfp", + }, + .probe = as5812_54t_sfp_probe, + .remove = as5812_54t_sfp_remove, + .id_table = as5812_54t_sfp_id, + .address_list = normal_i2c, +}; + +static int as5812_54t_sfp_read_byte(struct i2c_client *client, u8 command, u8 *data) +{ + int result = i2c_smbus_read_byte_data(client, command); + + if (unlikely(result < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result); + goto abort; + } + + *data = (u8)result; + result = 0; + +abort: + return result; +} + +static struct as5812_54t_sfp_data *as5812_54t_sfp_update_device(struct device *dev, int update_eeprom) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54t_sfp_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid || update_eeprom) { + int status = -1; + int i = 0; + + data->valid = 0; + //dev_dbg(&client->dev, "Starting as5812_54t sfp status update\n"); + data->status = 0xFF; + + /* + * Bring QSFPs out of reset, + * This is a temporary fix until the QSFP+_MOD_RST register + * can be exposed through the driver. + */ + accton_i2c_cpld_write(0x60, 0x23, 0x3F); + + /* Read present status of port 49-54(QSFP port) */ + status = accton_i2c_cpld_read(0x60, 0x22); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x60) reg(0x22) err %d\n", status); + } + else { + data->status = status & 0x3F; /* (u32)status */ + } + + if (update_eeprom) { + /* Read eeprom data based on port number */ + memset(data->eeprom, 0, sizeof(data->eeprom)); + + /* Check if the port is present */ + if ((data->status & BIT_INDEX(data->port - QSFP_PORT_START_INDEX)) == 0) { + /* read eeprom */ + for (i = 0; i < sizeof(data->eeprom); i++) { + status = as5812_54t_sfp_read_byte(client, i, data->eeprom + i); + + if (status < 0) { + dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n", + data->port); + goto exit; + } + } + } + } + + data->valid = 1; + data->last_updated = jiffies; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as5812_54t_sfp_init(void) +{ + extern int platform_accton_as5812_54t(void); + if (!platform_accton_as5812_54t()) { + return -ENODEV; + } + + return i2c_add_driver(&as5812_54t_sfp_driver); +} + +static void __exit as5812_54t_sfp_exit(void) +{ + i2c_del_driver(&as5812_54t_sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as5812_54t_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(as5812_54t_sfp_init); +module_exit(as5812_54t_sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/ym2651y.c new file mode 100644 index 000000000000..7101aa411f72 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/ym2651y.c @@ -0,0 +1,680 @@ +/* + * An hwmon driver for the 3Y Power YM-2651Y Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +enum chips { + YM2651, + YM2401, +}; + +/* Each client has this additional data + */ +struct ym2651y_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 chip; /* chip id */ + u8 capability; /* Register value */ + u16 status_word; /* Register value */ + u8 fan_fault; /* Register value */ + u8 over_temp; /* Register value */ + u16 v_out; /* Register value */ + u16 i_out; /* Register value */ + u16 p_out; /* Register value */ + u8 vout_mode; /* Register value */ + u16 temp; /* Register value */ + u16 fan_speed; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u8 fan_dir[5]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[16]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u16 mfr_vin_min; /* Register value */ + u16 mfr_vin_max; /* Register value */ + u16 mfr_iin_max; /* Register value */ + u16 mfr_iout_max; /* Register value */ + u16 mfr_pin_max; /* Register value */ + u16 mfr_pout_max; /* Register value */ + u16 mfr_vout_min; /* Register value */ + u16 mfr_vout_max; /* Register value */ +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static struct ym2651y_data *ym2651y_update_device(struct device *dev); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value); + +enum ym2651y_sysfs_attributes { + PSU_POWER_ON = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD, + PSU_FAN1_FAULT, + PSU_FAN_DIRECTION, + PSU_OVER_TEMP, + PSU_V_OUT, + PSU_I_OUT, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_SPEED, + PSU_FAN1_DUTY_CYCLE, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_VIN_MIN, + PSU_MFR_VIN_MAX, + PSU_MFR_VOUT_MIN, + PSU_MFR_VOUT_MAX, + PSU_MFR_IIN_MAX, + PSU_MFR_IOUT_MAX, + PSU_MFR_PIN_MAX, + PSU_MFR_POUT_MAX +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision,S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); + +static struct attribute *ym2651y_attributes[] = { + &sensor_dev_attr_psu_power_on.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_over_temp.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, + NULL +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + if (!data->valid) { + return 0; + } + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u16 status = 0; + + if (!data->valid) { + return 0; + } + + switch (attr->index) { + case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */ + status = (data->status_word & 0x40) ? 0 : 1; + break; + case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */ + status = (data->status_word & 0x4) >> 2; + break; + case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */ + status = (data->status_word & 0x800) ? 0 : 1; + break; + } + + return sprintf(buf, "%d\n", status); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + if (!data->valid) { + return 0; + } + + switch (attr->index) { + case PSU_V_OUT: + value = data->v_out; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp; + break; + case PSU_FAN1_SPEED: + value = data->fan_speed; + multiplier = 1; + break; + case PSU_FAN1_DUTY_CYCLE: + value = data->fan_duty_cycle[0]; + multiplier = 1; + break; + case PSU_MFR_VIN_MIN: + value = data->mfr_vin_min; + break; + case PSU_MFR_VIN_MAX: + value = data->mfr_vin_max; + break; + case PSU_MFR_VOUT_MIN: + value = data->mfr_vout_min; + break; + case PSU_MFR_VOUT_MAX: + value = data->mfr_vout_max; + break; + case PSU_MFR_PIN_MAX: + value = data->mfr_pin_max; + break; + case PSU_MFR_POUT_MAX: + value = data->mfr_pout_max; + break; + case PSU_MFR_IOUT_MAX: + value = data->mfr_iout_max; + break; + case PSU_MFR_IIN_MAX: + value = data->mfr_iin_max; + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u8 shift; + + if (!data->valid) { + return 0; + } + + shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct ym2651y_data *data = ym2651y_update_device(dev); + + if (!data->valid) { + return 0; + } + + return sprintf(buf, "%d\n", data->over_temp >> 7); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) { + return 0; + } + + switch (attr->index) { + case PSU_FAN_DIRECTION: /* psu_fan_dir */ + ptr = data->fan_dir + 1; /* Skip the first byte since it is the length of string. */ + break; + case PSU_MFR_ID: /* psu_mfr_id */ + ptr = data->mfr_id + 1; /* The first byte is the count byte of string. */; + break; + case PSU_MFR_MODEL: /* psu_mfr_model */ + ptr = data->mfr_model + 1; /* The first byte is the count byte of string. */ + break; + case PSU_MFR_REVISION: /* psu_mfr_revision */ + ptr = data->mfr_revsion + 1; /* The first byte is the count byte of string. */ + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + +static ssize_t show_vout_by_mode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct ym2651y_data *data = ym2651y_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + if (!data->valid) { + return 0; + } + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + if (data->chip == YM2401) { + return show_vout_by_mode(dev, da, buf); + } + + return show_linear(dev, da, buf); +} + +static const struct attribute_group ym2651y_group = { + .attrs = ym2651y_attributes, +}; + +static int ym2651y_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct ym2651y_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->chip = dev_id->driver_data; + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &ym2651y_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int ym2651y_remove(struct i2c_client *client) +{ + struct ym2651y_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id ym2651y_id[] = { + { "ym2651", YM2651 }, + { "ym2401", YM2401 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ym2651y_id); + +static struct i2c_driver ym2651y_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ym2651", + }, + .probe = ym2651y_probe, + .remove = ym2651y_remove, + .id_table = ym2651y_id, + .address_list = normal_i2c, +}; + +static int ym2651y_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int ym2651y_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct ym2651y_data *ym2651y_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status, length; + u8 command, buf; + struct reg_data_byte regs_byte[] = { {0x19, &data->capability}, + {0x20, &data->vout_mode}, + {0x7d, &data->over_temp}, + {0x81, &data->fan_fault}, + {0x98, &data->pmbus_revision}}; + struct reg_data_word regs_word[] = { {0x79, &data->status_word}, + {0x8b, &data->v_out}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x8d, &data->temp}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &data->fan_speed}, + {0xa0, &data->mfr_vin_min}, + {0xa1, &data->mfr_vin_max}, + {0xa2, &data->mfr_iin_max}, + {0xa3, &data->mfr_pin_max}, + {0xa4, &data->mfr_vout_min}, + {0xa5, &data->mfr_vout_max}, + {0xa6, &data->mfr_iout_max}, + {0xa7, &data->mfr_pout_max}}; + + dev_dbg(&client->dev, "Starting ym2651 update\n"); + data->valid = 0; + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = ym2651y_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + goto exit; + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = ym2651y_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + goto exit; + } + else { + *(regs_word[i].value) = status; + } + } + + /* Read fan_direction */ + command = 0xC3; + status = ym2651y_read_block(client, command, data->fan_dir, + ARRAY_SIZE(data->fan_dir)-1); + data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + /* Read mfr_id */ + command = 0x99; + status = ym2651y_read_block(client, command, data->mfr_id, + ARRAY_SIZE(data->mfr_id)-1); + data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + /* Read mfr_model */ + command = 0x9a; + length = 1; + + /* Read first byte to determine the length of data */ + status = ym2651y_read_block(client, command, &buf, length); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + status = ym2651y_read_block(client, command, data->mfr_model, buf+1); + data->mfr_model[buf+1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + /* Read mfr_revsion */ + command = 0x9b; + status = ym2651y_read_block(client, command, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)-1); + data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init ym2651y_init(void) +{ + return i2c_add_driver(&ym2651y_driver); +} + +static void __exit ym2651y_exit(void) +{ + i2c_del_driver(&ym2651y_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("3Y Power YM-2651Y driver"); +MODULE_LICENSE("GPL"); + +module_init(ym2651y_init); +module_exit(ym2651y_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/service/as5812-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/service/as5812-platform-init.service new file mode 100755 index 000000000000..30c1703dc40f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/service/as5812-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Accton AS5712-54T Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/accton_as5812_54t_util.py install +ExecStop=/usr/local/bin/accton_as5812_54t_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/README b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/README new file mode 100755 index 000000000000..2284eb091fcb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/README @@ -0,0 +1,60 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program is free software: you can redistribute it and/or modify +It under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +To initialize the system, run "accton_as5812_54t_util.py install". +To clean up the drivers & devices, run "accton_as5812_54t_util.py clean". +To dump information of sensors, run "accton_as5812_54t_util.py show". +To dump SFP EEPROM, run "accton_as5812_54t_util.py sff". +To set fan speed, run "accton_as5812_54t_util.py set fan". +To enable/disable SFP emission, run "accton_as5812_54t_util.py set sfp". +To set system LEDs' color, run "accton_as5812_54t_util.py set led" +For more information, run "accton_as5812_54t_util.py --help". + +==================================================================== +Besides applying accton_as5812_54t_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +LED controls can be found under /sys/class/leds. The sysfs interface +color mappings are as follows: +Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + +There are 5 system LEDs, loc, diag, fan, ps1, and ps2. +They are lit automatically by CPLD, but the loc and diag. +The loc led has only 1 color, blue. +The diag one has 3 colors: red, amber, and green. + +Fan controls can be found in /sys/bus/i2c/devices/2-0066. +There are 12 fans inside 6 fan modules. +All fans share 1 duty setting, ranged from 0~100. + +Three temperature sensors are controlled by the lm75 kernel modules. +They should already be visible under /sys/bus/i2c/drivers/lm75/. + +Two power supplies are controlled by the CPLD. +Here provide their status under +/sys/bus/i2c/devices/10-0050 and /sys/bus/i2c/devices/11-0053. + +There are 32 QSFP+ modules are equipped. +Apply "accton_as5812_54t_util.py show" to get their status. +Apply "accton_as5812_54t_util.py set sfp" to turn on/off light transmission. +Apply "accton_as5812_54t_util.py sff" to dump EEPROM information. +Before operating on that QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_54t_util.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_54t_util.py new file mode 100755 index 000000000000..4e9b0795081d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_54t_util.py @@ -0,0 +1,565 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'as5812_54t' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':5,'thermal':3, 'psu':2, 'sfp':6} +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-6 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + self.insmod("accton_i2c_cpld") + self.insmod("cpr_4011_4mxx") + self.insmod("ym2651y") + for m in [ "sfp", "psu", "fan", "leds" ]: + self.insmod("x86-64-accton-as5812-54t-%s" % m) + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_i2c_cpld' , +'modprobe cpr_4011_4mxx' , +'modprobe ym2651y' , +'modprobe x86-64-accton-as5812-54t-sfp' , +'modprobe x86-64-accton-as5812-54t-psu' , +'modprobe x86-64-accton-as5812-54t-fan' , +'modprobe x86-64-accton-as5812-54t-leds' ] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/accton_'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['2-0066'] , + 'thermal': ['15-0048','16-0049', '17-004a'] , + 'psu': ['11-0050','12-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable_all']} + +sfp_map = [4,6,3,5,7,2] + +sfp_1st_index = 48 + +mknod =[ +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo accton_i2c_cpld 0x60 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-15/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-16/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-17/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as5812_54t_psu1 0x38 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5812_54t_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5812_54t_psu2 0x3b > /sys/bus/i2c/devices/i2c-12/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as5812_54t_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device'] + +mknod2 =[ +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo accton_i2c_cpld 0x60 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-15/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-16/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-17/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as5812_54t_psu1 0x38 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5812_54t_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5812_54t_psu2 0x3b > /sys/bus/i2c/devices/i2c-12/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as5812_54t_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device'] + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x71 is exist @ i2c-0 + tmp = "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-0/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x71 > /sys/bus/i2c/devices/i2c-0/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x71 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + for i in range(sfp_1st_index,len(sfp_map)): + status, output =log_os_system("echo sfp"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0071", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(sfp_1st_index,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(sfp_1st_index,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0071", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/fanutil.py new file mode 100644 index 000000000000..73d020acccce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/fanutil.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 3/32/2018: Roy Lee modify for as7326_56x +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 5 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + #FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + #BASE_VAL_PATH = '/sys/bus/i2c/devices/11-0066/{0}' + #FAN_DUTY_PATH = '/sys/bus/i2c/devices/11-0066/fan_duty_cycle_percentage' + BASE_VAL_PATH = '/sys/devices/platform/as6712_32x_fan/{0}' + FAN_DUTY_PATH = '/sys/devices/platform/as6712_32x_fan/fan1_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + #val = ((val + 1 ) * 625 +75 ) / 100 + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/thermalutil.py new file mode 100644 index 000000000000..8fdb01ecc564 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/thermalutil.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# 3/23/2018: Roy Lee modify for as7326_56x +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD + + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['38', '48'], + THERMAL_NUM_2_IDX: ['39', '49'], + THERMAL_NUM_3_IDX: ['40', '4a'], + } + + def __init__(self): + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1): + self._thermal_to_device_path_mapping[x] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/Makefile new file mode 100644 index 000000000000..d052ddaf04e6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/Makefile @@ -0,0 +1,2 @@ +obj-m:= accton_as6712_32x_psu.o accton-as6712-32x-cpld.o \ + accton_as6712_32x_fan.o cpr_4011_4mxx.o leds-accton_as6712_32x.o diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton-as6712-32x-cpld.c b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton-as6712-32x-cpld.c new file mode 100755 index 000000000000..ff350597a718 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton-as6712-32x-cpld.c @@ -0,0 +1,887 @@ +/* + * I2C multiplexer + * + * Copyright (C) 2014 Accton Technology Corporation. + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as6712_32x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define NUM_OF_CPLD1_CHANS 0x0 +#define NUM_OF_CPLD2_CHANS 0x10 +#define NUM_OF_CPLD3_CHANS 0x10 +#define CPLD_CHANNEL_SELECT_REG 0x2 +#define CPLD_DESELECT_CHANNEL 0xFF + +#define ACCTON_I2C_CPLD_MUX_MAX_NCHANS NUM_OF_CPLD3_CHANS + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_mux_type { + as6712_32x_cpld2, + as6712_32x_cpld3, + as6712_32x_cpld1 +}; + +struct as6712_32x_cpld_data { + enum cpld_mux_type type; + struct i2c_client *client; + u8 last_chan; /* last register value */ + struct device *hwmon_dev; + struct mutex update_lock; +}; + +struct chip_desc { + u8 nchans; + u8 deselectChan; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = { + [as6712_32x_cpld1] = { + .nchans = NUM_OF_CPLD1_CHANS, + .deselectChan = NUM_OF_CPLD1_CHANS, + }, + [as6712_32x_cpld2] = { + .nchans = NUM_OF_CPLD2_CHANS, + .deselectChan = NUM_OF_CPLD2_CHANS, + }, + [as6712_32x_cpld3] = { + .nchans = NUM_OF_CPLD3_CHANS, + .deselectChan = NUM_OF_CPLD3_CHANS, + } +}; + +static const struct i2c_device_id as6712_32x_cpld_mux_id[] = { + { "as6712_32x_cpld1", as6712_32x_cpld1 }, + { "as6712_32x_cpld2", as6712_32x_cpld2 }, + { "as6712_32x_cpld3", as6712_32x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as6712_32x_cpld_mux_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as6712_32x_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + /*Reset*/ + TRANSCEIVER_RESET_ATTR_ID(1), + TRANSCEIVER_RESET_ATTR_ID(2), + TRANSCEIVER_RESET_ATTR_ID(3), + TRANSCEIVER_RESET_ATTR_ID(4), + TRANSCEIVER_RESET_ATTR_ID(5), + TRANSCEIVER_RESET_ATTR_ID(6), + TRANSCEIVER_RESET_ATTR_ID(7), + TRANSCEIVER_RESET_ATTR_ID(8), + TRANSCEIVER_RESET_ATTR_ID(9), + TRANSCEIVER_RESET_ATTR_ID(10), + TRANSCEIVER_RESET_ATTR_ID(11), + TRANSCEIVER_RESET_ATTR_ID(12), + TRANSCEIVER_RESET_ATTR_ID(13), + TRANSCEIVER_RESET_ATTR_ID(14), + TRANSCEIVER_RESET_ATTR_ID(15), + TRANSCEIVER_RESET_ATTR_ID(16), + TRANSCEIVER_RESET_ATTR_ID(17), + TRANSCEIVER_RESET_ATTR_ID(18), + TRANSCEIVER_RESET_ATTR_ID(19), + TRANSCEIVER_RESET_ATTR_ID(20), + TRANSCEIVER_RESET_ATTR_ID(21), + TRANSCEIVER_RESET_ATTR_ID(22), + TRANSCEIVER_RESET_ATTR_ID(23), + TRANSCEIVER_RESET_ATTR_ID(24), + TRANSCEIVER_RESET_ATTR_ID(25), + TRANSCEIVER_RESET_ATTR_ID(26), + TRANSCEIVER_RESET_ATTR_ID(27), + TRANSCEIVER_RESET_ATTR_ID(28), + TRANSCEIVER_RESET_ATTR_ID(29), + TRANSCEIVER_RESET_ATTR_ID(30), + TRANSCEIVER_RESET_ATTR_ID(31), + TRANSCEIVER_RESET_ATTR_ID(32), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_status(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as6712_32x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as6712_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR|S_IRUGO, show_status, set_status, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); + +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(32); + + +static struct attribute *as6712_32x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as6712_32x_cpld1_group = { + .attrs = as6712_32x_cpld1_attributes, +}; + +static struct attribute *as6712_32x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_RESET_ATTR(1), + DECLARE_TRANSCEIVER_RESET_ATTR(2), + DECLARE_TRANSCEIVER_RESET_ATTR(3), + DECLARE_TRANSCEIVER_RESET_ATTR(4), + DECLARE_TRANSCEIVER_RESET_ATTR(5), + DECLARE_TRANSCEIVER_RESET_ATTR(6), + DECLARE_TRANSCEIVER_RESET_ATTR(7), + DECLARE_TRANSCEIVER_RESET_ATTR(8), + DECLARE_TRANSCEIVER_RESET_ATTR(9), + DECLARE_TRANSCEIVER_RESET_ATTR(10), + DECLARE_TRANSCEIVER_RESET_ATTR(11), + DECLARE_TRANSCEIVER_RESET_ATTR(12), + DECLARE_TRANSCEIVER_RESET_ATTR(13), + DECLARE_TRANSCEIVER_RESET_ATTR(14), + DECLARE_TRANSCEIVER_RESET_ATTR(15), + DECLARE_TRANSCEIVER_RESET_ATTR(16), + NULL +}; + +static const struct attribute_group as6712_32x_cpld2_group = { + .attrs = as6712_32x_cpld2_attributes, +}; + +static struct attribute *as6712_32x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_RESET_ATTR(17), + DECLARE_TRANSCEIVER_RESET_ATTR(18), + DECLARE_TRANSCEIVER_RESET_ATTR(19), + DECLARE_TRANSCEIVER_RESET_ATTR(20), + DECLARE_TRANSCEIVER_RESET_ATTR(21), + DECLARE_TRANSCEIVER_RESET_ATTR(22), + DECLARE_TRANSCEIVER_RESET_ATTR(23), + DECLARE_TRANSCEIVER_RESET_ATTR(24), + DECLARE_TRANSCEIVER_RESET_ATTR(25), + DECLARE_TRANSCEIVER_RESET_ATTR(26), + DECLARE_TRANSCEIVER_RESET_ATTR(27), + DECLARE_TRANSCEIVER_RESET_ATTR(28), + DECLARE_TRANSCEIVER_RESET_ATTR(29), + DECLARE_TRANSCEIVER_RESET_ATTR(30), + DECLARE_TRANSCEIVER_RESET_ATTR(31), + DECLARE_TRANSCEIVER_RESET_ATTR(32), + NULL +}; + +static const struct attribute_group as6712_32x_cpld3_group = { + .attrs = as6712_32x_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[2] = {0}; + u8 regs[] = {0xA, 0xB}; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as6712_32x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 32 in order */ + return sprintf(buf, "%.2x %.2x\n", values[0], values[1]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_status(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + + int status = 0; + u8 reg = 0, mask = 0; + u32 val, para; + + if (sscanf(buf, "%d", ¶) != 1) { + return -EINVAL; + } + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_32: + reg = 0x4 + (((attr->index - MODULE_PRESENT_1)/8)%2); + mask = 0x1 << ((attr->index - MODULE_PRESENT_1)%8); + break; + default: + return 0; + } + + mutex_lock(&data->update_lock); + status = as6712_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + val = status & ~mask; + if (!para) { /*0 means reset*/ + val |= mask; + } + status = as6712_32x_cpld_write_internal(client, reg, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_RESET_1 ... MODULE_RESET_32: + reg = 0x4 + (((attr->index - MODULE_PRESENT_1)/8)%2); + mask = 0x1 << ((attr->index - MODULE_PRESENT_1)%8); + break; + default: + return 0; + } + + mutex_lock(&data->update_lock); + status = as6712_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as6712_32x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int as6712_32x_cpld_mux_reg_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 val) +{ + unsigned long orig_jiffies; + unsigned short flags; + union i2c_smbus_data data; + int try; + s32 res = -EIO; + + data.byte = val; + flags = client->flags; + flags &= I2C_M_TEN | I2C_CLIENT_PEC; + + if (adap->algo->smbus_xfer) { + /* Retry automatically on arbitration loss */ + orig_jiffies = jiffies; + for (res = 0, try = 0; try <= adap->retries; try++) { + res = adap->algo->smbus_xfer(adap, client->addr, flags, + I2C_SMBUS_WRITE, CPLD_CHANNEL_SELECT_REG, + I2C_SMBUS_BYTE_DATA, &data); + if (res != -EAGAIN) + break; + if (time_after(jiffies, + orig_jiffies + adap->timeout)) + break; + } + } + + return res; +} + +static int as6712_32x_cpld_mux_select_chan(struct i2c_mux_core *muxc, + u32 chan) +{ + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + u8 regval; + int ret = 0; + regval = chan; + + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) { + ret = as6712_32x_cpld_mux_reg_write(muxc->parent, client, regval); + data->last_chan = regval; + } + + return ret; +} + +static int as6712_32x_cpld_mux_deselect_mux(struct i2c_mux_core *muxc, + u32 chan) +{ + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + + /* Deselect active channel */ + data->last_chan = chips[data->type].deselectChan; + + return as6712_32x_cpld_mux_reg_write(muxc->parent, client, data->last_chan); +} + +static void as6712_32x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as6712_32x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as6712_32x_cpld_mux_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + int force, class; + struct i2c_mux_core *muxc; + struct as6712_32x_cpld_data *data; + int chan = 0; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + return -ENODEV; + + muxc = i2c_mux_alloc(adap, &client->dev, + chips[id->driver_data].nchans, + sizeof(*data), 0, + as6712_32x_cpld_mux_select_chan, + as6712_32x_cpld_mux_deselect_mux); + if (!muxc) + return -ENOMEM; + + i2c_set_clientdata(client, muxc); + data = i2c_mux_priv(muxc); + data->client = client; + mutex_init(&data->update_lock); + + if (data->type == as6712_32x_cpld2 || data->type == as6712_32x_cpld3) { + data->type = id->driver_data; + data->last_chan = chips[data->type].deselectChan; /* force the first selection */ + + /* Now create an adapter for each channel */ + for (chan = 0; chan < chips[data->type].nchans; chan++) { + force = 0; /* dynamic adap number */ + class = 0; /* no class by default */ + + ret = i2c_mux_add_adapter(muxc, force, chan, class); + + if (ret) { + ret = -ENODEV; + dev_err(&client->dev, "failed to register multiplexed adapter %d\n", chan); + goto exit_mux_register; + } + } + + dev_info(&client->dev, "registered %d multiplexed busses for I2C mux %s\n", + chan, client->name); + } + + /* Register sysfs hooks */ + switch (data->type) { + case as6712_32x_cpld1: + group = &as6712_32x_cpld1_group; + break; + case as6712_32x_cpld2: + group = &as6712_32x_cpld2_group; + break; + case as6712_32x_cpld3: + group = &as6712_32x_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_mux_register; + } + } + + if (chips[data->type].nchans) { + dev_info(&client->dev, + "registered %d multiplexed busses for I2C %s\n", + chan, client->name); + } + else { + dev_info(&client->dev, + "device %s registered\n", client->name); + } + + as6712_32x_cpld_add_client(client); + + return 0; + +exit_mux_register: + i2c_mux_del_adapters(muxc); + kfree(data); + return ret; +} + +static int as6712_32x_cpld_mux_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + const struct attribute_group *group = NULL; + + as6712_32x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as6712_32x_cpld1: + group = &as6712_32x_cpld1_group; + break; + case as6712_32x_cpld2: + group = &as6712_32x_cpld2_group; + break; + case as6712_32x_cpld3: + group = &as6712_32x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + i2c_mux_del_adapters(muxc); + + return 0; +} + +static int as6712_32x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as6712_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as6712_32x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as6712_32x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as6712_32x_cpld_read); + +int as6712_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as6712_32x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as6712_32x_cpld_write); + +static struct i2c_driver as6712_32x_cpld_mux_driver = { + .driver = { + .name = "as6712_32x_cpld", + .owner = THIS_MODULE, + }, + .probe = as6712_32x_cpld_mux_probe, + .remove = as6712_32x_cpld_mux_remove, + .id_table = as6712_32x_cpld_mux_id, +}; + +static int __init as6712_32x_cpld_mux_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as6712_32x_cpld_mux_driver); +} + +static void __exit as6712_32x_cpld_mux_exit(void) +{ + i2c_del_driver(&as6712_32x_cpld_mux_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton as6712-32x CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as6712_32x_cpld_mux_init); +module_exit(as6712_32x_cpld_mux_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton_as6712_32x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton_as6712_32x_fan.c new file mode 100644 index 000000000000..7033d8b75687 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton_as6712_32x_fan.c @@ -0,0 +1,463 @@ +/* + * A hwmon driver for the Accton as6712 32x fan contrl + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as6712_32x_fan" + +#define FAN_MAX_NUMBER 5 +#define FAN_SPEED_CPLD_TO_RPM_STEP 150 +#define FAN_SPEED_PRECENT_TO_CPLD_STEP 5 +#define FAN_DUTY_CYCLE_MIN 0 /* 10% ??*/ +#define FAN_DUTY_CYCLE_MAX 100 /* 100% */ + +#define CPLD_REG_FAN_STATUS_OFFSET 0xC +#define CPLD_REG_FANR_STATUS_OFFSET 0x17 +#define CPLD_REG_FAN_DIRECTION_OFFSET 0x1E + +#define CPLD_FAN1_REG_SPEED_OFFSET 0x10 +#define CPLD_FAN2_REG_SPEED_OFFSET 0x11 +#define CPLD_FAN3_REG_SPEED_OFFSET 0x12 +#define CPLD_FAN4_REG_SPEED_OFFSET 0x13 +#define CPLD_FAN5_REG_SPEED_OFFSET 0x14 + +#define CPLD_FANR1_REG_SPEED_OFFSET 0x18 +#define CPLD_FANR2_REG_SPEED_OFFSET 0x19 +#define CPLD_FANR3_REG_SPEED_OFFSET 0x1A +#define CPLD_FANR4_REG_SPEED_OFFSET 0x1B +#define CPLD_FANR5_REG_SPEED_OFFSET 0x1C + +#define CPLD_REG_FAN_PWM_CYCLE_OFFSET 0xD + +#define CPLD_FAN1_INFO_BIT_MASK 0x1 +#define CPLD_FAN2_INFO_BIT_MASK 0x2 +#define CPLD_FAN3_INFO_BIT_MASK 0x4 +#define CPLD_FAN4_INFO_BIT_MASK 0x8 +#define CPLD_FAN5_INFO_BIT_MASK 0x10 + +#define PROJECT_NAME + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(format, ...) printk(format, __VA_ARGS__) +#else + #define DEBUG_PRINT(format, ...) +#endif + +static struct accton_as6712_32x_fan *fan_data = NULL; + +struct accton_as6712_32x_fan { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[FAN_MAX_NUMBER]; /* inner first fan status */ + u32 speed[FAN_MAX_NUMBER]; /* inner first fan speed */ + u8 direction[FAN_MAX_NUMBER]; /* reconrd the direction of inner first and second fans */ + u32 duty_cycle[FAN_MAX_NUMBER]; /* control the speed of inner first and second fans */ + u8 r_status[FAN_MAX_NUMBER]; /* inner second fan status */ + u32 r_speed[FAN_MAX_NUMBER]; /* inner second fan speed */ +}; + +/*******************/ +#define MAKE_FAN_MASK_OR_REG(name,type) \ + CPLD_FAN##type##1_##name, \ + CPLD_FAN##type##2_##name, \ + CPLD_FAN##type##3_##name, \ + CPLD_FAN##type##4_##name, \ + CPLD_FAN##type##5_##name, + +/* fan related data + */ +static const u8 fan_info_mask[] = { + MAKE_FAN_MASK_OR_REG(INFO_BIT_MASK,) +}; + +static const u8 fan_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,) +}; + +static const u8 fanr_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,R) +}; + +/*******************/ +#define DEF_FAN_SET(id) \ + FAN##id##_FAULT, \ + FAN##id##_SPEED, \ + FAN##id##_DUTY_CYCLE, \ + FAN##id##_DIRECTION, \ + FANR##id##_FAULT, \ + FANR##id##_SPEED, + +enum sysfs_fan_attributes { + DEF_FAN_SET(1) + DEF_FAN_SET(2) + DEF_FAN_SET(3) + DEF_FAN_SET(4) + DEF_FAN_SET(5) +}; +/*******************/ +static void accton_as6712_32x_fan_update_device(struct device *dev); +static int accton_as6712_32x_fan_read_value(u8 reg); +static int accton_as6712_32x_fan_write_value(u8 reg, u8 value); + +static ssize_t fan_set_duty_cycle(struct device *dev, + struct device_attribute *da,const char *buf, size_t count); +static ssize_t fan_show_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t show_name(struct device *dev, + struct device_attribute *da, char *buf); + +extern int as6712_32x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as6712_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + + +/*******************/ +#define _MAKE_SENSOR_DEVICE_ATTR(prj, id, id2) \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, \ + fan_set_duty_cycle, FAN##id##_DUTY_CYCLE); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_direction, S_IRUGO, fan_show_value, NULL, FAN##id##_DIRECTION); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_fault, S_IRUGO, fan_show_value, NULL, FANR##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_input, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id2##_input, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fan##id2##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT); + +#define MAKE_SENSOR_DEVICE_ATTR(prj,id, id2) _MAKE_SENSOR_DEVICE_ATTR(prj,id, id2) + +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME ,1 ,11) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME ,2 ,12) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME ,3 ,13) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME ,4 ,14) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME ,5 ,15) + +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); +/*******************/ + +#define _MAKE_FAN_ATTR(prj, id, id2) \ + &sensor_dev_attr_##prj##fan##id##_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_duty_cycle_percentage.dev_attr.attr,\ + &sensor_dev_attr_##prj##fan##id##_direction.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_input.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id2##_input.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id2##_fault.dev_attr.attr, + + +#define MAKE_FAN_ATTR(prj, id, id2) _MAKE_FAN_ATTR(prj, id, id2) + +static struct attribute *accton_as6712_32x_fan_attributes[] = { + /* fan related attributes */ + MAKE_FAN_ATTR(PROJECT_NAME,1 ,11) + MAKE_FAN_ATTR(PROJECT_NAME,2 ,12) + MAKE_FAN_ATTR(PROJECT_NAME,3 ,13) + MAKE_FAN_ATTR(PROJECT_NAME,4 ,14) + MAKE_FAN_ATTR(PROJECT_NAME,5 ,15) + &sensor_dev_attr_name.dev_attr.attr, + NULL +}; +/*******************/ + +/* fan related functions + */ +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + ssize_t ret = 0; + int data_index, type_index; + + accton_as6712_32x_fan_update_device(dev); + + if (fan_data->valid == 0) { + return ret; + } + + type_index = attr->index%FAN2_FAULT; + data_index = attr->index/FAN2_FAULT; + + switch (type_index) { + case FAN1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->status[data_index]); + DEBUG_PRINT("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->speed[data_index]); + DEBUG_PRINT("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DUTY_CYCLE: + ret = sprintf(buf, "%d\n", fan_data->duty_cycle[data_index]); + DEBUG_PRINT("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DIRECTION: + ret = sprintf(buf, "%d\n", fan_data->direction[data_index]); /* presnet, need to modify*/ + DEBUG_PRINT("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->r_status[data_index]); + DEBUG_PRINT("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->r_speed[data_index]); + DEBUG_PRINT("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + default: + DEBUG_PRINT("[Check !!][%s][%d] \n", __FUNCTION__, __LINE__); + break; + } + + return ret; +} + +static ssize_t show_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + return sprintf(buf, "%s\n", DRVNAME); +} +/*******************/ +static ssize_t fan_set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { + + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < FAN_DUTY_CYCLE_MIN || value > FAN_DUTY_CYCLE_MAX) + return -EINVAL; + + accton_as6712_32x_fan_write_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET, value/FAN_SPEED_PRECENT_TO_CPLD_STEP); + + fan_data->valid = 0; + + return count; +} + +static const struct attribute_group accton_as6712_32x_fan_group = { + .attrs = accton_as6712_32x_fan_attributes, +}; + +static int accton_as6712_32x_fan_read_value(u8 reg) +{ + return as6712_32x_cpld_read(0x60, reg); +} + +static int accton_as6712_32x_fan_write_value(u8 reg, u8 value) +{ + return as6712_32x_cpld_write(0x60, reg, value); +} + +static void accton_as6712_32x_fan_update_device(struct device *dev) +{ + int speed, r_speed, fault, r_fault, direction, ctrl_speed; + int i; + int retry_count; + + mutex_lock(&fan_data->update_lock); + + DEBUG_PRINT("Starting accton_as6712_32x_fan update \n"); + + if (!(time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) || !fan_data->valid)) { + /* do nothing */ + goto _exit; + } + + fan_data->valid = 0; + + DEBUG_PRINT("Starting accton_as6712_32x_fan update 2 \n"); + + fault = accton_as6712_32x_fan_read_value(CPLD_REG_FAN_STATUS_OFFSET); + r_fault = accton_as6712_32x_fan_read_value(CPLD_REG_FANR_STATUS_OFFSET); + direction = accton_as6712_32x_fan_read_value(CPLD_REG_FAN_DIRECTION_OFFSET); + ctrl_speed = accton_as6712_32x_fan_read_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET); + + if ( (fault < 0) || (r_fault < 0) || (ctrl_speed < 0) ) + { + DEBUG_PRINT("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + + DEBUG_PRINT("[fan:] fault:%d, r_fault=%d, ctrl_speed=%d \n",fault, r_fault, ctrl_speed); + + for (i = 0; i < FAN_MAX_NUMBER; i++) + { + /* Update fan data + */ + + /* fan fault + * 0: normal, 1:abnormal + * Each FAN-tray module has two fans. + */ + fan_data->status[i] = (fault & fan_info_mask[i]) >> i; + DEBUG_PRINT("[fan%d:] fail=%d \n",i, fan_data->status[i]); + + fan_data->r_status[i] = (r_fault & fan_info_mask[i]) >> i; + fan_data->direction[i] = (direction & fan_info_mask[i]) >> i; + fan_data->duty_cycle[i] = ctrl_speed * FAN_SPEED_PRECENT_TO_CPLD_STEP; + + /* fan speed + */ + speed = 0; + r_speed = 0; + retry_count = 3; + while (retry_count) { + retry_count--; + speed = accton_as6712_32x_fan_read_value(fan_speed_reg[i]); + r_speed = accton_as6712_32x_fan_read_value(fanr_speed_reg[i]); + if ( (speed < 0) || (r_speed < 0) ) + { + DEBUG_PRINT("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + if ( (speed == 0) || (r_speed == 0) ) + { + msleep(50); + continue; + } + break; + } + + DEBUG_PRINT("[fan%d:] speed:%d, r_speed=%d \n", i, speed, r_speed); + + fan_data->speed[i] = speed * FAN_SPEED_CPLD_TO_RPM_STEP; + fan_data->r_speed[i] = r_speed * FAN_SPEED_CPLD_TO_RPM_STEP; + } + + /* finish to update */ + fan_data->last_updated = jiffies; + fan_data->valid = 1; + +_exit: + mutex_unlock(&fan_data->update_lock); +} + +static int accton_as6712_32x_fan_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &accton_as6712_32x_fan_group); + if (status) { + goto exit; + + } + + fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(fan_data->hwmon_dev)) { + status = PTR_ERR(fan_data->hwmon_dev); + goto exit_remove; + } + + dev_info(&pdev->dev, "accton_as6712_32x_fan\n"); + + return 0; + +exit_remove: + sysfs_remove_group(&pdev->dev.kobj, &accton_as6712_32x_fan_group); +exit: + return status; +} + +static int accton_as6712_32x_fan_remove(struct platform_device *pdev) +{ + hwmon_device_unregister(fan_data->hwmon_dev); + sysfs_remove_group(&fan_data->pdev->dev.kobj, &accton_as6712_32x_fan_group); + + return 0; +} + + + +static struct platform_driver accton_as6712_32x_fan_driver = { + .probe = accton_as6712_32x_fan_probe, + .remove = accton_as6712_32x_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as6712_32x_fan_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as6712_32x_fan_driver); + if (ret < 0) { + goto exit; + } + + fan_data = kzalloc(sizeof(struct accton_as6712_32x_fan), GFP_KERNEL); + if (!fan_data) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as6712_32x_fan_driver); + goto exit; + } + + mutex_init(&fan_data->update_lock); + fan_data->valid = 0; + + fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(fan_data->pdev)) { + ret = PTR_ERR(fan_data->pdev); + platform_driver_unregister(&accton_as6712_32x_fan_driver); + kfree(fan_data); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as6712_32x_fan_exit(void) +{ + platform_device_unregister(fan_data->pdev); + platform_driver_unregister(&accton_as6712_32x_fan_driver); + kfree(fan_data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as6712_32x_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_as6712_32x_fan_init); +module_exit(accton_as6712_32x_fan_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton_as6712_32x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton_as6712_32x_psu.c new file mode 100644 index 000000000000..5b9eda261489 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton_as6712_32x_psu.c @@ -0,0 +1,364 @@ +/* + * An hwmon driver for accton as6712_32x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +static ssize_t show_index(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as6712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as6712_32x_cpld_read(unsigned short cpld_addr, u8 reg); +static int as6712_32x_psu_model_name_get(struct device *dev); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as6712_32x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[14]; /* Model name, read from eeprom */ +}; + +static struct as6712_32x_psu_data *as6712_32x_psu_update_device(struct device *dev); + +enum as6712_32x_psu_sysfs_attributes { + PSU_INDEX, + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_index, S_IRUGO, show_index, NULL, PSU_INDEX); +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as6712_32x_psu_attributes[] = { + &sensor_dev_attr_psu_index.dev_attr.attr, + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_index(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as6712_32x_psu_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", data->index); +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as6712_32x_psu_data *data = as6712_32x_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as6712_32x_psu_data *data = as6712_32x_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!IS_PRESENT(data->index, data->status)) { + return 0; + } + + if (as6712_32x_psu_model_name_get(dev) < 0) { + return -ENXIO; + } + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as6712_32x_psu_group = { + .attrs = as6712_32x_psu_attributes, +}; + +static int as6712_32x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as6712_32x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as6712_32x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as6712_32x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as6712_32x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as6712_32x_psu_remove(struct i2c_client *client) +{ + struct as6712_32x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as6712_32x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as6712_32x_psu1, + as6712_32x_psu2 +}; + +static const struct i2c_device_id as6712_32x_psu_id[] = { + { "as6712_32x_psu1", as6712_32x_psu1 }, + { "as6712_32x_psu2", as6712_32x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as6712_32x_psu_id); + +static struct i2c_driver as6712_32x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as6712_32x_psu", + }, + .probe = as6712_32x_psu_probe, + .remove = as6712_32x_psu_remove, + .id_table = as6712_32x_psu_id, + .address_list = normal_i2c, +}; + +static int as6712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +enum psu_type { + PSU_YM_2401_JCR, /* AC110V - F2B */ + PSU_YM_2401_JDR, /* AC110V - B2F */ + PSU_CPR_4011_4M11, /* AC110V - F2B */ + PSU_CPR_4011_4M21, /* AC110V - B2F */ + PSU_CPR_6011_2M11, /* AC110V - F2B */ + PSU_CPR_6011_2M21, /* AC110V - B2F */ + PSU_UM400D_01G, /* DC48V - F2B */ + PSU_UM400D01_01G /* DC48V - B2F */ +}; + +struct model_name_info { + enum psu_type type; + u8 offset; + u8 length; + char* model_name; +}; + +struct model_name_info models[] = { +{PSU_YM_2401_JCR, 0x20, 11, "YM-2401JCR"}, +{PSU_YM_2401_JDR, 0x20, 11, "YM-2401JDR"}, +{PSU_CPR_4011_4M11, 0x26, 13, "CPR-4011-4M11"}, +{PSU_CPR_4011_4M21, 0x26, 13, "CPR-4011-4M21"}, +{PSU_CPR_6011_2M11, 0x26, 13, "CPR-6011-2M11"}, +{PSU_CPR_6011_2M21, 0x26, 13, "CPR-6011-2M21"}, +{PSU_UM400D_01G, 0x50, 9, "um400d01G"}, +{PSU_UM400D01_01G, 0x50, 12, "um400d01-01G"}, +}; + +static int as6712_32x_psu_model_name_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as6712_32x_psu_data *data = i2c_get_clientdata(client); + int i, status; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + memset(data->model_name, 0, sizeof(data->model_name)); + + status = as6712_32x_psu_read_block(client, models[i].offset, + data->model_name, models[i].length); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x%x)\n", + client->addr, models[i].offset); + return status; + } + else { + data->model_name[models[i].length] = '\0'; + } + + if (i == PSU_YM_2401_JCR || i == PSU_YM_2401_JDR) { + /* Skip the meaningless data byte 8*/ + data->model_name[8] = data->model_name[9]; + data->model_name[9] = data->model_name[10]; + data->model_name[10] = '\0'; + } + + /* Determine if the model name is known, if not, read next index + */ + if (strncmp(data->model_name, models[i].model_name, models[i].length) == 0) { + return 0; + } + else { + data->model_name[0] = '\0'; + } + } + + return -ENODATA; +} +static struct as6712_32x_psu_data *as6712_32x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as6712_32x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + + dev_dbg(&client->dev, "Starting as6812_32x update\n"); + data->valid = 0; + + /* Read psu status */ + status = as6712_32x_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as6712_32x_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as6712_32x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/cpr_4011_4mxx.c b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/cpr_4011_4mxx.c new file mode 100644 index 000000000000..15cef4ef50d7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/cpr_4011_4mxx.c @@ -0,0 +1,439 @@ +/* + * An hwmon driver for the CPR-4011-4Mxx Redundant Power Module + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x3c, 0x3d, 0x3e, 0x3f, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct cpr_4011_4mxx_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[2]; /* Register value */ + u8 fan_fault; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u16 fan_speed[2]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value); +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev); + +enum cpr_4011_4mxx_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_P_IN_UV, + PSU_P_OUT_UV, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); + +/*Duplicate nodes for lm-sensors. 1 for input, 2 for output.*/ +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_linear, NULL, PSU_P_IN_UV); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); + + + + + +static struct attribute *cpr_4011_4mxx_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan1_fault.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + cpr_4011_4mxx_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN_UV: + multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/ + /*Passing through*/ + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT_UV: + multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/ + /*Passing through*/ + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static const struct attribute_group cpr_4011_4mxx_group = { + .attrs = cpr_4011_4mxx_attributes, +}; + +static int cpr_4011_4mxx_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct cpr_4011_4mxx_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct cpr_4011_4mxx_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpr_4011_4mxx_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int cpr_4011_4mxx_remove(struct i2c_client *client) +{ + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id cpr_4011_4mxx_id[] = { + { "cpr_4011_4mxx", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpr_4011_4mxx_id); + +static struct i2c_driver cpr_4011_4mxx_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "cpr_4011_4mxx", + }, + .probe = cpr_4011_4mxx_probe, + .remove = cpr_4011_4mxx_remove, + .id_table = cpr_4011_4mxx_id, + .address_list = normal_i2c, +}; + +static int cpr_4011_4mxx_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int cpr_4011_4mxx_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + struct reg_data_byte regs_byte[] = { {0x20, &data->vout_mode}, + {0x81, &data->fan_fault}}; + struct reg_data_word regs_word[] = { {0x96, &data->p_out}, /*p_out must be the first one.*/ + {0x97, &data->p_in}, + {0x8b, &data->v_out}, + {0x89, &data->i_in}, + {0x8c, &data->i_out}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &(data->fan_speed[0])}, + {0x91, &(data->fan_speed[1])}}; + + dev_dbg(&client->dev, "Starting cpr_4011_4mxx update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = cpr_4011_4mxx_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + *(regs_byte[i].value) = 0; + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = cpr_4011_4mxx_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + *(regs_word[i].value) = 0; + } + else { + *(regs_word[i].value) = status; + } + + /*Elimated false values. so p_out must be updated at first. */ + if (data->p_out == 0) { + *(regs_word[i].value) = 0; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init cpr_4011_4mxx_init(void) +{ + return i2c_add_driver(&cpr_4011_4mxx_driver); +} + +static void __exit cpr_4011_4mxx_exit(void) +{ + i2c_del_driver(&cpr_4011_4mxx_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("CPR_4011_4MXX driver"); +MODULE_LICENSE("GPL"); + +module_init(cpr_4011_4mxx_init); +module_exit(cpr_4011_4mxx_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/leds-accton_as6712_32x.c b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/leds-accton_as6712_32x.c new file mode 100644 index 000000000000..2b45bc8777c8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/leds-accton_as6712_32x.c @@ -0,0 +1,612 @@ +/* + * A LED driver for the accton_as6712_32x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include + +extern int as6712_32x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as6712_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "as6712_32x_led" + +struct accton_as6712_32x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[4]; /* Register value, 0 = LOC/DIAG/FAN LED + 1 = PSU1/PSU2 LED + 2 = FAN1-4 LED + 3 = FAN5-6 LED */ +}; + +static struct accton_as6712_32x_led_data *ledctl = NULL; + +/* LED related data + */ +#define LED_TYPE_PSU1_REG_MASK 0x03 +#define LED_MODE_PSU1_GREEN_MASK 0x02 +#define LED_MODE_PSU1_AMBER_MASK 0x01 +#define LED_MODE_PSU1_OFF_MASK 0x03 +#define LED_MODE_PSU1_AUTO_MASK 0x00 + +#define LED_TYPE_PSU2_REG_MASK 0x0C +#define LED_MODE_PSU2_GREEN_MASK 0x08 +#define LED_MODE_PSU2_AMBER_MASK 0x04 +#define LED_MODE_PSU2_OFF_MASK 0x0C +#define LED_MODE_PSU2_AUTO_MASK 0x00 + +#define LED_TYPE_DIAG_REG_MASK 0x0C +#define LED_MODE_DIAG_GREEN_MASK 0x08 +#define LED_MODE_DIAG_AMBER_MASK 0x04 +#define LED_MODE_DIAG_OFF_MASK 0x0C +#define LED_MODE_DIAG_BLINK_MASK 0x48 + +#define LED_TYPE_FAN_REG_MASK 0x03 +#define LED_MODE_FAN_GREEN_MASK 0x02 +#define LED_MODE_FAN_AMBER_MASK 0x01 +#define LED_MODE_FAN_OFF_MASK 0x03 +#define LED_MODE_FAN_AUTO_MASK 0x00 + +#define LED_TYPE_FAN1_REG_MASK 0x03 +#define LED_TYPE_FAN2_REG_MASK 0xC0 +#define LED_TYPE_FAN3_REG_MASK 0x30 +#define LED_TYPE_FAN4_REG_MASK 0x0C +#define LED_TYPE_FAN5_REG_MASK 0x03 + +#define LED_MODE_FANX_GREEN_MASK 0x01 +#define LED_MODE_FANX_RED_MASK 0x02 +#define LED_MODE_FANX_OFF_MASK 0x00 + +#define LED_TYPE_LOC_REG_MASK 0x30 +#define LED_MODE_LOC_ON_MASK 0x00 +#define LED_MODE_LOC_OFF_MASK 0x10 +#define LED_MODE_LOC_BLINK_MASK 0x20 + +static const u8 led_reg[] = { + 0xA, /* LOC/DIAG/FAN LED*/ + 0xB, /* PSU1/PSU2 LED */ + 0xE, /* FAN2-5 LED */ + 0xF, /* FAN1 LED */ +}; + +enum led_type { + LED_TYPE_PSU1, + LED_TYPE_PSU2, + LED_TYPE_DIAG, + LED_TYPE_FAN, + LED_TYPE_FAN1, + LED_TYPE_FAN2, + LED_TYPE_FAN3, + LED_TYPE_FAN4, + LED_TYPE_FAN5, + LED_TYPE_LOC +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_AMBER, + LED_MODE_RED, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_RED_BLINK, + LED_MODE_AUTO, +}; + +struct led_type_mode { + enum led_type type; + int type_mask; + enum led_light_mode mode; + int mode_mask; +}; + +struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU1_GREEN_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU1_AMBER_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU1_AUTO_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_OFF, LED_MODE_PSU1_OFF_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU2_GREEN_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU2_AMBER_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU2_AUTO_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_OFF, LED_MODE_PSU2_OFF_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_GREEN, LED_MODE_FAN_GREEN_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AMBER, LED_MODE_FAN_AMBER_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AUTO, LED_MODE_FAN_AUTO_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_OFF, LED_MODE_FAN_OFF_MASK}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 6}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 6}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 6}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 4}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 2}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 2}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 2}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_GREEN, LED_MODE_DIAG_GREEN_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_AMBER, LED_MODE_DIAG_AMBER_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_OFF, LED_MODE_DIAG_OFF_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_GREEN_BLINK, LED_MODE_DIAG_BLINK_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER, LED_MODE_LOC_ON_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_OFF, LED_MODE_LOC_OFF_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER_BLINK, LED_MODE_LOC_BLINK_MASK} +}; + + +struct fanx_info_s { + u8 cname; /* device name */ + enum led_type type; + u8 reg_id; /* map to led_reg & reg_val */ +}; + +static struct fanx_info_s fanx_info[] = { + {'1', LED_TYPE_FAN1, 3}, + {'2', LED_TYPE_FAN2, 2}, + {'3', LED_TYPE_FAN3, 2}, + {'4', LED_TYPE_FAN4, 2}, + {'5', LED_TYPE_FAN5, 2}, +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if (type == LED_TYPE_DIAG) + { /* special case : bit 6 - meaning blinking */ + if (0x40 & reg_val) + return LED_MODE_GREEN_BLINK; + } + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_mask) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + if (type == LED_TYPE_DIAG) + { + if (mode == LED_MODE_GREEN_BLINK) + { /* special case : bit 6 - meaning blinking */ + reg_val = 0x48 | (reg_val & ~0x4C); + break; + } + else + { /* for diag led, other case must cancel bit 6 first */ + reg_val = reg_val & ~0x40; + } + } + reg_val = led_type_mode_data[i].mode_mask | + (reg_val & (~led_type_mode_data[i].type_mask)); + break; + } + + return reg_val; +} + +static int accton_as6712_32x_led_read_value(u8 reg) +{ + return as6712_32x_cpld_read(0x60, reg); +} + +static int accton_as6712_32x_led_write_value(u8 reg, u8 value) +{ + return as6712_32x_cpld_write(0x60, reg, value); +} + +static void accton_as6712_32x_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as6712_32x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as6712_32x_led_read_value(led_reg[i]); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as6712_32x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + + reg_val = accton_as6712_32x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as6712_32x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as6712_32x_led_psu_1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as6712_32x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1); +} + +static enum led_brightness accton_as6712_32x_led_psu_1_get(struct led_classdev *cdev) +{ + accton_as6712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void accton_as6712_32x_led_psu_2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as6712_32x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2); +} + +static enum led_brightness accton_as6712_32x_led_psu_2_get(struct led_classdev *cdev) +{ + accton_as6712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static void accton_as6712_32x_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as6712_32x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_FAN); +} + +static enum led_brightness accton_as6712_32x_led_fan_get(struct led_classdev *cdev) +{ + accton_as6712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + + +static void accton_as6712_32x_led_fanx_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (led_cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as6712_32x_led_set(led_cdev, led_light_mode, led_reg[reg_id], led_type1); + return; + } + } +} + + +static enum led_brightness accton_as6712_32x_led_fanx_get(struct led_classdev *cdev) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as6712_32x_led_update(); + return led_reg_val_to_light_mode(led_type1, ledctl->reg_val[reg_id]); + } + } + + + return led_reg_val_to_light_mode(LED_TYPE_FAN1, ledctl->reg_val[2]); +} + + +static void accton_as6712_32x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as6712_32x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} + +static enum led_brightness accton_as6712_32x_led_diag_get(struct led_classdev *cdev) +{ + accton_as6712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as6712_32x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as6712_32x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static enum led_brightness accton_as6712_32x_led_loc_get(struct led_classdev *cdev) +{ + accton_as6712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static struct led_classdev accton_as6712_32x_leds[] = { + [LED_TYPE_PSU1] = { + .name = "accton_as6712_32x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_psu_1_set, + .brightness_get = accton_as6712_32x_led_psu_1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as6712_32x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_psu_2_set, + .brightness_get = accton_as6712_32x_led_psu_2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "accton_as6712_32x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_fan_set, + .brightness_get = accton_as6712_32x_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN1] = { + .name = "accton_as6712_32x_led::fan1", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_fanx_set, + .brightness_get = accton_as6712_32x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN2] = { + .name = "accton_as6712_32x_led::fan2", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_fanx_set, + .brightness_get = accton_as6712_32x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN3] = { + .name = "accton_as6712_32x_led::fan3", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_fanx_set, + .brightness_get = accton_as6712_32x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN4] = { + .name = "accton_as6712_32x_led::fan4", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_fanx_set, + .brightness_get = accton_as6712_32x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN5] = { + .name = "accton_as6712_32x_led::fan5", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_fanx_set, + .brightness_get = accton_as6712_32x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_DIAG] = { + .name = "accton_as6712_32x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_diag_set, + .brightness_get = accton_as6712_32x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_LOC] = { + .name = "accton_as6712_32x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_loc_set, + .brightness_get = accton_as6712_32x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as6712_32x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as6712_32x_leds); i++) { + led_classdev_suspend(&accton_as6712_32x_leds[i]); + } + + return 0; +} + +static int accton_as6712_32x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as6712_32x_leds); i++) { + led_classdev_resume(&accton_as6712_32x_leds[i]); + } + + return 0; +} + +static int accton_as6712_32x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as6712_32x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as6712_32x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as6712_32x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as6712_32x_leds[i]); + } + } + + return ret; +} + +static int accton_as6712_32x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as6712_32x_leds); i++) { + led_classdev_unregister(&accton_as6712_32x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as6712_32x_led_driver = { + .probe = accton_as6712_32x_led_probe, + .remove = accton_as6712_32x_led_remove, + .suspend = accton_as6712_32x_led_suspend, + .resume = accton_as6712_32x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as6712_32x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as6712_32x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as6712_32x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as6712_32x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as6712_32x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as6712_32x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as6712_32x_led_driver); + kfree(ledctl); +} + +module_init(accton_as6712_32x_led_init); +module_exit(accton_as6712_32x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as6712_32x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/service/as6712-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/service/as6712-platform-init.service new file mode 100644 index 000000000000..ffdd6e1cee74 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/service/as6712-platform-init.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS6712-32X Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as6712_util.py install +ExecStart=/usr/local/bin/accton_as6712_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/setup.py new file mode 100644 index 000000000000..114b0837be69 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as6712_32x', + version='1.0', + description='Module to initialize Accton AS6712-32X platforms', + + packages=['as6712_32x'], + package_dir={'as6712_32x': 'as6712-32x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/README new file mode 100644 index 000000000000..bfa90e6b68e1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/README @@ -0,0 +1,74 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program is free software: you can redistribute it and/or modify +It under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + module - Contains source code of as6712 kernel driver modules. + util - operational scripts. + +Sonic creates a docker container and run building process under it. +If user tries to built new drivers, please get into that docker and +dpkg-buildpackage for them. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS6712-32X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers can be built to individual ko during dpkg-buildpackage. +2. A operational script, accton_as6712_util.py, for device initializatian. + Run "accton_as6712_util.py install" to install drivers. + +To initialize the system, run "accton_as6712_util.py install". +To clean up the drivers & devices, run "accton_as6712_util.py clean". +To dump information of sensors, run "accton_as6712_util.py show". +To dump SFP EEPROM, run "accton_as6712_util.py sff". +To set fan speed, run "accton_as6712_util.py set fan". +To enable/disable SFP emission, run "accton_as6712_util.py set sfp". +To set system LEDs' color, run "accton_as6712_util.py set led" +For more information, run "accton_as6712_util.py --help". + +==================================================================== +Besides applying accton_as6712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 32 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/accton_as6712_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/accton_as6712_monitor.py new file mode 100755 index 000000000000..fbcc74565d62 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/accton_as6712_monitor.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 4/10/2018: Roy Lee modify for as6712_32x +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + from as6712_32x.fanutil import FanUtil + from as6712_32x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as6712_monitor' + +global log_file +global log_level + +# (LM75_1+ LM75_2+ LM75_3) is LM75 at i2c addresses 0x48, 0x49, and 0x4A. +# TMP = (LM75_1+ LM75_2+ LM75_3)/3 +#1. If TMP < 35, All fans run with duty 30%. +#2. If TMP>=35 or the temperature of any one of fan is higher than 40, +# All fans run with duty 50% +#3. If TMP >= 40 or the temperature of any one of fan is higher than 45, +# All fans run with duty 65%. +#4. If TMP >= 45 or the temperature of any one of fan is higher than 50, +# All fans run with duty 100%. +#5. Any one of 5 fans is fault, set duty = 100%. +#6. Direction factor. If it is B2F direction, duty + 10%. + + # MISC: + # 1.Check single LM75 before applied average. + # 2.If no matched fan speed is found from the policy, + # use FAN_DUTY_CYCLE_MIN as default speed + # Get current temperature + # 4.Decision 3: Decide new fan speed depend on fan direction/current fan speed/temperature + + + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as6712_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + max_duty = 100 + fan_policy_f2b = { + 0: [30, 0, 105000], + 1: [50, 105000, 120000], + 2: [65, 120000, 135000], + 3: [max_duty, 135000, sys.maxsize], + } + fan_policy_b2f = { + 0: [40, 0, 105000], + 1: [60, 105000, 120000], + 2: [75, 120000, 135000], + 3: [max_duty, 135000, sys.maxsize], + } + fan_policy_single = { + 0: 40000, + 1: 45000, + 2: 50000, + } + + thermal = ThermalUtil() + fan = FanUtil() + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_status = fan.get_fan_status(x) + if fan_status is None: + logging.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', max_duty, x) + return False + if fan_status is False: + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', max_duty, x) + fan.set_fan_duty_cycle(max_duty) + return True + #logging.debug('INFO. fan_status is True (fan_num:%d)', x) + + fan_dir=fan.get_fan_dir(1) + if fan_dir == 0: + fan_policy = fan_policy_f2b + else: + fan_policy = fan_policy_b2f + + #Decide fan duty by if any of sensors > fan_policy_single. + new_duty_cycle = fan_policy[0][0] + for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): + single_thm = thermal._get_thermal_node_val(x) + for y in range(0, len(fan_policy_single)): + if single_thm > fan_policy_single[y]: + if fan_policy[y+1][0] > new_duty_cycle: + new_duty_cycle = fan_policy[y+1][0] + logging.debug('INFO. Single thermal sensor %d with temp %d > %d , new_duty_cycle=%d', + x, single_thm, fan_policy_single[y], new_duty_cycle) + single_result = new_duty_cycle + + + #Find if current duty matched any of define duty. + #If not, set it to highest one. + cur_duty_cycle = fan.get_fan_duty_cycle() + for x in range(0, len(fan_policy)): + if cur_duty_cycle == fan_policy[x][0]: + break + if x == len(fan_policy) : + fan.set_fan_duty_cycle(fan_policy[0][0]) + cur_duty_cycle = max_duty + + #Decide fan duty by if sum of sensors falls into any of fan_policy{} + get_temp = thermal.get_thermal_temp() + new_duty_cycle = cur_duty_cycle + for x in range(0, len(fan_policy)): + y = len(fan_policy) - x -1 #checked from highest + if get_temp > fan_policy[y][1] and get_temp <= fan_policy[y][2] : + new_duty_cycle= fan_policy[y][0] + logging.debug('INFO. Sum of temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy[y][1], new_duty_cycle) + + sum_result = new_duty_cycle + if (sum_result>single_result): + new_duty_cycle = sum_result; + else: + new_duty_cycle = single_result + + logging.debug('INFO. Final duty_cycle=%d', new_duty_cycle) + if(new_duty_cycle != cur_duty_cycle): + fan.set_fan_duty_cycle(new_duty_cycle) + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + monitor = accton_as6712_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/accton_as6712_util.py b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/accton_as6712_util.py new file mode 100755 index 000000000000..a77841857e6c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/accton_as6712_util.py @@ -0,0 +1,627 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Description: +# Due to adoption of optoe drivers, sideband signals of SFPs are moved +# into cpld drivers. Add a new dict, cpld_of_module, for mapping this +# attributes to corresponding cpld nodes. +# + + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +PROJECT_NAME = 'as6712_32x' +version = '0.2.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':4, 'psu':2, 'sfp':32} + + +led_prefix ='/sys/devices/platform/as6712_32x_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as6712_32x_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan1_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan2_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan3_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan4_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan5_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'thermal': ['38-0048','39-0049', '40-004a', '41-004b'] , + 'psu': ['35-0038','36-003b'], + 'sfp': ['-0050']} +i2c_nodes = { + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_', 'sfp_tx_disable']} + +sfp_map = [ 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33 + ] + +#For sideband signals of SFP/QSFP modules. +bus_of_cpld = [0, 1] +cpld_of_module = {'-0062': list(range(0,16)), + '-0064': list(range(16,32)) } + + +mknod =[ +'echo as6712_32x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as6712_32x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as6712_32x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', + +# PSU-1 +'echo as6712_32x_psu1 0x38 > /sys/bus/i2c/devices/i2c-35/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-35/new_device', +#'echo as6712_32x_psu1 0x50 > /sys/bus/i2c/devices/i2c-35/new_device', +#'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-35/new_device', + +# PSU-2 +'echo as6712_32x_psu2 0x3b > /sys/bus/i2c/devices/i2c-36/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-36/new_device', +#'echo as6712_32x_psu2 0x53 > /sys/bus/i2c/devices/i2c-36/new_device', +#'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-36/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-38/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-39/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-40/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-41/new_device', +] + +mknod2 =[ +'echo as6712_32x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as6712_32x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as6712_32x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', + +# PSU-1 +'echo as6712_32x_psu1 0x38 > /sys/bus/i2c/devices/i2c-35/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-35/new_device', +#'echo as6712_32x_psu1 0x50 > /sys/bus/i2c/devices/i2c-35/new_device', +#'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-35/new_device', + +# PSU-2 +'echo as6712_32x_psu2 0x3b > /sys/bus/i2c/devices/i2c-36/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-36/new_device', +#'echo as6712_32x_psu2 0x53 > /sys/bus/i2c/devices/i2c-36/new_device', +#'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-36/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-38/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-39/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-40/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-41/new_device', +] + +FORCE = 0 + + + +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(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + + + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x', +'modprobe optoe', +'modprobe accton_as6712_32x_cpld', +'modprobe cpr_4011_4mxx', +#'modprobe ym2651y', +'modprobe accton_as6712_32x_fan', +'modprobe leds-accton_as6712_32x', +'modprobe accton_as6712_32x_psu'] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +def cpld_bus_check(): + tmp = "i2cget -y -f 0 0x60" + status, output = log_os_system(tmp, 0) + if status: + return 1 + else: + return 0 + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x70 is exist @ i2c-0 + tmp = "echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x70 > /sys/bus/i2c/devices/i2c-1/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + # if 0x76 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca932x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca932x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/0-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_inserted() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + order = cpld_bus_check() + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + for lk in cpld_of_module: + if k in cpld_of_module[lk]: + bus = bus_of_cpld[order] + node = key+str(k+1) + path = i2c_prefix + str(bus) + lk + "/"+ nodes[j] + str(k+1) + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/fanutil.py new file mode 100755 index 000000000000..207436c1fc96 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/fanutil.py @@ -0,0 +1,255 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 2/27/2018: Roy Lee modify for as7312_54x +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + #FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + #BASE_VAL_PATH = '/sys/devices/platform/as5712_54x_fan/{0}' + BASE_VAL_PATH = '/sys/bus/i2c/devices/2-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/2-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + #val = ((val + 1 ) * 625 +75 ) / 100 + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/thermalutil.py new file mode 100755 index 000000000000..68f0ef900df6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/thermalutil.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# 2/27/2018: Roy Lee modify for as7312_54x +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD + + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['3', '48'], + THERMAL_NUM_2_IDX: ['3', '49'], + THERMAL_NUM_3_IDX: ['3', '4a'], + } + + def __init__(self): + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1): + self._thermal_to_device_path_mapping[x] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/Makefile new file mode 100755 index 000000000000..488fdb321cac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/Makefile @@ -0,0 +1,17 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_i2c_cpld.o \ + accton_as7312_54x_fan.o accton_as7312_54x_leds.o \ + accton_as7312_54x_psu.o ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +$(error KERNEL_SRC is not defined) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_fan.c new file mode 100755 index 000000000000..8764ec8a3176 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_fan.c @@ -0,0 +1,815 @@ +/* + * A hwmon driver for the Accton as7312 54x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7312_54x_fan" + +#define NUM_THERMAL_SENSORS (3) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a} + +#define IN +#define OUT + +static struct as7312_54x_fan_data *as7312_54x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_enable(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7312_54x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + u8 enable; + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index##_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr, \ + &sensor_dev_attr_pwm##index##_enable.dev_attr.attr + +#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ + static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr + + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); +/* System temperature for fancontrol */ +DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR(); + +static struct attribute *as7312_54x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + DECLARE_FAN_SYSTEM_TEMP_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7312_54x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7312_54x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as7312_54x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct as7312_54x_fan_data *data = as7312_54x_fan_update_device(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + data->enable = value; + if (value == 0) + { + return set_duty_cycle(dev, da, buf, FAN_MAX_DUTY_CYCLE); + } + return count; +} + + +static ssize_t get_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7312_54x_fan_data *data = as7312_54x_fan_update_device(dev); + + return sprintf(buf, "%u\n", data->enable); +} +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0) + return -EINVAL; + + value = (value > FAN_MAX_DUTY_CYCLE)? FAN_MAX_DUTY_CYCLE : value; + + as7312_54x_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as7312_54x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +/* Due to this struct is declared at lm75.c, it cannot be include + * under Sonic environment. I duplicate it from lm75.c. + */ +struct lm75_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct thermal_zone_device *tz; + struct mutex update_lock; + u8 orig_conf; + u8 resolution; /* In bits, between 9 and 12 */ + u8 resolution_limits; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long sample_time; /* In jiffies */ + s16 temp[3]; /* Register values, + 0 = input + 1 = max + 2 = hyst */ +}; + +/*Copied from lm75.c*/ +static inline long lm75_reg_to_mc(s16 temp, u8 resolution) +{ + return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); +} + +/*Get hwmon_dev from i2c_client, set hwmon_dev = NULL is failed.*/ +static struct device * get_hwmon_dev( + struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if(data) + { + if( data->valid == 1 && data->hwmon_dev) + { + return data->hwmon_dev; + } + + } + return NULL; +} + +/* To find hwmon index by opening hwmon under that i2c address. + */ +static int find_hwmon_index_by_FileOpen( + int bus_nr, + unsigned short addr, + OUT int *index) +{ +#define MAX_HWMON_DEVICE (10) /* Find hwmon device in 0~10*/ + struct file *sfd; + char client_name[96]; + int i=0; + + do { + snprintf(client_name, sizeof(client_name), + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + + sfd = filp_open(client_name, O_RDONLY, 0); + i++; + } while( IS_ERR(sfd) && i < MAX_HWMON_DEVICE); + + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", client_name, __LINE__); + return -ENOENT; + } + filp_close(sfd, 0); + *index = i - 1; + return 0; + +#undef MAX_HWMON_DEVICE +} + +static int get_temp_file_path( + int bus_nr, unsigned short addr, + struct device *hwmon_dev + ,char *path, int max_len) +{ + + if(hwmon_dev && strlen(dev_name(hwmon_dev))) + { + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/%s/temp1_input", + bus_nr, addr, dev_name(hwmon_dev)); + } + else + { + int i=0; + if(find_hwmon_index_by_FileOpen( bus_nr, addr, &i)) + { + return -EIO; + } + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + } + return 0; +} + +/*File read the dev file at user space.*/ +static int read_devfile_temp1_input( + struct device *dev, + int bus_nr, + unsigned short addr, + struct device *hwmon_dev, + int *miniCelsius) +{ + struct file *sfd; + char buffer[96]; + char devfile[96]; + int rc, status; + int rdlen, value; + mm_segment_t old_fs; + + rc = 0; + get_temp_file_path(bus_nr, addr, hwmon_dev, devfile, sizeof(devfile)); + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", devfile, __LINE__); + return -ENOENT; + } + dev_dbg(dev, "Found device:%s\n",devfile); + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + pr_err("file %s cann't readable ?\n",devfile); + return -ENOENT; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + pr_err( "File(%s) empty!\n", devfile); + rc = -EIO; + goto exit; + } + status = sscanf(buffer, "%d", &value); + if (status != 1) { + rc = -EIO; + goto exit; + } + *miniCelsius = value; + dev_dbg(dev,"found sensors: %d @i2c %d-%04x\n", value, bus_nr, addr); + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + return rc; +} + +static u8 is_lm75_data_due(struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if (time_after(jiffies, data->last_updated + data->sample_time)) + { + return 1; + } + return 0; +} +static int get_lm75_temp(struct i2c_client *client, int *miniCelsius) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + *miniCelsius = lm75_reg_to_mc(data->temp[0], data->resolution); + + return 0; +} + +static bool lm75_addr_mached(unsigned short addr) +{ + int i; + unsigned short addrs[] = THERMAL_SENSORS_ADDRS; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) + { + if( addr == addrs[i]) + return 1; + } + return 0; +} + +static int _find_lm75_device(struct device *dev, void *data) +{ + struct device_driver *driver; + struct as7312_54x_fan_data *prv = data; + char *driver_name = THERMAL_SENSORS_DRIVER; + + driver = dev->driver; + if (driver && driver->name && + strcmp(driver->name, driver_name) == 0) + { + struct i2c_client *client; + client = to_i2c_client(dev); + if (client) + { + /*cannot use "struct i2c_adapter *adap = to_i2c_adapter(dev);"*/ + struct i2c_adapter *adap = client->adapter; + int miniCelsius = 0; + + if (! lm75_addr_mached(client->addr)) + { + return 0; + } + + if (!adap) { + return -ENXIO; + } + + /* If the data is not updated, read them from devfile + to drive them updateing data from chip.*/ + if (is_lm75_data_due(client)) + { + struct device *hwmon_dev; + + hwmon_dev = get_hwmon_dev(client); + if(0 == read_devfile_temp1_input(dev, adap->nr, + client->addr, hwmon_dev, &miniCelsius)) + { + prv->system_temp += miniCelsius; + prv->sensors_found++; + } + + } + else + { + get_lm75_temp(client, &miniCelsius); + prv->system_temp += miniCelsius; + prv->sensors_found++; + + } + } + } + return 0; +} + +/*Find all lm75 devices and return sum of temperatures.*/ +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + ssize_t ret = 0; + struct as7312_54x_fan_data *data = as7312_54x_fan_update_device(dev); + + data->system_temp=0; + data->sensors_found=0; + i2c_for_each_dev(data, _find_lm75_device); + if (NUM_THERMAL_SENSORS != data->sensors_found) + { + dev_dbg(dev,"only %d of %d temps are found\n", + data->sensors_found, NUM_THERMAL_SENSORS); + data->system_temp = INT_MAX; + } + ret = sprintf(buf, "%d\n",data->system_temp); + return ret; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7312_54x_fan_data *data = as7312_54x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7312_54x_fan_group = { + .attrs = as7312_54x_fan_attributes, +}; + +static struct as7312_54x_fan_data *as7312_54x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7312_54x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7312_54x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7312_54x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7312_54x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7312_54x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->enable = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7312_54x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7312_54x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7312_54x_fan_remove(struct i2c_client *client) +{ + struct as7312_54x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7312_54x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7312_54x_fan_id[] = { + { "as7312_54x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7312_54x_fan_id); + +static struct i2c_driver as7312_54x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7312_54x_fan_probe, + .remove = as7312_54x_fan_remove, + .id_table = as7312_54x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7312_54x_fan_init(void) +{ + return i2c_add_driver(&as7312_54x_fan_driver); +} + +static void __exit as7312_54x_fan_exit(void) +{ + i2c_del_driver(&as7312_54x_fan_driver); +} + +module_init(as7312_54x_fan_init); +module_exit(as7312_54x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7312_54x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_leds.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_leds.c new file mode 100644 index 000000000000..1d54517c6243 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_leds.c @@ -0,0 +1,438 @@ +/* + * A LED driver for the accton_as7312_54x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as7312_54x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as7312_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "accton_as7312_54x_led" + +struct accton_as7312_54x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct accton_as7312_54x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as7312_54x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as7312_54x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7312_54x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = accton_as7312_54x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as7312_54x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as7312_54x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7312_54x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as7312_54x_led_diag_get(struct led_classdev *cdev) +{ + accton_as7312_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as7312_54x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7312_54x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_as7312_54x_led_loc_get(struct led_classdev *cdev) +{ + accton_as7312_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_as7312_54x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_as7312_54x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev accton_as7312_54x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_as7312_54x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_diag_set, + .brightness_get = accton_as7312_54x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "accton_as7312_54x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_loc_set, + .brightness_get = accton_as7312_54x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "accton_as7312_54x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_auto_set, + .brightness_get = accton_as7312_54x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "accton_as7312_54x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_auto_set, + .brightness_get = accton_as7312_54x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as7312_54x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_auto_set, + .brightness_get = accton_as7312_54x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as7312_54x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7312_54x_leds); i++) { + led_classdev_suspend(&accton_as7312_54x_leds[i]); + } + + return 0; +} + +static int accton_as7312_54x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7312_54x_leds); i++) { + led_classdev_resume(&accton_as7312_54x_leds[i]); + } + + return 0; +} + +static int accton_as7312_54x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as7312_54x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as7312_54x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as7312_54x_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as7312_54x_leds[i]); + } + } + + return ret; +} + +static int accton_as7312_54x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as7312_54x_leds); i++) { + led_classdev_unregister(&accton_as7312_54x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as7312_54x_led_driver = { + .probe = accton_as7312_54x_led_probe, + .remove = accton_as7312_54x_led_remove, + .suspend = accton_as7312_54x_led_suspend, + .resume = accton_as7312_54x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as7312_54x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as7312_54x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as7312_54x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as7312_54x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as7312_54x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as7312_54x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as7312_54x_led_driver); + kfree(ledctl); +} + +module_init(accton_as7312_54x_led_init); +module_exit(accton_as7312_54x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7312_54x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_psu.c new file mode 100644 index 000000000000..4646224ef903 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_psu.c @@ -0,0 +1,277 @@ +/* + * An hwmon driver for accton as7312_54x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as7312_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7312_54x_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7312_54x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[9]; /* Model name, read from eeprom */ +}; + +static struct as7312_54x_psu_data *as7312_54x_psu_update_device(struct device *dev); + +enum as7312_54x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as7312_54x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7312_54x_psu_data *data = as7312_54x_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7312_54x_psu_data *data = as7312_54x_psu_update_device(dev); + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as7312_54x_psu_group = { + .attrs = as7312_54x_psu_attributes, +}; + +static int as7312_54x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7312_54x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7312_54x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7312_54x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7312_54x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7312_54x_psu_remove(struct i2c_client *client) +{ + struct as7312_54x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7312_54x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7312_54x_psu1, + as7312_54x_psu2 +}; + +static const struct i2c_device_id as7312_54x_psu_id[] = { + { "as7312_54x_psu1", as7312_54x_psu1 }, + { "as7312_54x_psu2", as7312_54x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7312_54x_psu_id); + +static struct i2c_driver as7312_54x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7312_54x_psu", + }, + .probe = as7312_54x_psu_probe, + .remove = as7312_54x_psu_remove, + .id_table = as7312_54x_psu_id, + .address_list = normal_i2c, +}; + +static int as7312_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as7312_54x_psu_data *as7312_54x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as7312_54x update\n"); + + /* Read psu status */ + status = as7312_54x_cpld_read(0x60, 0x2); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as7312_54x_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as7312_54x_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7312_54x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_sfp.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_sfp.c new file mode 100644 index 000000000000..921d9f892cac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_sfp.c @@ -0,0 +1,1972 @@ +/* + * SFP driver for accton as7312_54x sfp + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "as7312_54x_sfp" /* Platform dependent */ + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) +#define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else +#define DEBUG_PRINT(fmt, args...) +#endif + +#define NUM_OF_PORT 54 +#define SFP_PORT_MAX 48 +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +#define MULTIPAGE_SUPPORT 1 + +#if (MULTIPAGE_SUPPORT == 1) +/* fundamental unit of addressing for SFF_8472/SFF_8436 */ +#define SFF_8436_PAGE_SIZE 128 +/* + * The current 8436 (QSFP) spec provides for only 4 supported + * pages (pages 0-3). + * This driver is prepared to support more, but needs a register in the + * EEPROM to indicate how many pages are supported before it is safe + * to implement more pages in the driver. + */ +#define SFF_8436_SPECED_PAGES 4 +#define SFF_8436_EEPROM_SIZE ((1 + SFF_8436_SPECED_PAGES) * SFF_8436_PAGE_SIZE) +#define SFF_8436_EEPROM_UNPAGED_SIZE (2 * SFF_8436_PAGE_SIZE) +/* + * The current 8472 (SFP) spec provides for only 3 supported + * pages (pages 0-2). + * This driver is prepared to support more, but needs a register in the + * EEPROM to indicate how many pages are supported before it is safe + * to implement more pages in the driver. + */ +#define SFF_8472_SPECED_PAGES 3 +#define SFF_8472_EEPROM_SIZE ((3 + SFF_8472_SPECED_PAGES) * SFF_8436_PAGE_SIZE) +#define SFF_8472_EEPROM_UNPAGED_SIZE (4 * SFF_8436_PAGE_SIZE) + +/* a few constants to find our way around the EEPROM */ +#define SFF_8436_PAGE_SELECT_REG 0x7F +#define SFF_8436_PAGEABLE_REG 0x02 +#define SFF_8436_NOT_PAGEABLE (1<<2) +#define SFF_8472_PAGEABLE_REG 0x40 +#define SFF_8472_PAGEABLE (1<<4) + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = SFF_8436_PAGE_SIZE; + +/* + * specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; + +typedef enum qsfp_opcode { + QSFP_READ_OP = 0, + QSFP_WRITE_OP = 1 +} qsfp_opcode_e; +#endif + +/* Platform dependent +++ */ +#define I2C_ADDR_CPLD1 0x60 +#define I2C_ADDR_CPLD2 0x62 +#define I2C_ADDR_CPLD3 0x64 + +#define CPLD3_OFFSET_QSFP_MOD_RST 0x17 +/* Platform dependent --- */ +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL, + SFP_MOD_RST +}; + +/* SFP/QSFP common attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); + +/* QSFP attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); +static SENSOR_DEVICE_ATTR(sfp_mod_rst, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, SFP_MOD_RST); + +static struct attribute *qsfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, + &sensor_dev_attr_sfp_mod_rst.dev_attr.attr, + NULL +}; + +/* SFP msa attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); +static struct attribute *sfp_msa_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + NULL +}; + +/* Platform dependent +++ */ +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { + as7312_54x_port1, as7312_54x_port2, as7312_54x_port3, as7312_54x_port4, + as7312_54x_port5, as7312_54x_port6, as7312_54x_port7, as7312_54x_port8, + as7312_54x_port9, as7312_54x_port10, as7312_54x_port11, as7312_54x_port12, + as7312_54x_port13, as7312_54x_port14, as7312_54x_port15, as7312_54x_port16, + as7312_54x_port17, as7312_54x_port18, as7312_54x_port19, as7312_54x_port20, + as7312_54x_port21, as7312_54x_port22, as7312_54x_port23, as7312_54x_port24, + as7312_54x_port25, as7312_54x_port26, as7312_54x_port27, as7312_54x_port28, + as7312_54x_port29, as7312_54x_port30, as7312_54x_port31, as7312_54x_port32, + as7312_54x_port33, as7312_54x_port34, as7312_54x_port35, as7312_54x_port36, + as7312_54x_port37, as7312_54x_port38, as7312_54x_port39, as7312_54x_port40, + as7312_54x_port41, as7312_54x_port42, as7312_54x_port43, as7312_54x_port44, + as7312_54x_port45, as7312_54x_port46, as7312_54x_port47, as7312_54x_port48, + as7312_54x_port49, as7312_54x_port52, as7312_54x_port50, as7312_54x_port53, + as7312_54x_port51, as7312_54x_port54 +}; + +#define I2C_DEV_ID(x) { #x, x} + +static const struct i2c_device_id sfp_device_id[] = { + I2C_DEV_ID(as7312_54x_port1), + I2C_DEV_ID(as7312_54x_port2), + I2C_DEV_ID(as7312_54x_port3), + I2C_DEV_ID(as7312_54x_port4), + I2C_DEV_ID(as7312_54x_port5), + I2C_DEV_ID(as7312_54x_port6), + I2C_DEV_ID(as7312_54x_port7), + I2C_DEV_ID(as7312_54x_port8), + I2C_DEV_ID(as7312_54x_port9), + I2C_DEV_ID(as7312_54x_port10), + I2C_DEV_ID(as7312_54x_port11), + I2C_DEV_ID(as7312_54x_port12), + I2C_DEV_ID(as7312_54x_port13), + I2C_DEV_ID(as7312_54x_port14), + I2C_DEV_ID(as7312_54x_port15), + I2C_DEV_ID(as7312_54x_port16), + I2C_DEV_ID(as7312_54x_port17), + I2C_DEV_ID(as7312_54x_port18), + I2C_DEV_ID(as7312_54x_port19), + I2C_DEV_ID(as7312_54x_port20), + I2C_DEV_ID(as7312_54x_port21), + I2C_DEV_ID(as7312_54x_port22), + I2C_DEV_ID(as7312_54x_port23), + I2C_DEV_ID(as7312_54x_port24), + I2C_DEV_ID(as7312_54x_port25), + I2C_DEV_ID(as7312_54x_port26), + I2C_DEV_ID(as7312_54x_port27), + I2C_DEV_ID(as7312_54x_port28), + I2C_DEV_ID(as7312_54x_port29), + I2C_DEV_ID(as7312_54x_port30), + I2C_DEV_ID(as7312_54x_port31), + I2C_DEV_ID(as7312_54x_port32), + I2C_DEV_ID(as7312_54x_port33), + I2C_DEV_ID(as7312_54x_port34), + I2C_DEV_ID(as7312_54x_port35), + I2C_DEV_ID(as7312_54x_port36), + I2C_DEV_ID(as7312_54x_port37), + I2C_DEV_ID(as7312_54x_port38), + I2C_DEV_ID(as7312_54x_port39), + I2C_DEV_ID(as7312_54x_port40), + I2C_DEV_ID(as7312_54x_port41), + I2C_DEV_ID(as7312_54x_port42), + I2C_DEV_ID(as7312_54x_port43), + I2C_DEV_ID(as7312_54x_port44), + I2C_DEV_ID(as7312_54x_port45), + I2C_DEV_ID(as7312_54x_port46), + I2C_DEV_ID(as7312_54x_port47), + I2C_DEV_ID(as7312_54x_port48), + I2C_DEV_ID(as7312_54x_port49), + I2C_DEV_ID(as7312_54x_port50), + I2C_DEV_ID(as7312_54x_port51), + I2C_DEV_ID(as7312_54x_port52), + I2C_DEV_ID(as7312_54x_port53), + I2C_DEV_ID(as7312_54x_port54), + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); +/* Platform dependent --- */ + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[6]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss + 3 => device id + 4 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 5 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +#if (MULTIPAGE_SUPPORT == 1) + struct i2c_client *ddm_client; /* dummy client instance for 0xA2 */ +#endif +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct qsfp_data *qsfp; + + struct i2c_client *client; +#if (MULTIPAGE_SUPPORT == 1) + int use_smbus; + u8 *writebuf; + unsigned write_max; +#endif +}; + +#if (MULTIPAGE_SUPPORT == 1) +static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, + char *buf, loff_t off, size_t len, qsfp_opcode_e opcode); +#endif +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + +/* Platform dependent +++ */ +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + int i = 0, j = 0, status = -1; + u8 reg; + unsigned short cpld_addr; + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + data->present = 0; + + /* Read present status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + cpld_addr = I2C_ADDR_CPLD2 + i*2; + reg = 0x9+j; + status = accton_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%lx\r\n", data->present); + data->present |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* Read present status of port 49-52(QSFP port) */ + cpld_addr = I2C_ADDR_CPLD2; + reg = 0x18; + status = accton_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + else { + data->present |= (u64)(status & 0xF) << SFP_PORT_MAX; + } + + /* Read present status of port 53-54(QSFP port) */ + cpld_addr = I2C_ADDR_CPLD3; + reg = 0x18; + status = accton_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + else { + data->present |= (u64)(status & 0x3) << 52; + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static struct sfp_port_data* sfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0, j = 0; + int status = -1; + + if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { + return data; + } + + DEBUG_PRINT("Starting as7312_54x sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->msa->valid = 0; + memset(data->msa->status, 0, sizeof(data->msa->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 9; j++) { + u8 reg; + unsigned short cpld_addr; + reg = 0xc+j; + cpld_addr = I2C_ADDR_CPLD2 + i*2; + + status = accton_i2c_cpld_read(cpld_addr, reg); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + + data->msa->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + data->msa->valid = 1; + data->msa->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + unsigned short cpld_addr = 0; + u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; + long disable; + int error; + + if (data->driver_type == DRIVER_TYPE_QSFP) { + return qsfp_set_tx_disable(dev, da, buf, count); + } + + error = kstrtol(buf, 10, &disable); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + if(data->port < 24) { + cpld_addr = I2C_ADDR_CPLD2; + cpld_reg = 0xF + data->port / 8; + cpld_bit = 1 << (data->port % 8); + } + else { /* port 24 ~ 48 */ + cpld_addr = I2C_ADDR_CPLD3; + cpld_reg = 0xF + (data->port - 24) / 8; + cpld_bit = 1 << (data->port % 8); + } + + /* Read current status */ + cpld_val = accton_i2c_cpld_read(cpld_addr, cpld_reg); + + /* Update tx_disable status */ + if (disable) { + data->msa->status[1] |= BIT_INDEX(data->port); + cpld_val |= cpld_bit; + } + else { + data->msa->status[1] &= ~BIT_INDEX(data->port); + cpld_val &= ~cpld_bit; + } + + accton_i2c_cpld_write(cpld_addr, cpld_reg, cpld_val); + mutex_unlock(&data->update_lock); + return count; +} + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + data = sfp_update_present(client); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + return (data->present & BIT_INDEX(data->port)) ? 0 : 1; /* Platform dependent */ +} + +/* Platform dependent +++ */ +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if (PRESENT_ALL == attr->index) { + int i; + u8 values[7] = {0}; + struct sfp_port_data *data = sfp_update_present(client); + + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = ~(u8)(data->present >> (i * 8)); + } + + /* Return values 1 -> 54 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5], + values[6] & 0x3F); + } + else { + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + /* PRESENT */ + return sprintf(buf, "%d\n", present); + } +} +/* Platform dependent --- */ + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + DEBUG_PRINT("Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + goto exit; + } + } + msleep(200); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + int port_bit; + int status = -EINVAL; + u8 cpld_addr[] = {I2C_ADDR_CPLD2, I2C_ADDR_CPLD3}; + + /* Low power mode is not supported for SFP ports(1-48) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + mutex_lock(&data->update_lock); + + port_bit = data->port - SFP_PORT_MAX; + cpld_val = accton_i2c_cpld_read(cpld_addr[port_bit/4], CPLD3_OFFSET_QSFP_MOD_RST); + + pr_err("[ROY]%s#%d, %x from %x\n", __func__, __LINE__, cpld_val, cpld_addr[port_bit/4]); + + cpld_val = cpld_val & 0x0F; + cpld_val = cpld_val & BIT_INDEX(port_bit%4); + + pr_err("[ROY]%s#%d, %x of bit %d\n", __func__, __LINE__, cpld_val, port_bit); + + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", cpld_val>>(port_bit%4)); + + mutex_unlock(&data->update_lock); + + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + long reset; + int error, port_bit; + u8 cpld_addr[] = {I2C_ADDR_CPLD2, I2C_ADDR_CPLD3}; + + pr_err("[ROY]%s#%d, port:%d\n", __func__, __LINE__, data->port); + + /* Tx disable is not supported for QSFP ports(49-54) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + port_bit = data->port - SFP_PORT_MAX; + error = kstrtol(buf, 10, &reset); + + pr_err("[ROY]%s#%d, %s == %d\n", __func__, __LINE__, buf, error); + if (error) { + return error; + } + mutex_lock(&data->update_lock); + + cpld_val = accton_i2c_cpld_read(cpld_addr[port_bit/4], CPLD3_OFFSET_QSFP_MOD_RST); + pr_err("[ROY]%s#%d, %x\n", __func__, __LINE__, cpld_val); + /* Update lp_mode status */ + if (reset) + { + cpld_val |= BIT_INDEX(port_bit%4); + } + else + { + cpld_val &= ~BIT_INDEX(port_bit%4); + } + pr_err("[ROY]%s#%d, %x to %x\n", __func__, __LINE__, cpld_val, cpld_addr[port_bit/4]); + + accton_i2c_cpld_write(cpld_addr[port_bit/4], CPLD3_OFFSET_QSFP_MOD_RST, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + int present; + u8 val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENXIO; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + switch (attr->index) { + case TX_FAULT: + val = !!(data->qsfp->status[2] & 0xF); + break; + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); + break; + case TX_DISABLE: + val = data->qsfp->status[1] & 0xF; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); + break; + case RX_LOS: + val = !!(data->qsfp->status[0] & 0xF); + break; + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); + break; + default: + break; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (!status) { + /* port is not present */ + return -ENXIO; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + mutex_lock(&data->update_lock); + + if (attr->index == TX_DISABLE) { + if (disable) { + data->qsfp->status[1] |= 0xF; + } + else { + data->qsfp->status[1] &= ~0xF; + } + } + else {/* TX_DISABLE1 ~ TX_DISABLE4*/ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + if (unlikely(status < 0)) { + count = status; + } + + mutex_unlock(&data->update_lock); + return count; +} + +/* Platform dependent +++ */ +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (data->driver_type == DRIVER_TYPE_QSFP) { + return qsfp_show_tx_rx_status(dev, da, buf); + } + + data = sfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + if(attr->index == RX_LOS_ALL) { + int i = 0; + u8 values[6] = {0}; + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = (u8)(data->msa->status[2] >> (i * 8)); + } + + /** Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5]); + } + + switch (attr->index) { + case TX_FAULT: + index = 0; + break; + case TX_DISABLE: + index = 1; + break; + case RX_LOS: + index = 2; + break; + default: + return 0; + } + + val = (data->msa->status[index] & BIT_INDEX(data->port)) ? 1 : 0; + return sprintf(buf, "%d\n", val); +} +/* Platform dependent --- */ +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return data_len; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, command, *data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return 1; +#endif + + +} + +#if (MULTIPAGE_SUPPORT == 0) +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} +#endif + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + +#if (MULTIPAGE_SUPPORT == 1) + return sfp_port_read_write(data, buf, off, count, QSFP_WRITE_OP); +#else + return sfp_port_write(data, buf, off, count); +#endif +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + goto abort; + } + if (unlikely(status != data_len)) { + status = -EIO; + goto abort; + } + + //result = data_len; + +abort: + return status; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); + goto abort; + } + + *data = (u8)status; + status = 1; + +abort: + return status; +#endif +} + +#if (MULTIPAGE_SUPPORT == 1) +/*-------------------------------------------------------------------------*/ +/* + * This routine computes the addressing information to be used for + * a given r/w request. + * + * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), + * the page, and the offset. + * + * Handles both SFP and QSFP. + * For SFP, offset 0-255 are on client[0], >255 is on client[1] + * Offset 256-383 are on the lower half of client[1] + * Pages are accessible on the upper half of client[1]. + * Offset >383 are in 128 byte pages mapped into the upper half + * + * For QSFP, all offsets are on client[0] + * offset 0-127 are on the lower half of client[0] (no paging) + * Pages are accessible on the upper half of client[1]. + * Offset >127 are in 128 byte pages mapped into the upper half + * + * Callers must not read/write beyond the end of a client or a page + * without recomputing the client/page. Hence offset (within page) + * plus length must be less than or equal to 128. (Note that this + * routine does not have access to the length of the call, hence + * cannot do the validity check.) + * + * Offset within Lower Page 00h and Upper Page 00h are not recomputed + */ +static uint8_t sff_8436_translate_offset(struct sfp_port_data *port_data, + loff_t *offset, struct i2c_client **client) +{ + unsigned page = 0; + + *client = port_data->client; + + /* if SFP style, offset > 255, shift to i2c addr 0x51 */ + if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { + if (*offset > 255) { + /* like QSFP, but shifted to client[1] */ + *client = port_data->msa->ddm_client; + *offset -= 256; + } + } + + /* + * if offset is in the range 0-128... + * page doesn't matter (using lower half), return 0. + * offset is already correct (don't add 128 to get to paged area) + */ + if (*offset < SFF_8436_PAGE_SIZE) + return page; + + /* note, page will always be positive since *offset >= 128 */ + page = (*offset >> 7)-1; + /* 0x80 places the offset in the top half, offset is last 7 bits */ + *offset = SFF_8436_PAGE_SIZE + (*offset & 0x7f); + + return page; /* note also returning client and offset */ +} + +static ssize_t sff_8436_eeprom_read(struct sfp_port_data *port_data, + struct i2c_client *client, + char *buf, unsigned offset, size_t count) +{ + struct i2c_msg msg[2]; + u8 msgbuf[2]; + unsigned long timeout, read_time; + int status, i; + + memset(msg, 0, sizeof(msg)); + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + /*smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: + /* Check for odd length transaction */ + count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; + break; + default: + /* + * When we have a better choice than SMBus calls, use a + * combined I2C message. Write address; then read up to + * io_limit data bytes. msgbuf is u8 and will cast to our + * needs. + */ + i = 0; + msgbuf[i++] = offset; + + msg[0].addr = client->addr; + msg[0].buf = msgbuf; + msg[0].len = i; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + } + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + read_time = jiffies; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_read_i2c_block_data(client, offset, + count, buf); + break; + case I2C_SMBUS_WORD_DATA: + status = i2c_smbus_read_word_data(client, offset); + if (status >= 0) { + buf[0] = status & 0xff; + if (count == 2) + buf[1] = status >> 8; + status = count; + } + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_read_byte_data(client, offset); + if (status >= 0) { + buf[0] = status; + status = count; + } + break; + default: + status = i2c_transfer(client->adapter, msg, 2); + if (status == 2) + status = count; + } + + dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", + count, offset, status, jiffies); + + if (status == count) /* happy path */ + return count; + + if (status == -ENXIO) /* no module present */ + return status; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(read_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t sff_8436_eeprom_write(struct sfp_port_data *port_data, + struct i2c_client *client, + const char *buf, + unsigned offset, size_t count) +{ + struct i2c_msg msg; + ssize_t status; + unsigned long timeout, write_time; + unsigned next_page_start; + int i = 0; + + /* write max is at most a page + * (In this driver, write_max is actually one byte!) + */ + if (count > port_data->write_max) + count = port_data->write_max; + + /* shorten count if necessary to avoid crossing page boundary */ + next_page_start = roundup(offset + 1, SFF_8436_PAGE_SIZE); + if (offset + count > next_page_start) + count = next_page_start - offset; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + /*smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: + /* Check for odd length transaction */ + count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; + break; + default: + /* If we'll use I2C calls for I/O, set up the message */ + msg.addr = client->addr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = port_data->writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + break; + } + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_write_i2c_block_data(client, + offset, count, buf); + if (status == 0) + status = count; + break; + case I2C_SMBUS_WORD_DATA: + if (count == 2) { + status = i2c_smbus_write_word_data(client, + offset, (u16)((buf[0])|(buf[1] << 8))); + } else { + /* count = 1 */ + status = i2c_smbus_write_byte_data(client, + offset, buf[0]); + } + if (status == 0) + status = count; + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_write_byte_data(client, offset, + buf[0]); + if (status == 0) + status = count; + break; + default: + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + break; + } + + dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", + count, offset, (long int) status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(write_time, timeout)); + + return -ETIMEDOUT; +} + + +static ssize_t sff_8436_eeprom_update_client(struct sfp_port_data *port_data, + char *buf, loff_t off, + size_t count, qsfp_opcode_e opcode) +{ + struct i2c_client *client; + ssize_t retval = 0; + u8 page = 0; + loff_t phy_offset = off; + int ret = 0; + + page = sff_8436_translate_offset(port_data, &phy_offset, &client); + + dev_dbg(&client->dev, + "sff_8436_eeprom_update_client off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", + off, page, phy_offset, (long int) count, opcode); + if (page > 0) { + ret = sff_8436_eeprom_write(port_data, client, &page, + SFF_8436_PAGE_SELECT_REG, 1); + if (ret < 0) { + dev_dbg(&client->dev, + "Write page register for page %d failed ret:%d!\n", + page, ret); + return ret; + } + } + + while (count) { + ssize_t status; + + if (opcode == QSFP_READ_OP) { + status = sff_8436_eeprom_read(port_data, client, + buf, phy_offset, count); + } else { + status = sff_8436_eeprom_write(port_data, client, + buf, phy_offset, count); + } + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + phy_offset += status; + count -= status; + retval += status; + } + + + if (page > 0) { + /* return the page register to page 0 (why?) */ + page = 0; + ret = sff_8436_eeprom_write(port_data, client, &page, + SFF_8436_PAGE_SELECT_REG, 1); + if (ret < 0) { + dev_err(&client->dev, + "Restore page register to page %d failed ret:%d!\n", + page, ret); + return ret; + } + } + return retval; +} + + +/* + * Figure out if this access is within the range of supported pages. + * Note this is called on every access because we don't know if the + * module has been replaced since the last call. + * If/when modules support more pages, this is the routine to update + * to validate and allow access to additional pages. + * + * Returns updated len for this access: + * - entire access is legal, original len is returned. + * - access begins legal but is too long, len is truncated to fit. + * - initial offset exceeds supported pages, return -EINVAL + */ +static ssize_t sff_8436_page_legal(struct sfp_port_data *port_data, + loff_t off, size_t len) +{ + struct i2c_client *client = port_data->client; + u8 regval; + int status; + size_t maxlen; + + if (off < 0) return -EINVAL; + if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { + /* SFP case */ + if ((off + len) <= 256) return len; + /* if no pages needed, we're good */ + //if ((off + len) <= SFF_8472_EEPROM_UNPAGED_SIZE) return len; + /* if offset exceeds possible pages, we're not good */ + if (off >= SFF_8472_EEPROM_SIZE) return -EINVAL; + + /* Check if ddm is supported */ + status = sff_8436_eeprom_read(port_data, client, ®val, + SFF8472_DIAG_MON_TYPE_ADDR, 1); + if (status < 0) return status; /* error out (no module?) */ + if (!(regval & SFF8472_DIAG_MON_TYPE_DDM_MASK)) { + if (off >= 256) return -EINVAL; + maxlen = 256 - off; + } + else { + /* in between, are pages supported? */ + status = sff_8436_eeprom_read(port_data, client, ®val, + SFF_8472_PAGEABLE_REG, 1); + if (status < 0) return status; /* error out (no module?) */ + if (regval & SFF_8472_PAGEABLE) { + /* Pages supported, trim len to the end of pages */ + maxlen = SFF_8472_EEPROM_SIZE - off; + } else { + /* pages not supported, trim len to unpaged size */ + if (off >= SFF_8472_EEPROM_UNPAGED_SIZE) return -EINVAL; + maxlen = SFF_8472_EEPROM_UNPAGED_SIZE - off; + } + } + len = (len > maxlen) ? maxlen : len; + dev_dbg(&client->dev, + "page_legal, SFP, off %lld len %ld\n", + off, (long int) len); + } + else if (port_data->driver_type == DRIVER_TYPE_QSFP) { + /* QSFP case */ + /* if no pages needed, we're good */ + if ((off + len) <= SFF_8436_EEPROM_UNPAGED_SIZE) return len; + /* if offset exceeds possible pages, we're not good */ + if (off >= SFF_8436_EEPROM_SIZE) return -EINVAL; + /* in between, are pages supported? */ + status = sff_8436_eeprom_read(port_data, client, ®val, + SFF_8436_PAGEABLE_REG, 1); + if (status < 0) return status; /* error out (no module?) */ + if (regval & SFF_8436_NOT_PAGEABLE) { + /* pages not supported, trim len to unpaged size */ + if (off >= SFF_8436_EEPROM_UNPAGED_SIZE) return -EINVAL; + maxlen = SFF_8436_EEPROM_UNPAGED_SIZE - off; + } else { + /* Pages supported, trim len to the end of pages */ + maxlen = SFF_8436_EEPROM_SIZE - off; + } + len = (len > maxlen) ? maxlen : len; + dev_dbg(&client->dev, + "page_legal, QSFP, off %lld len %ld\n", + off, (long int) len); + } + else { + return -EINVAL; + } + return len; +} + + +static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, + char *buf, loff_t off, size_t len, qsfp_opcode_e opcode) +{ + struct i2c_client *client = port_data->client; + int chunk; + int status = 0; + ssize_t retval; + size_t pending_len = 0, chunk_len = 0; + loff_t chunk_offset = 0, chunk_start_offset = 0; + + if (unlikely(!len)) + return len; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&port_data->update_lock); + + /* + * Confirm this access fits within the device suppored addr range + */ + len = sff_8436_page_legal(port_data, off, len); + if (len < 0) { + status = len; + goto err; + } + + /* + * For each (128 byte) chunk involved in this request, issue a + * separate call to sff_eeprom_update_client(), to + * ensure that each access recalculates the client/page + * and writes the page register as needed. + * Note that chunk to page mapping is confusing, is different for + * QSFP and SFP, and never needs to be done. Don't try! + */ + pending_len = len; /* amount remaining to transfer */ + retval = 0; /* amount transferred */ + for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { + + /* + * Compute the offset and number of bytes to be read/write + * + * 1. start at offset 0 (within the chunk), and read/write + * the entire chunk + * 2. start at offset 0 (within the chunk) and read/write less + * than entire chunk + * 3. start at an offset not equal to 0 and read/write the rest + * of the chunk + * 4. start at an offset not equal to 0 and read/write less than + * (end of chunk - offset) + */ + chunk_start_offset = chunk * SFF_8436_PAGE_SIZE; + + if (chunk_start_offset < off) { + chunk_offset = off; + if ((off + pending_len) < (chunk_start_offset + + SFF_8436_PAGE_SIZE)) + chunk_len = pending_len; + else + chunk_len = (chunk+1)*SFF_8436_PAGE_SIZE - off;/*SFF_8436_PAGE_SIZE - off;*/ + } else { + chunk_offset = chunk_start_offset; + if (pending_len > SFF_8436_PAGE_SIZE) + chunk_len = SFF_8436_PAGE_SIZE; + else + chunk_len = pending_len; + } + + dev_dbg(&client->dev, + "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", + off, (long int) len, chunk_start_offset, chunk_offset, + (long int) chunk_len, (long int) pending_len); + + /* + * note: chunk_offset is from the start of the EEPROM, + * not the start of the chunk + */ + status = sff_8436_eeprom_update_client(port_data, buf, + chunk_offset, chunk_len, opcode); + if (status != chunk_len) { + /* This is another 'no device present' path */ + dev_dbg(&client->dev, + "sff_8436_update_client for chunk %d chunk_offset %lld chunk_len %ld failed %d!\n", + chunk, chunk_offset, (long int) chunk_len, status); + goto err; + } + buf += status; + pending_len -= status; + retval += status; + } + mutex_unlock(&port_data->update_lock); + + return retval; + +err: + mutex_unlock(&port_data->update_lock); + + return status; +} + +#else +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} +#endif + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + +#if (MULTIPAGE_SUPPORT == 1) + return sfp_port_read_write(data, buf, off, count, QSFP_READ_OP); +#else + return sfp_port_read(data, buf, off, count); +#endif +} + +#if (MULTIPAGE_SUPPORT == 1) +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom, size_t size) +#else +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +#endif +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; +#if (MULTIPAGE_SUPPORT == 1) + eeprom->size = size; +#else + eeprom->size = EEPROM_SIZE; +#endif + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + + +#if (MULTIPAGE_SUPPORT == 0) +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} +#endif + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + +#if (MULTIPAGE_SUPPORT == 0) + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } +#endif + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ +#if (MULTIPAGE_SUPPORT == 1) + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin, SFF_8436_EEPROM_SIZE); +#else + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); +#endif + if (status) { + goto exit_remove; + } + +#if (MULTIPAGE_SUPPORT == 1) + msa->ddm_client = i2c_new_dummy(client->adapter, client->addr + 1); + if (!msa->ddm_client) { + dev_err(&client->dev, "address 0x%02x unavailable\n", client->addr + 1); + status = -EADDRINUSE; + goto exit_eeprom; + } +#endif + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + return 0; + +exit_eeprom: + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &msa->eeprom.bin); +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + +#if (MULTIPAGE_SUPPORT == 0) + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } +#endif + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ +#if (MULTIPAGE_SUPPORT == 1) + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin, SFF_8436_EEPROM_SIZE); +#else + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); +#endif + if (status) { + goto exit_remove; + } + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +/* Platform dependent +++ */ +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int ret = 0; + struct sfp_port_data *data = NULL; + + if (client->addr != SFP_EEPROM_A0_I2C_ADDR) { + return -ENODEV; + } + + if (dev_id->driver_data < as7312_54x_port1 || dev_id->driver_data > as7312_54x_port54) { + return -ENXIO; + } + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + +#if (MULTIPAGE_SUPPORT == 1) + data->use_smbus = 0; + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + data->use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) { + data->use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + data->use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + ret = -EPFNOSUPPORT; + goto exit_kfree; + } + } + + if (!data->use_smbus || + (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || + i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_WORD_DATA) || + i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + /* + * NOTE: AN-2079 + * Finisar recommends that the host implement 1 byte writes + * only since this module only supports 32 byte page boundaries. + * 2 byte writes are acceptable for PE and Vout changes per + * Application Note AN-2071. + */ + unsigned write_max = 1; + + if (write_max > io_limit) + write_max = io_limit; + if (data->use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + data->write_max = write_max; + + /* buffer (data + address at the beginning) */ + data->writebuf = kmalloc(write_max + 2, GFP_KERNEL); + if (!data->writebuf) { + ret = -ENOMEM; + goto exit_kfree; + } + } else { + dev_warn(&client->dev, + "cannot write due to controller restrictions."); + } + + if (data->use_smbus == I2C_SMBUS_WORD_DATA || + data->use_smbus == I2C_SMBUS_BYTE_DATA) { + dev_notice(&client->dev, "Falling back to %s reads, " + "performance will suffer\n", data->use_smbus == + I2C_SMBUS_WORD_DATA ? "word" : "byte"); + } +#endif + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + if (dev_id->driver_data >= as7312_54x_port1 && dev_id->driver_data <= as7312_54x_port48) { + data->driver_type = DRIVER_TYPE_SFP_MSA; + ret = sfp_msa_probe(client, dev_id, &data->msa); + } + else { /* as7312_54x_portsfp49 ~ as7312_54x_portsfp54 */ + data->driver_type = DRIVER_TYPE_QSFP; + ret = qsfp_probe(client, dev_id, &data->qsfp); + } + + if (ret < 0) { + goto exit_kfree_buf; + } + + + return ret; + +exit_kfree_buf: +#if (MULTIPAGE_SUPPORT == 1) + if (data->writebuf) kfree(data->writebuf); +#endif + +exit_kfree: + kfree(data); + return ret; +} +/* Platform dependent --- */ + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); +#if (MULTIPAGE_SUPPORT == 1) + i2c_unregister_device(data->ddm_client); +#endif + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + int ret = 0; + struct sfp_port_data *data = i2c_get_clientdata(client); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + +#if (MULTIPAGE_SUPPORT == 1) + if (data->writebuf) + kfree(data->writebuf); +#endif + kfree(data); + return ret; +} + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7312_54x_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_i2c_cpld.c new file mode 100644 index 000000000000..67ecd8e036a9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_i2c_cpld.c @@ -0,0 +1,1219 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as7312_54x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as7312_54x_cpld1, + as7312_54x_cpld2, + as7312_54x_cpld3 +}; + +struct as7312_54x_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as7312_54x_cpld_id[] = { + { "as7312_54x_cpld1", as7312_54x_cpld1 }, + { "as7312_54x_cpld2", as7312_54x_cpld2 }, + { "as7312_54x_cpld3", as7312_54x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as7312_54x_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as7312_54x_cpld1_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_RESET_ATTR_ID(49), + TRANSCEIVER_RESET_ATTR_ID(50), + TRANSCEIVER_RESET_ATTR_ID(51), + TRANSCEIVER_RESET_ATTR_ID(52), + TRANSCEIVER_RESET_ATTR_ID(53), + TRANSCEIVER_RESET_ATTR_ID(54), + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_TXDISABLE_ATTR_ID(5), + TRANSCEIVER_TXDISABLE_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(7), + TRANSCEIVER_TXDISABLE_ATTR_ID(8), + TRANSCEIVER_TXDISABLE_ATTR_ID(9), + TRANSCEIVER_TXDISABLE_ATTR_ID(10), + TRANSCEIVER_TXDISABLE_ATTR_ID(11), + TRANSCEIVER_TXDISABLE_ATTR_ID(12), + TRANSCEIVER_TXDISABLE_ATTR_ID(13), + TRANSCEIVER_TXDISABLE_ATTR_ID(14), + TRANSCEIVER_TXDISABLE_ATTR_ID(15), + TRANSCEIVER_TXDISABLE_ATTR_ID(16), + TRANSCEIVER_TXDISABLE_ATTR_ID(17), + TRANSCEIVER_TXDISABLE_ATTR_ID(18), + TRANSCEIVER_TXDISABLE_ATTR_ID(19), + TRANSCEIVER_TXDISABLE_ATTR_ID(20), + TRANSCEIVER_TXDISABLE_ATTR_ID(21), + TRANSCEIVER_TXDISABLE_ATTR_ID(22), + TRANSCEIVER_TXDISABLE_ATTR_ID(23), + TRANSCEIVER_TXDISABLE_ATTR_ID(24), + TRANSCEIVER_TXDISABLE_ATTR_ID(25), + TRANSCEIVER_TXDISABLE_ATTR_ID(26), + TRANSCEIVER_TXDISABLE_ATTR_ID(27), + TRANSCEIVER_TXDISABLE_ATTR_ID(28), + TRANSCEIVER_TXDISABLE_ATTR_ID(29), + TRANSCEIVER_TXDISABLE_ATTR_ID(30), + TRANSCEIVER_TXDISABLE_ATTR_ID(31), + TRANSCEIVER_TXDISABLE_ATTR_ID(32), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(35), + TRANSCEIVER_TXDISABLE_ATTR_ID(36), + TRANSCEIVER_TXDISABLE_ATTR_ID(37), + TRANSCEIVER_TXDISABLE_ATTR_ID(38), + TRANSCEIVER_TXDISABLE_ATTR_ID(39), + TRANSCEIVER_TXDISABLE_ATTR_ID(40), + TRANSCEIVER_TXDISABLE_ATTR_ID(41), + TRANSCEIVER_TXDISABLE_ATTR_ID(42), + TRANSCEIVER_TXDISABLE_ATTR_ID(43), + TRANSCEIVER_TXDISABLE_ATTR_ID(44), + TRANSCEIVER_TXDISABLE_ATTR_ID(45), + TRANSCEIVER_TXDISABLE_ATTR_ID(46), + TRANSCEIVER_TXDISABLE_ATTR_ID(47), + TRANSCEIVER_TXDISABLE_ATTR_ID(48), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(5), + TRANSCEIVER_RXLOS_ATTR_ID(6), + TRANSCEIVER_RXLOS_ATTR_ID(7), + TRANSCEIVER_RXLOS_ATTR_ID(8), + TRANSCEIVER_RXLOS_ATTR_ID(9), + TRANSCEIVER_RXLOS_ATTR_ID(10), + TRANSCEIVER_RXLOS_ATTR_ID(11), + TRANSCEIVER_RXLOS_ATTR_ID(12), + TRANSCEIVER_RXLOS_ATTR_ID(13), + TRANSCEIVER_RXLOS_ATTR_ID(14), + TRANSCEIVER_RXLOS_ATTR_ID(15), + TRANSCEIVER_RXLOS_ATTR_ID(16), + TRANSCEIVER_RXLOS_ATTR_ID(17), + TRANSCEIVER_RXLOS_ATTR_ID(18), + TRANSCEIVER_RXLOS_ATTR_ID(19), + TRANSCEIVER_RXLOS_ATTR_ID(20), + TRANSCEIVER_RXLOS_ATTR_ID(21), + TRANSCEIVER_RXLOS_ATTR_ID(22), + TRANSCEIVER_RXLOS_ATTR_ID(23), + TRANSCEIVER_RXLOS_ATTR_ID(24), + TRANSCEIVER_RXLOS_ATTR_ID(25), + TRANSCEIVER_RXLOS_ATTR_ID(26), + TRANSCEIVER_RXLOS_ATTR_ID(27), + TRANSCEIVER_RXLOS_ATTR_ID(28), + TRANSCEIVER_RXLOS_ATTR_ID(29), + TRANSCEIVER_RXLOS_ATTR_ID(30), + TRANSCEIVER_RXLOS_ATTR_ID(31), + TRANSCEIVER_RXLOS_ATTR_ID(32), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(35), + TRANSCEIVER_RXLOS_ATTR_ID(36), + TRANSCEIVER_RXLOS_ATTR_ID(37), + TRANSCEIVER_RXLOS_ATTR_ID(38), + TRANSCEIVER_RXLOS_ATTR_ID(39), + TRANSCEIVER_RXLOS_ATTR_ID(40), + TRANSCEIVER_RXLOS_ATTR_ID(41), + TRANSCEIVER_RXLOS_ATTR_ID(42), + TRANSCEIVER_RXLOS_ATTR_ID(43), + TRANSCEIVER_RXLOS_ATTR_ID(44), + TRANSCEIVER_RXLOS_ATTR_ID(45), + TRANSCEIVER_RXLOS_ATTR_ID(46), + TRANSCEIVER_RXLOS_ATTR_ID(47), + TRANSCEIVER_RXLOS_ATTR_ID(48), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(5), + TRANSCEIVER_TXFAULT_ATTR_ID(6), + TRANSCEIVER_TXFAULT_ATTR_ID(7), + TRANSCEIVER_TXFAULT_ATTR_ID(8), + TRANSCEIVER_TXFAULT_ATTR_ID(9), + TRANSCEIVER_TXFAULT_ATTR_ID(10), + TRANSCEIVER_TXFAULT_ATTR_ID(11), + TRANSCEIVER_TXFAULT_ATTR_ID(12), + TRANSCEIVER_TXFAULT_ATTR_ID(13), + TRANSCEIVER_TXFAULT_ATTR_ID(14), + TRANSCEIVER_TXFAULT_ATTR_ID(15), + TRANSCEIVER_TXFAULT_ATTR_ID(16), + TRANSCEIVER_TXFAULT_ATTR_ID(17), + TRANSCEIVER_TXFAULT_ATTR_ID(18), + TRANSCEIVER_TXFAULT_ATTR_ID(19), + TRANSCEIVER_TXFAULT_ATTR_ID(20), + TRANSCEIVER_TXFAULT_ATTR_ID(21), + TRANSCEIVER_TXFAULT_ATTR_ID(22), + TRANSCEIVER_TXFAULT_ATTR_ID(23), + TRANSCEIVER_TXFAULT_ATTR_ID(24), + TRANSCEIVER_TXFAULT_ATTR_ID(25), + TRANSCEIVER_TXFAULT_ATTR_ID(26), + TRANSCEIVER_TXFAULT_ATTR_ID(27), + TRANSCEIVER_TXFAULT_ATTR_ID(28), + TRANSCEIVER_TXFAULT_ATTR_ID(29), + TRANSCEIVER_TXFAULT_ATTR_ID(30), + TRANSCEIVER_TXFAULT_ATTR_ID(31), + TRANSCEIVER_TXFAULT_ATTR_ID(32), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(35), + TRANSCEIVER_TXFAULT_ATTR_ID(36), + TRANSCEIVER_TXFAULT_ATTR_ID(37), + TRANSCEIVER_TXFAULT_ATTR_ID(38), + TRANSCEIVER_TXFAULT_ATTR_ID(39), + TRANSCEIVER_TXFAULT_ATTR_ID(40), + TRANSCEIVER_TXFAULT_ATTR_ID(41), + TRANSCEIVER_TXFAULT_ATTR_ID(42), + TRANSCEIVER_TXFAULT_ATTR_ID(43), + TRANSCEIVER_TXFAULT_ATTR_ID(44), + TRANSCEIVER_TXFAULT_ATTR_ID(45), + TRANSCEIVER_TXFAULT_ATTR_ID(46), + TRANSCEIVER_TXFAULT_ATTR_ID(47), + TRANSCEIVER_TXFAULT_ATTR_ID(48), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as7312_54x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as7312_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO | S_IWUSR, show_status, set_reset, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(35); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(36); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(37); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(38); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(39); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(40); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(41); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(42); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(43); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(44); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(45); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(46); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(47); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(48); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); + +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(54); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); + +static struct attribute *as7312_54x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as7312_54x_cpld1_group = { + .attrs = as7312_54x_cpld1_attributes, +}; + +static struct attribute *as7312_54x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_RESET_ATTR(49), + DECLARE_TRANSCEIVER_RESET_ATTR(50), + DECLARE_TRANSCEIVER_RESET_ATTR(51), + DECLARE_TRANSCEIVER_RESET_ATTR(52), + DECLARE_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + DECLARE_SFP_TRANSCEIVER_ATTR(5), + DECLARE_SFP_TRANSCEIVER_ATTR(6), + DECLARE_SFP_TRANSCEIVER_ATTR(7), + DECLARE_SFP_TRANSCEIVER_ATTR(8), + DECLARE_SFP_TRANSCEIVER_ATTR(9), + DECLARE_SFP_TRANSCEIVER_ATTR(10), + DECLARE_SFP_TRANSCEIVER_ATTR(11), + DECLARE_SFP_TRANSCEIVER_ATTR(12), + DECLARE_SFP_TRANSCEIVER_ATTR(13), + DECLARE_SFP_TRANSCEIVER_ATTR(14), + DECLARE_SFP_TRANSCEIVER_ATTR(15), + DECLARE_SFP_TRANSCEIVER_ATTR(16), + DECLARE_SFP_TRANSCEIVER_ATTR(17), + DECLARE_SFP_TRANSCEIVER_ATTR(18), + DECLARE_SFP_TRANSCEIVER_ATTR(19), + DECLARE_SFP_TRANSCEIVER_ATTR(20), + DECLARE_SFP_TRANSCEIVER_ATTR(21), + DECLARE_SFP_TRANSCEIVER_ATTR(22), + DECLARE_SFP_TRANSCEIVER_ATTR(23), + DECLARE_SFP_TRANSCEIVER_ATTR(24), + NULL +}; + +static const struct attribute_group as7312_54x_cpld2_group = { + .attrs = as7312_54x_cpld2_attributes, +}; + +static struct attribute *as7312_54x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_TRANSCEIVER_PRESENT_ATTR(35), + DECLARE_TRANSCEIVER_PRESENT_ATTR(36), + DECLARE_TRANSCEIVER_PRESENT_ATTR(37), + DECLARE_TRANSCEIVER_PRESENT_ATTR(38), + DECLARE_TRANSCEIVER_PRESENT_ATTR(39), + DECLARE_TRANSCEIVER_PRESENT_ATTR(40), + DECLARE_TRANSCEIVER_PRESENT_ATTR(41), + DECLARE_TRANSCEIVER_PRESENT_ATTR(42), + DECLARE_TRANSCEIVER_PRESENT_ATTR(43), + DECLARE_TRANSCEIVER_PRESENT_ATTR(44), + DECLARE_TRANSCEIVER_PRESENT_ATTR(45), + DECLARE_TRANSCEIVER_PRESENT_ATTR(46), + DECLARE_TRANSCEIVER_PRESENT_ATTR(47), + DECLARE_TRANSCEIVER_PRESENT_ATTR(48), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_TRANSCEIVER_RESET_ATTR(53), + DECLARE_TRANSCEIVER_RESET_ATTR(54), + DECLARE_SFP_TRANSCEIVER_ATTR(25), + DECLARE_SFP_TRANSCEIVER_ATTR(26), + DECLARE_SFP_TRANSCEIVER_ATTR(27), + DECLARE_SFP_TRANSCEIVER_ATTR(28), + DECLARE_SFP_TRANSCEIVER_ATTR(29), + DECLARE_SFP_TRANSCEIVER_ATTR(30), + DECLARE_SFP_TRANSCEIVER_ATTR(31), + DECLARE_SFP_TRANSCEIVER_ATTR(32), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(35), + DECLARE_SFP_TRANSCEIVER_ATTR(36), + DECLARE_SFP_TRANSCEIVER_ATTR(37), + DECLARE_SFP_TRANSCEIVER_ATTR(38), + DECLARE_SFP_TRANSCEIVER_ATTR(39), + DECLARE_SFP_TRANSCEIVER_ATTR(40), + DECLARE_SFP_TRANSCEIVER_ATTR(41), + DECLARE_SFP_TRANSCEIVER_ATTR(42), + DECLARE_SFP_TRANSCEIVER_ATTR(43), + DECLARE_SFP_TRANSCEIVER_ATTR(44), + DECLARE_SFP_TRANSCEIVER_ATTR(45), + DECLARE_SFP_TRANSCEIVER_ATTR(46), + DECLARE_SFP_TRANSCEIVER_ATTR(47), + DECLARE_SFP_TRANSCEIVER_ATTR(48), + NULL +}; + +static const struct attribute_group as7312_54x_cpld3_group = { + .attrs = as7312_54x_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[4] = {0}; + u8 regs[] = {0x9, 0xA, 0xB, 0x18}; + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7312_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 54 in order */ + if (data->type == as7312_54x_cpld2) { + values[3] &= 0xF; + } + else { /* as7312_54x_cpld3 */ + values[3] &= 0x3; + } + + return sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[3] = {0}; + u8 regs[] = {0x12, 0x13, 0x14}; + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7312_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 24 in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", values[0], values[1], values[2]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33 ... MODULE_PRESENT_40: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_PRESENT_33); + break; + case MODULE_PRESENT_41 ... MODULE_PRESENT_48: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_PRESENT_41); + break; + case MODULE_PRESENT_49: + reg = 0x18; + mask = 0x1; + break; + case MODULE_PRESENT_50: + reg = 0x18; + mask = 0x2; + break; + case MODULE_PRESENT_51: + reg = 0x18; + mask = 0x4; + break; + case MODULE_PRESENT_52: + reg = 0x18; + mask = 0x8; + break; + case MODULE_PRESENT_53: + reg = 0x18; + mask = 0x1; + break; + case MODULE_PRESENT_54: + reg = 0x18; + mask = 0x2; + break; + + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x17; + mask = 1 << ((attr->index - MODULE_PRESENT_49)%4); + break; + + case MODULE_TXFAULT_1 ... MODULE_TXFAULT_8: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXFAULT_1); + break; + case MODULE_TXFAULT_9 ... MODULE_TXFAULT_16: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXFAULT_9); + break; + case MODULE_TXFAULT_17 ... MODULE_TXFAULT_24: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXFAULT_17); + break; + case MODULE_TXFAULT_25 ... MODULE_TXFAULT_32: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXFAULT_25); + break; + case MODULE_TXFAULT_33 ... MODULE_TXFAULT_40: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXFAULT_33); + break; + case MODULE_TXFAULT_41 ... MODULE_TXFAULT_48: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXFAULT_41); + break; + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + case MODULE_RXLOS_1 ... MODULE_RXLOS_8: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_RXLOS_1); + break; + case MODULE_RXLOS_9 ... MODULE_RXLOS_16: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_RXLOS_9); + break; + case MODULE_RXLOS_17 ... MODULE_RXLOS_24: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RXLOS_17); + break; + case MODULE_RXLOS_25 ... MODULE_RXLOS_32: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_RXLOS_25); + break; + case MODULE_RXLOS_33 ... MODULE_RXLOS_40: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_RXLOS_33); + break; + case MODULE_RXLOS_41 ... MODULE_RXLOS_48: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RXLOS_41); + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_54) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as7312_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &reset); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x17; + mask = 1 << ((attr->index - MODULE_RESET_49)%4); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7312_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update reset status */ + if (reset) { + status |= mask; + } + else { + status &= ~mask; + } + status = as7312_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + + + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7312_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as7312_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as7312_54x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as7312_54x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as7312_54x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as7312_54x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as7312_54x_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as7312_54x_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) { + case as7312_54x_cpld1: + group = &as7312_54x_cpld1_group; + break; + case as7312_54x_cpld2: + group = &as7312_54x_cpld2_group; + break; + case as7312_54x_cpld3: + group = &as7312_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as7312_54x_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as7312_54x_cpld_remove(struct i2c_client *client) +{ + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as7312_54x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as7312_54x_cpld1: + group = &as7312_54x_cpld1_group; + break; + case as7312_54x_cpld2: + group = &as7312_54x_cpld2_group; + break; + case as7312_54x_cpld3: + group = &as7312_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as7312_54x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as7312_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as7312_54x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7312_54x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7312_54x_cpld_read); + +int as7312_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7312_54x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7312_54x_cpld_write); + +static struct i2c_driver as7312_54x_cpld_driver = { + .driver = { + .name = "as7312_54x_cpld", + .owner = THIS_MODULE, + }, + .probe = as7312_54x_cpld_probe, + .remove = as7312_54x_cpld_remove, + .id_table = as7312_54x_cpld_id, +}; + +static int __init as7312_54x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7312_54x_cpld_driver); +} + +static void __exit as7312_54x_cpld_exit(void) +{ + i2c_del_driver(&as7312_54x_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as7312_54x_cpld_init); +module_exit(as7312_54x_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/service/as7312-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/service/as7312-platform-monitor.service new file mode 100755 index 000000000000..b79357665bed --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/service/as7312-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS7312-54X Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7312_util.py install +ExecStart=/usr/local/bin/accton_as7312_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/setup.py new file mode 100755 index 000000000000..f0518d07689d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env pytho + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7312_54x', + version='1.0', + description='Module to initialize Accton AS7312-54X platforms', + + packages=['as7312_54x'], + package_dir={'as7312_54x': 'as7312-54x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/README new file mode 100755 index 000000000000..66f31a030423 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program is free software: you can redistribute it and/or modify +It under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as7312_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as7312-fan-psu-cpld.patch + for as7312's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS7312-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as7312 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS7312-54X.patch" from patch/installer. + - Change setting for AS7312-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS7312-54X.patch" + !!NOTICE, patching onie_installer-accton-AS7312-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS7312-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as7312-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as7312_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS7312-54X.patch. + It's done by patching onie_installer-accton-AS7312-54X.patch at build-image. + Run "accton_as7312_util.py install" to install drivers. + +To initialize the system, run "accton_as7312_util.py install". +To clean up the drivers & devices, run "accton_as7312_util.py clean". +To dump information of sensors, run "accton_as7312_util.py show". +To dump SFP EEPROM, run "accton_as7312_util.py sff". +To set fan speed, run "accton_as7312_util.py set fan". +To enable/disable SFP emission, run "accton_as7312_util.py set sfp". +To set system LEDs' color, run "accton_as7312_util.py set led" +For more information, run "accton_as7312_util.py --help". + +==================================================================== +Besides applying accton_as7312_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_monitor.py new file mode 100755 index 000000000000..bdab0d4b8bff --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_monitor.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 2/27/2018: Roy Lee modify for as7312_54x +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + from as7312_54x.fanutil import FanUtil + from as7312_54x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as7312_monitor' + +global log_file +global log_level + +# (LM75_1+ LM75_2+ LM75_3) is LM75 at i2c addresses 0x48, 0x49, and 0x4A. +# TMP = (LM75_1+ LM75_2+ LM75_3)/3 +#1. If TMP < 35, All fans run with duty 31.25%. +#2. If TMP>=35 or the temperature of any one of fan is higher than 40, +# All fans run with duty 50% +#3. If TMP >= 40 or the temperature of any one of fan is higher than 45, +# All fans run with duty 62.5%. +#4. If TMP >= 45 or the temperature of any one of fan is higher than 50, +# All fans run with duty 100%. +#5. Any one of 6 fans is fault, set duty = 100%. +#6. Direction factor. If it is B2F direction, duty + 12%. + + # MISC: + # 1.Check single LM75 before applied average. + # 2.If no matched fan speed is found from the policy, + # use FAN_DUTY_CYCLE_MIN as default speed + # Get current temperature + # 4.Decision 3: Decide new fan speed depend on fan direction/current fan speed/temperature + + + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as7312_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + max_duty = 100 + fan_policy_f2b = { + 0: [32, 0, 105000], + 1: [50, 105000, 120000], + 2: [63, 120000, 135000], + 3: [max_duty, 135000, sys.maxsize], + } + fan_policy_b2f = { + 0: [44, 0, 105000], + 1: [63, 105000, 120000], + 2: [75, 120000, 135000], + 3: [max_duty, 135000, sys.maxsize], + } + fan_policy_single = { + 0: 40000, + 1: 45000, + 2: 50000, + } + + thermal = ThermalUtil() + fan = FanUtil() + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_status = fan.get_fan_status(x) + if fan_status is None: + logging.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', max_duty, x) + return False + if fan_status is False: + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', max_duty, x) + fan.set_fan_duty_cycle(max_duty) + return True + #logging.debug('INFO. fan_status is True (fan_num:%d)', x) + + fan_dir=fan.get_fan_dir(1) + if fan_dir == 1: + fan_policy = fan_policy_f2b + else: + fan_policy = fan_policy_b2f + + #Decide fan duty by if any of sensors > fan_policy_single. + new_duty_cycle = fan_policy[0][0] + for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): + single_thm = thermal._get_thermal_node_val(x) + for y in range(0, len(fan_policy_single)): + if single_thm > fan_policy_single[y]: + if fan_policy[y+1][0] > new_duty_cycle: + new_duty_cycle = fan_policy[y+1][0] + logging.debug('INFO. Single thermal sensor %d with temp %d > %d , new_duty_cycle=%d', + x, single_thm, fan_policy_single[y], new_duty_cycle) + single_result = new_duty_cycle + + + #Find if current duty matched any of define duty. + #If not, set it to highest one. + cur_duty_cycle = fan.get_fan_duty_cycle() + for x in range(0, len(fan_policy)): + if cur_duty_cycle == fan_policy[x][0]: + break + if x == len(fan_policy) : + fan.set_fan_duty_cycle(fan_policy[0][0]) + cur_duty_cycle = max_duty + + #Decide fan duty by if sum of sensors falls into any of fan_policy{} + get_temp = thermal.get_thermal_temp() + new_duty_cycle = cur_duty_cycle + for x in range(0, len(fan_policy)): + y = len(fan_policy) - x -1 #checked from highest + if get_temp > fan_policy[y][1] and get_temp < fan_policy[y][2] : + new_duty_cycle= fan_policy[y][0] + logging.debug('INFO. Sum of temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy[y][1], new_duty_cycle) + + sum_result = new_duty_cycle + if (sum_result>single_result): + new_duty_cycle = sum_result; + else: + new_duty_cycle = single_result + + logging.debug('INFO. Final duty_cycle=%d', new_duty_cycle) + if(new_duty_cycle != cur_duty_cycle): + fan.set_fan_duty_cycle(new_duty_cycle) + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + monitor = accton_as7312_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_util.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_util.py new file mode 100755 index 000000000000..b8107c47afea --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_util.py @@ -0,0 +1,588 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'as7312_54x' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':6,'thermal':4, 'psu':2, 'sfp':54} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-54 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_i2c_cpld' , +'modprobe ym2651y' , +'modprobe accton_as7312_54x_fan' , +'modprobe optoe' , +'modprobe accton_as7312_54x_leds' , +'modprobe accton_as7312_54x_psu' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + lst = rm.split(" ") + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/accton_'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['2-0066'] , + 'thermal': ['3-0048','3-0049', '3-004a', '3-004b'] , + 'psu': ['10-0051','11-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present', 'sfp_tx_disable']} + +sfp_map = [18,19,20,21,22,23,24,25,26,27, + 28,29,30,31,32,33,34,35,36,37, + 38,39,40,41,42,43,44,45,46,47, + 48,49,50,51,52,53,54,55,56,57, + 58,59,60,61,62,63,64,65,66,67, + 68,69,70,71] + +qsfp_start = 48 + +mknod =[ +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', + +'echo as7312_54x_fan 0x66 > /sys/bus/i2c/devices/i2c-2/new_device ', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as7312_54x_psu1 0x53 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as7312_54x_psu2 0x50 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo as7312_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-4/new_device', +'echo as7312_54x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-5/new_device', +'echo as7312_54x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-6/new_device'] + +mknod2 =[ +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', + +'echo as7312_54x_fan 0x66 > /sys/bus/i2c/devices/i2c-2/new_device ', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as7312_54x_psu1 0x53 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as7312_54x_psu2 0x50 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo as7312_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-4/new_device', +'echo as7312_54x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-5/new_device', +'echo as7312_54x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-6/new_device'] + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x70 is exist @ i2c-1 + tmp = "echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x70 > /sys/bus/i2c/devices/i2c-1/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x70 is not exist @i2c-1, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + for i in range(0,len(sfp_map)): + if i < qsfp_start: + status, output =log_os_system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + else: + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0076", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/fanutil.py new file mode 100755 index 000000000000..91ca21aa528e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/fanutil.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 3/23/2018: Roy Lee modify for as7326_56x +# 6/26/2018: Jostar implement by new thermal policy from HW RD +# ------------------------------------------------------------------ +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/11-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/11-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + #logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/thermalutil.py new file mode 100755 index 000000000000..2060bc19d943 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/thermalutil.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 3/23/2018: Roy Lee modify for as7326_56x +# 6/26/2018: Jostar implement by new thermal policy from HW RD +# ------------------------------------------------------------------ + +try: + import os + import time + import logging + import glob + import commands + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + if show: + print "ACC: " + str(cmd) + " , result:"+ str(status) + + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_MAX = 6 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD. LM75 + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75 + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75 + THERMAL_NUM_4_IDX = 4 # CPU board. LM75 + THERMAL_NUM_5_IDX = 5 # CPU core thermal + THERMAL_NUM_6_IDX = 6 # BCM thermal + + BCM_thermal_cmd = 'bcmcmd "show temp" > /tmp/bcm_thermal' + BCM_thermal_path = '/tmp/bcm_thermal' + #BCM_thermal_path = '/tmp/bcm_debug' + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + #_thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['15', '48'], + THERMAL_NUM_2_IDX: ['15', '49'], + THERMAL_NUM_3_IDX: ['15', '4a'], + THERMAL_NUM_4_IDX: ['15', '4b'], + } + thermal_sysfspath ={ + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/drivers/lm75/15-0048/hwmon/hwmon2/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/drivers/lm75/15-0049/hwmon/hwmon3/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/drivers/lm75/15-004a/hwmon/hwmon4/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/bus/i2c/drivers/lm75/15-004b/hwmon/hwmon5/temp1_input"], + THERMAL_NUM_5_IDX: ["/sys/class/hwmon/hwmon0/temp1_input"], + } + + #def __init__(self): + + def _get_thermal_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + if thermal_num < self.THERMAL_NUM_6_IDX: + device_path = self.get_thermal_to_device_path(thermal_num) + if(os.path.isfile(device_path)): + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + return int(content) + + else: + print "No such device_path=%s"%device_path + return 0 + + else: + log_os_system(self.BCM_thermal_cmd,0) + file_path = self.BCM_thermal_path + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return 0 + file_str = check_file.read() + search_str="average current temperature is" + print "file_str.find=%s"%file_str.find(search_str) + str_len = len(search_str) + idx=file_str.find(search_str) + if idx==-1: + print "bcm sdk is not ready ,retrun 0" + return 0 + else: + #print "file_str[idx]=%c"%file_str[idx+str_len+1] + #print "file_str[idx]=%c"%file_str[idx+str_len+2] + #print "file_str[idx]=%c"%file_str[idx+str_len+2+1] + #print "file_str[idx]=%c"%file_str[idx+str_len+2+2] + #print "file_str[idx]=%c"%file_str[idx+str_len+2+3] + #print "file_str[idx]=%c"%file_str[idx+str_len+2+4] + #print "file_str[idx]=%c"%file_str[idx+str_len+2+5] + #print "file_str[idx]=%c"%file_str[idx+str_len+2+6] + temp_str=file_str[idx+str_len+1] + file_str[idx+str_len+2] + file_str[idx+str_len+3]+file_str[idx+str_len+4] +file_str[idx+str_len+5] + print "bcm temp_str=%s"%temp_str + check_file.close() + return float(temp_str)*1000 + + def get_num_thermals(self): + return self.THERMAL_NUM_MAX + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self.thermal_sysfspath) + + def get_thermal_to_device_path(self, thermal_num): + return self.thermal_sysfspath[thermal_num][0] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +def main(): + thermal = ThermalUtil() + print "termal1=%d" %thermal._get_thermal_val(1) + print "termal2=%d" %thermal._get_thermal_val(2) + print "termal3=%d" %thermal._get_thermal_val(3) + print "termal4=%d" %thermal._get_thermal_val(4) + print "termal5=%d" %thermal._get_thermal_val(5) + print "termal6=%d" %thermal._get_thermal_val(6) +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/Makefile new file mode 100755 index 000000000000..85c066571c2f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/Makefile @@ -0,0 +1,17 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_i2c_cpld.o \ + accton_as7326_56x_fan.o accton_as7326_56x_leds.o \ + accton_as7326_56x_psu.o ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +$(error KERNEL_SRC is not defined) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_fan.c new file mode 100755 index 000000000000..606019f3ea44 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_fan.c @@ -0,0 +1,815 @@ +/* + * A hwmon driver for the Accton as7326 56x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7326_56x_fan" + +#define NUM_THERMAL_SENSORS (3) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a} + +#define IN +#define OUT + +static struct as7326_56x_fan_data *as7326_56x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_enable(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7326_56x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + u8 enable; + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index##_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr, \ + &sensor_dev_attr_pwm##index##_enable.dev_attr.attr + +#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ + static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr + + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); +/* System temperature for fancontrol */ +DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR(); + +static struct attribute *as7326_56x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + DECLARE_FAN_SYSTEM_TEMP_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7326_56x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7326_56x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as7326_56x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct as7326_56x_fan_data *data = as7326_56x_fan_update_device(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + data->enable = value; + if (value == 0) + { + return set_duty_cycle(dev, da, buf, FAN_MAX_DUTY_CYCLE); + } + return count; +} + + +static ssize_t get_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7326_56x_fan_data *data = as7326_56x_fan_update_device(dev); + + return sprintf(buf, "%u\n", data->enable); +} +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0) + return -EINVAL; + + value = (value > FAN_MAX_DUTY_CYCLE)? FAN_MAX_DUTY_CYCLE : value; + + as7326_56x_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as7326_56x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +/* Due to this struct is declared at lm75.c, it cannot be include + * under Sonic environment. I duplicate it from lm75.c. + */ +struct lm75_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct thermal_zone_device *tz; + struct mutex update_lock; + u8 orig_conf; + u8 resolution; /* In bits, between 9 and 12 */ + u8 resolution_limits; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long sample_time; /* In jiffies */ + s16 temp[3]; /* Register values, + 0 = input + 1 = max + 2 = hyst */ +}; + +/*Copied from lm75.c*/ +static inline long lm75_reg_to_mc(s16 temp, u8 resolution) +{ + return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); +} + +/*Get hwmon_dev from i2c_client, set hwmon_dev = NULL is failed.*/ +static struct device * get_hwmon_dev( + struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if(data) + { + if( data->valid == 1 && data->hwmon_dev) + { + return data->hwmon_dev; + } + + } + return NULL; +} + +/* To find hwmon index by opening hwmon under that i2c address. + */ +static int find_hwmon_index_by_FileOpen( + int bus_nr, + unsigned short addr, + OUT int *index) +{ +#define MAX_HWMON_DEVICE (10) /* Find hwmon device in 0~10*/ + struct file *sfd; + char client_name[96]; + int i=0; + + do { + snprintf(client_name, sizeof(client_name), + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + + sfd = filp_open(client_name, O_RDONLY, 0); + i++; + } while( IS_ERR(sfd) && i < MAX_HWMON_DEVICE); + + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", client_name, __LINE__); + return -ENOENT; + } + filp_close(sfd, 0); + *index = i - 1; + return 0; + +#undef MAX_HWMON_DEVICE +} + +static int get_temp_file_path( + int bus_nr, unsigned short addr, + struct device *hwmon_dev + ,char *path, int max_len) +{ + + if(hwmon_dev && strlen(dev_name(hwmon_dev))) + { + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/%s/temp1_input", + bus_nr, addr, dev_name(hwmon_dev)); + } + else + { + int i=0; + if(find_hwmon_index_by_FileOpen( bus_nr, addr, &i)) + { + return -EIO; + } + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + } + return 0; +} + +/*File read the dev file at user space.*/ +static int read_devfile_temp1_input( + struct device *dev, + int bus_nr, + unsigned short addr, + struct device *hwmon_dev, + int *miniCelsius) +{ + struct file *sfd; + char buffer[96]; + char devfile[96]; + int rc, status; + int rdlen, value; + mm_segment_t old_fs; + + rc = 0; + get_temp_file_path(bus_nr, addr, hwmon_dev, devfile, sizeof(devfile)); + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", devfile, __LINE__); + return -ENOENT; + } + dev_dbg(dev, "Found device:%s\n",devfile); + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + pr_err("file %s cann't readable ?\n",devfile); + return -ENOENT; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + pr_err( "File(%s) empty!\n", devfile); + rc = -EIO; + goto exit; + } + status = sscanf(buffer, "%d", &value); + if (status != 1) { + rc = -EIO; + goto exit; + } + *miniCelsius = value; + dev_dbg(dev,"found sensors: %d @i2c %d-%04x\n", value, bus_nr, addr); + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + return rc; +} + +static u8 is_lm75_data_due(struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if (time_after(jiffies, data->last_updated + data->sample_time)) + { + return 1; + } + return 0; +} +static int get_lm75_temp(struct i2c_client *client, int *miniCelsius) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + *miniCelsius = lm75_reg_to_mc(data->temp[0], data->resolution); + + return 0; +} + +static bool lm75_addr_mached(unsigned short addr) +{ + int i; + unsigned short addrs[] = THERMAL_SENSORS_ADDRS; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) + { + if( addr == addrs[i]) + return 1; + } + return 0; +} + +static int _find_lm75_device(struct device *dev, void *data) +{ + struct device_driver *driver; + struct as7326_56x_fan_data *prv = data; + char *driver_name = THERMAL_SENSORS_DRIVER; + + driver = dev->driver; + if (driver && driver->name && + strcmp(driver->name, driver_name) == 0) + { + struct i2c_client *client; + client = to_i2c_client(dev); + if (client) + { + /*cannot use "struct i2c_adapter *adap = to_i2c_adapter(dev);"*/ + struct i2c_adapter *adap = client->adapter; + int miniCelsius = 0; + + if (! lm75_addr_mached(client->addr)) + { + return 0; + } + + if (!adap) { + return -ENXIO; + } + + /* If the data is not updated, read them from devfile + to drive them updateing data from chip.*/ + if (is_lm75_data_due(client)) + { + struct device *hwmon_dev; + + hwmon_dev = get_hwmon_dev(client); + if(0 == read_devfile_temp1_input(dev, adap->nr, + client->addr, hwmon_dev, &miniCelsius)) + { + prv->system_temp += miniCelsius; + prv->sensors_found++; + } + + } + else + { + get_lm75_temp(client, &miniCelsius); + prv->system_temp += miniCelsius; + prv->sensors_found++; + + } + } + } + return 0; +} + +/*Find all lm75 devices and return sum of temperatures.*/ +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + ssize_t ret = 0; + struct as7326_56x_fan_data *data = as7326_56x_fan_update_device(dev); + + data->system_temp=0; + data->sensors_found=0; + i2c_for_each_dev(data, _find_lm75_device); + if (NUM_THERMAL_SENSORS != data->sensors_found) + { + dev_dbg(dev,"only %d of %d temps are found\n", + data->sensors_found, NUM_THERMAL_SENSORS); + data->system_temp = INT_MAX; + } + ret = sprintf(buf, "%d\n",data->system_temp); + return ret; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7326_56x_fan_data *data = as7326_56x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7326_56x_fan_group = { + .attrs = as7326_56x_fan_attributes, +}; + +static struct as7326_56x_fan_data *as7326_56x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7326_56x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7326_56x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7326_56x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7326_56x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7326_56x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->enable = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7326_56x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7326_56x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7326_56x_fan_remove(struct i2c_client *client) +{ + struct as7326_56x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7326_56x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7326_56x_fan_id[] = { + { "as7326_56x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7326_56x_fan_id); + +static struct i2c_driver as7326_56x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7326_56x_fan_probe, + .remove = as7326_56x_fan_remove, + .id_table = as7326_56x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7326_56x_fan_init(void) +{ + return i2c_add_driver(&as7326_56x_fan_driver); +} + +static void __exit as7326_56x_fan_exit(void) +{ + i2c_del_driver(&as7326_56x_fan_driver); +} + +module_init(as7326_56x_fan_init); +module_exit(as7326_56x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7326_56x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_leds.c b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_leds.c new file mode 100644 index 000000000000..4cb7f1fa25a5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_leds.c @@ -0,0 +1,438 @@ +/* + * A LED driver for the accton_as7326_56x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as7326_56x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as7326_56x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "accton_as7326_56x_led" + +struct accton_as7326_56x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct accton_as7326_56x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as7326_56x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as7326_56x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7326_56x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = accton_as7326_56x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as7326_56x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as7326_56x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7326_56x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as7326_56x_led_diag_get(struct led_classdev *cdev) +{ + accton_as7326_56x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as7326_56x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7326_56x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_as7326_56x_led_loc_get(struct led_classdev *cdev) +{ + accton_as7326_56x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_as7326_56x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_as7326_56x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev accton_as7326_56x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_as7326_56x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as7326_56x_led_diag_set, + .brightness_get = accton_as7326_56x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "accton_as7326_56x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as7326_56x_led_loc_set, + .brightness_get = accton_as7326_56x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "accton_as7326_56x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as7326_56x_led_auto_set, + .brightness_get = accton_as7326_56x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "accton_as7326_56x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as7326_56x_led_auto_set, + .brightness_get = accton_as7326_56x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as7326_56x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as7326_56x_led_auto_set, + .brightness_get = accton_as7326_56x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as7326_56x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7326_56x_leds); i++) { + led_classdev_suspend(&accton_as7326_56x_leds[i]); + } + + return 0; +} + +static int accton_as7326_56x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7326_56x_leds); i++) { + led_classdev_resume(&accton_as7326_56x_leds[i]); + } + + return 0; +} + +static int accton_as7326_56x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as7326_56x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as7326_56x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as7326_56x_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as7326_56x_leds[i]); + } + } + + return ret; +} + +static int accton_as7326_56x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as7326_56x_leds); i++) { + led_classdev_unregister(&accton_as7326_56x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as7326_56x_led_driver = { + .probe = accton_as7326_56x_led_probe, + .remove = accton_as7326_56x_led_remove, + .suspend = accton_as7326_56x_led_suspend, + .resume = accton_as7326_56x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as7326_56x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as7326_56x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as7326_56x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as7326_56x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as7326_56x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as7326_56x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as7326_56x_led_driver); + kfree(ledctl); +} + +module_init(accton_as7326_56x_led_init); +module_exit(accton_as7326_56x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7326_56x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_psu.c new file mode 100644 index 000000000000..8c2ece6200fe --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_psu.c @@ -0,0 +1,277 @@ +/* + * An hwmon driver for accton as7326_56x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as7326_56x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7326_56x_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7326_56x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[9]; /* Model name, read from eeprom */ +}; + +static struct as7326_56x_psu_data *as7326_56x_psu_update_device(struct device *dev); + +enum as7326_56x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as7326_56x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7326_56x_psu_data *data = as7326_56x_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7326_56x_psu_data *data = as7326_56x_psu_update_device(dev); + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as7326_56x_psu_group = { + .attrs = as7326_56x_psu_attributes, +}; + +static int as7326_56x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7326_56x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7326_56x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7326_56x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7326_56x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7326_56x_psu_remove(struct i2c_client *client) +{ + struct as7326_56x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7326_56x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7326_56x_psu1, + as7326_56x_psu2 +}; + +static const struct i2c_device_id as7326_56x_psu_id[] = { + { "as7326_56x_psu1", as7326_56x_psu1 }, + { "as7326_56x_psu2", as7326_56x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7326_56x_psu_id); + +static struct i2c_driver as7326_56x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7326_56x_psu", + }, + .probe = as7326_56x_psu_probe, + .remove = as7326_56x_psu_remove, + .id_table = as7326_56x_psu_id, + .address_list = normal_i2c, +}; + +static int as7326_56x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as7326_56x_psu_data *as7326_56x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as7326_56x update\n"); + + /* Read psu status */ + status = as7326_56x_cpld_read(0x60, 0x2); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as7326_56x_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as7326_56x_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7326_56x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_i2c_cpld.c new file mode 100644 index 000000000000..2274c4a934c0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_i2c_cpld.c @@ -0,0 +1,1080 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as7326_56x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as7326_56x_cpld1, + as7326_56x_cpld2, + as7326_56x_cpld3 +}; + +struct as7326_56x_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as7326_56x_cpld_id[] = { + { "as7326_56x_cpld1", as7326_56x_cpld1 }, + { "as7326_56x_cpld2", as7326_56x_cpld2 }, + { "as7326_56x_cpld3", as7326_56x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as7326_56x_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as7326_56x_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_PRESENT_ATTR_ID(55), + TRANSCEIVER_PRESENT_ATTR_ID(56), + TRANSCEIVER_PRESENT_ATTR_ID(57), + TRANSCEIVER_PRESENT_ATTR_ID(58), + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_TXDISABLE_ATTR_ID(5), + TRANSCEIVER_TXDISABLE_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(7), + TRANSCEIVER_TXDISABLE_ATTR_ID(8), + TRANSCEIVER_TXDISABLE_ATTR_ID(9), + TRANSCEIVER_TXDISABLE_ATTR_ID(10), + TRANSCEIVER_TXDISABLE_ATTR_ID(11), + TRANSCEIVER_TXDISABLE_ATTR_ID(12), + TRANSCEIVER_TXDISABLE_ATTR_ID(13), + TRANSCEIVER_TXDISABLE_ATTR_ID(14), + TRANSCEIVER_TXDISABLE_ATTR_ID(15), + TRANSCEIVER_TXDISABLE_ATTR_ID(16), + TRANSCEIVER_TXDISABLE_ATTR_ID(17), + TRANSCEIVER_TXDISABLE_ATTR_ID(18), + TRANSCEIVER_TXDISABLE_ATTR_ID(19), + TRANSCEIVER_TXDISABLE_ATTR_ID(20), + TRANSCEIVER_TXDISABLE_ATTR_ID(21), + TRANSCEIVER_TXDISABLE_ATTR_ID(22), + TRANSCEIVER_TXDISABLE_ATTR_ID(23), + TRANSCEIVER_TXDISABLE_ATTR_ID(24), + TRANSCEIVER_TXDISABLE_ATTR_ID(25), + TRANSCEIVER_TXDISABLE_ATTR_ID(26), + TRANSCEIVER_TXDISABLE_ATTR_ID(27), + TRANSCEIVER_TXDISABLE_ATTR_ID(28), + TRANSCEIVER_TXDISABLE_ATTR_ID(29), + TRANSCEIVER_TXDISABLE_ATTR_ID(30), + TRANSCEIVER_TXDISABLE_ATTR_ID(31), + TRANSCEIVER_TXDISABLE_ATTR_ID(32), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(35), + TRANSCEIVER_TXDISABLE_ATTR_ID(36), + TRANSCEIVER_TXDISABLE_ATTR_ID(37), + TRANSCEIVER_TXDISABLE_ATTR_ID(38), + TRANSCEIVER_TXDISABLE_ATTR_ID(39), + TRANSCEIVER_TXDISABLE_ATTR_ID(40), + TRANSCEIVER_TXDISABLE_ATTR_ID(41), + TRANSCEIVER_TXDISABLE_ATTR_ID(42), + TRANSCEIVER_TXDISABLE_ATTR_ID(43), + TRANSCEIVER_TXDISABLE_ATTR_ID(44), + TRANSCEIVER_TXDISABLE_ATTR_ID(45), + TRANSCEIVER_TXDISABLE_ATTR_ID(46), + TRANSCEIVER_TXDISABLE_ATTR_ID(47), + TRANSCEIVER_TXDISABLE_ATTR_ID(48), + TRANSCEIVER_TXDISABLE_ATTR_ID(57), + TRANSCEIVER_TXDISABLE_ATTR_ID(58), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(5), + TRANSCEIVER_RXLOS_ATTR_ID(6), + TRANSCEIVER_RXLOS_ATTR_ID(7), + TRANSCEIVER_RXLOS_ATTR_ID(8), + TRANSCEIVER_RXLOS_ATTR_ID(9), + TRANSCEIVER_RXLOS_ATTR_ID(10), + TRANSCEIVER_RXLOS_ATTR_ID(11), + TRANSCEIVER_RXLOS_ATTR_ID(12), + TRANSCEIVER_RXLOS_ATTR_ID(13), + TRANSCEIVER_RXLOS_ATTR_ID(14), + TRANSCEIVER_RXLOS_ATTR_ID(15), + TRANSCEIVER_RXLOS_ATTR_ID(16), + TRANSCEIVER_RXLOS_ATTR_ID(17), + TRANSCEIVER_RXLOS_ATTR_ID(18), + TRANSCEIVER_RXLOS_ATTR_ID(19), + TRANSCEIVER_RXLOS_ATTR_ID(20), + TRANSCEIVER_RXLOS_ATTR_ID(21), + TRANSCEIVER_RXLOS_ATTR_ID(22), + TRANSCEIVER_RXLOS_ATTR_ID(23), + TRANSCEIVER_RXLOS_ATTR_ID(24), + TRANSCEIVER_RXLOS_ATTR_ID(25), + TRANSCEIVER_RXLOS_ATTR_ID(26), + TRANSCEIVER_RXLOS_ATTR_ID(27), + TRANSCEIVER_RXLOS_ATTR_ID(28), + TRANSCEIVER_RXLOS_ATTR_ID(29), + TRANSCEIVER_RXLOS_ATTR_ID(30), + TRANSCEIVER_RXLOS_ATTR_ID(31), + TRANSCEIVER_RXLOS_ATTR_ID(32), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(35), + TRANSCEIVER_RXLOS_ATTR_ID(36), + TRANSCEIVER_RXLOS_ATTR_ID(37), + TRANSCEIVER_RXLOS_ATTR_ID(38), + TRANSCEIVER_RXLOS_ATTR_ID(39), + TRANSCEIVER_RXLOS_ATTR_ID(40), + TRANSCEIVER_RXLOS_ATTR_ID(41), + TRANSCEIVER_RXLOS_ATTR_ID(42), + TRANSCEIVER_RXLOS_ATTR_ID(43), + TRANSCEIVER_RXLOS_ATTR_ID(44), + TRANSCEIVER_RXLOS_ATTR_ID(45), + TRANSCEIVER_RXLOS_ATTR_ID(46), + TRANSCEIVER_RXLOS_ATTR_ID(47), + TRANSCEIVER_RXLOS_ATTR_ID(48), + TRANSCEIVER_RXLOS_ATTR_ID(57), + TRANSCEIVER_RXLOS_ATTR_ID(58), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(5), + TRANSCEIVER_TXFAULT_ATTR_ID(6), + TRANSCEIVER_TXFAULT_ATTR_ID(7), + TRANSCEIVER_TXFAULT_ATTR_ID(8), + TRANSCEIVER_TXFAULT_ATTR_ID(9), + TRANSCEIVER_TXFAULT_ATTR_ID(10), + TRANSCEIVER_TXFAULT_ATTR_ID(11), + TRANSCEIVER_TXFAULT_ATTR_ID(12), + TRANSCEIVER_TXFAULT_ATTR_ID(13), + TRANSCEIVER_TXFAULT_ATTR_ID(14), + TRANSCEIVER_TXFAULT_ATTR_ID(15), + TRANSCEIVER_TXFAULT_ATTR_ID(16), + TRANSCEIVER_TXFAULT_ATTR_ID(17), + TRANSCEIVER_TXFAULT_ATTR_ID(18), + TRANSCEIVER_TXFAULT_ATTR_ID(19), + TRANSCEIVER_TXFAULT_ATTR_ID(20), + TRANSCEIVER_TXFAULT_ATTR_ID(21), + TRANSCEIVER_TXFAULT_ATTR_ID(22), + TRANSCEIVER_TXFAULT_ATTR_ID(23), + TRANSCEIVER_TXFAULT_ATTR_ID(24), + TRANSCEIVER_TXFAULT_ATTR_ID(25), + TRANSCEIVER_TXFAULT_ATTR_ID(26), + TRANSCEIVER_TXFAULT_ATTR_ID(27), + TRANSCEIVER_TXFAULT_ATTR_ID(28), + TRANSCEIVER_TXFAULT_ATTR_ID(29), + TRANSCEIVER_TXFAULT_ATTR_ID(30), + TRANSCEIVER_TXFAULT_ATTR_ID(31), + TRANSCEIVER_TXFAULT_ATTR_ID(32), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(35), + TRANSCEIVER_TXFAULT_ATTR_ID(36), + TRANSCEIVER_TXFAULT_ATTR_ID(37), + TRANSCEIVER_TXFAULT_ATTR_ID(38), + TRANSCEIVER_TXFAULT_ATTR_ID(39), + TRANSCEIVER_TXFAULT_ATTR_ID(40), + TRANSCEIVER_TXFAULT_ATTR_ID(41), + TRANSCEIVER_TXFAULT_ATTR_ID(42), + TRANSCEIVER_TXFAULT_ATTR_ID(43), + TRANSCEIVER_TXFAULT_ATTR_ID(44), + TRANSCEIVER_TXFAULT_ATTR_ID(45), + TRANSCEIVER_TXFAULT_ATTR_ID(46), + TRANSCEIVER_TXFAULT_ATTR_ID(47), + TRANSCEIVER_TXFAULT_ATTR_ID(48), + TRANSCEIVER_TXFAULT_ATTR_ID(57), + TRANSCEIVER_TXFAULT_ATTR_ID(58), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as7326_56x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as7326_56x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO | S_IWUSR, show_status, set_reset, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(35); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(36); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(37); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(38); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(39); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(40); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(41); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(42); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(43); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(44); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(45); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(46); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(47); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(48); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(55); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(56); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(57); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(58); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(57); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(58); + +static struct attribute *as7326_56x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as7326_56x_cpld3_group = { + .attrs = as7326_56x_cpld3_attributes, +}; + +static struct attribute *as7326_56x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + DECLARE_SFP_TRANSCEIVER_ATTR(5), + DECLARE_SFP_TRANSCEIVER_ATTR(6), + DECLARE_SFP_TRANSCEIVER_ATTR(7), + DECLARE_SFP_TRANSCEIVER_ATTR(8), + DECLARE_SFP_TRANSCEIVER_ATTR(9), + DECLARE_SFP_TRANSCEIVER_ATTR(10), + DECLARE_SFP_TRANSCEIVER_ATTR(11), + DECLARE_SFP_TRANSCEIVER_ATTR(12), + DECLARE_SFP_TRANSCEIVER_ATTR(13), + DECLARE_SFP_TRANSCEIVER_ATTR(14), + DECLARE_SFP_TRANSCEIVER_ATTR(15), + DECLARE_SFP_TRANSCEIVER_ATTR(16), + DECLARE_SFP_TRANSCEIVER_ATTR(17), + DECLARE_SFP_TRANSCEIVER_ATTR(18), + DECLARE_SFP_TRANSCEIVER_ATTR(19), + DECLARE_SFP_TRANSCEIVER_ATTR(20), + DECLARE_SFP_TRANSCEIVER_ATTR(21), + DECLARE_SFP_TRANSCEIVER_ATTR(22), + DECLARE_SFP_TRANSCEIVER_ATTR(23), + DECLARE_SFP_TRANSCEIVER_ATTR(24), + DECLARE_SFP_TRANSCEIVER_ATTR(25), + DECLARE_SFP_TRANSCEIVER_ATTR(26), + DECLARE_SFP_TRANSCEIVER_ATTR(27), + DECLARE_SFP_TRANSCEIVER_ATTR(28), + DECLARE_SFP_TRANSCEIVER_ATTR(29), + DECLARE_SFP_TRANSCEIVER_ATTR(30), + NULL +}; + +static const struct attribute_group as7326_56x_cpld2_group = { + .attrs = as7326_56x_cpld2_attributes, +}; + +static struct attribute *as7326_56x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_TRANSCEIVER_PRESENT_ATTR(35), + DECLARE_TRANSCEIVER_PRESENT_ATTR(36), + DECLARE_TRANSCEIVER_PRESENT_ATTR(37), + DECLARE_TRANSCEIVER_PRESENT_ATTR(38), + DECLARE_TRANSCEIVER_PRESENT_ATTR(39), + DECLARE_TRANSCEIVER_PRESENT_ATTR(40), + DECLARE_TRANSCEIVER_PRESENT_ATTR(41), + DECLARE_TRANSCEIVER_PRESENT_ATTR(42), + DECLARE_TRANSCEIVER_PRESENT_ATTR(43), + DECLARE_TRANSCEIVER_PRESENT_ATTR(44), + DECLARE_TRANSCEIVER_PRESENT_ATTR(45), + DECLARE_TRANSCEIVER_PRESENT_ATTR(46), + DECLARE_TRANSCEIVER_PRESENT_ATTR(47), + DECLARE_TRANSCEIVER_PRESENT_ATTR(48), + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_TRANSCEIVER_PRESENT_ATTR(55), + DECLARE_TRANSCEIVER_PRESENT_ATTR(56), + DECLARE_TRANSCEIVER_PRESENT_ATTR(57), + DECLARE_TRANSCEIVER_PRESENT_ATTR(58), + DECLARE_SFP_TRANSCEIVER_ATTR(31), + DECLARE_SFP_TRANSCEIVER_ATTR(32), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(35), + DECLARE_SFP_TRANSCEIVER_ATTR(36), + DECLARE_SFP_TRANSCEIVER_ATTR(37), + DECLARE_SFP_TRANSCEIVER_ATTR(38), + DECLARE_SFP_TRANSCEIVER_ATTR(39), + DECLARE_SFP_TRANSCEIVER_ATTR(40), + DECLARE_SFP_TRANSCEIVER_ATTR(41), + DECLARE_SFP_TRANSCEIVER_ATTR(42), + DECLARE_SFP_TRANSCEIVER_ATTR(43), + DECLARE_SFP_TRANSCEIVER_ATTR(44), + DECLARE_SFP_TRANSCEIVER_ATTR(45), + DECLARE_SFP_TRANSCEIVER_ATTR(46), + DECLARE_SFP_TRANSCEIVER_ATTR(47), + DECLARE_SFP_TRANSCEIVER_ATTR(48), + DECLARE_SFP_TRANSCEIVER_ATTR(57), + DECLARE_SFP_TRANSCEIVER_ATTR(58), + NULL +}; + +static const struct attribute_group as7326_56x_cpld1_group = { + .attrs = as7326_56x_cpld1_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[4] = {0}; + u8 regs[] = {0x9, 0xA, 0xB, 0x18}; + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7326_56x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 56 in order */ + if (data->type == as7326_56x_cpld2) { + values[3] &= 0xF; + } + else { /* as7326_56x_cpld3 */ + values[3] &= 0x3; + } + + return sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[3] = {0}; + u8 regs[] = {0x12, 0x13, 0x14}; + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7326_56x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 24 in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", values[0], values[1], values[2]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_30: + reg = 0x0f + (attr->index-MODULE_PRESENT_1)/8; + mask = 0x1 << ((attr->index - MODULE_PRESENT_1)%8); + break; + case MODULE_PRESENT_31 ... MODULE_PRESENT_48: + reg = 0x10 + (attr->index-MODULE_PRESENT_31)/8; + mask = 0x1 << ((attr->index - MODULE_PRESENT_31)%8); + break; + case MODULE_PRESENT_57 ... MODULE_PRESENT_58: + reg = 0x12; + mask = 0x1 << (( MODULE_PRESENT_58 - attr->index)+2); + break; + case MODULE_PRESENT_49 ... MODULE_PRESENT_56: /*QSFP*/ + reg = 0x13 ; + mask = 0x1 << ((attr->index - MODULE_PRESENT_49)%8); + break; + case MODULE_TXFAULT_1 ... MODULE_TXFAULT_30: + reg = 0x03 + (attr->index - MODULE_TXFAULT_1)/8; + mask = 0x1 << ((attr->index - MODULE_TXFAULT_1)%8); + break; + case MODULE_TXFAULT_31 ... MODULE_TXFAULT_48: + reg = 0x1a + (attr->index-MODULE_TXFAULT_31)/8; + mask = 0x1 << ((attr->index - MODULE_TXFAULT_31)%8); + break; + case MODULE_TXFAULT_57 ... MODULE_TXFAULT_58: + reg = 0x1c; + mask = 0x1 << (( attr->index - MODULE_TXFAULT_57)+2); + break; + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_30: + reg = 0x07 + (attr->index - MODULE_TXDISABLE_1)/8; + mask = 0x1 << ((attr->index - MODULE_TXDISABLE_1)%8); + break; + case MODULE_TXDISABLE_31 ... MODULE_TXDISABLE_48: + reg = 0x14 + (attr->index-MODULE_TXDISABLE_31)/8; + mask = 0x1 << ((attr->index - MODULE_TXDISABLE_31)%8); + break; + case MODULE_TXDISABLE_57 ... MODULE_TXDISABLE_58: + reg = 0x16; + mask = 0x1 << ((attr->index - MODULE_TXDISABLE_57)+2); + break; + case MODULE_RXLOS_1 ... MODULE_RXLOS_30: + reg = 0x0b + (attr->index - MODULE_RXLOS_1)/8; + mask = 0x1 << ((attr->index - MODULE_RXLOS_1)%8); + break; + case MODULE_RXLOS_31 ... MODULE_RXLOS_48: + reg = 0x17 + (attr->index-MODULE_RXLOS_31)/8; + mask = 0x1 << ((attr->index - MODULE_RXLOS_31)%8); + break; + case MODULE_RXLOS_57 ... MODULE_RXLOS_58: + reg = 0x19; + mask = 0x1 << (( attr->index - MODULE_RXLOS_57)+2); + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_56) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as7326_56x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_30: + reg = 0x07 + (attr->index - MODULE_TXDISABLE_1)/8; + mask = 0x1 << ((attr->index - MODULE_TXDISABLE_1)%8); + break; + case MODULE_TXDISABLE_31 ... MODULE_TXDISABLE_48: + reg = 0x14 + (attr->index - MODULE_TXDISABLE_31)/8; + mask = 0x1 << ((attr->index - MODULE_TXDISABLE_31)%8); + break; + case MODULE_TXDISABLE_57 ... MODULE_TXDISABLE_58: + reg = 0x16; + mask = 0x1 << ((attr->index - MODULE_TXDISABLE_57)+2); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7326_56x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as7326_56x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as7326_56x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as7326_56x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as7326_56x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as7326_56x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as7326_56x_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as7326_56x_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) { + case as7326_56x_cpld1: + group = &as7326_56x_cpld1_group; + break; + case as7326_56x_cpld2: + group = &as7326_56x_cpld2_group; + break; + case as7326_56x_cpld3: + group = &as7326_56x_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as7326_56x_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as7326_56x_cpld_remove(struct i2c_client *client) +{ + struct as7326_56x_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as7326_56x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as7326_56x_cpld1: + group = &as7326_56x_cpld1_group; + break; + case as7326_56x_cpld2: + group = &as7326_56x_cpld2_group; + break; + case as7326_56x_cpld3: + group = &as7326_56x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as7326_56x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as7326_56x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as7326_56x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7326_56x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7326_56x_cpld_read); + +int as7326_56x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7326_56x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7326_56x_cpld_write); + +static struct i2c_driver as7326_56x_cpld_driver = { + .driver = { + .name = "as7326_56x_cpld", + .owner = THIS_MODULE, + }, + .probe = as7326_56x_cpld_probe, + .remove = as7326_56x_cpld_remove, + .id_table = as7326_56x_cpld_id, +}; + +static int __init as7326_56x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7326_56x_cpld_driver); +} + +static void __exit as7326_56x_cpld_exit(void) +{ + i2c_del_driver(&as7326_56x_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as7326_56x_cpld_init); +module_exit(as7326_56x_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-handle_mac.service b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-handle_mac.service new file mode 100755 index 000000000000..0e35d5929ef9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-handle_mac.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS7326-56X Platform MAC hnadle service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_handle_idt.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor-fan.service new file mode 100755 index 000000000000..e714561bdf8c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor-fan.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS7326-56X Platform Monitoring FAN service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as7326_monitor_fan.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor-psu.service new file mode 100755 index 000000000000..77fa1fd5c14f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor-psu.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS7326-56X Platform Monitoring PSU service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as7326_monitor_psu.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor.service new file mode 100755 index 000000000000..9da83704715a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS7326-56X Platform Monitoring service +Before=pmon.service +After=as7326-platform-handle_mac.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7326_util.py install +ExecStart=/usr/local/bin/accton_as7326_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/setup.py new file mode 100755 index 000000000000..77114c71285b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env pytho + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7326_56x', + version='1.0', + description='Module to initialize Accton AS7326-56X platforms', + + packages=['as7326_56x'], + package_dir={'as7326_56x': 'as7326-56x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/README new file mode 100755 index 000000000000..ef0d03cf5e45 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/README @@ -0,0 +1,74 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program is free software: you can redistribute it and/or modify +It under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + module - Contains source code of as7326 kernel driver modules. + util - operational scripts. + +Sonic creates a docker container and run building process under it. +If user tries to built new drivers, please get into that docker and +dpkg-buildpackage for them. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS7326-56X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers can be built to individual ko during dpkg-buildpackage. +2. A operational script, accton_as7326_util.py, for device initializatian. + Run "accton_as7326_util.py install" to install drivers. + +To initialize the system, run "accton_as7326_util.py install". +To clean up the drivers & devices, run "accton_as7326_util.py clean". +To dump information of sensors, run "accton_as7326_util.py show". +To dump SFP EEPROM, run "accton_as7326_util.py sff". +To set fan speed, run "accton_as7326_util.py set fan". +To enable/disable SFP emission, run "accton_as7326_util.py set sfp". +To set system LEDs' color, run "accton_as7326_util.py set led" +For more information, run "accton_as7326_util.py --help". + +==================================================================== +Besides applying accton_as7326_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 6 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 8 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor.py new file mode 100755 index 000000000000..1cbcf5b4cf7c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor.py @@ -0,0 +1,340 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 3/23/2018: Roy Lee modify for as7326_56x +# 6/26/2018: Jostar implement by new thermal policy from HW RD +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + from as7326_56x.fanutil import FanUtil + from as7326_56x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as7326_monitor' + +global log_file +global log_level + + +#Default FAN speed: 37.5%(0x05) +#Ori is that detect: (U45_BCM56873 + Thermal sensor_LM75_CPU:0x4B) /2 +#New Detect: (sensor_LM75_49 + Thermal sensor_LM75_CPU_4B) /2 +#Thermal policy: Both F2B and B2F +#1. (sensor_LM75_49 + Thermal sensor_LM75_CPU) /2 =< 39C , Keep 37.5%(0x05) Fan speed +#2. (sensor_LM75_49 + Thermal sensor_LM75_CPU) /2 > 39C , Change Fan speed from 37.5%(0x05) to % 75%(0x0B) +#3. (sensor_LM75_49 + Thermal sensor_LM75_CPU) /2 > 45C , Change Fan speed from 75%(0x0B) to 100%(0x0F) +#4. (sensor_LM75_49 + Thermal sensor_LM75_CPU) /2 > 61C , Send alarm message +#5. (sensor_LM75_49 + Thermal sensor_LM75_CPU) /2 > 66C , Shutdown system +#6. One Fan fail , Change Fan speed to 100%(0x0F) + +#fan-dev 0-11 speed 0x05 Setup fan speed 37.50% +#fan-dev 0-11 speed 0xB Setup fan speed 75% +#fan-dev 0-11 speed 0xF Setup fan speed 100.00% + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_policy_state=1 +fan_fail=0 +alarm_state = 0 #0->default or clear, 1-->alarm detect +test_temp = 0 +test_temp_list = [0, 0, 0, 0, 0, 0] + +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + # static temp var + temp = 0 + new_pwm = 0 + pwm=0 + ori_pwm = 0 + default_pwm=0x4 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setLevel(logging.WARNING) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def get_state_from_fan_policy(self, temp, policy): + state=0 + + #if temp >= 75000: + # state=LEVEL_TEMP_CRITICAL + # return state + logging.debug('temp=%d', temp) + for i in range(0, len(policy)): + #logging.debug('policy[%d][0]=%d, policy[%d][1]=%d', i,policy[i][0],i, policy[i][1]) + if temp > policy[i][0]: + if temp <= policy[i][1]: + state =policy[i][2] + logging.debug ('temp=%d >= policy[%d][0]=%d, temp=%d < policy[%d][1]=%d' , temp, i, policy[i][0], temp, i, policy[i][1]) + logging.debug ('fan_state=%d', state) + if state==0: + state=policy[0][2] #below fan_min, set to default pwm + logging.debug('set default state') + return state + + def manage_fans(self): + + thermal_pwm_list = {} #Ori sort is lm75_48, 49, 4a, 4b, cpu, bcm + # After get pwm, do sort to get max pwm. + LEVEL_FAN_DEF=1 + LEVEL_FAN_MID=2 + LEVEL_FAN_MAX=3 + LEVEL_TEMP_HIGH=4 + LEVEL_TEMP_CRITICAL=5 + + fan_policy_state_pwm_tlb = { + LEVEL_FAN_DEF: [38, 0x4], + LEVEL_FAN_MID: [75, 0xB], + LEVEL_FAN_MAX: [100, 0xE], + LEVEL_TEMP_HIGH: [100, 0xE], + LEVEL_TEMP_CRITICAL: [100, 0xE], + } + global fan_policy_state + global fan_fail + global test_temp + global test_temp_list + global alarm_state + fan_policy ={ + 0: [0, 39000, LEVEL_FAN_DEF], #F2B_policy, B2F_plicy, PWM, reg_val + 1: [39000, 45000, LEVEL_FAN_MID], + 2: [45000, 61000, LEVEL_FAN_MAX], + 3: [61000, 66000, LEVEL_TEMP_HIGH], + 4: [66000, 200000, LEVEL_TEMP_CRITICAL], + } + + thermal = ThermalUtil() + fan = FanUtil() + fan_dir=fan.get_fan_dir(1) + if fan_dir > 1: + fan_dri=1 #something wrong, set fan_dir to default val + if fan_dir < 0: + fan_dri=1 #something wrong, set fan_dir to default val + ori_pwm=fan.get_fan_duty_cycle() + new_pwm=0 + logging.debug('fan_dir=%d, ori_pwm=%d', fan_dir, ori_pwm) + logging.debug('test_temp=%d', test_temp) + if test_temp==0: + temp1 = thermal._get_thermal_val(1) + temp2 = thermal._get_thermal_val(2) + temp3 = thermal._get_thermal_val(3) + temp4 = thermal._get_thermal_val(4) + temp5 = thermal._get_thermal_val(5) + #temp6 = thermal._get_thermal_val(6) + temp6=0 + else: + temp1 = test_temp_list[0] + temp2 = test_temp_list[1] + temp3 = test_temp_list[2] + temp4 = test_temp_list[3] + temp5 = test_temp_list[4] + #temp6 = test_temp_list[5] + temp6=0 + fan_fail=0 + + if temp2==0: + temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% + logging.debug('lm75_49 detect fail, so set temp_get=50000, let fan to 75%') + elif temp2==0: + temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% + logging.debug('lm75_4b detect fail, so set temp_get=50000, let fan to 75%') + else: + temp_get= (temp2 + temp4)/2 # Use (sensor_LM75_49 + Thermal sensor_LM75_CPU_4B) /2 + ori_state=fan_policy_state + fan_policy_state=self.get_state_from_fan_policy(temp_get, fan_policy) + print "temp2=%d"%temp2 + print "temp4=%d"%temp4 + print "temp_get=%d"%temp_get + #print "temp4=%d"%temp4 + #print "temp6=%d"%temp6 + logging.debug('lm75_48=%d, lm75_49=%d, lm75_4a=%d, lm_4b=%d, cpu=%d, bcm=%d', temp1,temp2,temp3,temp4,temp5,temp6) + logging.debug('ori_state=%d, fan_policy_state=%d', ori_state, fan_policy_state) + new_pwm = fan_policy_state_pwm_tlb[fan_policy_state][0] + if fan_fail==0: + logging.debug('new_pwm=%d', new_pwm) + + if fan_fail==0: + if new_pwm!=ori_pwm: + fan.set_fan_duty_cycle(new_pwm) + logging.info('Set fan speed from %d to %d', ori_pwm, new_pwm) + + for i in range (fan.FAN_NUM_1_IDX, fan.FAN_NUM_ON_MAIN_BROAD+1): + if fan.get_fan_status(i)==0: + new_pwm=100 + logging.debug('fan_%d fail, set pwm to 100',i) + if test_temp==0: + fan_fail=1 + fan.set_fan_duty_cycle(new_pwm) + break + else: + fan_fail=0 + + #if fan_policy_state == ori_state: + # return True + #else: + new_state = fan_policy_state + + #logging.warning('Temperature high alarm testing') + if ori_state==LEVEL_FAN_DEF: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected, reboot DUT') + time.sleep(2) + os.system('reboot') + if ori_state==LEVEL_FAN_MID: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if ori_state==LEVEL_FAN_MAX: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if alarm_state==1: + if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if ori_state==LEVEL_TEMP_HIGH: + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if new_state <= LEVEL_FAN_MID: + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if new_state <= LEVEL_FAN_MAX: + if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if ori_state==LEVEL_TEMP_CRITICAL: + if new_state <= LEVEL_FAN_MAX: + logging.warning('Alarm for temperature critical is cleared') + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + global test_temp + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdlt:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + if sys.argv[1]== '-t': + if len(sys.argv)!=8: + print "temp test, need input six temp" + return 0 + + i=0 + for x in range(2, 8): + test_temp_list[i]= int(sys.argv[x])*1000 + i=i+1 + test_temp = 1 + log_level = logging.DEBUG + print test_temp_list + + fan = FanUtil() + fan.set_fan_duty_cycle(38) + print "set default fan speed to 37.5%" + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(5) + +if __name__ == '__main__': + main(sys.argv[1:]) + \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor_fan.py new file mode 100755 index 000000000000..6fa429d01314 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor_fan.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 7/2/2018: Jostar create for as7326-56x +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as7326_monitor_fan' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_state=[2, 2, 2, 2, 2, 2, 2] #init state=2, insert=1, remove=0 +fan_status_state=[2, 2, 2, 2, 2, 2, 2] #init state=2, fault=1, normal=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + #/sys/bus/i2c/devices/11-0066 + #fan1_present, fan6_present + + def __init__(self, log_file, log_level): + + self.fan_num = 6 + self.fan_path = "/sys/bus/i2c/devices/11-0066/" + self.present = { + 0: "fan1_present", + 1: "fan2_present", + 2: "fan3_present", + 3: "fan4_present", + 4: "fan5_present", + 5: "fan6_present", + } + + self.fault = { + 0: "fan1_fault", + 1: "fan2_fault", + 2: "fan3_fault", + 3: "fan4_fault", + 4: "fan5_fault", + 5: "fan6_fault", + } + + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fan(self): + + FAN_STATE_REMOVE = 0 + FAN_STATE_INSERT = 1 + + FAN_STATUS_FAULT = 1 + FAN_STATUS_NORMAL = 0 + + global fan_state + global fan_status_state + + for idx in range (0, self.fan_num): + node = self.fan_path + self.present[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_state[idx]!=1: + fan_state[idx]=FAN_STATE_INSERT + logging.info("FAN-%d present is detected", idx+1); + else: + if fan_state[idx]!=0: + fan_state[idx]=FAN_STATE_REMOVE + logging.warning("Alarm for FAN-%d absent is detected", idx+1) + + for idx in range (0, self.fan_num): + node = self.fan_path + self.fault[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_status_state[idx]!=FAN_STATUS_FAULT: + if fan_state[idx] == FAN_STATE_INSERT: + logging.warning("Alarm for FAN-%d failed is detected", idx+1); + fan_status_state[idx]=FAN_STATUS_FAULT + else: + fan_status_state[idx]=FAN_STATUS_NORMAL + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_fan() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor_psu.py new file mode 100755 index 000000000000..d76c20bd5a9b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor_psu.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 7/2/2018: Jostar create for as7326-56x +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as7326_monitor_psu' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +psu_state=[2, 2] +psu_power_status=[2, 2] +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.psu_num = 2 + self.psu_path = "/sys/bus/i2c/devices/" + self.presence = "/psu_present" + self.oper_status = "/psu_power_good" + self.mapping = { + 0: "17-0051", + 1: "13-0053", + } + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_psu(self): + + PSU_STATE_REMOVE = 0 + PSU_STATE_INSERT = 1 + + PSU_STATUS_NO_POWER = 0 + PSU_STATUS_POWER_GOOD = 1 + + global psu_state + global psu_power_status + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.presence + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if psu_state[idx]!=PSU_STATE_INSERT: + psu_state[idx]=PSU_STATE_INSERT + logging.info("PSU-%d present is detected", idx+1); + #psu_power_status[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it. + else: + if psu_state[idx]!=PSU_STATE_REMOVE: + psu_state[idx]=PSU_STATE_REMOVE + logging.warning("Alarm for PSU-%d absent is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_NO_POWER + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.oper_status + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + #logging.info("content=%s, psu_power_status[%d]=%d", content, idx, psu_power_status[idx]); + if content == "0": + if psu_power_status[idx]!=PSU_STATUS_NO_POWER: + if psu_state[idx]==PSU_STATE_INSERT: + logging.warning("Alarm for PSU-%d fault is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_NO_POWER + else: + if psu_power_status[idx] !=PSU_STATUS_POWER_GOOD: + logging.info("PSU-%d power_good is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_POWER_GOOD + + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_psu() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_util.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_util.py new file mode 100755 index 000000000000..02f98a4667fb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_util.py @@ -0,0 +1,579 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# +# Description: +# Due to adoption of optoe drivers, sideband signals of SFPs are moved +# into cpld drivers. Add a new dict, cpld_of_module, for mapping this +# attributes to corresponding cpld nodes. +# + + + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'as7326_56x' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':6,'thermal':4, 'psu':2, 'sfp':58} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-56 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-56 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_i2c_cpld' , +'modprobe ym2651y' , +'modprobe accton_as7326_56x_fan' , +'modprobe optoe' , +'modprobe accton_as7326_56x_leds' , +'modprobe accton_as7326_56x_psu' ] + +def driver_install(): + global FORCE + + status, output = log_os_system('modprobe i2c_dev', 1) + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + lst = rm.split(" ") + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/accton_'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['11-0066'] , + 'thermal': ['15-0048','15-0049', '15-004a', '15-004b'] , + 'psu': ['17-0051','13-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_', 'module_tx_disable_']} + +sfp_map = [ + 42,41,44,43,47,45,46,50, + 48,49,52,51,53,56,55,54, + 58,57,60,59,61,63,62,64, + 66,68,65,67,69,71,72,70, + 74,73,76,75,77,79,78,80, + 81,82,84,85,83,87,88,86, #port 41~48 + 25,26,27,28,29,30,31,32, #port 49~56 QSFP + 22,23] #port 57~58 SFP+ from CPU NIF. +qsfp_start = 48 +qsfp_end = 56 + +#For sideband signals of SFP/QSFP modules. +cpld_of_module = {'12-0062': list(range(0,30)), + '18-0060': list(range(30,58)) } + + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-24/new_device' , +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-33/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-34/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-35/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-36/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-37/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-38/new_device', +'echo 24c04 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', + +'echo as7326_56x_fan 0x66 > /sys/bus/i2c/devices/i2c-11/new_device ', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-15/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-15/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-15/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-15/new_device', +'echo as7326_56x_psu1 0x51 > /sys/bus/i2c/devices/i2c-17/new_device', +'echo ym2651 0x59 > /sys/bus/i2c/devices/i2c-17/new_device', +'echo as7326_56x_psu2 0x53 > /sys/bus/i2c/devices/i2c-13/new_device', +'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-13/new_device', +'echo as7326_56x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo as7326_56x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as7326_56x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-19/new_device'] + +mknod2 =[ +] + + + +def i2c_order_check(): + # This project has only 1 i2c bus. + return 0 + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x70 is not exist @i2c-1, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + for i in range(0,len(sfp_map)): + if i < qsfp_start or i >= qsfp_end: + status, output =log_os_system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + else: + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0076", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + for lk in cpld_of_module: + if k in cpld_of_module[lk]: + cpld_str = lk + node = key+str(k+1) + path = i2c_prefix+ lk + "/"+ nodes[j] + str(k+1) + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_handle_idt.sh b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_handle_idt.sh new file mode 100755 index 000000000000..60ec158b7229 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_handle_idt.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +if [ -s /usr/local/bin/done_idt_init ];then + echo "There is a done_idt_init file" +else + + cat /etc/init.d/opennsl-modules-4.9.0-7-amd64|grep idt_init.sh + if [ $? -ne 0 ];then + echo "Add idt_init.sh to opennsl-modules for TD3 MAC" + sed -i '/modprobe linux-kernel-bde/i sleep 1' /etc/init.d/opennsl-modules-4.9.0-7-amd64 + sed -i '/sleep/i /usr/local/bin/idt_init.sh' /etc/init.d/opennsl-modules-4.9.0-7-amd64 + sed -i '/idt_init/i echo "IDT init" ' /etc/init.d/opennsl-modules-4.9.0-7-amd64 + sed -i '/IDT init/i echo 1 > /usr/local/bin/done_idt_init' /etc/init.d/opennsl-modules-4.9.0-7-amd64 + + fi + +fi + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/idt_init.sh b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/idt_init.sh new file mode 100755 index 000000000000..7c1f1fcf3a7b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/idt_init.sh @@ -0,0 +1,150 @@ +#!/bin/bash +test_log=/usr/local/bin/check_idt_status.txt +modprobe i2c-i801 +modprobe i2c-dev +i2cset -y 0 0x77 0x1 +i2cset -y 0 0x70 0x1 +i2cget -y 0 0x54 0 b > /dev/null +if [ $? -ne 0 ];then + printf "Device 8v89307(0x54) not found\n" + exit 1 +fi +echo "IDT 82V89307 " +echo "idt init 1" +# Title = --- IDT 82V89307 Registers --- +#Select to Page 0 +i2cset -y 0 0x54 0x2D 0x00 +i2cset -y 0 0x54 0x7F 0x05 +i2cset -y 0 0x54 0x7E 0x85 +i2cset -y 0 0x54 0x7B 0x00 +i2cset -y 0 0x54 0x7A 0x00 +i2cset -y 0 0x54 0x79 0x40 +i2cset -y 0 0x54 0x78 0x06 +i2cset -y 0 0x54 0x73 0x40 +i2cset -y 0 0x54 0x72 0x40 + +# OUT3:25MHz +i2cset -y 0 0x54 0x71 0x0A +i2cset -y 0 0x54 0x70 0x00 + +# OUT1:1pps +i2cset -y 0 0x54 0x6B 0x4E +i2cset -y 0 0x54 0x69 0x00 +i2cset -y 0 0x54 0x68 0x00 +i2cset -y 0 0x54 0x67 0x19 +i2cset -y 0 0x54 0x66 0xAB +i2cset -y 0 0x54 0x65 0x8C +i2cset -y 0 0x54 0x64 0x00 +i2cset -y 0 0x54 0x63 0x00 +i2cset -y 0 0x54 0x62 0x00 +i2cset -y 0 0x54 0x5F 0x00 +i2cset -y 0 0x54 0x5E 0x00 +i2cset -y 0 0x54 0x5D 0x00 +i2cset -y 0 0x54 0x5C 0x78 +i2cset -y 0 0x54 0x5B 0x02 +i2cset -y 0 0x54 0x5A 0xE5 +i2cset -y 0 0x54 0x59 0x88 +i2cset -y 0 0x54 0x58 0x4B +i2cset -y 0 0x54 0x57 0x6C +i2cset -y 0 0x54 0x56 0x6C + +# Lock to DPLL, output 625MHz +i2cset -y 0 0x54 0x55 0x80 +i2cset -y 0 0x54 0x53 0x00 +i2cset -y 0 0x54 0x52 0x81 +i2cset -y 0 0x54 0x50 0x00 +i2cset -y 0 0x54 0x4F 0x00 +i2cset -y 0 0x54 0x4E 0x00 +i2cset -y 0 0x54 0x4C 0xCB +i2cset -y 0 0x54 0x4A 0x00 +i2cset -y 0 0x54 0x45 0x66 +i2cset -y 0 0x54 0x44 0x66 +i2cset -y 0 0x54 0x42 0x80 +i2cset -y 0 0x54 0x41 0x03 +i2cset -y 0 0x54 0x40 0x01 +i2cset -y 0 0x54 0x3F 0x08 +i2cset -y 0 0x54 0x3E 0x04 +i2cset -y 0 0x54 0x3D 0x20 +i2cset -y 0 0x54 0x3C 0x13 +i2cset -y 0 0x54 0x3B 0x00 +i2cset -y 0 0x54 0x3A 0x98 +i2cset -y 0 0x54 0x39 0x01 +i2cset -y 0 0x54 0x38 0xE6 +i2cset -y 0 0x54 0x37 0x04 +i2cset -y 0 0x54 0x36 0xCE +i2cset -y 0 0x54 0x35 0x7C +i2cset -y 0 0x54 0x34 0x01 +i2cset -y 0 0x54 0x33 0x08 +i2cset -y 0 0x54 0x32 0x08 +i2cset -y 0 0x54 0x31 0x08 +i2cset -y 0 0x54 0x30 0x03 +i2cset -y 0 0x54 0x2F 0x23 +i2cset -y 0 0x54 0x2E 0x0B +i2cset -y 0 0x54 0x2D 0x00 +i2cset -y 0 0x54 0x28 0x76 +i2cset -y 0 0x54 0x27 0x54 +i2cset -y 0 0x54 0x25 0x00 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x23 0x06 +i2cset -y 0 0x54 0x1A 0x8C +i2cset -y 0 0x54 0x19 0x8C +i2cset -y 0 0x54 0x18 0x00 +i2cset -y 0 0x54 0x16 0x0D +i2cset -y 0 0x54 0x11 0x00 +i2cset -y 0 0x54 0x10 0x00 +i2cset -y 0 0x54 0x0E 0x3F +i2cset -y 0 0x54 0x0D 0xFF +i2cset -y 0 0x54 0x0C 0x02 +i2cset -y 0 0x54 0x0B 0xA1 +i2cset -y 0 0x54 0x0A 0x89 +i2cset -y 0 0x54 0x09 0xA2 +i2cset -y 0 0x54 0x08 0x32 +i2cset -y 0 0x54 0x06 0x00 +i2cset -y 0 0x54 0x05 0x00 +i2cset -y 0 0x54 0x04 0x00 +i2cset -y 0 0x54 0x03 0x00 +i2cset -y 0 0x54 0x02 0x05 +i2cset -y 0 0x54 0x01 0x33 +i2cset -y 0 0x54 0x00 0x91 + +echo "idt init 2" +# PreDivider_Parameters +#IN1 +i2cset -y 0 0x54 0x23 0x05 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x25 0x00 +#IN2 +i2cset -y 0 0x54 0x23 0x06 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x25 0x00 +#IN3 +i2cset -y 0 0x54 0x23 0x03 +i2cset -y 0 0x54 0x24 0x00 +i2cset -y 0 0x54 0x25 0x00 + +echo "idt init 3" +# Page1_Parameters +#Select to Page 1 +i2cset -y 0 0x54 0x2D 0x01 +i2cset -y 0 0x54 0x30 0x03 +i2cset -y 0 0x54 0x31 0x08 +i2cset -y 0 0x54 0x32 0x08 +i2cset -y 0 0x54 0x33 0x08 +i2cset -y 0 0x54 0x35 0x7C +i2cset -y 0 0x54 0x36 0xCE +i2cset -y 0 0x54 0x37 0x04 +i2cset -y 0 0x54 0x38 0xE6 +i2cset -y 0 0x54 0x39 0x01 +i2cset -y 0 0x54 0x3A 0x98 +i2cset -y 0 0x54 0x3B 0x00 +i2cset -y 0 0x54 0x3C 0x13 +i2cset -y 0 0x54 0x3D 0x20 +#Return to Page 0 +i2cset -y 0 0x54 0x2D 0x00 + +echo "idt init 4" +#reset the in-path mux +i2cset -y 0 0x70 0x0 +i2cset -y 0 0x77 0x0 + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/Makefile new file mode 100644 index 000000000000..d9566355b849 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/Makefile @@ -0,0 +1,2 @@ +obj-m:=accton_as7712_32x_fan.o accton_as7712_32x_sfp.o leds-accton_as7712_32x.o \ + accton_as7712_32x_psu.o accton_i2c_cpld.o ym2651y.o diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_fan.c new file mode 100755 index 000000000000..73dd36c2883e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_fan.c @@ -0,0 +1,634 @@ +/* + * A hwmon driver for the Accton as7712 32x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7712_32x_fan" + +#define NUM_THERMAL_SENSORS (3) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a} + +#define IN +#define OUT + +static struct as7712_32x_fan_data *as7712_32x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_enable(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); + + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7712_32x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + u8 enable; + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index##_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr, \ + &sensor_dev_attr_pwm##index##_enable.dev_attr.attr + +#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ + static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr + + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); +/* System temperature for fancontrol */ +DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR(); + +static struct attribute *as7712_32x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + DECLARE_FAN_SYSTEM_TEMP_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7712_32x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7712_32x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as7712_32x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + data->enable = value; + if (value == 0) + { + return set_duty_cycle(dev, da, buf, FAN_MAX_DUTY_CYCLE); + } + return count; +} + +static ssize_t get_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev); + + return sprintf(buf, "%u\n", data->enable); +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0) + return -EINVAL; + + value = (value > FAN_MAX_DUTY_CYCLE)? FAN_MAX_DUTY_CYCLE : value; + + as7712_32x_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as7712_32x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static bool lm75_addr_mached(unsigned short addr) +{ + int i; + unsigned short addrs[] = THERMAL_SENSORS_ADDRS; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) + { + if( addr == addrs[i]) + return 1; + } + return 0; +} + +/* Struct and define are copied from drivers/hwmon/hwmon.c. */ +struct hwmon_device { + const char *name; + struct device dev; + const struct hwmon_chip_info *chip; + + struct attribute_group group; + const struct attribute_group **groups; +}; +#define to_hwmon_device(d) container_of(d, struct hwmon_device, dev) + +/*Find the 1st valid dev of all childs, it supposes to have only 1 child.*/ +static int is_valid_dev(struct device *dev, void *data) +{ + struct hwmon_device *hwmon_dev; + + if(dev) { + hwmon_dev = to_hwmon_device(dev); + if(hwmon_dev) { + int ret; + long t; + ret = hwmon_dev->chip->ops->read(dev, hwmon_temp, hwmon_temp_input, + 0, &t); + return !ret; + } + } + return 0; +} + +static int hwmon_get_temp(struct device *dev, long *mini_cel) +{ + struct hwmon_device *hwmon_dev = to_hwmon_device(dev); + int ret = 0; + + if(hwmon_dev) { + long t; + ret = hwmon_dev->chip->ops->read(dev, hwmon_temp, hwmon_temp_input, + 0, &t); + if (ret < 0) + return ret; + + *mini_cel = t; + } + return ret; +} + +/* Find devices under i2c_bus which with driver = lm75. + * Use the device to find its descendent hwmon_dev and read the temperature. + */ +static int _find_lm75_device(struct device *dev, void *data) +{ + struct device_driver *driver; + struct as7712_32x_fan_data *prv = data; + char *driver_name = THERMAL_SENSORS_DRIVER; + struct i2c_client *client; + + driver = dev->driver; + if (driver && driver->name && + strcmp(driver->name, driver_name) == 0) + { + + client = to_i2c_client(dev); + if (client) + { + long miniCelsius = 0; + struct device *child_dev; + + if (! lm75_addr_mached(client->addr)) + { + return 0; + } + + child_dev = device_find_child(dev, NULL, is_valid_dev); + if(child_dev) { + int ret = hwmon_get_temp(child_dev, &miniCelsius); + if (ret < 0) + return ret; + + prv->system_temp += miniCelsius; + prv->sensors_found++; + + } + } + } + return 0; +} + +/*Find all lm75 devices and return sum of temperatures.*/ +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + ssize_t ret = 0; + struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev); + + data->system_temp=0; + data->sensors_found=0; + i2c_for_each_dev(data, _find_lm75_device); + if (NUM_THERMAL_SENSORS != data->sensors_found) + { + dev_dbg(dev,"only %d of %d temps are found\n", + data->sensors_found, NUM_THERMAL_SENSORS); + data->system_temp = INT_MAX; + } + ret = sprintf(buf, "%d\n",data->system_temp); + return ret; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7712_32x_fan_group = { + .attrs = as7712_32x_fan_attributes, +}; + +static struct as7712_32x_fan_data *as7712_32x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7712_32x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7712_32x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7712_32x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7712_32x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7712_32x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7712_32x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->enable = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7712_32x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7712_32x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7712_32x_fan_remove(struct i2c_client *client) +{ + struct as7712_32x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7712_32x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7712_32x_fan_id[] = { + { "as7712_32x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7712_32x_fan_id); + +static struct i2c_driver as7712_32x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7712_32x_fan_probe, + .remove = as7712_32x_fan_remove, + .id_table = as7712_32x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7712_32x_fan_init(void) +{ + return i2c_add_driver(&as7712_32x_fan_driver); +} + +static void __exit as7712_32x_fan_exit(void) +{ + i2c_del_driver(&as7712_32x_fan_driver); +} + +module_init(as7712_32x_fan_init); +module_exit(as7712_32x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7712_32x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_psu.c new file mode 100644 index 000000000000..233aef78e09f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_psu.c @@ -0,0 +1,288 @@ +/* + * An hwmon driver for accton as7712_32x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as7712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7712_32x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[9]; /* Model name, read from eeprom */ +}; + +static struct as7712_32x_psu_data *as7712_32x_psu_update_device(struct device *dev); + +enum as7712_32x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as7712_32x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7712_32x_psu_data *data = as7712_32x_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7712_32x_psu_data *data = as7712_32x_psu_update_device(dev); + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as7712_32x_psu_group = { + .attrs = as7712_32x_psu_attributes, +}; + +static int as7712_32x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7712_32x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7712_32x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7712_32x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7712_32x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7712_32x_psu_remove(struct i2c_client *client) +{ + struct as7712_32x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7712_32x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7712_32x_psu1, + as7712_32x_psu2 +}; + +static const struct i2c_device_id as7712_32x_psu_id[] = { + { "as7712_32x_psu1", as7712_32x_psu1 }, + { "as7712_32x_psu2", as7712_32x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7712_32x_psu_id); + +static struct i2c_driver as7712_32x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7712_32x_psu", + }, + .probe = as7712_32x_psu_probe, + .remove = as7712_32x_psu_remove, + .id_table = as7712_32x_psu_id, + .address_list = normal_i2c, +}; + +static int as7712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as7712_32x_psu_data *as7712_32x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7712_32x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as7712_32x update\n"); + + /* Read psu status */ + status = accton_i2c_cpld_read(0x60, 0x2); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as7712_32x_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as7712_32x_psu_init(void) +{ + return i2c_add_driver(&as7712_32x_psu_driver); +} + +static void __exit as7712_32x_psu_exit(void) +{ + i2c_del_driver(&as7712_32x_psu_driver); +} + +module_init(as7712_32x_psu_init); +module_exit(as7712_32x_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7712_32x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_sfp.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_sfp.c new file mode 100644 index 000000000000..4668f5a7f050 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_sfp.c @@ -0,0 +1,1171 @@ +/* + * SFP driver for accton as7712_32x sfp + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "as7712_32x_sfp" + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define NUM_OF_SFP_PORT 32 +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) +#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1) + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 +#define SFF8472_10G_BASE_MASK 0xF0 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { SFP_EEPROM_A0_I2C_ADDR, SFP_EEPROM_A2_I2C_ADDR, I2C_CLIENT_END }; + +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +sfp1, sfp2, sfp3, sfp4, sfp5, sfp6, sfp7, sfp8, +sfp9, sfp10, sfp11, sfp12, sfp13, sfp14, sfp15, sfp16, +sfp17, sfp18, sfp19, sfp20, sfp21, sfp22, sfp23, sfp24, +sfp25, sfp26, sfp27, sfp28, sfp29, sfp30, sfp31, sfp32 +}; + +static const struct i2c_device_id sfp_device_id[] = { +{ "sfp1", sfp1 }, { "sfp2", sfp2 }, { "sfp3", sfp3 }, { "sfp4", sfp4 }, +{ "sfp5", sfp5 }, { "sfp6", sfp6 }, { "sfp7", sfp7 }, { "sfp8", sfp8 }, +{ "sfp9", sfp9 }, { "sfp10", sfp10 }, { "sfp11", sfp11 }, { "sfp12", sfp12 }, +{ "sfp13", sfp13 }, { "sfp14", sfp14 }, { "sfp15", sfp15 }, { "sfp16", sfp16 }, +{ "sfp17", sfp17 }, { "sfp18", sfp18 }, { "sfp19", sfp19 }, { "sfp20", sfp20 }, +{ "sfp21", sfp21 }, { "sfp22", sfp22 }, { "sfp23", sfp23 }, { "sfp24", sfp24 }, +{ "sfp25", sfp25 }, { "sfp26", sfp26 }, { "sfp27", sfp27 }, { "sfp28", sfp28 }, +{ "sfp29", sfp29 }, { "sfp30", sfp30 }, { "sfp31", sfp31 }, { "sfp32", sfp32 }, +{} +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28 +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[2]; /* index 0 => device id + 1 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 2 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +}; + +struct sfp_ddm_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + struct eeprom_data eeprom; +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + u64 port_reset; /* reset status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct sfp_ddm_data *ddm; + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + TX_DISABLE_ALL, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL, + PORT_RESET +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x30, 0x31, 0x32, 0x33}; + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + + /* Read present status of port 1~32 */ + data->present = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = accton_i2c_cpld_read(0x60, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); + data->present |= (u64)status << (i*8); + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) +{ + return NULL; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + return 0; +} + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = sfp_update_present(client); + return (data->present & BIT_INDEX(data->port)) ? 0 : 1; +} + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (PRESENT_ALL == attr->index) { + + } + + /* PRESENT */ + return sprintf(buf, "%d\n", sfp_is_port_present(client, data->port)); +} + +static struct sfp_port_data *sfp_update_port_type(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 buf = 0; + int status; + + mutex_lock(&data->update_lock); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + if (buf != SFF8024_DEVICE_ID_SFP) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + status = sfp_eeprom_read(data->client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); + data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; + break; + } + case DRIVER_TYPE_QSFP: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); + switch (buf) { + case SFF8024_DEVICE_ID_QSFP: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; + break; + case SFF8024_DEVICE_ID_QSFP_PLUS: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + case SFF8024_DEVICE_ID_QSFP28: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + default: + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + break; + } + default: + break; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (!sfp_is_port_present(client, data->port)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_type(dev); + return sprintf(buf, "%d\n", data->port_type); +} + + +static struct sfp_port_data *sfp_update_port_reset(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x4, 0x5, 0x6, 0x7}; + + mutex_lock(&data->update_lock); + + /* Read reset status of port 1~32 */ + data->port_reset = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = accton_i2c_cpld_read(0x60, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("reset status = 0x%x", status); + data->port_reset |= (u64)status << (i*8); + } + + DEBUG_PRINT("reset status = 0x%llx", data->port_reset); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int is_reset = 0; + + if (!sfp_is_port_present(client, data->port)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_reset(client); + is_reset = (data->port_reset & BIT_INDEX(data->port))? 0 : 1; + + return sprintf(buf, "%d\n", is_reset); +} + +static ssize_t sfp_set_port_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; + long is_reset; + int error; + + error = kstrtol(buf, 10, &is_reset); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + cpld_reg = 0x4 + data->port / 8; + cpld_bit = 1 << (data->port % 8); + + cpld_val = accton_i2c_cpld_read(0x60, cpld_reg); + DEBUG_PRINT("current cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + /* Update reset status. CPLD defined 0 is reset state, 1 is normal state. + * is_reset: 0 is not reset. 1 is reset. + */ + if (is_reset == 0) { + data->port_reset |= BIT_INDEX(data->port); + cpld_val |= cpld_bit; + } + else { + data->port_reset &= ~BIT_INDEX(data->port); + cpld_val &= ~cpld_bit; + } + + accton_i2c_cpld_write(0x60, cpld_reg, cpld_val); + DEBUG_PRINT("write cpld reg = 0x%x value = 0x%x cpld_bit = 0x%x", cpld_reg, cpld_val,cpld_bit); + + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + dev_dbg(dev, "Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + } + msleep(200); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + mutex_unlock(&data->update_lock); + return data; + +exit: + mutex_unlock(&data->update_lock); + return NULL; +} + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (!sfp_is_port_present(client, data->port)) { + return -ENODEV; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + switch (attr->index) { + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = (data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)) ? 1 : 0; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = (data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)) ? 1 : 0; + break; + case TX_DISABLE_ALL: + val = ((data->qsfp->status[1] & 0xF) == 0xF) ? 1 : 0; + break; + + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = (data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)) ? 1 : 0; + break; + default: + break; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int result; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + result = kstrtol(buf, 10, &disable); + if (result) { + return result; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + mutex_lock(&data->update_lock); + + DEBUG_PRINT ("disable:%ld %d==%d %u\r\n", disable, attr->index, TX_DISABLE_ALL, data->qsfp->status[1]); + + if (attr->index == TX_DISABLE_ALL) + { + data->qsfp->status[1] = disable? 0xF:0; + } + else + { + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); + } + } + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + result = sfp_eeprom_write(client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + char ddm; + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (!sfp_is_port_present(client, data->port)) { + return -ENODEV; + } + + status = sfp_eeprom_read(data->client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); + if (status < 0) { + return -EIO; + } + + return sprintf(buf, "%d\n", (ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK) ? 1 : 0); +} + +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + data = sfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + switch (attr->index) { + case TX_FAULT: + index = 0; + break; + case TX_DISABLE: + index = 1; + break; + case RX_LOS: + index = 2; + break; + default: + break; + } + + val = (data->ddm->status[index] & BIT_INDEX(data->port)) ? 1 : 0; + return sprintf(buf, "%d\n", val); +} + +/* SFP/QSFP common attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT_RESET); + +/* QSFP attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable_all, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE_ALL); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); +static struct attribute *qsfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_port_reset.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable_all.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, + NULL +}; + +/* SFP msa attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED); +static struct attribute *sfp_msa_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr, + NULL +}; + +/* SFP ddm attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); +static struct attribute *sfp_ddm_attributes[] = { + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + NULL +}; + +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return data_len; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_write_byte_data(client, command, *data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return 1; +#endif + + +} + + +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_write(data, buf, off, count); +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + //result = data_len; + +abort: + return result; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_read_byte_data(client, command); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result); + goto abort; + } + + *data = (u8)result; + result = 1; + +abort: + return result; +#endif +} + +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_read(data, buf, off, count); +} + +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group sfp_ddm_group = { + .attrs = sfp_ddm_attributes, +}; + +static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_ddm_data **data) +{ + int status; + struct sfp_ddm_data *ddm; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); + if (!ddm) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = ddm; + dev_info(&client->dev, "sfp ddm '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); +exit_free: + kfree(ddm); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); + if (status) { + goto exit_remove; + } + + /* Bring QSFPs out of reset + as6712_32x_i2c_cpld_write(0x62, 0x4, 0xFF); + as6712_32x_i2c_cpld_write(0x62, 0x5, 0xFF); + as6712_32x_i2c_cpld_write(0x64, 0x4, 0xFF); + as6712_32x_i2c_cpld_write(0x64, 0x5, 0xFF);*/ + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct sfp_port_data *data = NULL; + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + if (client->addr != SFP_EEPROM_A0_I2C_ADDR) { + return -ENODEV; + } + + data->driver_type = DRIVER_TYPE_QSFP; + return qsfp_probe(client, dev_id, &data->qsfp); +} + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_SFP_DDM: + return sfp_ddm_remove(client, data->ddm); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + + return 0; +} + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7712_32x_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_i2c_cpld.c new file mode 120000 index 000000000000..39c0826d16fd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_i2c_cpld.c @@ -0,0 +1 @@ +../../common/modules/accton_i2c_cpld.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_pmbus_3y.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_pmbus_3y.c new file mode 120000 index 000000000000..7504a0556e18 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_pmbus_3y.c @@ -0,0 +1 @@ +../../common/modules/accton_pmbus_3y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/leds-accton_as7712_32x.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/leds-accton_as7712_32x.c new file mode 100644 index 000000000000..5e1a9282db0e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/leds-accton_as7712_32x.c @@ -0,0 +1,690 @@ +/* + * A LED driver for the accton_as7712_32x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int accton_i2c_cpld_read (unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "accton_as7712_32x_led" +#define ENABLE_PORT_LED 1 + +struct accton_as7712_32x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct accton_as7712_32x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +#if (ENABLE_PORT_LED == 1) +#define LED_TYPE_PORT_LED(port) \ + LED_TYPE_PORT##port##_LED0, \ + LED_TYPE_PORT##port##_LED1, \ + LED_TYPE_PORT##port##_LED2, \ + LED_TYPE_PORT##port##_LED3 +#endif + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2, +#if (ENABLE_PORT_LED == 1) + LED_TYPE_PORT_LED(0), + LED_TYPE_PORT_LED(1), + LED_TYPE_PORT_LED(2), + LED_TYPE_PORT_LED(3), + LED_TYPE_PORT_LED(4), + LED_TYPE_PORT_LED(5), + LED_TYPE_PORT_LED(6), + LED_TYPE_PORT_LED(7), + LED_TYPE_PORT_LED(8), + LED_TYPE_PORT_LED(9), + LED_TYPE_PORT_LED(10), + LED_TYPE_PORT_LED(11), + LED_TYPE_PORT_LED(12), + LED_TYPE_PORT_LED(13), + LED_TYPE_PORT_LED(14), + LED_TYPE_PORT_LED(15), + LED_TYPE_PORT_LED(16), + LED_TYPE_PORT_LED(17), + LED_TYPE_PORT_LED(18), + LED_TYPE_PORT_LED(19), + LED_TYPE_PORT_LED(20), + LED_TYPE_PORT_LED(21), + LED_TYPE_PORT_LED(22), + LED_TYPE_PORT_LED(23), + LED_TYPE_PORT_LED(24), + LED_TYPE_PORT_LED(25), + LED_TYPE_PORT_LED(26), + LED_TYPE_PORT_LED(27), + LED_TYPE_PORT_LED(28), + LED_TYPE_PORT_LED(29), + LED_TYPE_PORT_LED(30), + LED_TYPE_PORT_LED(31), +#endif +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as7712_32x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as7712_32x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7712_32x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = accton_as7712_32x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as7712_32x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as7712_32x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7712_32x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as7712_32x_led_diag_get(struct led_classdev *cdev) +{ + accton_as7712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as7712_32x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7712_32x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_as7712_32x_led_loc_get(struct led_classdev *cdev) +{ + accton_as7712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_as7712_32x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_as7712_32x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +#if (ENABLE_PORT_LED == 1) +#define PORT_LED_COLOR_MASK (0x7 << 2) +#define PORT_LED_COLOR1_REG_VAL (0x0 << 2) +#define PORT_LED_COLOR2_REG_VAL (0x1 << 2) +#define PORT_LED_COLOR3_REG_VAL (0x2 << 2) +#define PORT_LED_COLOR4_REG_VAL (0x3 << 2) +#define PORT_LED_COLOR5_REG_VAL (0x4 << 2) +#define PORT_LED_COLOR6_REG_VAL (0x5 << 2) +#define PORT_LED_COLOR7_REG_VAL (0x6 << 2) +#define PORT_LED_COLOR8_REG_VAL (0x7 << 2) + +static int accton_as7712_32x_port_led_read_value(unsigned short cpld_addr, u8 reg) +{ + return accton_i2c_cpld_read(cpld_addr, reg); +} + +static int accton_as7712_32x_port_led_write_value(unsigned short cpld_addr, u8 reg, u8 value) +{ + return accton_i2c_cpld_write(cpld_addr, reg, value); +} + +static int port_led_mode_to_cpld_val(int mode) +{ + u8 color = 0; + u8 blinking = 0; + u8 on = 1 << 0; + + switch (mode) { + case LED_MODE_WHITE_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_WHITE: color = 0x0 << 2; + break; + case LED_MODE_YELLOW_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_YELLOW: color = 0x1 << 2; + break; + case LED_MODE_ORANGE_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_ORANGE: color = 0x2 << 2; + break; + case LED_MODE_PURPLE_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_PURPLE: color = 0x3 << 2; + break; + case LED_MODE_CYAN_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_CYAN: color = 0x4 << 2; + break; + case LED_MODE_RED_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_RED: color = 0x5 << 2; + break; + case LED_MODE_GREEN_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_GREEN: color = 0x6 << 2; + break; + case LED_MODE_BLUE_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_BLUE: color = 0x7 << 2; + break; + case LED_MODE_OFF: on = 0 << 0; + break; + default: + return -EINVAL; + } + + return (color | blinking | on); +} + +static int cpld_val_to_port_led_mode(uint8_t value) +{ + int on = (value & 0x1); + int blinking = (value & 0x2); + int color = (value & PORT_LED_COLOR_MASK) ; + + if (!on) { + return LED_MODE_OFF; + } + + switch (color) { + case PORT_LED_COLOR1_REG_VAL: + return blinking ? LED_MODE_WHITE_BLINKING : LED_MODE_WHITE; + case PORT_LED_COLOR2_REG_VAL: + return blinking ? LED_MODE_YELLOW_BLINKING : LED_MODE_YELLOW; + case PORT_LED_COLOR3_REG_VAL: + return blinking ? LED_MODE_ORANGE_BLINKING : LED_MODE_ORANGE; + case PORT_LED_COLOR4_REG_VAL: + return blinking ? LED_MODE_PURPLE_BLINKING : LED_MODE_PURPLE; + case PORT_LED_COLOR5_REG_VAL: + return blinking ? LED_MODE_CYAN_BLINKING : LED_MODE_CYAN; + case PORT_LED_COLOR6_REG_VAL: + return blinking ? LED_MODE_RED_BLINKING : LED_MODE_RED; + case PORT_LED_COLOR7_REG_VAL: + return blinking ? LED_MODE_GREEN_BLINKING : LED_MODE_GREEN; + case PORT_LED_COLOR8_REG_VAL: + return blinking ? LED_MODE_BLUE_BLINKING : LED_MODE_BLUE; + default: + return -EINVAL;; + } +} + + +static void accton_as7712_32x_port_led_set(struct led_classdev *cdev, + enum led_brightness led_light_mode) +{ + unsigned int port, lid; + unsigned short cpld_addr; + u8 reg, value; + sscanf(cdev->name, "accton_as7712_32x_led::port%u_led%u", &port, &lid); + + if (port > 32 || lid > 4) { + dev_dbg(&ledctl->pdev->dev, "Port(%u), Led_id(%u) not match\n", port, lid); + return; + } + + cpld_addr = (port < 16) ? 0x64 : 0x62; + reg = (0x50 + (port % 16) * 4 + lid); + value = port_led_mode_to_cpld_val(led_light_mode); + + if (value < 0) { + dev_dbg(&ledctl->pdev->dev, "Unknow port led mode(%d)\n", led_light_mode); + return; + } + + accton_as7712_32x_port_led_write_value(cpld_addr, reg, value); +} + +static enum led_brightness accton_as7712_32x_port_led_get(struct led_classdev *cdev) +{ + unsigned int port, lid; + unsigned short cpld_addr; + u8 reg, value; + sscanf(cdev->name, "accton_as7712_32x_led::port%u_led%u", &port, &lid); + + if (port > 32 || lid > 4) { + dev_dbg(&ledctl->pdev->dev, "Port(%u), Led_id(%u) not match\n", port, lid); + return -EINVAL; + } + + cpld_addr = (port < 16) ? 0x64 : 0x62; + reg = (0x50 + (port % 16) * 4 + lid); + value = accton_as7712_32x_port_led_read_value(cpld_addr, reg); + + if (value < 0) { + dev_dbg(&ledctl->pdev->dev, "Unable to read reg value from cpld(0x%x), reg(0x%x)\n", cpld_addr, reg); + return value; + } + + return cpld_val_to_port_led_mode(value); +} + +#define _PORT_LED_CLASSDEV(port, lid) \ + [LED_TYPE_PORT##port##_LED##lid] = { \ + .name = "accton_as7712_32x_led::port"#port"_led"#lid,\ + .default_trigger = "unused", \ + .brightness_set = accton_as7712_32x_port_led_set, \ + .brightness_get = accton_as7712_32x_port_led_get, \ + .max_brightness = LED_MODE_CYAN_BLINKING, \ + } + +#define PORT_LED_CLASSDEV(port) \ + _PORT_LED_CLASSDEV(port, 0),\ + _PORT_LED_CLASSDEV(port, 1),\ + _PORT_LED_CLASSDEV(port, 2),\ + _PORT_LED_CLASSDEV(port, 3) +#endif + +static struct led_classdev accton_as7712_32x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_as7712_32x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as7712_32x_led_diag_set, + .brightness_get = accton_as7712_32x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "accton_as7712_32x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as7712_32x_led_loc_set, + .brightness_get = accton_as7712_32x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "accton_as7712_32x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as7712_32x_led_auto_set, + .brightness_get = accton_as7712_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "accton_as7712_32x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as7712_32x_led_auto_set, + .brightness_get = accton_as7712_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as7712_32x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as7712_32x_led_auto_set, + .brightness_get = accton_as7712_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +#if (ENABLE_PORT_LED == 1) + PORT_LED_CLASSDEV(0), + PORT_LED_CLASSDEV(1), + PORT_LED_CLASSDEV(2), + PORT_LED_CLASSDEV(3), + PORT_LED_CLASSDEV(4), + PORT_LED_CLASSDEV(5), + PORT_LED_CLASSDEV(6), + PORT_LED_CLASSDEV(7), + PORT_LED_CLASSDEV(8), + PORT_LED_CLASSDEV(9), + PORT_LED_CLASSDEV(10), + PORT_LED_CLASSDEV(11), + PORT_LED_CLASSDEV(12), + PORT_LED_CLASSDEV(13), + PORT_LED_CLASSDEV(14), + PORT_LED_CLASSDEV(15), + PORT_LED_CLASSDEV(16), + PORT_LED_CLASSDEV(17), + PORT_LED_CLASSDEV(18), + PORT_LED_CLASSDEV(19), + PORT_LED_CLASSDEV(20), + PORT_LED_CLASSDEV(21), + PORT_LED_CLASSDEV(22), + PORT_LED_CLASSDEV(23), + PORT_LED_CLASSDEV(24), + PORT_LED_CLASSDEV(25), + PORT_LED_CLASSDEV(26), + PORT_LED_CLASSDEV(27), + PORT_LED_CLASSDEV(28), + PORT_LED_CLASSDEV(29), + PORT_LED_CLASSDEV(30), + PORT_LED_CLASSDEV(31), +#endif +}; + +static int accton_as7712_32x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7712_32x_leds); i++) { + led_classdev_suspend(&accton_as7712_32x_leds[i]); + } + + return 0; +} + +static int accton_as7712_32x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7712_32x_leds); i++) { + led_classdev_resume(&accton_as7712_32x_leds[i]); + } + + return 0; +} + +static int accton_as7712_32x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as7712_32x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as7712_32x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as7712_32x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as7712_32x_leds[i]); + } + } + + return ret; +} + +static int accton_as7712_32x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as7712_32x_leds); i++) { + led_classdev_unregister(&accton_as7712_32x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as7712_32x_led_driver = { + .probe = accton_as7712_32x_led_probe, + .remove = accton_as7712_32x_led_remove, + .suspend = accton_as7712_32x_led_suspend, + .resume = accton_as7712_32x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as7712_32x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as7712_32x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as7712_32x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as7712_32x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as7712_32x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as7712_32x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as7712_32x_led_driver); + kfree(ledctl); +} + +module_init(accton_as7712_32x_led_init); +module_exit(accton_as7712_32x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7712_32x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/pmbus.h new file mode 120000 index 000000000000..b0e1a57107fd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/pmbus.h @@ -0,0 +1 @@ +../../common/modules/pmbus.h \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/service/as7712-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/service/as7712-platform-init.service new file mode 100755 index 000000000000..d5d25b6cde04 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/service/as7712-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Accton AS7712-32X Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/accton_as7712_util.py install +ExecStop=/usr/local/bin/accton_as7712_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/setup.py new file mode 100755 index 000000000000..09c763c84f01 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7712_32x', + version='1.0', + description='Module to initialize Accton AS7712-32X platforms', + + packages=['as7712_32x'], + package_dir={'as7712_32x': 'as7712-32x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/utils/README new file mode 100755 index 000000000000..0b9fc1633999 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/utils/README @@ -0,0 +1,60 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program is free software: you can redistribute it and/or modify +It under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +To initialize the system, run "accton_as7712_util.py install". +To clean up the drivers & devices, run "accton_as7712_util.py clean". +To dump information of sensors, run "accton_as7712_util.py show". +To dump SFP EEPROM, run "accton_as7712_util.py sff". +To set fan speed, run "accton_as7712_util.py set fan". +To enable/disable SFP emission, run "accton_as7712_util.py set sfp". +To set system LEDs' color, run "accton_as7712_util.py set led" +For more information, run "accton_as7712_util.py --help". + +==================================================================== +Besides applying accton_as7712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +LED controls can be found under /sys/class/leds. The sysfs interface +color mappings are as follows: +Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + +There are 5 system LEDs, loc, diag, fan, ps1, and ps2. +They are lit automatically by CPLD, but the loc and diag. +The loc led has only 1 color, blue. +The diag one has 3 colors: red, amber, and green. + +Fan controls can be found in /sys/bus/i2c/devices/2-0066. +There are 12 fans inside 6 fan modules. +All fans share 1 duty setting, ranged from 0~100. + +Three temperature sensors are controlled by the lm75 kernel modules. +They should already be visible under /sys/bus/i2c/drivers/lm75/. + +Two power supplies are controlled by the CPLD. +Here provide their status under +/sys/bus/i2c/devices/10-0050 and /sys/bus/i2c/devices/11-0053. + +There are 32 QSFP+ modules are equipped. +Apply "accton_as7712_util.py show" to get their status. +Apply "accton_as7712_util.py set sfp" to turn on/off light transmission. +Apply "accton_as7712_util.py sff" to dump EEPROM information. +Before operating on that QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/utils/accton_as7712_util.py b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/utils/accton_as7712_util.py new file mode 100755 index 000000000000..c8b755b85b69 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/utils/accton_as7712_util.py @@ -0,0 +1,569 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'as7712_32x' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':6,'thermal':4, 'psu':2, 'sfp':32} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_i2c_cpld' , +'modprobe ym2651y' , +'modprobe accton_as7712_32x_fan' , +'modprobe optoe' , +'modprobe leds-accton_as7712_32x' , +'modprobe accton_as7712_32x_psu' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/accton_'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['2-0066'] , + 'thermal': ['3-0048','3-0049', '3-004a', '3-004b'] , + 'psu': ['10-0050','11-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present', 'sfp_tx_disable_all']} + +sfp_map = [22,23,24,25,27,26,29,28, + 18,19,20,21,30,31,32,33, + 34,35,36,37,46,47,48,49, + 38,39,40,41,42,43,44,45] +mknod =[ +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', + +'echo as7712_32x_fan 0x66 > /sys/bus/i2c/devices/i2c-2/new_device ', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as7712_32x_psu1 0x53 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as7712_32x_psu2 0x50 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo cpld_as7712 0x60 > /sys/bus/i2c/devices/i2c-4/new_device', +'echo cpld_plain 0x62 > /sys/bus/i2c/devices/i2c-5/new_device', +'echo cpld_plain 0x64 > /sys/bus/i2c/devices/i2c-6/new_device'] + +mknod2 =[ +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo pca9548 0X73 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', + +'echo as7712_32x_fan 0x66 > /sys/bus/i2c/devices/i2c-2/new_device ', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as7712_32x_psu1 0x53 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as7712_32x_psu2 0x50 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo cpld_as7712 0x60 > /sys/bus/i2c/devices/i2c-4/new_device', +'echo cpld_plain 0x62 > /sys/bus/i2c/devices/i2c-5/new_device', +'echo cpld_plain 0x64 > /sys/bus/i2c/devices/i2c-6/new_device'] + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x76 is exist @ i2c-0 + tmp = "echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-0/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x76 > /sys/bus/i2c/devices/i2c-0/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x76 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0076", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0076", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/fanutil.py new file mode 100755 index 000000000000..9a69f6e1d537 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/fanutil.py @@ -0,0 +1,254 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + #FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + #BASE_VAL_PATH = '/sys/devices/platform/as5712_54x_fan/{0}' + BASE_VAL_PATH = '/sys/bus/i2c/devices/9-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/9-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + #val = ((val + 1 ) * 625 +75 ) / 100 + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/thermalutil.py new file mode 100755 index 000000000000..50d8c85d94ca --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/thermalutil.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD + + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['10', '48'], + THERMAL_NUM_2_IDX: ['10', '49'], + THERMAL_NUM_3_IDX: ['10', '4a'], + } + + def __init__(self): + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1): + self._thermal_to_device_path_mapping[x] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/Makefile new file mode 100755 index 000000000000..6cdbdd81ac1e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/Makefile @@ -0,0 +1,21 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_as7716_32x_cpld1.o accton_as7716_32x_fan.o \ + accton_as7716_32x_leds.o accton_as7716_32x_psu.o cpr_4011_4mxx.o ym2651y.o \ + accton_i2c_cpld.o + +else +ifeq (,$(KERNEL_SRC)) +#$(error KERNEL_SRC is not defined) +KVERSION := $(shell uname -r) +KERNEL_DIR = /usr/src/linux-headers-$(KVERSION)/ +KERNELDIR:=$(KERNEL_DIR) +#export KERNELDIR:=${PWD}/../../../../../src/sonic-linux-kernel/linux-3.16.43/ +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_cpld1.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_cpld1.c new file mode 100755 index 000000000000..cbab013f5860 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_cpld1.c @@ -0,0 +1,781 @@ +/* + * A hwmon driver for the as7716_32x_cpld + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +static int as7716_32x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as7716_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +struct as7716_32x_cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; +}; + +/* Addresses scanned for as7716_32x_cpld + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as7716_32x_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_RESET_ATTR_ID(1), + TRANSCEIVER_RESET_ATTR_ID(2), + TRANSCEIVER_RESET_ATTR_ID(3), + TRANSCEIVER_RESET_ATTR_ID(4), + TRANSCEIVER_RESET_ATTR_ID(5), + TRANSCEIVER_RESET_ATTR_ID(6), + TRANSCEIVER_RESET_ATTR_ID(7), + TRANSCEIVER_RESET_ATTR_ID(8), + TRANSCEIVER_RESET_ATTR_ID(9), + TRANSCEIVER_RESET_ATTR_ID(10), + TRANSCEIVER_RESET_ATTR_ID(11), + TRANSCEIVER_RESET_ATTR_ID(12), + TRANSCEIVER_RESET_ATTR_ID(13), + TRANSCEIVER_RESET_ATTR_ID(14), + TRANSCEIVER_RESET_ATTR_ID(15), + TRANSCEIVER_RESET_ATTR_ID(16), + TRANSCEIVER_RESET_ATTR_ID(17), + TRANSCEIVER_RESET_ATTR_ID(18), + TRANSCEIVER_RESET_ATTR_ID(19), + TRANSCEIVER_RESET_ATTR_ID(20), + TRANSCEIVER_RESET_ATTR_ID(21), + TRANSCEIVER_RESET_ATTR_ID(22), + TRANSCEIVER_RESET_ATTR_ID(23), + TRANSCEIVER_RESET_ATTR_ID(24), + TRANSCEIVER_RESET_ATTR_ID(25), + TRANSCEIVER_RESET_ATTR_ID(26), + TRANSCEIVER_RESET_ATTR_ID(27), + TRANSCEIVER_RESET_ATTR_ID(28), + TRANSCEIVER_RESET_ATTR_ID(29), + TRANSCEIVER_RESET_ATTR_ID(30), + TRANSCEIVER_RESET_ATTR_ID(31), + TRANSCEIVER_RESET_ATTR_ID(32), +}; + +/* sysfs attributes for hwmon + */ + +/* transceiver attributes */ +/*present*/ +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_present, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +/*reset*/ +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); + +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(32); + + +static struct attribute *as7716_32x_cpld_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + DECLARE_TRANSCEIVER_ATTR(1), + DECLARE_TRANSCEIVER_ATTR(2), + DECLARE_TRANSCEIVER_ATTR(3), + DECLARE_TRANSCEIVER_ATTR(4), + DECLARE_TRANSCEIVER_ATTR(5), + DECLARE_TRANSCEIVER_ATTR(6), + DECLARE_TRANSCEIVER_ATTR(7), + DECLARE_TRANSCEIVER_ATTR(8), + DECLARE_TRANSCEIVER_ATTR(9), + DECLARE_TRANSCEIVER_ATTR(10), + DECLARE_TRANSCEIVER_ATTR(11), + DECLARE_TRANSCEIVER_ATTR(12), + DECLARE_TRANSCEIVER_ATTR(13), + DECLARE_TRANSCEIVER_ATTR(14), + DECLARE_TRANSCEIVER_ATTR(15), + DECLARE_TRANSCEIVER_ATTR(16), + DECLARE_TRANSCEIVER_ATTR(17), + DECLARE_TRANSCEIVER_ATTR(18), + DECLARE_TRANSCEIVER_ATTR(19), + DECLARE_TRANSCEIVER_ATTR(20), + DECLARE_TRANSCEIVER_ATTR(21), + DECLARE_TRANSCEIVER_ATTR(22), + DECLARE_TRANSCEIVER_ATTR(23), + DECLARE_TRANSCEIVER_ATTR(24), + DECLARE_TRANSCEIVER_ATTR(25), + DECLARE_TRANSCEIVER_ATTR(26), + DECLARE_TRANSCEIVER_ATTR(27), + DECLARE_TRANSCEIVER_ATTR(28), + DECLARE_TRANSCEIVER_ATTR(29), + DECLARE_TRANSCEIVER_ATTR(30), + DECLARE_TRANSCEIVER_ATTR(31), + DECLARE_TRANSCEIVER_ATTR(32), + DECLARE_TRANSCEIVER_RESET_ATTR(1), + DECLARE_TRANSCEIVER_RESET_ATTR(2), + DECLARE_TRANSCEIVER_RESET_ATTR(3), + DECLARE_TRANSCEIVER_RESET_ATTR(4), + DECLARE_TRANSCEIVER_RESET_ATTR(5), + DECLARE_TRANSCEIVER_RESET_ATTR(6), + DECLARE_TRANSCEIVER_RESET_ATTR(7), + DECLARE_TRANSCEIVER_RESET_ATTR(8), + DECLARE_TRANSCEIVER_RESET_ATTR(9), + DECLARE_TRANSCEIVER_RESET_ATTR(10), + DECLARE_TRANSCEIVER_RESET_ATTR(11), + DECLARE_TRANSCEIVER_RESET_ATTR(12), + DECLARE_TRANSCEIVER_RESET_ATTR(13), + DECLARE_TRANSCEIVER_RESET_ATTR(14), + DECLARE_TRANSCEIVER_RESET_ATTR(15), + DECLARE_TRANSCEIVER_RESET_ATTR(16), + DECLARE_TRANSCEIVER_RESET_ATTR(17), + DECLARE_TRANSCEIVER_RESET_ATTR(18), + DECLARE_TRANSCEIVER_RESET_ATTR(19), + DECLARE_TRANSCEIVER_RESET_ATTR(20), + DECLARE_TRANSCEIVER_RESET_ATTR(21), + DECLARE_TRANSCEIVER_RESET_ATTR(22), + DECLARE_TRANSCEIVER_RESET_ATTR(23), + DECLARE_TRANSCEIVER_RESET_ATTR(24), + DECLARE_TRANSCEIVER_RESET_ATTR(25), + DECLARE_TRANSCEIVER_RESET_ATTR(26), + DECLARE_TRANSCEIVER_RESET_ATTR(27), + DECLARE_TRANSCEIVER_RESET_ATTR(28), + DECLARE_TRANSCEIVER_RESET_ATTR(29), + DECLARE_TRANSCEIVER_RESET_ATTR(30), + DECLARE_TRANSCEIVER_RESET_ATTR(31), + DECLARE_TRANSCEIVER_RESET_ATTR(32), + NULL +}; + +static const struct attribute_group as7716_32x_cpld_group = { + .attrs = as7716_32x_cpld_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[4] = {0}; + u8 regs[] = {0x30, 0x31, 0x32, 0x33}; + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7716_32x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 32 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x30; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x31; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x32; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x33; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + default: + return 0; + } + + + mutex_lock(&data->update_lock); + status = as7716_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 reg = 0, mask = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + + switch (attr->index) { + case CPLD_VERSION: + reg = 0x1; + mask = 0xFF; + break; + default: + break; + } + + mutex_lock(&data->update_lock); + status = as7716_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", (status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as7716_32x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as7716_32x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as7716_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static void as7716_32x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as7716_32x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int as7716_32x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct as7716_32x_cpld_data *data = NULL; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7716_32x_cpld_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32x_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; + } + + as7716_32x_cpld_add_client(client); + + dev_info(&client->dev, "%s: cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32x_cpld_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32x_cpld_remove(struct i2c_client *client) +{ + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32x_cpld_group); + kfree(data); + as7716_32x_cpld_remove_client(client); + + return 0; +} + +int as7716_32x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7716_32x_cpld_read); + +int as7716_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7716_32x_cpld_write); + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x04; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x05; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x06; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x07; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + + + mutex_lock(&data->update_lock); + status = as7716_32x_cpld_read_internal(client, reg); + + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\r\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status=0, val, error; + u8 reg = 0, mask = 0; + + + error = kstrtol(buf, 10, &reset); + if (error) { + return error; + } + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x04; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x05; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x06; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x07; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + mutex_lock(&data->update_lock); + + status = as7716_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update lp_mode status */ + if (reset) + { + val = status&(~mask); + } + else + { + val =status | (mask); + } + + status = as7716_32x_cpld_write_internal(client, reg, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + + +static const struct i2c_device_id as7716_32x_cpld_id[] = { + { "as7716_32x_cpld1", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32x_cpld_id); + +static struct i2c_driver as7716_32x_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32x_cpld1", + }, + .probe = as7716_32x_cpld_probe, + .remove = as7716_32x_cpld_remove, + .id_table = as7716_32x_cpld_id, + .address_list = normal_i2c, +}; + +static int __init as7716_32x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7716_32x_cpld_driver); +} + +static void __exit as7716_32x_cpld_exit(void) +{ + i2c_del_driver(&as7716_32x_cpld_driver); +} + +module_init(as7716_32x_cpld_init); +module_exit(as7716_32x_cpld_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32x_cpld driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_fan.c new file mode 100644 index 000000000000..3a0610fe370d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_fan.c @@ -0,0 +1,535 @@ +/* + * A hwmon driver for the Accton as7716 32x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7716_32x_fan" + +#define IN +#define OUT + +static struct as7716_32x_fan_data *as7716_32x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_enable(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:B2F 1:F2B) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7716_32x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + u8 enable; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index##_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr, \ + &sensor_dev_attr_pwm##index##_enable.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); + +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); + +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); + +static struct attribute *as7716_32x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7716_32x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7716_32x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as7716_32x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct as7716_32x_fan_data *data = as7716_32x_fan_update_device(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + data->enable = value; + if (value == 0) + { + return set_duty_cycle(dev, da, buf, FAN_MAX_DUTY_CYCLE); + } + return count; +} + + +static ssize_t get_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7716_32x_fan_data *data = as7716_32x_fan_update_device(dev); + + return sprintf(buf, "%u\n", data->enable); +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as7716_32x_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as7716_32x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7716_32x_fan_data *data = as7716_32x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7716_32x_fan_group = { + .attrs = as7716_32x_fan_attributes, +}; + +static struct as7716_32x_fan_data *as7716_32x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7716_32x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7716_32x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7716_32x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7716_32x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32x_fan_remove(struct i2c_client *client) +{ + struct as7716_32x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7716_32x_fan_id[] = { + { "as7716_32x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32x_fan_id); + +static struct i2c_driver as7716_32x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7716_32x_fan_probe, + .remove = as7716_32x_fan_remove, + .id_table = as7716_32x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7716_32x_fan_init(void) +{ + return i2c_add_driver(&as7716_32x_fan_driver); +} + +static void __exit as7716_32x_fan_exit(void) +{ + i2c_del_driver(&as7716_32x_fan_driver); +} + +module_init(as7716_32x_fan_init); +module_exit(as7716_32x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_leds.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_leds.c new file mode 100755 index 000000000000..da3d9442035f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_leds.c @@ -0,0 +1,442 @@ +/* + * A LED driver for the as7716_32x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as7716_32x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as7716_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "as7716_32x_led" + +struct as7716_32x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct as7716_32x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting as7716_32x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = as7716_32x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void as7716_32x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = as7716_32x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + as7716_32x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void as7716_32x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7716_32x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness as7716_32x_led_diag_get(struct led_classdev *cdev) +{ + as7716_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void as7716_32x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7716_32x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness as7716_32x_led_loc_get(struct led_classdev *cdev) +{ + as7716_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void as7716_32x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness as7716_32x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev as7716_32x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "as7716_32x_led::diag", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_diag_set, + .brightness_get = as7716_32x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "as7716_32x_led::loc", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_loc_set, + .brightness_get = as7716_32x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "as7716_32x_led::fan", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_auto_set, + .brightness_get = as7716_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "as7716_32x_led::psu1", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_auto_set, + .brightness_get = as7716_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as7716_32x_led::psu2", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_auto_set, + .brightness_get = as7716_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int as7716_32x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + led_classdev_suspend(&as7716_32x_leds[i]); + } + + return 0; +} + +static int as7716_32x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + led_classdev_resume(&as7716_32x_leds[i]); + } + + return 0; +} + +static int as7716_32x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &as7716_32x_leds[i]); + + if (ret < 0) + { + break; + } + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(as7716_32x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&as7716_32x_leds[i]); + } + } + + return 0; +} + +static int as7716_32x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + led_classdev_unregister(&as7716_32x_leds[i]); + } + + return 0; +} + +static struct platform_driver as7716_32x_led_driver = { + .probe = as7716_32x_led_probe, + .remove = as7716_32x_led_remove, + .suspend = as7716_32x_led_suspend, + .resume = as7716_32x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init as7716_32x_led_init(void) +{ + int ret; + + + ret = platform_driver_register(&as7716_32x_led_driver); + if (ret < 0) { + + goto exit; + } + + ledctl = kzalloc(sizeof(struct as7716_32x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&as7716_32x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&as7716_32x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return 0; +} + +static void __exit as7716_32x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&as7716_32x_led_driver); + kfree(ledctl); +} + +module_init(as7716_32x_led_init); +module_exit(as7716_32x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_psu.c new file mode 100755 index 000000000000..78a58b820b2a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_psu.c @@ -0,0 +1,381 @@ +/* + * An hwmon driver for accton as7716_32x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MODEL_NAME 16 + +#define DC12V_FAN_DIR_OFFSET 0x34 +#define DC12V_FAN_DIR_LEN 3 + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +static int as7716_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7716_32x_cpld_read (unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7716_32x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MAX_MODEL_NAME+1]; /* Model name, read from eeprom */ + char fan_dir[DC12V_FAN_DIR_LEN+1]; /* DC12V fan direction */ +}; + +static struct as7716_32x_psu_data *as7716_32x_psu_update_device(struct device *dev); + +enum as7716_32x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_FAN_DIR /* For DC12V only */ +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_string, NULL, PSU_FAN_DIR); + +static struct attribute *as7716_32x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7716_32x_psu_data *data = as7716_32x_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return -EIO; + } + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7716_32x_psu_data *data = as7716_32x_psu_update_device(dev); + char *ptr = NULL; + + if (!data->valid) { + return -EIO; + } + + if (attr->index == PSU_MODEL_NAME) { + ptr = data->model_name; + } + else { /* PSU_FAN_DIR */ + ptr = data->fan_dir; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group as7716_32x_psu_group = { + .attrs = as7716_32x_psu_attributes, +}; + +static int as7716_32x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7716_32x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32x_psu_remove(struct i2c_client *client) +{ + struct as7716_32x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7716_32x_psu1, + as7716_32x_psu2 +}; + +static const struct i2c_device_id as7716_32x_psu_id[] = { + { "as7716_32x_psu1", as7716_32x_psu1 }, + { "as7716_32x_psu2", as7716_32x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32x_psu_id); + +static struct i2c_driver as7716_32x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32x_psu", + }, + .probe = as7716_32x_psu_probe, + .remove = as7716_32x_psu_remove, + .id_table = as7716_32x_psu_id, + .address_list = normal_i2c, +}; + +static int as7716_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +enum psu_type { + PSU_TYPE_AC_110V, + PSU_TYPE_DC_48V, + PSU_TYPE_DC_12V +}; + +struct model_name_info { + enum psu_type type; + u8 offset; + u8 length; + char* model_name; +}; + +struct model_name_info models[] = { +{PSU_TYPE_AC_110V, 0x20, 8, "YM-2651Y"}, +{PSU_TYPE_DC_48V, 0x20, 8, "YM-2651V"}, +{PSU_TYPE_DC_12V, 0x00, 11, "PSU-12V-750"}, +}; + +static int as7716_32x_psu_model_name_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_psu_data *data = i2c_get_clientdata(client); + int i, status; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + memset(data->model_name, 0, sizeof(data->model_name)); + + status = as7716_32x_psu_read_block(client, models[i].offset, + data->model_name, models[i].length); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x%x)\n", + client->addr, models[i].offset); + return status; + } + else { + data->model_name[models[i].length] = '\0'; + } + + /* Determine if the model name is known, if not, read next index + */ + if (strncmp(data->model_name, models[i].model_name, models[i].length) == 0) { + return 0; + } + else { + data->model_name[0] = '\0'; + } + } + + return -ENODATA; +} + +static struct as7716_32x_psu_data *as7716_32x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + data->valid = 0; + dev_dbg(&client->dev, "Starting as7716_32x update\n"); + + /* Read psu status */ + status = as7716_32x_cpld_read(0x60, 0x2); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + goto exit; + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->fan_dir, 0, sizeof(data->fan_dir)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + if (as7716_32x_psu_model_name_get(dev) < 0) { + goto exit; + } + + if (strncmp(data->model_name, + models[PSU_TYPE_DC_12V].model_name, + models[PSU_TYPE_DC_12V].length) == 0) + { + /* Read fan direction */ + + status = as7716_32x_psu_read_block(client, DC12V_FAN_DIR_OFFSET, + data->fan_dir, DC12V_FAN_DIR_LEN); + + if (status < 0) { + data->fan_dir[0] = '\0'; + dev_dbg(&client->dev, "unable to read fan direction from (0x%x) offset(0x%x)\n", + client->addr, DC12V_FAN_DIR_OFFSET); + goto exit; + } + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as7716_32x_psu_init(void) +{ + return i2c_add_driver(&as7716_32x_psu_driver); +} + +static void __exit as7716_32x_psu_exit(void) +{ + i2c_del_driver(&as7716_32x_psu_driver); +} + +module_init(as7716_32x_psu_init); +module_exit(as7716_32x_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_sfp.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_sfp.c new file mode 100755 index 000000000000..9c7a05632154 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_sfp.c @@ -0,0 +1,365 @@ +/* + * An hwmon driver for accton as7716_32x sfp + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BIT_INDEX(i) (1UL << (i)) +#define I2C_ADDR_CPLD1 0x60 +#define I2C_ADDR_CPLD2 0x62 +#define I2C_ADDR_CPLD3 0x64 +#define CPLD1_OFFSET_QSFP_PRESET1 0x30 +#define CPLD1_OFFSET_QSFP_PRESET2 0x31 +#define CPLD1_OFFSET_QSFP_PRESET3 0x32 +#define CPLD1_OFFSET_QSFP_PRESET4 0x33 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7716_32x_sfp_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + int port; /* Front port index */ + char eeprom[256]; /* eeprom data */ + u32 is_present; /* present status */ +}; + +static struct as7716_32x_sfp_data *as7716_32x_sfp_update_device(struct device *dev); +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da,char *buf); +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +enum as7716_32x_sfp_sysfs_attributes { + SFP_PORT_NUMBER, + SFP_IS_PRESENT, + SFP_IS_PRESENT_ALL, + SFP_EEPROM +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, SFP_PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, SFP_IS_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_eeprom, S_IRUGO, show_eeprom, NULL, SFP_EEPROM); + +static struct attribute *as7716_32x_sfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_eeprom.dev_attr.attr, + NULL +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_sfp_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", data->port+1); +} + +/* Error-check the CPLD read results. */ +#define VALIDATED_READ(_buf, _rv, _read_expr, _invert) \ +do { \ + _rv = (_read_expr); \ + if(_rv < 0) { \ + return sprintf(_buf, "READ ERROR\n"); \ + } \ + if(_invert) { \ + _rv = ~_rv; \ + } \ + _rv &= 0xFF; \ +} while(0) + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if(attr->index == SFP_IS_PRESENT_ALL) { + int values[4]; + /* + * Report the SFP_PRESENCE status for all ports. + */ + + /* QSFP_PRESENT Ports 1-8 */ + //VALIDATED_READ(buf, values[0], accton_i2c_cpld_read(0x62, 0x9), 1); + VALIDATED_READ(buf, values[0], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET1), 1); + /* QSFP_PRESENT Ports 9-16 */ + VALIDATED_READ(buf, values[1], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET2), 1); + /* QSFP_PRESENT Ports 17-24 */ + VALIDATED_READ(buf, values[2], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET3), 1); + /* QSFP_PRESENT Ports 25-32 */ + VALIDATED_READ(buf, values[3], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET4), 1); + + /* Return values 1 -> 32 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + } + else { /* SFP_IS_PRESENT */ + struct as7716_32x_sfp_data *data = as7716_32x_sfp_update_device(dev); + + if (!data->valid) { + printk("return -EIO\n"); + return -EIO; + } + + return sprintf(buf, "%d\n", data->is_present); + } +} + +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7716_32x_sfp_data *data = as7716_32x_sfp_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!data->is_present) { + return 0; + } + + memcpy(buf, data->eeprom, sizeof(data->eeprom)); + + return sizeof(data->eeprom); +} + +static const struct attribute_group as7716_32x_sfp_group = { + .attrs = as7716_32x_sfp_attributes, +}; + +static int as7716_32x_sfp_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32x_sfp_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7716_32x_sfp_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + i2c_set_clientdata(client, data); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32x_sfp_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: sfp '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32x_sfp_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32x_sfp_remove(struct i2c_client *client) +{ + struct as7716_32x_sfp_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32x_sfp_group); + kfree(data); + + return 0; +} + +enum port_numbers { +as7716_32x_sfp1, as7716_32x_sfp2, as7716_32x_sfp3, as7716_32x_sfp4, +as7716_32x_sfp5, as7716_32x_sfp6, as7716_32x_sfp7, as7716_32x_sfp8, +as7716_32x_sfp9, as7716_32x_sfp10,as7716_32x_sfp11,as7716_32x_sfp12, +as7716_32x_sfp13,as7716_32x_sfp14,as7716_32x_sfp15,as7716_32x_sfp16, +as7716_32x_sfp17,as7716_32x_sfp18,as7716_32x_sfp19,as7716_32x_sfp20, +as7716_32x_sfp21,as7716_32x_sfp22,as7716_32x_sfp23,as7716_32x_sfp24, +as7716_32x_sfp25,as7716_32x_sfp26,as7716_32x_sfp27,as7716_32x_sfp28, +as7716_32x_sfp29,as7716_32x_sfp30,as7716_32x_sfp31,as7716_32x_sfp32 +}; + +static const struct i2c_device_id as7716_32x_sfp_id[] = { +{ "as7716_32x_sfp1", as7716_32x_sfp1 }, { "as7716_32x_sfp2", as7716_32x_sfp2 }, +{ "as7716_32x_sfp3", as7716_32x_sfp3 }, { "as7716_32x_sfp4", as7716_32x_sfp4 }, +{ "as7716_32x_sfp5", as7716_32x_sfp5 }, { "as7716_32x_sfp6", as7716_32x_sfp6 }, +{ "as7716_32x_sfp7", as7716_32x_sfp7 }, { "as7716_32x_sfp8", as7716_32x_sfp8 }, +{ "as7716_32x_sfp9", as7716_32x_sfp9 }, { "as7716_32x_sfp10", as7716_32x_sfp10 }, +{ "as7716_32x_sfp11", as7716_32x_sfp11 }, { "as7716_32x_sfp12", as7716_32x_sfp12 }, +{ "as7716_32x_sfp13", as7716_32x_sfp13 }, { "as7716_32x_sfp14", as7716_32x_sfp14 }, +{ "as7716_32x_sfp15", as7716_32x_sfp15 }, { "as7716_32x_sfp16", as7716_32x_sfp16 }, +{ "as7716_32x_sfp17", as7716_32x_sfp17 }, { "as7716_32x_sfp18", as7716_32x_sfp18 }, +{ "as7716_32x_sfp19", as7716_32x_sfp19 }, { "as7716_32x_sfp20", as7716_32x_sfp20 }, +{ "as7716_32x_sfp21", as7716_32x_sfp21 }, { "as7716_32x_sfp22", as7716_32x_sfp22 }, +{ "as7716_32x_sfp23", as7716_32x_sfp23 }, { "as7716_32x_sfp24", as7716_32x_sfp24 }, +{ "as7716_32x_sfp25", as7716_32x_sfp25 }, { "as7716_32x_sfp26", as7716_32x_sfp26 }, +{ "as7716_32x_sfp27", as7716_32x_sfp27 }, { "as7716_32x_sfp28", as7716_32x_sfp28 }, +{ "as7716_32x_sfp29", as7716_32x_sfp29 }, { "as7716_32x_sfp30", as7716_32x_sfp30 }, +{ "as7716_32x_sfp31", as7716_32x_sfp31 }, { "as7716_32x_sfp32", as7716_32x_sfp32 }, +{} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32x_sfp_id); + +static struct i2c_driver as7716_32x_sfp_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32x_sfp", + }, + .probe = as7716_32x_sfp_probe, + .remove = as7716_32x_sfp_remove, + .id_table = as7716_32x_sfp_id, + .address_list = normal_i2c, +}; + +static int as7716_32x_sfp_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +static struct as7716_32x_sfp_data *as7716_32x_sfp_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_sfp_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + int i = 0; + u8 cpld_reg = 0x30 + (data->port/8); + + data->valid = 0; + + /* Read present status of the specified port number */ + data->is_present = 0; + status = accton_i2c_cpld_read(I2C_ADDR_CPLD1, cpld_reg); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD1, cpld_reg, status); + goto exit; + } + + data->is_present = (status & (1 << (data->port % 8))) ? 0 : 1; + printk("data->is_present=%d, data->port=%d, status=0x%x\n",data->is_present, data->port, status); + /* Read eeprom data based on port number */ + memset(data->eeprom, 0, sizeof(data->eeprom)); + + /* Check if the port is present */ + if (data->is_present) { + /* read eeprom */ + for (i = 0; i < sizeof(data->eeprom)/I2C_SMBUS_BLOCK_MAX; i++) { + status = as7716_32x_sfp_read_block(client, i*I2C_SMBUS_BLOCK_MAX, + data->eeprom+(i*I2C_SMBUS_BLOCK_MAX), + I2C_SMBUS_BLOCK_MAX); + if (status < 0) { + printk("unable to read eeprom from port(%d)\n", data->port); + dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n", data->port); + goto exit; + } + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as7716_32x_sfp_init(void) +{ + //extern int platform_accton_as7716_32x(void); + //if (!platform_accton_as7716_32x()) { +// return -ENODEV; + //} + + return i2c_add_driver(&as7716_32x_sfp_driver); +} + +static void __exit as7716_32x_sfp_exit(void) +{ + i2c_del_driver(&as7716_32x_sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7716_32x_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(as7716_32x_sfp_init); +module_exit(as7716_32x_sfp_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_i2c_cpld.c new file mode 100755 index 000000000000..46d1e2773287 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_i2c_cpld.c @@ -0,0 +1,259 @@ +/* + * A hwmon driver for the accton_i2c_cpld + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CPLD_VERSION_REG 0x1 + +enum as5712_54x_cpld_sysfs_attributes { + CPLD_READ_VERSION, + CPLD_BYTE_ACCESS, + CPLD_DUMP_ALL, +}; + +static ssize_t read_cpld_version(struct device *dev, struct device_attribute *da, + char *buf); +int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); + + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for accton_i2c_cpld + */ +static const unsigned short normal_i2c[] = { 0x31, 0x35, 0x60, 0x61, 0x62, I2C_CLIENT_END }; + +static SENSOR_DEVICE_ATTR(cpld_get_version, S_IRUGO, read_cpld_version, NULL, CPLD_READ_VERSION); + +static struct attribute *as5712_54x_cpld_attributes[] = { + &sensor_dev_attr_cpld_get_version.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5712_54x_cpld_group = { + .attrs = as5712_54x_cpld_attributes, +}; + +static ssize_t read_cpld_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + unsigned short cpld_reg = CPLD_VERSION_REG; + u8 reg; + + if(attr->index == CPLD_READ_VERSION) { + reg = accton_i2c_cpld_read(client->addr, cpld_reg); + return sprintf(buf, "%02x\n",reg); + } + return -1 ; +} + + +static void accton_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void accton_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int accton_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5712_54x_cpld_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + accton_i2c_cpld_add_client(client); + + return 0; +exit: + return status; +} + +static int accton_i2c_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &as5712_54x_cpld_group); + + accton_i2c_cpld_remove_client(client); + return 0; +} + +static const struct i2c_device_id accton_i2c_cpld_id[] = { + { "accton_i2c_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id); + +static struct i2c_driver accton_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "accton_i2c_cpld", + }, + .probe = accton_i2c_cpld_probe, + .remove = accton_i2c_cpld_remove, + .id_table = accton_i2c_cpld_id, + .address_list = normal_i2c, +}; + +int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_read); + +int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_write); + +static int __init accton_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&accton_i2c_cpld_driver); +} + +static void __exit accton_i2c_cpld_exit(void) +{ + i2c_del_driver(&accton_i2c_cpld_driver); +} +/* +static struct dmi_system_id as7712_dmi_table[] = { + { + .ident = "Accton AS7712", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS7712"), + }, + } +}; + +int platform_accton_as7712_32x(void) +{ + return dmi_check_system(as7712_dmi_table); +} +EXPORT_SYMBOL(platform_accton_as7712_32x); +*/ +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_i2c_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_i2c_cpld_init); +module_exit(accton_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/cpr_4011_4mxx.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/cpr_4011_4mxx.c new file mode 100755 index 000000000000..30bea914d589 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/cpr_4011_4mxx.c @@ -0,0 +1,400 @@ +/* + * An hwmon driver for the CPR-4011-4Mxx Redundant Power Module + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x3c, 0x3d, 0x3e, 0x3f, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct cpr_4011_4mxx_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[2]; /* Register value */ + u8 fan_fault; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u16 fan_speed[2]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value); +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev); + +enum cpr_4011_4mxx_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); + +static struct attribute *cpr_4011_4mxx_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + cpr_4011_4mxx_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static const struct attribute_group cpr_4011_4mxx_group = { + .attrs = cpr_4011_4mxx_attributes, +}; + +static int cpr_4011_4mxx_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct cpr_4011_4mxx_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct cpr_4011_4mxx_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpr_4011_4mxx_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int cpr_4011_4mxx_remove(struct i2c_client *client) +{ + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id cpr_4011_4mxx_id[] = { + { "cpr_4011_4mxx", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpr_4011_4mxx_id); + +static struct i2c_driver cpr_4011_4mxx_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "cpr_4011_4mxx", + }, + .probe = cpr_4011_4mxx_probe, + .remove = cpr_4011_4mxx_remove, + .id_table = cpr_4011_4mxx_id, + .address_list = normal_i2c, +}; + +static int cpr_4011_4mxx_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int cpr_4011_4mxx_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + struct reg_data_byte regs_byte[] = { {0x20, &data->vout_mode}, + {0x81, &data->fan_fault}}; + struct reg_data_word regs_word[] = { {0x88, &data->v_in}, + {0x8b, &data->v_out}, + {0x89, &data->i_in}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x97, &data->p_in}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &(data->fan_speed[0])}, + {0x91, &(data->fan_speed[1])}}; + + dev_dbg(&client->dev, "Starting cpr_4011_4mxx update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = cpr_4011_4mxx_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = cpr_4011_4mxx_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init cpr_4011_4mxx_init(void) +{ + return i2c_add_driver(&cpr_4011_4mxx_driver); +} + +static void __exit cpr_4011_4mxx_exit(void) +{ + i2c_del_driver(&cpr_4011_4mxx_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("CPR_4011_4MXX driver"); +MODULE_LICENSE("GPL"); + +module_init(cpr_4011_4mxx_init); +module_exit(cpr_4011_4mxx_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/ym2651y.c new file mode 100755 index 000000000000..8e76c56b54fc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/ym2651y.c @@ -0,0 +1,603 @@ +/* + * An hwmon driver for the 3Y Power YM-2651Y Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct ym2651y_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 capability; /* Register value */ + u16 status_word; /* Register value */ + u8 fan_fault; /* Register value */ + u8 over_temp; /* Register value */ + u16 v_out; /* Register value */ + u16 i_out; /* Register value */ + u16 p_out; /* Register value */ + u16 temp; /* Register value */ + u16 fan_speed; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u8 fan_dir[4]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[10]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u16 mfr_vin_min; /* Register value */ + u16 mfr_vin_max; /* Register value */ + u16 mfr_iin_max; /* Register value */ + u16 mfr_iout_max; /* Register value */ + u16 mfr_pin_max; /* Register value */ + u16 mfr_pout_max; /* Register value */ + u16 mfr_vout_min; /* Register value */ + u16 mfr_vout_max; /* Register value */ +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static struct ym2651y_data *ym2651y_update_device(struct device *dev); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value); + +enum ym2651y_sysfs_attributes { + PSU_POWER_ON = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD, + PSU_FAN1_FAULT, + PSU_FAN_DIRECTION, + PSU_OVER_TEMP, + PSU_V_OUT, + PSU_I_OUT, + PSU_P_OUT, + PSU_P_OUT_UV, /*In Unit of microVolt, instead of mini.*/ + PSU_TEMP1_INPUT, + PSU_FAN1_SPEED, + PSU_FAN1_DUTY_CYCLE, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_VIN_MIN, + PSU_MFR_VIN_MAX, + PSU_MFR_VOUT_MIN, + PSU_MFR_VOUT_MAX, + PSU_MFR_IIN_MAX, + PSU_MFR_IOUT_MAX, + PSU_MFR_PIN_MAX, + PSU_MFR_POUT_MAX +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision, S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); + +static struct attribute *ym2651y_attributes[] = { + &sensor_dev_attr_psu_power_on.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_over_temp.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_temp1_fault.dev_attr.attr, + NULL +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u16 status = 0; + + switch (attr->index) { + case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */ + status = (data->status_word & 0x40) ? 0 : 1; + break; + case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */ + status = (data->status_word & 0x4) >> 2; + break; + case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */ + status = (data->status_word & 0x800) ? 0 : 1; + break; + } + + return sprintf(buf, "%d\n", status); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_OUT: + value = data->v_out; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_OUT_UV: + multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/ + /*Passing through*/ + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp; + break; + case PSU_FAN1_SPEED: + value = data->fan_speed; + multiplier = 1; + break; + case PSU_FAN1_DUTY_CYCLE: + value = data->fan_duty_cycle[0]; + multiplier = 1; + break; + case PSU_MFR_VIN_MIN: + value = data->mfr_vin_min; + break; + case PSU_MFR_VIN_MAX: + value = data->mfr_vin_max; + break; + case PSU_MFR_VOUT_MIN: + value = data->mfr_vout_min; + break; + case PSU_MFR_VOUT_MAX: + value = data->mfr_vout_max; + break; + case PSU_MFR_PIN_MAX: + value = data->mfr_pin_max; + break; + case PSU_MFR_POUT_MAX: + value = data->mfr_pout_max; + break; + case PSU_MFR_IOUT_MAX: + value = data->mfr_iout_max; + break; + case PSU_MFR_IIN_MAX: + value = data->mfr_iin_max; + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct ym2651y_data *data = ym2651y_update_device(dev); + + return sprintf(buf, "%d\n", data->over_temp >> 7); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u8 *ptr = NULL; + + switch (attr->index) { + case PSU_FAN_DIRECTION: /* psu_fan_dir */ + ptr = data->fan_dir; + break; + case PSU_MFR_ID: /* psu_mfr_id */ + ptr = data->mfr_id; + break; + case PSU_MFR_MODEL: /* psu_mfr_model */ + ptr = data->mfr_model; + break; + case PSU_MFR_REVISION: /* psu_mfr_revision */ + ptr = data->mfr_revsion; + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group ym2651y_group = { + .attrs = ym2651y_attributes, +}; + +static int ym2651y_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct ym2651y_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &ym2651y_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int ym2651y_remove(struct i2c_client *client) +{ + struct ym2651y_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id ym2651y_id[] = { + { "ym2651", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ym2651y_id); + +static struct i2c_driver ym2651y_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ym2651", + }, + .probe = ym2651y_probe, + .remove = ym2651y_remove, + .id_table = ym2651y_id, + .address_list = normal_i2c, +}; + +static int ym2651y_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int ym2651y_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct ym2651y_data *ym2651y_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + u8 command; + u8 fan_dir[5] = {0}; + struct reg_data_byte regs_byte[] = { {0x19, &data->capability}, + {0x7d, &data->over_temp}, + {0x81, &data->fan_fault}, + {0x98, &data->pmbus_revision}}; + struct reg_data_word regs_word[] = { {0x79, &data->status_word}, + {0x8b, &data->v_out}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x8d, &data->temp}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &data->fan_speed}, + {0xa0, &data->mfr_vin_min}, + {0xa1, &data->mfr_vin_max}, + {0xa2, &data->mfr_iin_max}, + {0xa3, &data->mfr_pin_max}, + {0xa4, &data->mfr_vout_min}, + {0xa5, &data->mfr_vout_max}, + {0xa6, &data->mfr_iout_max}, + {0xa7, &data->mfr_pout_max}}; + + dev_dbg(&client->dev, "Starting ym2651 update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = ym2651y_read_byte(client, regs_byte[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = ym2651y_read_word(client, regs_word[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + } + + /* Read fan_direction */ + command = 0xC3; + status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + } + + strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1); + data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0'; + + /* Read mfr_id */ + command = 0x99; + status = ym2651y_read_block(client, command, data->mfr_id, + ARRAY_SIZE(data->mfr_id)-1); + data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_model */ + command = 0x9a; + status = ym2651y_read_block(client, command, data->mfr_model, + ARRAY_SIZE(data->mfr_model)-1); + data->mfr_model[ARRAY_SIZE(data->mfr_model)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_revsion */ + command = 0x9b; + status = ym2651y_read_block(client, command, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)-1); + data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(ym2651y_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("3Y Power YM-2651Y driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/service/as7716-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/service/as7716-platform-monitor.service new file mode 100755 index 000000000000..b1428d7844f8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/service/as7716-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS7716-32X Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7716_util.py install +ExecStart=/usr/local/bin/accton_as7716_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/setup.py new file mode 100755 index 000000000000..7a3d784d326e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7716_32x', + version='1.0', + description='Module to initialize Accton AS7716-32X platforms', + + packages=['as7716_32x'], + package_dir={'as7716_32x': 'as7716-32x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/README new file mode 100755 index 000000000000..44e03cab5f52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program is free software: you can redistribute it and/or modify +It under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as5712_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as5712-fan-psu-cpld.patch + for as5712's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS5712-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as5712 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS5712-54X.patch" from patch/installer. + - Change setting for AS5712-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS5712-54X.patch" + !!NOTICE, patching onie_installer-accton-AS5712-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5712-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as5712-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as5712_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS5712-54X.patch. + It's done by patching onie_installer-accton-AS5712-54X.patch at build-image. + Run "accton_as5712_util.py install" to install drivers. + +To initialize the system, run "accton_as5712_util.py install". +To clean up the drivers & devices, run "accton_as5712_util.py clean". +To dump information of sensors, run "accton_as5712_util.py show". +To dump SFP EEPROM, run "accton_as5712_util.py sff". +To set fan speed, run "accton_as5712_util.py set fan". +To enable/disable SFP emission, run "accton_as5712_util.py set sfp". +To set system LEDs' color, run "accton_as5712_util.py set led" +For more information, run "accton_as5712_util.py --help". + +==================================================================== +Besides applying accton_as5712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/accton_as7716_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/accton_as7716_monitor.py new file mode 100755 index 000000000000..63f26d5d2ef6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/accton_as7716_monitor.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + from as7716_32x.fanutil import FanUtil + from as7716_32x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as7716_monitor' + +global log_file +global log_level + + # For AC power Front to Back : + # If any fan fail, please fan speed register to 15 + # The max value of Fan speed register is 9 + # [LM75(48) + LM75(49) + LM75(4A)] > 174 => set Fan speed value from 4 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] > 182 => set Fan speed value from 5 to 7 + # [LM75(48) + LM75(49) + LM75(4A)] > 190 => set Fan speed value from 7 to 9 + # + # [LM75(48) + LM75(49) + LM75(4A)] < 170 => set Fan speed value from 5 to 4 + # [LM75(48) + LM75(49) + LM75(4A)] < 178 => set Fan speed value from 7 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] < 186 => set Fan speed value from 9 to 7 + # + # + # For AC power Back to Front : + # If any fan fail, please fan speed register to 15 + # The max value of Fan speed register is 10 + # [LM75(48) + LM75(49) + LM75(4A)] > 140 => set Fan speed value from 4 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] > 150 => set Fan speed value from 5 to 7 + # [LM75(48) + LM75(49) + LM75(4A)] > 160 => set Fan speed value from 7 to 10 + # + # [LM75(48) + LM75(49) + LM75(4A)] < 135 => set Fan speed value from 5 to 4 + # [LM75(48) + LM75(49) + LM75(4A)] < 145 => set Fan speed value from 7 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] < 155 => set Fan speed value from 10 to 7 + # + + + # 2.If no matched fan speed is found from the policy, + # use FAN_DUTY_CYCLE_MIN as default speed + # Get current temperature + # 4.Decision 3: Decide new fan speed depend on fan direction/current fan speed/temperature + + + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as7716_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + + fan_policy_f2b = { + 0: [32, 0, 174000], + 1: [38, 170000, 182000], + 2: [50, 178000, 190000], + 3: [63, 186000, 0], + } + fan_policy_b2f = { + 0: [32, 0, 140000], + 1: [38, 135000, 150000], + 2: [50, 145000, 160000], + 3: [69, 15500, 0], + } + + thermal = ThermalUtil() + fan = FanUtil() + get_temp = thermal.get_thermal_temp() + + cur_duty_cycle = fan.get_fan_duty_cycle() + + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_status = fan.get_fan_status(x) + if fan_status is None: + logging.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', 100, x) + return False + if fan_status is False: + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', 100, x) + fan.set_fan_duty_cycle(45) + return True + logging.debug('INFO. fan_status is True (fan_num:%d)', x) + + if fan_status is not None and fan_status is not False: + fan_dir=fan.get_fan_dir(1) + for x in range(0, 4): + if cur_duty_cycle == fan_policy_f2b[x][0]: + break + + if fan_dir == 1: + if x == 4 : + fan.set_fan_duty_cycle(fan_policy_f2b[0][0]) + new_duty_cycle=cur_duty_cycle + # if temp > up_levle, else if temp < down_level + if get_temp > fan_policy_f2b[x][2] and x != 3 : + new_duty_cycle= fan_policy_f2b[x+1][0] + logging.debug('INFO. THERMAL temp UP, temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy_f2b[x][2], new_duty_cycle) + elif get_temp < fan_policy_f2b[x][1] : + new_duty_cycle= fan_policy_f2b[x-1][0] + logging.debug('INFO. THERMAL temp down, temp %d < %d , new_duty_cycle=%d', get_temp, fan_policy_f2b[x][1], new_duty_cycle) + if new_duty_cycle == cur_duty_cycle : + return True + else: + if x == 4 : + fan.set_fan_duty_cycle(fan_policy_b2f[0][0]) + new_duty_cycle=cur_duty_cycle + # if temp > up_levle, else if temp < down_level + if get_temp > fan_policy_b2f[x][1] and x != 3 : + new_duty_cycle= fan_policy_b2f[x+1][0] + logging.debug('INFO. THERMAL temp UP, temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy_b2f[x][2], new_duty_cycle) + elif get_temp < fan_policy_b2f[x][0] and x != 0 : + new_duty_cycle= fan_policy_b2f[x-1][0] + logging.debug('INFO. THERMAL temp down, temp %d < %d , new_duty_cycle=%d', get_temp, fan_policy_b2f[x][1], new_duty_cycle) + if new_duty_cycle == cur_duty_cycle : + return True + + fan.set_fan_duty_cycle(new_duty_cycle) + + return True + + + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + monitor = accton_as7716_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(1) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/accton_as7716_util.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/accton_as7716_util.py new file mode 100755 index 000000000000..cd35b50d200e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/accton_as7716_util.py @@ -0,0 +1,595 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +PROJECT_NAME = 'as7716_32x' +version = '0.0.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':54} + + +led_prefix ='/sys/devices/platform/as7716_32x_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as7716_32x_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan4_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'thermal': ['10-0048','10-0049', '10-004a'] , + 'psu': ['17-0050','18-0053'], + 'sfp': ['-0050']} +i2c_nodes = { + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable']} + +sfp_map = [29, 30, 31, 32, 34, 33, 36, 35, + 25, 26, 27, 28, 37, 38, 39, 40, + 41, 42, 43, 44, 53, 54, 55, 56, + 45, 46, 47, 48, 49, 50, 51, 52] + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as7716_32x_fan 0x66 > /sys/bus/i2c/devices/i2c-9/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-10/new_device', + +'echo as7716_32x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo accton_i2c_cpld 0x62 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo accton_i2c_cpld 0x64 > /sys/bus/i2c/devices/i2c-13/new_device', + +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-2/new_device', + +# PSU-1 +'echo as7716_32x_psu1 0x53 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-18/new_device', + +# PSU-2 +'echo as7716_32x_psu2 0x50> /sys/bus/i2c/devices/i2c-17/new_device', +'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-17/new_device', + + + +#EERPOM +'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-1/new_device', +] + +mknod2 =[ +'echo as7716_32x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo accton_i2c_cpld 0x61 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo accton_i2c_cpld 0x62 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', + +# PSU-1 +'echo as7716_32x_psu1 0x38 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-57/new_device', +'echo as7716_32x_psu1 0x50 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-57/new_device', + +# PSU-2 +'echo as7716_32x_psu2 0x3b > /sys/bus/i2c/devices/i2c-58/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-58/new_device', +'echo as7716_32x_psu2 0x53 > /sys/bus/i2c/devices/i2c-58/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-58/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-61/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-62/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-63/new_device', + +#EERPOM +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', +] + +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + +#'modprobe cpr_4011_4mxx', + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x', +'modprobe accton_i2c_cpld', +'modprobe cpr_4011_4mxx', +'modprobe ym2651y', +'modprobe accton_as7716_32x_cpld1', +'modprobe accton_as7716_32x_fan', +'modprobe accton_as7716_32x_leds', +'modprobe accton_as7716_32x_psu'] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x76 is exist @ i2c-0 + tmp = "echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x70 > /sys/bus/i2c/devices/i2c-1/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca932x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/0-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + print "not device_exist()" + return False + return True + +def do_install(): + if driver_inserted() == False: + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/fanutil.py new file mode 100755 index 000000000000..e001e94092c7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/fanutil.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + #FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + #BASE_VAL_PATH = '/sys/devices/platform/as5712_54x_fan/{0}' + BASE_VAL_PATH = '/sys/bus/i2c/devices/9-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/9-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + #print "fan_num=%d" %fan_num + #print "node_num=%d" %node_num + #print "device_path=%s" %device_path + #print "content=%s" %content + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + #self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path + self._fan_to_device_node_mapping[(fan_num, node_num)]) + #print "fan_num=%d" %fan_num + #print "node_num=%d" %node_num + #print "self._fan_to_device_path_mapping[(fan_num, node_num)]=%s" %self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + #val = ((val + 1 ) * 625 +75 ) / 100 + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + print "fan %d return none" %fan_num + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/thermalutil.py new file mode 100755 index 000000000000..d3feda8faad9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/thermalutil.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD + + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['10', '48'], + THERMAL_NUM_2_IDX: ['10', '49'], + THERMAL_NUM_3_IDX: ['10', '4a'], + } + + def __init__(self): + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1): + self._thermal_to_device_path_mapping[x] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + #print "self._thermal_to_device_path_mapping[x]=%s" %self._thermal_to_device_path_mapping[x] + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/Makefile new file mode 100755 index 000000000000..3dfb021a7aaf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/Makefile @@ -0,0 +1,17 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_as7716_32xb_cpld1.o accton_as7716_32xb_fan.o \ + accton_as7716_32xb_leds.o accton_as7716_32xb_psu.o \ + accton_as7716_32xb_thermal.o accton_as7716_32xb_oom.o accton_as7716_32xb_pmbus.o\ + accton_as7716_32xb_sys.o accton_i2c_cpld.o +else +ifeq (,$(KERNEL_SRC)) +$(error KERNEL_SRC is not defined) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_cpld1.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_cpld1.c new file mode 100644 index 000000000000..c322972481ba --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_cpld1.c @@ -0,0 +1,1021 @@ +/* + * A hwmon driver for the as7716_32xbb_cpld + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ +#define STRING_TO_DEC_VALUE 10 + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +static int as7716_32xb_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as7716_32xb_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +static ssize_t sfp_value_show(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t sfp_value_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size); + + +#define PORT_NUM_MAX 32 + +struct as7716_32xb_cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; + unsigned int present[PORT_NUM_MAX]; + unsigned int reset[PORT_NUM_MAX]; +}; +enum port_id { + PORT1_ID, + PORT2_ID, + PORT3_ID, + PORT4_ID, + PORT5_ID, + PORT6_ID, + PORT7_ID, + PORT8_ID, + PORT9_ID, + PORT10_ID, + PORT11_ID, + PORT12_ID, + PORT13_ID, + PORT14_ID, + PORT15_ID, + PORT16_ID, + PORT17_ID, + PORT18_ID, + PORT19_ID, + PORT20_ID, + PORT21_ID, + PORT22_ID, + PORT23_ID, + PORT24_ID, + PORT25_ID, + PORT26_ID, + PORT27_ID, + PORT28_ID, + PORT29_ID, + PORT30_ID, + PORT31_ID, + PORT32_ID +}; + +/* Addresses scanned for as7716_32xbb_cpld + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as7716_32xb_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_RESET_ATTR_ID(1), + TRANSCEIVER_RESET_ATTR_ID(2), + TRANSCEIVER_RESET_ATTR_ID(3), + TRANSCEIVER_RESET_ATTR_ID(4), + TRANSCEIVER_RESET_ATTR_ID(5), + TRANSCEIVER_RESET_ATTR_ID(6), + TRANSCEIVER_RESET_ATTR_ID(7), + TRANSCEIVER_RESET_ATTR_ID(8), + TRANSCEIVER_RESET_ATTR_ID(9), + TRANSCEIVER_RESET_ATTR_ID(10), + TRANSCEIVER_RESET_ATTR_ID(11), + TRANSCEIVER_RESET_ATTR_ID(12), + TRANSCEIVER_RESET_ATTR_ID(13), + TRANSCEIVER_RESET_ATTR_ID(14), + TRANSCEIVER_RESET_ATTR_ID(15), + TRANSCEIVER_RESET_ATTR_ID(16), + TRANSCEIVER_RESET_ATTR_ID(17), + TRANSCEIVER_RESET_ATTR_ID(18), + TRANSCEIVER_RESET_ATTR_ID(19), + TRANSCEIVER_RESET_ATTR_ID(20), + TRANSCEIVER_RESET_ATTR_ID(21), + TRANSCEIVER_RESET_ATTR_ID(22), + TRANSCEIVER_RESET_ATTR_ID(23), + TRANSCEIVER_RESET_ATTR_ID(24), + TRANSCEIVER_RESET_ATTR_ID(25), + TRANSCEIVER_RESET_ATTR_ID(26), + TRANSCEIVER_RESET_ATTR_ID(27), + TRANSCEIVER_RESET_ATTR_ID(28), + TRANSCEIVER_RESET_ATTR_ID(29), + TRANSCEIVER_RESET_ATTR_ID(30), + TRANSCEIVER_RESET_ATTR_ID(31), + TRANSCEIVER_RESET_ATTR_ID(32), +}; + +/* sysfs attributes for hwmon + */ + +/* transceiver attributes */ +/*present*/ +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IWUSR|S_IRUGO, sfp_value_show, sfp_value_store, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +/*reset*/ +//#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(index) \ +// static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, MODULE_RESET_##index) +//#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, sfp_value_show, sfp_value_store, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + + + + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); + +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(32); + + +static struct attribute *as7716_32xb_cpld_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + DECLARE_TRANSCEIVER_ATTR(1), + DECLARE_TRANSCEIVER_ATTR(2), + DECLARE_TRANSCEIVER_ATTR(3), + DECLARE_TRANSCEIVER_ATTR(4), + DECLARE_TRANSCEIVER_ATTR(5), + DECLARE_TRANSCEIVER_ATTR(6), + DECLARE_TRANSCEIVER_ATTR(7), + DECLARE_TRANSCEIVER_ATTR(8), + DECLARE_TRANSCEIVER_ATTR(9), + DECLARE_TRANSCEIVER_ATTR(10), + DECLARE_TRANSCEIVER_ATTR(11), + DECLARE_TRANSCEIVER_ATTR(12), + DECLARE_TRANSCEIVER_ATTR(13), + DECLARE_TRANSCEIVER_ATTR(14), + DECLARE_TRANSCEIVER_ATTR(15), + DECLARE_TRANSCEIVER_ATTR(16), + DECLARE_TRANSCEIVER_ATTR(17), + DECLARE_TRANSCEIVER_ATTR(18), + DECLARE_TRANSCEIVER_ATTR(19), + DECLARE_TRANSCEIVER_ATTR(20), + DECLARE_TRANSCEIVER_ATTR(21), + DECLARE_TRANSCEIVER_ATTR(22), + DECLARE_TRANSCEIVER_ATTR(23), + DECLARE_TRANSCEIVER_ATTR(24), + DECLARE_TRANSCEIVER_ATTR(25), + DECLARE_TRANSCEIVER_ATTR(26), + DECLARE_TRANSCEIVER_ATTR(27), + DECLARE_TRANSCEIVER_ATTR(28), + DECLARE_TRANSCEIVER_ATTR(29), + DECLARE_TRANSCEIVER_ATTR(30), + DECLARE_TRANSCEIVER_ATTR(31), + DECLARE_TRANSCEIVER_ATTR(32), + DECLARE_TRANSCEIVER_RESET_ATTR(1), + DECLARE_TRANSCEIVER_RESET_ATTR(2), + DECLARE_TRANSCEIVER_RESET_ATTR(3), + DECLARE_TRANSCEIVER_RESET_ATTR(4), + DECLARE_TRANSCEIVER_RESET_ATTR(5), + DECLARE_TRANSCEIVER_RESET_ATTR(6), + DECLARE_TRANSCEIVER_RESET_ATTR(7), + DECLARE_TRANSCEIVER_RESET_ATTR(8), + DECLARE_TRANSCEIVER_RESET_ATTR(9), + DECLARE_TRANSCEIVER_RESET_ATTR(10), + DECLARE_TRANSCEIVER_RESET_ATTR(11), + DECLARE_TRANSCEIVER_RESET_ATTR(12), + DECLARE_TRANSCEIVER_RESET_ATTR(13), + DECLARE_TRANSCEIVER_RESET_ATTR(14), + DECLARE_TRANSCEIVER_RESET_ATTR(15), + DECLARE_TRANSCEIVER_RESET_ATTR(16), + DECLARE_TRANSCEIVER_RESET_ATTR(17), + DECLARE_TRANSCEIVER_RESET_ATTR(18), + DECLARE_TRANSCEIVER_RESET_ATTR(19), + DECLARE_TRANSCEIVER_RESET_ATTR(20), + DECLARE_TRANSCEIVER_RESET_ATTR(21), + DECLARE_TRANSCEIVER_RESET_ATTR(22), + DECLARE_TRANSCEIVER_RESET_ATTR(23), + DECLARE_TRANSCEIVER_RESET_ATTR(24), + DECLARE_TRANSCEIVER_RESET_ATTR(25), + DECLARE_TRANSCEIVER_RESET_ATTR(26), + DECLARE_TRANSCEIVER_RESET_ATTR(27), + DECLARE_TRANSCEIVER_RESET_ATTR(28), + DECLARE_TRANSCEIVER_RESET_ATTR(29), + DECLARE_TRANSCEIVER_RESET_ATTR(30), + DECLARE_TRANSCEIVER_RESET_ATTR(31), + DECLARE_TRANSCEIVER_RESET_ATTR(32), + NULL +}; + +static const struct attribute_group as7716_32xb_cpld_group = { + .attrs = as7716_32xb_cpld_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[4] = {0}; + u8 regs[] = {0x30, 0x31, 0x32, 0x33}; + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7716_32xb_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 32 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int sfp_array_index_get(int attr_idx) +{ + switch(attr_idx) + { + case TRANSCEIVER_PRESENT_ATTR_ID(1): + case TRANSCEIVER_RESET_ATTR_ID(1): + return PORT1_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(2): + case TRANSCEIVER_RESET_ATTR_ID(2): + return PORT2_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(3): + case TRANSCEIVER_RESET_ATTR_ID(3): + return PORT3_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(4): + case TRANSCEIVER_RESET_ATTR_ID(4): + return PORT4_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(5): + case TRANSCEIVER_RESET_ATTR_ID(5): + return PORT5_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(6): + case TRANSCEIVER_RESET_ATTR_ID(6): + return PORT6_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(7): + case TRANSCEIVER_RESET_ATTR_ID(7): + return PORT7_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(8): + case TRANSCEIVER_RESET_ATTR_ID(8): + return PORT8_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(9): + case TRANSCEIVER_RESET_ATTR_ID(9): + return PORT9_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(10): + case TRANSCEIVER_RESET_ATTR_ID(10): + return PORT10_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(11): + case TRANSCEIVER_RESET_ATTR_ID(11): + return PORT11_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(12): + case TRANSCEIVER_RESET_ATTR_ID(12): + return PORT12_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(13): + case TRANSCEIVER_RESET_ATTR_ID(13): + return PORT13_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(14): + case TRANSCEIVER_RESET_ATTR_ID(14): + return PORT14_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(15): + case TRANSCEIVER_RESET_ATTR_ID(15): + return PORT15_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(16): + case TRANSCEIVER_RESET_ATTR_ID(16): + return PORT16_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(17): + case TRANSCEIVER_RESET_ATTR_ID(17): + return PORT17_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(18): + case TRANSCEIVER_RESET_ATTR_ID(18): + return PORT18_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(19): + case TRANSCEIVER_RESET_ATTR_ID(19): + return PORT19_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(20): + case TRANSCEIVER_RESET_ATTR_ID(20): + return PORT20_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(21): + case TRANSCEIVER_RESET_ATTR_ID(21): + return PORT21_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(22): + case TRANSCEIVER_RESET_ATTR_ID(22): + return PORT22_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(23): + case TRANSCEIVER_RESET_ATTR_ID(23): + return PORT23_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(24): + case TRANSCEIVER_RESET_ATTR_ID(24): + return PORT24_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(25): + case TRANSCEIVER_RESET_ATTR_ID(25): + return PORT25_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(26): + case TRANSCEIVER_RESET_ATTR_ID(26): + return PORT26_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(27): + case TRANSCEIVER_RESET_ATTR_ID(27): + return PORT27_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(28): + case TRANSCEIVER_RESET_ATTR_ID(28): + return PORT28_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(29): + case TRANSCEIVER_RESET_ATTR_ID(29): + return PORT29_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(30): + case TRANSCEIVER_RESET_ATTR_ID(30): + return PORT30_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(31): + case TRANSCEIVER_RESET_ATTR_ID(31): + return PORT31_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(32): + case TRANSCEIVER_RESET_ATTR_ID(32): + return PORT32_ID; + default : + return -1; + } +} + + +static ssize_t sfp_value_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + int status = -EINVAL; + int index; + long keyin = 0; + + //printk("sfp_value_store\n"); + //printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + index=sfp_array_index_get(attr->index); + if(index < 0 || index > PORT_NUM_MAX -1) + break; + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if(keyin < 0 || keyin > 1) + break; + data->present[index]=keyin; + break; + case MODULE_RESET_1 ... MODULE_RESET_8: + case MODULE_RESET_9 ... MODULE_RESET_16: + case MODULE_RESET_17 ... MODULE_RESET_24: + case MODULE_RESET_25 ... MODULE_RESET_32: + index=sfp_array_index_get(attr->index); + if(index < 0 || index > PORT_NUM_MAX -1) + break; + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if(keyin < 0 || keyin > 1) + break; + data->reset[index]=keyin; + break; + default : + break; + } + mutex_unlock(&data->update_lock); + return size; +} +static ssize_t sfp_value_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + ssize_t ret = 0; + int index; + int status = -EINVAL; + + //printk("sfp_value_show, attr->index=%d\n", attr->index); + //printk("TRANSCEIVER_PRESENT_ATTR_ID(1)=%d, TRANSCEIVER_RESET_ATTR_ID(1)=%d\n", TRANSCEIVER_PRESENT_ATTR_ID(1), TRANSCEIVER_RESET_ATTR_ID(1)); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + index=sfp_array_index_get(attr->index); + if(index < 0 || index > PORT_NUM_MAX -1) + break; + status = sprintf(buf, "%u\n", data->present[index]); + break; + case MODULE_RESET_1 ... MODULE_RESET_8: + case MODULE_RESET_9 ... MODULE_RESET_16: + case MODULE_RESET_17 ... MODULE_RESET_24: + case MODULE_RESET_25 ... MODULE_RESET_32: + index=sfp_array_index_get(attr->index); + //printk("rst:attr->index=%d, index=%d\n",attr->index, index); + if(index < 0 || index > PORT_NUM_MAX -1) + break; + status = sprintf(buf, "%u\n", data->reset[index]); + break; + default : + break; + } + + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x30; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x31; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x32; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x33; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + default: + return 0; + } + + + mutex_lock(&data->update_lock); + status = as7716_32xb_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 reg = 0, mask = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + + switch (attr->index) { + case CPLD_VERSION: + reg = 0x1; + mask = 0xFF; + break; + default: + break; + } + + mutex_lock(&data->update_lock); + status = as7716_32xb_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", (status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as7716_32xb_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as7716_32xb_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as7716_32xb_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static void as7716_32xb_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as7716_32xb_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int as7716_32xb_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct as7716_32xb_cpld_data *data = NULL; + + data = kzalloc(sizeof(struct as7716_32xb_cpld_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_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; + } + + as7716_32xb_cpld_add_client(client); + + dev_info(&client->dev, "%s: cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_cpld_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_cpld_remove(struct i2c_client *client) +{ + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_cpld_group); + kfree(data); + as7716_32xb_cpld_remove_client(client); + + return 0; +} + +int as7716_32xb_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7716_32xb_cpld_read); + +int as7716_32xb_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7716_32xb_cpld_write); + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x04; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x05; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x06; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x07; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + + + mutex_lock(&data->update_lock); + status = as7716_32xb_cpld_read_internal(client, reg); + + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\r\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status=0, val, error; + u8 reg = 0, mask = 0; + + + error = kstrtol(buf, 10, &reset); + if (error) { + return error; + } + //printk("set_mode_reset:attr->index=%d\n",attr->index); + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x04; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x05; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x06; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x07; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + mutex_lock(&data->update_lock); + + status = as7716_32xb_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + //printk("set_mode_reset:reset=%d, reg=0x%x, mask=0x%x, ori_val=0x%x\n", reset, reg, mask, status); + /* Update lp_mode status */ + if (reset) + { + val = status&(~mask); + //printk("1:new val=0x%x\n", val); + } + else + { + val =status | (mask); + //printk("0:new val=0x%x\n", val); + } + + status = as7716_32xb_cpld_write_internal(client, reg, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + + +static const struct i2c_device_id as7716_32xb_cpld_id[] = { + { "as7716_32xb_cpld1", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_cpld_id); + +static struct i2c_driver as7716_32xb_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32xb_cpld1", + }, + .probe = as7716_32xb_cpld_probe, + .remove = as7716_32xb_cpld_remove, + .id_table = as7716_32xb_cpld_id, + .address_list = normal_i2c, +}; + +static int __init as7716_32xb_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7716_32xb_cpld_driver); +} + +static void __exit as7716_32xb_cpld_exit(void) +{ + i2c_del_driver(&as7716_32xb_cpld_driver); +} + +module_init(as7716_32xb_cpld_init); +module_exit(as7716_32xb_cpld_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32xb_cpld driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_fan.c new file mode 100644 index 000000000000..65f3251c00ec --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_fan.c @@ -0,0 +1,710 @@ +/* + * A hwmon driver for the Accton as7716 32x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7716_32xb_fan" + +#define NUM_THERMAL_SENSORS (3) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define STRING_TO_DEC_VALUE 10 + +#define IN +#define OUT + +static struct as7716_32xb_fan_data *as7716_32xb_fan_update_device(struct device *dev); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_enable(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +static ssize_t fan_value_show(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t fan_value_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:B2F 1:F2B) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +#define FAN_NUM_MAX 6 +/* Each client has this additional data */ +struct as7716_32xb_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + u8 enable; + u8 duty_cycle; + unsigned int present[FAN_NUM_MAX]; + unsigned int front_speed_rpm[FAN_NUM_MAX]; + unsigned int rear_speed_rpm[FAN_NUM_MAX]; + unsigned int direction[FAN_NUM_MAX]; + unsigned int fault[FAN_NUM_MAX]; + unsigned int input[FAN_NUM_MAX]; +}; + +enum FAN_ID { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO|S_IWUSR, fan_value_show, fan_value_store, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO|S_IWUSR, fan_value_show, fan_value_store, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO|S_IWUSR, fan_value_show, fan_value_store, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_value_show, fan_value_store, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_value_show, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index##_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr, \ + &sensor_dev_attr_pwm##index##_enable.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IWUSR|S_IRUGO, fan_value_show, fan_value_store, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IWUSR|S_IRUGO, fan_value_show, fan_value_store, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IWUSR|S_IRUGO, fan_value_show, fan_value_store, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IWUSR|S_IRUGO, fan_value_show, fan_value_store, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IWUSR|S_IRUGO, fan_value_show, fan_value_store, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); + +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); + +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); + +static struct attribute *as7716_32xb_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7716_32xb_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7716_32xb_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum FAN_ID id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum FAN_ID id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as7716_32xb_fan_data *data, enum FAN_ID id) +{ + u8 ret = 0; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (!data->front_speed_rpm[id] && + !data->rear_speed_rpm[id] ) + { + ret = 1; + } + + return ret; +} + + +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct as7716_32xb_fan_data *data = as7716_32xb_fan_update_device(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + data->enable = value; + if (value == 0) + { + return set_duty_cycle(dev, da, buf, FAN_MAX_DUTY_CYCLE); + } + return count; +} + + + +static ssize_t get_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7716_32xb_fan_data *data = as7716_32xb_fan_update_device(dev); + + return sprintf(buf, "%u\n", data->enable); +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as7716_32xb_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as7716_32xb_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static int fan_array_index_get(int attr_idx) +{ + switch(attr_idx) + { + case FAN1_PRESENT: + case FAN1_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN1_FAULT: + case FAN1_DIRECTION: + return FAN1_ID; + case FAN2_PRESENT: + case FAN2_FRONT_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN2_FAULT: + case FAN2_DIRECTION: + return FAN2_ID; + case FAN3_PRESENT: + case FAN3_FRONT_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN3_FAULT: + case FAN3_DIRECTION: + return FAN3_ID; + case FAN4_PRESENT: + case FAN4_FRONT_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN4_FAULT: + case FAN4_DIRECTION: + return FAN4_ID; + case FAN5_PRESENT: + case FAN5_FRONT_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN5_FAULT: + case FAN5_DIRECTION: + return FAN5_ID; + case FAN6_PRESENT: + case FAN6_FRONT_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + case FAN6_FAULT: + case FAN6_DIRECTION: + return FAN6_ID; + default : + return -1; + } +} + +static ssize_t fan_value_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_fan_data *data = i2c_get_clientdata(client); + int status = -EINVAL; + int index; + long keyin = 0; + //printk("fan_value_store\n"); + //printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case FAN_DUTY_CYCLE_PERCENTAGE: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + break; + if (keyin > 1 || keyin < 0) + break; + data->duty_cycle=keyin; + break; + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + break; + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + data->front_speed_rpm[index]=keyin; + break; + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + break; + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + data->rear_speed_rpm[index]=keyin; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + break; + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + if(keyin < 0 || keyin > 1) + break; + data->present[index]=keyin; + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + break; + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + if(keyin < 0 || keyin > 1) + break; + data->fault[index]=keyin; + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + break; + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + if(keyin < 0 || keyin > 1) + break; + data->direction[index]=keyin; + break; + default: + break; + } + mutex_unlock(&data->update_lock); + return size; +} +static ssize_t fan_value_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_fan_data *data = i2c_get_clientdata(client); + int status = -EINVAL; + int index=0; + //printk("ffan_value_show\n"); + //printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case FAN_DUTY_CYCLE_PERCENTAGE: + status = sprintf(buf, "%u\n", data->duty_cycle); + break; + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + status = sprintf(buf, "%u\n", data->front_speed_rpm[index]); + break; + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + status = sprintf(buf, "%u\n", data->rear_speed_rpm[index]); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + status = sprintf(buf, "%d\n", data->present[index]); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + status = sprintf(buf, "%d\n", is_fan_fault(data, index)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + index=fan_array_index_get(attr->index);; + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + status = sprintf(buf, "%d\n", data->direction[index]); + break; + default: + break; + } + mutex_unlock(&data->update_lock); + return status; +} + +static const struct attribute_group as7716_32xb_fan_group = { + .attrs = as7716_32xb_fan_attributes, +}; + +static struct as7716_32xb_fan_data *as7716_32xb_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7716_32xb_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7716_32xb_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7716_32xb_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32xb_fan_data *data; + int status; + + data = kzalloc(sizeof(struct as7716_32xb_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_fan_remove(struct i2c_client *client) +{ + struct as7716_32xb_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7716_32xb_fan_id[] = { + { "as7716_32xb_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_fan_id); + +static struct i2c_driver as7716_32xb_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7716_32xb_fan_probe, + .remove = as7716_32xb_fan_remove, + .id_table = as7716_32xb_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7716_32xb_fan_init(void) +{ + return i2c_add_driver(&as7716_32xb_fan_driver); +} + +static void __exit as7716_32xb_fan_exit(void) +{ + i2c_del_driver(&as7716_32xb_fan_driver); +} + +module_init(as7716_32xb_fan_init); +module_exit(as7716_32xb_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32xb_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_leds.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_leds.c new file mode 100755 index 000000000000..2fa3fd722cb1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_leds.c @@ -0,0 +1,443 @@ +/* + * A LED driver for the as7716_32xb_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "as7716_32x_led" + +struct as7716_32x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct as7716_32x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting as7716_32x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = as7716_32x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void as7716_32x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = as7716_32x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + as7716_32x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void as7716_32x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7716_32x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness as7716_32x_led_diag_get(struct led_classdev *cdev) +{ + as7716_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void as7716_32x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7716_32x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness as7716_32x_led_loc_get(struct led_classdev *cdev) +{ + as7716_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void as7716_32x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness as7716_32x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev as7716_32x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "as7716_32x_led::diag", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_diag_set, + .brightness_get = as7716_32x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "as7716_32x_led::loc", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_loc_set, + .brightness_get = as7716_32x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "as7716_32x_led::fan", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_auto_set, + .brightness_get = as7716_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "as7716_32x_led::psu1", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_auto_set, + .brightness_get = as7716_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as7716_32x_led::psu2", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_auto_set, + .brightness_get = as7716_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int as7716_32x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + led_classdev_suspend(&as7716_32x_leds[i]); + } + + return 0; +} + +static int as7716_32x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + led_classdev_resume(&as7716_32x_leds[i]); + } + + return 0; +} + +static int as7716_32x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + printk("as7716_32x_led_probe 1\n"); + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &as7716_32x_leds[i]); + + if (ret < 0) + { + printk("ret < 0, i=%d\n", i); + break; + } + } + printk("as7716_32x_led_probe 2\n"); + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(as7716_32x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&as7716_32x_leds[i]); + } + } + + printk("as7716_32x_led_probe 3\n"); + return 0; +} + +static int as7716_32x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + led_classdev_unregister(&as7716_32x_leds[i]); + } + + return 0; +} + +static struct platform_driver as7716_32x_led_driver = { + .probe = as7716_32x_led_probe, + .remove = as7716_32x_led_remove, + .suspend = as7716_32x_led_suspend, + .resume = as7716_32x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init as7716_32x_led_init(void) +{ + int ret; + + printk("leds:1\n"); + ret = platform_driver_register(&as7716_32x_led_driver); + if (ret < 0) { + printk("leds:fail platform_driver_register\n"); + goto exit; + } + printk("leds:2\n"); + ledctl = kzalloc(sizeof(struct as7716_32x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&as7716_32x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + printk("leds:3\n"); + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + printk("leds:fail platform_device_register_simple\n"); + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&as7716_32x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return 0; +} + +static void __exit as7716_32x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&as7716_32x_led_driver); + kfree(ledctl); +} + +module_init(as7716_32x_led_init); +module_exit(as7716_32x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_oom.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_oom.c new file mode 100755 index 000000000000..5e88d9efad5d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_oom.c @@ -0,0 +1,267 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STRING_TO_DEC_VALUE 10 +#define EEPROM_DATA_SIZE 512 + + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +#define MAX_PORT_NAME_LEN 20 +/* Each client has this additional data + */ +struct as7716_32xb_oom_data { + struct device *hwmon_dev; + struct mutex lock; + u8 index; + unsigned char eeprom[EEPROM_DATA_SIZE]; + char port_name[MAX_PORT_NAME_LEN]; + +}; + + + +enum as7716_32xb_oom_sysfs_attributes { + TEMP1_INPUT, + TEMP1_MAX_HYST, + TEMP1_MAX +}; + +/* sysfs attributes for hwmon + */ + +static ssize_t oom_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t oom_info_show(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_port_name(struct device *dev, + struct device_attribute *dattr, char *buf); +static ssize_t set_port_name(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +static SENSOR_DEVICE_ATTR(eeprom, S_IWUSR|S_IRUGO, oom_info_show, oom_info_store, 0); +static SENSOR_DEVICE_ATTR(port_name, S_IRUGO | S_IWUSR, show_port_name, set_port_name, 1); + + +static struct attribute *as7716_32xb_oom_attributes[] = { + &sensor_dev_attr_eeprom.dev_attr.attr, + &sensor_dev_attr_port_name.dev_attr.attr, + NULL +}; + + +static ssize_t oom_info_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_oom_data *data = i2c_get_clientdata(client); + int i; + + mutex_lock(&data->lock); + memcpy(buf, data->eeprom, EEPROM_DATA_SIZE); + //for(i=0; i < EEPROM_DATA_SIZE ; i++) + //{ + // buf[i]=data->eeprom[i]; + // printk("buf[%d]=0x%x ",i, buf[i]); + //} + //status = EEPROM_DATA_SIZE+1; + + + memcpy(buf, data->eeprom, 256); + mutex_unlock(&data->lock); + + return 256; +} + +static ssize_t oom_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_oom_data *data = i2c_get_clientdata(client); + int i=0, j=0, k=0; + unsigned char str[3]; + unsigned int val; + + // printk("strlen(buf)=%d\n",strlen(buf)); + k=0; + mutex_lock(&data->lock); + memset(data->eeprom, 0xFF, EEPROM_DATA_SIZE); + memset(str, 0x0, 3); + if(strlen(buf) >= 256 ) + { + for(i=0; i < strlen(buf) ; i++) + { + // printk("i=%d ", i); + for(j=0;j<2; j++) + { + str[j]=buf[i+j]; + } + sscanf(str, "%x", &val); + //printk("str=%s val=0x%x ", str, val); + i=j+i-1; + if(k>=EEPROM_DATA_SIZE) + { + break; + } + data->eeprom[k]=(unsigned char)val; + //printk("data->eeprom[%d]=0x%x\n",k, data->eeprom[k]); + k++; + } + } + //printk("buf=\n"); + //for(i=0; i < strlen(buf) ; i++) + //{ + // printk("%c%c ", buf[i], buf[i+1]); + // if((i % 31)==0) + // printk("\n"); + //} + //printk("\n"); + + + mutex_unlock(&data->lock); + return size; + +} + +static ssize_t show_port_name(struct device *dev, + struct device_attribute *dattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_oom_data *data = i2c_get_clientdata(client); + ssize_t count; + + mutex_lock(&data->lock); + count = sprintf(buf, "%s\n", data->port_name); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t set_port_name(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_oom_data *data = i2c_get_clientdata(client); + char port_name[MAX_PORT_NAME_LEN]; + + /* no checking, this value is not used except by show_port_name */ + + if (sscanf(buf, "%19s", port_name) != 1) + return -EINVAL; + + mutex_lock(&data->lock); + strcpy(data->port_name, port_name); + mutex_unlock(&data->lock); + + return count; +} + + +static const struct attribute_group as7716_32xb_oom_group = { + .attrs = as7716_32xb_oom_attributes, +}; + +static int as7716_32xb_oom_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32xb_oom_data *data; + int status; + + data = kzalloc(sizeof(struct as7716_32xb_oom_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + i2c_set_clientdata(client, data); + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_oom_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: oom '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_oom_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_oom_remove(struct i2c_client *client) +{ + struct as7716_32xb_oom_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_oom_group); + kfree(data); + + return 0; +} + + +static const struct i2c_device_id as7716_32xb_oom_id[] = { + { "as7716_32xb_oom", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_oom_id); + +static struct i2c_driver as7716_32xb_oom_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32xb_oom", + }, + .probe = as7716_32xb_oom_probe, + .remove = as7716_32xb_oom_remove, + .id_table = as7716_32xb_oom_id, + .address_list = normal_i2c, +}; + + + + + + +static int __init as7716_32xb_oom_init(void) +{ + return i2c_add_driver(&as7716_32xb_oom_driver); +} + +static void __exit as7716_32xb_oom_exit(void) +{ + i2c_del_driver(&as7716_32xb_oom_driver); +} + +module_init(as7716_32xb_oom_init); +module_exit(as7716_32xb_oom_exit); + +MODULE_AUTHOR("Jostar yang "); +MODULE_DESCRIPTION("as7716_32xb_oom driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_pmbus.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_pmbus.c new file mode 100755 index 000000000000..3f4dba90d1aa --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_pmbus.c @@ -0,0 +1,444 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STRING_TO_DEC_VALUE 10 + + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7716_32xb_pmbus_data { + struct device *hwmon_dev; + struct mutex update_lock; + u8 index; + u8 capability; + u16 status_word; + u8 fan_fault; + u8 over_temp; + u16 v_out; + u16 i_out; + u16 p_out; + u16 temp; + u16 fan_speed; + u16 fan_duty_cycle; + u8 fan_dir[4]; + u8 pmbus_revision; + u8 mfr_id[10]; + u8 mfr_model[10]; + u8 mfr_revision[3]; + u16 mfr_vin_min; + u16 mfr_vin_max; + u16 mfr_iin_max; + u16 mfr_iout_max; + u16 mfr_pin_max; + u16 mfr_pout_max; + u16 mfr_vout_min; + u16 mfr_vout_max; + u16 power_on; + u16 temp_fault; + u16 power_good; +}; + + + +enum as7716_32xb_pmbus_sysfs_attributes { + PSU_POWER_ON = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD, + PSU_FAN1_FAULT, + PSU_FAN_DIRECTION, + PSU_OVER_TEMP, + PSU_V_OUT, + PSU_I_OUT, + PSU_P_OUT, + PSU_P_OUT_UV, /*In Unit of microVolt, instead of mini.*/ + PSU_TEMP1_INPUT, + PSU_FAN1_SPEED, + PSU_FAN1_DUTY_CYCLE, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_VIN_MIN, + PSU_MFR_VIN_MAX, + PSU_MFR_VOUT_MIN, + PSU_MFR_VOUT_MAX, + PSU_MFR_IIN_MAX, + PSU_MFR_IOUT_MAX, + PSU_MFR_PIN_MAX, + PSU_MFR_POUT_MAX +}; + +/* sysfs attributes for hwmon + */ +static ssize_t pmbus_info_show(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t pmbus_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static SENSOR_DEVICE_ATTR(psu_power_on, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_POWER_ON); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_over_temp, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_OVER_TEMP); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input,S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm,S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_FAN_DIRECTION); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision,S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IWUSR| S_IRUGO, pmbus_info_show,pmbus_info_store, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_VIN_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_VIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_VOUT_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_VOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_IIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IWUSR|S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_PIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_POUT_MAX); + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_TEMP_FAULT); + + +static struct attribute *as7716_32xb_pmbus_attributes[] = { + &sensor_dev_attr_psu_power_on.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_over_temp.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_temp1_fault.dev_attr.attr, + NULL +}; + + +static ssize_t pmbus_info_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_pmbus_data *data = i2c_get_clientdata(client); + int status = -EINVAL; + //printk("pmbus_info_show\n"); + printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case PSU_POWER_ON: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->power_on); + break; + case PSU_TEMP_FAULT: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->temp_fault); + break; + case PSU_POWER_GOOD: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->power_good); + break; + case PSU_FAN1_FAULT: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->fan_fault); + break; + case PSU_FAN_DIRECTION: + status=snprintf(buf, PAGE_SIZE-1, "%s\r\n", data->fan_dir); + break; + case PSU_OVER_TEMP: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->over_temp); + break; + case PSU_V_OUT: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->v_out); + break; + case PSU_I_OUT: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->i_out); + break; + case PSU_P_OUT: + printk("read PSU_P_OUT\n"); + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->p_out); + break; + case PSU_P_OUT_UV: + printk("read PSU_P_OUT_UV\n"); + status=snprintf(buf, PAGE_SIZE-1, "%ld\r\n", data->p_out * 1000000); + break; + case PSU_TEMP1_INPUT: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->temp); + break; + case PSU_FAN1_SPEED: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->fan_speed); + break; + case PSU_FAN1_DUTY_CYCLE: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->fan_duty_cycle); + break; + case PSU_PMBUS_REVISION: + break; + case PSU_MFR_ID: + status=snprintf(buf, PAGE_SIZE-1, "%s\r\n", data->mfr_id); + break; + case PSU_MFR_MODEL: + status=snprintf(buf, PAGE_SIZE-1, "%s\r\n", data->mfr_model); + break; + case PSU_MFR_REVISION: + status=snprintf(buf, PAGE_SIZE-1, "%s\r\n", data->mfr_revision); + break; + case PSU_MFR_VIN_MIN: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_vin_min); + break; + case PSU_MFR_VIN_MAX: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_vin_max); + break; + case PSU_MFR_VOUT_MIN: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_vin_max); + break; + case PSU_MFR_VOUT_MAX: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_vout_max); + break; + case PSU_MFR_IIN_MAX: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_iin_max); + break; + case PSU_MFR_IOUT_MAX: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_iout_max); + break; + case PSU_MFR_PIN_MAX: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_pin_max); + break; + case PSU_MFR_POUT_MAX: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_pout_max); + break; + default : + break; + } + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t pmbus_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_pmbus_data *data = i2c_get_clientdata(client); + long keyin = 0; + int status = -EINVAL; + //printk("pmbus_info_store\n"); + //printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + switch (attr->index) + { + case PSU_POWER_ON: + data->power_on=keyin; + break; + case PSU_TEMP_FAULT: + data->temp_fault=keyin; + break; + case PSU_POWER_GOOD: + data->power_good=keyin; + break; + case PSU_FAN1_FAULT: + break; + case PSU_FAN_DIRECTION: + memcpy(data->fan_dir, buf, sizeof(data->fan_dir)); + break; + case PSU_OVER_TEMP: + data->over_temp=keyin; + break; + case PSU_V_OUT: + data->v_out=keyin; + break; + case PSU_I_OUT: + data->i_out=keyin; + break; + case PSU_P_OUT: + printk("data->p_out=%d\n", data->p_out); + data->p_out=keyin; + break; + case PSU_P_OUT_UV: + //multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/ + + break; + case PSU_TEMP1_INPUT: + data->temp=keyin; + break; + case PSU_FAN1_SPEED: + data->fan_speed=keyin; + break; + case PSU_FAN1_DUTY_CYCLE: + break; + case PSU_PMBUS_REVISION: + data->pmbus_revision=keyin; + break; + case PSU_MFR_ID: + memcpy(data->mfr_id, buf, sizeof(data->mfr_id)); + break; + case PSU_MFR_MODEL: + memcpy(data->mfr_model, buf, sizeof(data->mfr_model)); + break; + case PSU_MFR_REVISION: + memcpy(data->mfr_revision, buf, sizeof(data->mfr_revision)); + break; + case PSU_MFR_VIN_MIN: + data->mfr_vin_min=keyin; + break; + case PSU_MFR_VIN_MAX: + data->mfr_vin_max=keyin; + break; + case PSU_MFR_VOUT_MIN: + data->mfr_vout_min=keyin; + break; + case PSU_MFR_VOUT_MAX: + data->mfr_vout_max=keyin; + break; + case PSU_MFR_IIN_MAX: + data->mfr_iin_max=keyin; + break; + case PSU_MFR_IOUT_MAX: + data->mfr_iout_max=keyin; + break; + case PSU_MFR_PIN_MAX: + data->mfr_pin_max=keyin; + break; + case PSU_MFR_POUT_MAX: + data->mfr_pout_max=keyin; + break; + default : + break; + } + mutex_unlock(&data->update_lock); + return count; +} + + +static const struct attribute_group as7716_32xb_pmbus_group = { + .attrs = as7716_32xb_pmbus_attributes, +}; + +static int as7716_32xb_pmbus_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32xb_pmbus_data *data; + int status; + + data = kzalloc(sizeof(struct as7716_32xb_pmbus_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + i2c_set_clientdata(client, data); + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_pmbus_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: pmbus '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_pmbus_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_pmbus_remove(struct i2c_client *client) +{ + struct as7716_32xb_pmbus_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_pmbus_group); + kfree(data); + + return 0; +} + + +static const struct i2c_device_id as7716_32xb_pmbus_id[] = { + { "as7716_32xb_pmbus", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_pmbus_id); + +static struct i2c_driver as7716_32xb_pmbus_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32xb_pmbus", + }, + .probe = as7716_32xb_pmbus_probe, + .remove = as7716_32xb_pmbus_remove, + .id_table = as7716_32xb_pmbus_id, + .address_list = normal_i2c, +}; + + + + + + +static int __init as7716_32xb_pmbus_init(void) +{ + return i2c_add_driver(&as7716_32xb_pmbus_driver); +} + +static void __exit as7716_32xb_pmbus_exit(void) +{ + i2c_del_driver(&as7716_32xb_pmbus_driver); +} + +module_init(as7716_32xb_pmbus_init); +module_exit(as7716_32xb_pmbus_exit); + +MODULE_AUTHOR("Jostar yang "); +MODULE_DESCRIPTION("as7716_32xb_pmbus driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_psu.c new file mode 100755 index 000000000000..01756e8596eb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_psu.c @@ -0,0 +1,355 @@ +/* + * An hwmon driver for accton as7716_32xbb Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MODEL_NAME 16 +#define DC12V_FAN_DIR_OFFSET 0x34 +#define DC12V_FAN_DIR_LEN 3 +#define STRING_TO_DEC_VALUE 10 + +//static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +static int as7716_32xb_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7716_32xb_cpld_read (unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7716_32xb_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + u8 present; + u8 power_good; + char model_name[MAX_MODEL_NAME+1]; /* Model name, read from eeprom */ + char fan_dir[DC12V_FAN_DIR_LEN+1]; /* DC12V fan direction */ +}; + +enum as7716_32xb_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_FAN_DIR /* For DC12V only */ +}; + +/* sysfs attributes for hwmon + */ +static ssize_t psu_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t psu_info_show(struct device *dev, struct device_attribute *da, + char *buf); +static SENSOR_DEVICE_ATTR(psu_present, S_IWUSR|S_IRUGO, psu_info_show, psu_info_store, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IWUSR|S_IRUGO, psu_info_show, psu_info_store, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IWUSR|S_IRUGO, psu_info_show, psu_info_store, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IWUSR|S_IRUGO, psu_info_show, psu_info_store, PSU_FAN_DIR); + + +static struct attribute *as7716_32xb_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + NULL +}; + +static ssize_t psu_info_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_psu_data *data = i2c_get_clientdata(client); + int status = -EINVAL; + //printk("psu_info_show\n"); + // printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case PSU_PRESENT: + //printk("data->present=%d\n",data->present); + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", data->present); + break; + case PSU_MODEL_NAME: + //printk("data->model_name=%s\n",data->model_name); + status = snprintf(buf, PAGE_SIZE - 1, "%s\r\n", data->model_name); + break; + case PSU_POWER_GOOD: + // printk("data->present=%d\n",data->power_good); + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", data->power_good); + break; + case PSU_FAN_DIR: + //printk("data->fan_dir=%s\n",data->fan_dir); + status = snprintf(buf, PAGE_SIZE - 1, "%s\r\n", data->fan_dir); + break; + default : + break; + } + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t psu_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_psu_data *data = i2c_get_clientdata(client); + long keyin = 0; + int status = -EINVAL; + //printk("psu_info_store\n"); + //printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case PSU_PRESENT: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + goto fail_exit; + if (keyin > 1 || keyin < 0) + goto fail_exit; + data->present=keyin; + break; + case PSU_MODEL_NAME: + memcpy(data->model_name, buf, MAX_MODEL_NAME); + break; + case PSU_POWER_GOOD: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + goto fail_exit; + if (keyin > 1 || keyin < 0) + goto fail_exit; + data->power_good=keyin; + break; + case PSU_FAN_DIR: + memcpy(data->fan_dir, buf, DC12V_FAN_DIR_LEN); + break; + default : + goto fail_exit; + } + mutex_unlock(&data->update_lock); + return count; + +fail_exit: + mutex_unlock(&data->update_lock); + return -EINVAL; +} + +static const struct attribute_group as7716_32xb_psu_group = { + .attrs = as7716_32xb_psu_attributes, +}; + +static int as7716_32xb_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32xb_psu_data *data; + int status; + + data = kzalloc(sizeof(struct as7716_32xb_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_psu_remove(struct i2c_client *client) +{ + struct as7716_32xb_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7716_32xb_psu1, + as7716_32xb_psu2 +}; + +static const struct i2c_device_id as7716_32xb_psu_id[] = { + { "as7716_32xb_psu1", as7716_32xb_psu1 }, + { "as7716_32xb_psu2", as7716_32xb_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_psu_id); + +static struct i2c_driver as7716_32xb_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32xb_psu", + }, + .probe = as7716_32xb_psu_probe, + .remove = as7716_32xb_psu_remove, + .id_table = as7716_32xb_psu_id, + .address_list = normal_i2c, +}; + +static int as7716_32xb_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +enum psu_type { + PSU_TYPE_AC_110V, + PSU_TYPE_DC_48V, + PSU_TYPE_DC_12V +}; + +struct model_name_info { + enum psu_type type; + u8 offset; + u8 length; + char* model_name; +}; + +struct model_name_info models[] = { +{PSU_TYPE_AC_110V, 0x20, 8, "YM-2651Y"}, +{PSU_TYPE_DC_48V, 0x20, 8, "YM-2651V"}, +{PSU_TYPE_DC_12V, 0x00, 11, "PSU-12V-750"}, +}; + +static int as7716_32xb_psu_model_name_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_psu_data *data = i2c_get_clientdata(client); + int i, status; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + memset(data->model_name, 0, sizeof(data->model_name)); + + status = as7716_32xb_psu_read_block(client, models[i].offset, + data->model_name, models[i].length); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x%x)\n", + client->addr, models[i].offset); + return status; + } + else { + data->model_name[models[i].length] = '\0'; + } + + /* Determine if the model name is known, if not, read next index + */ + if (strncmp(data->model_name, models[i].model_name, models[i].length) == 0) { + return 0; + } + else { + data->model_name[0] = '\0'; + } + } + + return -ENODATA; +} + +static int __init as7716_32xb_psu_init(void) +{ + return i2c_add_driver(&as7716_32xb_psu_driver); +} + +static void __exit as7716_32xb_psu_exit(void) +{ + i2c_del_driver(&as7716_32xb_psu_driver); +} + +module_init(as7716_32xb_psu_init); +module_exit(as7716_32xb_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32xb_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_sfp.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_sfp.c new file mode 100755 index 000000000000..9c7a05632154 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_sfp.c @@ -0,0 +1,365 @@ +/* + * An hwmon driver for accton as7716_32x sfp + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BIT_INDEX(i) (1UL << (i)) +#define I2C_ADDR_CPLD1 0x60 +#define I2C_ADDR_CPLD2 0x62 +#define I2C_ADDR_CPLD3 0x64 +#define CPLD1_OFFSET_QSFP_PRESET1 0x30 +#define CPLD1_OFFSET_QSFP_PRESET2 0x31 +#define CPLD1_OFFSET_QSFP_PRESET3 0x32 +#define CPLD1_OFFSET_QSFP_PRESET4 0x33 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7716_32x_sfp_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + int port; /* Front port index */ + char eeprom[256]; /* eeprom data */ + u32 is_present; /* present status */ +}; + +static struct as7716_32x_sfp_data *as7716_32x_sfp_update_device(struct device *dev); +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da,char *buf); +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +enum as7716_32x_sfp_sysfs_attributes { + SFP_PORT_NUMBER, + SFP_IS_PRESENT, + SFP_IS_PRESENT_ALL, + SFP_EEPROM +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, SFP_PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, SFP_IS_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_eeprom, S_IRUGO, show_eeprom, NULL, SFP_EEPROM); + +static struct attribute *as7716_32x_sfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_eeprom.dev_attr.attr, + NULL +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_sfp_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", data->port+1); +} + +/* Error-check the CPLD read results. */ +#define VALIDATED_READ(_buf, _rv, _read_expr, _invert) \ +do { \ + _rv = (_read_expr); \ + if(_rv < 0) { \ + return sprintf(_buf, "READ ERROR\n"); \ + } \ + if(_invert) { \ + _rv = ~_rv; \ + } \ + _rv &= 0xFF; \ +} while(0) + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if(attr->index == SFP_IS_PRESENT_ALL) { + int values[4]; + /* + * Report the SFP_PRESENCE status for all ports. + */ + + /* QSFP_PRESENT Ports 1-8 */ + //VALIDATED_READ(buf, values[0], accton_i2c_cpld_read(0x62, 0x9), 1); + VALIDATED_READ(buf, values[0], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET1), 1); + /* QSFP_PRESENT Ports 9-16 */ + VALIDATED_READ(buf, values[1], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET2), 1); + /* QSFP_PRESENT Ports 17-24 */ + VALIDATED_READ(buf, values[2], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET3), 1); + /* QSFP_PRESENT Ports 25-32 */ + VALIDATED_READ(buf, values[3], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET4), 1); + + /* Return values 1 -> 32 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + } + else { /* SFP_IS_PRESENT */ + struct as7716_32x_sfp_data *data = as7716_32x_sfp_update_device(dev); + + if (!data->valid) { + printk("return -EIO\n"); + return -EIO; + } + + return sprintf(buf, "%d\n", data->is_present); + } +} + +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7716_32x_sfp_data *data = as7716_32x_sfp_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!data->is_present) { + return 0; + } + + memcpy(buf, data->eeprom, sizeof(data->eeprom)); + + return sizeof(data->eeprom); +} + +static const struct attribute_group as7716_32x_sfp_group = { + .attrs = as7716_32x_sfp_attributes, +}; + +static int as7716_32x_sfp_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32x_sfp_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7716_32x_sfp_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + i2c_set_clientdata(client, data); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32x_sfp_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: sfp '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32x_sfp_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32x_sfp_remove(struct i2c_client *client) +{ + struct as7716_32x_sfp_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32x_sfp_group); + kfree(data); + + return 0; +} + +enum port_numbers { +as7716_32x_sfp1, as7716_32x_sfp2, as7716_32x_sfp3, as7716_32x_sfp4, +as7716_32x_sfp5, as7716_32x_sfp6, as7716_32x_sfp7, as7716_32x_sfp8, +as7716_32x_sfp9, as7716_32x_sfp10,as7716_32x_sfp11,as7716_32x_sfp12, +as7716_32x_sfp13,as7716_32x_sfp14,as7716_32x_sfp15,as7716_32x_sfp16, +as7716_32x_sfp17,as7716_32x_sfp18,as7716_32x_sfp19,as7716_32x_sfp20, +as7716_32x_sfp21,as7716_32x_sfp22,as7716_32x_sfp23,as7716_32x_sfp24, +as7716_32x_sfp25,as7716_32x_sfp26,as7716_32x_sfp27,as7716_32x_sfp28, +as7716_32x_sfp29,as7716_32x_sfp30,as7716_32x_sfp31,as7716_32x_sfp32 +}; + +static const struct i2c_device_id as7716_32x_sfp_id[] = { +{ "as7716_32x_sfp1", as7716_32x_sfp1 }, { "as7716_32x_sfp2", as7716_32x_sfp2 }, +{ "as7716_32x_sfp3", as7716_32x_sfp3 }, { "as7716_32x_sfp4", as7716_32x_sfp4 }, +{ "as7716_32x_sfp5", as7716_32x_sfp5 }, { "as7716_32x_sfp6", as7716_32x_sfp6 }, +{ "as7716_32x_sfp7", as7716_32x_sfp7 }, { "as7716_32x_sfp8", as7716_32x_sfp8 }, +{ "as7716_32x_sfp9", as7716_32x_sfp9 }, { "as7716_32x_sfp10", as7716_32x_sfp10 }, +{ "as7716_32x_sfp11", as7716_32x_sfp11 }, { "as7716_32x_sfp12", as7716_32x_sfp12 }, +{ "as7716_32x_sfp13", as7716_32x_sfp13 }, { "as7716_32x_sfp14", as7716_32x_sfp14 }, +{ "as7716_32x_sfp15", as7716_32x_sfp15 }, { "as7716_32x_sfp16", as7716_32x_sfp16 }, +{ "as7716_32x_sfp17", as7716_32x_sfp17 }, { "as7716_32x_sfp18", as7716_32x_sfp18 }, +{ "as7716_32x_sfp19", as7716_32x_sfp19 }, { "as7716_32x_sfp20", as7716_32x_sfp20 }, +{ "as7716_32x_sfp21", as7716_32x_sfp21 }, { "as7716_32x_sfp22", as7716_32x_sfp22 }, +{ "as7716_32x_sfp23", as7716_32x_sfp23 }, { "as7716_32x_sfp24", as7716_32x_sfp24 }, +{ "as7716_32x_sfp25", as7716_32x_sfp25 }, { "as7716_32x_sfp26", as7716_32x_sfp26 }, +{ "as7716_32x_sfp27", as7716_32x_sfp27 }, { "as7716_32x_sfp28", as7716_32x_sfp28 }, +{ "as7716_32x_sfp29", as7716_32x_sfp29 }, { "as7716_32x_sfp30", as7716_32x_sfp30 }, +{ "as7716_32x_sfp31", as7716_32x_sfp31 }, { "as7716_32x_sfp32", as7716_32x_sfp32 }, +{} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32x_sfp_id); + +static struct i2c_driver as7716_32x_sfp_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32x_sfp", + }, + .probe = as7716_32x_sfp_probe, + .remove = as7716_32x_sfp_remove, + .id_table = as7716_32x_sfp_id, + .address_list = normal_i2c, +}; + +static int as7716_32x_sfp_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +static struct as7716_32x_sfp_data *as7716_32x_sfp_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_sfp_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + int i = 0; + u8 cpld_reg = 0x30 + (data->port/8); + + data->valid = 0; + + /* Read present status of the specified port number */ + data->is_present = 0; + status = accton_i2c_cpld_read(I2C_ADDR_CPLD1, cpld_reg); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD1, cpld_reg, status); + goto exit; + } + + data->is_present = (status & (1 << (data->port % 8))) ? 0 : 1; + printk("data->is_present=%d, data->port=%d, status=0x%x\n",data->is_present, data->port, status); + /* Read eeprom data based on port number */ + memset(data->eeprom, 0, sizeof(data->eeprom)); + + /* Check if the port is present */ + if (data->is_present) { + /* read eeprom */ + for (i = 0; i < sizeof(data->eeprom)/I2C_SMBUS_BLOCK_MAX; i++) { + status = as7716_32x_sfp_read_block(client, i*I2C_SMBUS_BLOCK_MAX, + data->eeprom+(i*I2C_SMBUS_BLOCK_MAX), + I2C_SMBUS_BLOCK_MAX); + if (status < 0) { + printk("unable to read eeprom from port(%d)\n", data->port); + dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n", data->port); + goto exit; + } + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as7716_32x_sfp_init(void) +{ + //extern int platform_accton_as7716_32x(void); + //if (!platform_accton_as7716_32x()) { +// return -ENODEV; + //} + + return i2c_add_driver(&as7716_32x_sfp_driver); +} + +static void __exit as7716_32x_sfp_exit(void) +{ + i2c_del_driver(&as7716_32x_sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7716_32x_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(as7716_32x_sfp_init); +module_exit(as7716_32x_sfp_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_sys.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_sys.c new file mode 100755 index 000000000000..f0a8125139cc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_sys.c @@ -0,0 +1,243 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STRING_TO_DEC_VALUE 10 +#define EEPROM_DATA_SIZE 256 + + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +#define MAX_PORT_NAME_LEN 20 +/* Each client has this additional data + */ +struct as7716_32xb_sys_data { + struct device *hwmon_dev; + struct mutex lock; + u8 index; + unsigned char eeprom[EEPROM_DATA_SIZE]; +}; + + +/* sysfs attributes for hwmon + */ + +static ssize_t sys_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t sys_info_show(struct device *dev, struct device_attribute *da, + char *buf); + +static SENSOR_DEVICE_ATTR(eeprom, S_IWUSR|S_IRUGO, sys_info_show, sys_info_store, 0); + + + +static struct attribute *as7716_32xb_sys_attributes[] = { + &sensor_dev_attr_eeprom.dev_attr.attr, + NULL +}; + + +static ssize_t sys_info_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_sys_data *data = i2c_get_clientdata(client); +// int status = -EINVAL; + int i; + + //printk("sys_info_show\n"); + // printk("attr->index=%d\n", attr->index); + mutex_lock(&data->lock); + //for(i=0; i<8; i++) + // printk("data->eeprom[%d]=0x%x ",i, data->eeprom[i]); + //printk("\n"); + memcpy(buf, data->eeprom, EEPROM_DATA_SIZE); + //for(i=0; i < EEPROM_DATA_SIZE ; i++) + //{ + // buf[i]=data->eeprom[i]; + // printk("buf[%d]=0x%x ",i, buf[i]); + //} + //status = EEPROM_DATA_SIZE+1; + + //printk("\n"); + //status = sprintf(buf, "%x", 0xA); + //data->eeprom[0]=0x0d; + //data->eeprom[1]=0x0; + //data->eeprom[2]=0x06; + // buf[3]=0xFF; + + // for(i=0; i< 16; i++) + // printk("buf[%d]=0x%x ",i, buf[i]); + //printk("\n"); + + memcpy(buf, data->eeprom, 256); + + + mutex_unlock(&data->lock); + + return 256; +} + +static ssize_t sys_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_sys_data *data = i2c_get_clientdata(client); + int i=0, j=0, k=0; + unsigned char str[3]; + unsigned int val; + + //printk("sys_info_store\n"); + //printk("attr->index=%d\n", attr->index); + //printk("buf[0]=0x%x, buf[1]=0x%x, buf[2]=0x%x, buf[3]=0x%x\n", buf[0], buf[1], buf[2], buf[3]); + + // printk("strlen(buf)=%d\n",strlen(buf)); + k=0; + mutex_lock(&data->lock); + memset(data->eeprom, 0xFF, EEPROM_DATA_SIZE); + memset(str, 0x0, 3); + if(strlen(buf) >= 256 ) + { + for(i=0; i < strlen(buf) ; i++) + { + // printk("i=%d ", i); + for(j=0;j<2; j++) + { + str[j]=buf[i+j]; + } + sscanf(str, "%x", &val); + // printk("str=%s val=0x%x ", str, val); + i=j+i-1; + if(k>=EEPROM_DATA_SIZE) + { + break; + } + data->eeprom[k]=(unsigned char)val; + // printk("data->eeprom[%d]=0x%x\n",k, data->eeprom[k]); + k++; + } + } + //printk("buf=\n"); + //for(i=0; i < strlen(buf) ; i++) + //{ + // printk("%c%c ", buf[i], buf[i+1]); + // if((i % 31)==0) + // printk("\n"); + //} + //printk("\n"); + + //printk("eeprom[0]=0x%x, eeprom[1]=0x%x, eeprom[2]=0x%x, eeprom[3]=0x%x\n", + // data->eeprom[0], data->eeprom[1], data->eeprom[2], data->eeprom[3]); + + mutex_unlock(&data->lock); + return size; + +} + +static const struct attribute_group as7716_32xb_sys_group = { + .attrs = as7716_32xb_sys_attributes, +}; + +static int as7716_32xb_sys_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32xb_sys_data *data; + int status; + + data = kzalloc(sizeof(struct as7716_32xb_sys_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + i2c_set_clientdata(client, data); + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_sys_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: sys '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_sys_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_sys_remove(struct i2c_client *client) +{ + struct as7716_32xb_sys_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_sys_group); + kfree(data); + + return 0; +} + + +static const struct i2c_device_id as7716_32xb_sys_id[] = { + { "as7716_32xb_sys", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_sys_id); + +static struct i2c_driver as7716_32xb_sys_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32xb_sys", + }, + .probe = as7716_32xb_sys_probe, + .remove = as7716_32xb_sys_remove, + .id_table = as7716_32xb_sys_id, + .address_list = normal_i2c, +}; + + + + + + +static int __init as7716_32xb_sys_init(void) +{ + return i2c_add_driver(&as7716_32xb_sys_driver); +} + +static void __exit as7716_32xb_sys_exit(void) +{ + i2c_del_driver(&as7716_32xb_sys_driver); +} + +module_init(as7716_32xb_sys_init); +module_exit(as7716_32xb_sys_exit); + +MODULE_AUTHOR("Jostar yang "); +MODULE_DESCRIPTION("as7716_32xb_sys driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_thermal.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_thermal.c new file mode 100755 index 000000000000..d42341bb181a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_thermal.c @@ -0,0 +1,214 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STRING_TO_DEC_VALUE 10 +#define STRING_TO_HEX_VALUE 16 + +#define TEMP1_MAX_HYST_DEFAULT 75000 +#define TEMP1_MAX_DEFAULT 80000 +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7716_32xb_thermal_data { + struct device *hwmon_dev; + struct mutex update_lock; + u8 index; + unsigned int temp1_input; + unsigned int temp1_max_hyst; + unsigned int temp1_max; +}; + + + +enum as7716_32xb_thermal_sysfs_attributes { + TEMP1_INPUT, + TEMP1_MAX_HYST, + TEMP1_MAX +}; + +/* sysfs attributes for hwmon + */ + +static ssize_t temp_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t temp_info_show(struct device *dev, struct device_attribute *da, + char *buf); +static SENSOR_DEVICE_ATTR(temp1_input, S_IWUSR|S_IRUGO, temp_info_show, temp_info_store, TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR|S_IRUGO, temp_info_show, temp_info_store, TEMP1_MAX_HYST); +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR|S_IRUGO, temp_info_show, temp_info_store, TEMP1_MAX); + + +static struct attribute *as7716_32xb_thermal_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + NULL +}; + + +static ssize_t temp_info_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_thermal_data *data = i2c_get_clientdata(client); + int status = -EINVAL; + + mutex_lock(&data->update_lock); + switch (attr->index) + { + case TEMP1_INPUT: + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", data->temp1_input); + break; + case TEMP1_MAX_HYST: + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", TEMP1_MAX_HYST_DEFAULT); + break; + case TEMP1_MAX: + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", TEMP1_MAX_DEFAULT); + break; + default : + break; + } + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t temp_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_thermal_data *data = i2c_get_clientdata(client); + long keyin = 0; + int status = -EINVAL; + + mutex_lock(&data->update_lock); + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + switch (attr->index) + { + case TEMP1_INPUT: + data->temp1_input=keyin; + break; + case TEMP1_MAX_HYST: + data->temp1_max_hyst=keyin; + break; + case TEMP1_MAX: + data->temp1_max=keyin; + break; + default : + break; + } + mutex_unlock(&data->update_lock); + return size; + +} + +static const struct attribute_group as7716_32xb_thermal_group = { + .attrs = as7716_32xb_thermal_attributes, +}; + +static int as7716_32xb_thermal_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32xb_thermal_data *data; + int status; + + data = kzalloc(sizeof(struct as7716_32xb_thermal_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + i2c_set_clientdata(client, data); + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_thermal_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: thermal '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_thermal_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_thermal_remove(struct i2c_client *client) +{ + struct as7716_32xb_thermal_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_thermal_group); + kfree(data); + + return 0; +} + + +static const struct i2c_device_id as7716_32xb_thermal_id[] = { + { "as7716_32xb_thermal", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_thermal_id); + +static struct i2c_driver as7716_32xb_thermal_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32xb_thermal", + }, + .probe = as7716_32xb_thermal_probe, + .remove = as7716_32xb_thermal_remove, + .id_table = as7716_32xb_thermal_id, + .address_list = normal_i2c, +}; + + + + + + +static int __init as7716_32xb_thermal_init(void) +{ + return i2c_add_driver(&as7716_32xb_thermal_driver); +} + +static void __exit as7716_32xb_thermal_exit(void) +{ + i2c_del_driver(&as7716_32xb_thermal_driver); +} + +module_init(as7716_32xb_thermal_init); +module_exit(as7716_32xb_thermal_exit); + +MODULE_AUTHOR("Jostar yang "); +MODULE_DESCRIPTION("as7716_32xb_thermal driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_i2c_cpld.c new file mode 100755 index 000000000000..46d1e2773287 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_i2c_cpld.c @@ -0,0 +1,259 @@ +/* + * A hwmon driver for the accton_i2c_cpld + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CPLD_VERSION_REG 0x1 + +enum as5712_54x_cpld_sysfs_attributes { + CPLD_READ_VERSION, + CPLD_BYTE_ACCESS, + CPLD_DUMP_ALL, +}; + +static ssize_t read_cpld_version(struct device *dev, struct device_attribute *da, + char *buf); +int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); + + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for accton_i2c_cpld + */ +static const unsigned short normal_i2c[] = { 0x31, 0x35, 0x60, 0x61, 0x62, I2C_CLIENT_END }; + +static SENSOR_DEVICE_ATTR(cpld_get_version, S_IRUGO, read_cpld_version, NULL, CPLD_READ_VERSION); + +static struct attribute *as5712_54x_cpld_attributes[] = { + &sensor_dev_attr_cpld_get_version.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5712_54x_cpld_group = { + .attrs = as5712_54x_cpld_attributes, +}; + +static ssize_t read_cpld_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + unsigned short cpld_reg = CPLD_VERSION_REG; + u8 reg; + + if(attr->index == CPLD_READ_VERSION) { + reg = accton_i2c_cpld_read(client->addr, cpld_reg); + return sprintf(buf, "%02x\n",reg); + } + return -1 ; +} + + +static void accton_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void accton_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int accton_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5712_54x_cpld_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + accton_i2c_cpld_add_client(client); + + return 0; +exit: + return status; +} + +static int accton_i2c_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &as5712_54x_cpld_group); + + accton_i2c_cpld_remove_client(client); + return 0; +} + +static const struct i2c_device_id accton_i2c_cpld_id[] = { + { "accton_i2c_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id); + +static struct i2c_driver accton_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "accton_i2c_cpld", + }, + .probe = accton_i2c_cpld_probe, + .remove = accton_i2c_cpld_remove, + .id_table = accton_i2c_cpld_id, + .address_list = normal_i2c, +}; + +int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_read); + +int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_write); + +static int __init accton_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&accton_i2c_cpld_driver); +} + +static void __exit accton_i2c_cpld_exit(void) +{ + i2c_del_driver(&accton_i2c_cpld_driver); +} +/* +static struct dmi_system_id as7712_dmi_table[] = { + { + .ident = "Accton AS7712", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS7712"), + }, + } +}; + +int platform_accton_as7712_32x(void) +{ + return dmi_check_system(as7712_dmi_table); +} +EXPORT_SYMBOL(platform_accton_as7712_32x); +*/ +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_i2c_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_i2c_cpld_init); +module_exit(accton_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/service/as7716_32xb-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/service/as7716_32xb-platform-monitor.service new file mode 100755 index 000000000000..05a5d93c48b9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/service/as7716_32xb-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS7716-32XB Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7716_32xb_util.py install +ExecStart=/usr/local/bin/accton_as7716_32xb_drv_handler.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/setup.py new file mode 100755 index 000000000000..3edfc29b3817 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7716_32xb', + version='1.0', + description='Module to initialize Accton AS7716-32XB platforms', + + packages=['as7716_32xb'], + package_dir={'as7716_32xb': 'as7716-32xb/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/README new file mode 100755 index 000000000000..c602d753301e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program is free software: you can redistribute it and/or modify +It under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as5712_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as5712-fan-psu-cpld.patch + for as5712's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS5712-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as5712 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-4-amd64_3.16.36-1+deb8u2_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS5712-54X.patch" from patch/installer. + - Change setting for AS5712-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS5712-54X.patch" + !!NOTICE, patching onie_installer-accton-AS5712-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-4-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5712-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as5712-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as5712_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS5712-54X.patch. + It's done by patching onie_installer-accton-AS5712-54X.patch at build-image. + Run "accton_as5712_util.py install" to install drivers. + +To initialize the system, run "accton_as5712_util.py install". +To clean up the drivers & devices, run "accton_as5712_util.py clean". +To dump information of sensors, run "accton_as5712_util.py show". +To dump SFP EEPROM, run "accton_as5712_util.py sff". +To set fan speed, run "accton_as5712_util.py set fan". +To enable/disable SFP emission, run "accton_as5712_util.py set sfp". +To set system LEDs' color, run "accton_as5712_util.py set led" +For more information, run "accton_as5712_util.py --help". + +==================================================================== +Besides applying accton_as5712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_drv_handler.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_drv_handler.py new file mode 100755 index 000000000000..c08a82c7dc45 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_drv_handler.py @@ -0,0 +1,443 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 1/18/2018: Jostar create for as7716_32xb +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import types + import time # this is only being used as part of the example + import traceback + import commands + from tabulate import tabulate +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'as7716_32xb_drv_handler' +DEBUG = False + +global log_file +global log_level + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + if DEBUG == True: + my_log (cmd +" , result:" + str(status)) + else: + if show: + print "ACC: " + str(cmd) + " , result:"+ str(status) + #my_log ("cmd:" + cmd) + #my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as7716xb_drv_handler(object): + + QSFP_PORT_START = 1 + QSFP_PORT_END = 32 + BASE_PATH = "/usr/local/bin/" + BASE_I2C_PATH="/sys/bus/i2c/devices/" + QSFP_PRESENT_PATH = "/sys/bus/i2c/devices/0-0060/module_present_" + QSFP_RESET_PATH = "/sys/bus/i2c/devices/0-0060/module_reset_" + QSFP_PRESENT_FILE = "/tmp/ipmi_qsfp_pres" + QSFP_EEPROM_FILE = "/tmp/ipmi_qsfp_ee_" + THERMAL_FILE = "/tmp/ipmi_thermal" + IPMI_CMD_QSFP = "ipmitool raw 0x34 0x10 " + IPMI_CMD_THERMAL = "ipmitool raw 0x34 0x12 " + IPMI_CMD_FAN = "ipmitool raw 0x34 0x14 " + IPMI_CMD_PSU ="ipmitool raw 0x34 0x16 " + IPMI_CMD_SYS_EEPROM_1 ="ipmitool raw 0x34 0x18 0x0 0x80" + IPMI_CMD_SYS_EEPROM_2 ="ipmitool raw 0x34 0x18 0x80 0x80" + FAN_ID_START = 1 + FAN_ID_END = 6 + FAN_FILE = "/tmp/ipmi_fan" + FAN_PATH = "/sys/bus/i2c/devices/0-0066/fan" + PSU_ID_START = 1 + PSU_ID_END = 2 + PSU1_PATH = "/sys/bus/i2c/devices/0-0053/" + PSU2_PATH = "/sys/bus/i2c/devices/0-0050/" + PSU1_PMBUS_PATH = "/sys/bus/i2c/devices/0-005b/" + PSU2_PMBUS_PATH = "/sys/bus/i2c/devices/0-0058/" + PSU_FILE = "/tmp/ipmi_psu_" + SYS_EEPROM_FILE_1 = "/tmp/ipmi_sys_eeprom_1" + SYS_EEPROM_FILE_2 = "/tmp/ipmi_sys_eeprom_2" + SYS_EEPROM_PATH = "/sys/bus/i2c/devices/0-0056/eeprom" + + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_ipmi_qsfp(self): + logging.debug ("drv hanlder-manage_ipmi_qsfp") + print "drv hanlder" + #Handle QSFP case + ipmi_cmd = self.IPMI_CMD_QSFP + " 0x10 > " +self.QSFP_PRESENT_FILE + log_os_system(ipmi_cmd, 0) + file_path = self.QSFP_PRESENT_FILE + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + pres_line= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + pres_line+=line.rstrip().replace(" ","") + check_file.close() + + + for i in range(self.QSFP_PORT_START, self.QSFP_PORT_END+1, 1): + if i>1: + k=(i-1)*2 +1 + else: + k=1; + if pres_line[k] == '1': + #Set QSFP present + #print "port-%d present" %i + set_drv_cmd = "echo 1 > " + self.QSFP_PRESENT_PATH + str(i) + log_os_system(set_drv_cmd, 0) + #Read QSFP EEPROM + ipmi_cmd = self.IPMI_CMD_QSFP +str(i)+ " 0x00 > " +self.QSFP_EEPROM_FILE + str(i) + "_1" + log_os_system(ipmi_cmd, 0) + ipmi_cmd = self.IPMI_CMD_QSFP +str(i)+ " 0x01 > " +self.QSFP_EEPROM_FILE + str(i) + "_2" + log_os_system(ipmi_cmd, 0) + file_path = self.QSFP_EEPROM_FILE + str(i) + "_1" + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + file_path = self.QSFP_EEPROM_FILE + str(i) + "_2" + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line+= line.rstrip().replace(" ","") + + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + #Set QSFP EEPROM + if(i < 10): + set_drv_cmd = "echo " + str_line+ " > " + self.BASE_I2C_PATH + "0-000"+str(i) +"/eeprom" + else: + set_drv_cmd = "echo " + str_line+ " > " + self.BASE_I2C_PATH + "0-00"+str(i) +"/eeprom" + #print(set_drv_cmd) + log_os_system(set_drv_cmd, 0) + else: + ipmi_cmd = "echo 0 > " + self.QSFP_PRESENT_PATH + str(i) + log_os_system(ipmi_cmd, 0) + if(i < 10): + set_drv_cmd = "echo 0 > " + self.BASE_I2C_PATH + "0-000"+str(i) +"/eeprom" + else: + set_drv_cmd = "echo 0 > " + self.BASE_I2C_PATH + "0-00"+str(i) +"/eeprom" + #print(set_drv_cmd) + log_os_system(set_drv_cmd, 0) + + time.sleep(0.01) + return True + + def manage_ipmi_thermal(self): + logging.debug ("drv hanlder-manage_ipmi_thermal") + #Handle thermal case + #ipmitool raw 0x34 0x12 + ipmi_cmd = self.IPMI_CMD_THERMAL + " > " +self.THERMAL_FILE + log_os_system(ipmi_cmd, 0) + file_path = self.THERMAL_FILE + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + val_str= "0x" + str(str_line[4])+str(str_line[5]) + val_int=int(val_str, 16)*1000 + check_file.close() + set_drv_cmd = "echo "+str(val_int) + " > " + self.BASE_I2C_PATH + "0-0048/temp1_input" + log_os_system(set_drv_cmd,0) + val_str= "0x" + str(str_line[10])+str(str_line[11]) + val_int=int(val_str, 16) * 1000 + set_drv_cmd = "echo "+str(val_int) + " > " + self.BASE_I2C_PATH + "0-0049/temp1_input" + log_os_system(set_drv_cmd,0) + val_str= "0x" + str(str_line[16])+str(str_line[17]) + val_int=int(val_str, 16) * 1000 + set_drv_cmd = "echo "+str(val_int) + " > " + self.BASE_I2C_PATH + "0-004a/temp1_input" + log_os_system(set_drv_cmd, 0) + + return True + + def manage_ipmi_fan(self): + logging.debug ("drv hanlder-manage_ipmi_fan") + #Handle fan case + #ipmitool raw 0x34 0x14 + ipmi_cmd = self.IPMI_CMD_FAN + " > " +self.FAN_FILE + log_os_system(ipmi_cmd, 0) + file_path = self.FAN_FILE + #print(file_path) + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + #print (str_line) + k=0 + for i in range(self.FAN_ID_START, self.FAN_ID_END+1, 1): + #print "k=%d"%k + if str_line[k+1]=='0': + set_drv_cmd = "echo 1 > " + self.FAN_PATH + str(i) + "_present" + else: + set_drv_cmd = "echo 0 > " + self.FAN_PATH + str(i) + "_present" + log_os_system(set_drv_cmd, 0) + + val_str= "0x" + str(str_line[k+6])+str(str_line[k+7]) + str(str_line[k+4])+str(str_line[k+5]) + val_int=int(val_str, 16) + set_drv_cmd = "echo " + str(val_int) + " > " + self.FAN_PATH + str(i) + "_front_speed_rpm" + log_os_system(set_drv_cmd, 0) + val_str= "0x" + str(str_line[k+54])+str(str_line[k+55]) + str(str_line[k+52])+str(str_line[k+53]) + val_int=int(val_str, 16) + set_drv_cmd = "echo " + str(val_int) + " > " + self.FAN_PATH + str(i) + "_rear_speed_rpm" + log_os_system(set_drv_cmd, 0) + k+=8; + return True + + + def manage_ipmi_psu(self): + logging.debug ("drv hanlder-manage_ipmi_psu") + #Handle psu case + #present: ipmitool raw 0x34 0x16 '0x1' . Param-1 is psu id(id_1:0x1, id_2:0x2) + + #cpld access psu + for i in range(self.PSU_ID_START, self.PSU_ID_END+1, 1): + #present case + ipmi_cmd = self.IPMI_CMD_PSU + str(i) + " > " +self.PSU_FILE + str(i) + log_os_system(ipmi_cmd, 0) + if i==1: + psu_sysfs_path = self.PSU1_PATH + else: + psu_sysfs_path = self.PSU2_PATH + file_path = self.PSU_FILE + str(i) + #print(file_path) + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + #print (line) + if str_line[1]=='0': + int_val=1 #psu insert + #print "psu_%d present"%i + set_drv_cmd = "echo " +str(int_val) + " > " + psu_sysfs_path + "psu_present" + log_os_system(set_drv_cmd, 0) + set_drv_cmd = "echo " + str(str_line[5]) + " > " + psu_sysfs_path + "psu_power_good" + log_os_system(set_drv_cmd, 0) + else: + int_val=0 + set_drv_cmd = "echo " +str(int_val) + " > " + psu_sysfs_path + "psu_present" + log_os_system(set_drv_cmd, 0) + set_drv_cmd = "echo " + str(int_val) + " > " + psu_sysfs_path + "psu_power_good" + log_os_system(set_drv_cmd, 0) + + #pmbus + if i==1: + psu_sysfs_path = self.PSU1_PMBUS_PATH + else: + psu_sysfs_path = self.PSU2_PMBUS_PATH + + if str_line[5]=='1': #power_on + val_str= "0x" + str(str_line[28])+str(str_line[29]) + str(str_line[26])+str(str_line[27]) + val_int=int(val_str, 16) * 1000 + set_drv_cmd = "echo " + str(val_int) + " > " + psu_sysfs_path + "psu_temp1_input" + log_os_system(set_drv_cmd, 0) + #print "val_int=%d"%val_int + val_str= "0x" + str(str_line[32])+str(str_line[33]) + str(str_line[30])+str(str_line[31]) + val_int=int(val_str, 16) + #print "fan:val_int=%d"%val_int + set_drv_cmd = "echo " + str(val_int) + " > " + psu_sysfs_path + "psu_fan1_speed_rpm" + log_os_system(set_drv_cmd, 0) + val_str= "0x" + str(str_line[36])+str(str_line[37]) + str(str_line[34])+str(str_line[35]) + val_int=int(val_str, 16) + #print "pout val_int=%d"%val_int + set_drv_cmd = "echo " + str(val_int) + " > " + psu_sysfs_path + "psu_p_out" + log_os_system(set_drv_cmd, 0) + else: #power_off + val_int=0 + set_drv_cmd = "echo " + str(val_int) + " > " + psu_sysfs_path + "psu_temp1_input" + log_os_system(set_drv_cmd, 0) + set_drv_cmd = "echo " + str(val_int) + " > " + psu_sysfs_path + "psu_fan1_speed_rpm" + log_os_system(set_drv_cmd, 0) + set_drv_cmd = "echo " + str(val_int) + " > " + psu_sysfs_path + "psu_p_out" + log_os_system(set_drv_cmd, 0) + + time.sleep(2) + return True + + def manage_ipmi_sys(self): + logging.debug ("drv hanlder-manage_ipmi_sys") + #Handle sys case + #ipmitool -raw 0x34 0x18 0x00 0x80 + #ipmitool -raw 0x34 0x18 0x80 0x80 + + ipmi_cmd = self.IPMI_CMD_SYS_EEPROM_1 + " > " + self.SYS_EEPROM_FILE_1 + log_os_system(ipmi_cmd, 0) + ipmi_cmd = self.IPMI_CMD_SYS_EEPROM_2 + " > " + self.SYS_EEPROM_FILE_2 + log_os_system(ipmi_cmd, 0) + + #Read SYS EEPROM + file_path = self.SYS_EEPROM_FILE_1 + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + + file_path = self.SYS_EEPROM_FILE_2 + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line+= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + #print(len(str_line)) + #print(str_line) + set_drv_cmd = "echo " + str_line+ " > " + self.SYS_EEPROM_PATH + #print(set_drv_cmd) + log_os_system(set_drv_cmd, 0) + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.WARNING + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + set_drv_cmd = "echo 100 > /sys/module/ipmi_si/parameters/kipmid_max_busy_us" + log_os_system(set_drv_cmd, 0) + monitor = accton_as7716xb_drv_handler(log_file, log_level) + + set_sys_eeprom=0 + thermal_chk_time=0 + psu_chk_time=0 + # Loop forever, doing something useful hopefully: + while True: + logging.debug ("monitor.manage_ipmi") + if set_sys_eeprom==0: + monitor.manage_ipmi_sys() + set_sys_eeprom=1 + monitor.manage_ipmi_qsfp() + time.sleep(0.1) + monitor.manage_ipmi_thermal() + monitor.manage_ipmi_psu() + time.sleep(0.1) + monitor.manage_ipmi_fan() + time.sleep(0.05) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_monitor.py new file mode 100755 index 000000000000..2568312b0955 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_monitor.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + from as7716_32x.fanutil import FanUtil + from as7716_32x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as7716_monitor' + +global log_file +global log_level + + # For AC power Front to Back : + # If any fan fail, please fan speed register to 15 + # The max value of Fan speed register is 9 + # [LM75(48) + LM75(49) + LM75(4A)] > 174 => set Fan speed value from 4 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] > 182 => set Fan speed value from 5 to 7 + # [LM75(48) + LM75(49) + LM75(4A)] > 190 => set Fan speed value from 7 to 9 + # + # [LM75(48) + LM75(49) + LM75(4A)] < 170 => set Fan speed value from 5 to 4 + # [LM75(48) + LM75(49) + LM75(4A)] < 178 => set Fan speed value from 7 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] < 186 => set Fan speed value from 9 to 7 + # + # + # For AC power Back to Front : + # If any fan fail, please fan speed register to 15 + # The max value of Fan speed register is 10 + # [LM75(48) + LM75(49) + LM75(4A)] > 140 => set Fan speed value from 4 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] > 150 => set Fan speed value from 5 to 7 + # [LM75(48) + LM75(49) + LM75(4A)] > 160 => set Fan speed value from 7 to 10 + # + # [LM75(48) + LM75(49) + LM75(4A)] < 135 => set Fan speed value from 5 to 4 + # [LM75(48) + LM75(49) + LM75(4A)] < 145 => set Fan speed value from 7 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] < 155 => set Fan speed value from 10 to 7 + # + + + # 2.If no matched fan speed is found from the policy, + # use FAN_DUTY_CYCLE_MIN as default speed + # Get current temperature + # 4.Decision 3: Decide new fan speed depend on fan direction/current fan speed/temperature + + + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as7716_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + + fan_policy_f2b = { + 0: [32, 0, 174000], + 1: [38, 170000, 182000], + 2: [50, 178000, 190000], + 3: [63, 186000, 0], + } + fan_policy_b2f = { + 0: [32, 0, 140000], + 1: [38, 135000, 150000], + 2: [50, 145000, 160000], + 3: [69, 15500, 0], + } + + thermal = ThermalUtil() + fan = FanUtil() + get_temp = thermal.get_thermal_temp() + # 1. Get each fan status, one not presented, set speed to full + # Get fan direction (Only get the first one since all fan direction are the same) + # Get current fan duty cycle + cur_duty_cycle = fan.get_fan_duty_cycle() + #print "cur_duty_cycle=%d" %cur_duty_cycle + #print "get_temp=%d" %get_temp + + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_status = fan.get_fan_status(x) + if fan_status is None: + #print "fan_status is None" + logging.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', 100, x) + return False + if fan_status is False: + #self._new_perc = FAN_LEV1_SPEED_PERC + #print "fan_%d status=false, set 45 duty_cycle" %x + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', 100, x) + fan.set_fan_duty_cycle(45) + return True + logging.debug('INFO. fan_status is True (fan_num:%d)', x) + + if fan_status is not None and fan_status is not False: + fan_dir=fan.get_fan_dir(1) + for x in range(0, 4): + if cur_duty_cycle == fan_policy_f2b[x][0]: + break + #print "x=%d" %x + #print "fan_dir=%d" %fan_dir + #print "fan_policy_f2b[x][0]=%d" %fan_policy_f2b[x][0] + #print "cur_duty_cycle=%d" %cur_duty_cycle + + if fan_dir == 1: + if x == 4 : + fan.set_fan_duty_cycle(fan_policy_f2b[0][0]) + new_duty_cycle=cur_duty_cycle + # if temp > up_levle, else if temp < down_level + if get_temp > fan_policy_f2b[x][2] and x != 3 : + new_duty_cycle= fan_policy_f2b[x+1][0] + #print "new_duty_cycle= fan_policy_f2b[x+1][0]=%d" %new_duty_cycle + #print "Becasue get_temp > fan_policy_f2b[x][2]=%d" %fan_policy_f2b[x][2] + logging.debug('INFO. THERMAL temp UP, temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy_f2b[x][2], new_duty_cycle) + #else get_temp < fan_policy_f2b[x][1] and x != 0 : + elif get_temp < fan_policy_f2b[x][1] : + new_duty_cycle= fan_policy_f2b[x-1][0] + #print "new_duty_cycle= fan_policy_f2b[x-1][0]=%d" %new_duty_cycle + #print "Becasue get_temp < fan_policy_f2b[x][1]=%d" %fan_policy_f2b[x][1] + logging.debug('INFO. THERMAL temp down, temp %d < %d , new_duty_cycle=%d', get_temp, fan_policy_f2b[x][1], new_duty_cycle) + if new_duty_cycle == cur_duty_cycle : + #print "new_duty_cycle == cur_duty_cycle case, so return True" + return True + else: + if x == 4 : + fan.set_fan_duty_cycle(fan_policy_b2f[0][0]) + new_duty_cycle=cur_duty_cycle + # if temp > up_levle, else if temp < down_level + if get_temp > fan_policy_b2f[x][1] and x != 3 : + new_duty_cycle= fan_policy_b2f[x+1][0] + logging.debug('INFO. THERMAL temp UP, temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy_b2f[x][2], new_duty_cycle) + elif get_temp < fan_policy_b2f[x][0] and x != 0 : + #elif get_temp < fan_policy_b2f[x][0] + new_duty_cycle= fan_policy_b2f[x-1][0] + logging.debug('INFO. THERMAL temp down, temp %d < %d , new_duty_cycle=%d', get_temp, fan_policy_b2f[x][1], new_duty_cycle) + if new_duty_cycle == cur_duty_cycle : + return True + + fan.set_fan_duty_cycle(new_duty_cycle) + #print "set new_duty_cycle=%d" %new_duty_cycle + #print "old_duty_cycle=%d" %cur_duty_cycle + + return True + + + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + monitor = accton_as7716_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(1) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_util.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_util.py new file mode 100755 index 000000000000..ffddfb338506 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_util.py @@ -0,0 +1,616 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +PROJECT_NAME = 'as7716_32xb' +version = '0.0.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':54} + + +led_prefix ='/sys/devices/platform/as7716_32xb_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as7716_32xb_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan4_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_drv_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'thermal': ['10-0048','10-0049', '10-004a'] , + 'psu': ['17-0050','18-0053'], + 'sfp': ['-0050']} +i2c_nodes = { + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable']} + +sfp_map = [1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32] + +mknod =[ +'echo as7716_32xb_cpld1 0x60 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo accton_i2c_cpld 0x62 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo accton_i2c_cpld 0x64 > /sys/bus/i2c/devices/i2c-0/new_device', + +] + +mknod_xb =[ +'echo as7716_32xb_cpld1 0x60 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo accton_i2c_cpld 0x62 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo accton_i2c_cpld 0x64 > /sys/bus/i2c/devices/i2c-0/new_device', +#Thermal +'echo as7716_32xb_thermal 0x48 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as7716_32xb_thermal 0x49 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as7716_32xb_thermal 0x4a > /sys/bus/i2c/devices/i2c-0/new_device', +#Fan +'echo as7716_32xb_fan 0x66 > /sys/bus/i2c/devices/i2c-0/new_device', +# PSU-1 +'echo as7716_32xb_psu1 0x53 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as7716_32xb_psu2 0x50> /sys/bus/i2c/devices/i2c-0/new_device', +# PSU-2 +'echo as7716_32xb_pmbus 0x5b > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as7716_32xb_pmbus 0x58 > /sys/bus/i2c/devices/i2c-0/new_device', +#EERPOM +'echo as7716_32xb_sys 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +] + + + +mknod2 =[ +'echo as7716_32xb_cpld1 0x60 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo accton_i2c_cpld 0x61 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo accton_i2c_cpld 0x62 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', + +# PSU-1 +'echo as7716_32xb_psu1 0x38 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-57/new_device', +'echo as7716_32xb_psu1 0x50 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-57/new_device', + +# PSU-2 +'echo as7716_32xb_psu2 0x3b > /sys/bus/i2c/devices/i2c-58/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-58/new_device', +'echo as7716_32xb_psu2 0x53 > /sys/bus/i2c/devices/i2c-58/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-58/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-61/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-62/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-63/new_device', + +#EERPOM +#'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', +] + +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + + +kos = [ +'depmod -ae', +'modprobe ipmi_msghandler', +'modprobe ipmi_si', +'modprobe ipmi_devintf', +'modprobe i2c_dev', +'modprobe accton_i2c_cpld', +'modprobe accton_as7716_32xb_cpld1', +'modprobe accton_as7716_32xb_fan', +'modprobe accton_as7716_32xb_leds', +'modprobe accton_as7716_32xb_psu', +'modprobe accton_as7716_32xb_oom', +'modprobe accton_as7716_32xb_thermal', +'modprobe accton_as7716_32xb_pmbus', +'modprobe accton_as7716_32xb_sys'] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x76 is exist @ i2c-0 + tmp = "echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x70 > /sys/bus/i2c/devices/i2c-1/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + #order = i2c_order_check() + # if 0x76 is not exist @i2c-0, use reversed bus order + #if order: + # for i in range(0,len(mknod2)): + # #for pca932x need times to built new i2c buses + # if mknod2[i].find('pca954') != -1: + # time.sleep(2) + + # status, output = log_os_system(mknod2[i], 1) + # if status: + # print output + # if FORCE == 0: + # return status + #else: + print "Prepar to create instance.............." + for i in range(0,len(mknod_xb)): + print "Beginn to create instance.............." + status, output = log_os_system(mknod_xb[i], 1) + print "status=%s" %status + print "output=%s" %output + if status: + print output + if FORCE == 0: + return status + #time.sleep (50.0 / 1000.0) + print "Create sfp instance.............." + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo as7716_32xb_oom 0x"+str(sfp_map[i])+ " > /sys/bus/i2c/devices/i2c-0/new_device", 1) + if status: + print output + if FORCE == 0: + return status + #status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/0-000"+str(sfp_map[i])+"/port_name", 1) + #if status: + # print output + # if FORCE == 0: + # return status + return + +def device_uninstall(): + global FORCE + + for i in range(0,len(sfp_map)): + target = "echo 0x"+str(sfp_map[i])+ " > /sys/bus/i2c/devices/i2c-0/delete_device" + print(target) + status, output =log_os_system(target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod_xb + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + print "driver_inserted() == False" + return False + if not device_exist(): + print "not device_exist()" + return False + return True + +def do_install(): + print "Checking system...." + if driver_inserted() == False: + print "No driver, installing.1..." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing..2.." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking systemm...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + print "path= %s" %path + print "i=%d" %i + print "k=%d" %k + print "j= %d" %j + print "sfp_map[k]=%s" %sfp_map[k] + print " buses[i]=%s" %buses[i] + print "nodes[j]=%s" %nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0060", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-0", 0) + print(ret1) + print(ret2) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/fanutil.py new file mode 100755 index 000000000000..ca0f3f9da1e3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/fanutil.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 12/03/2018: Jostar modify for as7726_32 +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_DIR_IDX_OF_MAP = 2 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/54-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/54-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + #val = ((val + 1 ) * 625 +75 ) / 100 + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/thermalutil.py new file mode 100755 index 000000000000..96163f1d63ab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/thermalutil.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# 12/03/2018:Jostar modify for as7726_32x thermal plan +# ------------------------------------------------------------------ + +try: + import os + import time + import logging + import glob + import commands + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + THERMAL_NUM_MAX = 5 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD. LM75 + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75 + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75 + THERMAL_NUM_4_IDX = 4 # 4_ON_MAIN_BROAD. LM75 + THERMAL_NUM_5_IDX = 5 # 5_ON_MAIN_BROAD. LM75 + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + #_thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['55', '48'], + THERMAL_NUM_2_IDX: ['55', '49'], + THERMAL_NUM_3_IDX: ['55', '4a'], + THERMAL_NUM_4_IDX: ['55', '4b'], + THERMAL_NUM_5_IDX: ['54', '4c'], + } + thermal_sysfspath ={ + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/55-0048/hwmon/hwmon4/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/55-0049/hwmon/hwmon5/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/55-004a/hwmon/hwmon6/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/55-004b/hwmon/hwmon7/temp1_input"], + THERMAL_NUM_5_IDX: ["/sys/bus/i2c/devices/54-004c/hwmon/hwmon3/temp1_input"], + } + + #def __init__(self): + def _get_thermal_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + if(os.path.isfile(device_path)): + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + return int(content) + + else: + print "No such device_path=%s"%device_path + return 0 + + def get_num_thermals(self): + return self.THERMAL_NUM_MAX + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self.thermal_sysfspath) + + def get_thermal_to_device_path(self, thermal_num): + return self.thermal_sysfspath[thermal_num][0] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +def main(): + thermal = ThermalUtil() + print "termal1=%d" %thermal._get_thermal_val(1) + print "termal2=%d" %thermal._get_thermal_val(2) + print "termal3=%d" %thermal._get_thermal_val(3) + print "termal4=%d" %thermal._get_thermal_val(4) + print "termal5=%d" %thermal._get_thermal_val(5) +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/Makefile new file mode 100755 index 000000000000..5b5e6912c56a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/Makefile @@ -0,0 +1,19 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_as7726_32x_cpld.o accton_as7726_32x_fan.o \ + accton_as7726_32x_leds.o accton_as7726_32x_psu.o ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +#$(error KERNEL_SRC is not defined) +KVERSION=3.16.0-6-amd64 +KERNEL_DIR = /usr/src/linux-headers-$(KVERSION)/ +KERNELDIR:=$(KERNEL_DIR) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_cpld.c new file mode 100755 index 000000000000..9ffc3353839c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_cpld.c @@ -0,0 +1,919 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as7726_32x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as7726_32x_cpld1, + as7726_32x_cpld2, + as7726_32x_cpld3 +}; + +struct as7726_32x_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as7726_32x_cpld_id[] = { + { "as7726_32x_cpld1", as7726_32x_cpld1 }, + { "as7726_32x_cpld2", as7726_32x_cpld2 }, + { "as7726_32x_cpld3", as7726_32x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as7726_32x_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index +//#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index + +enum as7726_32x_cpld1_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RESET_ATTR_ID(1), + TRANSCEIVER_RESET_ATTR_ID(2), + TRANSCEIVER_RESET_ATTR_ID(3), + TRANSCEIVER_RESET_ATTR_ID(4), + TRANSCEIVER_RESET_ATTR_ID(5), + TRANSCEIVER_RESET_ATTR_ID(6), + TRANSCEIVER_RESET_ATTR_ID(7), + TRANSCEIVER_RESET_ATTR_ID(8), + TRANSCEIVER_RESET_ATTR_ID(9), + TRANSCEIVER_RESET_ATTR_ID(10), + TRANSCEIVER_RESET_ATTR_ID(11), + TRANSCEIVER_RESET_ATTR_ID(12), + TRANSCEIVER_RESET_ATTR_ID(13), + TRANSCEIVER_RESET_ATTR_ID(14), + TRANSCEIVER_RESET_ATTR_ID(15), + TRANSCEIVER_RESET_ATTR_ID(16), + TRANSCEIVER_RESET_ATTR_ID(17), + TRANSCEIVER_RESET_ATTR_ID(18), + TRANSCEIVER_RESET_ATTR_ID(19), + TRANSCEIVER_RESET_ATTR_ID(20), + TRANSCEIVER_RESET_ATTR_ID(21), + TRANSCEIVER_RESET_ATTR_ID(22), + TRANSCEIVER_RESET_ATTR_ID(23), + TRANSCEIVER_RESET_ATTR_ID(24), + TRANSCEIVER_RESET_ATTR_ID(25), + TRANSCEIVER_RESET_ATTR_ID(26), + TRANSCEIVER_RESET_ATTR_ID(27), + TRANSCEIVER_RESET_ATTR_ID(28), + TRANSCEIVER_RESET_ATTR_ID(29), + TRANSCEIVER_RESET_ATTR_ID(30), + TRANSCEIVER_RESET_ATTR_ID(31), + TRANSCEIVER_RESET_ATTR_ID(32) +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as7726_32x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as7726_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + + +#define DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO|S_IWUSR, show_status, set_reset, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); + + +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr + + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(32); + +static struct attribute *as7726_32x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_TRANSCEIVER_RESET_ATTR(1), + DECLARE_TRANSCEIVER_RESET_ATTR(2), + DECLARE_TRANSCEIVER_RESET_ATTR(3), + DECLARE_TRANSCEIVER_RESET_ATTR(4), + DECLARE_TRANSCEIVER_RESET_ATTR(5), + DECLARE_TRANSCEIVER_RESET_ATTR(6), + DECLARE_TRANSCEIVER_RESET_ATTR(7), + DECLARE_TRANSCEIVER_RESET_ATTR(8), + DECLARE_TRANSCEIVER_RESET_ATTR(9), + DECLARE_TRANSCEIVER_RESET_ATTR(10), + DECLARE_TRANSCEIVER_RESET_ATTR(11), + DECLARE_TRANSCEIVER_RESET_ATTR(12), + DECLARE_TRANSCEIVER_RESET_ATTR(13), + DECLARE_TRANSCEIVER_RESET_ATTR(14), + DECLARE_TRANSCEIVER_RESET_ATTR(15), + DECLARE_TRANSCEIVER_RESET_ATTR(16), + DECLARE_TRANSCEIVER_RESET_ATTR(17), + DECLARE_TRANSCEIVER_RESET_ATTR(18), + DECLARE_TRANSCEIVER_RESET_ATTR(19), + DECLARE_TRANSCEIVER_RESET_ATTR(20), + DECLARE_TRANSCEIVER_RESET_ATTR(21), + DECLARE_TRANSCEIVER_RESET_ATTR(22), + DECLARE_TRANSCEIVER_RESET_ATTR(23), + DECLARE_TRANSCEIVER_RESET_ATTR(24), + DECLARE_TRANSCEIVER_RESET_ATTR(25), + DECLARE_TRANSCEIVER_RESET_ATTR(26), + DECLARE_TRANSCEIVER_RESET_ATTR(27), + DECLARE_TRANSCEIVER_RESET_ATTR(28), + DECLARE_TRANSCEIVER_RESET_ATTR(29), + DECLARE_TRANSCEIVER_RESET_ATTR(30), + DECLARE_TRANSCEIVER_RESET_ATTR(31), + DECLARE_TRANSCEIVER_RESET_ATTR(32), + NULL +}; + +static const struct attribute_group as7726_32x_cpld1_group = { + .attrs = as7726_32x_cpld1_attributes, +}; + +static struct attribute *as7726_32x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as7726_32x_cpld2_group = { + .attrs = as7726_32x_cpld2_attributes, +}; + +static struct attribute *as7726_32x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as7726_32x_cpld3_group = { + .attrs = as7726_32x_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[5] = {0}; + u8 regs[] = {0x30, 0x31, 0x32, 0x33, 0x50}; + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7726_32x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + values[4] &= 0x3; + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3], values[4]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + u8 value=0; + u8 reg = 0x50; + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + status = as7726_32x_cpld_read_internal(client, reg); + + if (status < 0) + goto exit; + + value = (u8)status; + value &= 0x0C; + value = value >> 2; + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 34 in order */ + return sprintf(buf, "00 00 00 00 %.2x\n", value); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x30; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x31; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x32; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x33; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33: + reg = 0x50; + mask = 0x1; + break; + case MODULE_PRESENT_34: + reg = 0x50; + mask = 0x2; + break; + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x4; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x5; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + case MODULE_RXLOS_33: + reg = 0x50; + mask = 0x4; + break; + case MODULE_RXLOS_34: + reg = 0x50; + mask = 0x8; + break; + case MODULE_TXDISABLE_33: + reg = 0x49; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x49; + mask = 0x2; + break; + + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_34) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as7726_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_33: + reg = 0x49; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x49; + mask = 0x2; + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7726_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as7726_32x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &reset); + if (status) { + return status; + } + + switch (attr->index) + { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x4; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x5; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7726_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (!reset) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as7726_32x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as7726_32x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as7726_32x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as7726_32x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as7726_32x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as7726_32x_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as7726_32x_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) { + case as7726_32x_cpld1: + group = &as7726_32x_cpld1_group; + break; + case as7726_32x_cpld2: + group = &as7726_32x_cpld2_group; + break; + case as7726_32x_cpld3: + group = &as7726_32x_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as7726_32x_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as7726_32x_cpld_remove(struct i2c_client *client) +{ + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as7726_32x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as7726_32x_cpld1: + group = &as7726_32x_cpld1_group; + break; + case as7726_32x_cpld2: + group = &as7726_32x_cpld2_group; + break; + case as7726_32x_cpld3: + group = &as7726_32x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as7726_32x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as7726_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as7726_32x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7726_32x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7726_32x_cpld_read); + +int as7726_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7726_32x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7726_32x_cpld_write); + +static struct i2c_driver as7726_32x_cpld_driver = { + .driver = { + .name = "as7726_32x_cpld", + .owner = THIS_MODULE, + }, + .probe = as7726_32x_cpld_probe, + .remove = as7726_32x_cpld_remove, + .id_table = as7726_32x_cpld_id, +}; + +static int __init as7726_32x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7726_32x_cpld_driver); +} + +static void __exit as7726_32x_cpld_exit(void) +{ + i2c_del_driver(&as7726_32x_cpld_driver); +} + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as7726_32x_cpld_init); +module_exit(as7726_32x_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_fan.c new file mode 100755 index 000000000000..beb58804ac94 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_fan.c @@ -0,0 +1,763 @@ +/* + * A hwmon driver for the Accton as7726 32x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7726_32x_fan" + +#define NUM_THERMAL_SENSORS (5) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a, 0x4b, 0x4c} + +#define IN +#define OUT + +static struct as7726_32x_fan_data *as7726_32x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7726_32x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) + +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ + static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); + +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); +/* System temperature for fancontrol */ +DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR(); + +static struct attribute *as7726_32x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + DECLARE_FAN_SYSTEM_TEMP_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7726_32x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7726_32x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as7726_32x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as7726_32x_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as7726_32x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +/* Due to this struct is declared at lm75.c, it cannot be include + * under Sonic environment. I duplicate it from lm75.c. + */ +struct lm75_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct thermal_zone_device *tz; + struct mutex update_lock; + u8 orig_conf; + u8 resolution; /* In bits, between 9 and 12 */ + u8 resolution_limits; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long sample_time; /* In jiffies */ + s16 temp[3]; /* Register values, + 0 = input + 1 = max + 2 = hyst */ +}; + +/*Copied from lm75.c*/ +static inline long lm75_reg_to_mc(s16 temp, u8 resolution) +{ + return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); +} + +/*Get hwmon_dev from i2c_client, set hwmon_dev = NULL is failed.*/ +static struct device * get_hwmon_dev( + struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if(data) + { + if( data->valid == 1 && data->hwmon_dev) + { + return data->hwmon_dev; + } + + } + return NULL; +} + +/* To find hwmon index by opening hwmon under that i2c address. + */ +static int find_hwmon_index_by_FileOpen( + int bus_nr, + unsigned short addr, + OUT int *index) +{ +#define MAX_HWMON_DEVICE (10) /* Find hwmon device in 0~10*/ + struct file *sfd; + char client_name[96]; + int i=0; + + do { + snprintf(client_name, sizeof(client_name), + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + + sfd = filp_open(client_name, O_RDONLY, 0); + i++; + } while( IS_ERR(sfd) && i < MAX_HWMON_DEVICE); + + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", client_name, __LINE__); + return -ENOENT; + } + filp_close(sfd, 0); + *index = i - 1; + return 0; + +#undef MAX_HWMON_DEVICE +} + +static int get_temp_file_path( + int bus_nr, unsigned short addr, + struct device *hwmon_dev + ,char *path, int max_len) +{ + + if(hwmon_dev && strlen(dev_name(hwmon_dev))) + { + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/%s/temp1_input", + bus_nr, addr, dev_name(hwmon_dev)); + } + else + { + int i=0; + if(find_hwmon_index_by_FileOpen( bus_nr, addr, &i)) + { + return -EIO; + } + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + } + + return 0; +} + +/*File read the dev file at user space.*/ +static int read_devfile_temp1_input( + struct device *dev, + int bus_nr, + unsigned short addr, + struct device *hwmon_dev, + int *miniCelsius) +{ + struct file *sfd; + char buffer[96]; + char devfile[96]; + int rc, status; + int rdlen, value; + mm_segment_t old_fs; + + rc = 0; + get_temp_file_path(bus_nr, addr, hwmon_dev, devfile, sizeof(devfile)); + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", devfile, __LINE__); + return -ENOENT; + } + dev_dbg(dev, "Found device:%s\n",devfile); + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + pr_err("file %s cann't readable ?\n",devfile); + return -ENOENT; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + pr_err( "File(%s) empty!\n", devfile); + rc = -EIO; + goto exit; + } + status = sscanf(buffer, "%d", &value); + if (status != 1) { + rc = -EIO; + goto exit; + } + *miniCelsius = value; + dev_dbg(dev,"found sensors: %d @i2c %d-%04x\n", value, bus_nr, addr); + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + return rc; +} + +static u8 is_lm75_data_due(struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if (time_after(jiffies, data->last_updated + data->sample_time)) + { + return 1; + } + return 0; +} +static int get_lm75_temp(struct i2c_client *client, int *miniCelsius) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + *miniCelsius = lm75_reg_to_mc(data->temp[0], data->resolution); + + return 0; +} + +static bool lm75_addr_mached(unsigned short addr) +{ + int i; + unsigned short addrs[] = THERMAL_SENSORS_ADDRS; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) + { + if( addr == addrs[i]) + return 1; + } + return 0; +} + +static int _find_lm75_device(struct device *dev, void *data) +{ + struct device_driver *driver; + struct as7726_32x_fan_data *prv = data; + char *driver_name = THERMAL_SENSORS_DRIVER; + + driver = dev->driver; + if (driver && driver->name && + strcmp(driver->name, driver_name) == 0) + { + struct i2c_client *client; + client = to_i2c_client(dev); + if (client) + { + /*cannot use "struct i2c_adapter *adap = to_i2c_adapter(dev);"*/ + struct i2c_adapter *adap = client->adapter; + int miniCelsius = 0; + + if (! lm75_addr_mached(client->addr)) + { + return 0; + } + + if (!adap) { + return -ENXIO; + } + + /* If the data is not updated, read them from devfile + to drive them updateing data from chip.*/ + if (is_lm75_data_due(client)) + { + struct device *hwmon_dev; + + hwmon_dev = get_hwmon_dev(client); + if(0 == read_devfile_temp1_input(dev, adap->nr, + client->addr, hwmon_dev, &miniCelsius)) + { + prv->system_temp += miniCelsius; + prv->sensors_found++; + } + + } + else + { + get_lm75_temp(client, &miniCelsius); + prv->system_temp += miniCelsius; + prv->sensors_found++; + + } + } + } + return 0; +} + +/*Find all lm75 devices and return sum of temperatures.*/ +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + ssize_t ret = 0; + struct as7726_32x_fan_data *data = as7726_32x_fan_update_device(dev); + + data->system_temp=0; + data->sensors_found=0; + i2c_for_each_dev(data, _find_lm75_device); + if (NUM_THERMAL_SENSORS != data->sensors_found) + { + dev_dbg(dev,"only %d of %d temps are found\n", + data->sensors_found, NUM_THERMAL_SENSORS); + data->system_temp = INT_MAX; + } + ret = sprintf(buf, "%d\n",data->system_temp); + return ret; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7726_32x_fan_data *data = as7726_32x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7726_32x_fan_group = { + .attrs = as7726_32x_fan_attributes, +}; + +static struct as7726_32x_fan_data *as7726_32x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7726_32x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7726_32x_fan_read_value(client, fan_reg[i]); + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7726_32x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7726_32x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7726_32x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7726_32x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7726_32x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7726_32x_fan_remove(struct i2c_client *client) +{ + struct as7726_32x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7726_32x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7726_32x_fan_id[] = { + { "as7726_32x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7726_32x_fan_id); + +static struct i2c_driver as7726_32x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7726_32x_fan_probe, + .remove = as7726_32x_fan_remove, + .id_table = as7726_32x_fan_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(as7726_32x_fan_driver); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("as7726_32x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_leds.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_leds.c new file mode 100755 index 000000000000..65b962e628cc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_leds.c @@ -0,0 +1,438 @@ +/* + * A LED driver for the accton_as7726_32x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as7726_32x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as7726_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "accton_as7726_32x_led" + +struct accton_as7726_32x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct accton_as7726_32x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as7726_32x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as7726_32x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7726_32x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = accton_as7726_32x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as7726_32x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as7726_32x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7726_32x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as7726_32x_led_diag_get(struct led_classdev *cdev) +{ + accton_as7726_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as7726_32x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7726_32x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_as7726_32x_led_loc_get(struct led_classdev *cdev) +{ + accton_as7726_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_as7726_32x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_as7726_32x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev accton_as7726_32x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_as7726_32x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as7726_32x_led_diag_set, + .brightness_get = accton_as7726_32x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "accton_as7726_32x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as7726_32x_led_loc_set, + .brightness_get = accton_as7726_32x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "accton_as7726_32x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as7726_32x_led_auto_set, + .brightness_get = accton_as7726_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "accton_as7726_32x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as7726_32x_led_auto_set, + .brightness_get = accton_as7726_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as7726_32x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as7726_32x_led_auto_set, + .brightness_get = accton_as7726_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as7726_32x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7726_32x_leds); i++) { + led_classdev_suspend(&accton_as7726_32x_leds[i]); + } + + return 0; +} + +static int accton_as7726_32x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7726_32x_leds); i++) { + led_classdev_resume(&accton_as7726_32x_leds[i]); + } + + return 0; +} + +static int accton_as7726_32x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as7726_32x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as7726_32x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as7726_32x_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as7726_32x_leds[i]); + } + } + + return ret; +} + +static int accton_as7726_32x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as7726_32x_leds); i++) { + led_classdev_unregister(&accton_as7726_32x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as7726_32x_led_driver = { + .probe = accton_as7726_32x_led_probe, + .remove = accton_as7726_32x_led_remove, + .suspend = accton_as7726_32x_led_suspend, + .resume = accton_as7726_32x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as7726_32x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as7726_32x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as7726_32x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as7726_32x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as7726_32x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as7726_32x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as7726_32x_led_driver); + kfree(ledctl); +} + +module_init(accton_as7726_32x_led_init); +module_exit(accton_as7726_32x_led_exit); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("accton_as7726_32x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_psu.c new file mode 100755 index 000000000000..f4da01e86d9b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_psu.c @@ -0,0 +1,276 @@ +/* + * An hwmon driver for accton as7726_32x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as7726_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7726_32x_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7726_32x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[9]; /* Model name, read from eeprom */ +}; + +static struct as7726_32x_psu_data *as7726_32x_psu_update_device(struct device *dev); + +enum as7726_32x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as7726_32x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7726_32x_psu_data *data = as7726_32x_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7726_32x_psu_data *data = as7726_32x_psu_update_device(dev); + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as7726_32x_psu_group = { + .attrs = as7726_32x_psu_attributes, +}; + +static int as7726_32x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7726_32x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7726_32x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7726_32x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7726_32x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7726_32x_psu_remove(struct i2c_client *client) +{ + struct as7726_32x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7726_32x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7726_32x_psu1, + as7726_32x_psu2 +}; + +static const struct i2c_device_id as7726_32x_psu_id[] = { + { "as7726_32x_psu1", as7726_32x_psu1 }, + { "as7726_32x_psu2", as7726_32x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7726_32x_psu_id); + +static struct i2c_driver as7726_32x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7726_32x_psu", + }, + .probe = as7726_32x_psu_probe, + .remove = as7726_32x_psu_remove, + .id_table = as7726_32x_psu_id, + .address_list = normal_i2c, +}; + +static int as7726_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as7726_32x_psu_data *as7726_32x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as7726_32x update\n"); + + /* Read psu status */ + status = as7726_32x_cpld_read(0x60, 0x2); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as7726_32x_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as7726_32x_psu_driver); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("as7726_32x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/ym2651y.c new file mode 100755 index 000000000000..8e76c56b54fc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/ym2651y.c @@ -0,0 +1,603 @@ +/* + * An hwmon driver for the 3Y Power YM-2651Y Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct ym2651y_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 capability; /* Register value */ + u16 status_word; /* Register value */ + u8 fan_fault; /* Register value */ + u8 over_temp; /* Register value */ + u16 v_out; /* Register value */ + u16 i_out; /* Register value */ + u16 p_out; /* Register value */ + u16 temp; /* Register value */ + u16 fan_speed; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u8 fan_dir[4]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[10]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u16 mfr_vin_min; /* Register value */ + u16 mfr_vin_max; /* Register value */ + u16 mfr_iin_max; /* Register value */ + u16 mfr_iout_max; /* Register value */ + u16 mfr_pin_max; /* Register value */ + u16 mfr_pout_max; /* Register value */ + u16 mfr_vout_min; /* Register value */ + u16 mfr_vout_max; /* Register value */ +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static struct ym2651y_data *ym2651y_update_device(struct device *dev); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value); + +enum ym2651y_sysfs_attributes { + PSU_POWER_ON = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD, + PSU_FAN1_FAULT, + PSU_FAN_DIRECTION, + PSU_OVER_TEMP, + PSU_V_OUT, + PSU_I_OUT, + PSU_P_OUT, + PSU_P_OUT_UV, /*In Unit of microVolt, instead of mini.*/ + PSU_TEMP1_INPUT, + PSU_FAN1_SPEED, + PSU_FAN1_DUTY_CYCLE, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_VIN_MIN, + PSU_MFR_VIN_MAX, + PSU_MFR_VOUT_MIN, + PSU_MFR_VOUT_MAX, + PSU_MFR_IIN_MAX, + PSU_MFR_IOUT_MAX, + PSU_MFR_PIN_MAX, + PSU_MFR_POUT_MAX +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision, S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); + +static struct attribute *ym2651y_attributes[] = { + &sensor_dev_attr_psu_power_on.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_over_temp.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_temp1_fault.dev_attr.attr, + NULL +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u16 status = 0; + + switch (attr->index) { + case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */ + status = (data->status_word & 0x40) ? 0 : 1; + break; + case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */ + status = (data->status_word & 0x4) >> 2; + break; + case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */ + status = (data->status_word & 0x800) ? 0 : 1; + break; + } + + return sprintf(buf, "%d\n", status); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_OUT: + value = data->v_out; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_OUT_UV: + multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/ + /*Passing through*/ + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp; + break; + case PSU_FAN1_SPEED: + value = data->fan_speed; + multiplier = 1; + break; + case PSU_FAN1_DUTY_CYCLE: + value = data->fan_duty_cycle[0]; + multiplier = 1; + break; + case PSU_MFR_VIN_MIN: + value = data->mfr_vin_min; + break; + case PSU_MFR_VIN_MAX: + value = data->mfr_vin_max; + break; + case PSU_MFR_VOUT_MIN: + value = data->mfr_vout_min; + break; + case PSU_MFR_VOUT_MAX: + value = data->mfr_vout_max; + break; + case PSU_MFR_PIN_MAX: + value = data->mfr_pin_max; + break; + case PSU_MFR_POUT_MAX: + value = data->mfr_pout_max; + break; + case PSU_MFR_IOUT_MAX: + value = data->mfr_iout_max; + break; + case PSU_MFR_IIN_MAX: + value = data->mfr_iin_max; + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct ym2651y_data *data = ym2651y_update_device(dev); + + return sprintf(buf, "%d\n", data->over_temp >> 7); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u8 *ptr = NULL; + + switch (attr->index) { + case PSU_FAN_DIRECTION: /* psu_fan_dir */ + ptr = data->fan_dir; + break; + case PSU_MFR_ID: /* psu_mfr_id */ + ptr = data->mfr_id; + break; + case PSU_MFR_MODEL: /* psu_mfr_model */ + ptr = data->mfr_model; + break; + case PSU_MFR_REVISION: /* psu_mfr_revision */ + ptr = data->mfr_revsion; + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group ym2651y_group = { + .attrs = ym2651y_attributes, +}; + +static int ym2651y_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct ym2651y_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &ym2651y_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int ym2651y_remove(struct i2c_client *client) +{ + struct ym2651y_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id ym2651y_id[] = { + { "ym2651", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ym2651y_id); + +static struct i2c_driver ym2651y_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ym2651", + }, + .probe = ym2651y_probe, + .remove = ym2651y_remove, + .id_table = ym2651y_id, + .address_list = normal_i2c, +}; + +static int ym2651y_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int ym2651y_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct ym2651y_data *ym2651y_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + u8 command; + u8 fan_dir[5] = {0}; + struct reg_data_byte regs_byte[] = { {0x19, &data->capability}, + {0x7d, &data->over_temp}, + {0x81, &data->fan_fault}, + {0x98, &data->pmbus_revision}}; + struct reg_data_word regs_word[] = { {0x79, &data->status_word}, + {0x8b, &data->v_out}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x8d, &data->temp}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &data->fan_speed}, + {0xa0, &data->mfr_vin_min}, + {0xa1, &data->mfr_vin_max}, + {0xa2, &data->mfr_iin_max}, + {0xa3, &data->mfr_pin_max}, + {0xa4, &data->mfr_vout_min}, + {0xa5, &data->mfr_vout_max}, + {0xa6, &data->mfr_iout_max}, + {0xa7, &data->mfr_pout_max}}; + + dev_dbg(&client->dev, "Starting ym2651 update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = ym2651y_read_byte(client, regs_byte[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = ym2651y_read_word(client, regs_word[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + } + + /* Read fan_direction */ + command = 0xC3; + status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + } + + strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1); + data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0'; + + /* Read mfr_id */ + command = 0x99; + status = ym2651y_read_block(client, command, data->mfr_id, + ARRAY_SIZE(data->mfr_id)-1); + data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_model */ + command = 0x9a; + status = ym2651y_read_block(client, command, data->mfr_model, + ARRAY_SIZE(data->mfr_model)-1); + data->mfr_model[ARRAY_SIZE(data->mfr_model)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_revsion */ + command = 0x9b; + status = ym2651y_read_block(client, command, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)-1); + data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(ym2651y_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("3Y Power YM-2651Y driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-handle_mac.service b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-handle_mac.service new file mode 100755 index 000000000000..d29342a56fe1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-handle_mac.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS7726-32X Platform MAC hnadle service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_handle_idt.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-fan.service new file mode 100755 index 000000000000..e18d592d6c19 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-fan.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS7726-32X Platform Monitoring FAN service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as7726_32x_monitor_fan.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-psu.service new file mode 100755 index 000000000000..99f7479494e0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-psu.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS7726-32X Platform Monitoring PSU service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as7726_32x_monitor_psu.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor.service new file mode 100755 index 000000000000..5b04ad410101 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor.service @@ -0,0 +1,18 @@ +[Unit] +Description=Accton AS7726-32X Platform Monitoring service +Before=pmon.service +After=as7726-32x-platform-handle_mac.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7726_32x_util.py install +ExecStart=/usr/local/bin/accton_as7726_32x_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL +#StandardOutput=tty + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/setup.py new file mode 100755 index 000000000000..9841874dbd1e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7726_32x', + version='1.0', + description='Module to initialize Accton AS7726-32X platforms', + + packages=['as7726_32x'], + package_dir={'as7726_32x': 'as7726-32x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/README new file mode 100755 index 000000000000..44e03cab5f52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program is free software: you can redistribute it and/or modify +It under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as5712_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as5712-fan-psu-cpld.patch + for as5712's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS5712-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as5712 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS5712-54X.patch" from patch/installer. + - Change setting for AS5712-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS5712-54X.patch" + !!NOTICE, patching onie_installer-accton-AS5712-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5712-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as5712-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as5712_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS5712-54X.patch. + It's done by patching onie_installer-accton-AS5712-54X.patch at build-image. + Run "accton_as5712_util.py install" to install drivers. + +To initialize the system, run "accton_as5712_util.py install". +To clean up the drivers & devices, run "accton_as5712_util.py clean". +To dump information of sensors, run "accton_as5712_util.py show". +To dump SFP EEPROM, run "accton_as5712_util.py sff". +To set fan speed, run "accton_as5712_util.py set fan". +To enable/disable SFP emission, run "accton_as5712_util.py set sfp". +To set system LEDs' color, run "accton_as5712_util.py set led" +For more information, run "accton_as5712_util.py --help". + +==================================================================== +Besides applying accton_as5712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor.py new file mode 100755 index 000000000000..b88b440c9032 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor.py @@ -0,0 +1,345 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.)# +# 4/20/2018: Jostar modify for as7726_32x +# 12/03/2018:Jostar modify for as7726_32x thermal plan +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + from as7726_32x.fanutil import FanUtil + from as7726_32x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as7726_32x_monitor' + +global log_file +global log_level + + +# Air Flow Front to Back : +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=38C : Keep 37.5%(0x04) Fan speed +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 38C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 46C : Change Fan speed from 62.5%(0x08) to 100%(0x0E) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 58C : Send alarm message +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 66C : Shut down system +# One Fan fail : Change Fan speed to 100%(0x0E) + + +# Air Flow Back to Front : +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=34C : Keep 37.5%(0x04) Fan speed +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 34C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 44C : Change Fan speed from 62.5%(0x08) to 100%(0x0E) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 59C : Send alarm message +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 67C : Shut down system +# One Fan fail: Change Fan speed to 100%(0x0E) +# sensor_LM75_CPU == sensor_LM75_4B + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_policy_state=1 +fan_fail=0 +alarm_state = 0 #0->default or clear, 1-->alarm detect +test_temp = 0 +test_temp_list = [0, 0, 0, 0, 0, 0] +temp_test_data=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + # static temp var + temp = 0 + new_pwm = 0 + pwm=0 + ori_pwm = 0 + default_pwm=0x4 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setLevel(logging.WARNING) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def get_state_from_fan_policy(self, temp, policy): + state=0 + + logging.debug('temp=%d', temp) + for i in range(0, len(policy)): + #logging.debug('policy[%d][0]=%d, policy[%d][1]=%d, policy[%d][2]=%d', i,policy[i][0],i, policy[i][1], i, policy[i][2]) + if temp > policy[i][2]: + if temp <= policy[i][3]: + state =i + logging.debug ('temp=%d >= policy[%d][2]=%d, temp=%d < policy[%d][3]=%d' , temp, i, policy[i][2], temp, i, policy[i][3]) + logging.debug ('fan_state=%d', state) + break + + return state + + + def manage_fans(self): + + global fan_policy_state + global fan_fail + global test_temp + global test_temp_list + global alarm_state + global temp_test_data + + LEVEL_FAN_DEF=0 + LEVEL_FAN_MID=1 + LEVEL_FAN_MAX=2 + LEVEL_TEMP_HIGH=3 + LEVEL_TEMP_CRITICAL=4 + + + fan_policy_f2b = { + LEVEL_FAN_DEF: [38, 0x4, 0, 38000], + LEVEL_FAN_MID: [63, 0x6, 38000, 46000], + LEVEL_FAN_MAX: [100, 0xE, 46000, 58000], + LEVEL_TEMP_HIGH: [100, 0xE, 58000, 66000], + LEVEL_TEMP_CRITICAL: [100, 0xE, 58000, 200000], + } + fan_policy_b2f = { + LEVEL_FAN_DEF: [38, 0x4, 0, 34000], + LEVEL_FAN_MID: [63, 0x8, 34000, 44000], + LEVEL_FAN_MAX: [100, 0xE, 44000, 59000], + LEVEL_TEMP_HIGH: [100, 0xE, 59000, 67000], + LEVEL_TEMP_CRITICAL: [100, 0xE, 59000, 200000], + } + + fan_policy = fan_policy_f2b + + thermal = ThermalUtil() + fan = FanUtil() + fan_dir=fan.get_fan_dir(1) + if fan_dir == 1: + fan_dri=1 #something wrong, set fan_dir to default val + else: + fan_policy = fan_policy_b2f + + ori_pwm=fan.get_fan_duty_cycle() + new_pwm=0 + logging.debug('fan_dir=%d, ori_pwm=%d', fan_dir, ori_pwm) + logging.debug('test_temp=%d', test_temp) + if test_temp==0: + temp1 = thermal._get_thermal_val(1) + temp2 = thermal._get_thermal_val(2) + temp3 = thermal._get_thermal_val(3) + temp4 = thermal._get_thermal_val(4) + temp5 = thermal._get_thermal_val(5) + else: + temp1 = test_temp_list[0] + temp2 = test_temp_list[1] + temp3 = test_temp_list[2] + temp4 = test_temp_list[3] + temp5 = test_temp_list[4] + fan_fail=0 + + if temp3==0: + temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% + logging.debug('lm75_49 detect fail, so set temp_get=50000, let fan to 75%') + elif temp4==0: + temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% + logging.debug('lm75_4b detect fail, so set temp_get=50000, let fan to 75%') + else: + temp_get= (temp3 + temp4)/2 # Use (sensor_LM75_4a + sensor_LM75_4b) /2 + ori_state=fan_policy_state + + #temp_test_data=temp_test_data+1000 + #temp_get = temp_get + temp_test_data + #print "Unit test:temp_get=%d"%temp_get + + fan_policy_state=self.get_state_from_fan_policy(temp_get, fan_policy) + #print "temp3=%d"%temp3 + #print "temp4=%d"%temp4 + #print "temp_get=%d"%temp_get + + logging.debug('lm75_48=%d, lm75_49=%d, lm75_4a=%d, lm_4b=%d, lm_4b=%d', temp1,temp2,temp3,temp4,temp5) + logging.debug('ori_state=%d, fan_policy_state=%d', ori_state, fan_policy_state) + new_pwm = fan_policy[fan_policy_state][0] + if fan_fail==0: + logging.debug('new_fan_cycle=%d', new_pwm) + + if fan_fail==0: + if new_pwm!=ori_pwm: + fan.set_fan_duty_cycle(new_pwm) + logging.info('Set fan speed from %d to %d', ori_pwm, new_pwm) + + #Check Fan status + for i in range (fan.FAN_NUM_1_IDX, fan.FAN_NUM_ON_MAIN_BROAD+1): + if fan.get_fan_status(i)==0: + new_pwm=100 + logging.debug('fan_%d fail, set pwm to 100',i) + if test_temp==0: + fan_fail=1 + fan.set_fan_duty_cycle(new_pwm) + break + else: + fan_fail=0 + + #if fan_policy_state == ori_state: + # return True + #else: + new_state = fan_policy_state + + #logging.warning('Temperature high alarm testing') + if ori_state==LEVEL_FAN_DEF: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected, reboot DUT') + time.sleep(2) + os.system('reboot') + if ori_state==LEVEL_FAN_MID: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if ori_state==LEVEL_FAN_MAX: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if alarm_state==1: + if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if ori_state==LEVEL_TEMP_HIGH: + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if new_state <= LEVEL_FAN_MID: + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if new_state <= LEVEL_FAN_MAX: + if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if ori_state==LEVEL_TEMP_CRITICAL: + if new_state <= LEVEL_FAN_MAX: + logging.warning('Alarm for temperature critical is cleared') + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + global test_temp + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdlt:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + if sys.argv[1]== '-t': + if len(sys.argv)!=7: + print "temp test, need input six temp" + return 0 + + i=0 + for x in range(2, 7): + test_temp_list[i]= int(sys.argv[x])*1000 + i=i+1 + test_temp = 1 + log_level = logging.DEBUG + print test_temp_list + + fan = FanUtil() + fan.set_fan_duty_cycle(38) + print "set default fan speed to 37.5%" + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(5) + +if __name__ == '__main__': + main(sys.argv[1:]) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_fan.py new file mode 100755 index 000000000000..de737b99f1f3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_fan.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 7/2/2018: Jostar create for as7326-56x +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as7726_32x_monitor_fan' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_state=[2, 2, 2, 2, 2, 2, 2] #init state=2, insert=1, remove=0 +fan_status_state=[2, 2, 2, 2, 2, 2, 2] #init state=2, fault=1, normal=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.fan_num = 6 + self.fan_path = "/sys/bus/i2c/devices/54-0066/" + self.present = { + 0: "fan1_present", + 1: "fan2_present", + 2: "fan3_present", + 3: "fan4_present", + 4: "fan5_present", + 5: "fan6_present", + } + + self.fault = { + 0: "fan1_fault", + 1: "fan2_fault", + 2: "fan3_fault", + 3: "fan4_fault", + 4: "fan5_fault", + 5: "fan6_fault", + } + + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fan(self): + + FAN_STATE_REMOVE = 0 + FAN_STATE_INSERT = 1 + + FAN_STATUS_FAULT = 1 + FAN_STATUS_NORMAL = 0 + + global fan_state + global fan_status_state + + for idx in range (0, self.fan_num): + node = self.fan_path + self.present[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_state[idx]!=1: + fan_state[idx]=FAN_STATE_INSERT + logging.info("FAN-%d present is detected", idx+1); + else: + if fan_state[idx]!=0: + fan_state[idx]=FAN_STATE_REMOVE + logging.warning("Alarm for FAN-%d absent is detected", idx+1) + + for idx in range (0, self.fan_num): + node = self.fan_path + self.fault[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_status_state[idx]!=FAN_STATUS_FAULT: + if fan_state[idx] == FAN_STATE_INSERT: + logging.warning("Alarm for FAN-%d failed is detected", idx+1); + fan_status_state[idx]=FAN_STATUS_FAULT + else: + fan_status_state[idx]=FAN_STATUS_NORMAL + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_fan() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_psu.py new file mode 100755 index 000000000000..618c58eec872 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_psu.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 7/2/2018: Jostar create for as7326-56x +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as7726_32x_monitor_psu' + +global log_file +global log_level + + +psu_state=[2, 2] +psu_status_state=[2, 2] +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.psu_num = 2 + self.psu_path = "/sys/bus/i2c/devices/" + self.presence = "/psu_present" + self.oper_status = "/psu_power_good" + self.mapping = { + 0: "50-0053", + 1: "49-0050", + } + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_psu(self): + + PSU_STATE_REMOVE = 0 + PSU_STATE_INSERT = 1 + + PSU_STATUS_NO_POWER = 0 + PSU_STATUS_POWER_GOOD = 1 + PSU_STATUS_IDLE =2 + + global psu_state + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.presence + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if psu_state[idx]!=1: + psu_state[idx]=PSU_STATE_INSERT + logging.info("PSU-%d present is detected", idx+1); + #psu_status_state[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it. + else: + if psu_state[idx]!=0: + psu_state[idx]=PSU_STATE_REMOVE + logging.warning("Alarm for PSU-%d absent is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_IDLE + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.oper_status + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "0": + if psu_status_state[idx]!=PSU_STATUS_NO_POWER: + if psu_state[idx]==PSU_STATE_INSERT: + logging.warning("Alarm for PSU-%d failed is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_NO_POWER + else: + if psu_state[idx]==PSU_STATE_INSERT: + if psu_status_state[idx]!=PSU_STATUS_POWER_GOOD: + logging.info("PSU-%d power_good is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_POWER_GOOD + + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_psu() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_util.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_util.py new file mode 100755 index 000000000000..89643edd621a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_util.py @@ -0,0 +1,572 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +PROJECT_NAME = 'as7726_32x' +version = '0.0.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':54} + + +led_prefix ='/sys/devices/platform/as7716_32x_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as7716_32x_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan4_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['54-0066'], + 'thermal': ['54-004c', '55-0048','55-0049', '55-004a', '55-004b'] , + 'psu': ['49-0050','50-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'], + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_ ', 'module_tx_disable_']} + +sfp_map = [21, 22, 23, 24, 26, 25, 28, 27, + 17, 18, 19, 20, 29, 30, 31, 32, + 33, 34, 35, 36, 45, 46, 47, 48, + 37, 38, 39, 40, 41, 42, 43, 44, + 15, 16] + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device', + +'echo as7726_32x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as7726_32x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as7726_32x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-13/new_device', + +'echo as7726_32x_fan 0x66 > /sys/bus/i2c/devices/i2c-54/new_device', + + +'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-54/new_device', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-55/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-55/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-55/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-55/new_device', + + +# PSU-1 +'echo as7726_32x_psu1 0x53 > /sys/bus/i2c/devices/i2c-50/new_device', +'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-50/new_device', + +# PSU-2 +'echo as7726_32x_psu2 0x50> /sys/bus/i2c/devices/i2c-49/new_device', +'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-49/new_device', + +#EERPOM +'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +] + + + +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + +def cpld_reset_mac(): + ret, lsmod = log_os_system("i2cset -y 0 0x77 0x1", 0) + ret, lsmod = log_os_system("i2cset -y 0 0x76 0x4", 0) + ret, lsmod = log_os_system("i2cset -y 0 0x60 0x8 0x77", 0) + time.sleep(1) + ret, lsmod = log_os_system("i2cset -y 0 0x60 0x8 0xf7", 0) + return True + + + +#'modprobe cpr_4011_4mxx', + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe ym2651y', +'modprobe accton_as7726_32x_cpld', +'modprobe accton_as7726_32x_fan', +'modprobe accton_as7726_32x_leds', +'modprobe accton_as7726_32x_psu', +'modprobe optoe'] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + + #status=cpld_reset_mac() + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + lst = rm.split(" ") + print "lst=%s"%lst + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/0-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + print "not device_exist()" + return False + return True + +def do_install(): + if driver_inserted() == False: + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + print "node=%s"%node + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_handle_idt.sh b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_handle_idt.sh new file mode 100755 index 000000000000..a4c7c745fd11 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_handle_idt.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +if [ -s /usr/local/bin/done_idt_init ];then + echo "There is a done_idt_init file" +else + cat /etc/init.d/opennsl-modules-4.9.0-7-amd64|grep idt_init.sh + if [ $? -ne 0 ];then + echo "Add idt_init.sh to opennsl-modules for TD3 MAC" + sed -i '/modprobe linux-kernel-bde/i sleep 1' /etc/init.d/opennsl-modules-4.9.0-7-amd64 + sed -i '/sleep/i /usr/local/bin/idt_init.sh' /etc/init.d/opennsl-modules-4.9.0-7-amd64 + sed -i '/idt_init/i echo "IDT init" ' /etc/init.d/opennsl-modules-4.9.0-7-amd64 + sed -i '/IDT init/i echo 1 > /usr/local/bin/done_idt_init' /etc/init.d/opennsl-modules-4.9.0-7-amd64 + fi + +fi + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/idt_init.sh b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/idt_init.sh new file mode 100755 index 000000000000..257a0242702f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/idt_init.sh @@ -0,0 +1,152 @@ +#!/bin/bash +test_log=/usr/local/bin/check_idt_status.txt +modprobe i2c-i801 +modprobe i2c-dev +i2cset -y 0 0x77 0x1 +i2cset -y 0 0x76 0x1 +i2cget -y 0 0x54 0 b > /dev/null +if [ $? -ne 0 ];then + printf "Device 8v89307(0x54) not found\n" + exit 1 +fi +echo "IDT 82V89307 " +echo "idt init 1" +# Title = --- IDT 82V89307 Registers --- +#Select to Page 0 +i2cset -y 0 0x54 0x2D 0x00 +i2cset -y 0 0x54 0x7F 0x05 +i2cset -y 0 0x54 0x7E 0x85 +i2cset -y 0 0x54 0x7B 0x00 +i2cset -y 0 0x54 0x7A 0x00 +i2cset -y 0 0x54 0x79 0x40 +i2cset -y 0 0x54 0x78 0x06 +i2cset -y 0 0x54 0x73 0x40 +i2cset -y 0 0x54 0x72 0x40 + +# OUT3:25MHz +i2cset -y 0 0x54 0x71 0x0A +i2cset -y 0 0x54 0x70 0x00 + +# OUT1:1pps +i2cset -y 0 0x54 0x6B 0x4E +i2cset -y 0 0x54 0x69 0x00 +i2cset -y 0 0x54 0x68 0x00 +i2cset -y 0 0x54 0x67 0x19 +i2cset -y 0 0x54 0x66 0xAB +i2cset -y 0 0x54 0x65 0x8C +i2cset -y 0 0x54 0x64 0x00 +i2cset -y 0 0x54 0x63 0x00 +i2cset -y 0 0x54 0x62 0x00 +i2cset -y 0 0x54 0x5F 0x00 +i2cset -y 0 0x54 0x5E 0x00 +i2cset -y 0 0x54 0x5D 0x00 +i2cset -y 0 0x54 0x5C 0x78 +i2cset -y 0 0x54 0x5B 0x02 +i2cset -y 0 0x54 0x5A 0xE5 +i2cset -y 0 0x54 0x59 0x88 +i2cset -y 0 0x54 0x58 0x4B +i2cset -y 0 0x54 0x57 0x6C +i2cset -y 0 0x54 0x56 0x6C + +# Lock to DPLL, output 625MHz +i2cset -y 0 0x54 0x55 0x80 +i2cset -y 0 0x54 0x53 0x00 +i2cset -y 0 0x54 0x52 0x81 +i2cset -y 0 0x54 0x50 0x00 +i2cset -y 0 0x54 0x4F 0x00 +i2cset -y 0 0x54 0x4E 0x00 +i2cset -y 0 0x54 0x4C 0xCB +i2cset -y 0 0x54 0x4A 0x00 +i2cset -y 0 0x54 0x45 0x66 +i2cset -y 0 0x54 0x44 0x66 +i2cset -y 0 0x54 0x42 0x80 +i2cset -y 0 0x54 0x41 0x03 +i2cset -y 0 0x54 0x40 0x01 +i2cset -y 0 0x54 0x3F 0x08 +i2cset -y 0 0x54 0x3E 0x04 +i2cset -y 0 0x54 0x3D 0x20 +i2cset -y 0 0x54 0x3C 0x13 +i2cset -y 0 0x54 0x3B 0x00 +i2cset -y 0 0x54 0x3A 0x98 +i2cset -y 0 0x54 0x39 0x01 +i2cset -y 0 0x54 0x38 0xE6 +i2cset -y 0 0x54 0x37 0x04 +i2cset -y 0 0x54 0x36 0xCE +i2cset -y 0 0x54 0x35 0x7C +i2cset -y 0 0x54 0x34 0x01 +i2cset -y 0 0x54 0x33 0x08 +i2cset -y 0 0x54 0x32 0x08 +i2cset -y 0 0x54 0x31 0x08 +i2cset -y 0 0x54 0x30 0x03 +i2cset -y 0 0x54 0x2F 0x23 +i2cset -y 0 0x54 0x2E 0x0B +i2cset -y 0 0x54 0x2D 0x00 +i2cset -y 0 0x54 0x28 0x76 +i2cset -y 0 0x54 0x27 0x54 +i2cset -y 0 0x54 0x25 0x00 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x23 0x06 +i2cset -y 0 0x54 0x1A 0x8C +i2cset -y 0 0x54 0x19 0x8C +i2cset -y 0 0x54 0x18 0x00 +i2cset -y 0 0x54 0x16 0x0D +i2cset -y 0 0x54 0x11 0x00 +i2cset -y 0 0x54 0x10 0x00 +i2cset -y 0 0x54 0x0E 0x3F +i2cset -y 0 0x54 0x0D 0xFF +i2cset -y 0 0x54 0x0C 0x02 +i2cset -y 0 0x54 0x0B 0xA1 +i2cset -y 0 0x54 0x0A 0x89 +i2cset -y 0 0x54 0x09 0xA2 +i2cset -y 0 0x54 0x08 0x32 +i2cset -y 0 0x54 0x06 0x00 +i2cset -y 0 0x54 0x05 0x00 +i2cset -y 0 0x54 0x04 0x00 +i2cset -y 0 0x54 0x03 0x00 +i2cset -y 0 0x54 0x02 0x05 +i2cset -y 0 0x54 0x01 0x33 +i2cset -y 0 0x54 0x00 0x91 + +echo "idt init 2" +# PreDivider_Parameters +#IN1 +i2cset -y 0 0x54 0x23 0x05 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x25 0x00 +#IN2 +i2cset -y 0 0x54 0x23 0x06 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x25 0x00 +#IN3 +i2cset -y 0 0x54 0x23 0x03 +i2cset -y 0 0x54 0x24 0x00 +i2cset -y 0 0x54 0x25 0x00 + +echo "idt init 3" +# Page1_Parameters +#Select to Page 1 +i2cset -y 0 0x54 0x2D 0x01 +i2cset -y 0 0x54 0x30 0x03 +i2cset -y 0 0x54 0x31 0x08 +i2cset -y 0 0x54 0x32 0x08 +i2cset -y 0 0x54 0x33 0x08 +i2cset -y 0 0x54 0x35 0x7C +i2cset -y 0 0x54 0x36 0xCE +i2cset -y 0 0x54 0x37 0x04 +i2cset -y 0 0x54 0x38 0xE6 +i2cset -y 0 0x54 0x39 0x01 +i2cset -y 0 0x54 0x3A 0x98 +i2cset -y 0 0x54 0x3B 0x00 +i2cset -y 0 0x54 0x3C 0x13 +i2cset -y 0 0x54 0x3D 0x20 +#Return to Page 0 +i2cset -y 0 0x54 0x2D 0x00 + +echo "idt init 4" +#reset the in-path mux +i2cset -y 0 0x76 0x0 +i2cset -y 0 0x77 0x0 + + + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/mac_reset.sh b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/mac_reset.sh new file mode 100755 index 000000000000..9f688058c305 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/mac_reset.sh @@ -0,0 +1,242 @@ +#!/bin/bash +test_log=/usr/local/bin/check_mac_status.txt +modprobe i2c-i801 +modprobe i2c-dev +i2cset -y 0 0x77 0x1 +i2cset -y 0 0x76 0x1 +i2cget -y 0 0x54 0 b > /dev/null +if [ $? -ne 0 ];then + printf "Device 8v89307(0x54) not found\n" + i2cdetect -y 0 + echo "Reset both MAC and PCI (write 0x6F)" + i2cset -y 0 0x60 0x8 0x6f + + echo "Sleep 1s" + sleep 1 + + echo "Pull back MAC reset, keep PCIE reset (write 0xEF)" + i2cset -y 0 0x60 0x7 0xef + + echo "Sleep 1s" + sleep 1 + + echo "Set to default normal state (write 0xFF)" + i2cset -y 0 0x60 0x8 0xff + + + echo "remove PCI device" + echo 1 > /sys/bus/pci/devices/0000:07:00.0/remove + ls /sys/bus/pci/devices/ + echo "rescan PCI device" + echo 1 > /sys/bus/pci/rescan + ls /sys/bus/pci/devices/ + echo "Sleep 1s" + sleep 1 + lspci -n|grep 07:00.0 + if [ $? -ne 0 ];then + echo "Broadcom Corporation Device is not detect">>$test_log + echo "rescan PCI again" >>$test_log + echo 1 > /sys/bus/pci/rescan + sleep 1 + lspci -n|grep 07:00.0 + if [ $? -ne 0 ];then + echo "Broadcom Corporation Device NG">>$test_log + echo "rescan PCI again-2" >>$test_log + echo 1 > /sys/bus/pci/rescan + sleep 1 + else + echo "done mac_pci_reset_rescan" + fi + fi + + exit 1 +fi +echo "idt init 1" +# Title = --- IDT 82V89307 Registers --- +#Select to Page 0 +i2cset -y 0 0x54 0x2D 0x00 +i2cset -y 0 0x54 0x7F 0x05 +i2cset -y 0 0x54 0x7E 0x85 +i2cset -y 0 0x54 0x7B 0x00 +i2cset -y 0 0x54 0x7A 0x00 +i2cset -y 0 0x54 0x79 0x40 +i2cset -y 0 0x54 0x78 0x06 +i2cset -y 0 0x54 0x73 0x40 +i2cset -y 0 0x54 0x72 0x40 + +# OUT3:25MHz +i2cset -y 0 0x54 0x71 0x0A +i2cset -y 0 0x54 0x70 0x00 + +# OUT1:1pps +i2cset -y 0 0x54 0x6B 0x4E +i2cset -y 0 0x54 0x69 0x00 +i2cset -y 0 0x54 0x68 0x00 +i2cset -y 0 0x54 0x67 0x19 +i2cset -y 0 0x54 0x66 0xAB +i2cset -y 0 0x54 0x65 0x8C +i2cset -y 0 0x54 0x64 0x00 +i2cset -y 0 0x54 0x63 0x00 +i2cset -y 0 0x54 0x62 0x00 +i2cset -y 0 0x54 0x5F 0x00 +i2cset -y 0 0x54 0x5E 0x00 +i2cset -y 0 0x54 0x5D 0x00 +i2cset -y 0 0x54 0x5C 0x78 +i2cset -y 0 0x54 0x5B 0x02 +i2cset -y 0 0x54 0x5A 0xE5 +i2cset -y 0 0x54 0x59 0x88 +i2cset -y 0 0x54 0x58 0x4B +i2cset -y 0 0x54 0x57 0x6C +i2cset -y 0 0x54 0x56 0x6C + +# Lock to DPLL, output 625MHz +i2cset -y 0 0x54 0x55 0x80 +i2cset -y 0 0x54 0x53 0x00 +i2cset -y 0 0x54 0x52 0x81 +i2cset -y 0 0x54 0x50 0x00 +i2cset -y 0 0x54 0x4F 0x00 +i2cset -y 0 0x54 0x4E 0x00 +i2cset -y 0 0x54 0x4C 0xCB +i2cset -y 0 0x54 0x4A 0x00 +i2cset -y 0 0x54 0x45 0x66 +i2cset -y 0 0x54 0x44 0x66 +i2cset -y 0 0x54 0x42 0x80 +i2cset -y 0 0x54 0x41 0x03 +i2cset -y 0 0x54 0x40 0x01 +i2cset -y 0 0x54 0x3F 0x08 +i2cset -y 0 0x54 0x3E 0x04 +i2cset -y 0 0x54 0x3D 0x20 +i2cset -y 0 0x54 0x3C 0x13 +i2cset -y 0 0x54 0x3B 0x00 +i2cset -y 0 0x54 0x3A 0x98 +i2cset -y 0 0x54 0x39 0x01 +i2cset -y 0 0x54 0x38 0xE6 +i2cset -y 0 0x54 0x37 0x04 +i2cset -y 0 0x54 0x36 0xCE +i2cset -y 0 0x54 0x35 0x7C +i2cset -y 0 0x54 0x34 0x01 +i2cset -y 0 0x54 0x33 0x08 +i2cset -y 0 0x54 0x32 0x08 +i2cset -y 0 0x54 0x31 0x08 +i2cset -y 0 0x54 0x30 0x03 +i2cset -y 0 0x54 0x2F 0x23 +i2cset -y 0 0x54 0x2E 0x0B +i2cset -y 0 0x54 0x2D 0x00 +i2cset -y 0 0x54 0x28 0x76 +i2cset -y 0 0x54 0x27 0x54 +i2cset -y 0 0x54 0x25 0x00 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x23 0x06 +i2cset -y 0 0x54 0x1A 0x8C +i2cset -y 0 0x54 0x19 0x8C +i2cset -y 0 0x54 0x18 0x00 +i2cset -y 0 0x54 0x16 0x0D +i2cset -y 0 0x54 0x11 0x00 +i2cset -y 0 0x54 0x10 0x00 +i2cset -y 0 0x54 0x0E 0x3F +i2cset -y 0 0x54 0x0D 0xFF +i2cset -y 0 0x54 0x0C 0x02 +i2cset -y 0 0x54 0x0B 0xA1 +i2cset -y 0 0x54 0x0A 0x89 +i2cset -y 0 0x54 0x09 0xA2 +i2cset -y 0 0x54 0x08 0x32 +i2cset -y 0 0x54 0x06 0x00 +i2cset -y 0 0x54 0x05 0x00 +i2cset -y 0 0x54 0x04 0x00 +i2cset -y 0 0x54 0x03 0x00 +i2cset -y 0 0x54 0x02 0x05 +i2cset -y 0 0x54 0x01 0x33 +i2cset -y 0 0x54 0x00 0x91 + +echo "idt init 2" +# PreDivider_Parameters +#IN1 +i2cset -y 0 0x54 0x23 0x05 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x25 0x00 +#IN2 +i2cset -y 0 0x54 0x23 0x06 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x25 0x00 +#IN3 +i2cset -y 0 0x54 0x23 0x03 +i2cset -y 0 0x54 0x24 0x00 +i2cset -y 0 0x54 0x25 0x00 + +echo "idt init 3" +# Page1_Parameters +#Select to Page 1 +i2cset -y 0 0x54 0x2D 0x01 +i2cset -y 0 0x54 0x30 0x03 +i2cset -y 0 0x54 0x31 0x08 +i2cset -y 0 0x54 0x32 0x08 +i2cset -y 0 0x54 0x33 0x08 +i2cset -y 0 0x54 0x35 0x7C +i2cset -y 0 0x54 0x36 0xCE +i2cset -y 0 0x54 0x37 0x04 +i2cset -y 0 0x54 0x38 0xE6 +i2cset -y 0 0x54 0x39 0x01 +i2cset -y 0 0x54 0x3A 0x98 +i2cset -y 0 0x54 0x3B 0x00 +i2cset -y 0 0x54 0x3C 0x13 +i2cset -y 0 0x54 0x3D 0x20 +#Return to Page 0 +i2cset -y 0 0x54 0x2D 0x00 + +echo "idt init 4" +#reset the in-path mux +i2cset -y 0 0x76 0x0 +i2cset -y 0 0x77 0x0 + +#flip MAC reset at CPLD +echo "Work around: We need to reset MAC after set 8v89307 clock output" +echo " or it is possible to get sdk init failure sometimes" +echo "MAC reset at CPLD" +i2cset -y 0 0x77 0x1 +i2cset -y 0 0x76 0x4 +#i2cset -y 0 0x60 0x8 0x7f +#sleep 1 +#i2cset -y 0 0x60 0x8 0xff + + echo "Reset both MAC and PCI (write 0x6F)" + i2cset -y 0 0x60 0x8 0x6f + + echo "Sleep 1s" + sleep 1 + + echo "Pull back MAC reset, keep PCIE reset (write 0xEF)" + i2cset -y 0 0x60 0x7 0xef + + echo "Sleep 1s" + sleep 1 + + echo "Set to default normal state (write 0xFF)" + i2cset -y 0 0x60 0x8 0xff + + + echo "remove PCI device" + echo 1 > /sys/bus/pci/devices/0000:07:00.0/remove + ls /sys/bus/pci/devices/ + echo "rescan PCI device" + echo 1 > /sys/bus/pci/rescan + ls /sys/bus/pci/devices/ + echo "Sleep 1s" + sleep 1 + lspci -n|grep 07:00.0 + if [ $? -ne 0 ];then + echo "Broadcom Corporation Device is not detect">>$test_log + echo "rescan PCI again" >>$test_log + echo 1 > /sys/bus/pci/rescan + sleep 1 + lspci -n|grep 07:00.0 + if [ $? -ne 0 ];then + echo "Broadcom Corporation Device NG">>$test_log + echo "rescan PCI again-2" >>$test_log + echo 1 > /sys/bus/pci/rescan + sleep 1 + else + echo "done mac_pci_reset_rescan" + fi + fi + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/fanutil.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/thermalutil.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/Makefile new file mode 100644 index 000000000000..1b3477b0b771 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/Makefile @@ -0,0 +1,2 @@ +obj-m:=x86-64-accton-as7816-64x-fan.o x86-64-accton-as7816-64x-sfp.o x86-64-accton-as7816-64x-leds.o \ + x86-64-accton-as7816-64x-psu.o accton_i2c_cpld.o ym2651y.o diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_i2c_cpld.c new file mode 120000 index 000000000000..39c0826d16fd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_i2c_cpld.c @@ -0,0 +1 @@ +../../common/modules/accton_i2c_cpld.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-fan.c b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-fan.c new file mode 100644 index 000000000000..3de2c200e1e1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-fan.c @@ -0,0 +1,466 @@ +/* + * A hwmon driver for the Accton as7816-64x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7816_64x_fan" + +static struct as7816_64x_fan_data *as7816_64x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x80, /* fan 1-4 present status */ + 0x81, /* fan 1-4 direction(0:F2B 1:B2F) */ + 0x87, /* fan PWM(for all fan) */ + 0x90, /* front fan 1 speed(rpm) */ + 0x91, /* front fan 2 speed(rpm) */ + 0x92, /* front fan 3 speed(rpm) */ + 0x93, /* front fan 4 speed(rpm) */ + 0x98, /* rear fan 1 speed(rpm) */ + 0x99, /* rear fan 2 speed(rpm) */ + 0x9A, /* rear fan 3 speed(rpm) */ + 0x9B, /* rear fan 4 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7816_64x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr + + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); + +static struct attribute *as7816_64x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7816_64x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7816_64x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + + if (!reg_val) { + return 0; + } + + if (reg_val == 0xF) { + return FAN_MAX_DUTY_CYCLE; + } + + return (reg_val * 6) + 10; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + if (duty_cycle < 16) { + return 0; + } + + if (duty_cycle >= 100) { + return 0xF; + } + + return (duty_cycle - 10) / 6; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + return !!(reg_val & mask); +} + +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + return !(reg_val & mask); +} + +static u8 is_fan_fault(struct as7816_64x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as7816_64x_fan_write_value(client, 0x28, 0); /* Disable fan speed watch dog */ + as7816_64x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7816_64x_fan_data *data = as7816_64x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + { + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + } + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7816_64x_fan_group = { + .attrs = as7816_64x_fan_attributes, +}; + +static struct as7816_64x_fan_data *as7816_64x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7816_64x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7816_64x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7816_64x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7816_64x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7816_64x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7816_64x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7816_64x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7816_64x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7816_64x_fan_remove(struct i2c_client *client) +{ + struct as7816_64x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7816_64x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static const struct i2c_device_id as7816_64x_fan_id[] = { + { "as7816_64x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7816_64x_fan_id); + +static struct i2c_driver as7816_64x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7816_64x_fan_probe, + .remove = as7816_64x_fan_remove, + .id_table = as7816_64x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7816_64x_fan_init(void) +{ + return i2c_add_driver(&as7816_64x_fan_driver); +} + +static void __exit as7816_64x_fan_exit(void) +{ + i2c_del_driver(&as7816_64x_fan_driver); +} + +module_init(as7816_64x_fan_init); +module_exit(as7816_64x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7816_64x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-leds.c b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-leds.c new file mode 100644 index 000000000000..025f87d692a3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-leds.c @@ -0,0 +1,460 @@ +/* + * A LED driver for the as7816_64x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int accton_i2c_cpld_read (u8 cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "as7816_64x_led" + +struct as7816_64x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct as7816_64x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x03) +#define LED_MODE_DIAG_YELLOW_VALUE (0x00) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_OFF_VALUE (0x03) + +#define LED_TYPE_LOC_REG_MASK (0x10) +#define LED_MODE_LOC_ORANGE_VALUE (0x00) +#define LED_MODE_LOC_OFF_VALUE (0x10) + +#define LED_TYPE_FAN_REG_MASK (0x0C) +#define LED_MODE_FAN_ORANGE_VALUE (0x04) +#define LED_MODE_FAN_GREEN_VALUE_1 (0x00) +#define LED_MODE_FAN_GREEN_VALUE_2 (0x08) +#define LED_MODE_FAN_OFF_VALUE (0x0C) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1 << LED_TYPE_LOC) | (1 << LED_TYPE_DIAG) | (1 << LED_TYPE_FAN), 0x30}, +}; + +enum led_light_mode { + LED_MODE_OFF, + LED_MODE_RED = 10, + LED_MODE_RED_BLINKING = 11, + LED_MODE_ORANGE = 12, + LED_MODE_ORANGE_BLINKING = 13, + LED_MODE_YELLOW = 14, + LED_MODE_YELLOW_BLINKING = 15, + LED_MODE_GREEN = 16, + LED_MODE_GREEN_BLINKING = 17, + LED_MODE_BLUE = 18, + LED_MODE_BLUE_BLINKING = 19, + LED_MODE_PURPLE = 20, + LED_MODE_PURPLE_BLINKING = 21, + LED_MODE_AUTO = 22, + LED_MODE_AUTO_BLINKING = 23, + LED_MODE_WHITE = 24, + LED_MODE_WHITE_BLINKING = 25, + LED_MODE_CYAN = 26, + LED_MODE_CYAN_BLINKING = 27, + LED_MODE_UNKNOWN = 99 +}; + +struct led_type_mode { + enum led_type type; + enum led_light_mode mode; + int reg_bit_mask; + int mode_value; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE}, +{LED_TYPE_LOC, LED_MODE_ORANGE,LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_ORANGE_VALUE}, +{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE}, +{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE}, +{LED_TYPE_DIAG, LED_MODE_RED, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_RED_VALUE}, +{LED_TYPE_DIAG, LED_MODE_YELLOW,LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_YELLOW_VALUE}, +{LED_TYPE_FAN, LED_MODE_OFF, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_OFF_VALUE}, +{LED_TYPE_FAN, LED_MODE_GREEN, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_GREEN_VALUE_1}, +{LED_TYPE_FAN, LED_MODE_GREEN, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_GREEN_VALUE_2}, +{LED_TYPE_FAN, LED_MODE_ORANGE,LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_ORANGE_VALUE} +}; + +static int get_led_reg(enum led_type type, u8 *reg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(led_reg_map); i++) { + if(led_reg_map[i].types & (1 << type)) { + *reg = led_reg_map[i].reg_addr; + return 0; + } + } + + return 1; +} + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].reg_bit_mask & reg_val) == + led_type_mode_data[i].mode_value) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + reg_val = led_type_mode_data[i].mode_value | + (reg_val & (~led_type_mode_data[i].reg_bit_mask)); + break; + } + + return reg_val; +} + +static int as7816_64x_led_read_value(u8 reg) +{ + return accton_i2c_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); +} + +static int as7816_64x_led_write_value(u8 reg, u8 value) +{ + return accton_i2c_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); +} + +static void as7816_64x_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting as7816_64x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = as7816_64x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void as7816_64x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !get_led_reg(type, ®)) { + dev_dbg(&ledctl->pdev->dev, "Not match register for %d.\n", type); + } + + reg_val = as7816_64x_led_read_value(reg); + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + as7816_64x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void as7816_64x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7816_64x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness as7816_64x_led_diag_get(struct led_classdev *cdev) +{ + as7816_64x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void as7816_64x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7816_64x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness as7816_64x_led_loc_get(struct led_classdev *cdev) +{ + as7816_64x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void as7816_64x_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7816_64x_led_set(led_cdev, led_light_mode, LED_TYPE_FAN); +} + +static enum led_brightness as7816_64x_led_fan_get(struct led_classdev *cdev) +{ + as7816_64x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + +static void as7816_64x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness as7816_64x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev as7816_64x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "as7816_64x_led::diag", + .default_trigger = "unused", + .brightness_set = as7816_64x_led_diag_set, + .brightness_get = as7816_64x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN, + }, + [LED_TYPE_LOC] = { + .name = "as7816_64x_led::loc", + .default_trigger = "unused", + .brightness_set = as7816_64x_led_loc_set, + .brightness_get = as7816_64x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_ORANGE, + }, + [LED_TYPE_FAN] = { + .name = "as7816_64x_led::fan", + .default_trigger = "unused", + .brightness_set = as7816_64x_led_fan_set, + .brightness_get = as7816_64x_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN, + }, + [LED_TYPE_PSU1] = { + .name = "as7816_64x_led::psu1", + .default_trigger = "unused", + .brightness_set = as7816_64x_led_auto_set, + .brightness_get = as7816_64x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as7816_64x_led::psu2", + .default_trigger = "unused", + .brightness_set = as7816_64x_led_auto_set, + .brightness_get = as7816_64x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int as7816_64x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(as7816_64x_leds); i++) { + led_classdev_suspend(&as7816_64x_leds[i]); + } + + return 0; +} + +static int as7816_64x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(as7816_64x_leds); i++) { + led_classdev_resume(&as7816_64x_leds[i]); + } + + return 0; +} + +static int as7816_64x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(as7816_64x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &as7816_64x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(as7816_64x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&as7816_64x_leds[i]); + } + } + + return ret; +} + +static int as7816_64x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(as7816_64x_leds); i++) { + led_classdev_unregister(&as7816_64x_leds[i]); + } + + return 0; +} + +static struct platform_driver as7816_64x_led_driver = { + .probe = as7816_64x_led_probe, + .remove = as7816_64x_led_remove, + .suspend = as7816_64x_led_suspend, + .resume = as7816_64x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init as7816_64x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&as7816_64x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct as7816_64x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&as7816_64x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&as7816_64x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit as7816_64x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&as7816_64x_led_driver); + kfree(ledctl); +} + +module_init(as7816_64x_led_init); +module_exit(as7816_64x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7816_64x_led driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-psu.c b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-psu.c new file mode 100644 index 000000000000..cdc535347dc0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-psu.c @@ -0,0 +1,239 @@ +/* + * An hwmon driver for accton as7816_64x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x03 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(2+id))) +#define IS_PRESENT(id, value) (!(value & BIT(id))) + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static struct as7816_64x_psu_data *as7816_64x_psu_update_device(struct device *dev); +extern int accton_i2c_cpld_read (u8 cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7816_64x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ +}; + +enum as7816_64x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as7816_64x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7816_64x_psu_data *data = as7816_64x_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return -EIO; + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static const struct attribute_group as7816_64x_psu_group = { + .attrs = as7816_64x_psu_attributes, +}; + +static int as7816_64x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7816_64x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7816_64x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7816_64x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7816_64x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7816_64x_psu_remove(struct i2c_client *client) +{ + struct as7816_64x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7816_64x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7816_64x_psu1, + as7816_64x_psu2 +}; + +static const struct i2c_device_id as7816_64x_psu_id[] = { + { "as7816_64x_psu1", as7816_64x_psu1 }, + { "as7816_64x_psu2", as7816_64x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7816_64x_psu_id); + +static struct i2c_driver as7816_64x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7816_64x_psu", + }, + .probe = as7816_64x_psu_probe, + .remove = as7816_64x_psu_remove, + .id_table = as7816_64x_psu_id, + .address_list = normal_i2c, +}; + +static struct as7816_64x_psu_data *as7816_64x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7816_64x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + + data->valid = 0; + dev_dbg(&client->dev, "Starting as7816_64x update\n"); + + /* Read psu status */ + status = accton_i2c_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as7816_64x_psu_init(void) +{ + return i2c_add_driver(&as7816_64x_psu_driver); +} + +static void __exit as7816_64x_psu_exit(void) +{ + i2c_del_driver(&as7816_64x_psu_driver); +} + +module_init(as7816_64x_psu_init); +module_exit(as7816_64x_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7816_64x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-sfp.c b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-sfp.c new file mode 100644 index 000000000000..76444ebbafcb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-sfp.c @@ -0,0 +1,1576 @@ +/* + * SFP driver for accton as7816_64x sfp + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "as7816_64x_sfp" /* Platform dependent */ + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define NUM_OF_SFP_PORT 24 +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +#define MULTIPAGE_SUPPORT 1 + +#if (MULTIPAGE_SUPPORT == 1) +/* fundamental unit of addressing for SFF_8472/SFF_8436 */ +#define SFF_8436_PAGE_SIZE 128 +/* + * The current 8436 (QSFP) spec provides for only 4 supported + * pages (pages 0-3). + * This driver is prepared to support more, but needs a register in the + * EEPROM to indicate how many pages are supported before it is safe + * to implement more pages in the driver. + */ +#define SFF_8436_SPECED_PAGES 4 +#define SFF_8436_EEPROM_SIZE ((1 + SFF_8436_SPECED_PAGES) * SFF_8436_PAGE_SIZE) +#define SFF_8436_EEPROM_UNPAGED_SIZE (2 * SFF_8436_PAGE_SIZE) +/* + * The current 8472 (SFP) spec provides for only 3 supported + * pages (pages 0-2). + * This driver is prepared to support more, but needs a register in the + * EEPROM to indicate how many pages are supported before it is safe + * to implement more pages in the driver. + */ +#define SFF_8472_SPECED_PAGES 3 +#define SFF_8472_EEPROM_SIZE ((3 + SFF_8472_SPECED_PAGES) * SFF_8436_PAGE_SIZE) +#define SFF_8472_EEPROM_UNPAGED_SIZE (4 * SFF_8436_PAGE_SIZE) + +/* a few constants to find our way around the EEPROM */ +#define SFF_8436_PAGE_SELECT_REG 0x7F +#define SFF_8436_PAGEABLE_REG 0x02 +#define SFF_8436_NOT_PAGEABLE (1<<2) +#define SFF_8472_PAGEABLE_REG 0x40 +#define SFF_8472_PAGEABLE (1<<4) + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = SFF_8436_PAGE_SIZE; + +/* + * specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; + +typedef enum qsfp_opcode { + QSFP_READ_OP = 0, + QSFP_WRITE_OP = 1 +} qsfp_opcode_e; +#endif + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +extern int accton_i2c_cpld_read (u8 cpld_addr, u8 reg); + +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL +}; + +/* SFP/QSFP common attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT); + +/* QSFP attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); +static struct attribute *qsfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, + NULL +}; + +/* Platform dependent +++ */ +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +as7816_64x_port1, as7816_64x_port2, as7816_64x_port3, as7816_64x_port4, +as7816_64x_port5, as7816_64x_port6, as7816_64x_port7, as7816_64x_port8, +as7816_64x_port9, as7816_64x_port10, as7816_64x_port11, as7816_64x_port12, +as7816_64x_port13, as7816_64x_port14, as7816_64x_port15, as7816_64x_port16, +as7816_64x_port17, as7816_64x_port18, as7816_64x_port19, as7816_64x_port20, +as7816_64x_port21, as7816_64x_port22, as7816_64x_port23, as7816_64x_port24, +as7816_64x_port25, as7816_64x_port26, as7816_64x_port27, as7816_64x_port28, +as7816_64x_port29, as7816_64x_port30, as7816_64x_port31, as7816_64x_port32, +as7816_64x_port33, as7816_64x_port34, as7816_64x_port35, as7816_64x_port36, +as7816_64x_port37, as7816_64x_port38, as7816_64x_port39, as7816_64x_port40, +as7816_64x_port41, as7816_64x_port42, as7816_64x_port43, as7816_64x_port44, +as7816_64x_port45, as7816_64x_port46, as7816_64x_port47, as7816_64x_port48, +as7816_64x_port49, as7816_64x_port50, as7816_64x_port51, as7816_64x_port52, +as7816_64x_port53, as7816_64x_port54, as7816_64x_port55, as7816_64x_port56, +as7816_64x_port57, as7816_64x_port58, as7816_64x_port59, as7816_64x_port60, +as7816_64x_port61, as7816_64x_port62, as7816_64x_port63, as7816_64x_port64 +}; + +#define I2C_DEV_ID(x) { #x, x} + +static const struct i2c_device_id sfp_device_id[] = { +I2C_DEV_ID(as7816_64x_port1), +I2C_DEV_ID(as7816_64x_port2), +I2C_DEV_ID(as7816_64x_port3), +I2C_DEV_ID(as7816_64x_port4), +I2C_DEV_ID(as7816_64x_port5), +I2C_DEV_ID(as7816_64x_port6), +I2C_DEV_ID(as7816_64x_port7), +I2C_DEV_ID(as7816_64x_port8), +I2C_DEV_ID(as7816_64x_port9), +I2C_DEV_ID(as7816_64x_port10), +I2C_DEV_ID(as7816_64x_port11), +I2C_DEV_ID(as7816_64x_port12), +I2C_DEV_ID(as7816_64x_port13), +I2C_DEV_ID(as7816_64x_port14), +I2C_DEV_ID(as7816_64x_port15), +I2C_DEV_ID(as7816_64x_port16), +I2C_DEV_ID(as7816_64x_port17), +I2C_DEV_ID(as7816_64x_port18), +I2C_DEV_ID(as7816_64x_port19), +I2C_DEV_ID(as7816_64x_port20), +I2C_DEV_ID(as7816_64x_port21), +I2C_DEV_ID(as7816_64x_port22), +I2C_DEV_ID(as7816_64x_port23), +I2C_DEV_ID(as7816_64x_port24), +I2C_DEV_ID(as7816_64x_port25), +I2C_DEV_ID(as7816_64x_port26), +I2C_DEV_ID(as7816_64x_port27), +I2C_DEV_ID(as7816_64x_port28), +I2C_DEV_ID(as7816_64x_port29), +I2C_DEV_ID(as7816_64x_port30), +I2C_DEV_ID(as7816_64x_port31), +I2C_DEV_ID(as7816_64x_port32), +I2C_DEV_ID(as7816_64x_port33), +I2C_DEV_ID(as7816_64x_port34), +I2C_DEV_ID(as7816_64x_port35), +I2C_DEV_ID(as7816_64x_port36), +I2C_DEV_ID(as7816_64x_port37), +I2C_DEV_ID(as7816_64x_port38), +I2C_DEV_ID(as7816_64x_port39), +I2C_DEV_ID(as7816_64x_port40), +I2C_DEV_ID(as7816_64x_port41), +I2C_DEV_ID(as7816_64x_port42), +I2C_DEV_ID(as7816_64x_port43), +I2C_DEV_ID(as7816_64x_port44), +I2C_DEV_ID(as7816_64x_port45), +I2C_DEV_ID(as7816_64x_port46), +I2C_DEV_ID(as7816_64x_port47), +I2C_DEV_ID(as7816_64x_port48), +I2C_DEV_ID(as7816_64x_port49), +I2C_DEV_ID(as7816_64x_port50), +I2C_DEV_ID(as7816_64x_port51), +I2C_DEV_ID(as7816_64x_port52), +I2C_DEV_ID(as7816_64x_port53), +I2C_DEV_ID(as7816_64x_port54), +I2C_DEV_ID(as7816_64x_port55), +I2C_DEV_ID(as7816_64x_port56), +I2C_DEV_ID(as7816_64x_port57), +I2C_DEV_ID(as7816_64x_port58), +I2C_DEV_ID(as7816_64x_port59), +I2C_DEV_ID(as7816_64x_port60), +I2C_DEV_ID(as7816_64x_port61), +I2C_DEV_ID(as7816_64x_port62), +I2C_DEV_ID(as7816_64x_port63), +I2C_DEV_ID(as7816_64x_port64), +{ /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); +/* Platform dependent --- */ + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP, + DRIVER_TYPE_XFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + + struct qsfp_data *qsfp; + + struct i2c_client *client; +#if (MULTIPAGE_SUPPORT == 1) + int use_smbus; + u8 *writebuf; + unsigned write_max; +#endif +}; + +#if (MULTIPAGE_SUPPORT == 1) +static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, + char *buf, loff_t off, size_t len, qsfp_opcode_e opcode); +#endif +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + +/* Platform dependent +++ */ +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77}; + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + + /* Read present status of port 1~64 */ + data->present = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = accton_i2c_cpld_read(0x60, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); + data->present |= (u64)status << (i*8); + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +/* Platform dependent --- */ + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + data = sfp_update_present(client); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + return (data->present & BIT_INDEX(data->port)) ? 0 : 1; /* Platform dependent */ +} + +/* Platform dependent +++ */ +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if (PRESENT_ALL == attr->index) { + int i; + u8 values[8] = {0}; + struct sfp_port_data *data = sfp_update_present(client); + + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = ~(u8)(data->present >> (i * 8)); + } + + /* Return values 1 -> 64 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3], + values[4], values[5], values[6], values[7]); + } + else { + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + /* PRESENT */ + return sprintf(buf, "%d\n", present); + } +} +/* Platform dependent --- */ + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + DEBUG_PRINT("Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + goto exit; + } + } + msleep(200); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + int present; + u8 val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENXIO; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + switch (attr->index) { + case TX_FAULT: + val = !!(data->qsfp->status[2] & 0xF); + break; + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); + break; + case TX_DISABLE: + val = data->qsfp->status[1] & 0xF; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); + break; + case RX_LOS: + val = !!(data->qsfp->status[0] & 0xF); + break; + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); + break; + default: + break; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (!status) { + /* port is not present */ + return -ENXIO; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + mutex_lock(&data->update_lock); + + if (attr->index == TX_DISABLE) { + if (disable) { + data->qsfp->status[1] |= 0xF; + } + else { + data->qsfp->status[1] &= ~0xF; + } + } + else {/* TX_DISABLE1 ~ TX_DISABLE4*/ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + if (unlikely(status < 0)) { + count = status; + } + + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return data_len; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, command, *data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return 1; +#endif + + +} + +#if (MULTIPAGE_SUPPORT == 0) +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} +#endif + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + +#if (MULTIPAGE_SUPPORT == 1) + return sfp_port_read_write(data, buf, off, count, QSFP_WRITE_OP); +#else + return sfp_port_write(data, buf, off, count); +#endif +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + goto abort; + } + if (unlikely(status != data_len)) { + status = -EIO; + goto abort; + } + + //result = data_len; + +abort: + return status; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); + goto abort; + } + + *data = (u8)status; + status = 1; + +abort: + return status; +#endif +} + +#if (MULTIPAGE_SUPPORT == 1) +/*-------------------------------------------------------------------------*/ +/* + * This routine computes the addressing information to be used for + * a given r/w request. + * + * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), + * the page, and the offset. + * + * Handles both SFP and QSFP. + * For SFP, offset 0-255 are on client[0], >255 is on client[1] + * Offset 256-383 are on the lower half of client[1] + * Pages are accessible on the upper half of client[1]. + * Offset >383 are in 128 byte pages mapped into the upper half + * + * For QSFP, all offsets are on client[0] + * offset 0-127 are on the lower half of client[0] (no paging) + * Pages are accessible on the upper half of client[1]. + * Offset >127 are in 128 byte pages mapped into the upper half + * + * Callers must not read/write beyond the end of a client or a page + * without recomputing the client/page. Hence offset (within page) + * plus length must be less than or equal to 128. (Note that this + * routine does not have access to the length of the call, hence + * cannot do the validity check.) + * + * Offset within Lower Page 00h and Upper Page 00h are not recomputed + */ +static uint8_t sff_8436_translate_offset(struct sfp_port_data *port_data, + loff_t *offset, struct i2c_client **client) +{ + unsigned page = 0; + + *client = port_data->client; + + /* + * if offset is in the range 0-128... + * page doesn't matter (using lower half), return 0. + * offset is already correct (don't add 128 to get to paged area) + */ + if (*offset < SFF_8436_PAGE_SIZE) + return page; + + /* note, page will always be positive since *offset >= 128 */ + page = (*offset >> 7)-1; + /* 0x80 places the offset in the top half, offset is last 7 bits */ + *offset = SFF_8436_PAGE_SIZE + (*offset & 0x7f); + + return page; /* note also returning client and offset */ +} + +static ssize_t sff_8436_eeprom_read(struct sfp_port_data *port_data, + struct i2c_client *client, + char *buf, unsigned offset, size_t count) +{ + struct i2c_msg msg[2]; + u8 msgbuf[2]; + unsigned long timeout, read_time; + int status, i; + + memset(msg, 0, sizeof(msg)); + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + /*smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: + /* Check for odd length transaction */ + count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; + break; + default: + /* + * When we have a better choice than SMBus calls, use a + * combined I2C message. Write address; then read up to + * io_limit data bytes. msgbuf is u8 and will cast to our + * needs. + */ + i = 0; + msgbuf[i++] = offset; + + msg[0].addr = client->addr; + msg[0].buf = msgbuf; + msg[0].len = i; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + } + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + read_time = jiffies; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_read_i2c_block_data(client, offset, + count, buf); + break; + case I2C_SMBUS_WORD_DATA: + status = i2c_smbus_read_word_data(client, offset); + if (status >= 0) { + buf[0] = status & 0xff; + if (count == 2) + buf[1] = status >> 8; + status = count; + } + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_read_byte_data(client, offset); + if (status >= 0) { + buf[0] = status; + status = count; + } + break; + default: + status = i2c_transfer(client->adapter, msg, 2); + if (status == 2) + status = count; + } + + dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", + count, offset, status, jiffies); + + if (status == count) /* happy path */ + return count; + + if (status == -ENXIO) /* no module present */ + return status; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(read_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t sff_8436_eeprom_write(struct sfp_port_data *port_data, + struct i2c_client *client, + const char *buf, + unsigned offset, size_t count) +{ + struct i2c_msg msg; + ssize_t status; + unsigned long timeout, write_time; + unsigned next_page_start; + int i = 0; + + /* write max is at most a page + * (In this driver, write_max is actually one byte!) + */ + if (count > port_data->write_max) + count = port_data->write_max; + + /* shorten count if necessary to avoid crossing page boundary */ + next_page_start = roundup(offset + 1, SFF_8436_PAGE_SIZE); + if (offset + count > next_page_start) + count = next_page_start - offset; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + /*smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: + /* Check for odd length transaction */ + count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; + break; + default: + /* If we'll use I2C calls for I/O, set up the message */ + msg.addr = client->addr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = port_data->writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + break; + } + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_write_i2c_block_data(client, + offset, count, buf); + if (status == 0) + status = count; + break; + case I2C_SMBUS_WORD_DATA: + if (count == 2) { + status = i2c_smbus_write_word_data(client, + offset, (u16)((buf[0])|(buf[1] << 8))); + } else { + /* count = 1 */ + status = i2c_smbus_write_byte_data(client, + offset, buf[0]); + } + if (status == 0) + status = count; + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_write_byte_data(client, offset, + buf[0]); + if (status == 0) + status = count; + break; + default: + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + break; + } + + dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", + count, offset, (long int) status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(write_time, timeout)); + + return -ETIMEDOUT; +} + + +static ssize_t sff_8436_eeprom_update_client(struct sfp_port_data *port_data, + char *buf, loff_t off, + size_t count, qsfp_opcode_e opcode) +{ + struct i2c_client *client; + ssize_t retval = 0; + u8 page = 0; + loff_t phy_offset = off; + int ret = 0; + + page = sff_8436_translate_offset(port_data, &phy_offset, &client); + + dev_dbg(&client->dev, + "sff_8436_eeprom_update_client off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", + off, page, phy_offset, (long int) count, opcode); + if (page > 0) { + ret = sff_8436_eeprom_write(port_data, client, &page, + SFF_8436_PAGE_SELECT_REG, 1); + if (ret < 0) { + dev_dbg(&client->dev, + "Write page register for page %d failed ret:%d!\n", + page, ret); + return ret; + } + } + + while (count) { + ssize_t status; + + if (opcode == QSFP_READ_OP) { + status = sff_8436_eeprom_read(port_data, client, + buf, phy_offset, count); + } else { + status = sff_8436_eeprom_write(port_data, client, + buf, phy_offset, count); + } + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + phy_offset += status; + count -= status; + retval += status; + } + + + if (page > 0) { + /* return the page register to page 0 (why?) */ + page = 0; + ret = sff_8436_eeprom_write(port_data, client, &page, + SFF_8436_PAGE_SELECT_REG, 1); + if (ret < 0) { + dev_err(&client->dev, + "Restore page register to page %d failed ret:%d!\n", + page, ret); + return ret; + } + } + return retval; +} + + +/* + * Figure out if this access is within the range of supported pages. + * Note this is called on every access because we don't know if the + * module has been replaced since the last call. + * If/when modules support more pages, this is the routine to update + * to validate and allow access to additional pages. + * + * Returns updated len for this access: + * - entire access is legal, original len is returned. + * - access begins legal but is too long, len is truncated to fit. + * - initial offset exceeds supported pages, return -EINVAL + */ +static ssize_t sff_8436_page_legal(struct sfp_port_data *port_data, + loff_t off, size_t len) +{ + struct i2c_client *client = port_data->client; + u8 regval; + int status; + size_t maxlen; + + if (off < 0) return -EINVAL; + if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { + /* SFP case */ + /* if no pages needed, we're good */ + if ((off + len) <= SFF_8472_EEPROM_UNPAGED_SIZE) return len; + /* if offset exceeds possible pages, we're not good */ + if (off >= SFF_8472_EEPROM_SIZE) return -EINVAL; + /* in between, are pages supported? */ + status = sff_8436_eeprom_read(port_data, client, ®val, + SFF_8472_PAGEABLE_REG, 1); + if (status < 0) return status; /* error out (no module?) */ + if (regval & SFF_8472_PAGEABLE) { + /* Pages supported, trim len to the end of pages */ + maxlen = SFF_8472_EEPROM_SIZE - off; + } else { + /* pages not supported, trim len to unpaged size */ + maxlen = SFF_8472_EEPROM_UNPAGED_SIZE - off; + } + len = (len > maxlen) ? maxlen : len; + dev_dbg(&client->dev, + "page_legal, SFP, off %lld len %ld\n", + off, (long int) len); + } + else if (port_data->driver_type == DRIVER_TYPE_QSFP || + port_data->driver_type == DRIVER_TYPE_XFP) { + /* QSFP case */ + /* if no pages needed, we're good */ + if ((off + len) <= SFF_8436_EEPROM_UNPAGED_SIZE) return len; + /* if offset exceeds possible pages, we're not good */ + if (off >= SFF_8436_EEPROM_SIZE) return -EINVAL; + /* in between, are pages supported? */ + status = sff_8436_eeprom_read(port_data, client, ®val, + SFF_8436_PAGEABLE_REG, 1); + if (status < 0) return status; /* error out (no module?) */ + if (regval & SFF_8436_NOT_PAGEABLE) { + /* pages not supported, trim len to unpaged size */ + maxlen = SFF_8436_EEPROM_UNPAGED_SIZE - off; + } else { + /* Pages supported, trim len to the end of pages */ + maxlen = SFF_8436_EEPROM_SIZE - off; + } + len = (len > maxlen) ? maxlen : len; + dev_dbg(&client->dev, + "page_legal, QSFP, off %lld len %ld\n", + off, (long int) len); + } + else { + return -EINVAL; + } + return len; +} + + +static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, + char *buf, loff_t off, size_t len, qsfp_opcode_e opcode) +{ + struct i2c_client *client = port_data->client; + int chunk; + int status = 0; + ssize_t retval; + size_t pending_len = 0, chunk_len = 0; + loff_t chunk_offset = 0, chunk_start_offset = 0; + + if (unlikely(!len)) + return len; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&port_data->update_lock); + + /* + * Confirm this access fits within the device suppored addr range + */ + len = sff_8436_page_legal(port_data, off, len); + if (len < 0) { + status = len; + goto err; + } + + /* + * For each (128 byte) chunk involved in this request, issue a + * separate call to sff_eeprom_update_client(), to + * ensure that each access recalculates the client/page + * and writes the page register as needed. + * Note that chunk to page mapping is confusing, is different for + * QSFP and SFP, and never needs to be done. Don't try! + */ + pending_len = len; /* amount remaining to transfer */ + retval = 0; /* amount transferred */ + for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { + + /* + * Compute the offset and number of bytes to be read/write + * + * 1. start at offset 0 (within the chunk), and read/write + * the entire chunk + * 2. start at offset 0 (within the chunk) and read/write less + * than entire chunk + * 3. start at an offset not equal to 0 and read/write the rest + * of the chunk + * 4. start at an offset not equal to 0 and read/write less than + * (end of chunk - offset) + */ + chunk_start_offset = chunk * SFF_8436_PAGE_SIZE; + + if (chunk_start_offset < off) { + chunk_offset = off; + if ((off + pending_len) < (chunk_start_offset + + SFF_8436_PAGE_SIZE)) + chunk_len = pending_len; + else + chunk_len = (chunk+1)*SFF_8436_PAGE_SIZE - off;/*SFF_8436_PAGE_SIZE - off;*/ + } else { + chunk_offset = chunk_start_offset; + if (pending_len > SFF_8436_PAGE_SIZE) + chunk_len = SFF_8436_PAGE_SIZE; + else + chunk_len = pending_len; + } + + dev_dbg(&client->dev, + "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", + off, (long int) len, chunk_start_offset, chunk_offset, + (long int) chunk_len, (long int) pending_len); + + /* + * note: chunk_offset is from the start of the EEPROM, + * not the start of the chunk + */ + status = sff_8436_eeprom_update_client(port_data, buf, + chunk_offset, chunk_len, opcode); + if (status != chunk_len) { + /* This is another 'no device present' path */ + dev_dbg(&client->dev, + "sff_8436_update_client for chunk %d chunk_offset %lld chunk_len %ld failed %d!\n", + chunk, chunk_offset, (long int) chunk_len, status); + goto err; + } + buf += status; + pending_len -= status; + retval += status; + } + mutex_unlock(&port_data->update_lock); + + return retval; + +err: + mutex_unlock(&port_data->update_lock); + + return status; +} + +#else +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} +#endif + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + +#if (MULTIPAGE_SUPPORT == 1) + return sfp_port_read_write(data, buf, off, count, QSFP_READ_OP); +#else + return sfp_port_read(data, buf, off, count); +#endif +} + +#if (MULTIPAGE_SUPPORT == 1) +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom, size_t size) +#else +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +#endif +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; +#if (MULTIPAGE_SUPPORT == 1) + eeprom->size = size; +#else + eeprom->size = EEPROM_SIZE; +#endif + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + + +#if (MULTIPAGE_SUPPORT == 0) +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} +#endif + + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + +#if (MULTIPAGE_SUPPORT == 0) + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } +#endif + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ +#if (MULTIPAGE_SUPPORT == 1) + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin, SFF_8436_EEPROM_SIZE); +#else + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); +#endif + if (status) { + goto exit_remove; + } + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +/* Platform dependent +++ */ +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int ret = 0; + struct sfp_port_data *data = NULL; + + if (client->addr != SFP_EEPROM_A0_I2C_ADDR) { + return -ENODEV; + } + + if (dev_id->driver_data < as7816_64x_port1 || dev_id->driver_data > as7816_64x_port64) { + return -ENXIO; + } + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + +#if (MULTIPAGE_SUPPORT == 1) + data->use_smbus = 0; + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + data->use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) { + data->use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + data->use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + ret = -EPFNOSUPPORT; + goto exit_kfree; + } + } + + if (!data->use_smbus || + (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || + i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_WORD_DATA) || + i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + /* + * NOTE: AN-2079 + * Finisar recommends that the host implement 1 byte writes + * only since this module only supports 32 byte page boundaries. + * 2 byte writes are acceptable for PE and Vout changes per + * Application Note AN-2071. + */ + unsigned write_max = 1; + + if (write_max > io_limit) + write_max = io_limit; + if (data->use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + data->write_max = write_max; + + /* buffer (data + address at the beginning) */ + data->writebuf = kmalloc(write_max + 2, GFP_KERNEL); + if (!data->writebuf) { + ret = -ENOMEM; + goto exit_kfree; + } + } else { + dev_warn(&client->dev, + "cannot write due to controller restrictions."); + } + + if (data->use_smbus == I2C_SMBUS_WORD_DATA || + data->use_smbus == I2C_SMBUS_BYTE_DATA) { + dev_notice(&client->dev, "Falling back to %s reads, " + "performance will suffer\n", data->use_smbus == + I2C_SMBUS_WORD_DATA ? "word" : "byte"); + } +#endif + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + data->driver_type = DRIVER_TYPE_QSFP; + + ret = qsfp_probe(client, dev_id, &data->qsfp); + if (ret < 0) { + goto exit_kfree_buf; + } + + return ret; + +exit_kfree_buf: +#if (MULTIPAGE_SUPPORT == 1) + if (data->writebuf) kfree(data->writebuf); +#endif + +exit_kfree: + kfree(data); + return ret; +} +/* Platform dependent --- */ + +static int qsfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + int ret = 0; + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (data->driver_type == DRIVER_TYPE_QSFP) { + ret = qsfp_remove(client, data->qsfp); + } + + kfree(data); + return ret; +} + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7816_64x_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-platform-init.service new file mode 100755 index 000000000000..c1ba30092f1d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Accton AS7816-64X Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/accton_as7816_util.py install +ExecStop=/usr/local/bin/accton_as7816_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/setup.py new file mode 100755 index 000000000000..6633b9438b86 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7816_64x', + version='1.0', + description='Module to initialize Accton AS7816-64X platforms', + + packages=['as7816_64x'], + package_dir={'as7816_64x': 'as7816-64x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/README new file mode 100755 index 000000000000..0b9fc1633999 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/README @@ -0,0 +1,60 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program is free software: you can redistribute it and/or modify +It under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +To initialize the system, run "accton_as7712_util.py install". +To clean up the drivers & devices, run "accton_as7712_util.py clean". +To dump information of sensors, run "accton_as7712_util.py show". +To dump SFP EEPROM, run "accton_as7712_util.py sff". +To set fan speed, run "accton_as7712_util.py set fan". +To enable/disable SFP emission, run "accton_as7712_util.py set sfp". +To set system LEDs' color, run "accton_as7712_util.py set led" +For more information, run "accton_as7712_util.py --help". + +==================================================================== +Besides applying accton_as7712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +LED controls can be found under /sys/class/leds. The sysfs interface +color mappings are as follows: +Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + +There are 5 system LEDs, loc, diag, fan, ps1, and ps2. +They are lit automatically by CPLD, but the loc and diag. +The loc led has only 1 color, blue. +The diag one has 3 colors: red, amber, and green. + +Fan controls can be found in /sys/bus/i2c/devices/2-0066. +There are 12 fans inside 6 fan modules. +All fans share 1 duty setting, ranged from 0~100. + +Three temperature sensors are controlled by the lm75 kernel modules. +They should already be visible under /sys/bus/i2c/drivers/lm75/. + +Two power supplies are controlled by the CPLD. +Here provide their status under +/sys/bus/i2c/devices/10-0050 and /sys/bus/i2c/devices/11-0053. + +There are 32 QSFP+ modules are equipped. +Apply "accton_as7712_util.py show" to get their status. +Apply "accton_as7712_util.py set sfp" to turn on/off light transmission. +Apply "accton_as7712_util.py sff" to dump EEPROM information. +Before operating on that QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_util.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_util.py new file mode 100755 index 000000000000..44c4486a2d59 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_util.py @@ -0,0 +1,523 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'as7816_64x' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':4,'thermal':6, 'psu':2, 'sfp':64} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x', +'modprobe accton_i2c_cpld' , +'modprobe ym2651y' , +'modprobe x86-64-accton-as7816-64x-fan' , +'modprobe x86-64-accton-as7816-64x-sfp' , +'modprobe x86-64-accton-as7816-64x-leds' , +'modprobe x86-64-accton-as7816-64x-psu' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['17-0068'] , + 'thermal': ['18-0048','18-0049', '18-004a' , '18-004b', '17-004d', '17-004e'] , + 'psu': ['10-0053','9-0050'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable']} + +sfp_map = [37,38,39,40,42,41,44,43,33,34,35,36,45,46,47,48,49,50,51,52, + 61,62,63,64,53,54,55,56,57,58,59,60,69,70,71,72,77,78,79,80,65, + 66,67,68,73,74,75,76,85,86,87,88,31,32,29,30,81,82,83,84,25,26, + 27,28] + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as7816_64x_psu1 0x53 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo ym2851 0x5b > /sys/bus/i2c/devices/i2c-10/new_device', +'echo as7816_64x_psu2 0x50 > /sys/bus/i2c/devices/i2c-9/new_device', +'echo ym2851 0x58 > /sys/bus/i2c/devices/i2c-9/new_device', +'echo as7816_64x_fan 0x68 > /sys/bus/i2c/devices/i2c-17/new_device', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4d > /sys/bus/i2c/devices/i2c-17/new_device', +'echo lm75 0x4e > /sys/bus/i2c/devices/i2c-17/new_device', +'echo cpld_as7816 0x60 > /sys/bus/i2c/devices/i2c-19/new_device', +'echo cpld_plain 0x62 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo cpld_plain 0x64 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo cpld_plain 0x66 > /sys/bus/i2c/devices/i2c-22/new_device'] + +def i2c_order_check(): + return 0 + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo as7816_64x_port"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0076", 0) + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0076", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/common/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/common/modules/accton_i2c_cpld.c new file mode 100644 index 000000000000..aae4e5538b63 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/common/modules/accton_i2c_cpld.c @@ -0,0 +1,887 @@ +/* + * A hwmon driver for the accton_i2c_cpld + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define MAX_PORT_NUM 64 +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define I2C_ADDR_CPLD1 0x60 +#define I2C_ADDR_CPLD2 0x62 +#define I2C_ADDR_CPLD3 0x64 +#define CPLD_ADDRS {I2C_ADDR_CPLD1, I2C_ADDR_CPLD2, I2C_ADDR_CPLD3} + + +/* + * Number of additional attribute pointers to allocate + * with each call to krealloc + */ +#define ATTR_ALLOC_SIZE 1 /*For last attribute which is NUll.*/ + +#define NAME_SIZE 24 +#define MAX_RESP_LENGTH 48 + +typedef ssize_t (*show_func)( struct device *dev, + struct device_attribute *attr, + char *buf); +typedef ssize_t (*store_func)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); + +enum models { + AS7712_32X, + AS7716_32X, + AS7816_64X, + AS7312_54X, + PLAIN_CPLD, /*No attribute but add i2c addr to the list.*/ + NUM_MODEL +}; + +enum sfp_func { + HAS_SFP = 1<<0 , + HAS_QSFP = 1<<1 , +}; + +enum common_attrs { + CMN_VERSION, + CMN_ACCESS, + CMN_PRESENT_ALL, + NUM_COMMON_ATTR +}; + +enum sfp_attrs { + SFP_PRESENT, + SFP_RESET, + SFP_LP_MODE, + NUM_SFP_ATTR +}; + +struct cpld_sensor { + struct cpld_sensor *next; + char name[NAME_SIZE+1]; /* sysfs sensor name */ + struct device_attribute attribute; + bool update; /* runtime sensor update needed */ + int data; /* Sensor data. Negative if there was a read error */ + + u8 reg; /* register */ + u8 mask; /* bit mask */ + bool invert; /* inverted value*/ + +}; + +#define to_cpld_sensor(_attr) \ + container_of(_attr, struct cpld_sensor, attribute) + +struct cpld_data { + struct device *dev; + struct device *hwmon_dev; + + int num_attributes; + struct attribute_group group; + + enum models model; + struct cpld_sensor *sensors; + struct mutex update_lock; + bool valid; + unsigned long last_updated; /* in jiffies */ + + int attr_index; + u16 sfp_num; + u8 sfp_types; + struct model_attrs *cmn_attr; +}; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + + +struct base_attrs { + const char *name; + umode_t mode; + show_func get; + store_func set; +}; + +struct attrs { + int reg; + bool invert; + struct base_attrs *base; +}; + +struct model_attrs { + struct attrs **cmn; + struct attrs **portly; +}; + + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t show_presnet_all(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t set_1bit(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_byte(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +int accton_i2c_cpld_read(u8 cpld_addr, u8 reg); +int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + + +struct base_attrs common_attrs[NUM_COMMON_ATTR] = +{ + [CMN_VERSION] = {"version", S_IRUGO, show_bit, NULL}, + [CMN_ACCESS] = {"access", S_IWUSR, NULL, set_byte}, + [CMN_PRESENT_ALL] = {"module_present_all", S_IRUGO, show_presnet_all, NULL}, +}; + +struct attrs as7712_common[] = { + [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]}, + [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]}, + [CMN_PRESENT_ALL] = {0x30, false, &common_attrs[CMN_PRESENT_ALL]}, +}; +struct attrs as7816_common[] = { + [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]}, + [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]}, + [CMN_PRESENT_ALL] = {0x30, false, &common_attrs[CMN_PRESENT_ALL]}, +}; +struct attrs as7312_common[] = { + [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]}, + [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]}, + [CMN_PRESENT_ALL] = {-1, false, &common_attrs[CMN_PRESENT_ALL]}, +}; +struct attrs plain_common[] = { + [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]}, +}; + +struct base_attrs portly_attrs[] = +{ + [SFP_PRESENT] = {"module_present", S_IRUGO, show_bit, NULL}, + [SFP_RESET] = {"module_reset", S_IRUGO|S_IWUGO, show_bit, set_1bit}, +}; + +struct attrs as7712_port[] = { + {0x30, true, &portly_attrs[SFP_PRESENT]}, + {0x04, true, &portly_attrs[SFP_RESET]}, +}; + +struct attrs as7816_port[] = { + {0x70, true, &portly_attrs[SFP_PRESENT]}, + {0x40, true, &portly_attrs[SFP_RESET]}, +}; + +struct attrs *as7712_cmn_list[] = { + &as7712_common[CMN_VERSION], + &as7712_common[CMN_ACCESS], + &as7712_common[CMN_PRESENT_ALL], + NULL +}; + +struct attrs *as7816_cmn_list[] = { + &as7816_common[CMN_VERSION], + &as7816_common[CMN_ACCESS], + &as7816_common[CMN_PRESENT_ALL], + NULL +}; + +struct attrs *as7312_cmn_list[] = { + &as7312_common[CMN_VERSION], + &as7312_common[CMN_ACCESS], + &as7312_common[CMN_PRESENT_ALL], + NULL +}; + +struct attrs *plain_cmn_list[] = { + &plain_common[CMN_VERSION], + NULL +}; + +struct attrs *as7712_port_list[] = { + &as7712_port[SFP_PRESENT], + &as7712_port[SFP_RESET], + NULL +}; +struct attrs *as7816_port_list[] = { + &as7816_port[SFP_PRESENT], + &as7816_port[SFP_RESET], + NULL +}; + +struct model_attrs models_attr[NUM_MODEL] = { + {.cmn = as7712_cmn_list, .portly=as7712_port_list}, + {.cmn = as7712_cmn_list, .portly=as7712_port_list}, /*7716's as 7712*/ + {.cmn = as7816_cmn_list, .portly=as7816_port_list}, + {.cmn = as7312_cmn_list, .portly=as7816_port_list}, + {.cmn = plain_cmn_list, .portly=NULL}, +}; + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; +/* Addresses scanned for accton_i2c_cpld + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static int get_sfp_spec(int model, u16 *num, u8 *types) +{ + switch (model) { + case AS7712_32X: + case AS7716_32X: + *num = 32; + *types = HAS_QSFP; + break; + case AS7816_64X: + *num = 64; + *types = HAS_QSFP; + break; + case AS7312_54X: + *num = 54; + *types = HAS_QSFP|HAS_SFP; + default: + *types = 0; + *num = 0; + break; + } + + return 0; +} + +static int get_present_reg(int model, u8 port, u8 *cpld_addr, u8 *reg, u8 *num) +{ + u8 cpld_address[] = CPLD_ADDRS; + + switch (model) { + case AS7312_54X: + if (port < 48) { + *cpld_addr = cpld_address[1 + port/24]; + *reg = 0x09 + (port%24)/8; + *num = 8; + } + else + { + *reg = 0x18; + *num = 4; + *cpld_addr = ( port < 52)? cpld_address[1]: cpld_address[2]; + } + break; + default: + return -EINVAL; + } +} + + +/*Assume the bits for ports are listed in-a-row.*/ +static int get_reg_bit(u8 reg_start, int port, + u8 *reg ,u8 *mask) +{ + *reg = reg_start + ((port)/8); + *mask = 1 << ((port)%8); + + return 0; +} + +static int cpld_write_internal( + struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + + +/*Turn a numberic array into string with " " between each element. + * e.g., {0x11, 0x33, 0xff, 0xf1} => "11 33 ff f1" + */ +static ssize_t array_stringify(char *buf, u8 *input, size_t size) { + + int i; + char t[MAX_RESP_LENGTH+1]; + + buf[0] = '\0'; + for (i = 0; i < size; i++) { + snprintf(t, MAX_RESP_LENGTH, "%x ", input[i]); + strncat(buf, t, MAX_RESP_LENGTH); + } + + if (strlen(buf) > 0) + buf[strlen(buf)-1] = '\0'; /*Remove tailing blank*/ + + return snprintf(buf, MAX_RESP_LENGTH, "%s\n", buf); +} + +static ssize_t show_presnet_all_distinct(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 i, value, reg; + u8 cpld_addr, num; + u8 _value[8]; + u64 *values = (u64 *)_value; + + values = 0; + mutex_lock(&data->update_lock); + while(i < data->sfp_num) + { + get_present_reg(data->model, i, &cpld_addr, ®, &num); + if(cpld_addr == client->addr) + value = cpld_read_internal(client, reg); + else + value = accton_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(value < 0)) { + goto exit; + } + + *values |= (value&((1<<(num))-1)) << i; + i += num; + } + mutex_unlock(&data->update_lock); + + *values = cpu_to_le64(*values); + return array_stringify(buf, _value, i); +exit: + mutex_unlock(&data->update_lock); + return value; +} + +static ssize_t show_presnet_all(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + struct cpld_sensor *sensor = to_cpld_sensor(devattr); + u8 i, values[MAX_RESP_LENGTH/8]; + + if (sensor->reg < 0) { + return show_presnet_all_distinct(dev, devattr, buf); + } + + mutex_lock(&data->update_lock); + for (i = 0; i < ((data->sfp_num+7)/8); i++) { + values[i] = cpld_read_internal(client, sensor->reg + i); + if (unlikely(values[i] < 0)) { + goto exit; + } + } + mutex_unlock(&data->update_lock); + return array_stringify(buf, values, i); + +exit: + mutex_unlock(&data->update_lock); + return values[i]; +} + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int value; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + struct cpld_sensor *sensor = to_cpld_sensor(devattr); + + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, sensor->reg); + value = value & sensor->mask; + if (sensor->invert) + value = !value; + mutex_unlock(&data->update_lock); + + return snprintf(buf, PAGE_SIZE, "%x\n", value); +} + +static ssize_t set_1bit(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + long is_reset; + int value, status; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + struct cpld_sensor *sensor = to_cpld_sensor(devattr); + u8 cpld_bit, reg; + + status = kstrtol(buf, 10, &is_reset); + if (status) { + return status; + } + reg = sensor->reg; + cpld_bit = sensor->mask; + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + if (sensor->invert) + is_reset = !is_reset; + + if (is_reset) { + value |= cpld_bit; + } + else { + value &= ~cpld_bit; + } + + status = cpld_write_internal(client, reg, value); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_byte(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + return access(dev, da, buf, count); +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void accton_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = + kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", + client->addr); + return; + } + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void accton_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int cpld_add_attribute(struct cpld_data *data, struct attribute *attr) +{ + int new_max_attrs = ++data->num_attributes + ATTR_ALLOC_SIZE; + void *new_attrs = krealloc(data->group.attrs, + new_max_attrs * sizeof(void *), + GFP_KERNEL); + if (!new_attrs) + return -ENOMEM; + data->group.attrs = new_attrs; + + + data->group.attrs[data->num_attributes-1] = attr; + data->group.attrs[data->num_attributes] = NULL; + + return 0; +} + +static void cpld_dev_attr_init(struct device_attribute *dev_attr, + const char *name, umode_t mode, + show_func show, store_func store) +{ + sysfs_attr_init(&dev_attr->attr); + dev_attr->attr.name = name; + dev_attr->attr.mode = mode; + dev_attr->show = show; + dev_attr->store = store; +} + +static struct cpld_sensor * add_sensor(struct cpld_data *data, + const char *name, + u8 reg, u8 mask, bool invert, + bool update, umode_t mode, + show_func get, store_func set) +{ + struct cpld_sensor *sensor; + struct device_attribute *a; + + sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return NULL; + a = &sensor->attribute; + + snprintf(sensor->name, sizeof(sensor->name), name); + sensor->reg = reg; + sensor->mask = mask; + sensor->update = update; + sensor->invert = invert; + cpld_dev_attr_init(a, sensor->name, + mode, + get, set); + + if (cpld_add_attribute(data, &a->attr)) + return NULL; + + sensor->next = data->sensors; + data->sensors = sensor; + + return sensor; +} + +static int add_attributes_cmn(struct cpld_data *data, struct attrs **cmn) +{ + u8 reg, i ; + bool invert; + struct attrs *a; + struct base_attrs *b; + + if (NULL == cmn) + return -1; + + for (i = 0; cmn[i]; i++) + { + a = cmn[i]; + + reg = a->reg; + invert = a->invert; + + b = a->base; + if (NULL == b) + break; + + if (add_sensor(data, b->name, + reg, 0xff, invert, + true, b->mode, + b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + return 0; +} + +static int add_attributes_portly(struct cpld_data *data, struct attrs **pa) +{ + char name[NAME_SIZE+1]; + int i, j; + u8 reg, mask, invert; + struct attrs *a; + struct base_attrs *b; + + if (NULL == pa) + return -1; + + + for (i = 0; pa[i]; i++) { + a = pa[i]; + + invert = a->invert; + b = a->base; + if (b == NULL) + break; + + for (j = 0; j < data->sfp_num; j++) + { + snprintf(name, NAME_SIZE, "%s_%d", b->name, j+1); + get_reg_bit(a->reg, j, ®, &mask); + + if (add_sensor(data, name, reg, mask, invert, + true, b->mode, b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + } + return 0; +} + +static int add_attributes(struct i2c_client *client, + struct cpld_data *data) +{ + struct model_attrs *m = data->cmn_attr; + + if (m == NULL) + return -EINVAL; + + /* Common attributes.*/ + add_attributes_cmn(data, m->cmn); + + /* Port-wise attributes.*/ + add_attributes_portly(data, m->portly); + + return 0; +} + +static int accton_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct cpld_data *data = NULL; + struct device *dev = &client->dev; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + return -EIO; + } + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + data->model = dev_id->driver_data; + data->cmn_attr = &models_attr[data->model]; + get_sfp_spec(data->model, &data->sfp_num, &data->sfp_types); + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->dev = dev; + dev_info(dev, "chip found\n"); + + status = add_attributes(client, data); + if (status) + goto out_kfree; + + /* + * If there are no attributes, something is wrong. + * Bail out instead of trying to register nothing. + */ + if (!data->num_attributes) { + dev_err(dev, "No attributes found\n"); + status = -ENODEV; + goto out_kfree; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->group); + if (status) { + goto out_kfree; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + accton_i2c_cpld_add_client(client); + dev_info(dev, "%s: cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->group); +out_kfree: + kfree(data->group.attrs); + return status; + +} + +static int accton_i2c_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, &data->group); + kfree(data->group.attrs); + accton_i2c_cpld_remove_client(client); + return 0; +} + +int accton_i2c_cpld_read(u8 cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_read); + +int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_write); + + +static const struct i2c_device_id accton_i2c_cpld_id[] = { + { "cpld_as7712", AS7712_32X}, + { "cpld_as7716", AS7716_32X}, + { "cpld_as7816", AS7816_64X}, + { "cpld_as7312", AS7312_54X}, + { "cpld_plain", PLAIN_CPLD}, + { }, +}; +MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id); + +static struct i2c_driver accton_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "accton_i2c_cpld", + }, + .probe = accton_i2c_cpld_probe, + .remove = accton_i2c_cpld_remove, + .id_table = accton_i2c_cpld_id, + .address_list = normal_i2c, +}; + + +static int __init accton_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&accton_i2c_cpld_driver); +} + +static void __exit accton_i2c_cpld_exit(void) +{ + i2c_del_driver(&accton_i2c_cpld_driver); +} + +module_init(accton_i2c_cpld_init); +module_exit(accton_i2c_cpld_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_i2c_cpld driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/common/modules/accton_pmbus_3y.c b/platform/broadcom/sonic-platform-modules-accton/common/modules/accton_pmbus_3y.c new file mode 100644 index 000000000000..ed176189cdcd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/common/modules/accton_pmbus_3y.c @@ -0,0 +1,1978 @@ +/* + * Hardware monitoring driver for 3Y power devices. + * + * Copyright (C) 2018 Accton Technology Corporation. + * Roy Lee + * + * Based on pmbus.c, pmbus.h and pmbus_core.c. + * Copyright 2012 Guenter Roeck/Ericsson AB. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pmbus.h" + + +enum chips { + YM2651, + YM2401, + YM2851, + LIMITED_CHIPS, +}; + + +/* + * Number of additional attribute pointers to allocate + * with each call to krealloc + */ +#define PMBUS_ATTR_ALLOC_SIZE 32 + +/* + * Index into status register array, per status register group + */ +#define PB_STATUS_BASE 0 +#define PB_STATUS_VOUT_BASE (PB_STATUS_BASE + PMBUS_PAGES) +#define PB_STATUS_IOUT_BASE (PB_STATUS_VOUT_BASE + PMBUS_PAGES) +#define PB_STATUS_FAN_BASE (PB_STATUS_IOUT_BASE + PMBUS_PAGES) +#define PB_STATUS_FAN34_BASE (PB_STATUS_FAN_BASE + PMBUS_PAGES) +#define PB_STATUS_TEMP_BASE (PB_STATUS_FAN34_BASE + PMBUS_PAGES) +#define PB_STATUS_INPUT_BASE (PB_STATUS_TEMP_BASE + PMBUS_PAGES) +#define PB_STATUS_VMON_BASE (PB_STATUS_INPUT_BASE + 1) + +#define PB_NUM_STATUS_REG (PB_STATUS_VMON_BASE + 1) + +#define PMBUS_NAME_SIZE 24 + +struct pmbus_sensor { + struct pmbus_sensor *next; + char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */ + struct device_attribute attribute; + u8 page; /* page number */ + u16 reg; /* register */ + enum pmbus_sensor_classes class; /* sensor class */ + bool update; /* runtime sensor update needed */ + int data; /* Sensor data. + Negative if there was a read error */ +}; +#define to_pmbus_sensor(_attr) \ + container_of(_attr, struct pmbus_sensor, attribute) + +struct pmbus_boolean { + char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */ + struct sensor_device_attribute attribute; + struct pmbus_sensor *s1; + struct pmbus_sensor *s2; +}; +#define to_pmbus_boolean(_attr) \ + container_of(_attr, struct pmbus_boolean, attribute) + +struct pmbus_label { + char name[PMBUS_NAME_SIZE]; /* sysfs label name */ + struct device_attribute attribute; + char label[PMBUS_NAME_SIZE]; /* label */ +}; +#define to_pmbus_label(_attr) \ + container_of(_attr, struct pmbus_label, attribute) + +struct pmbus_data { + struct device *dev; + struct device *hwmon_dev; + + u32 flags; /* from platform data */ + + int exponent[PMBUS_PAGES]; + /* linear mode: exponent for output voltages */ + + const struct pmbus_driver_info *info; + + int max_attributes; + int num_attributes; + struct attribute_group group; + const struct attribute_group *groups[2]; + + struct pmbus_sensor *sensors; + + struct mutex update_lock; + bool valid; + unsigned long last_updated; /* in jiffies */ + + /* + * A single status register covers multiple attributes, + * so we keep them all together. + */ + u8 status[PB_NUM_STATUS_REG]; + u8 status_register; + + u8 currpage; + bool linear_16; +}; + + +static int limited_models(const struct i2c_device_id *id); + +int _pmbus_set_page(struct i2c_client *client, u8 page) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int rv = 0; + int newpage; + + if (page != data->currpage) { + rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); + newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); + if (newpage != page) + rv = -EIO; + else + data->currpage = page; + } + return 0; +} + +/* + * _pmbus_write_byte() is similar to pmbus_write_byte(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_write_byte(struct i2c_client *client, int page, u8 value) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + int status; + + if (info->write_byte) { + status = info->write_byte(client, page, value); + if (status != -ENODATA) + return status; + } + /*Ignore page*/ + return i2c_smbus_write_byte(client, value);; +} + +/* + * _pmbus_write_word_data() is similar to pmbus_write_word_data(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_write_word_data(struct i2c_client *client, int page, int reg, + u16 word) +{ + if (reg >= PMBUS_VIRT_BASE) + return -ENXIO; + /*Ignore page*/ + return i2c_smbus_write_word_data(client, reg, word); +} + +/* + * _pmbus_read_word_data() is similar to pmbus_read_word_data(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg) +{ + /*Ignore page*/ + return i2c_smbus_read_word_data(client, reg);; +} + +/* + * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg) +{ + if (reg >= PMBUS_VIRT_BASE) + return -ENXIO; + + /*Ignore page*/ + return i2c_smbus_read_byte_data(client, reg); +} + +static void pmbus_clear_fault_page(struct i2c_client *client, int page) +{ + _pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); +} + + +static int pmbus_check_status_cml(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int status, status2; + + status = _pmbus_read_byte_data(client, -1, data->status_register); + if (status < 0 || (status & PB_STATUS_CML)) { + status2 = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML); + if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND)) + return -EIO; + } + return 0; +} + +static bool pmbus_check_register(struct i2c_client *client, + int (*func)(struct i2c_client *client, + int page, int reg), + int page, int reg) +{ + int rv; + struct pmbus_data *data = i2c_get_clientdata(client); + + if((data->flags & PMBUS_SKIP_STATUS_CHECK)) + return 1; + + rv = func(client, page, reg); + if (rv >= 0) + rv = pmbus_check_status_cml(client); + pmbus_clear_fault_page(client, -1); + return rv >= 0; +} + +static struct _pmbus_status { + u32 func; + u16 base; + u16 reg; +} pmbus_status[] = { + { PMBUS_HAVE_STATUS_VOUT, PB_STATUS_VOUT_BASE, PMBUS_STATUS_VOUT }, + { PMBUS_HAVE_STATUS_IOUT, PB_STATUS_IOUT_BASE, PMBUS_STATUS_IOUT }, + { PMBUS_HAVE_STATUS_TEMP, PB_STATUS_TEMP_BASE, + PMBUS_STATUS_TEMPERATURE + }, + { PMBUS_HAVE_STATUS_FAN12, PB_STATUS_FAN_BASE, PMBUS_STATUS_FAN_12 }, + { PMBUS_HAVE_STATUS_FAN34, PB_STATUS_FAN34_BASE, PMBUS_STATUS_FAN_34 }, +}; + +void _pmbus_clear_faults(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int i; + + for (i = 0; i < data->info->pages; i++) + pmbus_clear_fault_page(client, i); +} +static struct pmbus_data *pmbus_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev->parent); + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + struct pmbus_sensor *sensor; + + mutex_lock(&data->update_lock); + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { + int i, j; + + for (i = 0; i < info->pages; i++) { + data->status[PB_STATUS_BASE + i] + = _pmbus_read_byte_data(client, i, + data->status_register); + for (j = 0; j < ARRAY_SIZE(pmbus_status); j++) { + struct _pmbus_status *s = &pmbus_status[j]; + + if (!(info->func[i] & s->func)) + continue; + data->status[s->base + i] + = _pmbus_read_byte_data(client, i, + s->reg); + } + } + + if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) + data->status[PB_STATUS_INPUT_BASE] + = _pmbus_read_byte_data(client, 0, + PMBUS_STATUS_INPUT); + + if (info->func[0] & PMBUS_HAVE_STATUS_VMON) + data->status[PB_STATUS_VMON_BASE] + = _pmbus_read_byte_data(client, 0, + PMBUS_VIRT_STATUS_VMON); + + for (sensor = data->sensors; sensor; sensor = sensor->next) { + if (!data->valid || sensor->update) + sensor->data + = _pmbus_read_word_data(client, + sensor->page, + sensor->reg); + } + _pmbus_clear_faults(client); + data->last_updated = jiffies; + data->valid = 1; + } + mutex_unlock(&data->update_lock); + return data; +} + +/* + * Convert linear sensor values to milli- or micro-units + * depending on sensor type. + */ +static long pmbus_reg2data_linear(struct pmbus_data *data, + struct pmbus_sensor *sensor) +{ + s16 exponent; + s32 mantissa; + long val; + + /* LINEAR16 */ + if ( data->linear_16 && + sensor->class == PSC_VOLTAGE_OUT) { + exponent = data->exponent[sensor->page]; + mantissa = (u16) sensor->data; + } else + { /* LINEAR11 */ + exponent = ((s16)sensor->data) >> 11; + mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5; + } + + val = mantissa; + + /* scale result to milli-units for all sensors except fans */ + if (sensor->class != PSC_FAN) + val = val * 1000L; + + /* scale result to micro-units for power sensors */ + if (sensor->class == PSC_POWER) + val = val * 1000L; + + if (exponent >= 0) + val <<= exponent; + else + val >>= -exponent; + + return val; +} + +/* + * Convert direct sensor values to milli- or micro-units + * depending on sensor type. + */ +static long pmbus_reg2data_direct(struct pmbus_data *data, + struct pmbus_sensor *sensor) +{ + long val = (s16) sensor->data; + long m, b, R; + + m = data->info->m[sensor->class]; + b = data->info->b[sensor->class]; + R = data->info->R[sensor->class]; + + if (m == 0) + return 0; + + /* X = 1/m * (Y * 10^-R - b) */ + R = -R; + /* scale result to milli-units for everything but fans */ + if (sensor->class != PSC_FAN) { + R += 3; + b *= 1000; + } + + /* scale result to micro-units for power sensors */ + if (sensor->class == PSC_POWER) { + R += 3; + b *= 1000; + } + + while (R > 0) { + val *= 10; + R--; + } + while (R < 0) { + val = DIV_ROUND_CLOSEST(val, 10); + R++; + } + + return (val - b) / m; +} + +/* + * Convert VID sensor values to milli- or micro-units + * depending on sensor type. + * We currently only support VR11. + */ +static long pmbus_reg2data_vid(struct pmbus_data *data, + struct pmbus_sensor *sensor) +{ + long val = sensor->data; + + if (val < 0x02 || val > 0xb2) + return 0; + return DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100); +} + +static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor) +{ + long val; + + switch (data->info->format[sensor->class]) { + case direct: + val = pmbus_reg2data_direct(data, sensor); + break; + case vid: + val = pmbus_reg2data_vid(data, sensor); + break; + case linear: + default: + val = pmbus_reg2data_linear(data, sensor); + break; + } + return val; +} + +#define MAX_MANTISSA (1023 * 1000) +#define MIN_MANTISSA (511 * 1000) + +static u16 pmbus_data2reg_linear(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + s16 exponent = 0, mantissa; + bool negative = false; + + /* simple case */ + if (val == 0) + return 0; + + if (data->linear_16 && + sensor->class == PSC_VOLTAGE_OUT) { + /* LINEAR16 does not support negative voltages */ + if (val < 0) + return 0; + + /* + * For a static exponents, we don't have a choice + * but to adjust the value to it. + */ + if (data->exponent[sensor->page] < 0) + val <<= -data->exponent[sensor->page]; + else + val >>= data->exponent[sensor->page]; + val = DIV_ROUND_CLOSEST(val, 1000); + return val & 0xffff; + } + + if (val < 0) { + negative = true; + val = -val; + } + + /* Power is in uW. Convert to mW before converting. */ + if (sensor->class == PSC_POWER) + val = DIV_ROUND_CLOSEST(val, 1000L); + + /* + * For simplicity, convert fan data to milli-units + * before calculating the exponent. + */ + if (sensor->class == PSC_FAN) + val = val * 1000; + + /* Reduce large mantissa until it fits into 10 bit */ + while (val >= MAX_MANTISSA && exponent < 15) { + exponent++; + val >>= 1; + } + /* Increase small mantissa to improve precision */ + while (val < MIN_MANTISSA && exponent > -15) { + exponent--; + val <<= 1; + } + + /* Convert mantissa from milli-units to units */ + mantissa = DIV_ROUND_CLOSEST(val, 1000); + + /* Ensure that resulting number is within range */ + if (mantissa > 0x3ff) + mantissa = 0x3ff; + + /* restore sign */ + if (negative) + mantissa = -mantissa; + + /* Convert to 5 bit exponent, 11 bit mantissa */ + return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800); +} + +static u16 pmbus_data2reg_direct(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + long m, b, R; + + m = data->info->m[sensor->class]; + b = data->info->b[sensor->class]; + R = data->info->R[sensor->class]; + + /* Power is in uW. Adjust R and b. */ + if (sensor->class == PSC_POWER) { + R -= 3; + b *= 1000; + } + + /* Calculate Y = (m * X + b) * 10^R */ + if (sensor->class != PSC_FAN) { + R -= 3; /* Adjust R and b for data in milli-units */ + b *= 1000; + } + val = val * m + b; + + while (R > 0) { + val *= 10; + R--; + } + while (R < 0) { + val = DIV_ROUND_CLOSEST(val, 10); + R++; + } + + return val; +} + +static u16 pmbus_data2reg_vid(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + val = clamp_val(val, 500, 1600); + + return 2 + DIV_ROUND_CLOSEST((1600 - val) * 100, 625); +} + +static u16 pmbus_data2reg(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + u16 regval; + + switch (data->info->format[sensor->class]) { + case direct: + regval = pmbus_data2reg_direct(data, sensor, val); + break; + case vid: + regval = pmbus_data2reg_vid(data, sensor, val); + break; + case linear: + default: + regval = pmbus_data2reg_linear(data, sensor, val); + break; + } + return regval; +} + +/* + * Return boolean calculated from converted data. + * defines a status register index and mask. + * The mask is in the lower 8 bits, the register index is in bits 8..23. + * + * The associated pmbus_boolean structure contains optional pointers to two + * sensor attributes. If specified, those attributes are compared against each + * other to determine if a limit has been exceeded. + * + * If the sensor attribute pointers are NULL, the function returns true if + * (status[reg] & mask) is true. + * + * If sensor attribute pointers are provided, a comparison against a specified + * limit has to be performed to determine the boolean result. + * In this case, the function returns true if v1 >= v2 (where v1 and v2 are + * sensor values referenced by sensor attribute pointers s1 and s2). + * + * To determine if an object exceeds upper limits, specify = . + * To determine if an object exceeds lower limits, specify = . + * + * If a negative value is stored in any of the referenced registers, this value + * reflects an error code which will be returned. + */ +static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b, + int index) +{ + struct pmbus_sensor *s1 = b->s1; + struct pmbus_sensor *s2 = b->s2; + u16 reg = (index >> 8) & 0xffff; + u8 mask = index & 0xff; + int ret, status; + u8 regval; + + status = data->status[reg]; + if (status < 0) + return status; + + regval = status & mask; + if (!s1 && !s2) { + ret = !!regval; + } else if (!s1 || !s2) { + WARN(1, "Bad boolean descriptor %p: s1=%p, s2=%p\n", b, s1, s2); + return 0; + } else { + long v1, v2; + + if (s1->data < 0) + return s1->data; + if (s2->data < 0) + return s2->data; + + v1 = pmbus_reg2data(data, s1); + v2 = pmbus_reg2data(data, s2); + ret = !!(regval && v1 >= v2); + } + return ret; +} + +static ssize_t pmbus_show_boolean(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct pmbus_boolean *boolean = to_pmbus_boolean(attr); + struct pmbus_data *data = pmbus_update_device(dev); + int val; + + val = pmbus_get_boolean(data, boolean, attr->index); + if (val < 0) { + return snprintf(buf, PAGE_SIZE, "%d\n", 1); + } + return snprintf(buf, PAGE_SIZE, "%d\n", val); +} + +static ssize_t pmbus_show_sensor(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct pmbus_data *data = pmbus_update_device(dev); + struct pmbus_sensor *sensor = to_pmbus_sensor(devattr); + + + if (sensor->data < 0) { + return snprintf(buf, PAGE_SIZE, "%d\n", 0); + } + + + return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor)); +} + +static ssize_t pmbus_set_sensor(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev->parent); + struct pmbus_data *data = i2c_get_clientdata(client); + struct pmbus_sensor *sensor = to_pmbus_sensor(devattr); + ssize_t rv = count; + long val = 0; + int ret; + u16 regval; + + if (kstrtol(buf, 10, &val) < 0) + return -EINVAL; + + mutex_lock(&data->update_lock); + regval = pmbus_data2reg(data, sensor, val); + ret = _pmbus_write_word_data(client, sensor->page, sensor->reg, regval); + if (ret < 0) + rv = ret; + else + sensor->data = regval; + mutex_unlock(&data->update_lock); + return rv; +} + +static ssize_t pmbus_show_label(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct pmbus_label *label = to_pmbus_label(da); + + return snprintf(buf, PAGE_SIZE, "%s\n", label->label); +} + +static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr) +{ + if (data->num_attributes >= data->max_attributes - 1) { + int new_max_attrs = data->max_attributes + PMBUS_ATTR_ALLOC_SIZE; + void *new_attrs = krealloc(data->group.attrs, + new_max_attrs * sizeof(void *), + GFP_KERNEL); + if (!new_attrs) + return -ENOMEM; + data->group.attrs = new_attrs; + data->max_attributes = new_max_attrs; + } + + + + data->group.attrs[data->num_attributes++] = attr; + data->group.attrs[data->num_attributes] = NULL; + return 0; +} + +static void pmbus_dev_attr_init(struct device_attribute *dev_attr, + const char *name, + umode_t mode, + ssize_t (*show)(struct device *dev, + struct device_attribute *attr, + char *buf), + ssize_t (*store)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count)) +{ + sysfs_attr_init(&dev_attr->attr); + dev_attr->attr.name = name; + dev_attr->attr.mode = mode; + dev_attr->show = show; + dev_attr->store = store; +} + +static void pmbus_attr_init(struct sensor_device_attribute *a, + const char *name, + umode_t mode, + ssize_t (*show)(struct device *dev, + struct device_attribute *attr, + char *buf), + ssize_t (*store)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count), + int idx) +{ + pmbus_dev_attr_init(&a->dev_attr, name, mode, show, store); + a->index = idx; +} + +static int pmbus_add_boolean(struct pmbus_data *data, + const char *name, const char *type, int seq, + struct pmbus_sensor *s1, + struct pmbus_sensor *s2, + u16 reg, u8 mask) +{ + struct pmbus_boolean *boolean; + struct sensor_device_attribute *a; + + boolean = devm_kzalloc(data->dev, sizeof(*boolean), GFP_KERNEL); + if (!boolean) + return -ENOMEM; + + a = &boolean->attribute; + + snprintf(boolean->name, sizeof(boolean->name), "%s%d_%s", + name, seq, type); + boolean->s1 = s1; + boolean->s2 = s2; + pmbus_attr_init(a, boolean->name, S_IRUGO, pmbus_show_boolean, NULL, + (reg << 8) | mask); + + return pmbus_add_attribute(data, &a->dev_attr.attr); +} + +static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data, + const char *name, const char *type, + int seq, int page, int reg, + enum pmbus_sensor_classes class, + bool update, bool readonly) +{ + struct pmbus_sensor *sensor; + struct device_attribute *a; + + sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return NULL; + a = &sensor->attribute; + + snprintf(sensor->name, sizeof(sensor->name), "%s%d_%s", + name, seq, type); + sensor->page = page; + sensor->reg = reg; + sensor->class = class; + sensor->update = update; + pmbus_dev_attr_init(a, sensor->name, + readonly ? S_IRUGO : S_IRUGO | S_IWUSR, + pmbus_show_sensor, pmbus_set_sensor); + + if (pmbus_add_attribute(data, &a->attr)) + return NULL; + + sensor->next = data->sensors; + data->sensors = sensor; + + return sensor; +} + +static int pmbus_add_label(struct pmbus_data *data, + const char *name, int seq, + const char *lstring, int index) +{ + struct pmbus_label *label; + struct device_attribute *a; + + label = devm_kzalloc(data->dev, sizeof(*label), GFP_KERNEL); + if (!label) + return -ENOMEM; + + a = &label->attribute; + + snprintf(label->name, sizeof(label->name), "%s%d_label", name, seq); + if (!index) + strncpy(label->label, lstring, sizeof(label->label) - 1); + else + snprintf(label->label, sizeof(label->label), "%s%d", lstring, + index); + + pmbus_dev_attr_init(a, label->name, S_IRUGO, pmbus_show_label, NULL); + return pmbus_add_attribute(data, &a->attr); +} + +/* + * Search for attributes. Allocate sensors, booleans, and labels as needed. + */ + +/* + * The pmbus_limit_attr structure describes a single limit attribute + * and its associated alarm attribute. + */ +struct pmbus_limit_attr { + u16 reg; /* Limit register */ + u16 sbit; /* Alarm attribute status bit */ + bool update; /* True if register needs updates */ + bool low; /* True if low limit; for limits with compare + functions only */ + const char *attr; /* Attribute name */ + const char *alarm; /* Alarm attribute name */ +}; + +/* + * The pmbus_sensor_attr structure describes one sensor attribute. This + * description includes a reference to the associated limit attributes. + */ +struct pmbus_sensor_attr { + u16 reg; /* sensor register */ + u8 gbit; /* generic status bit */ + u8 nlimit; /* # of limit registers */ + enum pmbus_sensor_classes class;/* sensor class */ + const char *label; /* sensor label */ + bool paged; /* true if paged sensor */ + bool update; /* true if update needed */ + bool compare; /* true if compare function needed */ + u32 func; /* sensor mask */ + u32 sfunc; /* sensor status mask */ + int sbase; /* status base register */ + const struct pmbus_limit_attr *limit;/* limit registers */ +}; + +/* + * Add a set of limit attributes and, if supported, the associated + * alarm attributes. + * returns 0 if no alarm register found, 1 if an alarm register was found, + * < 0 on errors. + */ +static int pmbus_add_limit_attrs(struct i2c_client *client, + struct pmbus_data *data, + const struct pmbus_driver_info *info, + const char *name, int index, int page, + struct pmbus_sensor *base, + const struct pmbus_sensor_attr *attr) +{ + const struct pmbus_limit_attr *l = attr->limit; + int nlimit = attr->nlimit; + int have_alarm = 0; + int i, ret; + struct pmbus_sensor *curr; + + for (i = 0; i < nlimit; i++) { + if (_pmbus_check_word_register(client, page, l->reg)) + { + curr = pmbus_add_sensor(data, name, l->attr, index, + page, l->reg, attr->class, + attr->update || l->update, + false); + if (!curr) + return -ENOMEM; + if (l->sbit && (info->func[page] & attr->sfunc)) { + ret = pmbus_add_boolean(data, name, + l->alarm, index, + attr->compare ? l->low ? curr : base + : NULL, + attr->compare ? l->low ? base : curr + : NULL, + attr->sbase + page, l->sbit); + if (ret) + return ret; + have_alarm = 1; + } + } + l++; + } + return have_alarm; +} + +bool _pmbus_check_byte_register(struct i2c_client *client, int page, int reg) +{ + return pmbus_check_register(client, _pmbus_read_byte_data, page, reg); +} + + +bool _pmbus_check_word_register(struct i2c_client *client, int page, int reg) +{ + return pmbus_check_register(client, _pmbus_read_word_data, page, reg); +} + +static int pmbus_add_sensor_attrs_one(struct i2c_client *client, + struct pmbus_data *data, + const struct pmbus_driver_info *info, + const char *name, + int index, int page, + const struct pmbus_sensor_attr *attr) +{ + struct pmbus_sensor *base; + int ret; + + if (attr->label) { + ret = pmbus_add_label(data, name, index, attr->label, + attr->paged ? page + 1 : 0); + if (ret) + return ret; + } + base = pmbus_add_sensor(data, name, "input", index, page, attr->reg, + attr->class, true, true); + + + if (!base) + return -ENOMEM; + + if (attr->sfunc) { + ret = pmbus_add_limit_attrs(client, data, info, name, + index, page, base, attr); + if (ret < 0) + return ret; + /* + * Add generic alarm attribute only if there are no individual + * alarm attributes, if there is a global alarm bit, and if + * the generic status register for this page is accessible. + */ + if (!ret && attr->gbit && + _pmbus_check_byte_register(client, page, + data->status_register)) { + ret = pmbus_add_boolean(data, name, "alarm", index, + NULL, NULL, + PB_STATUS_BASE + page, + attr->gbit); + if (ret) + return ret; + } + } + return 0; +} + +static int pmbus_add_sensor_attrs(struct i2c_client *client, + struct pmbus_data *data, + const char *name, + const struct pmbus_sensor_attr *attrs, + int nattrs) +{ + const struct pmbus_driver_info *info = data->info; + int index, i; + int ret; + + index = 1; + for (i = 0; i < nattrs; i++) { + int page, pages; + + pages = attrs->paged ? info->pages : 1; + for (page = 0; page < pages; page++) { + if (!(info->func[page] & attrs->func)) + continue; + ret = pmbus_add_sensor_attrs_one(client, data, info, + name, index, page, + attrs); + if (ret) + return ret; + index++; + } + attrs++; + } + return 0; +} + +static const struct pmbus_limit_attr vin_limit_attrs[] = { + { + .reg = PMBUS_VIN_UV_WARN_LIMIT, + .attr = "min", + .alarm = "min_alarm", + .sbit = PB_VOLTAGE_UV_WARNING, + }, { + .reg = PMBUS_VIN_UV_FAULT_LIMIT, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_VOLTAGE_UV_FAULT, + }, { + .reg = PMBUS_VIN_OV_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_VOLTAGE_OV_WARNING, + }, { + .reg = PMBUS_VIN_OV_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_VOLTAGE_OV_FAULT, + }, { + .reg = PMBUS_VIRT_READ_VIN_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_VIN_MIN, + .update = true, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_VIN_MAX, + .update = true, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_VIN_HISTORY, + .attr = "reset_history", + }, +}; + +static const struct pmbus_limit_attr vmon_limit_attrs[] = { + { + .reg = PMBUS_VIRT_VMON_UV_WARN_LIMIT, + .attr = "min", + .alarm = "min_alarm", + .sbit = PB_VOLTAGE_UV_WARNING, + }, { + .reg = PMBUS_VIRT_VMON_UV_FAULT_LIMIT, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_VOLTAGE_UV_FAULT, + }, { + .reg = PMBUS_VIRT_VMON_OV_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_VOLTAGE_OV_WARNING, + }, { + .reg = PMBUS_VIRT_VMON_OV_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_VOLTAGE_OV_FAULT, + } +}; + +static const struct pmbus_limit_attr vout_limit_attrs[] = { + { + .reg = PMBUS_VOUT_UV_WARN_LIMIT, + .attr = "min", + .alarm = "min_alarm", + .sbit = PB_VOLTAGE_UV_WARNING, + }, { + .reg = PMBUS_VOUT_UV_FAULT_LIMIT, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_VOLTAGE_UV_FAULT, + }, { + .reg = PMBUS_VOUT_OV_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_VOLTAGE_OV_WARNING, + }, { + .reg = PMBUS_VOUT_OV_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_VOLTAGE_OV_FAULT, + }, { + .reg = PMBUS_VIRT_READ_VOUT_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_VOUT_MIN, + .update = true, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_VOUT_MAX, + .update = true, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_VOUT_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_sensor_attr voltage_attributes[] = { + { + .reg = PMBUS_READ_VIN, + .class = PSC_VOLTAGE_IN, + .label = "vin", + .func = PMBUS_HAVE_VIN, + .sfunc = PMBUS_HAVE_STATUS_INPUT, + .sbase = PB_STATUS_INPUT_BASE, + .gbit = PB_STATUS_VIN_UV, + .limit = vin_limit_attrs, + .nlimit = ARRAY_SIZE(vin_limit_attrs), + }, { + .reg = PMBUS_VIRT_READ_VMON, + .class = PSC_VOLTAGE_IN, + .label = "vmon", + .func = PMBUS_HAVE_VMON, + .sfunc = PMBUS_HAVE_STATUS_VMON, + .sbase = PB_STATUS_VMON_BASE, + .limit = vmon_limit_attrs, + .nlimit = ARRAY_SIZE(vmon_limit_attrs), + }, { + .reg = PMBUS_READ_VCAP, + .class = PSC_VOLTAGE_IN, + .label = "vcap", + .func = PMBUS_HAVE_VCAP, + }, { + .reg = PMBUS_READ_VOUT, + .class = PSC_VOLTAGE_OUT, + .label = "vout", + .paged = true, + .func = PMBUS_HAVE_VOUT, + .sfunc = PMBUS_HAVE_STATUS_VOUT, + .sbase = PB_STATUS_VOUT_BASE, + .gbit = PB_STATUS_VOUT_OV, + .limit = vout_limit_attrs, + .nlimit = ARRAY_SIZE(vout_limit_attrs), + } +}; + +/* Current attributes */ + +static const struct pmbus_limit_attr iin_limit_attrs[] = { + { + .reg = PMBUS_IIN_OC_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_IIN_OC_WARNING, + }, { + .reg = PMBUS_IIN_OC_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_IIN_OC_FAULT, + }, { + .reg = PMBUS_VIRT_READ_IIN_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_IIN_MIN, + .update = true, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_IIN_MAX, + .update = true, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_IIN_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_limit_attr iout_limit_attrs[] = { + { + .reg = PMBUS_IOUT_OC_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_IOUT_OC_WARNING, + }, { + .reg = PMBUS_IOUT_UC_FAULT_LIMIT, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_IOUT_UC_FAULT, + }, { + .reg = PMBUS_IOUT_OC_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_IOUT_OC_FAULT, + }, { + .reg = PMBUS_VIRT_READ_IOUT_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_IOUT_MIN, + .update = true, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_IOUT_MAX, + .update = true, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_IOUT_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_sensor_attr current_attributes[] = { + { + .reg = PMBUS_READ_IIN, + .class = PSC_CURRENT_IN, + .label = "iin", + .func = PMBUS_HAVE_IIN, + .sfunc = PMBUS_HAVE_STATUS_INPUT, + .sbase = PB_STATUS_INPUT_BASE, + .limit = iin_limit_attrs, + .nlimit = ARRAY_SIZE(iin_limit_attrs), + }, { + .reg = PMBUS_READ_IOUT, + .class = PSC_CURRENT_OUT, + .label = "iout", + .paged = true, + .func = PMBUS_HAVE_IOUT, + .sfunc = PMBUS_HAVE_STATUS_IOUT, + .sbase = PB_STATUS_IOUT_BASE, + .gbit = PB_STATUS_IOUT_OC, + .limit = iout_limit_attrs, + .nlimit = ARRAY_SIZE(iout_limit_attrs), + } +}; + +/* Power attributes */ + +static const struct pmbus_limit_attr pin_limit_attrs[] = { + { + .reg = PMBUS_PIN_OP_WARN_LIMIT, + .attr = "max", + .alarm = "alarm", + .sbit = PB_PIN_OP_WARNING, + }, { + .reg = PMBUS_VIRT_READ_PIN_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_PIN_MAX, + .update = true, + .attr = "input_highest", + }, { + .reg = PMBUS_VIRT_RESET_PIN_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_limit_attr pout_limit_attrs[] = { + { + .reg = PMBUS_POUT_MAX, + .attr = "cap", + .alarm = "cap_alarm", + .sbit = PB_POWER_LIMITING, + }, { + .reg = PMBUS_POUT_OP_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_POUT_OP_WARNING, + }, { + .reg = PMBUS_POUT_OP_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_POUT_OP_FAULT, + }, { + .reg = PMBUS_VIRT_READ_POUT_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_POUT_MAX, + .update = true, + .attr = "input_highest", + }, { + .reg = PMBUS_VIRT_RESET_POUT_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_sensor_attr power_attributes[] = { + { + .reg = PMBUS_READ_PIN, + .class = PSC_POWER, + .label = "pin", + .func = PMBUS_HAVE_PIN, + .sfunc = PMBUS_HAVE_STATUS_INPUT, + .sbase = PB_STATUS_INPUT_BASE, + .limit = pin_limit_attrs, + .nlimit = ARRAY_SIZE(pin_limit_attrs), + }, { + .reg = PMBUS_READ_POUT, + .class = PSC_POWER, + .label = "pout", + .paged = true, + .func = PMBUS_HAVE_POUT, + .sfunc = PMBUS_HAVE_STATUS_IOUT, + .sbase = PB_STATUS_IOUT_BASE, + .limit = pout_limit_attrs, + .nlimit = ARRAY_SIZE(pout_limit_attrs), + } +}; + +/* Temperature atributes */ + +static const struct pmbus_limit_attr temp_limit_attrs[] = { + { + .reg = PMBUS_UT_WARN_LIMIT, + .low = true, + .attr = "min", + .alarm = "min_alarm", + .sbit = PB_TEMP_UT_WARNING, + }, { + .reg = PMBUS_UT_FAULT_LIMIT, + .low = true, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_TEMP_UT_FAULT, + }, { + .reg = PMBUS_OT_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_TEMP_OT_WARNING, + }, { + .reg = PMBUS_OT_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_TEMP_OT_FAULT, + }, { + .reg = PMBUS_VIRT_READ_TEMP_MIN, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_TEMP_AVG, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_TEMP_MAX, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_TEMP_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_limit_attr temp_limit_attrs2[] = { + { + .reg = PMBUS_UT_WARN_LIMIT, + .low = true, + .attr = "min", + .alarm = "min_alarm", + .sbit = PB_TEMP_UT_WARNING, + }, { + .reg = PMBUS_UT_FAULT_LIMIT, + .low = true, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_TEMP_UT_FAULT, + }, { + .reg = PMBUS_OT_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_TEMP_OT_WARNING, + }, { + .reg = PMBUS_OT_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_TEMP_OT_FAULT, + }, { + .reg = PMBUS_VIRT_READ_TEMP2_MIN, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_TEMP2_AVG, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_TEMP2_MAX, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_TEMP2_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_limit_attr temp_limit_attrs3[] = { + { + .reg = PMBUS_UT_WARN_LIMIT, + .low = true, + .attr = "min", + .alarm = "min_alarm", + .sbit = PB_TEMP_UT_WARNING, + }, { + .reg = PMBUS_UT_FAULT_LIMIT, + .low = true, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_TEMP_UT_FAULT, + }, { + .reg = PMBUS_OT_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_TEMP_OT_WARNING, + }, { + .reg = PMBUS_OT_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_TEMP_OT_FAULT, + } +}; + +static const struct pmbus_sensor_attr temp_attributes[] = { + { + .reg = PMBUS_READ_TEMPERATURE_1, + .class = PSC_TEMPERATURE, + .paged = true, + .update = true, + .compare = true, + .func = PMBUS_HAVE_TEMP, + .sfunc = PMBUS_HAVE_STATUS_TEMP, + .sbase = PB_STATUS_TEMP_BASE, + .gbit = PB_STATUS_TEMPERATURE, + .limit = temp_limit_attrs, + .nlimit = ARRAY_SIZE(temp_limit_attrs), + }, { + .reg = PMBUS_READ_TEMPERATURE_2, + .class = PSC_TEMPERATURE, + .paged = true, + .update = true, + .compare = true, + .func = PMBUS_HAVE_TEMP2, + .sfunc = PMBUS_HAVE_STATUS_TEMP, + .sbase = PB_STATUS_TEMP_BASE, + .gbit = PB_STATUS_TEMPERATURE, + .limit = temp_limit_attrs2, + .nlimit = ARRAY_SIZE(temp_limit_attrs2), + }, { + .reg = PMBUS_READ_TEMPERATURE_3, + .class = PSC_TEMPERATURE, + .paged = true, + .update = true, + .compare = true, + .func = PMBUS_HAVE_TEMP3, + .sfunc = PMBUS_HAVE_STATUS_TEMP, + .sbase = PB_STATUS_TEMP_BASE, + .gbit = PB_STATUS_TEMPERATURE, + .limit = temp_limit_attrs3, + .nlimit = ARRAY_SIZE(temp_limit_attrs3), + } +}; + +static const int pmbus_fan_registers[] = { + PMBUS_READ_FAN_SPEED_1, + PMBUS_READ_FAN_SPEED_2, + PMBUS_READ_FAN_SPEED_3, + PMBUS_READ_FAN_SPEED_4 +}; + +static const int pmbus_fan_config_registers[] = { + PMBUS_FAN_CONFIG_12, + PMBUS_FAN_CONFIG_12, + PMBUS_FAN_CONFIG_34, + PMBUS_FAN_CONFIG_34 +}; + +static const int pmbus_fan_status_registers[] = { + PMBUS_STATUS_FAN_12, + PMBUS_STATUS_FAN_12, + PMBUS_STATUS_FAN_34, + PMBUS_STATUS_FAN_34 +}; + +static const u32 pmbus_fan_flags[] = { + PMBUS_HAVE_FAN12, + PMBUS_HAVE_FAN12, + PMBUS_HAVE_FAN34, + PMBUS_HAVE_FAN34 +}; + +static const u32 pmbus_fan_status_flags[] = { + PMBUS_HAVE_STATUS_FAN12, + PMBUS_HAVE_STATUS_FAN12, + PMBUS_HAVE_STATUS_FAN34, + PMBUS_HAVE_STATUS_FAN34 +}; + +/* Fans */ +static int pmbus_add_fan_attributes(struct i2c_client *client, + struct pmbus_data *data) +{ + const struct pmbus_driver_info *info = data->info; + int index = 1; + int page; + int ret; + + for (page = 0; page < info->pages; page++) { + int f; + + for (f = 0; f < ARRAY_SIZE(pmbus_fan_registers); f++) { + int regval; + + if (f >= info->fan_num) + break; + + if (!(info->func[page] & pmbus_fan_flags[f])) + break; + + if (!_pmbus_check_word_register(client, page, + pmbus_fan_registers[f])) + break; + + /* + * Skip fan if not installed. + * Each fan configuration register covers multiple fans, + * so we have to do some magic. + */ + regval = _pmbus_read_byte_data(client, page, + pmbus_fan_config_registers[f]); + if (regval < 0 || + (!(regval & (PB_FAN_1_INSTALLED >> ((f & 1) * 4))))) + continue; + + if (pmbus_add_sensor(data, "fan", "input", index, + page, pmbus_fan_registers[f], + PSC_FAN, true, true) == NULL) + return -ENOMEM; + + /* + * Each fan status register covers multiple fans, + * so we have to do some magic. + */ + if ((info->func[page] & pmbus_fan_status_flags[f]) && + _pmbus_check_byte_register(client, + page, pmbus_fan_status_registers[f])) { + int base; + + if (f > 1) /* fan 3, 4 */ + base = PB_STATUS_FAN34_BASE + page; + else + base = PB_STATUS_FAN_BASE + page; + ret = pmbus_add_boolean(data, "fan", + "alarm", index, NULL, NULL, base, + PB_FAN_FAN1_WARNING >> (f & 1)); + if (ret) + return ret; + ret = pmbus_add_boolean(data, "fan", + "fault", index, NULL, NULL, base, + PB_FAN_FAN1_FAULT >> (f & 1)); + if (ret) + return ret; + } + index++; + } + } + return 0; +} + +static int pmbus_find_attributes(struct i2c_client *client, + struct pmbus_data *data) +{ + int ret; + + /* Voltage sensors */ + ret = pmbus_add_sensor_attrs(client, data, "in", voltage_attributes, + ARRAY_SIZE(voltage_attributes)); + if (ret) + return ret; + + /* Current sensors */ + ret = pmbus_add_sensor_attrs(client, data, "curr", current_attributes, + ARRAY_SIZE(current_attributes)); + if (ret) + return ret; + + /* Power sensors */ + ret = pmbus_add_sensor_attrs(client, data, "power", power_attributes, + ARRAY_SIZE(power_attributes)); + if (ret) + return ret; + + /* Temperature sensors */ + ret = pmbus_add_sensor_attrs(client, data, "temp", temp_attributes, + ARRAY_SIZE(temp_attributes)); + if (ret) + return ret; + + /* Fans */ + ret = pmbus_add_fan_attributes(client, data); + return ret; +} + +/* + * Identify chip parameters. + * This function is called for all chips. + */ +static int pmbus_identify_common(struct i2c_client *client, + struct pmbus_data *data, int page) +{ + int vout_mode = -1; + + if (_pmbus_check_byte_register(client, page, PMBUS_VOUT_MODE)) + { + vout_mode = _pmbus_read_byte_data(client, page, + PMBUS_VOUT_MODE); + } + + if (vout_mode >= 0 && vout_mode != 0xff) { + /* + * Not all chips support the VOUT_MODE command, + * so a failure to read it is not an error. + */ + switch (vout_mode >> 5) { + case 0: /* linear mode */ + if (data->info->format[PSC_VOLTAGE_OUT] != linear) + return -ENODEV; + + data->exponent[page] = ((s8)(vout_mode << 3)) >> 3; + break; + case 1: /* VID mode */ + if (data->info->format[PSC_VOLTAGE_OUT] != vid) + return -ENODEV; + break; + case 2: /* direct mode */ + if (data->info->format[PSC_VOLTAGE_OUT] != direct) + return -ENODEV; + break; + default: + return -ENODEV; + } + } + + pmbus_clear_fault_page(client, page); + return 0; +} + +static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, + struct pmbus_driver_info *info) +{ + struct device *dev = &client->dev; + int page, ret; + + /* + * Some PMBus chips don't support PMBUS_STATUS_BYTE, so try + * to use PMBUS_STATUS_WORD instead if that is the case. + * Bail out if both registers are not supported. + */ + if(0) { /*Skip this for the i2c access may fail if PSU is not powered.*/ + data->status_register = PMBUS_STATUS_BYTE; + ret = i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE); + if (ret < 0 || ret == 0xff) { + data->status_register = PMBUS_STATUS_WORD; + ret = i2c_smbus_read_word_data(client, PMBUS_STATUS_WORD); + if (ret < 0 || ret == 0xffff) { + dev_err(dev, "PMBus status register not found\n"); + return -ENODEV; + } + } + } + _pmbus_clear_faults(client); + + if (info->identify) { + ret = (*info->identify)(client, info); + if (ret < 0) { + dev_err(dev, "Chip identification failed\n"); + return ret; + } + } + + if (info->pages <= 0 || info->pages > PMBUS_PAGES) { + dev_err(dev, "Bad number of PMBus pages: %d\n", info->pages); + return -ENODEV; + } + + for (page = 0; page < info->pages; page++) { + ret = pmbus_identify_common(client, data, page); + if (ret < 0) { + dev_err(dev, "Failed to identify chip capabilities\n"); + return ret; + } + } + return 0; +} + +int _pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info) +{ + struct device *dev = &client->dev; + struct pmbus_data *data; + int ret; + + if (!info) + return -ENODEV; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE + | I2C_FUNC_SMBUS_BYTE_DATA + | I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->dev = dev; + + if (limited_models(id)) + { + data->flags |= PMBUS_SKIP_STATUS_CHECK; + info->pages = 1; + info->fan_num = 1; + data->linear_16 = 0; + } + else + { + info->pages = id->driver_data; + info->fan_num = 4; + data->linear_16 = 1; + + } + + data->info = info; + + ret = pmbus_init_common(client, data, info); + if (ret < 0) + return ret; + + ret = pmbus_find_attributes(client, data); + if (ret) + goto out_kfree; + + /* + * If there are no attributes, something is wrong. + * Bail out instead of trying to register nothing. + */ + if (!data->num_attributes) { + dev_err(dev, "No attributes found\n"); + ret = -ENODEV; + goto out_kfree; + } + + data->groups[0] = &data->group; + data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + if (IS_ERR(data->hwmon_dev)) { + ret = PTR_ERR(data->hwmon_dev); + dev_err(dev, "Failed to register hwmon device\n"); + goto out_kfree; + } + return 0; + +out_kfree: + kfree(data->group.attrs); + return ret; +} + +/* + * Find sensor groups and status registers on each page. + */ +static void pmbus_find_sensor_groups(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int page; + + /* For i2c might not available when this driver installing, + turn on all attributes but VMON and FAN34.*/ + info->func[0] |= 0x1feff; + return ; + + + /* Sensors detected on page 0 only */ + if (_pmbus_check_word_register(client, 0, PMBUS_READ_VIN)) + info->func[0] |= PMBUS_HAVE_VIN; + if (_pmbus_check_word_register(client, 0, PMBUS_READ_VCAP)) + info->func[0] |= PMBUS_HAVE_VCAP; + if (_pmbus_check_word_register(client, 0, PMBUS_READ_IIN)) + info->func[0] |= PMBUS_HAVE_IIN; + if (_pmbus_check_word_register(client, 0, PMBUS_READ_PIN)) + info->func[0] |= PMBUS_HAVE_PIN; + if (info->func[0] + && _pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT)) + info->func[0] |= PMBUS_HAVE_STATUS_INPUT; + if (info->fan_num > 0) + { + if (_pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) && + _pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) { + info->func[0] |= PMBUS_HAVE_FAN12; + if (_pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN12; + } + } + if (info->fan_num > 2) + { + if (_pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) && + _pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) { + info->func[0] |= PMBUS_HAVE_FAN34; + if (_pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN34; + } + } + + if (_pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) + info->func[0] |= PMBUS_HAVE_TEMP; + if (_pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2)) + info->func[0] |= PMBUS_HAVE_TEMP2; + if (_pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3)) + info->func[0] |= PMBUS_HAVE_TEMP3; + + if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 + | PMBUS_HAVE_TEMP3) + && _pmbus_check_byte_register(client, 0, + PMBUS_STATUS_TEMPERATURE)) + info->func[0] |= PMBUS_HAVE_STATUS_TEMP; + + /* Sensors detected on all pages */ + for (page = 0; page < info->pages; page++) { + if (_pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) { + info->func[page] |= PMBUS_HAVE_VOUT; + if (_pmbus_check_byte_register(client, page, + PMBUS_STATUS_VOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_VOUT; + } + if (_pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) { + info->func[page] |= PMBUS_HAVE_IOUT; + if (_pmbus_check_byte_register(client, 0, + PMBUS_STATUS_IOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_IOUT; + } + if (_pmbus_check_word_register(client, page, PMBUS_READ_POUT)) + info->func[page] |= PMBUS_HAVE_POUT; + } +} + +/* + * Identify chip parameters. + */ +static int pmbus_identify(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int ret = 0; + + if (!info->pages) { + /* + * Check if the PAGE command is supported. If it is, + * keep setting the page number until it fails or until the + * maximum number of pages has been reached. Assume that + * this is the number of pages supported by the chip. + */ + if (_pmbus_check_byte_register(client, 0, PMBUS_PAGE)) { + int page; + + for (page = 1; page < PMBUS_PAGES; page++) { + if (_pmbus_set_page(client, page) < 0) + break; + } + _pmbus_set_page(client, 0); + info->pages = page; + } else { + info->pages = 1; + } + } + + if (_pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) { + int vout_mode; + + vout_mode = _pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); + if (vout_mode >= 0 && vout_mode != 0xff) { + switch (vout_mode >> 5) { + case 0: + break; + case 1: + info->format[PSC_VOLTAGE_OUT] = vid; + break; + case 2: + info->format[PSC_VOLTAGE_OUT] = direct; + break; + default: + ret = -ENODEV; + goto abort; + } + } + } + + + /* + * We should check if the COEFFICIENTS register is supported. + * If it is, and the chip is configured for direct mode, we can read + * the coefficients from the chip, one set per group of sensor + * registers. + * + * To do this, we will need access to a chip which actually supports the + * COEFFICIENTS command, since the command is too complex to implement + * without testing it. Until then, abort if a chip configured for direct + * mode was detected. + */ + if (info->format[PSC_VOLTAGE_OUT] == direct) { + ret = -ENODEV; + goto abort; + } + + /* Try to find sensor groups */ + pmbus_find_sensor_groups(client, info); +abort: + return ret; +} + +/* + * Use driver_data to set the number of pages supported by the chip. + */ +static const struct i2c_device_id pmbus_id[] = { + { "accton_ym2651", YM2651 }, + { "accton_ym2401", YM2401 }, + { "accton_ym2851", YM2851 }, + {} +}; + +static int limited_models(const struct i2c_device_id *id) +{ + int j; + + if (!id->name) + return 0; + + for (j = 0; j < ARRAY_SIZE(pmbus_id); j++) { + if (!pmbus_id[j].name) + continue; + + if (!strcmp(id->name, pmbus_id[j].name)) + { + if(id->driver_data < LIMITED_CHIPS) + { + return 1; + } + else + { + return 0; + } + } + + } + + return 0; +} + +static int pmbus_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pmbus_driver_info *info; + + info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), + GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->identify = pmbus_identify; + + return _pmbus_do_probe(client, id, info); +} + +int _pmbus_do_remove(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + kfree(data->group.attrs); + return 0; +} + +MODULE_DEVICE_TABLE(i2c, pmbus_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver pmbus_driver = { + .driver = { + .name = "accton_pmbus_3y", + }, + .probe = pmbus_probe, + .remove = _pmbus_do_remove, + .id_table = pmbus_id, +}; + +module_i2c_driver(pmbus_driver); + +MODULE_AUTHOR("Roy Lee"); +MODULE_DESCRIPTION("Accton PMBus driver for 3Y Power YM-2651Y."); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/common/modules/cpr_4011_4mxx.c b/platform/broadcom/sonic-platform-modules-accton/common/modules/cpr_4011_4mxx.c new file mode 100644 index 000000000000..2cea5f5e39f9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/common/modules/cpr_4011_4mxx.c @@ -0,0 +1,402 @@ +/* + * An hwmon driver for the CPR-4011-4Mxx Redundant Power Module + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x3c, 0x3d, 0x3e, 0x3f, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct cpr_4011_4mxx_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[2]; /* Register value */ + u8 fan_fault; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u16 fan_speed[2]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value); +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev); + +enum cpr_4011_4mxx_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); + +static struct attribute *cpr_4011_4mxx_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + cpr_4011_4mxx_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static const struct attribute_group cpr_4011_4mxx_group = { + .attrs = cpr_4011_4mxx_attributes, +}; + +static int cpr_4011_4mxx_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct cpr_4011_4mxx_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct cpr_4011_4mxx_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpr_4011_4mxx_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int cpr_4011_4mxx_remove(struct i2c_client *client) +{ + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id cpr_4011_4mxx_id[] = { + { "cpr_4011_4mxx", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpr_4011_4mxx_id); + +static struct i2c_driver cpr_4011_4mxx_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "cpr_4011_4mxx", + }, + .probe = cpr_4011_4mxx_probe, + .remove = cpr_4011_4mxx_remove, + .id_table = cpr_4011_4mxx_id, + .address_list = normal_i2c, +}; + +static int cpr_4011_4mxx_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int cpr_4011_4mxx_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + struct reg_data_byte regs_byte[] = { {0x20, &data->vout_mode}, + {0x81, &data->fan_fault} + }; + struct reg_data_word regs_word[] = { {0x88, &data->v_in}, + {0x8b, &data->v_out}, + {0x89, &data->i_in}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x97, &data->p_in}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &(data->fan_speed[0])}, + {0x91, &(data->fan_speed[1])} + }; + + dev_dbg(&client->dev, "Starting cpr_4011_4mxx update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = cpr_4011_4mxx_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = cpr_4011_4mxx_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init cpr_4011_4mxx_init(void) +{ + return i2c_add_driver(&cpr_4011_4mxx_driver); +} + +static void __exit cpr_4011_4mxx_exit(void) +{ + i2c_del_driver(&cpr_4011_4mxx_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("CPR_4011_4MXX driver"); +MODULE_LICENSE("GPL"); + +module_init(cpr_4011_4mxx_init); +module_exit(cpr_4011_4mxx_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/common/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-accton/common/modules/pmbus.h new file mode 100644 index 000000000000..cb6dbc34d87c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/common/modules/pmbus.h @@ -0,0 +1,389 @@ +/* + * pmbus.h - Common defines and structures for PMBus devices + * + * Copyright (c) 2010, 2011 Ericsson AB. + * Copyright (c) 2012 Guenter Roeck + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PMBUS_H +#define PMBUS_H + +/* + * Registers + */ +#define PMBUS_PAGE 0x00 +#define PMBUS_OPERATION 0x01 +#define PMBUS_ON_OFF_CONFIG 0x02 +#define PMBUS_CLEAR_FAULTS 0x03 +#define PMBUS_PHASE 0x04 + +#define PMBUS_CAPABILITY 0x19 +#define PMBUS_QUERY 0x1A + +#define PMBUS_VOUT_MODE 0x20 +#define PMBUS_VOUT_COMMAND 0x21 +#define PMBUS_VOUT_TRIM 0x22 +#define PMBUS_VOUT_CAL_OFFSET 0x23 +#define PMBUS_VOUT_MAX 0x24 +#define PMBUS_VOUT_MARGIN_HIGH 0x25 +#define PMBUS_VOUT_MARGIN_LOW 0x26 +#define PMBUS_VOUT_TRANSITION_RATE 0x27 +#define PMBUS_VOUT_DROOP 0x28 +#define PMBUS_VOUT_SCALE_LOOP 0x29 +#define PMBUS_VOUT_SCALE_MONITOR 0x2A + +#define PMBUS_COEFFICIENTS 0x30 +#define PMBUS_POUT_MAX 0x31 + +#define PMBUS_FAN_CONFIG_12 0x3A +#define PMBUS_FAN_COMMAND_1 0x3B +#define PMBUS_FAN_COMMAND_2 0x3C +#define PMBUS_FAN_CONFIG_34 0x3D +#define PMBUS_FAN_COMMAND_3 0x3E +#define PMBUS_FAN_COMMAND_4 0x3F + +#define PMBUS_VOUT_OV_FAULT_LIMIT 0x40 +#define PMBUS_VOUT_OV_FAULT_RESPONSE 0x41 +#define PMBUS_VOUT_OV_WARN_LIMIT 0x42 +#define PMBUS_VOUT_UV_WARN_LIMIT 0x43 +#define PMBUS_VOUT_UV_FAULT_LIMIT 0x44 +#define PMBUS_VOUT_UV_FAULT_RESPONSE 0x45 +#define PMBUS_IOUT_OC_FAULT_LIMIT 0x46 +#define PMBUS_IOUT_OC_FAULT_RESPONSE 0x47 +#define PMBUS_IOUT_OC_LV_FAULT_LIMIT 0x48 +#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE 0x49 +#define PMBUS_IOUT_OC_WARN_LIMIT 0x4A +#define PMBUS_IOUT_UC_FAULT_LIMIT 0x4B +#define PMBUS_IOUT_UC_FAULT_RESPONSE 0x4C + +#define PMBUS_OT_FAULT_LIMIT 0x4F +#define PMBUS_OT_FAULT_RESPONSE 0x50 +#define PMBUS_OT_WARN_LIMIT 0x51 +#define PMBUS_UT_WARN_LIMIT 0x52 +#define PMBUS_UT_FAULT_LIMIT 0x53 +#define PMBUS_UT_FAULT_RESPONSE 0x54 +#define PMBUS_VIN_OV_FAULT_LIMIT 0x55 +#define PMBUS_VIN_OV_FAULT_RESPONSE 0x56 +#define PMBUS_VIN_OV_WARN_LIMIT 0x57 +#define PMBUS_VIN_UV_WARN_LIMIT 0x58 +#define PMBUS_VIN_UV_FAULT_LIMIT 0x59 + +#define PMBUS_IIN_OC_FAULT_LIMIT 0x5B +#define PMBUS_IIN_OC_WARN_LIMIT 0x5D + +#define PMBUS_POUT_OP_FAULT_LIMIT 0x68 +#define PMBUS_POUT_OP_WARN_LIMIT 0x6A +#define PMBUS_PIN_OP_WARN_LIMIT 0x6B + +#define PMBUS_STATUS_BYTE 0x78 +#define PMBUS_STATUS_WORD 0x79 +#define PMBUS_STATUS_VOUT 0x7A +#define PMBUS_STATUS_IOUT 0x7B +#define PMBUS_STATUS_INPUT 0x7C +#define PMBUS_STATUS_TEMPERATURE 0x7D +#define PMBUS_STATUS_CML 0x7E +#define PMBUS_STATUS_OTHER 0x7F +#define PMBUS_STATUS_MFR_SPECIFIC 0x80 +#define PMBUS_STATUS_FAN_12 0x81 +#define PMBUS_STATUS_FAN_34 0x82 + +#define PMBUS_READ_VIN 0x88 +#define PMBUS_READ_IIN 0x89 +#define PMBUS_READ_VCAP 0x8A +#define PMBUS_READ_VOUT 0x8B +#define PMBUS_READ_IOUT 0x8C +#define PMBUS_READ_TEMPERATURE_1 0x8D +#define PMBUS_READ_TEMPERATURE_2 0x8E +#define PMBUS_READ_TEMPERATURE_3 0x8F +#define PMBUS_READ_FAN_SPEED_1 0x90 +#define PMBUS_READ_FAN_SPEED_2 0x91 +#define PMBUS_READ_FAN_SPEED_3 0x92 +#define PMBUS_READ_FAN_SPEED_4 0x93 +#define PMBUS_READ_DUTY_CYCLE 0x94 +#define PMBUS_READ_FREQUENCY 0x95 +#define PMBUS_READ_POUT 0x96 +#define PMBUS_READ_PIN 0x97 + +#define PMBUS_REVISION 0x98 +#define PMBUS_MFR_ID 0x99 +#define PMBUS_MFR_MODEL 0x9A +#define PMBUS_MFR_REVISION 0x9B +#define PMBUS_MFR_LOCATION 0x9C +#define PMBUS_MFR_DATE 0x9D +#define PMBUS_MFR_SERIAL 0x9E + +/* + * Virtual registers. + * Useful to support attributes which are not supported by standard PMBus + * registers but exist as manufacturer specific registers on individual chips. + * Must be mapped to real registers in device specific code. + * + * Semantics: + * Virtual registers are all word size. + * READ registers are read-only; writes are either ignored or return an error. + * RESET registers are read/write. Reading reset registers returns zero + * (used for detection), writing any value causes the associated history to be + * reset. + * Virtual registers have to be handled in device specific driver code. Chip + * driver code returns non-negative register values if a virtual register is + * supported, or a negative error code if not. The chip driver may return + * -ENODATA or any other error code in this case, though an error code other + * than -ENODATA is handled more efficiently and thus preferred. Either case, + * the calling PMBus core code will abort if the chip driver returns an error + * code when reading or writing virtual registers. + */ +#define PMBUS_VIRT_BASE 0x100 +#define PMBUS_VIRT_READ_TEMP_AVG (PMBUS_VIRT_BASE + 0) +#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 1) +#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 2) +#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 3) +#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 4) +#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 5) +#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 6) +#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 7) +#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 8) +#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 9) +#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 10) +#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 11) +#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 12) +#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 13) +#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 14) +#define PMBUS_VIRT_READ_POUT_AVG (PMBUS_VIRT_BASE + 15) +#define PMBUS_VIRT_READ_POUT_MAX (PMBUS_VIRT_BASE + 16) +#define PMBUS_VIRT_RESET_POUT_HISTORY (PMBUS_VIRT_BASE + 17) +#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 18) +#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 19) +#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 20) +#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 21) +#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 22) +#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 23) +#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 24) +#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 25) +#define PMBUS_VIRT_READ_TEMP2_AVG (PMBUS_VIRT_BASE + 26) +#define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 27) +#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 28) +#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 29) + +#define PMBUS_VIRT_READ_VMON (PMBUS_VIRT_BASE + 30) +#define PMBUS_VIRT_VMON_UV_WARN_LIMIT (PMBUS_VIRT_BASE + 31) +#define PMBUS_VIRT_VMON_OV_WARN_LIMIT (PMBUS_VIRT_BASE + 32) +#define PMBUS_VIRT_VMON_UV_FAULT_LIMIT (PMBUS_VIRT_BASE + 33) +#define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34) +#define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35) + +/* + * CAPABILITY + */ +#define PB_CAPABILITY_SMBALERT (1<<4) +#define PB_CAPABILITY_ERROR_CHECK (1<<7) + +/* + * VOUT_MODE + */ +#define PB_VOUT_MODE_MODE_MASK 0xe0 +#define PB_VOUT_MODE_PARAM_MASK 0x1f + +#define PB_VOUT_MODE_LINEAR 0x00 +#define PB_VOUT_MODE_VID 0x20 +#define PB_VOUT_MODE_DIRECT 0x40 + +/* + * Fan configuration + */ +#define PB_FAN_2_PULSE_MASK ((1 << 0) | (1 << 1)) +#define PB_FAN_2_RPM (1 << 2) +#define PB_FAN_2_INSTALLED (1 << 3) +#define PB_FAN_1_PULSE_MASK ((1 << 4) | (1 << 5)) +#define PB_FAN_1_RPM (1 << 6) +#define PB_FAN_1_INSTALLED (1 << 7) + +/* + * STATUS_BYTE, STATUS_WORD (lower) + */ +#define PB_STATUS_NONE_ABOVE (1<<0) +#define PB_STATUS_CML (1<<1) +#define PB_STATUS_TEMPERATURE (1<<2) +#define PB_STATUS_VIN_UV (1<<3) +#define PB_STATUS_IOUT_OC (1<<4) +#define PB_STATUS_VOUT_OV (1<<5) +#define PB_STATUS_OFF (1<<6) +#define PB_STATUS_BUSY (1<<7) + +/* + * STATUS_WORD (upper) + */ +#define PB_STATUS_UNKNOWN (1<<8) +#define PB_STATUS_OTHER (1<<9) +#define PB_STATUS_FANS (1<<10) +#define PB_STATUS_POWER_GOOD_N (1<<11) +#define PB_STATUS_WORD_MFR (1<<12) +#define PB_STATUS_INPUT (1<<13) +#define PB_STATUS_IOUT_POUT (1<<14) +#define PB_STATUS_VOUT (1<<15) + +/* + * STATUS_IOUT + */ +#define PB_POUT_OP_WARNING (1<<0) +#define PB_POUT_OP_FAULT (1<<1) +#define PB_POWER_LIMITING (1<<2) +#define PB_CURRENT_SHARE_FAULT (1<<3) +#define PB_IOUT_UC_FAULT (1<<4) +#define PB_IOUT_OC_WARNING (1<<5) +#define PB_IOUT_OC_LV_FAULT (1<<6) +#define PB_IOUT_OC_FAULT (1<<7) + +/* + * STATUS_VOUT, STATUS_INPUT + */ +#define PB_VOLTAGE_UV_FAULT (1<<4) +#define PB_VOLTAGE_UV_WARNING (1<<5) +#define PB_VOLTAGE_OV_WARNING (1<<6) +#define PB_VOLTAGE_OV_FAULT (1<<7) + +/* + * STATUS_INPUT + */ +#define PB_PIN_OP_WARNING (1<<0) +#define PB_IIN_OC_WARNING (1<<1) +#define PB_IIN_OC_FAULT (1<<2) + +/* + * STATUS_TEMPERATURE + */ +#define PB_TEMP_UT_FAULT (1<<4) +#define PB_TEMP_UT_WARNING (1<<5) +#define PB_TEMP_OT_WARNING (1<<6) +#define PB_TEMP_OT_FAULT (1<<7) + +/* + * STATUS_FAN + */ +#define PB_FAN_AIRFLOW_WARNING (1<<0) +#define PB_FAN_AIRFLOW_FAULT (1<<1) +#define PB_FAN_FAN2_SPEED_OVERRIDE (1<<2) +#define PB_FAN_FAN1_SPEED_OVERRIDE (1<<3) +#define PB_FAN_FAN2_WARNING (1<<4) +#define PB_FAN_FAN1_WARNING (1<<5) +#define PB_FAN_FAN2_FAULT (1<<6) +#define PB_FAN_FAN1_FAULT (1<<7) + +/* + * CML_FAULT_STATUS + */ +#define PB_CML_FAULT_OTHER_MEM_LOGIC (1<<0) +#define PB_CML_FAULT_OTHER_COMM (1<<1) +#define PB_CML_FAULT_PROCESSOR (1<<3) +#define PB_CML_FAULT_MEMORY (1<<4) +#define PB_CML_FAULT_PACKET_ERROR (1<<5) +#define PB_CML_FAULT_INVALID_DATA (1<<6) +#define PB_CML_FAULT_INVALID_COMMAND (1<<7) + +enum pmbus_sensor_classes { + PSC_VOLTAGE_IN = 0, + PSC_VOLTAGE_OUT, + PSC_CURRENT_IN, + PSC_CURRENT_OUT, + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ + +/* Functionality bit mask */ +#define PMBUS_HAVE_VIN (1 << 0) +#define PMBUS_HAVE_VCAP (1 << 1) +#define PMBUS_HAVE_VOUT (1 << 2) +#define PMBUS_HAVE_IIN (1 << 3) +#define PMBUS_HAVE_IOUT (1 << 4) +#define PMBUS_HAVE_PIN (1 << 5) +#define PMBUS_HAVE_POUT (1 << 6) +#define PMBUS_HAVE_FAN12 (1 << 7) +#define PMBUS_HAVE_FAN34 (1 << 8) +#define PMBUS_HAVE_TEMP (1 << 9) +#define PMBUS_HAVE_TEMP2 (1 << 10) +#define PMBUS_HAVE_TEMP3 (1 << 11) +#define PMBUS_HAVE_STATUS_VOUT (1 << 12) +#define PMBUS_HAVE_STATUS_IOUT (1 << 13) +#define PMBUS_HAVE_STATUS_INPUT (1 << 14) +#define PMBUS_HAVE_STATUS_TEMP (1 << 15) +#define PMBUS_HAVE_STATUS_FAN12 (1 << 16) +#define PMBUS_HAVE_STATUS_FAN34 (1 << 17) +#define PMBUS_HAVE_VMON (1 << 18) +#define PMBUS_HAVE_STATUS_VMON (1 << 19) + +enum pmbus_data_format { linear = 0, direct, vid }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + /* + * Support one set of coefficients for each sensor type + * Used for chips providing data in direct mode. + */ + int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */ + int b[PSC_NUM_CLASSES]; /* offset */ + int R[PSC_NUM_CLASSES]; /* exponent */ + + u32 func[PMBUS_PAGES]; /* Functionality, per page */ + /* + * The following functions map manufacturing specific register values + * to PMBus standard register values. Specify only if mapping is + * necessary. + * Functions return the register value (read) or zero (write) if + * successful. A return value of -ENODATA indicates that there is no + * manufacturer specific register, but that a standard PMBus register + * may exist. Any other negative return value indicates that the + * register does not exist, and that no attempt should be made to read + * the standard register. + */ + int (*read_byte_data)(struct i2c_client *client, int page, int reg); + int (*read_word_data)(struct i2c_client *client, int page, int reg); + int (*write_word_data)(struct i2c_client *client, int page, int reg, + u16 word); + int (*write_byte)(struct i2c_client *client, int page, u8 value); + /* + * The identify function determines supported PMBus functionality. + * This function is only necessary if a chip driver supports multiple + * chips, and the chip functionality is not pre-determined. + */ + int (*identify)(struct i2c_client *client, + struct pmbus_driver_info *info); + + int fan_num; +}; + +/* Function declarations */ + +void pmbus_clear_cache(struct i2c_client *client); +int pmbus_set_page(struct i2c_client *client, u8 page); +int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); +int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); +int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); +int pmbus_write_byte(struct i2c_client *client, int page, u8 value); +void _pmbus_clear_faults(struct i2c_client *client); +bool _pmbus_check_byte_register(struct i2c_client *client, int page, int reg); +bool _pmbus_check_word_register(struct i2c_client *client, int page, int reg); +int _pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info); +int pmbus_do_remove(struct i2c_client *client); +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client + *client); + +#endif /* PMBUS_H */ diff --git a/platform/broadcom/sonic-platform-modules-accton/common/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/common/modules/ym2651y.c new file mode 100644 index 000000000000..47e6a1d06bc5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/common/modules/ym2651y.c @@ -0,0 +1,619 @@ +/* + * An hwmon driver for the 3Y Power YM-2651Y Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END }; + +enum chips { + YM2651, + YM2401, + YM2851, +}; + +/* Each client has this additional data + */ +struct ym2651y_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 capability; /* Register value */ + u16 status_word; /* Register value */ + u8 fan_fault; /* Register value */ + u8 over_temp; /* Register value */ + u16 v_out; /* Register value */ + u16 i_out; /* Register value */ + u16 p_out; /* Register value */ + u16 temp; /* Register value */ + u16 fan_speed; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u8 fan_dir[4]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[10]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u16 mfr_vin_min; /* Register value */ + u16 mfr_vin_max; /* Register value */ + u16 mfr_iin_max; /* Register value */ + u16 mfr_iout_max; /* Register value */ + u16 mfr_pin_max; /* Register value */ + u16 mfr_pout_max; /* Register value */ + u16 mfr_vout_min; /* Register value */ + u16 mfr_vout_max; /* Register value */ +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static struct ym2651y_data *ym2651y_update_device(struct device *dev); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value); + +enum ym2651y_sysfs_attributes { + PSU_POWER_ON = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD, + PSU_FAN1_FAULT, + PSU_FAN_DIRECTION, + PSU_OVER_TEMP, + PSU_V_OUT, + PSU_I_OUT, + PSU_P_OUT, + PSU_P_OUT_UV, /*In Unit of microVolt, instead of mini.*/ + PSU_TEMP1_INPUT, + PSU_FAN1_SPEED, + PSU_FAN1_DUTY_CYCLE, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_VIN_MIN, + PSU_MFR_VIN_MAX, + PSU_MFR_VOUT_MIN, + PSU_MFR_VOUT_MAX, + PSU_MFR_IIN_MAX, + PSU_MFR_IOUT_MAX, + PSU_MFR_PIN_MAX, + PSU_MFR_POUT_MAX +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision, S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_linear, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); + +static struct attribute *ym2651y_attributes[] = { + &sensor_dev_attr_psu_power_on.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_over_temp.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_temp1_fault.dev_attr.attr, + NULL +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u16 status = 0; + + switch (attr->index) { + case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */ + status = (data->status_word & 0x40) ? 0 : 1; + break; + case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */ + status = (data->status_word & 0x4) >> 2; + break; + case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */ + status = (data->status_word & 0x800) ? 0 : 1; + break; + } + + return sprintf(buf, "%d\n", status); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_OUT: + value = data->v_out; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_OUT_UV: + multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/ + /*Passing through*/ + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp; + break; + case PSU_FAN1_SPEED: + value = data->fan_speed; + multiplier = 1; + break; + case PSU_FAN1_DUTY_CYCLE: + value = data->fan_duty_cycle[0]; + multiplier = 1; + break; + case PSU_MFR_VIN_MIN: + value = data->mfr_vin_min; + break; + case PSU_MFR_VIN_MAX: + value = data->mfr_vin_max; + break; + case PSU_MFR_VOUT_MIN: + value = data->mfr_vout_min; + break; + case PSU_MFR_VOUT_MAX: + value = data->mfr_vout_max; + break; + case PSU_MFR_PIN_MAX: + value = data->mfr_pin_max; + break; + case PSU_MFR_POUT_MAX: + value = data->mfr_pout_max; + break; + case PSU_MFR_IOUT_MAX: + value = data->mfr_iout_max; + break; + case PSU_MFR_IIN_MAX: + value = data->mfr_iin_max; + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct ym2651y_data *data = ym2651y_update_device(dev); + + return sprintf(buf, "%d\n", data->over_temp >> 7); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u8 *ptr = NULL; + + switch (attr->index) { + case PSU_FAN_DIRECTION: /* psu_fan_dir */ + ptr = data->fan_dir; + break; + case PSU_MFR_ID: /* psu_mfr_id */ + ptr = data->mfr_id; + break; + case PSU_MFR_MODEL: /* psu_mfr_model */ + ptr = data->mfr_model; + break; + case PSU_MFR_REVISION: /* psu_mfr_revision */ + ptr = data->mfr_revsion; + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group ym2651y_group = { + .attrs = ym2651y_attributes, +}; + +static int ym2651y_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct ym2651y_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &ym2651y_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int ym2651y_remove(struct i2c_client *client) +{ + struct ym2651y_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id ym2651y_id[] = { + { "ym2651", YM2651 }, + { "ym2401", YM2401 }, + { "ym2851", YM2851 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ym2651y_id); + +static struct i2c_driver ym2651y_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ym2651", + }, + .probe = ym2651y_probe, + .remove = ym2651y_remove, + .id_table = ym2651y_id, + .address_list = normal_i2c, +}; + +static int ym2651y_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int ym2651y_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct ym2651y_data *ym2651y_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + u8 command; + u8 fan_dir[5] = {0}; + struct reg_data_byte regs_byte[] = { {0x19, &data->capability}, + {0x7d, &data->over_temp}, + {0x81, &data->fan_fault}, + {0x98, &data->pmbus_revision} + }; + struct reg_data_word regs_word[] = { {0x79, &data->status_word}, + {0x8b, &data->v_out}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x8d, &data->temp}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &data->fan_speed}, + {0xa0, &data->mfr_vin_min}, + {0xa1, &data->mfr_vin_max}, + {0xa2, &data->mfr_iin_max}, + {0xa3, &data->mfr_pin_max}, + {0xa4, &data->mfr_vout_min}, + {0xa5, &data->mfr_vout_max}, + {0xa6, &data->mfr_iout_max}, + {0xa7, &data->mfr_pout_max} + }; + + dev_dbg(&client->dev, "Starting ym2651 update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = ym2651y_read_byte(client, regs_byte[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + *(regs_byte[i].value) = 0; + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = ym2651y_read_word(client, regs_word[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + *(regs_word[i].value) = 0; + } + else { + *(regs_word[i].value) = status; + } + } + + /* Read fan_direction */ + command = 0xC3; + status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + } + + strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1); + data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0'; + + /* Read mfr_id */ + command = 0x99; + status = ym2651y_read_block(client, command, data->mfr_id, + ARRAY_SIZE(data->mfr_id)-1); + data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_model */ + command = 0x9a; + status = ym2651y_read_block(client, command, data->mfr_model, + ARRAY_SIZE(data->mfr_model)-1); + data->mfr_model[ARRAY_SIZE(data->mfr_model)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_revsion */ + command = 0x9b; + status = ym2651y_read_block(client, command, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)-1); + data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(ym2651y_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("3Y Power YM-2651Y driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/changelog b/platform/broadcom/sonic-platform-modules-accton/debian/changelog new file mode 100755 index 000000000000..2b08b12c206a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/debian/changelog @@ -0,0 +1,18 @@ +sonic-accton-platform-modules (1.1) unstable; urgency=low + + * Add support for AS7816-64X. + + -- Accton Network Tue, 19 Dec 2017 09:35:58 +0800 + +sonic-accton-platform-modules (1.1) unstable; urgency=low + + * Add support for Accton AS5712-54X + + -- Accton Network Wed, 11 Oct 2017 14:21:45 +0800 + +sonic-accton-platform-modules (1.0) unstable; urgency=low + + * Add support for Accton AS7712-32X + * Initial release + + -- Accton Network Thu, 01 Jun 2017 14:06:38 +0800 diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/compat b/platform/broadcom/sonic-platform-modules-accton/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/control b/platform/broadcom/sonic-platform-modules-accton/debian/control new file mode 100755 index 000000000000..e8db57c6a155 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/debian/control @@ -0,0 +1,43 @@ +Source: sonic-accton-platform-modules +Section: main +Priority: extra +Maintainer: Accton network , Accton Network +Build-Depends: debhelper (>= 9), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-accton-as7712-32x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as5712-54x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7816-64x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7716-32x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7716-32xb +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7312-54x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7326-56x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as6712-32x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7726-32x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/rules b/platform/broadcom/sonic-platform-modules-accton/debian/rules new file mode 100755 index 000000000000..7f1b9bfdce9e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/debian/rules @@ -0,0 +1,86 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-accton +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CLASSES_DIR := classes +CONF_DIR := conf + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + $(PYTHON) $${mod}/setup.py build; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/.gitignore b/platform/broadcom/sonic-platform-modules-alphanetworks/.gitignore new file mode 100644 index 000000000000..7f287d538227 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/.gitignore @@ -0,0 +1,50 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/README.md b/platform/broadcom/sonic-platform-modules-alphanetworks/README.md new file mode 100644 index 000000000000..a0c753830103 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/README.md @@ -0,0 +1 @@ +platform drivers of Alphanetworks products for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/changelog b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/changelog new file mode 100644 index 000000000000..2742b7c6a416 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/changelog @@ -0,0 +1,6 @@ +sonic-alphanetworks-platform-modules (1.0) unstable; urgency=low + + * Add support for SNH60A0-320FV2 and SNH60B0_640F. + + -- Alphanetworks Tue, 19 Dec 2017 09:35:58 +0800 + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/compat b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control new file mode 100644 index 000000000000..075e86a008e4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control @@ -0,0 +1,17 @@ +Source: sonic-alphanetworks-platform-modules +Section: main +Priority: extra +Maintainer: Alphanetworks , Alphanetworks +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-alphanetworks-snh60a0-320fv2 +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-alphanetworks-snh60b0-640f +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/rules b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/rules new file mode 100755 index 000000000000..0d1a588db6bd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/rules @@ -0,0 +1,86 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-alphanetworks +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= snh60a0-320fv2 snh60b0-640f +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CLASSES_DIR := classes +CONF_DIR := conf + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + $(PYTHON) $${mod}/setup.py build; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/classes/__init__.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/Makefile b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/Makefile new file mode 100644 index 000000000000..f9477910d382 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/Makefile @@ -0,0 +1,8 @@ +# obj-m:=accton_as7712_32x_fan.o accton_as7712_32x_sfp.o leds-accton_as7712_32x.o \ +# goreme_system_cpld.o ym2651y.o optoe.o + +obj-m:=alphanetworks_snh60a0-320fv2_sfp.o snh60a0_system_cpld.o snh60a0_power_cpld.o snh60a0_onie_eeprom.o + + +# obj-m:=accton_as7712_32x_fan.o accton_as7712_32x_sfp.o leds-accton_as7712_32x.o \ +# accton_as7712_32x_psu.o accton_i2c_cpld.o ym2651y.o optoe.o diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/alphanetworks_snh60a0-320fv2_sfp.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/alphanetworks_snh60a0-320fv2_sfp.c new file mode 100644 index 000000000000..af47c6521a0f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/alphanetworks_snh60a0-320fv2_sfp.c @@ -0,0 +1,1669 @@ +/* + * SFP driver for alphanetworks snh60a0-320fv2 sfp + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Philip Wang + * + * 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 + * 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. + * see + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "snh60a0_320fv2_sfp" + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s[%s,%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define NUM_OF_SFP_PORT 32 +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +#define SFP_CPLD_I2C_ADDR 0x5F +#define SFP_EEPROM_A0_I2C_ADDR 0x50 +#define SFP_EEPROM_A2_I2C_ADDR 0x68 + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 +#define SFF8472_10G_BASE_MASK 0xF0 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +/* extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); */ +extern int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { SFP_EEPROM_A0_I2C_ADDR, SFP_EEPROM_A2_I2C_ADDR, SFP_CPLD_I2C_ADDR, I2C_CLIENT_END }; + +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +sfp1, sfp2, sfp3, sfp4, sfp5, sfp6, sfp7, sfp8, +sfp9, sfp10, sfp11, sfp12, sfp13, sfp14, sfp15, sfp16, +sfp17, sfp18, sfp19, sfp20, sfp21, sfp22, sfp23, sfp24, +sfp25, sfp26, sfp27, sfp28, sfp29, sfp30, sfp31, sfp32 +}; + +static const struct i2c_device_id sfp_device_id[] = { +{ "sfpcpld1", sfp1 }, { "sfpcpld2", sfp2 }, { "sfpcpld3", sfp3 }, { "sfpcpld4", sfp4 }, +{ "sfpcpld5", sfp5 }, { "sfpcpld6", sfp6 }, { "sfpcpld7", sfp7 }, { "sfpcpld8", sfp8 }, +{ "sfpcpld9", sfp9 }, { "sfpcpld10", sfp10 }, { "sfpcpld11", sfp11 }, { "sfpcpld12", sfp12 }, +{ "sfpcpld13", sfp13 }, { "sfpcpld14", sfp14 }, { "sfpcpld15", sfp15 }, { "sfpcpld16", sfp16 }, +{ "sfpcpld17", sfp17 }, { "sfpcpld18", sfp18 }, { "sfpcpld19", sfp19 }, { "sfpcpld20", sfp20 }, +{ "sfpcpld21", sfp21 }, { "sfpcpld22", sfp22 }, { "sfpcpld23", sfp23 }, { "sfpcpld24", sfp24 }, +{ "sfpcpld25", sfp25 }, { "sfpcpld26", sfp26 }, { "sfpcpld27", sfp27 }, { "sfpcpld28", sfp28 }, +{ "sfpcpld29", sfp29 }, { "sfpcpld30", sfp30 }, { "sfpcpld31", sfp31 }, { "sfpcpld32", sfp32 }, +{} +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28 +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[2]; /* index 0 => device id + 1 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 2 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +}; + +struct sfp_ddm_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + struct eeprom_data eeprom; +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + u64 port_reset; /* reset status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct sfp_ddm_data *ddm; + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +enum sfp_sysfs_port_num_attributes { + PORT1_NUMBER, + PORT2_NUMBER, + PORT3_NUMBER, + PORT4_NUMBER, + PORT5_NUMBER, + PORT6_NUMBER, + PORT7_NUMBER, + PORT8_NUMBER, + PORT_NUMBER_MAX +}; + +enum sfp_sysfs_present_attributes { + PORT1_PRESENT, + PORT2_PRESENT, + PORT3_PRESENT, + PORT4_PRESENT, + PORT5_PRESENT, + PORT6_PRESENT, + PORT7_PRESENT, + PORT8_PRESENT, + PORT1_PRESENT_ALL, + PORT2_PRESENT_ALL, + PORT3_PRESENT_ALL, + PORT4_PRESENT_ALL, + PORT5_PRESENT_ALL, + PORT6_PRESENT_ALL, + PORT7_PRESENT_ALL, + PORT8_PRESENT_ALL, + PORT_PRESENT_MAX +}; + +enum sfp_sysfs_type_attributes { + PORT1_TYPE, + PORT2_TYPE, + PORT3_TYPE, + PORT4_TYPE, + PORT5_TYPE, + PORT6_TYPE, + PORT7_TYPE, + PORT8_TYPE, + PORT_TYPE_MAX +}; + +enum sfp_sysfs_reset_attributes { + PORT1_RESET, + PORT2_RESET, + PORT3_RESET, + PORT4_RESET, + PORT5_RESET, + PORT6_RESET, + PORT7_RESET, + PORT8_RESET, + PORT_RESET_MAX +}; + +enum sfp_sysfs_rx_los_attributes { + PORT1_RX_LOS, + PORT2_RX_LOS, + PORT3_RX_LOS, + PORT4_RX_LOS, + PORT5_RX_LOS, + PORT6_RX_LOS, + PORT7_RX_LOS, + PORT8_RX_LOS, + PORT1_RX_LOS1, + PORT2_RX_LOS1, + PORT3_RX_LOS1, + PORT4_RX_LOS1, + PORT5_RX_LOS1, + PORT6_RX_LOS1, + PORT7_RX_LOS1, + PORT8_RX_LOS1, + PORT1_RX_LOS2, + PORT2_RX_LOS2, + PORT3_RX_LOS2, + PORT4_RX_LOS2, + PORT5_RX_LOS2, + PORT6_RX_LOS2, + PORT7_RX_LOS2, + PORT8_RX_LOS2, + PORT1_RX_LOS3, + PORT2_RX_LOS3, + PORT3_RX_LOS3, + PORT4_RX_LOS3, + PORT5_RX_LOS3, + PORT6_RX_LOS3, + PORT7_RX_LOS3, + PORT8_RX_LOS3, + PORT1_RX_LOS4, + PORT2_RX_LOS4, + PORT3_RX_LOS4, + PORT4_RX_LOS4, + PORT5_RX_LOS4, + PORT6_RX_LOS4, + PORT7_RX_LOS4, + PORT8_RX_LOS4, + PORT1_RX_LOS_ALL, + PORT2_RX_LOS_ALL, + PORT3_RX_LOS_ALL, + PORT4_RX_LOS_ALL, + PORT5_RX_LOS_ALL, + PORT6_RX_LOS_ALL, + PORT7_RX_LOS_ALL, + PORT8_RX_LOS_ALL, + PORT_RX_LOS_MAX +}; + +enum sfp_sysfs_tx_disable_attributes { + PORT1_TX_DISABLE = PORT_RX_LOS_MAX, + PORT2_TX_DISABLE, + PORT3_TX_DISABLE, + PORT4_TX_DISABLE, + PORT5_TX_DISABLE, + PORT6_TX_DISABLE, + PORT7_TX_DISABLE, + PORT8_TX_DISABLE, + PORT1_TX_DISABLE1, + PORT2_TX_DISABLE1, + PORT3_TX_DISABLE1, + PORT4_TX_DISABLE1, + PORT5_TX_DISABLE1, + PORT6_TX_DISABLE1, + PORT7_TX_DISABLE1, + PORT8_TX_DISABLE1, + PORT1_TX_DISABLE2, + PORT2_TX_DISABLE2, + PORT3_TX_DISABLE2, + PORT4_TX_DISABLE2, + PORT5_TX_DISABLE2, + PORT6_TX_DISABLE2, + PORT7_TX_DISABLE2, + PORT8_TX_DISABLE2, + PORT1_TX_DISABLE3, + PORT2_TX_DISABLE3, + PORT3_TX_DISABLE3, + PORT4_TX_DISABLE3, + PORT5_TX_DISABLE3, + PORT6_TX_DISABLE3, + PORT7_TX_DISABLE3, + PORT8_TX_DISABLE3, + PORT1_TX_DISABLE4, + PORT2_TX_DISABLE4, + PORT3_TX_DISABLE4, + PORT4_TX_DISABLE4, + PORT5_TX_DISABLE4, + PORT6_TX_DISABLE4, + PORT7_TX_DISABLE4, + PORT8_TX_DISABLE4, + PORT1_TX_DISABLE_ALL, + PORT2_TX_DISABLE_ALL, + PORT3_TX_DISABLE_ALL, + PORT4_TX_DISABLE_ALL, + PORT5_TX_DISABLE_ALL, + PORT6_TX_DISABLE_ALL, + PORT7_TX_DISABLE_ALL, + PORT8_TX_DISABLE_ALL, + PORT_TX_DISABLE_MAX +}; + +enum sfp_sysfs_tx_fault_attributes { + PORT1_TX_FAULT = PORT_TX_DISABLE_MAX, + PORT2_TX_FAULT, + PORT3_TX_FAULT, + PORT4_TX_FAULT, + PORT5_TX_FAULT, + PORT6_TX_FAULT, + PORT7_TX_FAULT, + PORT8_TX_FAULT, + PORT1_TX_FAULT1, + PORT2_TX_FAULT1, + PORT3_TX_FAULT1, + PORT4_TX_FAULT1, + PORT5_TX_FAULT1, + PORT6_TX_FAULT1, + PORT7_TX_FAULT1, + PORT8_TX_FAULT1, + PORT1_TX_FAULT2, + PORT2_TX_FAULT2, + PORT3_TX_FAULT2, + PORT4_TX_FAULT2, + PORT5_TX_FAULT2, + PORT6_TX_FAULT2, + PORT7_TX_FAULT2, + PORT8_TX_FAULT2, + PORT1_TX_FAULT3, + PORT2_TX_FAULT3, + PORT3_TX_FAULT3, + PORT4_TX_FAULT3, + PORT5_TX_FAULT3, + PORT6_TX_FAULT3, + PORT7_TX_FAULT3, + PORT8_TX_FAULT3, + PORT1_TX_FAULT4, + PORT2_TX_FAULT4, + PORT3_TX_FAULT4, + PORT4_TX_FAULT4, + PORT5_TX_FAULT4, + PORT6_TX_FAULT4, + PORT7_TX_FAULT4, + PORT8_TX_FAULT4, + PORT_TX_FAULT_MAX +}; + +enum sfp_sysfs_eeprom_attributes { + PORT1_EEPROM, + PORT2_EEPROM, + PORT3_EEPROM, + PORT4_EEPROM, + PORT5_EEPROM, + PORT6_EEPROM, + PORT7_EEPROM, + PORT8_EEPROM, + PORT_EEPROM_MAX +}; + +enum sfp_sysfs_ddm_implemented_attributes { + PORT1_DDM_IMPLEMENTED, + PORT2_DDM_IMPLEMENTED, + PORT3_DDM_IMPLEMENTED, + PORT4_DDM_IMPLEMENTED, + PORT5_DDM_IMPLEMENTED, + PORT6_DDM_IMPLEMENTED, + PORT7_DDM_IMPLEMENTED, + PORT8_DDM_IMPLEMENTED, + PORT_DDM_IMPLEMENTED_MAX +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + DEBUG_PRINT("show_port_number port number:%d", data->port + attr->index); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port + attr->index)); +} + +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x05}; + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + + /* Read present status of port 1~32 */ + data->present = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x5f) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); + data->present |= (u64)status << (i*8); + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) +{ + return NULL; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + return 0; +} + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = sfp_update_present(client); + return (data->present & BIT_INDEX(port)) ? 1 : 0; +} + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if ((attr->index >= PORT1_PRESENT_ALL) && (attr->index <= PORT8_PRESENT_ALL)) { + + } + + /* PRESENT */ + return sprintf(buf, "%d\n", sfp_is_port_present(client, attr->index)); +} + +static struct sfp_port_data *sfp_update_port_type(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 buf = 0; + int status; + + mutex_lock(&data->update_lock); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + if (buf != SFF8024_DEVICE_ID_SFP) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + status = sfp_eeprom_read(data->client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); + data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; + break; + } + case DRIVER_TYPE_QSFP: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); + switch (buf) { + case SFF8024_DEVICE_ID_QSFP: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; + break; + case SFF8024_DEVICE_ID_QSFP_PLUS: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + case SFF8024_DEVICE_ID_QSFP28: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + default: + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + break; + } + default: + break; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + + if (!sfp_is_port_present(client, attr->index)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_type(dev); + return sprintf(buf, "%d\n", data->port_type); +} + + +static struct sfp_port_data *sfp_update_port_reset(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x7}; + + mutex_lock(&data->update_lock); + + /* Read reset status of port 1~32 */ + data->port_reset = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("reset status = 0x%x", status); + data->port_reset |= (u64)status << (i*8); + } + + DEBUG_PRINT("reset status = 0x%llx", data->port_reset); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int is_reset = 0; + + if (!sfp_is_port_present(client, attr->index)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_reset(client); + is_reset = (data->port_reset & BIT_INDEX(attr->index))? 0 : 1; + + return sprintf(buf, "%d\n", is_reset); +} + +static ssize_t sfp_set_port_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_reg = 0, cpld_val = 0; /*, cpld_bit = 0; //remove unused variable */ + long is_reset; + int error; + + error = kstrtol(buf, 10, &is_reset); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + cpld_reg = 0x07; + + cpld_val = i2c_smbus_read_byte_data(client, cpld_reg); + + DEBUG_PRINT("current cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + /* Update reset status. CPLD defined 0 is reset state, 1 is normal state. + * is_reset: 0 is not reset. 1 is reset. + */ + if (is_reset == 0) { + data->port_reset |= BIT_INDEX(attr->index); + } + else { + data->port_reset &= ~BIT_INDEX(attr->index); + } + + alpha_i2c_cpld_write(0x5f, cpld_reg, cpld_val); + DEBUG_PRINT("write cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + dev_dbg(dev, "Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + } + msleep(200); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + mutex_unlock(&data->update_lock); + return data; + +exit: + mutex_unlock(&data->update_lock); + return NULL; +} + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (!sfp_is_port_present(client, attr->index)) { + return -ENODEV; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + if ((attr->index >= PORT1_TX_FAULT1) && (attr->index <= PORT8_TX_FAULT4)){ + val = (data->qsfp->status[2] & BIT_INDEX(attr->index - PORT1_TX_FAULT1)) ? 1 : 0; + } + else if ((attr->index >= PORT1_TX_DISABLE1) && (attr->index <= PORT8_TX_DISABLE4)){ + val = (data->qsfp->status[1] & BIT_INDEX(attr->index - PORT1_TX_DISABLE1)) ? 1 : 0; + } + else if ((attr->index >= PORT1_TX_DISABLE_ALL) && (attr->index <= PORT8_TX_DISABLE_ALL)){ + val = ((data->qsfp->status[1] & 0xF) == 0xF) ? 1 : 0; + } + if ((attr->index >= PORT1_RX_LOS1) && (attr->index <= PORT8_RX_LOS4)){ + val = (data->qsfp->status[0] & BIT_INDEX(attr->index - PORT1_RX_LOS1)) ? 1 : 0; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int result; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + result = kstrtol(buf, 10, &disable); + if (result) { + return result; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + mutex_lock(&data->update_lock); + + if((attr->index >= PORT1_TX_DISABLE_ALL) && (attr->index <= PORT8_TX_DISABLE_ALL)){ + DEBUG_PRINT ("disable:%ld %d==TX_DISABLE_ALL %u\r\n", disable, attr->index, data->qsfp->status[1]); + data->qsfp->status[1] = disable? 0xF:0; + } + else{ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - PORT1_TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - PORT1_TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + result = sfp_eeprom_write(client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + char ddm; + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (!sfp_is_port_present(client, attr->index)) { + return -ENODEV; + } + + status = sfp_eeprom_read(data->client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); + if (status < 0) { + return -EIO; + } + + return sprintf(buf, "%d\n", (ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK) ? 1 : 0); +} + +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + data = sfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + if ((attr->index >= PORT1_TX_FAULT) && (attr->index <= PORT8_TX_FAULT)){ + index = 0; + } + else if ((attr->index >= PORT1_TX_DISABLE) && (attr->index <= PORT8_TX_DISABLE)){ + index = 1; + } + if ((attr->index >= PORT1_RX_LOS) && (attr->index <= PORT8_RX_LOS)){ + index = 2; + } + + val = (data->ddm->status[index] & BIT_INDEX(attr->index)) ? 1 : 0; + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_show_eeprom(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + char devfile[96]; + struct file *sfd; + int i2c_index = 0; + int status, result, offset = 0xb; + int rdlen, rc; + mm_segment_t old_fs; + char buffer[256]; + + if (!sfp_is_port_present(client, attr->index)) { + return 0; + } + + if(strcmp(client->name, "sfpcpld1") == 0) + i2c_index = 14; + else if(strcmp(client->name, "sfpcpld9") == 0) + i2c_index = 15; + else if(strcmp(client->name, "sfpcpld17") == 0) + i2c_index = 16; + else if(strcmp(client->name, "sfpcpld25") == 0) + i2c_index = 17; + + snprintf(devfile, sizeof(devfile), "/sys/bus/i2c/devices/%d-0050/sfp_eeprom", i2c_index); + + /* Set module select register */ + result = i2c_smbus_write_byte_data(client, offset, BIT_INDEX(attr->index)); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data faill(%d)", result); + } + + /* Read SFP EEPROM */ + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + dev_info(&client->dev, "Failed to open file(%s)#%d", devfile, __LINE__); + return 0; + } + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + dev_info(&client->dev, "file %s cann't readable ?\n", devfile); + return 0; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + dev_info(&client->dev, "File(%s) empty!\n", devfile); + rc = 0; + goto exit; + } + + rc = sizeof(buffer); + memcpy(buf, buffer, rc); + + /* Reset module select register */ + result = i2c_smbus_write_byte_data(client, offset, 0); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data faill(%d)", result); + } + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + + return rc; +} + +#if 0 +static ssize_t qsfp_set_eeprom(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + DEBUG_PRINT("data->port:%d attr index:%d", data->port, attr->index); + return 1; +} +#endif + +/* SFP/QSFP common attributes for sysfs */ +#define DECLARE_PORT_NUMBER_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT1##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT2##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT3##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT4##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT5##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT6##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT7##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT8##_NUMBER); +#define DECLARE_PORT_NUMBER_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_number.dev_attr.attr, +DECLARE_PORT_NUMBER_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_IS_PRESENT_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_is_present, S_IRUGO, show_present, NULL, PORT##PORT1##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_is_present, S_IRUGO, show_present, NULL, PORT##PORT2##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_is_present, S_IRUGO, show_present, NULL, PORT##PORT3##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_is_present, S_IRUGO, show_present, NULL, PORT##PORT4##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_is_present, S_IRUGO, show_present, NULL, PORT##PORT5##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_is_present, S_IRUGO, show_present, NULL, PORT##PORT6##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_is_present, S_IRUGO, show_present, NULL, PORT##PORT7##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_is_present, S_IRUGO, show_present, NULL, PORT##PORT8##_PRESENT); +#define DECLARE_PORT_IS_PRESENT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_is_present.dev_attr.attr, +DECLARE_PORT_IS_PRESENT_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_TYPE_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT1##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT2##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT3##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT4##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT5##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT6##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT7##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT8##_TYPE); +#define DECLARE_PORT_TYPE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_type.dev_attr.attr, +DECLARE_PORT_TYPE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_RESET_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT1##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT2##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT3##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT4##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT5##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT6##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT7##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT8##_RESET); +#define DECLARE_PORT_RESET_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_reset.dev_attr.attr, +DECLARE_PORT_RESET_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +/* QSFP attributes for sysfs */ +#define DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT1##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT2##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT3##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT4##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT5##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT6##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT7##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT8##_RX_LOS##INDEX); +#define DECLARE_PORT_RX_LOSn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_rx_los##INDEX.dev_attr.attr, +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT1##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT2##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT3##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT4##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT5##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT6##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT7##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT8##_TX_DISABLE##INDEX); + +#define DECLARE_PORT_TX_DISABLEn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_disable##INDEX.dev_attr.attr, +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT1##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT2##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT3##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT4##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT5##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT6##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT7##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT8##_TX_FAULT##INDEX); +#define DECLARE_PORT_TX_FAULTn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_fault##INDEX.dev_attr.attr, +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT1##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT2##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT3##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT4##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT5##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT6##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT7##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT8##_EEPROM); +#define DECLARE_PORT_EEPROMTn_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_eeprom.dev_attr.attr, +DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +static struct attribute *qsfp_attributes[] = { + DECLARE_PORT_NUMBER_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TYPE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_IS_PRESENT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RESET_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_EEPROMTn_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + NULL +}; + + +/* SFP msa attributes for sysfs */ +static struct attribute *sfp_msa_attributes[] = { + DECLARE_PORT_NUMBER_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TYPE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_IS_PRESENT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RESET_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + NULL +}; + +/* SFP ddm attributes for sysfs */ +#define DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT1##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT2##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT3##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT4##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT5##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_RX_LOS); +#define DECLARE_RX_LOS_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_rx_los.dev_attr.attr, +DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT1##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT2##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT3##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT4##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT5##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT6##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT7##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT8##_TX_DISABLE); +#define DECLARE_TX_DISABLE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_disable.dev_attr.attr, +DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_TX_FAULT_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT1##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT2##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT3##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT4##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT5##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_TX_FAULT); +#define DECLARE_TX_FAULT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_fault.dev_attr.attr, +DECLARE_TX_FAULT_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +static struct attribute *sfp_ddm_attributes[] = { + DECLARE_RX_LOS_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_TX_DISABLE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_TX_FAULT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + NULL +}; + +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return data_len; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_write_byte_data(client, command, *data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return 1; +#endif + + +} + + +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", (int)off, (int)count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_write(data, buf, off, count); +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + /* result = data_len; */ + +abort: + return result; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_read_byte_data(client, command); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result); + goto abort; + } + + *data = (u8)result; + result = 1; + +abort: + return result; +#endif +} + +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", (int)off, (int)count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_read(data, buf, off, count); +} + +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); + if (status) { + dev_info(&client->dev, "sfp msa '%s' (sfp_sysfs_eeprom_init fail...)\n", client->name); + /* goto exit_remove; */ + } + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + return 0; + +/* exit_remove: */ + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group sfp_ddm_group = { + .attrs = sfp_ddm_attributes, +}; + +static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_ddm_data **data) +{ + int status; + struct sfp_ddm_data *ddm; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); + if (!ddm) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = ddm; + dev_info(&client->dev, "sfp ddm '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); +exit_free: + kfree(ddm); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + if (client->addr == SFP_CPLD_I2C_ADDR){ + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + } + + if (client->addr == SFP_EEPROM_A0_I2C_ADDR){ + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); + if (status) { + goto exit_remove; + } + } + + /* Bring QSFPs out of reset */ + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct sfp_port_data *data = NULL; + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + if ((client->addr != SFP_EEPROM_A0_I2C_ADDR) && (client->addr != SFP_CPLD_I2C_ADDR)){ + DEBUG_PRINT("client->addr:0x%0x\n", client->addr); + return -ENODEV; + } + + data->driver_type = DRIVER_TYPE_QSFP; + return qsfp_probe(client, dev_id, &data->qsfp); +} + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if (client->addr == SFP_CPLD_I2C_ADDR) + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if (client->addr == SFP_CPLD_I2C_ADDR) + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if (client->addr == SFP_CPLD_I2C_ADDR) + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_SFP_DDM: + return sfp_ddm_remove(client, data->ddm); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + + return 0; +} + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Philip Wang "); +MODULE_DESCRIPTION("alphanetworks snh60a0-320fv2 driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_onie_eeprom.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_onie_eeprom.c new file mode 100644 index 000000000000..d8e246ec2a86 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_onie_eeprom.c @@ -0,0 +1,268 @@ +/* + * A driver for alphanetworks_snh60a0_320fv2 onie eeprom + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Robin Chen + * 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 + * 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. + * see + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EEPROM_SIZE 256 + +#define SYS_LED_REG 0x8 +#define FAN12_LED_REG 0x9 +#define FAN34_LED_REG 0xA +#define FAN56_LED_REG 0xB +#define SYS_RESET1_REG 0x2 + +#define SYS_LOCATOR_LED_BITS 0x01 +#define SYS_PWR_LED_BITS 0x0E +#define SYS_STATUS_LED_BITS 0x70 +#define FAN135_LED_BITS 0x07 +#define FAN246_LED_BITS 0x38 + + +extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +static ssize_t onie_read(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t onie_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for alphanetworks_snh60a0_320fv2_onie_eeprom */ +static const unsigned short normal_i2c[] = { 0x56, I2C_CLIENT_END }; + + +enum sysfs_onie_attributes { + ONIE_RW, +}; + +static SENSOR_DEVICE_ATTR(eeprom, (0660), onie_read, onie_write, ONIE_RW); + +static struct attribute *alphanetworks_snh60a0_320fv2_onie_attributes[] = { + &sensor_dev_attr_eeprom.dev_attr.attr, + NULL +}; + +static const struct attribute_group alphanetworks_snh60a0_320fv2_onie_group = { + .attrs = alphanetworks_snh60a0_320fv2_onie_attributes, +}; + + +static ssize_t onie_read(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + __u8 read_write; + unsigned short offset = 0; + union i2c_smbus_data temp; + char rbuf[EEPROM_SIZE]; + + for( offset=0 ; offset < EEPROM_SIZE ; ++offset ) + { + read_write = I2C_SMBUS_WRITE; + offset = offset & 0x3fff; + temp.byte = (u8)offset; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 2, &temp); + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 2, &temp); + + read_write = I2C_SMBUS_READ; + temp.byte = 0xaa; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 1, &temp); + if (!res) + { + res = temp.byte; + rbuf[offset] = (char)temp.byte; + } + + read_write = I2C_SMBUS_READ; + temp.byte = 0xbb; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 1, &temp); + if (!res) + { + res = temp.byte; + } + } + + memcpy(buf, rbuf, EEPROM_SIZE); + return EEPROM_SIZE; +} + +static ssize_t onie_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int error, write, command, read; + + error = kstrtoint(buf, 10, &write); + if (error) + return error; + + if (write < 0 || write > 255) + return -EINVAL; + + /* Not support yet */ + + return count; +} + + + +static void alpha_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int onie_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_onie_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int onie_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_onie_group); + alpha_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id onie_eeprom_id[] = { + { "snh60a0_onie_eeprom", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, onie_eeprom_id); + +static struct i2c_driver onie_eeprom_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "snh60a0_onie_eeprom", + }, + .probe = onie_eeprom_probe, + .remove = onie_eeprom_remove, + .id_table = onie_eeprom_id, + .address_list = normal_i2c, +}; + + +static int __init onie_eeprom_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&onie_eeprom_driver); +} + +static void __exit onie_eeprom_exit(void) + +{ + i2c_del_driver(&onie_eeprom_driver); +} + + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("onie eeprom driver"); +MODULE_LICENSE("GPL"); + +module_init(onie_eeprom_init); +module_exit(onie_eeprom_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_power_cpld.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_power_cpld.c new file mode 100644 index 000000000000..c9a9104d266f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_power_cpld.c @@ -0,0 +1,507 @@ +/* + * A hwmon driver for the alphanetworks_snh60a0_320fv2_power_cpld + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Robin Chen + * 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 + * 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. + * see + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DRIVER_NAME "snh60a0_power_cpld" +#define PSU1_STATUS_REG 0x3 +#define PSU2_STATUS_REG 0x4 +#define FAN_PWM_REG 0x23 + +#define PSU_PRESENT_BIT 0x4 +#define PSU_POWER_BIT 0x2 +#define FAN_PRESENT_BIT 0x2 + + +static ssize_t psu_show_status(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t fan_pwm_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +static ssize_t fan_show_status(struct device *dev, struct device_attribute *attr, char *buf); + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for alphanetworks_snh60a0_320fv2_power_cpld */ +static const unsigned short normal_i2c[] = { 0x5E, I2C_CLIENT_END }; + +struct alphanetworks_snh60a0_320fv2_pwr_cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; + char model_name[9]; /* Model name, read from eeprom */ +}; + + +enum sysfs_psu_attributes { + PSU1_PRESENT, + PSU2_PRESENT, + PSU1_POWER_GOOD, + PSU2_POWER_GOOD, + FAN_PWM, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT, + FAN1_PRESENT=0x10, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN6_REAR_SPEED_RPM, +}; + +static SENSOR_DEVICE_ATTR(psu1_present, S_IRUGO, psu_show_status, NULL, PSU1_PRESENT); +static SENSOR_DEVICE_ATTR(psu2_present, S_IRUGO, psu_show_status, NULL, PSU2_PRESENT); +static SENSOR_DEVICE_ATTR(psu1_power_good, S_IRUGO, psu_show_status, NULL, PSU1_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu2_power_good, S_IRUGO, psu_show_status, NULL, PSU2_POWER_GOOD); +static SENSOR_DEVICE_ATTR(fan_pwm, (0660), fan_pwm_show, set_fan_pwm, FAN_PWM); +static SENSOR_DEVICE_ATTR(fan1_present, S_IRUGO, fan_show_status, NULL, FAN1_PRESENT); +static SENSOR_DEVICE_ATTR(fan2_present, S_IRUGO, fan_show_status, NULL, FAN2_PRESENT); +static SENSOR_DEVICE_ATTR(fan3_present, S_IRUGO, fan_show_status, NULL, FAN3_PRESENT); +static SENSOR_DEVICE_ATTR(fan4_present, S_IRUGO, fan_show_status, NULL, FAN4_PRESENT); +static SENSOR_DEVICE_ATTR(fan5_present, S_IRUGO, fan_show_status, NULL, FAN5_PRESENT); +static SENSOR_DEVICE_ATTR(fan6_present, S_IRUGO, fan_show_status, NULL, FAN6_PRESENT); +static SENSOR_DEVICE_ATTR(fan1_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN1_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN2_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN3_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN4_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan5_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN5_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan6_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN6_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan1_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN1_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN2_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN3_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN4_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan5_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN5_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan6_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN6_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, fan_show_status, NULL, FAN1_FAULT); static SENSOR_DEVICE_ATTR(fan11_fault, S_IRUGO, fan_show_status, NULL, FAN1_FAULT); +static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, fan_show_status, NULL, FAN2_FAULT); static SENSOR_DEVICE_ATTR(fan12_fault, S_IRUGO, fan_show_status, NULL, FAN2_FAULT); +static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, fan_show_status, NULL, FAN3_FAULT); static SENSOR_DEVICE_ATTR(fan13_fault, S_IRUGO, fan_show_status, NULL, FAN3_FAULT); +static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, fan_show_status, NULL, FAN4_FAULT); static SENSOR_DEVICE_ATTR(fan14_fault, S_IRUGO, fan_show_status, NULL, FAN4_FAULT); +static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, fan_show_status, NULL, FAN5_FAULT); static SENSOR_DEVICE_ATTR(fan15_fault, S_IRUGO, fan_show_status, NULL, FAN5_FAULT); +static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, fan_show_status, NULL, FAN6_FAULT); static SENSOR_DEVICE_ATTR(fan16_fault, S_IRUGO, fan_show_status, NULL, FAN6_FAULT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, fan_show_status, NULL, FAN1_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, fan_show_status, NULL, FAN1_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, fan_show_status, NULL, FAN2_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan12_input, S_IRUGO, fan_show_status, NULL, FAN2_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, fan_show_status, NULL, FAN3_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan13_input, S_IRUGO, fan_show_status, NULL, FAN3_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, fan_show_status, NULL, FAN4_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan14_input, S_IRUGO, fan_show_status, NULL, FAN4_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, fan_show_status, NULL, FAN5_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan15_input, S_IRUGO, fan_show_status, NULL, FAN5_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, fan_show_status, NULL, FAN6_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan16_input, S_IRUGO, fan_show_status, NULL, FAN6_REAR_SPEED_RPM); + + +static struct attribute *alphanetworks_snh60a0_320fv2_psu_attributes[] = { + &sensor_dev_attr_psu1_present.dev_attr.attr, + &sensor_dev_attr_psu2_present.dev_attr.attr, + &sensor_dev_attr_psu1_power_good.dev_attr.attr, + &sensor_dev_attr_psu2_power_good.dev_attr.attr, + &sensor_dev_attr_fan_pwm.dev_attr.attr, + &sensor_dev_attr_fan1_present.dev_attr.attr, + &sensor_dev_attr_fan2_present.dev_attr.attr, + &sensor_dev_attr_fan3_present.dev_attr.attr, + &sensor_dev_attr_fan4_present.dev_attr.attr, + &sensor_dev_attr_fan5_present.dev_attr.attr, + &sensor_dev_attr_fan6_present.dev_attr.attr, + &sensor_dev_attr_fan1_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan5_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan6_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan1_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan5_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan6_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan1_fault.dev_attr.attr, &sensor_dev_attr_fan11_fault.dev_attr.attr, + &sensor_dev_attr_fan2_fault.dev_attr.attr, &sensor_dev_attr_fan12_fault.dev_attr.attr, + &sensor_dev_attr_fan3_fault.dev_attr.attr, &sensor_dev_attr_fan13_fault.dev_attr.attr, + &sensor_dev_attr_fan4_fault.dev_attr.attr, &sensor_dev_attr_fan14_fault.dev_attr.attr, + &sensor_dev_attr_fan5_fault.dev_attr.attr, &sensor_dev_attr_fan15_fault.dev_attr.attr, + &sensor_dev_attr_fan6_fault.dev_attr.attr, &sensor_dev_attr_fan16_fault.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan11_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan12_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, &sensor_dev_attr_fan13_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, &sensor_dev_attr_fan14_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, &sensor_dev_attr_fan15_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, &sensor_dev_attr_fan16_input.dev_attr.attr, + NULL +}; + +static const struct attribute_group alphanetworks_snh60a0_320fv2_psu_group = { + .attrs = alphanetworks_snh60a0_320fv2_psu_attributes, +}; + + +static ssize_t psu_show_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + + switch(sda->index) { + case PSU1_PRESENT: + case PSU1_POWER_GOOD: + command = PSU1_STATUS_REG; + break; + case PSU2_PRESENT: + case PSU2_POWER_GOOD: + command = PSU2_STATUS_REG; + break; + } + + val = i2c_smbus_read_byte_data(client, command); + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + switch(sda->index) { + case PSU1_PRESENT: + case PSU2_PRESENT: + res = (val & PSU_PRESENT_BIT ? 1 : 0 ); + break; + case PSU1_POWER_GOOD: + case PSU2_POWER_GOOD: + res = (val & PSU_POWER_BIT ? 1 : 0 ); + break; + } + + return sprintf(buf, "%d\n", res); +} + +static ssize_t fan_pwm_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, FAN_PWM_REG); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 0xFF) + return -EINVAL; + + i2c_smbus_write_byte_data(client, FAN_PWM_REG, value); + + return count; +} + +static ssize_t fan_show_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + // struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev); + ssize_t ret = 0; + int val, val2; + + switch (sda->index) { + /* case FAN_DUTY_CYCLE_PERCENTAGE: */ + /* { */ + /* u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); */ + /* ret = sprintf(buf, "%u\n", duty_cycle); */ + /* break; */ + /* } */ + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + val = i2c_smbus_read_byte_data(client, sda->index); + ret = sprintf(buf, "%d\n", val * 150); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + val = i2c_smbus_read_byte_data(client, sda->index); + ret = sprintf(buf, "%d\n", (val & FAN_PRESENT_BIT) ? 1 : 0); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + val = i2c_smbus_read_byte_data(client, (sda->index - FAN1_FAULT)*2 + FAN1_FRONT_SPEED_RPM); + val2 = i2c_smbus_read_byte_data(client, (sda->index - FAN1_FAULT)*2 + FAN1_REAR_SPEED_RPM); + ret = sprintf(buf, "%d\n", (val|val2) ? 0 : 1); + break; + default: + break; + } + + return ret; +} + + +static void alpha_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int alpha_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct alphanetworks_snh60a0_320fv2_pwr_cpld_data* data; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct alphanetworks_snh60a0_320fv2_pwr_cpld_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_psu_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_add_client(client); + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit; + } + + dev_info(&client->dev, "%s: pwr_cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit: + return status; +} + +static int alpha_i2c_cpld_remove(struct i2c_client *client) +{ + struct alphanetworks_snh60a0_320fv2_pwr_cpld_data *data = i2c_get_clientdata(client); + sysfs_remove_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_psu_group); + alpha_i2c_cpld_remove_client(client); + kfree(data); + + return 0; +} + +static const struct i2c_device_id alpha_i2c_cpld_id[] = { + { DRIVER_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, alpha_i2c_cpld_id); + +static struct i2c_driver alpha_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRIVER_NAME, + }, + .probe = alpha_i2c_cpld_probe, + .remove = alpha_i2c_cpld_remove, + .id_table = alpha_i2c_cpld_id, + .address_list = normal_i2c, +}; + +int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_cpld_read); + +int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_cpld_write); + +static int __init alpha_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&alpha_i2c_cpld_driver); +} + +static void __exit alpha_i2c_cpld_exit(void) +{ + i2c_del_driver(&alpha_i2c_cpld_driver); +} + +static struct dmi_system_id alphanetworks_snh60a0_320fv2_dmi_table[] = { + { + .ident = "Alpha Zion", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alpha"), + DMI_MATCH(DMI_PRODUCT_NAME, "Zion"), + }, + } +}; + +int platform_alphanetworks_snh60a0_320fv2(void) +{ + return dmi_check_system(alphanetworks_snh60a0_320fv2_dmi_table); +} +EXPORT_SYMBOL(platform_alphanetworks_snh60a0_320fv2); + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("alpha_power_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(alpha_i2c_cpld_init); +module_exit(alpha_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_system_cpld.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_system_cpld.c new file mode 100644 index 000000000000..13c302b35696 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_system_cpld.c @@ -0,0 +1,380 @@ +/* + * A hwmon driver for the alphanetworks_snh60a0_320fv2_system_cpld + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Robin Chen + * 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 + * 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. + * see + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SYS_LED_REG 0x8 +#define FAN12_LED_REG 0x9 +#define FAN34_LED_REG 0xA +#define FAN56_LED_REG 0xB +#define SYS_RESET1_REG 0x2 +#define SWI_CTRL_REG 0x4 + +#define SYS_LOCATOR_LED_BITS 0x01 +#define SYS_PWR_LED_BITS 0x0E +#define SYS_STATUS_LED_BITS 0x70 +#define FAN135_LED_BITS 0x07 +#define FAN246_LED_BITS 0x38 +#define REST_BUTTON_BITS 0x0 + + +extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +static ssize_t sys_led_read(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t sys_led_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for alphanetworks_snh60a0_320fv2_system_cpld */ +static const unsigned short normal_i2c[] = { 0x5F, I2C_CLIENT_END }; + + +enum sysfs_sys_attributes { + SYS_LOCATOR, + SYS_PWR, + SYS_STATUS, + FAN1_LED, + FAN2_LED, + FAN3_LED, + FAN4_LED, + FAN5_LED, + FAN6_LED, + SYS_REST1, + SWI_CTRL, +}; + +static SENSOR_DEVICE_ATTR(sys_locator, (0660), sys_led_read, sys_led_write, SYS_LOCATOR); +static SENSOR_DEVICE_ATTR(sys_pwr, (0660), sys_led_read, sys_led_write, SYS_PWR); +static SENSOR_DEVICE_ATTR(sys_status, (0600), sys_led_read, sys_led_write, SYS_STATUS); +static SENSOR_DEVICE_ATTR(fan1_led, (0660), sys_led_read, sys_led_write, FAN1_LED); +static SENSOR_DEVICE_ATTR(fan2_led, (0660), sys_led_read, sys_led_write, FAN2_LED); +static SENSOR_DEVICE_ATTR(fan3_led, (0660), sys_led_read, sys_led_write, FAN3_LED); +static SENSOR_DEVICE_ATTR(fan4_led, (0660), sys_led_read, sys_led_write, FAN4_LED); +static SENSOR_DEVICE_ATTR(fan5_led, (0660), sys_led_read, sys_led_write, FAN5_LED); +static SENSOR_DEVICE_ATTR(fan6_led, (0660), sys_led_read, sys_led_write, FAN6_LED); +static SENSOR_DEVICE_ATTR(sys_reset1, (0660), sys_led_read, sys_led_write, SYS_REST1); +static SENSOR_DEVICE_ATTR(swi_ctrl, (0660), sys_led_read, NULL, SWI_CTRL); + +static struct attribute *alphanetworks_snh60a0_320fv2_sys_attributes[] = { + &sensor_dev_attr_sys_locator.dev_attr.attr, + &sensor_dev_attr_sys_pwr.dev_attr.attr, + &sensor_dev_attr_sys_status.dev_attr.attr, + &sensor_dev_attr_fan1_led.dev_attr.attr, + &sensor_dev_attr_fan2_led.dev_attr.attr, + &sensor_dev_attr_fan3_led.dev_attr.attr, + &sensor_dev_attr_fan4_led.dev_attr.attr, + &sensor_dev_attr_fan5_led.dev_attr.attr, + &sensor_dev_attr_fan6_led.dev_attr.attr, + &sensor_dev_attr_sys_reset1.dev_attr.attr, + &sensor_dev_attr_swi_ctrl.dev_attr.attr, + NULL +}; + +static const struct attribute_group alphanetworks_snh60a0_320fv2_sys_group = { + .attrs = alphanetworks_snh60a0_320fv2_sys_attributes, +}; + + +static ssize_t sys_led_read(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + + switch(sda->index) { + case SYS_LOCATOR: + case SYS_PWR: + case SYS_STATUS: + command = SYS_LED_REG; + break; + case FAN1_LED: + case FAN2_LED: + case FAN3_LED: + case FAN4_LED: + case FAN5_LED: + case FAN6_LED: + command = FAN12_LED_REG + (sda->index - FAN1_LED)/2; + break; + case SYS_REST1: + command = SYS_RESET1_REG; + break; + case SWI_CTRL: + command = SWI_CTRL_REG; + break; + } + + val = i2c_smbus_read_byte_data(client, command); + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + switch(sda->index) { + case SYS_LOCATOR: + res = (val & SYS_LOCATOR_LED_BITS) >> 0; + break; + case SYS_PWR: + res = (val & SYS_PWR_LED_BITS) >> 1; + break; + case SYS_STATUS: + res = (val & SYS_STATUS_LED_BITS) >> 4; + break; + case FAN1_LED: + case FAN3_LED: + case FAN5_LED: + res = (val & FAN135_LED_BITS) >> 0; + break; + case FAN2_LED: + case FAN4_LED: + case FAN6_LED: + res = (val & FAN246_LED_BITS) >> 3; + break; + case SYS_REST1: + res = val; + break; + case SWI_CTRL: + res = (val & REST_BUTTON_BITS) >> 0; + break; + } + + return sprintf(buf, "%d\n", res); +} + +static ssize_t sys_led_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + int error, write, command, read; + + error = kstrtoint(buf, 10, &write); + if (error) + return error; + + + switch(sda->index) { + case SYS_LOCATOR: + if(write < 0 || write > 2) + return -EINVAL; + case SYS_PWR: + case SYS_STATUS: + if (write < 0 || write > 7) + return -EINVAL; + command = SYS_LED_REG; + break; + case FAN1_LED: + case FAN2_LED: + case FAN3_LED: + case FAN4_LED: + case FAN5_LED: + case FAN6_LED: + if (write < 0 || write > 7) + return -EINVAL; + command = FAN12_LED_REG + (sda->index - FAN1_LED)/2; + break; + case SYS_REST1: + if (write < 0 || write > 15) + return -EINVAL; + command = SYS_RESET1_REG; + break; + } + + read = i2c_smbus_read_byte_data(client, command); + if (read < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, read); + } + + switch(sda->index) { + case SYS_LOCATOR: + read &= ~SYS_LOCATOR_LED_BITS; + read |= write << 0; + break; + case SYS_PWR: + read &= ~SYS_PWR_LED_BITS; + read |= write << 1; + break; + case SYS_STATUS: + read &= ~SYS_STATUS_LED_BITS; + read |= write << 4; + break; + case FAN1_LED: + case FAN3_LED: + case FAN5_LED: + read &= ~FAN135_LED_BITS; + read |= write << 0; + break; + case FAN2_LED: + case FAN4_LED: + case FAN6_LED: + read &= ~FAN246_LED_BITS; + read |= write << 3; + break; + case SYS_REST1: + read = write; + break; + } + + i2c_smbus_write_byte_data(client, command, read); + + return count; +} + + + +static void alpha_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int alpha_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_sys_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int alpha_i2c_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_sys_group); + alpha_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id alpha_i2c_cpld_id[] = { + { "snh60a0_system_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, alpha_i2c_cpld_id); + +static struct i2c_driver alpha_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "snh60a0_system_cpld", + }, + .probe = alpha_i2c_cpld_probe, + .remove = alpha_i2c_cpld_remove, + .id_table = alpha_i2c_cpld_id, + .address_list = normal_i2c, +}; + + +static int __init alpha_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&alpha_i2c_cpld_driver); +} + +static void __exit alpha_i2c_cpld_exit(void) +{ + i2c_del_driver(&alpha_i2c_cpld_driver); +} + + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("alpha_system_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(alpha_i2c_cpld_init); +module_exit(alpha_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/service/snh60a0-platform-init.service b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/service/snh60a0-platform-init.service new file mode 100644 index 000000000000..564a8dcdb7a4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/service/snh60a0-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Alphanetworks SNH60A0-320F Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/alphanetworks_snh60a0_util.py install +ExecStop=/usr/local/bin/alphanetworks_snh60a0_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/setup.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/setup.py new file mode 100644 index 000000000000..94435eef3c0e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='snh60a0_320fv2', + version='1.0', + description='Module to initialize Alphanetworks SNH60A0-320FV2 platforms', + + packages=['snh60a0_320fv2'], + package_dir={'snh60a0_320fv2': 'snh60a0-320fv2/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/utils/alphanetworks_snh60a0_util.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/utils/alphanetworks_snh60a0_util.py new file mode 100755 index 000000000000..870267e31c26 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/utils/alphanetworks_snh60a0_util.py @@ -0,0 +1,399 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Alphanetworks Technology Corporation. +# Robin Chen +# 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 +# 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. +# see +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'snh60a0-320fv2' +device_path = "x86_64-alphanetworks_snh60a0_320fv2-r0" +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +FORCE = 0 + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + 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 PROJECT_NAME.upper()+": "+txt + return + +def log_os_system(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 + +def driver_check(): + ret, lsmod = log_os_system("lsmod | grep alphanetworks", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x', +'modprobe optoe' , +'modprobe snh60a0_power_cpld' , +'modprobe snh60a0_system_cpld' , +'modprobe snh60a0_onie_eeprom' , +'modprobe alphanetworks_snh60a0_320fv2_sfp' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + if kos[i].find('pca954') != -1: + status, output = log_os_system(kos[i]+ " force_deselect_on_exit=1", 1) + else: + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +i2c_prefix = '/sys/bus/i2c/devices/' + +sfp_map = [14,15,16,17] +mknod =[ +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-6/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-8/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo snh60a0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo snh60a0_power_cpld 0x5e > /sys/bus/i2c/devices/i2c-0/new_device', +'echo snh60a0_system_cpld 0x5f > /sys/bus/i2c/devices/i2c-9/new_device', +'echo lm75 0x4D > /sys/bus/i2c/devices/i2c-4/new_device', +'echo lm75 0x4C > /sys/bus/i2c/devices/i2c-5/new_device', +'echo lm75 0x4F > /sys/bus/i2c/devices/i2c-0/new_device' ] + +mknod2 =[ +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-6/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-8/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo snh60a0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo snh60a0_power_cpld 0x5e > /sys/bus/i2c/devices/i2c-1/new_device', +'echo snh60a0_system_cpld 0x5f > /sys/bus/i2c/devices/i2c-9/new_device', +'echo lm75 0x4D > /sys/bus/i2c/devices/i2c-4/new_device', +'echo lm75 0x4C > /sys/bus/i2c/devices/i2c-5/new_device', +'echo lm75 0x4F > /sys/bus/i2c/devices/i2c-1/new_device' ] + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x76 is exist @ i2c-0 + + status, output = log_os_system("i2cdetect -l | grep I801 | grep i2c-0", 0) + if not output: + order = 1 + else: + order = 0 + + if not device_exist(): + #order = 1 + tmp = "sed -i 's/0-/1-/g' /usr/share/sonic/device/"+device_path+"/fancontrol" + status, output = log_os_system(tmp, 0) + tmp = "sed -i 's/0-/1-/g' /usr/share/sonic/device/"+device_path+"/plugins/led_control.py" + status, output = log_os_system(tmp, 0) + else: + #order = 0 + tmp = "sed -i 's/1-/0-/g' /usr/share/sonic/device/"+device_path+"/fancontrol" + status, output = log_os_system(tmp, 0) + tmp = "sed -i 's/1-/0-/g' /usr/share/sonic/device/"+device_path+"/plugins/led_control.py" + status, output = log_os_system(tmp, 0) + + + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x76 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + if mknod2[i].find('lm75') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + if mknod[i].find('lm75') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + status, output =log_os_system("echo 0 > /sys/bus/i2c/devices/9-005f/sys_reset1", 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0, 32): + index = i / 8 + port = i % 8 + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + + if reg_sfp == 1: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x5f > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + status, output = log_os_system("i2cdetect -l | grep I801 | grep i2c-0", 0) + + if not output: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0, 32): + index = i / 8 + port = i % 8 + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + + if reg_sfp == 1: + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x5f > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + tmp = "find /var/lib/docker/overlay -iname fancontrol | grep usr/sbin/fancontrol | xargs cat | sed '429d' | sed '428a if \[ $? -ne 1 \]' | sed '425d' | sed '424a return' > /tmp/tmp_fancontrol" + status, output = log_os_system(tmp, 1) + tmp = "fancontrol_tmp=`find /var/lib/docker/overlay -iname fancontrol | grep usr/sbin/fancontrol` ; cp /tmp/tmp_fancontrol $fancontrol_tmp" + status, output = log_os_system(tmp, 1) + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/classes/__init__.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/Makefile b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/Makefile new file mode 100644 index 000000000000..ec14f1229d66 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/Makefile @@ -0,0 +1,8 @@ +# obj-m:=accton_as7712_32x_fan.o accton_as7712_32x_sfp.o leds-accton_as7712_32x.o \ +# goreme_system_cpld.o ym2651y.o optoe.o + +obj-m:=alphanetworks_snh60b0-640f_sfp.o snh60b0-640f_system_cpld.o snh60b0-640f_power_cpld.o snh60b0-640f_onie_eeprom.o + + +# obj-m:=accton_as7712_32x_fan.o accton_as7712_32x_sfp.o leds-accton_as7712_32x.o \ +# accton_as7712_32x_psu.o accton_i2c_cpld.o ym2651y.o optoe.o diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/alphanetworks_snh60b0-640f_sfp.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/alphanetworks_snh60b0-640f_sfp.c new file mode 100644 index 000000000000..8985790cce6c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/alphanetworks_snh60b0-640f_sfp.c @@ -0,0 +1,2076 @@ +/* + * SFP driver for alphanetworks snh60b0-640f sfp + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Philip Wang + * + * 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 + * 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. + * see + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "snh60b0_640f_sfp" + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s[%s,%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define NUM_OF_SFP_PORT 64 +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +#define SFP_CPLD_I2C_ADDR 0x5F +#define SFP_EEPROM_A0_I2C_ADDR 0x50 +#define SFP_EEPROM_A2_I2C_ADDR 0x68 +#define SFP_PCA9506_I2C_ADDR 0x20 + + +#define SFPPLUS_1_PORT_NUMBER 64 +#define SFPPLUS_2_PORT_NUMBER 65 + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 +#define SFF8472_10G_BASE_MASK 0xF0 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +/* extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); */ +extern int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { SFP_EEPROM_A0_I2C_ADDR, SFP_EEPROM_A2_I2C_ADDR, SFP_CPLD_I2C_ADDR, SFP_PCA9506_I2C_ADDR, I2C_CLIENT_END }; + +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +sfp1, sfp2, sfp3, sfp4, sfp5, sfp6, sfp7, sfp8, +sfp9, sfp10, sfp11, sfp12, sfp13, sfp14, sfp15, sfp16, +sfp17, sfp18, sfp19, sfp20, sfp21, sfp22, sfp23, sfp24, +sfp25, sfp26, sfp27, sfp28, sfp29, sfp30, sfp31, sfp32, +sfp33, sfp34, sfp35, sfp36, sfp37, sfp38, sfp39, sfp40, +sfp41, sfp42, sfp43, sfp44, sfp45, sfp46, sfp47, sfp48, +sfp49, sfp50, sfp51, sfp52, sfp53, sfp54, sfp55, sfp56, +sfp57, sfp58, sfp59, sfp60, sfp61, sfp62, sfp63, sfp64, +sfp65, sfp66 +}; + +static const struct i2c_device_id sfp_device_id[] = { +{ "sfpcpld1", sfp1 }, { "sfpcpld2", sfp2 }, { "sfpcpld3", sfp3 }, { "sfpcpld4", sfp4 }, +{ "sfpcpld5", sfp5 }, { "sfpcpld6", sfp6 }, { "sfpcpld7", sfp7 }, { "sfpcpld8", sfp8 }, +{ "sfpcpld9", sfp9 }, { "sfpcpld10", sfp10 }, { "sfpcpld11", sfp11 }, { "sfpcpld12", sfp12 }, +{ "sfpcpld13", sfp13 }, { "sfpcpld14", sfp14 }, { "sfpcpld15", sfp15 }, { "sfpcpld16", sfp16 }, +{ "sfpcpld17", sfp17 }, { "sfpcpld18", sfp18 }, { "sfpcpld19", sfp19 }, { "sfpcpld20", sfp20 }, +{ "sfpcpld21", sfp21 }, { "sfpcpld22", sfp22 }, { "sfpcpld23", sfp23 }, { "sfpcpld24", sfp24 }, +{ "sfpcpld25", sfp25 }, { "sfpcpld26", sfp26 }, { "sfpcpld27", sfp27 }, { "sfpcpld28", sfp28 }, +{ "sfpcpld29", sfp29 }, { "sfpcpld30", sfp30 }, { "sfpcpld31", sfp31 }, { "sfpcpld32", sfp32 }, +{ "sfpcpld33", sfp33 }, { "sfpcpld34", sfp34 }, { "sfpcpld35", sfp35 }, { "sfpcpld36", sfp36 }, +{ "sfpcpld37", sfp37 }, { "sfpcpld38", sfp38 }, { "sfpcpld39", sfp39 }, { "sfpcpld40", sfp40 }, +{ "sfpcpld41", sfp41 }, { "sfpcpld42", sfp42 }, { "sfpcpld43", sfp43 }, { "sfpcpld44", sfp44 }, +{ "sfpcpld45", sfp45 }, { "sfpcpld46", sfp46 }, { "sfpcpld47", sfp47 }, { "sfpcpld48", sfp48 }, +{ "sfpcpld49", sfp49 }, { "sfpcpld50", sfp50 }, { "sfpcpld51", sfp51 }, { "sfpcpld52", sfp52 }, +{ "sfpcpld53", sfp53 }, { "sfpcpld54", sfp54 }, { "sfpcpld55", sfp55 }, { "sfpcpld56", sfp56 }, +{ "sfpcpld57", sfp57 }, { "sfpcpld58", sfp58 }, { "sfpcpld59", sfp59 }, { "sfpcpld60", sfp60 }, +{ "sfpcpld61", sfp61 }, { "sfpcpld62", sfp62 }, { "sfpcpld63", sfp63 }, { "sfpcpld64", sfp64 }, +{ "sfpcpld65", sfp65 }, { "sfpcpld66", sfp66 }, {} +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28 +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[2]; /* index 0 => device id + 1 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 2 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +}; + +struct sfp_ddm_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + struct eeprom_data eeprom; +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + u64 port_reset; /* reset status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct sfp_ddm_data *ddm; + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +enum sfp_sysfs_port_num_attributes { + PORT1_NUMBER, + PORT2_NUMBER, + PORT3_NUMBER, + PORT4_NUMBER, + PORT5_NUMBER, + PORT6_NUMBER, + PORT7_NUMBER, + PORT8_NUMBER, + PORT9_NUMBER, + PORT10_NUMBER, + PORT11_NUMBER, + PORT12_NUMBER, + PORT13_NUMBER, + PORT14_NUMBER, + PORT15_NUMBER, + PORT16_NUMBER, + PORT_NUMBER_MAX +}; + +enum sfp_sysfs_present_attributes { + PORT1_PRESENT, + PORT2_PRESENT, + PORT3_PRESENT, + PORT4_PRESENT, + PORT5_PRESENT, + PORT6_PRESENT, + PORT7_PRESENT, + PORT8_PRESENT, + PORT9_PRESENT, + PORT10_PRESENT, + PORT11_PRESENT, + PORT12_PRESENT, + PORT13_PRESENT, + PORT14_PRESENT, + PORT15_PRESENT, + PORT16_PRESENT, + PORT1_PRESENT_ALL, + PORT2_PRESENT_ALL, + PORT3_PRESENT_ALL, + PORT4_PRESENT_ALL, + PORT5_PRESENT_ALL, + PORT6_PRESENT_ALL, + PORT7_PRESENT_ALL, + PORT8_PRESENT_ALL, + PORT9_PRESENT_ALL, + PORT10_PRESENT_ALL, + PORT11_PRESENT_ALL, + PORT12_PRESENT_ALL, + PORT13_PRESENT_ALL, + PORT14_PRESENT_ALL, + PORT15_PRESENT_ALL, + PORT16_PRESENT_ALL, + PORT_PRESENT_MAX +}; + +enum sfp_sysfs_type_attributes { + PORT1_TYPE, + PORT2_TYPE, + PORT3_TYPE, + PORT4_TYPE, + PORT5_TYPE, + PORT6_TYPE, + PORT7_TYPE, + PORT8_TYPE, + PORT9_TYPE, + PORT10_TYPE, + PORT11_TYPE, + PORT12_TYPE, + PORT13_TYPE, + PORT14_TYPE, + PORT15_TYPE, + PORT16_TYPE, + PORT_TYPE_MAX +}; + +enum sfp_sysfs_reset_attributes { + PORT1_RESET, + PORT2_RESET, + PORT3_RESET, + PORT4_RESET, + PORT5_RESET, + PORT6_RESET, + PORT7_RESET, + PORT8_RESET, + PORT9_RESET, + PORT10_RESET, + PORT11_RESET, + PORT12_RESET, + PORT13_RESET, + PORT14_RESET, + PORT15_RESET, + PORT16_RESET, + PORT_RESET_MAX +}; + +enum sfp_sysfs_rx_los_attributes { + PORT1_RX_LOS, + PORT2_RX_LOS, + PORT3_RX_LOS, + PORT4_RX_LOS, + PORT5_RX_LOS, + PORT6_RX_LOS, + PORT7_RX_LOS, + PORT8_RX_LOS, + PORT9_RX_LOS, + PORT10_RX_LOS, + PORT11_RX_LOS, + PORT12_RX_LOS, + PORT13_RX_LOS, + PORT14_RX_LOS, + PORT15_RX_LOS, + PORT16_RX_LOS, + PORT_RX_LOS_MAX +}; + +enum sfp_sysfs_rx_los1_attributes { + PORT1_RX_LOS1 = PORT_RX_LOS_MAX, + PORT2_RX_LOS1, + PORT3_RX_LOS1, + PORT4_RX_LOS1, + PORT5_RX_LOS1, + PORT6_RX_LOS1, + PORT7_RX_LOS1, + PORT8_RX_LOS1, + PORT9_RX_LOS1, + PORT10_RX_LOS1, + PORT11_RX_LOS1, + PORT12_RX_LOS1, + PORT13_RX_LOS1, + PORT14_RX_LOS1, + PORT15_RX_LOS1, + PORT16_RX_LOS1, + PORT_RX_LOS1_MAX +}; + +enum sfp_sysfs_rx_los2_attributes { + PORT1_RX_LOS2 = PORT_RX_LOS1_MAX, + PORT2_RX_LOS2, + PORT3_RX_LOS2, + PORT4_RX_LOS2, + PORT5_RX_LOS2, + PORT6_RX_LOS2, + PORT7_RX_LOS2, + PORT8_RX_LOS2, + PORT9_RX_LOS2, + PORT10_RX_LOS2, + PORT11_RX_LOS2, + PORT12_RX_LOS2, + PORT13_RX_LOS2, + PORT14_RX_LOS2, + PORT15_RX_LOS2, + PORT16_RX_LOS2, + PORT_RX_LOS2_MAX +}; + +enum sfp_sysfs_rx_los3_attributes { + PORT1_RX_LOS3 = PORT_RX_LOS2_MAX, + PORT2_RX_LOS3, + PORT3_RX_LOS3, + PORT4_RX_LOS3, + PORT5_RX_LOS3, + PORT6_RX_LOS3, + PORT7_RX_LOS3, + PORT8_RX_LOS3, + PORT9_RX_LOS3, + PORT10_RX_LOS3, + PORT11_RX_LOS3, + PORT12_RX_LOS3, + PORT13_RX_LOS3, + PORT14_RX_LOS3, + PORT15_RX_LOS3, + PORT16_RX_LOS3, + PORT_RX_LOS3_MAX +}; + +enum sfp_sysfs_rx_los4_attributes { + PORT1_RX_LOS4 = PORT_RX_LOS3_MAX, + PORT2_RX_LOS4, + PORT3_RX_LOS4, + PORT4_RX_LOS4, + PORT5_RX_LOS4, + PORT6_RX_LOS4, + PORT7_RX_LOS4, + PORT8_RX_LOS4, + PORT9_RX_LOS4, + PORT10_RX_LOS4, + PORT11_RX_LOS4, + PORT12_RX_LOS4, + PORT13_RX_LOS4, + PORT14_RX_LOS4, + PORT15_RX_LOS4, + PORT16_RX_LOS4, + PORT_RX_LOS4_MAX +}; + +enum sfp_sysfs_rx_los_all_attributes { + PORT1_RX_LOS_ALL = PORT_RX_LOS4_MAX, + PORT2_RX_LOS_ALL, + PORT3_RX_LOS_ALL, + PORT4_RX_LOS_ALL, + PORT5_RX_LOS_ALL, + PORT6_RX_LOS_ALL, + PORT7_RX_LOS_ALL, + PORT8_RX_LOS_ALL, + PORT9_RX_LOS_ALL, + PORT10_RX_LOS_ALL, + PORT11_RX_LOS_ALL, + PORT12_RX_LOS_ALL, + PORT13_RX_LOS_ALL, + PORT14_RX_LOS_ALL, + PORT15_RX_LOS_ALL, + PORT16_RX_LOS_ALL, + PORT_RX_LOS_ALL_MAX +}; + +enum sfp_sysfs_tx_disable_attributes { + PORT1_TX_DISABLE = PORT_RX_LOS_ALL_MAX, + PORT2_TX_DISABLE, + PORT3_TX_DISABLE, + PORT4_TX_DISABLE, + PORT5_TX_DISABLE, + PORT6_TX_DISABLE, + PORT7_TX_DISABLE, + PORT8_TX_DISABLE, + PORT9_TX_DISABLE, + PORT10_TX_DISABLE, + PORT11_TX_DISABLE, + PORT12_TX_DISABLE, + PORT13_TX_DISABLE, + PORT14_TX_DISABLE, + PORT15_TX_DISABLE, + PORT16_TX_DISABLE, + PORT_TX_DISABLE_MAX +}; + +enum sfp_sysfs_tx_disable1_attributes { + PORT1_TX_DISABLE1 = PORT_TX_DISABLE_MAX, + PORT2_TX_DISABLE1, + PORT3_TX_DISABLE1, + PORT4_TX_DISABLE1, + PORT5_TX_DISABLE1, + PORT6_TX_DISABLE1, + PORT7_TX_DISABLE1, + PORT8_TX_DISABLE1, + PORT9_TX_DISABLE1, + PORT10_TX_DISABLE1, + PORT11_TX_DISABLE1, + PORT12_TX_DISABLE1, + PORT13_TX_DISABLE1, + PORT14_TX_DISABLE1, + PORT15_TX_DISABLE1, + PORT16_TX_DISABLE1, + PORT_TX_DISABLE1_MAX +}; + +enum sfp_sysfs_tx_disable2_attributes { + PORT1_TX_DISABLE2 = PORT_TX_DISABLE1_MAX, + PORT2_TX_DISABLE2, + PORT3_TX_DISABLE2, + PORT4_TX_DISABLE2, + PORT5_TX_DISABLE2, + PORT6_TX_DISABLE2, + PORT7_TX_DISABLE2, + PORT8_TX_DISABLE2, + PORT9_TX_DISABLE2, + PORT10_TX_DISABLE2, + PORT11_TX_DISABLE2, + PORT12_TX_DISABLE2, + PORT13_TX_DISABLE2, + PORT14_TX_DISABLE2, + PORT15_TX_DISABLE2, + PORT16_TX_DISABLE2, + PORT_TX_DISABLE2_MAX +}; + +enum sfp_sysfs_tx_disable3_attributes { + PORT1_TX_DISABLE3 = PORT_TX_DISABLE2_MAX, + PORT2_TX_DISABLE3, + PORT3_TX_DISABLE3, + PORT4_TX_DISABLE3, + PORT5_TX_DISABLE3, + PORT6_TX_DISABLE3, + PORT7_TX_DISABLE3, + PORT8_TX_DISABLE3, + PORT9_TX_DISABLE3, + PORT10_TX_DISABLE3, + PORT11_TX_DISABLE3, + PORT12_TX_DISABLE3, + PORT13_TX_DISABLE3, + PORT14_TX_DISABLE3, + PORT15_TX_DISABLE3, + PORT16_TX_DISABLE3, + PORT_TX_DISABLE3_MAX +}; + +enum sfp_sysfs_tx_disable4_attributes { + PORT1_TX_DISABLE4 = PORT_TX_DISABLE3_MAX, + PORT2_TX_DISABLE4, + PORT3_TX_DISABLE4, + PORT4_TX_DISABLE4, + PORT5_TX_DISABLE4, + PORT6_TX_DISABLE4, + PORT7_TX_DISABLE4, + PORT8_TX_DISABLE4, + PORT9_TX_DISABLE4, + PORT10_TX_DISABLE4, + PORT11_TX_DISABLE4, + PORT12_TX_DISABLE4, + PORT13_TX_DISABLE4, + PORT14_TX_DISABLE4, + PORT15_TX_DISABLE4, + PORT16_TX_DISABLE4, + PORT_TX_DISABLE4_MAX +}; + +enum sfp_sysfs_tx_disable_all_attributes { + PORT1_TX_DISABLE_ALL = PORT_TX_DISABLE4_MAX, + PORT2_TX_DISABLE_ALL, + PORT3_TX_DISABLE_ALL, + PORT4_TX_DISABLE_ALL, + PORT5_TX_DISABLE_ALL, + PORT6_TX_DISABLE_ALL, + PORT7_TX_DISABLE_ALL, + PORT8_TX_DISABLE_ALL, + PORT9_TX_DISABLE_ALL, + PORT10_TX_DISABLE_ALL, + PORT11_TX_DISABLE_ALL, + PORT12_TX_DISABLE_ALL, + PORT13_TX_DISABLE_ALL, + PORT14_TX_DISABLE_ALL, + PORT15_TX_DISABLE_ALL, + PORT16_TX_DISABLE_ALL, + PORT_TX_DISABLE_ALL_MAX +}; + +enum sfp_sysfs_tx_fault_attributes { + PORT1_TX_FAULT = PORT_TX_DISABLE_ALL_MAX, + PORT2_TX_FAULT, + PORT3_TX_FAULT, + PORT4_TX_FAULT, + PORT5_TX_FAULT, + PORT6_TX_FAULT, + PORT7_TX_FAULT, + PORT8_TX_FAULT, + PORT9_TX_FAULT, + PORT10_TX_FAULT, + PORT11_TX_FAULT, + PORT12_TX_FAULT, + PORT13_TX_FAULT, + PORT14_TX_FAULT, + PORT15_TX_FAULT, + PORT16_TX_FAULT, + PORT_TX_FAULT_MAX +}; + +enum sfp_sysfs_tx_fault1_attributes { + PORT1_TX_FAULT1 = PORT_TX_FAULT_MAX, + PORT2_TX_FAULT1, + PORT3_TX_FAULT1, + PORT4_TX_FAULT1, + PORT5_TX_FAULT1, + PORT6_TX_FAULT1, + PORT7_TX_FAULT1, + PORT8_TX_FAULT1, + PORT9_TX_FAULT1, + PORT10_TX_FAULT1, + PORT11_TX_FAULT1, + PORT12_TX_FAULT1, + PORT13_TX_FAULT1, + PORT14_TX_FAULT1, + PORT15_TX_FAULT1, + PORT16_TX_FAULT1, + PORT_TX_FAULT1_MAX +}; + +enum sfp_sysfs_tx_fault2_attributes { + PORT1_TX_FAULT2 = PORT_TX_FAULT1_MAX, + PORT2_TX_FAULT2, + PORT3_TX_FAULT2, + PORT4_TX_FAULT2, + PORT5_TX_FAULT2, + PORT6_TX_FAULT2, + PORT7_TX_FAULT2, + PORT8_TX_FAULT2, + PORT9_TX_FAULT2, + PORT10_TX_FAULT2, + PORT11_TX_FAULT2, + PORT12_TX_FAULT2, + PORT13_TX_FAULT2, + PORT14_TX_FAULT2, + PORT15_TX_FAULT2, + PORT16_TX_FAULT2, + PORT_TX_FAULT2_MAX +}; + +enum sfp_sysfs_tx_fault3_attributes { + PORT1_TX_FAULT3 = PORT_TX_FAULT2_MAX, + PORT2_TX_FAULT3, + PORT3_TX_FAULT3, + PORT4_TX_FAULT3, + PORT5_TX_FAULT3, + PORT6_TX_FAULT3, + PORT7_TX_FAULT3, + PORT8_TX_FAULT3, + PORT9_TX_FAULT3, + PORT10_TX_FAULT3, + PORT11_TX_FAULT3, + PORT12_TX_FAULT3, + PORT13_TX_FAULT3, + PORT14_TX_FAULT3, + PORT15_TX_FAULT3, + PORT16_TX_FAULT3, + PORT_TX_FAULT3_MAX +}; + +enum sfp_sysfs_tx_fault4_attributes { + PORT1_TX_FAULT4 = PORT_TX_FAULT3_MAX, + PORT2_TX_FAULT4, + PORT3_TX_FAULT4, + PORT4_TX_FAULT4, + PORT5_TX_FAULT4, + PORT6_TX_FAULT4, + PORT7_TX_FAULT4, + PORT8_TX_FAULT4, + PORT9_TX_FAULT4, + PORT10_TX_FAULT4, + PORT11_TX_FAULT4, + PORT12_TX_FAULT4, + PORT13_TX_FAULT4, + PORT14_TX_FAULT4, + PORT15_TX_FAULT4, + PORT16_TX_FAULT4, + PORT_TX_FAULT4_MAX +}; + +enum sfp_sysfs_eeprom_attributes { + PORT1_EEPROM, + PORT2_EEPROM, + PORT3_EEPROM, + PORT4_EEPROM, + PORT5_EEPROM, + PORT6_EEPROM, + PORT7_EEPROM, + PORT8_EEPROM, + PORT9_EEPROM, + PORT10_EEPROM, + PORT11_EEPROM, + PORT12_EEPROM, + PORT13_EEPROM, + PORT14_EEPROM, + PORT15_EEPROM, + PORT16_EEPROM, + PORT_EEPROM_MAX +}; + +enum sfp_sysfs_ddm_implemented_attributes { + PORT1_DDM_IMPLEMENTED, + PORT2_DDM_IMPLEMENTED, + PORT3_DDM_IMPLEMENTED, + PORT4_DDM_IMPLEMENTED, + PORT5_DDM_IMPLEMENTED, + PORT6_DDM_IMPLEMENTED, + PORT7_DDM_IMPLEMENTED, + PORT8_DDM_IMPLEMENTED, + PORT9_DDM_IMPLEMENTED, + PORT10_DDM_IMPLEMENTED, + PORT11_DDM_IMPLEMENTED, + PORT12_DDM_IMPLEMENTED, + PORT13_DDM_IMPLEMENTED, + PORT14_DDM_IMPLEMENTED, + PORT15_DDM_IMPLEMENTED, + PORT16_DDM_IMPLEMENTED, + PORT_DDM_IMPLEMENTED_MAX +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + DEBUG_PRINT("show_port_number port number:%d", data->port + attr->index); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port + attr->index)); +} + +static struct sfp_port_data *sfp_pca9506_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x03}; + + DEBUG_PRINT("Starting pca9506 sfp present status update"); + mutex_lock(&data->update_lock); + + /* Read present status of port */ + data->present = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + /* status = alpha_i2c_cpld_read(0x5f, regs[i]); */ + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("pca9506(0x20) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + data->present = status; + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x05, 0x06}; + + if(data->port >= SFPPLUS_1_PORT_NUMBER){ + return sfp_pca9506_update_present(client); + } + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + + /* Read present status of port 1~32 */ + data->present = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + /* status = alpha_i2c_cpld_read(0x5f, regs[i]); */ + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x5f) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + data->present |= (u64)status << (i*8); + DEBUG_PRINT("Present status = 0x%llx", data->present); + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) +{ + return NULL; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + return 0; +} + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = sfp_update_present(client); + + if(data->port >= SFPPLUS_1_PORT_NUMBER) + return (data->present & BIT_INDEX(port)) ? 0 : 1; + else + return (data->present & BIT_INDEX(port)) ? 1 : 0; +} + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if ((attr->index >= PORT1_PRESENT_ALL) && (attr->index <= PORT8_PRESENT_ALL)) { + + } + + /* PRESENT */ + return sprintf(buf, "%d\n", sfp_is_port_present(client, attr->index)); +} + +static struct sfp_port_data *sfp_update_port_type(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 buf = 0; + int status; + + mutex_lock(&data->update_lock); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + if (buf != SFF8024_DEVICE_ID_SFP) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + status = sfp_eeprom_read(data->client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); + data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; + break; + } + case DRIVER_TYPE_QSFP: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); + switch (buf) { + case SFF8024_DEVICE_ID_QSFP: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; + break; + case SFF8024_DEVICE_ID_QSFP_PLUS: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + case SFF8024_DEVICE_ID_QSFP28: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + default: + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + break; + } + default: + break; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (!sfp_is_port_present(client, attr->index)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_type(dev); + return sprintf(buf, "%d\n", data->port_type); +} + + +static struct sfp_port_data *sfp_update_port_reset(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x07, 0x08}; + + mutex_lock(&data->update_lock); + + /* Read reset status of port 1~32 */ + data->port_reset = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("reset status = 0x%x", status); + data->port_reset |= (u64)status << (i*8); + } + + DEBUG_PRINT("reset status = 0x%llx", data->port_reset); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int is_reset = 0; + + if (!sfp_is_port_present(client, attr->index)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_reset(client); + is_reset = (data->port_reset & BIT_INDEX(attr->index))? 0 : 1; + + return sprintf(buf, "%d\n", is_reset); +} + +static ssize_t sfp_set_port_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_reg = 0, cpld_val = 0; /*, cpld_bit = 0; //remove unused variable */ + long is_reset; + int error; + + error = kstrtol(buf, 10, &is_reset); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + cpld_reg = 0x07; + + cpld_val = i2c_smbus_read_byte_data(client, cpld_reg); + + DEBUG_PRINT("current cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + /* Update reset status. CPLD defined 0 is reset state, 1 is normal state. + * is_reset: 0 is not reset. 1 is reset. + */ + if (is_reset == 0) { + data->port_reset |= BIT_INDEX(attr->index); + } + else { + data->port_reset &= ~BIT_INDEX(attr->index); + } + + alpha_i2c_cpld_write(0x5f, cpld_reg, cpld_val); + DEBUG_PRINT("write cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + dev_dbg(dev, "Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + } + msleep(200); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + mutex_unlock(&data->update_lock); + return data; + +exit: + mutex_unlock(&data->update_lock); + return NULL; +} + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (!sfp_is_port_present(client, attr->index)) { + return -ENODEV; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + if ((attr->index >= PORT1_TX_FAULT1) && (attr->index < PORT_TX_FAULT4_MAX)){ + val = (data->qsfp->status[2] & BIT_INDEX(attr->index - PORT1_TX_FAULT1)) ? 1 : 0; + } + else if ((attr->index >= PORT1_TX_DISABLE1) && (attr->index < PORT_TX_DISABLE4_MAX)){ + val = (data->qsfp->status[1] & BIT_INDEX(attr->index - PORT1_TX_DISABLE1)) ? 1 : 0; + } + else if ((attr->index >= PORT1_TX_DISABLE_ALL) && (attr->index < PORT_TX_DISABLE_ALL_MAX)){ + val = ((data->qsfp->status[1] & 0xF) == 0xF) ? 1 : 0; + } + if ((attr->index >= PORT1_RX_LOS1) && (attr->index < PORT_RX_LOS4_MAX)){ + val = (data->qsfp->status[0] & BIT_INDEX(attr->index - PORT1_RX_LOS1)) ? 1 : 0; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int result; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + result = kstrtol(buf, 10, &disable); + if (result) { + return result; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + mutex_lock(&data->update_lock); + + if((attr->index >= PORT1_TX_DISABLE_ALL) && (attr->index < PORT_TX_DISABLE_ALL_MAX)){ + DEBUG_PRINT ("disable:%ld %d==TX_DISABLE_ALL %u\r\n", disable, attr->index, data->qsfp->status[1]); + data->qsfp->status[1] = disable? 0xF:0; + } + else{ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - PORT1_TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - PORT1_TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + result = sfp_eeprom_write(client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + char ddm; + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (!sfp_is_port_present(client, attr->index)) { + return -ENODEV; + } + + status = sfp_eeprom_read(data->client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); + if (status < 0) { + return -EIO; + } + + return sprintf(buf, "%d\n", (ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK) ? 1 : 0); +} + +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + data = sfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + if ((attr->index >= PORT1_TX_FAULT) && (attr->index < PORT_TX_FAULT_MAX)){ + index = 0; + } + else if ((attr->index >= PORT1_TX_DISABLE) && (attr->index < PORT_TX_DISABLE_MAX)){ + index = 1; + } + if ((attr->index >= PORT1_RX_LOS) && (attr->index < PORT_RX_LOS_MAX)){ + index = 2; + } + + if(data->port == SFPPLUS_1_PORT_NUMBER) + val = (data->ddm->status[index] & BIT_INDEX(0)) ? 1 : 0; + else if(data->port == SFPPLUS_1_PORT_NUMBER) + val = (data->ddm->status[index] & BIT_INDEX(1)) ? 1 : 0; + else + val = (data->ddm->status[index] & BIT_INDEX(attr->index)) ? 1 : 0; + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_show_eeprom(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + char devfile[96]; + struct file *sfd; + int i2c_index = 0; + int result; + int offset[] = {0x0b, 0x0c}; + int rdlen, rc; + mm_segment_t old_fs; + char buffer[256]; + + if (!sfp_is_port_present(client, attr->index)) { + return 0; + } + + if(strcmp(client->name, "sfpcpld1") == 0) + i2c_index = 13; + else if(strcmp(client->name, "sfpcpld17") == 0) + i2c_index = 14; + else if(strcmp(client->name, "sfpcpld33") == 0) + i2c_index = 15; + else if(strcmp(client->name, "sfpcpld49") == 0) + i2c_index = 16; + else if(strcmp(client->name, "sfpcpld65") == 0){ + if(attr->index == 0) + i2c_index = 21; + else if(attr->index == 1) + i2c_index = 22; + } + + snprintf(devfile, sizeof(devfile), "/sys/bus/i2c/devices/%d-0050/sfp_eeprom", i2c_index); + + /* Set module select register */ + switch(i2c_index){ + case 13: + case 14: + case 15: + case 16: + if((attr->index/8) == 0){ + /* Port number is 1-8 */ + result = i2c_smbus_write_byte_data(client, offset[0], BIT_INDEX(attr->index)); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data fail(%d)", result); + } + } + else if((attr->index/8) == 1){ + /* Port number is 9-16 */ + result = i2c_smbus_write_byte_data(client, offset[1], BIT_INDEX((attr->index)%8)); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data fail(%d)", result); + } + } + break; + default: + break; + } + + /* Read SFP EEPROM */ + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + dev_info(&client->dev, "Failed to open file(%s)#%d", devfile, __LINE__); + return 0; + } + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + dev_info(&client->dev, "file %s cann't readable ?\n", devfile); + return 0; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + dev_info(&client->dev, "File(%s) empty!\n", devfile); + rc = 0; + goto exit; + } + + rc = sizeof(buffer); + memcpy(buf, buffer, rc); + + /* Reset module select register */ + switch(i2c_index){ + case 13: + case 14: + case 15: + case 16: + if((attr->index/8) == 0){ + /* Port number is 1-8 */ + result = i2c_smbus_write_byte_data(client, offset[0], 0); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data fail(%d)", result); + } + } + else if((attr->index/8) == 1){ + /* Port number is 9-16 */ + result = i2c_smbus_write_byte_data(client, offset[1], 0); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data fail(%d)", result); + } + } + break; + default: + break; + } + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + + return rc; +} + +#if 0 +static ssize_t qsfp_set_eeprom(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + DEBUG_PRINT("data->port:%d attr index:%d", data->port, attr->index); + return 1; +} +#endif + +/* SFP/QSFP common attributes for sysfs */ +#define DECLARE_PORT_NUMBER_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT1##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT2##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT3##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT4##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT5##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT6##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT7##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT8##_NUMBER); +#define DECLARE_PORT_NUMBER_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_number.dev_attr.attr, +DECLARE_PORT_NUMBER_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_NUMBER_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_PORT_IS_PRESENT_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_is_present, S_IRUGO, show_present, NULL, PORT##PORT1##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_is_present, S_IRUGO, show_present, NULL, PORT##PORT2##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_is_present, S_IRUGO, show_present, NULL, PORT##PORT3##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_is_present, S_IRUGO, show_present, NULL, PORT##PORT4##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_is_present, S_IRUGO, show_present, NULL, PORT##PORT5##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_is_present, S_IRUGO, show_present, NULL, PORT##PORT6##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_is_present, S_IRUGO, show_present, NULL, PORT##PORT7##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_is_present, S_IRUGO, show_present, NULL, PORT##PORT8##_PRESENT); +#define DECLARE_PORT_IS_PRESENT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_is_present.dev_attr.attr, +DECLARE_PORT_IS_PRESENT_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_IS_PRESENT_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_PORT_TYPE_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT1##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT2##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT3##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT4##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT5##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT6##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT7##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT8##_TYPE); +#define DECLARE_PORT_TYPE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_type.dev_attr.attr, +DECLARE_PORT_TYPE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TYPE_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_PORT_RESET_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT1##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT2##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT3##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT4##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT5##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT6##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT7##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT8##_RESET); +#define DECLARE_PORT_RESET_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_reset.dev_attr.attr, +DECLARE_PORT_RESET_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RESET_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +/* QSFP attributes for sysfs */ +#define DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT1##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT2##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT3##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT4##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT5##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT6##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT7##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT8##_RX_LOS##INDEX); +#define DECLARE_PORT_RX_LOSn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_rx_los##INDEX.dev_attr.attr, +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT1##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT2##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT3##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT4##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT5##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT6##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT7##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT8##_TX_DISABLE##INDEX); + +#define DECLARE_PORT_TX_DISABLEn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_disable##INDEX.dev_attr.attr, +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT1##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT2##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT3##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT4##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT5##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT6##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT7##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT8##_TX_FAULT##INDEX); +#define DECLARE_PORT_TX_FAULTn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_fault##INDEX.dev_attr.attr, +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT1##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT2##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT3##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT4##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT5##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT6##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT7##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT8##_EEPROM); +#define DECLARE_PORT_EEPROMTn_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_eeprom.dev_attr.attr, +DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +static struct attribute *qsfp_attributes[] = { + DECLARE_PORT_NUMBER_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_NUMBER_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TYPE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TYPE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_IS_PRESENT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_IS_PRESENT_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RESET_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RESET_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RX_LOSn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RX_LOSn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RX_LOSn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RX_LOSn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_DISABLEn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_DISABLEn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_DISABLEn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_DISABLEn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_FAULTn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_FAULTn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_FAULTn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_FAULTn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_EEPROMTn_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_EEPROMTn_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + NULL +}; + + +/* SFP msa attributes for sysfs */ +static struct attribute *sfp_msa_attributes[] = { + DECLARE_PORT_NUMBER_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_NUMBER_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TYPE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TYPE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_IS_PRESENT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_IS_PRESENT_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RESET_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RESET_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + NULL +}; + +/* SFP ddm attributes for sysfs */ +#define DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT1##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT2##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT3##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT4##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT5##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_RX_LOS); +#define DECLARE_RX_LOS_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_rx_los.dev_attr.attr, +DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT1##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT2##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT3##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT4##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT5##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT6##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT7##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT8##_TX_DISABLE); +#define DECLARE_TX_DISABLE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_disable.dev_attr.attr, +DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_TX_FAULT_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT1##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT2##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT3##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT4##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT5##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_TX_FAULT); +#define DECLARE_TX_FAULT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_fault.dev_attr.attr, +DECLARE_TX_FAULT_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_TX_FAULT_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) +static struct attribute *sfp_ddm_attributes[] = { + DECLARE_RX_LOS_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_RX_LOS_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_TX_DISABLE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_TX_DISABLE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_TX_FAULT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_TX_FAULT_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + NULL +}; + +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return data_len; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_write_byte_data(client, command, *data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return 1; +#endif + + +} + + +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", (int)off, (int)count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_write(data, buf, off, count); +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + /* result = data_len; */ + +abort: + return result; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_read_byte_data(client, command); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result); + goto abort; + } + + *data = (u8)result; + result = 1; + +abort: + return result; +#endif +} + +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", (int)off, (int)count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_read(data, buf, off, count); +} + +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); + if (status) { + dev_info(&client->dev, "sfp msa '%s' (sfp_sysfs_eeprom_init fail...)\n", client->name); + /* goto exit_remove; */ + } + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + return 0; + +/* exit_remove: */ + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group sfp_ddm_group = { + .attrs = sfp_ddm_attributes, +}; + +static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_ddm_data **data) +{ + int status; + struct sfp_ddm_data *ddm; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); + if (!ddm) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = ddm; + dev_info(&client->dev, "sfp ddm '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); +exit_free: + kfree(ddm); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_PCA9506_I2C_ADDR)){ + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + } + + if (client->addr == SFP_EEPROM_A0_I2C_ADDR){ + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); + if (status) { + goto exit_remove; + } + } + + /* Bring QSFPs out of reset */ + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct sfp_port_data *data = NULL; + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + DEBUG_PRINT("data->port:%d client->addr:0x%0x\n", data->port, client->addr); + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_PCA9506_I2C_ADDR)){ + if(data->port >= SFPPLUS_1_PORT_NUMBER){ + if(client->addr != SFP_PCA9506_I2C_ADDR){ + DEBUG_PRINT("client->addr:0x%0x\n", client->addr); + return -ENODEV; + } + } + else if(client->addr != SFP_CPLD_I2C_ADDR){ + DEBUG_PRINT("client->addr:0x%0x\n", client->addr); + return -ENODEV; + } + } + + data->driver_type = DRIVER_TYPE_QSFP; + return qsfp_probe(client, dev_id, &data->qsfp); +} + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_PCA9506_I2C_ADDR)) + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_PCA9506_I2C_ADDR)) + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_PCA9506_I2C_ADDR)) + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_SFP_DDM: + return sfp_ddm_remove(client, data->ddm); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + + return 0; +} + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Philip Wang "); +MODULE_DESCRIPTION("alphanetworks snh60b0-640f driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_onie_eeprom.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_onie_eeprom.c new file mode 100644 index 000000000000..f259abdca8fc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_onie_eeprom.c @@ -0,0 +1,268 @@ +/* + * A driver for snh60b0-640f onie eeprom + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Robin Chen + * 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 + * 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. + * see + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EEPROM_SIZE 256 + +#define SYS_LED_REG 0x8 +#define FAN12_LED_REG 0x9 +#define FAN34_LED_REG 0xA +#define FAN56_LED_REG 0xB +#define SYS_RESET1_REG 0x2 + +#define SYS_LOCATOR_LED_BITS 0x01 +#define SYS_PWR_LED_BITS 0x0E +#define SYS_STATUS_LED_BITS 0x70 +#define FAN135_LED_BITS 0x07 +#define FAN246_LED_BITS 0x38 + + +extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +static ssize_t onie_read(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t onie_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for snh60b0-640f_onie_eeprom */ +static const unsigned short normal_i2c[] = { 0x56, I2C_CLIENT_END }; + + +enum sysfs_onie_attributes { + ONIE_RW, +}; + +static SENSOR_DEVICE_ATTR(eeprom, (0660), onie_read, onie_write, ONIE_RW); + +static struct attribute *snh60b0_onie_attributes[] = { + &sensor_dev_attr_eeprom.dev_attr.attr, + NULL +}; + +static const struct attribute_group snh60b0_onie_group = { + .attrs = snh60b0_onie_attributes, +}; + + +static ssize_t onie_read(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + __u8 read_write; + unsigned short offset = 0; + union i2c_smbus_data temp; + char rbuf[EEPROM_SIZE]; + + for( offset=0 ; offset < EEPROM_SIZE ; ++offset ) + { + read_write = I2C_SMBUS_WRITE; + offset = offset & 0x3fff; + temp.byte = (u8)offset; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 2, &temp); + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 2, &temp); + + read_write = I2C_SMBUS_READ; + temp.byte = 0xaa; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 1, &temp); + if (!res) + { + res = temp.byte; + rbuf[offset] = (char)temp.byte; + } + + read_write = I2C_SMBUS_READ; + temp.byte = 0xbb; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 1, &temp); + if (!res) + { + res = temp.byte; + } + } + + memcpy(buf, rbuf, EEPROM_SIZE); + return EEPROM_SIZE; +} + +static ssize_t onie_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int error, write, command, read; + + error = kstrtoint(buf, 10, &write); + if (error) + return error; + + if (write < 0 || write > 255) + return -EINVAL; + + /* Not support yet */ + + return count; +} + + + +static void alpha_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int onie_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &snh60b0_onie_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int onie_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &snh60b0_onie_group); + alpha_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id onie_eeprom_id[] = { + { "snh60b0_onie_eeprom", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, onie_eeprom_id); + +static struct i2c_driver onie_eeprom_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "snh60b0_onie_eeprom", + }, + .probe = onie_eeprom_probe, + .remove = onie_eeprom_remove, + .id_table = onie_eeprom_id, + .address_list = normal_i2c, +}; + + +static int __init onie_eeprom_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&onie_eeprom_driver); +} + +static void __exit onie_eeprom_exit(void) + +{ + i2c_del_driver(&onie_eeprom_driver); +} + + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("onie eeprom driver"); +MODULE_LICENSE("GPL"); + +module_init(onie_eeprom_init); +module_exit(onie_eeprom_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_power_cpld.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_power_cpld.c new file mode 100644 index 000000000000..00b8779ad50c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_power_cpld.c @@ -0,0 +1,501 @@ +/* + * A hwmon driver for the snh60b0-640f_power_cpld + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Robin Chen + * 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 + * 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. + * see + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DRIVER_NAME "snh60b0_power_cpld" +#define PSU1_STATUS_REG 0x3 +#define PSU2_STATUS_REG 0x4 +#define FAN_PWM_REG 0x23 + +#define PSU_PRESENT_BIT 0x4 +#define PSU_POWER_BIT 0x2 +#define FAN_PRESENT_BIT 0x2 + + +static ssize_t psu_show_status(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t fan_pwm_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +static ssize_t fan_show_status(struct device *dev, struct device_attribute *attr, char *buf); + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for snh60b0-640f_power_cpld */ +static const unsigned short normal_i2c[] = { 0x5E, I2C_CLIENT_END }; + +struct snh60b0_pwr_cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; + char model_name[9]; /* Model name, read from eeprom */ +}; + + +enum sysfs_psu_attributes { + PSU1_PRESENT, + PSU2_PRESENT, + PSU1_POWER_GOOD, + PSU2_POWER_GOOD, + FAN_PWM, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + /* FAN5_FAULT, */ + /* FAN6_FAULT, */ + FAN1_PRESENT=0x12, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + /* FAN5_PRESENT, */ + /* FAN6_PRESENT, */ + FAN1_FRONT_SPEED_RPM=0x1A, + FAN1_REAR_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + /* FAN5_FRONT_SPEED_RPM, */ + /* FAN5_REAR_SPEED_RPM, */ + /* FAN6_FRONT_SPEED_RPM, */ + /* FAN6_REAR_SPEED_RPM, */ +}; + +static SENSOR_DEVICE_ATTR(psu1_present, S_IRUGO, psu_show_status, NULL, PSU1_PRESENT); +static SENSOR_DEVICE_ATTR(psu2_present, S_IRUGO, psu_show_status, NULL, PSU2_PRESENT); +static SENSOR_DEVICE_ATTR(psu1_power_good, S_IRUGO, psu_show_status, NULL, PSU1_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu2_power_good, S_IRUGO, psu_show_status, NULL, PSU2_POWER_GOOD); +static SENSOR_DEVICE_ATTR(fan_pwm, (0660), fan_pwm_show, set_fan_pwm, FAN_PWM); +static SENSOR_DEVICE_ATTR(fan1_present, S_IRUGO, fan_show_status, NULL, FAN1_PRESENT); +static SENSOR_DEVICE_ATTR(fan2_present, S_IRUGO, fan_show_status, NULL, FAN2_PRESENT); +static SENSOR_DEVICE_ATTR(fan3_present, S_IRUGO, fan_show_status, NULL, FAN3_PRESENT); +static SENSOR_DEVICE_ATTR(fan4_present, S_IRUGO, fan_show_status, NULL, FAN4_PRESENT); +/* static SENSOR_DEVICE_ATTR(fan5_present, S_IRUGO, fan_show_status, NULL, FAN5_PRESENT); */ +/* static SENSOR_DEVICE_ATTR(fan6_present, S_IRUGO, fan_show_status, NULL, FAN6_PRESENT); */ +static SENSOR_DEVICE_ATTR(fan1_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN1_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN2_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN3_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN4_FRONT_SPEED_RPM); +/* static SENSOR_DEVICE_ATTR(fan5_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN5_FRONT_SPEED_RPM); */ +/* static SENSOR_DEVICE_ATTR(fan6_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN6_FRONT_SPEED_RPM); */ +static SENSOR_DEVICE_ATTR(fan1_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN1_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN2_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN3_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN4_REAR_SPEED_RPM); +/* static SENSOR_DEVICE_ATTR(fan5_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN5_REAR_SPEED_RPM); */ +/* static SENSOR_DEVICE_ATTR(fan6_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN6_REAR_SPEED_RPM); */ +static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, fan_show_status, NULL, FAN1_FAULT); static SENSOR_DEVICE_ATTR(fan11_fault, S_IRUGO, fan_show_status, NULL, FAN1_FAULT); +static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, fan_show_status, NULL, FAN2_FAULT); static SENSOR_DEVICE_ATTR(fan12_fault, S_IRUGO, fan_show_status, NULL, FAN2_FAULT); +static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, fan_show_status, NULL, FAN3_FAULT); static SENSOR_DEVICE_ATTR(fan13_fault, S_IRUGO, fan_show_status, NULL, FAN3_FAULT); +static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, fan_show_status, NULL, FAN4_FAULT); static SENSOR_DEVICE_ATTR(fan14_fault, S_IRUGO, fan_show_status, NULL, FAN4_FAULT); +/* static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, fan_show_status, NULL, FAN5_FAULT); static SENSOR_DEVICE_ATTR(fan15_fault, S_IRUGO, fan_show_status, NULL, FAN5_FAULT); */ +/* static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, fan_show_status, NULL, FAN6_FAULT); static SENSOR_DEVICE_ATTR(fan16_fault, S_IRUGO, fan_show_status, NULL, FAN6_FAULT); */ +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, fan_show_status, NULL, FAN1_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, fan_show_status, NULL, FAN1_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, fan_show_status, NULL, FAN2_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan12_input, S_IRUGO, fan_show_status, NULL, FAN2_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, fan_show_status, NULL, FAN3_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan13_input, S_IRUGO, fan_show_status, NULL, FAN3_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, fan_show_status, NULL, FAN4_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan14_input, S_IRUGO, fan_show_status, NULL, FAN4_REAR_SPEED_RPM); +/* static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, fan_show_status, NULL, FAN5_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan15_input, S_IRUGO, fan_show_status, NULL, FAN5_REAR_SPEED_RPM); */ +/* static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, fan_show_status, NULL, FAN6_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan16_input, S_IRUGO, fan_show_status, NULL, FAN6_REAR_SPEED_RPM); */ + + +static struct attribute *snh60b0_psu_attributes[] = { + &sensor_dev_attr_psu1_present.dev_attr.attr, + &sensor_dev_attr_psu2_present.dev_attr.attr, + &sensor_dev_attr_psu1_power_good.dev_attr.attr, + &sensor_dev_attr_psu2_power_good.dev_attr.attr, + &sensor_dev_attr_fan_pwm.dev_attr.attr, + &sensor_dev_attr_fan1_present.dev_attr.attr, + &sensor_dev_attr_fan2_present.dev_attr.attr, + &sensor_dev_attr_fan3_present.dev_attr.attr, + &sensor_dev_attr_fan4_present.dev_attr.attr, + /* &sensor_dev_attr_fan5_present.dev_attr.attr, */ + /* &sensor_dev_attr_fan6_present.dev_attr.attr, */ + &sensor_dev_attr_fan1_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_front_speed_rpm.dev_attr.attr, + /* &sensor_dev_attr_fan5_front_speed_rpm.dev_attr.attr, */ + /* &sensor_dev_attr_fan6_front_speed_rpm.dev_attr.attr, */ + &sensor_dev_attr_fan1_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_rear_speed_rpm.dev_attr.attr, + /* &sensor_dev_attr_fan5_rear_speed_rpm.dev_attr.attr, */ + /* &sensor_dev_attr_fan6_rear_speed_rpm.dev_attr.attr, */ + &sensor_dev_attr_fan1_fault.dev_attr.attr, &sensor_dev_attr_fan11_fault.dev_attr.attr, + &sensor_dev_attr_fan2_fault.dev_attr.attr, &sensor_dev_attr_fan12_fault.dev_attr.attr, + &sensor_dev_attr_fan3_fault.dev_attr.attr, &sensor_dev_attr_fan13_fault.dev_attr.attr, + &sensor_dev_attr_fan4_fault.dev_attr.attr, &sensor_dev_attr_fan14_fault.dev_attr.attr, + /* &sensor_dev_attr_fan5_fault.dev_attr.attr, &sensor_dev_attr_fan15_fault.dev_attr.attr, */ + /* &sensor_dev_attr_fan6_fault.dev_attr.attr, &sensor_dev_attr_fan16_fault.dev_attr.attr, */ + &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan11_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan12_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, &sensor_dev_attr_fan13_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, &sensor_dev_attr_fan14_input.dev_attr.attr, + /* &sensor_dev_attr_fan5_input.dev_attr.attr, &sensor_dev_attr_fan15_input.dev_attr.attr, */ + /* &sensor_dev_attr_fan6_input.dev_attr.attr, &sensor_dev_attr_fan16_input.dev_attr.attr, */ + NULL +}; + +static const struct attribute_group snh60b0_psu_group = { + .attrs = snh60b0_psu_attributes, +}; + + +static ssize_t psu_show_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + + switch(sda->index) { + case PSU1_PRESENT: + case PSU1_POWER_GOOD: + command = PSU1_STATUS_REG; + break; + case PSU2_PRESENT: + case PSU2_POWER_GOOD: + command = PSU2_STATUS_REG; + break; + } + + val = i2c_smbus_read_byte_data(client, command); + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + switch(sda->index) { + case PSU1_PRESENT: + case PSU2_PRESENT: + res = (val & PSU_PRESENT_BIT ? 1 : 0 ); + break; + case PSU1_POWER_GOOD: + case PSU2_POWER_GOOD: + res = (val & PSU_POWER_BIT ? 1 : 0 ); + break; + } + + return sprintf(buf, "%d\n", res); +} + +static ssize_t fan_pwm_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, FAN_PWM_REG); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 0xFF) + return -EINVAL; + + i2c_smbus_write_byte_data(client, FAN_PWM_REG, value); + + return count; +} + +static ssize_t fan_show_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + // struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev); + ssize_t ret = 0; + int val, val2; + + switch (sda->index) { + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + /* case FAN5_FRONT_SPEED_RPM: */ + /* case FAN6_FRONT_SPEED_RPM: */ + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + /* case FAN5_REAR_SPEED_RPM: */ + /* case FAN6_REAR_SPEED_RPM: */ + val = i2c_smbus_read_byte_data(client, sda->index); + ret = sprintf(buf, "%d\n", val * 150); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + /* case FAN5_PRESENT: */ + /* case FAN6_PRESENT: */ + val = i2c_smbus_read_byte_data(client, sda->index); + ret = sprintf(buf, "%d\n", (val & FAN_PRESENT_BIT) ? 1 : 0); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + /* case FAN5_FAULT: */ + /* case FAN6_FAULT: */ + val = i2c_smbus_read_byte_data(client, (sda->index - FAN1_FAULT)*2 + FAN1_FRONT_SPEED_RPM); + val2 = i2c_smbus_read_byte_data(client, (sda->index - FAN1_FAULT)*2 + FAN1_REAR_SPEED_RPM); + ret = sprintf(buf, "%d\n", (val|val2) ? 0 : 1); + break; + default: + break; + } + + return ret; +} + + +static void alpha_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int alpha_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct snh60b0_pwr_cpld_data* data; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct snh60b0_pwr_cpld_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &snh60b0_psu_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_add_client(client); + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit; + } + + dev_info(&client->dev, "%s: pwr_cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit: + return status; +} + +static int alpha_i2c_cpld_remove(struct i2c_client *client) +{ + struct snh60b0_pwr_cpld_data *data = i2c_get_clientdata(client); + sysfs_remove_group(&client->dev.kobj, &snh60b0_psu_group); + alpha_i2c_cpld_remove_client(client); + kfree(data); + + return 0; +} + +static const struct i2c_device_id alpha_i2c_cpld_id[] = { + { DRIVER_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, alpha_i2c_cpld_id); + +static struct i2c_driver alpha_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRIVER_NAME, + }, + .probe = alpha_i2c_cpld_probe, + .remove = alpha_i2c_cpld_remove, + .id_table = alpha_i2c_cpld_id, + .address_list = normal_i2c, +}; + +int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_cpld_read); + +int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_cpld_write); + +static int __init alpha_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&alpha_i2c_cpld_driver); +} + +static void __exit alpha_i2c_cpld_exit(void) +{ + i2c_del_driver(&alpha_i2c_cpld_driver); +} + +static struct dmi_system_id snh60b0_dmi_table[] = { + { + .ident = "Alpha snh60b0-640f", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alpha"), + DMI_MATCH(DMI_PRODUCT_NAME, "snh60b0-640f"), + }, + } +}; + +int platform_alpha_snh60b0(void) +{ + return dmi_check_system(snh60b0_dmi_table); +} +EXPORT_SYMBOL(platform_alpha_snh60b0); + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("alpha_power_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(alpha_i2c_cpld_init); +module_exit(alpha_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_system_cpld.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_system_cpld.c new file mode 100644 index 000000000000..ddba09370ca2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_system_cpld.c @@ -0,0 +1,365 @@ +/* + * A hwmon driver for the snh60b0-640f_system_cpld + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Robin Chen + * 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 + * 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. + * see + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SYS_LED_REG 0x8 +#define FAN12_LED_REG 0x9 +#define FAN34_LED_REG 0xA +#define SYS_RESET1_REG 0x2 +#define SWI_CTRL_REG 0x4 + +#define SYS_LOCATOR_LED_BITS 0x01 +#define SYS_PWR_LED_BITS 0x0E +#define SYS_STATUS_LED_BITS 0x70 +#define FAN135_LED_BITS 0x07 +#define FAN246_LED_BITS 0x38 +#define REST_BUTTON_BITS 0x0 + + +extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +static ssize_t sys_led_read(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t sys_led_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for snh60b0-640f_system_cpld */ +static const unsigned short normal_i2c[] = { 0x5F, I2C_CLIENT_END }; + + +enum sysfs_sys_attributes { + SYS_LOCATOR, + SYS_PWR, + SYS_STATUS, + FAN1_LED, + FAN2_LED, + FAN3_LED, + FAN4_LED, + SYS_REST1, + SWI_CTRL, +}; + +static SENSOR_DEVICE_ATTR(sys_locator, (0660), sys_led_read, sys_led_write, SYS_LOCATOR); +static SENSOR_DEVICE_ATTR(sys_pwr, (0660), sys_led_read, sys_led_write, SYS_PWR); +static SENSOR_DEVICE_ATTR(sys_status, (0600), sys_led_read, sys_led_write, SYS_STATUS); +static SENSOR_DEVICE_ATTR(fan1_led, (0660), sys_led_read, sys_led_write, FAN1_LED); +static SENSOR_DEVICE_ATTR(fan2_led, (0660), sys_led_read, sys_led_write, FAN2_LED); +static SENSOR_DEVICE_ATTR(fan3_led, (0660), sys_led_read, sys_led_write, FAN3_LED); +static SENSOR_DEVICE_ATTR(fan4_led, (0660), sys_led_read, sys_led_write, FAN4_LED); +static SENSOR_DEVICE_ATTR(sys_reset1, (0660), sys_led_read, sys_led_write, SYS_REST1); +static SENSOR_DEVICE_ATTR(swi_ctrl, (0660), sys_led_read, NULL, SWI_CTRL); + +static struct attribute *snh60b0_sys_attributes[] = { + &sensor_dev_attr_sys_locator.dev_attr.attr, + &sensor_dev_attr_sys_pwr.dev_attr.attr, + &sensor_dev_attr_sys_status.dev_attr.attr, + &sensor_dev_attr_fan1_led.dev_attr.attr, + &sensor_dev_attr_fan2_led.dev_attr.attr, + &sensor_dev_attr_fan3_led.dev_attr.attr, + &sensor_dev_attr_fan4_led.dev_attr.attr, + &sensor_dev_attr_sys_reset1.dev_attr.attr, + &sensor_dev_attr_swi_ctrl.dev_attr.attr, + NULL +}; + +static const struct attribute_group snh60b0_sys_group = { + .attrs = snh60b0_sys_attributes, +}; + + +static ssize_t sys_led_read(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + + switch(sda->index) { + case SYS_LOCATOR: + case SYS_PWR: + case SYS_STATUS: + command = SYS_LED_REG; + break; + case FAN1_LED: + case FAN2_LED: + case FAN3_LED: + case FAN4_LED: + command = FAN12_LED_REG + (sda->index - FAN1_LED)/2; + break; + case SYS_REST1: + command = SYS_RESET1_REG; + break; + case SWI_CTRL: + command = SWI_CTRL_REG; + break; + } + + val = i2c_smbus_read_byte_data(client, command); + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + switch(sda->index) { + case SYS_LOCATOR: + res = (val & SYS_LOCATOR_LED_BITS) >> 0; + break; + case SYS_PWR: + res = (val & SYS_PWR_LED_BITS) >> 1; + break; + case SYS_STATUS: + res = (val & SYS_STATUS_LED_BITS) >> 4; + break; + case FAN1_LED: + case FAN3_LED: + res = (val & FAN135_LED_BITS) >> 0; + break; + case FAN2_LED: + case FAN4_LED: + res = (val & FAN246_LED_BITS) >> 3; + break; + case SYS_REST1: + res = val; + break; + case SWI_CTRL: + res = (val & REST_BUTTON_BITS) >> 0; + break; + } + + return sprintf(buf, "%d\n", res); +} + +static ssize_t sys_led_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + int error, write, command, read; + + error = kstrtoint(buf, 10, &write); + if (error) + return error; + + + switch(sda->index) { + case SYS_LOCATOR: + if(write < 0 || write > 2) + return -EINVAL; + case SYS_PWR: + case SYS_STATUS: + if (write < 0 || write > 7) + return -EINVAL; + command = SYS_LED_REG; + break; + case FAN1_LED: + case FAN2_LED: + case FAN3_LED: + case FAN4_LED: + if (write < 0 || write > 7) + return -EINVAL; + command = FAN12_LED_REG + (sda->index - FAN1_LED)/2; + break; + case SYS_REST1: + if (write < 0 || write > 15) + return -EINVAL; + command = SYS_RESET1_REG; + break; + } + + read = i2c_smbus_read_byte_data(client, command); + if (read < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, read); + } + + switch(sda->index) { + case SYS_LOCATOR: + read &= ~SYS_LOCATOR_LED_BITS; + read |= write << 0; + break; + case SYS_PWR: + read &= ~SYS_PWR_LED_BITS; + read |= write << 1; + break; + case SYS_STATUS: + read &= ~SYS_STATUS_LED_BITS; + read |= write << 4; + break; + case FAN1_LED: + case FAN3_LED: + read &= ~FAN135_LED_BITS; + read |= write << 0; + break; + case FAN2_LED: + case FAN4_LED: + read &= ~FAN246_LED_BITS; + read |= write << 3; + break; + case SYS_REST1: + read = write; + break; + } + + i2c_smbus_write_byte_data(client, command, read); + + return count; +} + + + +static void alpha_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int alpha_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &snh60b0_sys_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int alpha_i2c_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &snh60b0_sys_group); + alpha_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id alpha_i2c_cpld_id[] = { + { "snh60b0_system_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, alpha_i2c_cpld_id); + +static struct i2c_driver alpha_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "snh60b0_system_cpld", + }, + .probe = alpha_i2c_cpld_probe, + .remove = alpha_i2c_cpld_remove, + .id_table = alpha_i2c_cpld_id, + .address_list = normal_i2c, +}; + + +static int __init alpha_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&alpha_i2c_cpld_driver); +} + +static void __exit alpha_i2c_cpld_exit(void) +{ + i2c_del_driver(&alpha_i2c_cpld_driver); +} + + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("alpha_system_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(alpha_i2c_cpld_init); +module_exit(alpha_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/service/snh60b0-platform-init.service b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/service/snh60b0-platform-init.service new file mode 100644 index 000000000000..fa2e849c7c34 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/service/snh60b0-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Alphanetworks SNH60B0-640F Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/alphanetworks_snh60b0_util.py -f install +ExecStop=/usr/local/bin/alphanetworks_snh60b0_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/setup.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/setup.py new file mode 100644 index 000000000000..785a36660182 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='snh60b0_640f', + version='1.0', + description='Module to initialize Alphanetworks SNH60B0-640F platforms', + + packages=['snh60b0_640f'], + package_dir={'snh60b0_640f': 'snh60b0-640f/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/utils/alphanetworks_snh60b0_util.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/utils/alphanetworks_snh60b0_util.py new file mode 100755 index 000000000000..4b64a2e12a1f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/utils/alphanetworks_snh60b0_util.py @@ -0,0 +1,427 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Alphanetworks Technology Corporation. +# Robin Chen +# 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 +# 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. +# see +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'snh60b0-640f' +device_path = "x86_64-alphanetworks_snh60b0_640f-r0" +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +FORCE = 0 + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + 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 PROJECT_NAME.upper()+": "+txt + return + +def log_os_system(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 + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep alphanetworks", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x', +'modprobe optoe' , +'modprobe snh60b0-640f_power_cpld' , +'modprobe snh60b0-640f_system_cpld' , +'modprobe snh60b0-640f_onie_eeprom' , +'modprobe alphanetworks_snh60b0_640f_sfp' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + if kos[i].find('pca954') != -1: + status, output = log_os_system(kos[i]+ " force_deselect_on_exit=1", 1) + else: + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +i2c_prefix = '/sys/bus/i2c/devices/' + +sfp_map = [13,14,15,16,23] +mknod =[ +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-5/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-6/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo snh60b0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo snh60b0_power_cpld 0x5e > /sys/bus/i2c/devices/i2c-0/new_device', +'echo snh60b0_system_cpld 0x5f > /sys/bus/i2c/devices/i2c-8/new_device', +'echo lm75 0x4D > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4C > /sys/bus/i2c/devices/i2c-4/new_device', +'echo lm75 0x4F > /sys/bus/i2c/devices/i2c-0/new_device' ] + +mknod2 =[ +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-6/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-8/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo snh60b0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo snh60b0_power_cpld 0x5e > /sys/bus/i2c/devices/i2c-1/new_device', +'echo snh60b0_system_cpld 0x5f > /sys/bus/i2c/devices/i2c-9/new_device', +'echo lm75 0x4D > /sys/bus/i2c/devices/i2c-4/new_device', +'echo lm75 0x4C > /sys/bus/i2c/devices/i2c-5/new_device', +'echo lm75 0x4F > /sys/bus/i2c/devices/i2c-1/new_device' ] + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x76 is exist @ i2c-0 + tmp = "echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + tmp = "sed -i 's/0-/1-/g' /usr/share/sonic/device/"+device_path+"/fancontrol" + status, output = log_os_system(tmp, 0) + else: + order = 0 + tmp = "sed -i 's/1-/0-/g' /usr/share/sonic/device/"+device_path+"/fancontrol" + status, output = log_os_system(tmp, 0) + tmp = "echo 0x70 > /sys/bus/i2c/devices/i2c-0/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x76 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + if mknod2[i].find('lm75') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + if mknod[i].find('lm75') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + status, output =log_os_system("echo 0 > /sys/bus/i2c/devices/8-005f/sys_reset1", 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0, 66): + index = i / 16 + port = i % 16 + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + + if reg_sfp == 1: + if i == 64: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x20 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + if i < 64: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x5f > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + if i == 64: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-21/new_device", 1) + if status: + print output + if FORCE == 0: + return status + if i == 65: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-22/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0, 66): + index = i / 16 + port = i % 16 + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + + if reg_sfp == 1: + if i == 64: + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x20 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + if i < 64: + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x5f > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if i == 64: + status, output =log_os_system("echo 0x50 > /sys/bus/i2c/devices/i2c-21/delete_device", 1) + if status: + print output + if FORCE == 0: + return status + if i == 65: + status, output =log_os_system("echo 0x50 > /sys/bus/i2c/devices/i2c-22/delete_device", 1) + if status: + print output + if FORCE == 0: + return status + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + tmp = "find /var/lib/docker/overlay -iname fancontrol | grep usr/sbin/fancontrol | xargs cat | sed '429d' | sed '428a if \[ $? -ne 1 \]' | sed '425d' | sed '424a return' > /tmp/tmp_fancontrol" + status, output = log_os_system(tmp, 1) + tmp = "fancontrol_tmp=`find /var/lib/docker/overlay -iname fancontrol | grep usr/sbin/fancontrol` ; cp /tmp/tmp_fancontrol $fancontrol_tmp" + status, output = log_os_system(tmp, 1) + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-arista b/platform/broadcom/sonic-platform-modules-arista new file mode 160000 index 000000000000..0fc0c23d8bb8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-arista @@ -0,0 +1 @@ +Subproject commit 0fc0c23d8bb8826d6431f35aff12ad1a5e098395 diff --git a/platform/broadcom/sonic-platform-modules-cel/.gitignore b/platform/broadcom/sonic-platform-modules-cel/.gitignore new file mode 100644 index 000000000000..2490baa9d1e2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/.gitignore @@ -0,0 +1,59 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-cel/LICENSE b/platform/broadcom/sonic-platform-modules-cel/LICENSE new file mode 100644 index 000000000000..2386a3920c07 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2017 Celestica, 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 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-cel/README.md b/platform/broadcom/sonic-platform-modules-cel/README.md new file mode 100644 index 000000000000..26e45c685e44 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/README.md @@ -0,0 +1 @@ +platform drivers for Celestica DX010 and Haliburton for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/changelog b/platform/broadcom/sonic-platform-modules-cel/debian/changelog new file mode 100644 index 000000000000..843b028e4301 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/changelog @@ -0,0 +1,57 @@ +sonic-cel-platform-modules (0.9) unstable; urgency=low + + * Add haliburton platform module. + + -- Wirut Getbamrung Fri, 17 Aug 2018 10:10:10 +0700 + +sonic-cel-platform-modules (0.8) unstable; urgency=low + + * Add dx010 platform fan led control. + * The platform gpio init moved to kernel space. + + -- Pradchaya Phucharoen Mon, 1 Jul 2018 11:09:13 +0700 + +sonic-cel-platform-modules (0.7) unstable; urgency=low + + * Add dx010 plaform gpio sysfs exported when module load. + + -- Pradchaya Phucharoen Wed, 21 Jun 2018 13:29:05 +0700 + +sonic-cel-platform-modules (0.6) unstable; urgency=low + + * Remove unused port-mode switch script. This should be done by hwsku config script. + * Add script to turn off QSFP low power mode when boot up. + + -- Pradchaya Phucharoen Wed, 26 July 2017 10:43:00 +0700 + +sonic-cel-platform-modules (0.5) unstable; urgency=low + + * Add port-mode switch script to support 100G 50G 10G_50G qsfp modes. + * Fix garbage data when using sfputil to read QSFP-transceiver's eeprom. + * Fix incorrect endian in eeprom read word data. + + -- Pradchaya Phucharoen Tue, 18 July 2017 11:30:00 +0700 + +sonic-cel-platform-modules (0.4) unstable; urgency=low + + * Add support for DX010's fancontrol, automatic run-up and FIX bug lpmod + + -- Pariwat Leamsumran Thu, 14 June 2017 16:25:00 +0700 + +sonic-cel-platform-modules (0.3) unstable; urgency=low + + * Add support for DX010's DPS800 + + -- Abhisit Sangjan Thu, 29 May 2017 19:23:00 +0700 + +sonic-cel-platform-modules (0.2) unstable; urgency=low + + * Add support for DX010's LM75B, Watchdog and EMC2305 + + -- Abhisit Sangjan Thu, 25 May 2017 15:26:00 +0700 + +sonic-cel-platform-modules (0.1) unstable; urgency=low + + * Initial release + + -- Abhisit Sangjan Mon, 2 May 2017 14:47:00 +0700 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/compat b/platform/broadcom/sonic-platform-modules-cel/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/control b/platform/broadcom/sonic-platform-modules-cel/debian/control new file mode 100644 index 000000000000..9f561288d399 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/control @@ -0,0 +1,17 @@ +Source: sonic-cel-platform-modules +Section: main +Priority: extra +Maintainer: Abhisit Sangjan +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-dx010 +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + + +Package: platform-modules-haliburton +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init new file mode 100644 index 000000000000..2117ab22b402 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init @@ -0,0 +1,147 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: $portmap +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup DX010 board. +### END INIT INFO + +function export_gpio { +label=$2 +gpio_num=$1 +gpio_base=`( cat /sys/class/gpio/gpiochip*/base | head -1 ) 2>/dev/null` +gpio_label=`( cat /sys/class/gpio/gpiochip*/label | head -1 ) 2>/dev/null` +if [[ "X$gpio_base" == "X" ]] || +( [[ "X$label" != "X" ]] && [[ "$label" != "$gpio_label" ]] ); then + echo "Platform driver error: No gpiochip found!" + exit 1; +fi +ionum=$((gpio_base+gpio_num)) +echo $ionum > /sys/class/gpio/export +if [ $? -ne 0 ]; then + echo "Platform driver error: Cannot export gpio$ionum!" + exit 1; +fi +} + +case "$1" in +start) + echo -n "Setting up board... " + + modprobe i2c-dev + modprobe i2c-mux-pca954x + modprobe dx010_wdt + modprobe leds-dx010 + modprobe lm75 + + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find iSMT" && exit 1 + + i2cset -y ${devnum} 0x70 0x10 0x00 0x01 i + + # Attach PCA9541 Ox70 Master Selector + chmod 755 /sys/bus/i2c/devices/i2c-${devnum}/new_device + echo pca9541 0x70 > /sys/bus/i2c/devices/i2c-${devnum}/new_device + sleep 1 + + # Attach PCA9548 0x71 Channel Extender for Main Board + echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-${devnum}/new_device + sleep 1 + + # Attach PCA9548 0x73 Channel Extender for CPU Board + echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-${devnum}/new_device + sleep 1 + + # Attach PCA9548 0x77 Channel Extender for Fan's EEPROMs + echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-${devnum}/new_device + sleep 1 + + # Attach syseeprom + echo 24lc64t 0x50 > /sys/bus/i2c/devices/i2c-12/new_device + + # Attach temperature sensors + echo lm75b 0x48 > /sys/bus/i2c/devices/i2c-5/new_device + echo lm75b 0x49 > /sys/bus/i2c/devices/i2c-6/new_device + echo lm75b 0x4a > /sys/bus/i2c/devices/i2c-7/new_device + echo lm75b 0x48 > /sys/bus/i2c/devices/i2c-14/new_device + echo lm75b 0x4e > /sys/bus/i2c/devices/i2c-15/new_device + + # Attach fans + echo emc2305 0x2e > /sys/bus/i2c/devices/i2c-13/new_device + echo emc2305 0x4d > /sys/bus/i2c/devices/i2c-13/new_device + + # Attach PSUs + echo dps460 0x5a > /sys/bus/i2c/devices/i2c-10/new_device + echo dps460 0x5b > /sys/bus/i2c/devices/i2c-11/new_device + + # Attach PCA9506 GPIO expander for 40 pins + echo pca9505 0x20 > /sys/bus/i2c/devices/i2c-17/new_device + + modprobe dx010_cpld + sleep 2 + + # Export platform gpio sysfs + export_gpio 10 # Fan 1 present + export_gpio 11 # Fan 2 present + export_gpio 12 # Fan 3 present + export_gpio 13 # Fan 4 present + export_gpio 14 # Fan 5 present + + export_gpio 22 # PSU L PWOK + export_gpio 25 # PSU R PWOK + export_gpio 27 # PSU L ABS + export_gpio 28 # PSU R ABS + + export_gpio 29 # Fan 1 LED: Red + export_gpio 30 # Fan 1 LED: Yellow + export_gpio 31 # Fan 2 LED: Red + export_gpio 32 # Fan 2 LED: Yellow + export_gpio 33 # Fan 3 LED: Red + export_gpio 34 # Fan 3 LED: Yellow + export_gpio 35 # Fan 4 LED: Red + export_gpio 36 # Fan 4 LED: Yellow + export_gpio 37 # Fan 5 LED: Red + export_gpio 38 # Fan 5 LED: Yellow + + # Turn off/down lpmod by defult (0 - Normal, 1 - Low Pow) + echo 0x00000000 > /sys/devices/platform/dx010_cpld/qsfp_lpmode + + # Attach 32 instances of EEPROM driver QSFP ports + for ((n=26;n<=58;n++)); + do + echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-$n/new_device + sleep 0.1 + done + + echo "done." + ;; + +stop) + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-dx010.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install new file mode 100644 index 000000000000..b25d47022b08 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install @@ -0,0 +1,3 @@ +dx010/scripts/dx010_check_qsfp.sh usr/local/bin +dx010/cfg/dx010-modules.conf etc/modules-load.d +dx010/systemd/platform-modules-dx010.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst new file mode 100644 index 000000000000..baff704171c7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst @@ -0,0 +1,3 @@ +depmod -a +systemctl enable platform-modules-dx010.service +systemctl start platform-modules-dx010.service diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init new file mode 100644 index 000000000000..5192b202a3f9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init @@ -0,0 +1,84 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: $portmap +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Haliburton board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + modprobe smc + + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find iSMT" && exit 1 + + i2cset -y ${devnum} 0x73 0x10 0x00 0x01 i + + # Attach PCA9548 0x73 Channel Extender for CPU Board + echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-${devnum}/new_device + sleep 1 + + # Attach PCA9541 Ox71 Master Selector + chmod 755 /sys/bus/i2c/devices/i2c-${devnum}/new_device + echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-8/new_device + sleep 1 + + # Attach PCA9548 0x72 Channel Extender for Main Board + echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-8/new_device + sleep 1 + + # Attach syseeprom + echo 24lc64t 0x50 > /sys/bus/i2c/devices/i2c-2/new_device + + echo max6697 0x1a > /sys/bus/i2c/devices/i2c-3/new_device + echo max6697 0x1a > /sys/bus/i2c/devices/i2c-11/new_device + + + # Attach fans + echo emc2305 0x4d > /sys/bus/i2c/devices/i2c-23/new_device + + # Attach 4 SFP+ Uplink + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-14/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-15/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-16/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-17/new_device + + # Enable SFP module presence interrupt + echo "both" > /sys/devices/platform/e1031.smc/SFP/modabs_trig + echo 0 > /sys/devices/platform/e1031.smc/SFP/modabs_mask + + echo "done." + ;; + +stop) + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-haliburton.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.install new file mode 100644 index 000000000000..93b2eed633d1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.install @@ -0,0 +1,2 @@ +haliburton/cfg/haliburton-modules.conf etc/modules-load.d +haliburton/systemd/platform-modules-haliburton.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.postinst new file mode 100644 index 000000000000..bdc23c66d5a4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.postinst @@ -0,0 +1,3 @@ +depmod -a +systemctl enable platform-modules-haliburton.service +systemctl start platform-modules-haliburton.service diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/rules b/platform/broadcom/sonic-platform-modules-cel/debian/rules new file mode 100755 index 000000000000..5086302b70b2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/rules @@ -0,0 +1,33 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= dx010 haliburton + +%: + dh $@ + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -pplatform-modules-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/cfg/dx010-modules.conf b/platform/broadcom/sonic-platform-modules-cel/dx010/cfg/dx010-modules.conf new file mode 100644 index 000000000000..66f002a5fc94 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/cfg/dx010-modules.conf @@ -0,0 +1,15 @@ +# /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. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-gpio +i2c-mux-pca954x + diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/Makefile new file mode 100644 index 000000000000..9b0f10604811 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/Makefile @@ -0,0 +1 @@ +obj-m := dx010_cpld.o mc24lc64t.o emc2305.o dx010_wdt.o leds-dx010.o \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c new file mode 100644 index 000000000000..397361a5edd6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c @@ -0,0 +1,561 @@ +/* + * dx010_cpld.c - driver for SeaStone's CPLD + * + * Copyright (C) 2017 Celestica Corp. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "dx010_cpld" + +#define RESET0108 0x250 +#define RESET0910 0x251 +#define RESET1118 0x2d0 +#define RESET1921 0x2d1 +#define RESET2229 0x3d0 +#define RESET3032 0x3d1 + +#define LPMOD0108 0x252 +#define LPMOD0910 0x253 +#define LPMOD1118 0x2d2 +#define LPMOD1921 0x2d3 +#define LPMOD2229 0x3d2 +#define LPMOD3032 0x3d3 + +#define ABS0108 0x254 +#define ABS0910 0x255 +#define ABS1118 0x2d4 +#define ABS1921 0x2d5 +#define ABS2229 0x3d4 +#define ABS3032 0x3d5 + +#define INT0108 0x256 +#define INT0910 0x257 +#define INT1118 0x2d6 +#define INT1921 0x2d7 +#define INT2229 0x3d6 +#define INT3032 0x3d7 + + +#define LENGTH_PORT_CPLD 34 +#define PORT_BANK1_START 1 +#define PORT_BANK1_END 10 +#define PORT_BANK2_START 11 +#define PORT_BANK2_END 21 +#define PORT_BANK3_START 22 +#define PORT_BANK3_END 32 +#define PORT_SFPP1 33 +#define PORT_SFPP2 34 + +#define PORT_ID_BANK1 0x210 +#define PORT_ID_BANK2 0x290 +#define PORT_ID_BANK3 0x390 + +#define OPCODE_ID_BANK1 0x211 +#define OPCODE_ID_BANK2 0x291 +#define OPCODE_ID_BANK3 0x391 + +#define DEVADDR_ID_BANK1 0x212 +#define DEVADDR_ID_BANK2 0x292 +#define DEVADDR_ID_BANK3 0x392 + +#define CMDBYT_ID_BANK1 0x213 +#define CMDBYT_ID_BANK2 0x293 +#define CMDBYT_ID_BANK3 0x393 + +#define WRITE_ID_BANK1 0x220 +#define WRITE_ID_BANK2 0x2A0 +#define WRITE_ID_BANK3 0x3A0 + +#define READ_ID_BANK1 0x230 +#define READ_ID_BANK2 0x2B0 +#define READ_ID_BANK3 0x3B0 + +#define SSRR_ID_BANK1 0x216 +#define SSRR_ID_BANK2 0x296 +#define SSRR_ID_BANK3 0x396 + +#define HST_CNTL2_QUICK 0x00 +#define HST_CNTL2_BYTE 0x01 +#define HST_CNTL2_BYTE_DATA 0x02 +#define HST_CNTL2_WORD_DATA 0x03 +#define HST_CNTL2_BLOCK 0x05 + +struct dx010_i2c_data { + int portid; +}; + +struct dx010_cpld_data { + struct i2c_adapter *i2c_adapter[LENGTH_PORT_CPLD]; + struct mutex cpld_lock; +}; + +struct dx010_cpld_data *cpld_data; + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long reset = 0; + + mutex_lock(&cpld_data->cpld_lock); + + reset = + (inb(RESET3032) & 0x07) << (24+5) | + inb(RESET2229) << (24-3) | + (inb(RESET1921) & 0x07) << (16 + 2) | + inb(RESET1118) << (16-6) | + (inb(RESET0910) & 0x03 ) << 8 | + inb(RESET0108); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%8.8lx\n", reset & 0xffffffff); +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long reset; + int err; + + mutex_lock(&cpld_data->cpld_lock); + + err = kstrtoul(buf, 16, &reset); + if (err) + { + mutex_unlock(&cpld_data->cpld_lock); + return err; + } + + outb( (reset >> 0) & 0xFF, RESET0108); + outb( (reset >> 8) & 0x03, RESET0910); + outb( (reset >> 10) & 0xFF, RESET1118); + outb( (reset >> 18) & 0x07, RESET1921); + outb( (reset >> 21) & 0xFF, RESET2229); + outb( (reset >> 29) & 0x07, RESET3032); + + mutex_unlock(&cpld_data->cpld_lock); + + return count; +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long lpmod = 0; + + mutex_lock(&cpld_data->cpld_lock); + + lpmod = + (inb(LPMOD3032) & 0x07) << (24+5) | + inb(LPMOD2229) << (24-3) | + (inb(LPMOD1921) & 0x07) << (16 + 2) | + inb(LPMOD1118) << (16-6) | + (inb(LPMOD0910) & 0x03 ) << 8 | + inb(LPMOD0108); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%8.8lx\n", lpmod & 0xffffffff); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long lpmod; + int err; + + mutex_lock(&cpld_data->cpld_lock); + + err = kstrtoul(buf, 16, &lpmod); + if (err) + { + mutex_unlock(&cpld_data->cpld_lock); + return err; + } + + outb( (lpmod >> 0) & 0xFF, LPMOD0108); + outb( (lpmod >> 8) & 0x03, LPMOD0910); + outb( (lpmod >> 10) & 0xFF, LPMOD1118); + outb( (lpmod >> 18) & 0x07, LPMOD1921); + outb( (lpmod >> 21) & 0xFF, LPMOD2229); + outb( (lpmod >> 29) & 0x07, LPMOD3032); + + mutex_unlock(&cpld_data->cpld_lock); + + return count; +} + +static ssize_t get_modprs(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long present; + + mutex_lock(&cpld_data->cpld_lock); + + present = + (inb(ABS3032) & 0x07) << (24+5) | + inb(ABS2229) << (24-3) | + (inb(ABS1921) & 0x07) << (16 + 2) | + inb(ABS1118) << (16-6) | + (inb(ABS0910) & 0x03) << 8 | + inb(ABS0108); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%8.8lx\n", present & 0xffffffff); +} + +static ssize_t get_modirq(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long irq; + + mutex_lock(&cpld_data->cpld_lock); + + irq = + (inb(INT3032) & 0x07) << (24+5) | + inb(INT2229) << (24-3) | + (inb(INT1921) & 0x07) << (16 + 2) | + inb(INT1118) << (16-6) | + (inb(INT0910) & 0x03) << 8 | + inb(INT0108); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%8.8lx\n", irq & 0xffffffff); +} + +static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset); +static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode); +static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL); +static DEVICE_ATTR(qsfp_modirq, S_IRUGO, get_modirq, NULL); + +static struct attribute *dx010_lpc_attrs[] = { + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_qsfp_modirq.attr, + NULL, +}; + +static struct attribute_group dx010_lpc_attr_grp = { + .attrs = dx010_lpc_attrs, +}; + +static struct resource cel_dx010_lpc_resources[] = { + { + .flags = IORESOURCE_IO, + }, +}; + +static void cel_dx010_lpc_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device cel_dx010_lpc_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(cel_dx010_lpc_resources), + .resource = cel_dx010_lpc_resources, + .dev = { + .release = cel_dx010_lpc_dev_release, + } +}; + + +/** + * Read eeprom of QSFP device. + * @param a i2c adapter. + * @param addr address to read. + * @param new_data QSFP port number struct. + * @param cmd i2c command. + * @return 0 if not error, else the error code. + */ +static int i2c_read_eeprom(struct i2c_adapter *a, u16 addr, + struct dx010_i2c_data *new_data, u8 cmd, union i2c_smbus_data *data){ + + u32 reg; + int ioBase=0; + char byte; + short temp; + short portid, opcode, devaddr, cmdbyte0, ssrr, writedata, readdata; + __u16 word_data; + int error = -EIO; + + mutex_lock(&cpld_data->cpld_lock); + + if (((new_data->portid >= PORT_BANK1_START) + && (new_data->portid <= PORT_BANK1_END)) + || (new_data->portid == PORT_SFPP1) + || (new_data->portid == PORT_SFPP2)) + { + portid = PORT_ID_BANK1; + opcode = OPCODE_ID_BANK1; + devaddr = DEVADDR_ID_BANK1; + cmdbyte0 = CMDBYT_ID_BANK1; + ssrr = SSRR_ID_BANK1; + writedata = WRITE_ID_BANK1; + readdata = READ_ID_BANK1; + }else if ((new_data->portid >= PORT_BANK2_START) && (new_data->portid <= PORT_BANK2_END)){ + portid = PORT_ID_BANK2; + opcode = OPCODE_ID_BANK2; + devaddr = DEVADDR_ID_BANK2; + cmdbyte0 = CMDBYT_ID_BANK2; + ssrr = SSRR_ID_BANK2; + writedata = WRITE_ID_BANK2; + readdata = READ_ID_BANK2; + }else if ((new_data->portid >= PORT_BANK3_START) && (new_data->portid <= PORT_BANK3_END)){ + portid = PORT_ID_BANK3; + opcode = OPCODE_ID_BANK3; + devaddr = DEVADDR_ID_BANK3; + cmdbyte0 = CMDBYT_ID_BANK3; + ssrr = SSRR_ID_BANK3; + writedata = WRITE_ID_BANK3; + readdata = READ_ID_BANK3; + }else{ + /* Invalid parameter! */ + error = -EINVAL; + goto exit; + } + + while ((inb(ioBase + ssrr) & 0x40)); + if ((inb(ioBase + ssrr) & 0x80) == 0x80) { + error = -EIO; + /* Read error reset the port */ + outb(0x00, ioBase + ssrr); + udelay(3000); + outb(0x01, ioBase + ssrr); + goto exit; + } + + byte = 0x40 +new_data->portid; + reg = cmd; + outb(byte, ioBase + portid); + outb(reg,ioBase + cmdbyte0); + byte = 33; + outb(byte, ioBase + opcode); + addr = addr << 1; + addr |= 0x01; + outb(addr, ioBase + devaddr); + while ((inb(ioBase + ssrr) & 0x40)) + { + udelay(100); + } + + if ((inb(ioBase + ssrr) & 0x80) == 0x80) { + /* Read error reset the port */ + error = -EIO; + outb(0x00, ioBase + ssrr); + udelay(3000); + outb(0x01, ioBase + ssrr); + goto exit; + } + + temp = ioBase + readdata; + word_data = inb(temp); + word_data |= (inb(++temp) << 8); + + mutex_unlock(&cpld_data->cpld_lock); + data->word = word_data; + return 0; + +exit: + mutex_unlock(&cpld_data->cpld_lock); + return error; +} + +static int dx010_i2c_access(struct i2c_adapter *a, u16 addr, + unsigned short flags, char rw, u8 cmd, + int size, union i2c_smbus_data *data) +{ + + int error = 0; + + struct dx010_i2c_data *new_data; + + /* Write the command register */ + new_data = i2c_get_adapdata(a); + + /* Map the size to what the chip understands */ + switch (size) { + case I2C_SMBUS_QUICK: + size = HST_CNTL2_QUICK; + break; + case I2C_SMBUS_BYTE: + size = HST_CNTL2_BYTE; + break; + case I2C_SMBUS_BYTE_DATA: + size = HST_CNTL2_BYTE_DATA; + break; + case I2C_SMBUS_WORD_DATA: + size = HST_CNTL2_WORD_DATA; + break; + case I2C_SMBUS_BLOCK_DATA: + size = HST_CNTL2_BLOCK; + break; + default: + dev_warn(&a->dev, "Unsupported transaction %d\n", size); + error = -EOPNOTSUPP; + goto Done; + } + + switch (size) { + case HST_CNTL2_BYTE: /* Result put in SMBHSTDAT0 */ + break; + case HST_CNTL2_BYTE_DATA: + break; + case HST_CNTL2_WORD_DATA: + if( 0 == i2c_read_eeprom(a,addr,new_data,cmd,data)){ + error = 0; + }else{ + error = -EIO; + } + break; + } + +Done: + return error; +} + +static u32 dx010_i2c_func(struct i2c_adapter *a) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA; +} + +static const struct i2c_algorithm dx010_i2c_algorithm = { + .smbus_xfer = dx010_i2c_access, + .functionality = dx010_i2c_func, +}; + +static struct i2c_adapter * cel_dx010_i2c_init(struct platform_device *pdev, int portid) +{ + int error; + + struct i2c_adapter *new_adapter; + struct dx010_i2c_data *new_data; + + new_adapter = kzalloc(sizeof(*new_adapter), GFP_KERNEL); + if (!new_adapter) + return NULL; + + new_adapter->dev.parent = &pdev->dev; + new_adapter->owner = THIS_MODULE; + new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + new_adapter->algo = &dx010_i2c_algorithm; + + snprintf(new_adapter->name, sizeof(new_adapter->name), + "SMBus dx010 i2c Adapter portid@%04x", portid); + + new_data = kzalloc(sizeof(*new_data), GFP_KERNEL); + if (!new_data) + return NULL; + + new_data->portid = portid; + + i2c_set_adapdata(new_adapter,new_data); + + error = i2c_add_adapter(new_adapter); + if(error) + return NULL; + + return new_adapter; +}; + +static int cel_dx010_lpc_drv_probe(struct platform_device *pdev) +{ + struct resource *res; + int ret =0; + int portid_count; + + cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct dx010_cpld_data), + GFP_KERNEL); + if (!cpld_data) + return -ENOMEM; + + mutex_init(&cpld_data->cpld_lock); + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (unlikely(!res)) { + printk(KERN_ERR " Specified Resource Not Available...\n"); + return -1; + } + + ret = sysfs_create_group(&pdev->dev.kobj, &dx010_lpc_attr_grp); + if (ret) { + printk(KERN_ERR "Cannot create sysfs\n"); + } + + for(portid_count=1 ; portid_count<=LENGTH_PORT_CPLD ; portid_count++) + cpld_data->i2c_adapter[portid_count-1] = + cel_dx010_i2c_init(pdev, portid_count); + + return 0; +} + +static int cel_dx010_lpc_drv_remove(struct platform_device *pdev) +{ + int portid_count; + + sysfs_remove_group(&pdev->dev.kobj, &dx010_lpc_attr_grp); + + for (portid_count=1 ; portid_count<=LENGTH_PORT_CPLD ; portid_count++) + i2c_del_adapter(cpld_data->i2c_adapter[portid_count-1]); + + return 0; +} + +static struct platform_driver cel_dx010_lpc_drv = { + .probe = cel_dx010_lpc_drv_probe, + .remove = __exit_p(cel_dx010_lpc_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +int cel_dx010_lpc_init(void) +{ + platform_device_register(&cel_dx010_lpc_dev); + platform_driver_register(&cel_dx010_lpc_drv); + + return 0; +} + +void cel_dx010_lpc_exit(void) +{ + platform_driver_unregister(&cel_dx010_lpc_drv); + platform_device_unregister(&cel_dx010_lpc_dev); +} + +module_init(cel_dx010_lpc_init); +module_exit(cel_dx010_lpc_exit); + +MODULE_AUTHOR("Abhisit Sangjan "); +MODULE_AUTHOR("Pariwat Leamsumran "); +MODULE_DESCRIPTION("Celestica SeaStone DX010 LPC Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_wdt.c b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_wdt.c new file mode 100644 index 000000000000..a386c065051a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_wdt.c @@ -0,0 +1,215 @@ +/* + * Watchdog driver for the Seastone DX010 + * + * Copyright (C) 2017 Celestica Corp. + * + * 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 +#include + + +#define DRIVER_NAME "dx010_wdt" + +#define RESET_CTRL 0x102 +#define WDT_MASK 0x04 +#define WDI_GPIO_DIR 0x504 +#define WDI_GPIO 0x508 + +static bool nowayout = WATCHDOG_NOWAYOUT; + +struct dx010_wdt_drvdata { + struct watchdog_device wdt; + struct mutex lock; +}; + +static struct resource dx010_wdt_resources[] = { + { + .flags = IORESOURCE_IO, + }, +}; + +static void dx010_wdt_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device dx010_wdt_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(dx010_wdt_resources), + .resource = dx010_wdt_resources, + .dev = { + .release = dx010_wdt_dev_release, + } +}; + +static int dx010_wdt_start(struct watchdog_device *wdt_dev) +{ + struct dx010_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); + unsigned char reset_ctrl = 0x00; + unsigned long gpio ,dir; + + mutex_lock(&drvdata->lock); + + gpio = inl(WDI_GPIO); + gpio |= 1 << 15; + outl(gpio, WDI_GPIO); + + outl((inl(WDI_GPIO_DIR) & (~(1 << 15))), WDI_GPIO_DIR); + + reset_ctrl = inb(RESET_CTRL); + + gpio = inl(WDI_GPIO); + gpio &= ~(1 << 15); + outl_p( gpio, WDI_GPIO ); + + mdelay(10); + + gpio = inl(WDI_GPIO); + gpio |= (1 << 15); + outl_p( gpio, WDI_GPIO ); + + reset_ctrl |= WDT_MASK; + outb(reset_ctrl, RESET_CTRL); + + mutex_unlock(&drvdata->lock); + + return 0; +} + +static int dx010_wdt_stop(struct watchdog_device *wdt_dev) +{ + struct dx010_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); + unsigned long reset_ctrl; + + mutex_lock(&drvdata->lock); + + reset_ctrl = inb(RESET_CTRL); + reset_ctrl &= ~WDT_MASK; + outb(reset_ctrl, RESET_CTRL); + + mutex_unlock(&drvdata->lock); + + return 0; +} + +static int dx010_wdt_ping(struct watchdog_device *wdt_dev) +{ + struct dx010_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); + unsigned long gpio; + + mutex_lock(&drvdata->lock); + + gpio = inl(WDI_GPIO); + gpio &= ~(1 << 15); + outl_p( gpio, WDI_GPIO ); + + mdelay(10); + + gpio = inl(WDI_GPIO); + gpio |= (1 << 15); + outl_p( gpio, WDI_GPIO ); + + mutex_unlock(&drvdata->lock); + + return 0; +} + +static const struct watchdog_info dx010_wdt_info = { + .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, + .identity = "DX010 Watchdog", +}; + +static const struct watchdog_ops dx010_wdt_ops = { + .owner = THIS_MODULE, + .start = dx010_wdt_start, + .stop = dx010_wdt_stop, + .ping = dx010_wdt_ping, +}; + +static int dx010_wdt_probe(struct platform_device *pdev) +{ + struct dx010_wdt_drvdata *drvdata; + int ret; + + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), + GFP_KERNEL); + if (!drvdata) { + ret = -ENOMEM; + goto err; + } + + mutex_init(&drvdata->lock); + + drvdata->wdt.info = &dx010_wdt_info; + drvdata->wdt.ops = &dx010_wdt_ops; + + watchdog_set_nowayout(&drvdata->wdt, nowayout); + watchdog_set_drvdata(&drvdata->wdt, drvdata); + + ret = watchdog_register_device(&drvdata->wdt); + if (ret != 0) { + dev_err(&pdev->dev, "watchdog_register_device() failed: %d\n", + ret); + goto err; + } + + platform_set_drvdata(pdev, drvdata); + +err: + return ret; +} + +static int dx010_wdt_remove(struct platform_device *pdev) +{ + struct dx010_wdt_drvdata *drvdata = platform_get_drvdata(pdev); + + watchdog_unregister_device(&drvdata->wdt); + + return 0; +} + +static struct platform_driver dx010_wdt_drv = { + .probe = dx010_wdt_probe, + .remove = dx010_wdt_remove, + .driver = { + .name = DRIVER_NAME, + }, +}; + +int dx010_wdt_init(void) +{ + platform_device_register(&dx010_wdt_dev); + platform_driver_register(&dx010_wdt_drv); + + return 0; +} + +void dx010_wdt_exit(void) +{ + platform_driver_unregister(&dx010_wdt_drv); + platform_device_unregister(&dx010_wdt_dev); +} + +module_init(dx010_wdt_init); +module_exit(dx010_wdt_exit); + +MODULE_AUTHOR("Abhisit Sangjan "); +MODULE_AUTHOR("Pariwat Leamsumran "); +MODULE_DESCRIPTION("Seastone DX010 Watchdog"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:dx010-watchdog"); diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/emc2305.c b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/emc2305.c new file mode 100644 index 000000000000..b406a29fd9be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/emc2305.c @@ -0,0 +1,886 @@ +/* + * emc2305.c - hwmon driver for SMSC EMC2305 fan controller + * (C) Copyright 2013 + * Reinhard Pfau, Guntermann & Drunck GmbH + * + * Based on emc2103 driver by SMSC. + * + * Datasheet available at: + * http://www.smsc.com/Downloads/SMSC/Downloads_Public/Data_Sheets/2305.pdf + * + * Also supports the EMC2303 fan controller which has the same functionality + * and register layout as EMC2305, but supports only up to 3 fans instead of 5. + * + * Also supports EMC2302 (up to 2 fans) and EMC2301 (1 fan) fan controller. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * TODO / IDEAS: + * - expose more of the configuration and features + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Addresses scanned. + * Listed in the same order as they appear in the EMC2305, EMC2303 data sheets. + * + * Note: these are the I2C adresses which are possible for EMC2305 and EMC2303 + * chips. + * The EMC2302 supports only 0x2e (EMC2302-1) and 0x2f (EMC2302-2). + * The EMC2301 supports only 0x2f. + */ +static const unsigned short i2c_adresses[] = { + 0x2E, + 0x2F, + 0x2C, + 0x2D, + 0x4C, + 0x4D, + I2C_CLIENT_END +}; + +/* + * global registers + */ +enum { + REG_CONFIGURATION = 0x20, + REG_FAN_STATUS = 0x24, + REG_FAN_STALL_STATUS = 0x25, + REG_FAN_SPIN_STATUS = 0x26, + REG_DRIVE_FAIL_STATUS = 0x27, + REG_FAN_INTERRUPT_ENABLE = 0x29, + REG_PWM_POLARITY_CONFIG = 0x2a, + REG_PWM_OUTPUT_CONFIG = 0x2b, + REG_PWM_BASE_FREQ_1 = 0x2c, + REG_PWM_BASE_FREQ_2 = 0x2d, + REG_SOFTWARE_LOCK = 0xef, + REG_PRODUCT_FEATURES = 0xfc, + REG_PRODUCT_ID = 0xfd, + REG_MANUFACTURER_ID = 0xfe, + REG_REVISION = 0xff +}; + +/* + * fan specific registers + */ +enum { + REG_FAN_SETTING = 0x30, + REG_PWM_DIVIDE = 0x31, + REG_FAN_CONFIGURATION_1 = 0x32, + REG_FAN_CONFIGURATION_2 = 0x33, + REG_GAIN = 0x35, + REG_FAN_SPIN_UP_CONFIG = 0x36, + REG_FAN_MAX_STEP = 0x37, + REG_FAN_MINIMUM_DRIVE = 0x38, + REG_FAN_VALID_TACH_COUNT = 0x39, + REG_FAN_DRIVE_FAIL_BAND_LOW = 0x3a, + REG_FAN_DRIVE_FAIL_BAND_HIGH = 0x3b, + REG_TACH_TARGET_LOW = 0x3c, + REG_TACH_TARGET_HIGH = 0x3d, + REG_TACH_READ_HIGH = 0x3e, + REG_TACH_READ_LOW = 0x3f, +}; + +#define SEL_FAN(fan, reg) (reg + fan * 0x10) + +/* + * Factor by equations [2] and [3] from data sheet; valid for fans where the + * number of edges equals (poles * 2 + 1). + */ +#define FAN_RPM_FACTOR 3932160 + + +struct emc2305_fan_data { + bool enabled; + bool valid; + unsigned long last_updated; + bool rpm_control; + u8 multiplier; + u8 poles; + u16 target; + u16 tach; + u16 rpm_factor; + u8 pwm; +}; + +struct emc2305_data { + struct device *hwmon_dev; + struct mutex update_lock; + int fans; + struct emc2305_fan_data fan[5]; +}; + +static int read_u8_from_i2c(struct i2c_client *client, u8 i2c_reg, u8 *output) +{ + int status = i2c_smbus_read_byte_data(client, i2c_reg); + if (status < 0) { + dev_warn(&client->dev, "reg 0x%02x, err %d\n", + i2c_reg, status); + } else { + *output = status; + } + return status; +} + +static void read_fan_from_i2c(struct i2c_client *client, u16 *output, + u8 hi_addr, u8 lo_addr) +{ + u8 high_byte, lo_byte; + + if (read_u8_from_i2c(client, hi_addr, &high_byte) < 0) + return; + + if (read_u8_from_i2c(client, lo_addr, &lo_byte) < 0) + return; + + *output = ((u16)high_byte << 5) | (lo_byte >> 3); +} + +static void write_fan_target_to_i2c(struct i2c_client *client, int fan, + u16 new_target) +{ + const u8 lo_reg = SEL_FAN(fan, REG_TACH_TARGET_LOW); + const u8 hi_reg = SEL_FAN(fan, REG_TACH_TARGET_HIGH); + u8 high_byte = (new_target & 0x1fe0) >> 5; + u8 low_byte = (new_target & 0x001f) << 3; + i2c_smbus_write_byte_data(client, lo_reg, low_byte); + i2c_smbus_write_byte_data(client, hi_reg, high_byte); +} + +static void read_fan_config_from_i2c(struct i2c_client *client, int fan) + +{ + struct emc2305_data *data = i2c_get_clientdata(client); + u8 conf1; + + if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_CONFIGURATION_1), + &conf1) < 0) + return; + + data->fan[fan].rpm_control = (conf1 & 0x80) != 0; + data->fan[fan].multiplier = 1 << ((conf1 & 0x60) >> 5); + data->fan[fan].poles = ((conf1 & 0x18) >> 3) + 1; +} + +static void read_fan_setting(struct i2c_client *client, int fan) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + u8 setting; + + if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_SETTING), + &setting) < 0) + return; + + data->fan[fan].pwm = setting; +} + +static void read_fan_data(struct i2c_client *client, int fan_idx) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + + read_fan_from_i2c(client, &data->fan[fan_idx].target, + SEL_FAN(fan_idx, REG_TACH_TARGET_HIGH), + SEL_FAN(fan_idx, REG_TACH_TARGET_LOW)); + read_fan_from_i2c(client, &data->fan[fan_idx].tach, + SEL_FAN(fan_idx, REG_TACH_READ_HIGH), + SEL_FAN(fan_idx, REG_TACH_READ_LOW)); +} + +static struct emc2305_fan_data * +emc2305_update_fan(struct i2c_client *client, int fan_idx) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan_data = &data->fan[fan_idx]; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) + || !fan_data->valid) { + read_fan_config_from_i2c(client, fan_idx); + read_fan_data(client, fan_idx); + read_fan_setting(client, fan_idx); + fan_data->valid = true; + fan_data->last_updated = jiffies; + } + + mutex_unlock(&data->update_lock); + return fan_data; +} + +static struct emc2305_fan_data * +emc2305_update_device_fan(struct device *dev, struct device_attribute *da) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + + return emc2305_update_fan(client, fan_idx); +} + +/* + * set/ config functions + */ + +/* + * Note: we also update the fan target here, because its value is + * determined in part by the fan clock divider. This follows the principle + * of least surprise; the user doesn't expect the fan target to change just + * because the divider changed. + */ +static int +emc2305_set_fan_div(struct i2c_client *client, int fan_idx, long new_div) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); + int new_range_bits, old_div = 8 / fan->multiplier; + int status = 0; + + if (new_div == old_div) /* No change */ + return 0; + + switch (new_div) { + case 1: + new_range_bits = 3; + break; + case 2: + new_range_bits = 2; + break; + case 4: + new_range_bits = 1; + break; + case 8: + new_range_bits = 0; + break; + default: + return -EINVAL; + } + + mutex_lock(&data->update_lock); + + status = i2c_smbus_read_byte_data(client, reg_conf1); + if (status < 0) { + dev_dbg(&client->dev, "reg 0x%02x, err %d\n", + reg_conf1, status); + status = -EIO; + goto exit_unlock; + } + status &= 0x9F; + status |= (new_range_bits << 5); + status = i2c_smbus_write_byte_data(client, reg_conf1, status); + if (status < 0) { + status = -EIO; + goto exit_invalidate; + } + + fan->multiplier = 8 / new_div; + + /* update fan target if high byte is not disabled */ + if ((fan->target & 0x1fe0) != 0x1fe0) { + u16 new_target = (fan->target * old_div) / new_div; + fan->target = min_t(u16, new_target, 0x1fff); + write_fan_target_to_i2c(client, fan_idx, fan->target); + } + +exit_invalidate: + /* invalidate fan data to force re-read from hardware */ + fan->valid = false; +exit_unlock: + mutex_unlock(&data->update_lock); + return status; +} + +static int +emc2305_set_fan_target(struct i2c_client *client, int fan_idx, long rpm_target) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + + /* + * Datasheet states 16000 as maximum RPM target + * (table 2.2 and section 4.3) + */ + if ((rpm_target < 0) || (rpm_target > 16000)) + return -EINVAL; + + mutex_lock(&data->update_lock); + + if (rpm_target == 0) + fan->target = 0x1fff; + else + fan->target = clamp_val( + (FAN_RPM_FACTOR * fan->multiplier) / rpm_target, + 0, 0x1fff); + + write_fan_target_to_i2c(client, fan_idx, fan->target); + + mutex_unlock(&data->update_lock); + return 0; +} + +static int +emc2305_set_pwm_enable(struct i2c_client *client, int fan_idx, long enable) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_fan_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); + int status = 0; + u8 conf_reg; + + mutex_lock(&data->update_lock); + switch (enable) { + case 0: + fan->rpm_control = false; + break; + case 3: + fan->rpm_control = true; + break; + default: + status = -EINVAL; + goto exit_unlock; + } + + status = read_u8_from_i2c(client, reg_fan_conf1, &conf_reg); + if (status < 0) { + status = -EIO; + goto exit_unlock; + } + + if (fan->rpm_control) + conf_reg |= 0x80; + else + conf_reg &= ~0x80; + + status = i2c_smbus_write_byte_data(client, reg_fan_conf1, conf_reg); + if (status < 0) + status = -EIO; + +exit_unlock: + mutex_unlock(&data->update_lock); + return status; +} + +static int +emc2305_set_pwm(struct i2c_client *client, int fan_idx, long pwm) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_fan_setting = SEL_FAN(fan_idx, REG_FAN_SETTING); + int status = 0; + + /* + * Datasheet states 255 as maximum PWM + * (section 5.7) + */ + if ((pwm < 0) || (pwm > 255)) + return -EINVAL; + + fan->pwm = pwm; + + mutex_lock(&data->update_lock); + + status = i2c_smbus_write_byte_data(client, reg_fan_setting, fan->pwm); + + mutex_unlock(&data->update_lock); + return status; +} +/* + * sysfs callback functions + * + * Note: + * Naming of the funcs is modelled after the naming scheme described in + * Documentation/hwmon/sysfs-interface: + * + * For a sysfs file _ the functions are named like this: + * the show function: show__ + * the store function: set__ + * For read only (RO) attributes of course only the show func is required. + * + * This convention allows us to define the sysfs attributes by using macros. + */ + +static ssize_t +show_fan_input(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int rpm = 0; + if (fan->tach != 0) + rpm = (FAN_RPM_FACTOR * fan->multiplier) / fan->tach; + return sprintf(buf, "%d\n", rpm); +} + +static ssize_t +show_fan_fault(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + bool fault = ((fan->tach & 0x1fe0) == 0x1fe0); + return sprintf(buf, "%d\n", fault ? 1 : 0); +} + +static ssize_t +show_fan_div(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int fan_div = 8 / fan->multiplier; + return sprintf(buf, "%d\n", fan_div); +} + +static ssize_t +show_fan_alarm(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + bool fault = ((fan->tach & 0x1fe0) == 0x1fe0); + return sprintf(buf, "%d\n", fault ? 1 : 0); +} + +static ssize_t +set_fan_div(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long new_div; + int status; + + status = kstrtol(buf, 10, &new_div); + if (status < 0) + return -EINVAL; + + status = emc2305_set_fan_div(client, fan_idx, new_div); + if (status < 0) + return status; + + return count; +} + +static ssize_t +show_fan_target(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int rpm = 0; + + /* high byte of 0xff indicates disabled so return 0 */ + if ((fan->target != 0) && ((fan->target & 0x1fe0) != 0x1fe0)) + rpm = (FAN_RPM_FACTOR * fan->multiplier) + / fan->target; + + return sprintf(buf, "%d\n", rpm); +} + +static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long rpm_target; + int status; + + status = kstrtol(buf, 10, &rpm_target); + if (status < 0) + return -EINVAL; + + status = emc2305_set_fan_target(client, fan_idx, rpm_target); + if (status < 0) + return status; + + return count; +} + +static ssize_t +show_pwm_enable(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + return sprintf(buf, "%d\n", fan->rpm_control ? 3 : 0); +} + +static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long new_value; + int status; + + status = kstrtol(buf, 10, &new_value); + if (status < 0) + return -EINVAL; + status = emc2305_set_pwm_enable(client, fan_idx, new_value); + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + return sprintf(buf, "%d\n", fan->pwm); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + unsigned long val; + int ret; + int status; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + if (val > 255) + return -EINVAL; + + status = emc2305_set_pwm(client, fan_idx, val); + return count; +} + +/* define a read only attribute */ +#define EMC2305_ATTR_RO(_type, _item, _num) \ + SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO, \ + show_## _type ## _ ## _item, NULL, _num - 1) + +/* define a read/write attribute */ +#define EMC2305_ATTR_RW(_type, _item, _num) \ + SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO | S_IWUSR, \ + show_## _type ##_ ## _item, \ + set_## _type ## _ ## _item, _num - 1) + +/* + * TODO: Ugly hack, but temporary as this whole logic needs + * to be rewritten as per standard HWMON sysfs registration + */ + +/* define a read/write attribute */ +#define EMC2305_ATTR_RW2(_type, _num) \ + SENSOR_ATTR(_type ## _num, S_IRUGO | S_IWUSR, \ + show_## _type, set_## _type, _num - 1) + +/* defines the attributes for a single fan */ +#define EMC2305_DEFINE_FAN_ATTRS(_num) \ + static const \ + struct sensor_device_attribute emc2305_attr_fan ## _num[] = { \ + EMC2305_ATTR_RO(fan, input, _num), \ + EMC2305_ATTR_RO(fan, fault, _num), \ + EMC2305_ATTR_RW(fan, div, _num), \ + EMC2305_ATTR_RO(fan, alarm, _num), \ + EMC2305_ATTR_RW(fan, target, _num), \ + EMC2305_ATTR_RW(pwm, enable, _num), \ + EMC2305_ATTR_RW2(pwm, _num) \ + } + +#define EMC2305_NUM_FAN_ATTRS ARRAY_SIZE(emc2305_attr_fan1) + +/* common attributes for EMC2303 and EMC2305 */ +static const struct sensor_device_attribute emc2305_attr_common[] = { +}; + +/* fan attributes for the single fans */ +EMC2305_DEFINE_FAN_ATTRS(1); +EMC2305_DEFINE_FAN_ATTRS(2); +EMC2305_DEFINE_FAN_ATTRS(3); +EMC2305_DEFINE_FAN_ATTRS(4); +EMC2305_DEFINE_FAN_ATTRS(5); +EMC2305_DEFINE_FAN_ATTRS(6); + +/* fan attributes */ +static const struct sensor_device_attribute *emc2305_fan_attrs[] = { + emc2305_attr_fan1, + emc2305_attr_fan2, + emc2305_attr_fan3, + emc2305_attr_fan4, + emc2305_attr_fan5, +}; + +/* + * driver interface + */ + +static int emc2305_remove(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + int fan_idx, i; + + hwmon_device_unregister(data->hwmon_dev); + + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) + device_remove_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) + device_remove_file(&client->dev, + &emc2305_attr_common[i].dev_attr); + + kfree(data); + return 0; +} + + +#ifdef CONFIG_OF +/* + * device tree support + */ + +struct of_fan_attribute { + const char *name; + int (*set)(struct i2c_client*, int, long); +}; + +struct of_fan_attribute of_fan_attributes[] = { + {"fan-div", emc2305_set_fan_div}, + {"fan-target", emc2305_set_fan_target}, + {"pwm-enable", emc2305_set_pwm_enable}, + {NULL, NULL} +}; + +static int emc2305_config_of(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct device_node *node; + unsigned int fan_idx; + + if (!client->dev.of_node) + return -EINVAL; + if (!of_get_next_child(client->dev.of_node, NULL)) + return 0; + + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + data->fan[fan_idx].enabled = false; + + for_each_child_of_node(client->dev.of_node, node) { + const __be32 *property; + int len; + struct of_fan_attribute *attr; + + property = of_get_property(node, "reg", &len); + if (!property || len != sizeof(int)) { + dev_err(&client->dev, "invalid reg on %s\n", + node->full_name); + continue; + } + + fan_idx = be32_to_cpup(property); + if (fan_idx >= data->fans) { + dev_err(&client->dev, + "invalid fan index %d on %s\n", + fan_idx, node->full_name); + continue; + } + + data->fan[fan_idx].enabled = true; + + for (attr = of_fan_attributes; attr->name; ++attr) { + int status = 0; + long value; + property = of_get_property(node, attr->name, &len); + if (!property) + continue; + if (len != sizeof(int)) { + dev_err(&client->dev, "invalid %s on %s\n", + attr->name, node->full_name); + continue; + } + value = be32_to_cpup(property); + status = attr->set(client, fan_idx, value); + if (status == -EINVAL) { + dev_err(&client->dev, + "invalid value for %s on %s\n", + attr->name, node->full_name); + } + } + } + + return 0; +} + +#endif + +static void emc2305_get_config(struct i2c_client *client) +{ + int i; + struct emc2305_data *data = i2c_get_clientdata(client); + + for (i = 0; i < data->fans; ++i) { + data->fan[i].enabled = true; + emc2305_update_fan(client, i); + } + +#ifdef CONFIG_OF + emc2305_config_of(client); +#endif + +} + +static int +emc2305_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct emc2305_data *data; + int status; + int i; + int fan_idx; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct emc2305_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + status = i2c_smbus_read_byte_data(client, REG_PRODUCT_ID); + switch (status) { + case 0x34: /* EMC2305 */ + data->fans = 5; + break; + case 0x35: /* EMC2303 */ + data->fans = 3; + break; + case 0x36: /* EMC2302 */ + data->fans = 2; + break; + case 0x37: /* EMC2301 */ + data->fans = 1; + break; + default: + if (status >= 0) + status = -EINVAL; + goto exit_free; + } + + emc2305_get_config(client); + + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) { + status = device_create_file(&client->dev, + &emc2305_attr_common[i].dev_attr); + if (status) + goto exit_remove; + } + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) { + if (!data->fan[fan_idx].enabled) + continue; + status = device_create_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + if (status) + goto exit_remove_fans; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove_fans; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove_fans: + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) + device_remove_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + +exit_remove: + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) + device_remove_file(&client->dev, + &emc2305_attr_common[i].dev_attr); +exit_free: + kfree(data); + return status; +} + +static const struct i2c_device_id emc2305_id[] = { + { "emc2305", 0 }, + { "emc2303", 0 }, + { "emc2302", 0 }, + { "emc2301", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, emc2305_id); + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int +emc2305_detect(struct i2c_client *new_client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + int manufacturer, product; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + manufacturer = + i2c_smbus_read_byte_data(new_client, REG_MANUFACTURER_ID); + if (manufacturer != 0x5D) + return -ENODEV; + + product = i2c_smbus_read_byte_data(new_client, REG_PRODUCT_ID); + + switch (product) { + case 0x34: + strlcpy(info->type, "emc2305", I2C_NAME_SIZE); + break; + case 0x35: + strlcpy(info->type, "emc2303", I2C_NAME_SIZE); + break; + case 0x36: + strlcpy(info->type, "emc2302", I2C_NAME_SIZE); + break; + case 0x37: + strlcpy(info->type, "emc2301", I2C_NAME_SIZE); + break; + default: + return -ENODEV; + } + + return 0; +} + +static struct i2c_driver emc2305_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc2305", + }, + .probe = emc2305_probe, + .remove = emc2305_remove, + .id_table = emc2305_id, +/* + .detect = emc2305_detect, + .address_list = i2c_adresses, +*/ +}; + +module_i2c_driver(emc2305_driver); + +MODULE_AUTHOR("Reinhard Pfau "); +MODULE_DESCRIPTION("SMSC EMC2305 hwmon driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/leds-dx010.c b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/leds-dx010.c new file mode 100644 index 000000000000..fac8322f06b0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/leds-dx010.c @@ -0,0 +1,289 @@ +/* + * leds-dx010-status.c - Driver for Seastone DX010 front panel LEDs + * + * Copyright (C) 2017 Celestica Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#define DRIVER_NAME "leds_dx010" +#define FRONT_LED_STAT 0x303 + +static int dx010_led_blink_stat(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + unsigned char led; + + if (!(*delay_on == 0 && *delay_off == 0) && + !(*delay_on == 250 && *delay_off == 250) && + !(*delay_on == 500 && *delay_off == 500)) + return -EINVAL; + + led = inb(FRONT_LED_STAT); + led &= 0xfc; + + if ((*delay_on == 250) && (*delay_off == 250)) + led |= 0x02; + else if ((*delay_on == 500) && (*delay_off == 500)) + led |= 0x01; + + outb(led, FRONT_LED_STAT); + + return 0; +} + +static ssize_t dx010_led_blink_show_stat(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *leddev = dev_get_drvdata(dev); + unsigned char led; + const char *msg; + + led = inb(FRONT_LED_STAT); + led &= 0x03; + + switch (led) + { + case 0: + msg = "No blinking, turn on"; + break; + case 1: + msg = "1 Hz is blinking"; + break; + case 2: + msg = "4 Hz is blinking"; + break; + case 3: + msg = "No blinking, turn off"; + break; + default: + msg = "Unknown error"; + break; + } + + return sprintf(buf, "%s\n", msg); +} + +static ssize_t dx010_led_blink_store_stat(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + struct led_classdev *leddev = dev_get_drvdata(dev); + unsigned long blink_state; + unsigned char led; + + ret = kstrtoul(buf, 10, &blink_state); + if (ret) + return ret; + + led = inb(FRONT_LED_STAT); + led &= 0xfc; + + switch (blink_state) + { + case 0: + led |= 0x03; + break; + case 1: + break; + case 250: + led |= 0x02; + break; + case 500: + led |= 0x01; + break; + default: + return -EINVAL; + break; + } + + outb(led, FRONT_LED_STAT); + + return size; +} +static DEVICE_ATTR(blink, 0644, dx010_led_blink_show_stat, dx010_led_blink_store_stat); + +static void dx010_led_brightness_set_stat(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + unsigned char led; + + led = inb(FRONT_LED_STAT); + led &= 0xfc; + + if (!brightness) + led |= 0x03; + + outb( led, FRONT_LED_STAT); +} + +enum led_brightness dx010_led_brightness_get_p2(struct led_classdev *led_cdev) +{ + unsigned char led; + + led = inb(FRONT_LED_STAT); + + return (led & 0x08) ? LED_OFF : LED_FULL; +} + +static void dx010_led_brightness_set_p2(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + unsigned char led; + + led = inb(FRONT_LED_STAT); + led &= 0xf7; + + if (!brightness) + led |= 0x08; + + outb( led, FRONT_LED_STAT); +} + +enum led_brightness dx010_led_brightness_get_p1(struct led_classdev *led_cdev) +{ + unsigned char led; + + led = inb(FRONT_LED_STAT); + + return (led & 0x04) ? LED_OFF : LED_FULL; +} + +static void dx010_led_brightness_set_p1(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + unsigned char led; + + led = inb(FRONT_LED_STAT); + led &= 0xfb; + + if (!brightness) + led |= 0x04; + + outb( led, FRONT_LED_STAT); +} + +static struct led_classdev dx010_leds[] = { + { + .name = "dx010:green:p-1", + .brightness = LED_OFF, + .max_brightness = 1, + .brightness_get = dx010_led_brightness_get_p1, + .brightness_set = dx010_led_brightness_set_p1, + }, + { + .name = "dx010:green:p-2", + .brightness = LED_OFF, + .max_brightness = 1, + .brightness_get = dx010_led_brightness_get_p2, + .brightness_set = dx010_led_brightness_set_p2, + }, + { + .name = "dx010:green:stat", + .brightness = LED_OFF, + .max_brightness = 1, + .brightness_set = dx010_led_brightness_set_stat, + .blink_set = dx010_led_blink_stat, + .flags = LED_CORE_SUSPENDRESUME, + }, +}; + +static struct resource dx010_led_resources[] = { + { + .flags = IORESOURCE_IO, + }, +}; + +static void dx010_led_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device dx010_lpc_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(dx010_led_resources), + .resource = dx010_led_resources, + .dev = { + .release = dx010_led_dev_release, + } +}; + +static int dx010_led_drv_probe(struct platform_device *pdev) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(dx010_leds); i++) { + ret = led_classdev_register(&pdev->dev, &dx010_leds[i]); + if (ret < 0) + goto exit; + } + + ret = device_create_file(&pdev->dev, &dev_attr_blink); + if (ret) + { + for (i = 0; i < ARRAY_SIZE(dx010_leds); i++) + led_classdev_unregister(&dx010_leds[i]); + } +exit: + return ret; +} + +static int dx010_led_drv_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dx010_leds); i++) + led_classdev_unregister(&dx010_leds[i]); + + device_remove_file(&pdev->dev, &dev_attr_blink); + + return 0; +} + +static struct platform_driver dx010_led_drv = { + .probe = dx010_led_drv_probe, + .remove = __exit_p(dx010_led_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +int dx010_led_init(void) +{ + platform_device_register(&dx010_lpc_dev); + platform_driver_register(&dx010_led_drv); + + return 0; +} + +void dx010_led_exit(void) +{ + platform_driver_unregister(&dx010_led_drv); + platform_device_unregister(&dx010_lpc_dev); +} + +module_init(dx010_led_init); +module_exit(dx010_led_exit); + +MODULE_AUTHOR("Abhisit Sangjan "); +MODULE_DESCRIPTION("Celestica SeaStone DX010 LEDs Front Panel Status Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/mc24lc64t.c new file mode 100644 index 000000000000..a391056d09a7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/mc24lc64t.c @@ -0,0 +1,142 @@ +/* + * mc24lc64t.c - driver for Microchip 24LC64T + * + * Copyright (C) 2017 Celestica Corp. + * + * 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 + +struct mc24lc64t_data { + struct i2c_client *fake_client; + struct mutex update_lock; +}; + +static ssize_t mc24lc64t_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = kobj_to_i2c_client(kobj); + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + unsigned long timeout, read_time, i = 0; + int status; + + mutex_lock(&drvdata->update_lock); + + if (i2c_smbus_write_byte_data(client, off>>8, off)) + { + status = -EIO; + goto exit; + } + + msleep(1); + +begin: + + if (i < count) + { + timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/ + do { + read_time = jiffies; + + status = i2c_smbus_read_byte(client); + if (status >= 0) + { + buf[i++] = status; + goto begin; + } + } while (time_before(read_time, timeout)); + + status = -ETIMEDOUT; + goto exit; + } + + status = count; + +exit: + mutex_unlock(&drvdata->update_lock); + + return status; +} + +static struct bin_attribute mc24lc64t_bit_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = 65536, + .read = mc24lc64t_read, +}; + +static int mc24lc64t_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + struct mc24lc64t_data *drvdata; + int err; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA + | I2C_FUNC_SMBUS_READ_BYTE)) + return -EPFNOSUPPORT; + + if (!(drvdata = devm_kzalloc(&client->dev, + sizeof(struct mc24lc64t_data), GFP_KERNEL))) + return -ENOMEM; + + drvdata->fake_client = i2c_new_dummy(client->adapter, client->addr + 1); + if (!drvdata->fake_client) + return -ENOMEM; + + i2c_set_clientdata(client, drvdata); + mutex_init(&drvdata->update_lock); + + err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); + if (err) + i2c_unregister_device(drvdata->fake_client); + + return err; +} + +static int mc24lc64t_remove(struct i2c_client *client) +{ + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + + i2c_unregister_device(drvdata->fake_client); + + sysfs_remove_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); + + return 0; +} + +static const struct i2c_device_id mc24lc64t_id[] = { + { "24lc64t", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mc24lc64t_id); + +static struct i2c_driver mc24lc64t_driver = { + .driver = { + .name = "mc24lc64t", + .owner = THIS_MODULE, + }, + .probe = mc24lc64t_probe, + .remove = mc24lc64t_remove, + .id_table = mc24lc64t_id, +}; + +module_i2c_driver(mc24lc64t_driver); + +MODULE_AUTHOR("Abhisit Sangjan "); +MODULE_DESCRIPTION("Microchip 24LC64T Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/dx010_check_qsfp.sh b/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/dx010_check_qsfp.sh new file mode 100644 index 000000000000..938b07952e0d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/dx010_check_qsfp.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +#Usage: +# TBD + +echo "Do we need to check qsfp?" + diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/systemd/platform-modules-dx010.service b/platform/broadcom/sonic-platform-modules-cel/dx010/systemd/platform-modules-dx010.service new file mode 100644 index 000000000000..32827dcf0dec --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/systemd/platform-modules-dx010.service @@ -0,0 +1,14 @@ + +[Unit] +Description=Celestica Seastone dx010 platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-dx010 start +ExecStop=-/etc/init.d/platform-modules-dx010 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/cfg/haliburton-modules.conf b/platform/broadcom/sonic-platform-modules-cel/haliburton/cfg/haliburton-modules.conf new file mode 100644 index 000000000000..66f002a5fc94 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/cfg/haliburton-modules.conf @@ -0,0 +1,15 @@ +# /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. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-gpio +i2c-mux-pca954x + diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/Makefile new file mode 100644 index 000000000000..58e2b0bf2d7a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/Makefile @@ -0,0 +1 @@ +obj-m := mc24lc64t.o emc2305.o smc.o diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/emc2305.c b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/emc2305.c new file mode 100644 index 000000000000..f08033e080ce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/emc2305.c @@ -0,0 +1,877 @@ +/* + * emc2305.c - hwmon driver for SMSC EMC2305 fan controller + * (C) Copyright 2013 + * Reinhard Pfau, Guntermann & Drunck GmbH + * + * Based on emc2103 driver by SMSC. + * + * Datasheet available at: + * http://www.smsc.com/Downloads/SMSC/Downloads_Public/Data_Sheets/2305.pdf + * + * Also supports the EMC2303 fan controller which has the same functionality + * and register layout as EMC2305, but supports only up to 3 fans instead of 5. + * + * Also supports EMC2302 (up to 2 fans) and EMC2301 (1 fan) fan controller. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * TODO / IDEAS: + * - expose more of the configuration and features + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Addresses scanned. + * Listed in the same order as they appear in the EMC2305, EMC2303 data sheets. + * + * Note: these are the I2C adresses which are possible for EMC2305 and EMC2303 + * chips. + * The EMC2302 supports only 0x2e (EMC2302-1) and 0x2f (EMC2302-2). + * The EMC2301 supports only 0x2f. + */ +static const unsigned short i2c_adresses[] = { + 0x2E, + 0x2F, + 0x2C, + 0x2D, + 0x4C, + 0x4D, + I2C_CLIENT_END +}; + +/* + * global registers + */ +enum { + REG_CONFIGURATION = 0x20, + REG_FAN_STATUS = 0x24, + REG_FAN_STALL_STATUS = 0x25, + REG_FAN_SPIN_STATUS = 0x26, + REG_DRIVE_FAIL_STATUS = 0x27, + REG_FAN_INTERRUPT_ENABLE = 0x29, + REG_PWM_POLARITY_CONFIG = 0x2a, + REG_PWM_OUTPUT_CONFIG = 0x2b, + REG_PWM_BASE_FREQ_1 = 0x2c, + REG_PWM_BASE_FREQ_2 = 0x2d, + REG_SOFTWARE_LOCK = 0xef, + REG_PRODUCT_FEATURES = 0xfc, + REG_PRODUCT_ID = 0xfd, + REG_MANUFACTURER_ID = 0xfe, + REG_REVISION = 0xff +}; + +/* + * fan specific registers + */ +enum { + REG_FAN_SETTING = 0x30, + REG_PWM_DIVIDE = 0x31, + REG_FAN_CONFIGURATION_1 = 0x32, + REG_FAN_CONFIGURATION_2 = 0x33, + REG_GAIN = 0x35, + REG_FAN_SPIN_UP_CONFIG = 0x36, + REG_FAN_MAX_STEP = 0x37, + REG_FAN_MINIMUM_DRIVE = 0x38, + REG_FAN_VALID_TACH_COUNT = 0x39, + REG_FAN_DRIVE_FAIL_BAND_LOW = 0x3a, + REG_FAN_DRIVE_FAIL_BAND_HIGH = 0x3b, + REG_TACH_TARGET_LOW = 0x3c, + REG_TACH_TARGET_HIGH = 0x3d, + REG_TACH_READ_HIGH = 0x3e, + REG_TACH_READ_LOW = 0x3f, +}; + +#define SEL_FAN(fan, reg) (reg + fan * 0x10) + +/* + * Factor by equations [2] and [3] from data sheet; valid for fans where the + * number of edges equals (poles * 2 + 1). + */ +#define FAN_RPM_FACTOR 3932160 + + +struct emc2305_fan_data { + bool enabled; + bool valid; + unsigned long last_updated; + bool rpm_control; + u8 multiplier; + u8 poles; + u16 target; + u16 tach; + u16 rpm_factor; + u8 pwm; +}; + +struct emc2305_data { + struct device *hwmon_dev; + struct mutex update_lock; + int fans; + struct emc2305_fan_data fan[5]; +}; + +static int read_u8_from_i2c(struct i2c_client *client, u8 i2c_reg, u8 *output) +{ + int status = i2c_smbus_read_byte_data(client, i2c_reg); + if (status < 0) { + dev_warn(&client->dev, "reg 0x%02x, err %d\n", + i2c_reg, status); + } else { + *output = status; + } + return status; +} + +static void read_fan_from_i2c(struct i2c_client *client, u16 *output, + u8 hi_addr, u8 lo_addr) +{ + u8 high_byte, lo_byte; + + if (read_u8_from_i2c(client, hi_addr, &high_byte) < 0) + return; + + if (read_u8_from_i2c(client, lo_addr, &lo_byte) < 0) + return; + + *output = ((u16)high_byte << 5) | (lo_byte >> 3); +} + +static void write_fan_target_to_i2c(struct i2c_client *client, int fan, + u16 new_target) +{ + const u8 lo_reg = SEL_FAN(fan, REG_TACH_TARGET_LOW); + const u8 hi_reg = SEL_FAN(fan, REG_TACH_TARGET_HIGH); + u8 high_byte = (new_target & 0x1fe0) >> 5; + u8 low_byte = (new_target & 0x001f) << 3; + i2c_smbus_write_byte_data(client, lo_reg, low_byte); + i2c_smbus_write_byte_data(client, hi_reg, high_byte); +} + +static void read_fan_config_from_i2c(struct i2c_client *client, int fan) + +{ + struct emc2305_data *data = i2c_get_clientdata(client); + u8 conf1; + + if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_CONFIGURATION_1), + &conf1) < 0) + return; + + data->fan[fan].rpm_control = (conf1 & 0x80) != 0; + data->fan[fan].multiplier = 1 << ((conf1 & 0x60) >> 5); + data->fan[fan].poles = ((conf1 & 0x18) >> 3) + 1; +} + +static void read_fan_setting(struct i2c_client *client, int fan) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + u8 setting; + + if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_SETTING), + &setting) < 0) + return; + + data->fan[fan].pwm = setting; +} + +static void read_fan_data(struct i2c_client *client, int fan_idx) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + + read_fan_from_i2c(client, &data->fan[fan_idx].target, + SEL_FAN(fan_idx, REG_TACH_TARGET_HIGH), + SEL_FAN(fan_idx, REG_TACH_TARGET_LOW)); + read_fan_from_i2c(client, &data->fan[fan_idx].tach, + SEL_FAN(fan_idx, REG_TACH_READ_HIGH), + SEL_FAN(fan_idx, REG_TACH_READ_LOW)); +} + +static struct emc2305_fan_data * +emc2305_update_fan(struct i2c_client *client, int fan_idx) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan_data = &data->fan[fan_idx]; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) + || !fan_data->valid) { + read_fan_config_from_i2c(client, fan_idx); + read_fan_data(client, fan_idx); + read_fan_setting(client, fan_idx); + fan_data->valid = true; + fan_data->last_updated = jiffies; + } + + mutex_unlock(&data->update_lock); + return fan_data; +} + +static struct emc2305_fan_data * +emc2305_update_device_fan(struct device *dev, struct device_attribute *da) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + + return emc2305_update_fan(client, fan_idx); +} + +/* + * set/ config functions + */ + +/* + * Note: we also update the fan target here, because its value is + * determined in part by the fan clock divider. This follows the principle + * of least surprise; the user doesn't expect the fan target to change just + * because the divider changed. + */ +static int +emc2305_set_fan_div(struct i2c_client *client, int fan_idx, long new_div) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); + int new_range_bits, old_div = 8 / fan->multiplier; + int status = 0; + + if (new_div == old_div) /* No change */ + return 0; + + switch (new_div) { + case 1: + new_range_bits = 3; + break; + case 2: + new_range_bits = 2; + break; + case 4: + new_range_bits = 1; + break; + case 8: + new_range_bits = 0; + break; + default: + return -EINVAL; + } + + mutex_lock(&data->update_lock); + + status = i2c_smbus_read_byte_data(client, reg_conf1); + if (status < 0) { + dev_dbg(&client->dev, "reg 0x%02x, err %d\n", + reg_conf1, status); + status = -EIO; + goto exit_unlock; + } + status &= 0x9F; + status |= (new_range_bits << 5); + status = i2c_smbus_write_byte_data(client, reg_conf1, status); + if (status < 0) { + status = -EIO; + goto exit_invalidate; + } + + fan->multiplier = 8 / new_div; + + /* update fan target if high byte is not disabled */ + if ((fan->target & 0x1fe0) != 0x1fe0) { + u16 new_target = (fan->target * old_div) / new_div; + fan->target = min_t(u16, new_target, 0x1fff); + write_fan_target_to_i2c(client, fan_idx, fan->target); + } + +exit_invalidate: + /* invalidate fan data to force re-read from hardware */ + fan->valid = false; +exit_unlock: + mutex_unlock(&data->update_lock); + return status; +} + +static int +emc2305_set_fan_target(struct i2c_client *client, int fan_idx, long rpm_target) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + + /* + * Datasheet states 16000 as maximum RPM target + * (table 2.2 and section 4.3) + */ + if ((rpm_target < 0) || (rpm_target > 16000)) + return -EINVAL; + + mutex_lock(&data->update_lock); + + if (rpm_target == 0) + fan->target = 0x1fff; + else + fan->target = clamp_val( + (FAN_RPM_FACTOR * fan->multiplier) / rpm_target, + 0, 0x1fff); + + write_fan_target_to_i2c(client, fan_idx, fan->target); + + mutex_unlock(&data->update_lock); + return 0; +} + +static int +emc2305_set_pwm_enable(struct i2c_client *client, int fan_idx, long enable) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_fan_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); + int status = 0; + u8 conf_reg; + + mutex_lock(&data->update_lock); + switch (enable) { + case 0: + fan->rpm_control = false; + break; + case 3: + fan->rpm_control = true; + break; + default: + status = -EINVAL; + goto exit_unlock; + } + + status = read_u8_from_i2c(client, reg_fan_conf1, &conf_reg); + if (status < 0) { + status = -EIO; + goto exit_unlock; + } + + if (fan->rpm_control) + conf_reg |= 0x80; + else + conf_reg &= ~0x80; + + status = i2c_smbus_write_byte_data(client, reg_fan_conf1, conf_reg); + if (status < 0) + status = -EIO; + +exit_unlock: + mutex_unlock(&data->update_lock); + return status; +} + +static int +emc2305_set_pwm(struct i2c_client *client, int fan_idx, long pwm) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_fan_setting = SEL_FAN(fan_idx, REG_FAN_SETTING); + int status = 0; + + /* + * Datasheet states 255 as maximum PWM + * (section 5.7) + */ + if ((pwm < 0) || (pwm > 255)) + return -EINVAL; + + fan->pwm = pwm; + + mutex_lock(&data->update_lock); + + status = i2c_smbus_write_byte_data(client, reg_fan_setting, fan->pwm); + + mutex_unlock(&data->update_lock); + return status; +} +/* + * sysfs callback functions + * + * Note: + * Naming of the funcs is modelled after the naming scheme described in + * Documentation/hwmon/sysfs-interface: + * + * For a sysfs file _ the functions are named like this: + * the show function: show__ + * the store function: set__ + * For read only (RO) attributes of course only the show func is required. + * + * This convention allows us to define the sysfs attributes by using macros. + */ + +static ssize_t +show_fan_input(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int rpm = 0; + if (fan->tach != 0) + rpm = (FAN_RPM_FACTOR * fan->multiplier) / fan->tach; + return sprintf(buf, "%d\n", rpm); +} + +static ssize_t +show_fan_fault(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + bool fault = ((fan->tach & 0x1fe0) == 0x1fe0); + return sprintf(buf, "%d\n", fault ? 1 : 0); +} + +static ssize_t +show_fan_div(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int fan_div = 8 / fan->multiplier; + return sprintf(buf, "%d\n", fan_div); +} + +static ssize_t +set_fan_div(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long new_div; + int status; + + status = kstrtol(buf, 10, &new_div); + if (status < 0) + return -EINVAL; + + status = emc2305_set_fan_div(client, fan_idx, new_div); + if (status < 0) + return status; + + return count; +} + +static ssize_t +show_fan_target(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int rpm = 0; + + /* high byte of 0xff indicates disabled so return 0 */ + if ((fan->target != 0) && ((fan->target & 0x1fe0) != 0x1fe0)) + rpm = (FAN_RPM_FACTOR * fan->multiplier) + / fan->target; + + return sprintf(buf, "%d\n", rpm); +} + +static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long rpm_target; + int status; + + status = kstrtol(buf, 10, &rpm_target); + if (status < 0) + return -EINVAL; + + status = emc2305_set_fan_target(client, fan_idx, rpm_target); + if (status < 0) + return status; + + return count; +} + +static ssize_t +show_pwm_enable(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + return sprintf(buf, "%d\n", fan->rpm_control ? 3 : 0); +} + +static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long new_value; + int status; + + status = kstrtol(buf, 10, &new_value); + if (status < 0) + return -EINVAL; + status = emc2305_set_pwm_enable(client, fan_idx, new_value); + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + return sprintf(buf, "%d\n", fan->pwm); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + unsigned long val; + int ret; + int status; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + if (val > 255) + return -EINVAL; + + status = emc2305_set_pwm(client, fan_idx, val); + return count; +} + +/* define a read only attribute */ +#define EMC2305_ATTR_RO(_type, _item, _num) \ + SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO, \ + show_## _type ## _ ## _item, NULL, _num - 1) + +/* define a read/write attribute */ +#define EMC2305_ATTR_RW(_type, _item, _num) \ + SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO | S_IWUSR, \ + show_## _type ##_ ## _item, \ + set_## _type ## _ ## _item, _num - 1) + +/* + * TODO: Ugly hack, but temporary as this whole logic needs + * to be rewritten as per standard HWMON sysfs registration + */ + +/* define a read/write attribute */ +#define EMC2305_ATTR_RW2(_type, _num) \ + SENSOR_ATTR(_type ## _num, S_IRUGO | S_IWUSR, \ + show_## _type, set_## _type, _num - 1) + +/* defines the attributes for a single fan */ +#define EMC2305_DEFINE_FAN_ATTRS(_num) \ + static const \ + struct sensor_device_attribute emc2305_attr_fan ## _num[] = { \ + EMC2305_ATTR_RO(fan, input, _num), \ + EMC2305_ATTR_RO(fan, fault, _num), \ + EMC2305_ATTR_RW(fan, div, _num), \ + EMC2305_ATTR_RW(fan, target, _num), \ + EMC2305_ATTR_RW(pwm, enable, _num), \ + EMC2305_ATTR_RW2(pwm, _num) \ + } + +#define EMC2305_NUM_FAN_ATTRS ARRAY_SIZE(emc2305_attr_fan1) + +/* common attributes for EMC2303 and EMC2305 */ +static const struct sensor_device_attribute emc2305_attr_common[] = { +}; + +/* fan attributes for the single fans */ +EMC2305_DEFINE_FAN_ATTRS(1); +EMC2305_DEFINE_FAN_ATTRS(2); +EMC2305_DEFINE_FAN_ATTRS(3); +EMC2305_DEFINE_FAN_ATTRS(4); +EMC2305_DEFINE_FAN_ATTRS(5); +EMC2305_DEFINE_FAN_ATTRS(6); + +/* fan attributes */ +static const struct sensor_device_attribute *emc2305_fan_attrs[] = { + emc2305_attr_fan1, + emc2305_attr_fan2, + emc2305_attr_fan3, + emc2305_attr_fan4, + emc2305_attr_fan5, +}; + +/* + * driver interface + */ + +static int emc2305_remove(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + int fan_idx, i; + + hwmon_device_unregister(data->hwmon_dev); + + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) + device_remove_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) + device_remove_file(&client->dev, + &emc2305_attr_common[i].dev_attr); + + kfree(data); + return 0; +} + + +#ifdef CONFIG_OF +/* + * device tree support + */ + +struct of_fan_attribute { + const char *name; + int (*set)(struct i2c_client*, int, long); +}; + +struct of_fan_attribute of_fan_attributes[] = { + {"fan-div", emc2305_set_fan_div}, + {"fan-target", emc2305_set_fan_target}, + {"pwm-enable", emc2305_set_pwm_enable}, + {NULL, NULL} +}; + +static int emc2305_config_of(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct device_node *node; + unsigned int fan_idx; + + if (!client->dev.of_node) + return -EINVAL; + if (!of_get_next_child(client->dev.of_node, NULL)) + return 0; + + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + data->fan[fan_idx].enabled = false; + + for_each_child_of_node(client->dev.of_node, node) { + const __be32 *property; + int len; + struct of_fan_attribute *attr; + + property = of_get_property(node, "reg", &len); + if (!property || len != sizeof(int)) { + dev_err(&client->dev, "invalid reg on %s\n", + node->full_name); + continue; + } + + fan_idx = be32_to_cpup(property); + if (fan_idx >= data->fans) { + dev_err(&client->dev, + "invalid fan index %d on %s\n", + fan_idx, node->full_name); + continue; + } + + data->fan[fan_idx].enabled = true; + + for (attr = of_fan_attributes; attr->name; ++attr) { + int status = 0; + long value; + property = of_get_property(node, attr->name, &len); + if (!property) + continue; + if (len != sizeof(int)) { + dev_err(&client->dev, "invalid %s on %s\n", + attr->name, node->full_name); + continue; + } + value = be32_to_cpup(property); + status = attr->set(client, fan_idx, value); + if (status == -EINVAL) { + dev_err(&client->dev, + "invalid value for %s on %s\n", + attr->name, node->full_name); + } + } + } + + return 0; +} + +#endif + +static void emc2305_get_config(struct i2c_client *client) +{ + int i; + struct emc2305_data *data = i2c_get_clientdata(client); + + for (i = 0; i < data->fans; ++i) { + data->fan[i].enabled = true; + emc2305_update_fan(client, i); + } + +#ifdef CONFIG_OF + emc2305_config_of(client); +#endif + +} + +static int +emc2305_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct emc2305_data *data; + int status; + int i; + int fan_idx; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct emc2305_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + status = i2c_smbus_read_byte_data(client, REG_PRODUCT_ID); + switch (status) { + case 0x34: /* EMC2305 */ + data->fans = 5; + break; + case 0x35: /* EMC2303 */ + data->fans = 3; + break; + case 0x36: /* EMC2302 */ + data->fans = 2; + break; + case 0x37: /* EMC2301 */ + data->fans = 1; + break; + default: + if (status >= 0) + status = -EINVAL; + goto exit_free; + } + + emc2305_get_config(client); + + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) { + status = device_create_file(&client->dev, + &emc2305_attr_common[i].dev_attr); + if (status) + goto exit_remove; + } + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) { + if (!data->fan[fan_idx].enabled) + continue; + status = device_create_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + if (status) + goto exit_remove_fans; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove_fans; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove_fans: + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) + device_remove_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + +exit_remove: + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) + device_remove_file(&client->dev, + &emc2305_attr_common[i].dev_attr); +exit_free: + kfree(data); + return status; +} + +static const struct i2c_device_id emc2305_id[] = { + { "emc2305", 0 }, + { "emc2303", 0 }, + { "emc2302", 0 }, + { "emc2301", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, emc2305_id); + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int +emc2305_detect(struct i2c_client *new_client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + int manufacturer, product; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + manufacturer = + i2c_smbus_read_byte_data(new_client, REG_MANUFACTURER_ID); + if (manufacturer != 0x5D) + return -ENODEV; + + product = i2c_smbus_read_byte_data(new_client, REG_PRODUCT_ID); + + switch (product) { + case 0x34: + strlcpy(info->type, "emc2305", I2C_NAME_SIZE); + break; + case 0x35: + strlcpy(info->type, "emc2303", I2C_NAME_SIZE); + break; + case 0x36: + strlcpy(info->type, "emc2302", I2C_NAME_SIZE); + break; + case 0x37: + strlcpy(info->type, "emc2301", I2C_NAME_SIZE); + break; + default: + return -ENODEV; + } + + return 0; +} + +static struct i2c_driver emc2305_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc2305", + }, + .probe = emc2305_probe, + .remove = emc2305_remove, + .id_table = emc2305_id, +/* + .detect = emc2305_detect, + .address_list = i2c_adresses, +*/ +}; + +module_i2c_driver(emc2305_driver); + +MODULE_AUTHOR("Reinhard Pfau "); +MODULE_DESCRIPTION("SMSC EMC2305 hwmon driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/mc24lc64t.c new file mode 100644 index 000000000000..a391056d09a7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/mc24lc64t.c @@ -0,0 +1,142 @@ +/* + * mc24lc64t.c - driver for Microchip 24LC64T + * + * Copyright (C) 2017 Celestica Corp. + * + * 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 + +struct mc24lc64t_data { + struct i2c_client *fake_client; + struct mutex update_lock; +}; + +static ssize_t mc24lc64t_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = kobj_to_i2c_client(kobj); + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + unsigned long timeout, read_time, i = 0; + int status; + + mutex_lock(&drvdata->update_lock); + + if (i2c_smbus_write_byte_data(client, off>>8, off)) + { + status = -EIO; + goto exit; + } + + msleep(1); + +begin: + + if (i < count) + { + timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/ + do { + read_time = jiffies; + + status = i2c_smbus_read_byte(client); + if (status >= 0) + { + buf[i++] = status; + goto begin; + } + } while (time_before(read_time, timeout)); + + status = -ETIMEDOUT; + goto exit; + } + + status = count; + +exit: + mutex_unlock(&drvdata->update_lock); + + return status; +} + +static struct bin_attribute mc24lc64t_bit_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = 65536, + .read = mc24lc64t_read, +}; + +static int mc24lc64t_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + struct mc24lc64t_data *drvdata; + int err; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA + | I2C_FUNC_SMBUS_READ_BYTE)) + return -EPFNOSUPPORT; + + if (!(drvdata = devm_kzalloc(&client->dev, + sizeof(struct mc24lc64t_data), GFP_KERNEL))) + return -ENOMEM; + + drvdata->fake_client = i2c_new_dummy(client->adapter, client->addr + 1); + if (!drvdata->fake_client) + return -ENOMEM; + + i2c_set_clientdata(client, drvdata); + mutex_init(&drvdata->update_lock); + + err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); + if (err) + i2c_unregister_device(drvdata->fake_client); + + return err; +} + +static int mc24lc64t_remove(struct i2c_client *client) +{ + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + + i2c_unregister_device(drvdata->fake_client); + + sysfs_remove_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); + + return 0; +} + +static const struct i2c_device_id mc24lc64t_id[] = { + { "24lc64t", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mc24lc64t_id); + +static struct i2c_driver mc24lc64t_driver = { + .driver = { + .name = "mc24lc64t", + .owner = THIS_MODULE, + }, + .probe = mc24lc64t_probe, + .remove = mc24lc64t_remove, + .id_table = mc24lc64t_id, +}; + +module_i2c_driver(mc24lc64t_driver); + +MODULE_AUTHOR("Abhisit Sangjan "); +MODULE_DESCRIPTION("Microchip 24LC64T Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/smc.c b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/smc.c new file mode 100644 index 000000000000..7b8d410cdd2b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/smc.c @@ -0,0 +1,1039 @@ +/* + * smc.c - The CPLD driver for E1031 System Management. + * The driver implement sysfs to access CPLD register on the E1031 via LPC bus. + * Copyright (C) 2018 Celestica Corp. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + + +#define DRIVER_NAME "e1031.smc" + +/** + * CPLD register address for read and write. + */ +#define VERSION 0x0200 +#define SCRATCH 0x0201 +#define BROAD_ID 0x0202 + +/* SEPERATE RESET + * [7:5] RESERVED + * [4] RESET PCIE + * [3] RESET USBHUB + * [2] RESET B50282 + * [1] RESET PCA9548 + * [0] RESET BCM54616 + * 1: not reset, 0: reset + */ +#define SPR_RESET 0x0222 + +/* PSU STATUS + * [7] PSUR_ACOK + * [6] PSUR_PWOK + * [5] PSUR_ALRT + * [4] PSUR_PRS + * [3] PSUL_ACOK + * [2] PSUL_PWOK + * [1] PSUL_ALRT + * [0] PSUL_PRS + */ +#define PSU_STAT 0x0204 +#define PSUR_ACOK 7 +#define PSUR_PWOK 6 +#define PSUR_ALRT 5 +#define PSUR_PRS 4 +#define PSUL_ACOK 3 +#define PSUL_PWOK 2 +#define PSUL_ALRT 1 +#define PSUL_PRS 0 + +/* FAN LED CTRL + * [7:3] RESERVED + * [2:0] LED CTRL + */ +#define FAN_LED_1 0x0205 +#define FAN_LED_2 0x0206 +#define FAN_LED_3 0x0207 + +enum FAN_LED { + fan_led_grn = 0, + fan_led_grn_bnk, + fan_led_amb, + fan_led_amb_bnk, + fan_led_off +} fan_led; + +#define LED_OPMOD 0x0208 +#define LED_TEST 0x0209 + +/* SYSTEM LED + * [7:4] RESERVED + * [3:2] STATUS LED + * [1:0] MASTER LED + */ +#define LED_FPS 0x020a + +enum STAT_LED { + stat_led_off = 0, + stat_led_grn, + stat_led_grn_bnk +} stat_led; + +enum MASTER_LED { + master_led_off = 0, + master_led_grn, + master_led_amb +} master_led; + +/* FAN DIRECTION STAT + * [7:4] RESERVED + * [3] USB HUB STAT + * [2:0] FAN_DIR + */ +#define DEV_STAT 0x020c +#define FAN_3 2 +#define FAN_2 1 +#define FAN_1 0 + +/* SFP PORT INT TRIGGER MODE + * [7:6] RESERVED + * [5:4] RXLOS + * [3:2] MODABS + * [1:0] TXFAULT + * 00: falling edge, + * 01: rising edge, + * 10: Both edges, + * 11: low level detect + */ +#define TRIG_MODE 0x0240 +#define TXFAULT_TRIG 0 +#define MODABS_TRIG 2 +#define RXLOS_TRIG 4 + + +/* SFP PORT STATUS + * [7:4] RESERVED + * [3:0] TX_FAULT / MODABS / RXLOS + */ +#define SFP_TXFAULT 0x0242 +#define SFP_MODABS 0x0243 +#define SFP_RXLOS 0x0244 + +/* SFP PORT INTERRUPT + * [7:4] RESERVED + * [3:0] TX_FAULT / MODABS / RXLOS + * 1: int, 0: no int + */ +#define TXFAULT_INT 0x0246 +#define MODABS_INT 0x0247 +#define RXLOS_INT 0x0248 + +/* INTERRUPT MASK REGISTER + * [7:4] RESERVED + * [3:0] TX_FAULT / MODABS / RXLOS + * 1: mask, 0: not mask + */ +#define TXFAULT_MSK 0x024A +#define MODABS_MSK 0x024B +#define RXLOS_MSK 0x024C + +/* SFP PORT CTRL + * [7:4] RATE SEL (RS0/RS1) + * [3:0] TX_DIS + */ +#define SFP_TXCTRL 0x0255 + +struct cpld_data { + struct mutex cpld_lock; + uint16_t read_addr; + struct device *fpp_node; + struct device *sfp_devices[4]; +}; + +struct sfp_device_data { + int portid; +}; + +struct class *celplatform; +struct cpld_data *cpld_data; + +struct index_device_attribute { + struct device_attribute dev_attr; + int index; +}; + +static ssize_t scratch_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SCRATCH); + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%2.2x\n", data); +} + +static ssize_t scratch_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long data; + char *last; + + mutex_lock(&cpld_data->cpld_lock); + data = (uint16_t)strtoul(buf, &last, 16); + if (data == 0 && buf == last) { + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + outb(data, SCRATCH); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + + +static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int len = 0; + mutex_lock(&cpld_data->cpld_lock); + len = sprintf(buf, "0x%2.2x\n", inb(VERSION)); + mutex_unlock(&cpld_data->cpld_lock); + return len; +} + +static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + uint16_t addr; + char *last; + + addr = (uint16_t)strtoul(buf, &last, 16); + if (addr == 0 && buf == last) { + return -EINVAL; + } + cpld_data->read_addr = addr; + return count; +} + +static ssize_t getreg_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int len = 0; + mutex_lock(&cpld_data->cpld_lock); + len = sprintf(buf, "0x%2.2x\n", inb(cpld_data->read_addr)); + mutex_unlock(&cpld_data->cpld_lock); + return len; +} + +static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + uint16_t addr; + uint8_t value; + char *tok; + char clone[count]; + char *pclone = clone; + char *last; + + strcpy(clone, buf); + + mutex_lock(&cpld_data->cpld_lock); + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + addr = (uint16_t)strtoul(tok, &last, 16); + if (addr == 0 && tok == last) { + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + value = (uint8_t)strtoul(tok, &last, 16); + if (value == 0 && tok == last) { + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + + outb(value, addr); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + +/** + * @brief Show status led + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return led state - off/on/blink + */ +static ssize_t status_led_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(LED_FPS); + mutex_unlock(&cpld_data->cpld_lock); + data = data & 0xc; + return sprintf(buf, "%s\n", + data == stat_led_grn ? "on" : data == stat_led_grn_bnk ? "blink" : "off"); +} + +/** + * @brief Set the status led + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value - off/on/blink + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t status_led_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char led_status, data; + + if (sysfs_streq(buf, "off")) { + led_status = stat_led_off; + } else if (sysfs_streq(buf, "on")) { + led_status = stat_led_grn; + } else if (sysfs_streq(buf, "blink")) { + led_status = stat_led_grn_bnk; + } else { + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + data = inb(LED_FPS); + data = data & ~(0xc); + data = data | ( led_status << 2 ); + outb(data, LED_FPS); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + +/** + * @brief Show master led + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return led state - off/green/amber + */ +static ssize_t master_led_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(LED_FPS); + mutex_unlock(&cpld_data->cpld_lock); + data = data & 0x3; + return sprintf(buf, "%s\n", + data == master_led_grn ? "on" : data == master_led_amb ? "amber" : "off"); +} + +/** + * @brief Set the master led + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value - off/green/amber + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t master_led_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char led_status, data; + + if (sysfs_streq(buf, "off")) { + led_status = master_led_off; + } else if (sysfs_streq(buf, "green")) { + led_status = master_led_grn; + } else if (sysfs_streq(buf, "amber")) { + led_status = master_led_amb; + } else { + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + data = inb(LED_FPS); + data = data & ~(0x3); + data = data | led_status; + outb(data, LED_FPS); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + +static ssize_t psuL_prs_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(PSU_STAT); + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%d\n", ~(data >> PSUL_PRS) & 1U); +} + +static ssize_t psuR_prs_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(PSU_STAT); + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%d\n", ~(data >> PSUR_PRS) & 1U); +} +static DEVICE_ATTR_RO(psuR_prs); + +static ssize_t psuL_status_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(PSU_STAT); + mutex_unlock(&cpld_data->cpld_lock); + data = ( data >> PSUL_PWOK ) & 0x3; + return sprintf(buf, "%d\n", data == 0x3 ); +} + +static ssize_t psuR_status_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(PSU_STAT); + mutex_unlock(&cpld_data->cpld_lock); + data = ( data >> PSUR_PWOK ) & 0x3; + return sprintf(buf, "%d\n", data == 0x3 ); +} + + +static ssize_t fan_dir_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr); + int index = sa->index; + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(DEV_STAT); + mutex_unlock(&cpld_data->cpld_lock); + data = ( data >> index ) & 1U; + return sprintf(buf, "%s\n", data ? "B2F" : "F2B" ); +} + +static ssize_t sfp_txfault_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SFP_TXFAULT); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t sfp_modabs_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SFP_MODABS); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t sfp_rxlos_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SFP_RXLOS); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t sfp_txdis_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SFP_TXCTRL); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t sfp_txdis_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + long value; + ssize_t status; + unsigned char data; + + mutex_lock(&cpld_data->cpld_lock); + status = kstrtol(buf, 0, &value); + if (status == 0) { + data = inb(SFP_TXCTRL); + data = data & ~(0x0F); + data = data | (value & 0x0F); + outb(data, SFP_TXCTRL); + status = size; + } + mutex_unlock(&cpld_data->cpld_lock); + return status; +} + +static ssize_t sfp_rs_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SFP_TXCTRL) >> 4; + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t sfp_rs_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + long value; + ssize_t status; + unsigned char data; + + mutex_lock(&cpld_data->cpld_lock); + status = kstrtol(buf, 0, &value); + value = (value & 0x0F) << 4; + if (status == 0) { + data = inb(SFP_TXCTRL); + data = data & ~(0xF0); + data = data | value; + outb(data, SFP_TXCTRL); + status = size; + } + mutex_unlock(&cpld_data->cpld_lock); + return status; +} + +/** + * @brief Show the avaliable interrupt trigger mode. + * "none" means the interrupt is masked. + * + * @return Current trigger mode. + */ +static ssize_t txfault_trig_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char mode; + char *mode_str[5] = {"falling", "rising", "both", "low"}; + + mutex_lock(&cpld_data->cpld_lock); + mode = inb(TRIG_MODE) >> TXFAULT_TRIG; + mode = mode & 0x3; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%s\n", mode_str[mode]); +} + +/** + * @brief Set the trigger mode of each interrupt type. + * Only one trigger mode allow in a type. + * + * @param buf The trigger mode of follwings + * "falling", "rising", "both" + */ +static ssize_t txfault_trig_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + ssize_t status; + unsigned char data, trig_mode; + + if (sysfs_streq(buf, "falling")) { + trig_mode = 0; + } else if (sysfs_streq(buf, "rising")) { + trig_mode = 1; + } else if (sysfs_streq(buf, "both")) { + trig_mode = 2; + } else if (sysfs_streq(buf, "low")) { + trig_mode = 3; + } else { + status = -EINVAL; + return status; + } + + mutex_lock(&cpld_data->cpld_lock); + data = inb(TRIG_MODE); + data = data & ~(0x03 << TXFAULT_TRIG); + data = data | trig_mode << TXFAULT_TRIG; + outb(data, TRIG_MODE); + mutex_unlock(&cpld_data->cpld_lock); + status = size; + return status; +} + +/** + * @brief Show the avaliable interrupt trigger mode. + * "none" means the interrupt is masked. + * + * @return Current trigger mode. + */ +static ssize_t modabs_trig_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char mode; + char *mode_str[5] = {"falling", "rising", "both", "low"}; + + mutex_lock(&cpld_data->cpld_lock); + mode = inb(TRIG_MODE) >> MODABS_TRIG; + mode = mode & 0x3; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%s\n", mode_str[mode]); +} + +/** + * @brief Set the trigger mode of each interrupt type. + * Only one trigger mode allow in a type. + * + * @param buf The trigger mode of follwings + * "falling", "rising", "both", "low" + */ +static ssize_t modabs_trig_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + ssize_t status; + unsigned char data, trig_mode; + + if (sysfs_streq(buf, "falling")) { + trig_mode = 0; + } else if (sysfs_streq(buf, "rising")) { + trig_mode = 1; + } else if (sysfs_streq(buf, "both")) { + trig_mode = 2; + } else if (sysfs_streq(buf, "low")) { + trig_mode = 3; + } else { + status = -EINVAL; + return status; + } + + mutex_lock(&cpld_data->cpld_lock); + data = inb(TRIG_MODE); + data = data & ~(0x03 << MODABS_TRIG); + data = data | trig_mode << MODABS_TRIG; + outb(data, TRIG_MODE); + mutex_unlock(&cpld_data->cpld_lock); + status = size; + return status; +} + +/** + * @brief Show the avaliable interrupt trigger mode. + * "none" means the interrupt is masked. + * + * @return Current trigger mode. + */ +static ssize_t rxlos_trig_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char mode; + char *mode_str[5] = {"falling", "rising", "both", "low"}; + + mutex_lock(&cpld_data->cpld_lock); + mode = inb(TRIG_MODE) >> RXLOS_TRIG; + mode = mode & 0x3; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%s\n", mode_str[mode]); +} + +/** + * @brief Set the trigger mode of each interrupt type. + * Only one trigger mode allow in a type. + * + * @param buf The trigger mode of follwings + * "falling", "rising", "both", "low" + */ +static ssize_t rxlos_trig_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + ssize_t status; + unsigned char data, trig_mode; + + if (sysfs_streq(buf, "falling")) { + trig_mode = 0; + } else if (sysfs_streq(buf, "rising")) { + trig_mode = 1; + } else if (sysfs_streq(buf, "both")) { + trig_mode = 2; + } else if (sysfs_streq(buf, "low")) { + trig_mode = 3; + } else { + status = -EINVAL; + return status; + } + + mutex_lock(&cpld_data->cpld_lock); + data = inb(TRIG_MODE); + data = data & ~(0x03 << RXLOS_TRIG); + data = data | trig_mode << RXLOS_TRIG; + outb(data, TRIG_MODE); + mutex_unlock(&cpld_data->cpld_lock); + status = size; + return status; +} + +static ssize_t txfault_int_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(TXFAULT_INT); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t modabs_int_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(MODABS_INT); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t rxlos_int_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(RXLOS_INT); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t txfault_mask_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(TXFAULT_MSK); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t txfault_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + long value; + ssize_t status; + + status = kstrtol(buf, 0, &value); + value = value & 0x0F; + if (status == 0) { + mutex_lock(&cpld_data->cpld_lock); + outb(value, TXFAULT_MSK); + mutex_unlock(&cpld_data->cpld_lock); + status = size; + } + return status; +} + +static ssize_t modabs_mask_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(MODABS_MSK); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t modabs_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + long value; + ssize_t status; + + status = kstrtol(buf, 0, &value); + value = value & 0x0F; + if (status == 0) { + mutex_lock(&cpld_data->cpld_lock); + outb(value, MODABS_MSK); + mutex_unlock(&cpld_data->cpld_lock); + status = size; + } + return status; +} + +static ssize_t rxlos_mask_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(RXLOS_MSK); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t rxlos_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + long value; + ssize_t status; + + status = kstrtol(buf, 0, &value); + value = value & 0x0F; + if (status == 0) { + mutex_lock(&cpld_data->cpld_lock); + outb(value, RXLOS_MSK); + mutex_unlock(&cpld_data->cpld_lock); + status = size; + } + return status; +} + +static ssize_t fan_led_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr); + int index = sa->index; + unsigned char data = 0; + char *led_str[5] = {"green", "green-blink", "amber", "amber-blink", "off"}; + + // Use index to determind the status bit + mutex_lock(&cpld_data->cpld_lock); + data = inb(FAN_LED_1 + index); + data = data & 0x7; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%s\n", led_str[data]); +} + +static ssize_t fan_led_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr); + int index = sa->index; + unsigned char led_status = 0; + + if (sysfs_streq(buf, "off")) { + led_status = fan_led_off; + } else if (sysfs_streq(buf, "green")) { + led_status = fan_led_grn; + } else if (sysfs_streq(buf, "amber")) { + led_status = fan_led_amb; + } else if (sysfs_streq(buf, "green-blink")) { + led_status = fan_led_grn_bnk; + } else if (sysfs_streq(buf, "amber-blink")) { + led_status = fan_led_amb_bnk; + } else { + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + outb(led_status, FAN_LED_1 + index); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + +static DEVICE_ATTR_RO(version); +static DEVICE_ATTR_RW(scratch); +static DEVICE_ATTR_RW(getreg); +static DEVICE_ATTR_WO(setreg); +static DEVICE_ATTR_RW(status_led); +static DEVICE_ATTR_RW(master_led); +static DEVICE_ATTR_RO(psuL_prs); +static DEVICE_ATTR_RO(psuL_status); +static DEVICE_ATTR_RO(psuR_status); +static DEVICE_ATTR_RO(sfp_txfault); +static DEVICE_ATTR_RO(sfp_modabs); +static DEVICE_ATTR_RO(sfp_rxlos); +static DEVICE_ATTR_RW(sfp_txdis); +static DEVICE_ATTR_RW(sfp_rs); +static DEVICE_ATTR_RW(txfault_trig); +static DEVICE_ATTR_RW(modabs_trig); +static DEVICE_ATTR_RW(rxlos_trig); +static DEVICE_ATTR_RO(txfault_int); +static DEVICE_ATTR_RO(modabs_int); +static DEVICE_ATTR_RO(rxlos_int); +static DEVICE_ATTR_RW(txfault_mask); +static DEVICE_ATTR_RW(modabs_mask); +static DEVICE_ATTR_RW(rxlos_mask); +static SENSOR_DEVICE_ATTR(fan1_dir, S_IRUGO, fan_dir_show, NULL, FAN_1); +static SENSOR_DEVICE_ATTR(fan2_dir, S_IRUGO, fan_dir_show, NULL, FAN_2); +static SENSOR_DEVICE_ATTR(fan3_dir, S_IRUGO, fan_dir_show, NULL, FAN_3); +static SENSOR_DEVICE_ATTR(fan1_led, S_IWUSR | S_IRUGO, fan_led_show, fan_led_store, FAN_1); +static SENSOR_DEVICE_ATTR(fan2_led, S_IWUSR | S_IRUGO, fan_led_show, fan_led_store, FAN_2); +static SENSOR_DEVICE_ATTR(fan3_led, S_IWUSR | S_IRUGO, fan_led_show, fan_led_store, FAN_3); + +static struct attribute *cpld_attrs[] = { + &dev_attr_version.attr, + &dev_attr_scratch.attr, + &dev_attr_getreg.attr, + &dev_attr_setreg.attr, + // LEDs + &dev_attr_status_led.attr, + &dev_attr_master_led.attr, + // PSUs + &dev_attr_psuL_prs.attr, + &dev_attr_psuR_prs.attr, + &dev_attr_psuL_status.attr, + &dev_attr_psuR_status.attr, + // FANs + &sensor_dev_attr_fan1_dir.dev_attr.attr, + &sensor_dev_attr_fan2_dir.dev_attr.attr, + &sensor_dev_attr_fan3_dir.dev_attr.attr, + &sensor_dev_attr_fan1_led.dev_attr.attr, + &sensor_dev_attr_fan2_led.dev_attr.attr, + &sensor_dev_attr_fan3_led.dev_attr.attr, + NULL, +}; + +static struct attribute_group cpld_group = { + .attrs = cpld_attrs, +}; + +static struct attribute *sfp_attrs[] = { + // SFP + &dev_attr_sfp_txfault.attr, + &dev_attr_sfp_modabs.attr, + &dev_attr_sfp_rxlos.attr, + &dev_attr_sfp_txdis.attr, + &dev_attr_sfp_rs.attr, + &dev_attr_txfault_trig.attr, + &dev_attr_modabs_trig.attr, + &dev_attr_rxlos_trig.attr, + &dev_attr_txfault_int.attr, + &dev_attr_modabs_int.attr, + &dev_attr_rxlos_int.attr, + &dev_attr_txfault_mask.attr, + &dev_attr_modabs_mask.attr, + &dev_attr_rxlos_mask.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(sfp); + +static struct resource cpld_resources[] = { + { + .start = 0x0200, + .end = 0x0255, + .flags = IORESOURCE_IO, + }, +}; + +static void cpld_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device cpld_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(cpld_resources), + .resource = cpld_resources, + .dev = { + .release = cpld_dev_release, + } +}; + +static int cpld_drv_probe(struct platform_device *pdev) +{ + struct resource *res; + int err; + + cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct cpld_data), + GFP_KERNEL); + if (!cpld_data) + return -ENOMEM; + + mutex_init(&cpld_data->cpld_lock); + + cpld_data->read_addr = VERSION; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (unlikely(!res)) { + printk(KERN_ERR "Specified Resource Not Available...\n"); + return -ENODEV; + } + + err = sysfs_create_group(&pdev->dev.kobj, &cpld_group); + if (err) { + printk(KERN_ERR "Cannot create sysfs for SMC.\n"); + return err; + } + + celplatform = class_create(THIS_MODULE, "celplatform"); + if (IS_ERR(celplatform)) { + printk(KERN_ERR "Failed to register device class\n"); + sysfs_remove_group(&pdev->dev.kobj, &cpld_group); + return PTR_ERR(celplatform); + } + + cpld_data->fpp_node = device_create_with_groups(celplatform, NULL, MKDEV(0, 0), NULL, sfp_groups, "optical_ports"); + + if (IS_ERR(cpld_data->fpp_node)) { + class_destroy(celplatform); + sysfs_remove_group(&pdev->dev.kobj, &cpld_group); + return PTR_ERR(cpld_data->fpp_node); + } + + err = sysfs_create_link(&pdev->dev.kobj, &cpld_data->fpp_node->kobj, "SFP"); + if (err != 0) { + put_device(cpld_data->fpp_node); + device_unregister(cpld_data->fpp_node); + class_destroy(celplatform); + sysfs_remove_group(&pdev->dev.kobj, &cpld_group); + return err; + } + + // Clear all reset signals + outb(0xFF, SPR_RESET); + return 0; +} + +static int cpld_drv_remove(struct platform_device *pdev) +{ + device_unregister(cpld_data->fpp_node); + put_device(cpld_data->fpp_node); + sysfs_remove_group(&pdev->dev.kobj, &cpld_group); + class_destroy(celplatform); + return 0; +} + +static struct platform_driver cpld_drv = { + .probe = cpld_drv_probe, + .remove = __exit_p(cpld_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +int cpld_init(void) +{ + // Register platform device and platform driver + platform_device_register(&cpld_dev); + platform_driver_register(&cpld_drv); + return 0; +} + +void cpld_exit(void) +{ + // Unregister platform device and platform driver + platform_driver_unregister(&cpld_drv); + platform_device_unregister(&cpld_dev); +} + +module_init(cpld_init); +module_exit(cpld_exit); + + +MODULE_AUTHOR("Celestica Inc."); +MODULE_DESCRIPTION("Celestica E1031 SMC driver"); +MODULE_VERSION("1.0.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/systemd/platform-modules-haliburton.service b/platform/broadcom/sonic-platform-modules-cel/haliburton/systemd/platform-modules-haliburton.service new file mode 100644 index 000000000000..bf1295038856 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/systemd/platform-modules-haliburton.service @@ -0,0 +1,14 @@ + +[Unit] +Description=Celestica haliburton platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-haliburton start +ExecStop=-/etc/init.d/platform-modules-haliburton stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/.gitignore b/platform/broadcom/sonic-platform-modules-dell/.gitignore new file mode 100644 index 000000000000..7f287d538227 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/.gitignore @@ -0,0 +1,50 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-dell/LICENSE b/platform/broadcom/sonic-platform-modules-dell/LICENSE new file mode 100644 index 000000000000..243a846ea80b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2017 Dell, 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 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-dell/README.md b/platform/broadcom/sonic-platform-modules-dell/README.md new file mode 100644 index 000000000000..a9f5358192ad --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/README.md @@ -0,0 +1 @@ +platform drivers for Dell Z9100 for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-dell/common/dell_i2c_utils.sh b/platform/broadcom/sonic-platform-modules-dell/common/dell_i2c_utils.sh new file mode 100755 index 000000000000..896e0166dc59 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/dell_i2c_utils.sh @@ -0,0 +1,62 @@ +# Perform an i2c device configuration : instantiate / delete. +# Input is of the form: +# "echo [driver] > " +# where operation = "new_device" or "delete_device" + +i2c_config() { + local count=0 + local MAX_BUS_RETRY=20 + local MAX_I2C_OP_RETRY=10 + + i2c_bus_op=`echo "$@" | cut -d'>' -f 2` + i2c_bus=$(dirname $i2c_bus_op) + + # check if bus exists + while [[ "$count" -lt "$MAX_BUS_RETRY" ]]; do + [[ -e $i2c_bus ]] && break || sleep .1 + count=$((count+1)) + done + + if [[ "$count" -eq "$MAX_BUS_RETRY" ]]; then + echo "ERROR: $@ : i2c bus not created" + return + fi + + # perform the add/delete + count=0 + while [[ "$count" -lt "$MAX_I2C_OP_RETRY" ]]; do + eval "$@" > /dev/null 2>&1 + [[ $? == 0 ]] && break || sleep .2 + count=$((count+1)) + done + + if [[ "$count" -eq "$MAX_I2C_OP_RETRY" ]]; then + echo "ERROR: $@ : i2c operation failed" + return + fi +} + +# Check if a i2c bus exists. Poll for upto 2 seconds since mux creation may take time.. +# Input: bus to check for existence + +i2c_poll_bus_exists() { + local count=0 + local MAX_BUS_RETRY=20 + local i2c_bus + + i2c_bus=$1 + + # check if bus exists + while [[ "$count" -lt "$MAX_BUS_RETRY" ]]; do + [[ -e $i2c_bus ]] && break || sleep .1 + count=$((count+1)) + done + + if [[ "$count" -eq "$MAX_BUS_RETRY" ]]; then + echo "ERROR: $@ : i2c bus not created" + return 1 + else + return 0 + fi +} + diff --git a/platform/broadcom/sonic-platform-modules-dell/common/dell_ich.c b/platform/broadcom/sonic-platform-modules-dell/common/dell_ich.c new file mode 100644 index 000000000000..8bfe4295cb64 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/dell_ich.c @@ -0,0 +1,1042 @@ +/* Copyright (c) 2018 Dell Inc. + * dell_ich.c - ICH driver for Dell Avoton/Rangeley switches + * + * 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. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "dell_ich" + +#define AVOTON_PCU_DEVICE_ID 0x1f38 + +// GPIO registers +// GPIO Core Control/Access Registers in I/O Space +#define GPIO_SC_USE_SEL 0x0 +#define GPIO_SC_IO_SEL 0x4 +#define GPIO_SC_GP_LVL 0x8 +#define GPIO_SC_TPE 0xC +#define GPIO_SC_TNE 0x10 +#define GPIO_SC_TS 0x14 + +// GPIO SUS Control/Access Registers in I/O Space +#define GPIO_SUS_USE_SEL 0x80 +#define GPIO_SUS_IO_SEL 0x84 +#define GPIO_SUS_GP_LVL 0x88 +#define GPIO_SUS_TPE 0x8C +#define GPIO_SUS_TNE 0x90 +#define GPIO_SUS_TS 0x94 +#define GPIO_SUS_WAKE_EN 0x98 + +static const unsigned char avoton_gpio_regs[] = { + GPIO_SC_USE_SEL, + GPIO_SC_IO_SEL, + GPIO_SC_GP_LVL, + GPIO_SC_TPE, + GPIO_SC_TNE, + GPIO_SC_TS, + GPIO_SUS_USE_SEL, + GPIO_SUS_IO_SEL, + GPIO_SUS_GP_LVL, + GPIO_SUS_TPE, + GPIO_SUS_TNE, + GPIO_SUS_TS, + GPIO_SUS_WAKE_EN +}; + +#define GPIO_REG_LEN 0x4 + +#define GPIOS0_EN (1 << 0) +#define GPIOS1_EN (1 << 1) +#define GPIOS2_EN (1 << 2) +#define GPIOS3_EN (1 << 3) +#define GPIOS4_EN (1 << 4) +#define GPIOS5_EN (1 << 5) +#define GPIOS6_EN (1 << 6) +#define GPIOS7_EN (1 << 7) + +#define GPIOSUS0_EN (1 << 0) +#define GPIOSUS1_EN (1 << 1) +#define GPIOSUS2_EN (1 << 2) +#define GPIOSUS3_EN (1 << 3) +// GPIOSUS4_EN : unused +// GPIOSUS5_EN : unused +#define GPIOSUS6_EN (1 << 6) +#define GPIOSUS7_EN (1 << 7) + + +// GPE0a_EN - General Purpose Event 0 Enables +#define GPIO_GPE0a_EN_SUS0 (1 << 16) +#define GPIO_GPE0a_EN_SUS1 (1 << 17) +#define GPIO_GPE0a_EN_SUS2 (1 << 18) +#define GPIO_GPE0a_EN_SUS3 (1 << 19) +// GPIO_GPE0a_EN_SUS4 : unused +// GPIO_GPE0a_EN_SUS5 : unused +#define GPIO_GPE0a_EN_SUS6 (1 << 22) +#define GPIO_GPE0a_EN_SUS7 (1 << 23) + +#define GPIO_GPE0a_EN_CORE0 (1 << 24) +#define GPIO_GPE0a_EN_CORE1 (1 << 25) +#define GPIO_GPE0a_EN_CORE2 (1 << 26) +#define GPIO_GPE0a_EN_CORE3 (1 << 27) +#define GPIO_GPE0a_EN_CORE4 (1 << 28) +#define GPIO_GPE0a_EN_CORE5 (1 << 29) +#define GPIO_GPE0a_EN_CORE6 (1 << 30) +#define GPIO_GPE0a_EN_CORE7 (1 << 31) + +// GPE0a_STS - General Purpose Event 0 Status +// We're interested in only SUS6 for now +#define GPIO_GPE0a_STS_SUS6 (1 << 22) + +// GPIO_ROUT - GPIO_ROUT Register +#define GPIO_ROUT_OFFSET_SUS0 0 +#define GPIO_ROUT_OFFSET_SUS1 2 +#define GPIO_ROUT_OFFSET_SUS2 4 +#define GPIO_ROUT_OFFSET_SUS3 6 +// GPIO_ROUT_OFFSET_SUS4 : unused +// GPIO_ROUT_OFFSET_SUS5 : unused +#define GPIO_ROUT_OFFSET_SUS6 12 +#define GPIO_ROUT_OFFSET_SUS7 14 + +#define GPIO_ROUT_OFFSET_CORE0 16 +#define GPIO_ROUT_OFFSET_CORE1 18 +#define GPIO_ROUT_OFFSET_CORE2 20 +#define GPIO_ROUT_OFFSET_CORE3 22 +#define GPIO_ROUT_OFFSET_CORE4 24 +#define GPIO_ROUT_OFFSET_CORE5 26 +#define GPIO_ROUT_OFFSET_CORE6 28 +#define GPIO_ROUT_OFFSET_CORE7 30 + +enum GPIO_ROUT { + GPIO_NO_EFFECT = 0, + GPIO_SMI, + GPIO_SCI, + GPIO_RESERVED +}; + +/* + * GPIO resources + * defined as in drivers/gpio/gpio-ich.c + */ +#define ICH_RES_GPIO 0 +#define ICH_RES_GPE0 1 +static struct resource gpio_ich_res[] = { + /* GPIO */ + { + .flags = IORESOURCE_IO, + }, + /* ACPI - GPE0 */ + { + .flags = IORESOURCE_IO, + }, +}; + +// ACPI registers +#define ACPI_GPE0a_STS 0x20 +#define ACPI_GPE0a_EN 0x28 + +// PMC registers +#define PMC_GPIO_ROUT 0x58 +#define PMC_REG_LEN 0x4 + +// lpc_ich_priv is derived from drivers/mfd/lpc_ich.c +struct lpc_ich_priv { + int chipset; + + int abase; /* ACPI base */ + int actrl_pbase; /* ACPI control or PMC base */ + int gbase; /* GPIO base */ + int gctrl; /* GPIO control */ + + int abase_save; /* Cached ACPI base value */ + int actrl_pbase_save; /* Cached ACPI control or PMC base value */ + int gctrl_save; /* Cached GPIO control value */ +}; + +#define ICH_RES_MEM_GCS_PMC 0 + +#define IO_REG_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start) +#define IO_REG_READ(reg, base_res) inl((reg) + (base_res)->start) + +struct resource pmc_res = {.flags = IORESOURCE_MEM,}; + +static struct kobject *dell_kobj; +static unsigned short force_id; +module_param(force_id, ushort, 0); + +#define SMF_REG_ADDR 0x200 +#define SIO_REG_DEVID 0x1 +#define SIO_Z9100_ID 0x1 +#define SIO_S6100_ID 0x2 +#define SIO_S4200_ID 0x3 +#define SIO_S5148_ID 0x4 + +enum kinds { + z9100smf, s6100smf +}; + +struct dell_ich_data { + enum kinds kind; + struct resource *gpio_base, *acpi_base, *pmc_base; + int gpio_alloc,pmc_alloc; + unsigned int int_gpio_sus6_count; +}; + +// GPIO sysfs attributes + +static ssize_t get_sc_use_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_USE_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_use_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_USE_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_io_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_IO_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_io_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_IO_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_lvl(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_GP_LVL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_lvl(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_GP_LVL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_tpe(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_TPE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_tpe(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_TPE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_tne(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_TNE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_tne(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_TNE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_ts(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_TS,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_ts(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_TS,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_use_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_USE_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_use_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_USE_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_io_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_IO_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_io_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_IO_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_lvl(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_GP_LVL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_lvl(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_GP_LVL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_tpe(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_TPE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_tpe(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_TPE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_tne(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_TNE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_tne(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_TNE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_ts(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_TS,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_ts(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_TS,ich_data->gpio_base); + + return count; +} + +static DEVICE_ATTR(sc_use_sel, S_IRUGO | S_IWUSR, get_sc_use_sel, set_sc_use_sel); +static DEVICE_ATTR(sc_io_sel, S_IRUGO | S_IWUSR, get_sc_io_sel, set_sc_io_sel); +static DEVICE_ATTR(sc_gp_lvl, S_IRUGO | S_IWUSR, get_sc_gp_lvl, set_sc_gp_lvl); +static DEVICE_ATTR(sc_gp_tpe, S_IRUGO | S_IWUSR, get_sc_gp_tpe, set_sc_gp_tpe); +static DEVICE_ATTR(sc_gp_tne, S_IRUGO | S_IWUSR, get_sc_gp_tne, set_sc_gp_tne); +static DEVICE_ATTR(sc_gp_ts, S_IRUGO | S_IWUSR, get_sc_gp_ts, set_sc_gp_ts); +static DEVICE_ATTR(sus_use_sel, S_IRUGO | S_IWUSR, get_sus_use_sel,set_sus_use_sel); +static DEVICE_ATTR(sus_io_sel, S_IRUGO | S_IWUSR, get_sus_io_sel, set_sus_io_sel); +static DEVICE_ATTR(sus_gp_lvl, S_IRUGO | S_IWUSR, get_sus_gp_lvl, set_sus_gp_lvl); +static DEVICE_ATTR(sus_gp_tpe, S_IRUGO | S_IWUSR, get_sus_gp_tpe, set_sus_gp_tpe); +static DEVICE_ATTR(sus_gp_tne, S_IRUGO | S_IWUSR, get_sus_gp_tne, set_sus_gp_tne); +static DEVICE_ATTR(sus_gp_ts, S_IRUGO | S_IWUSR, get_sus_gp_ts, set_sus_gp_ts); + +static struct attribute *gpio_attrs[] = { + &dev_attr_sc_use_sel.attr, + &dev_attr_sc_io_sel.attr, + &dev_attr_sc_gp_lvl.attr, + &dev_attr_sc_gp_tpe.attr, + &dev_attr_sc_gp_tne.attr, + &dev_attr_sc_gp_ts.attr, + &dev_attr_sus_use_sel.attr, + &dev_attr_sus_io_sel.attr, + &dev_attr_sus_gp_lvl.attr, + &dev_attr_sus_gp_tpe.attr, + &dev_attr_sus_gp_tne.attr, + &dev_attr_sus_gp_ts.attr, + NULL, +}; + +static struct attribute_group gpio_attrs_group= { + .attrs = gpio_attrs, +}; + +// ACPI sysfs attributes + +static ssize_t get_gpe0a_sts(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(ACPI_GPE0a_STS,ich_data->acpi_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_gpe0a_sts(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,ACPI_GPE0a_STS,ich_data->acpi_base); + + return count; +} + +static ssize_t get_gpe0a_en(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(ACPI_GPE0a_EN,ich_data->acpi_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_gpe0a_en(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,ACPI_GPE0a_EN,ich_data->acpi_base); + + return count; +} + +static DEVICE_ATTR(gpe0a_sts, S_IRUGO | S_IWUSR, get_gpe0a_sts, set_gpe0a_sts); +static DEVICE_ATTR(gpe0a_en, S_IRUGO | S_IWUSR, get_gpe0a_en, set_gpe0a_en); + +static struct attribute *acpi_attrs[] = { + &dev_attr_gpe0a_sts.attr, + &dev_attr_gpe0a_en.attr, + NULL, +}; + +static struct attribute_group acpi_attrs_group= { + .attrs = acpi_attrs, +}; + +static ssize_t get_gpio_rout(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = readl(ich_data->pmc_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +// PMC sysfs attributes + +static ssize_t set_gpio_rout(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + writel(devdata,ich_data->pmc_base); + + return count; +} + +static DEVICE_ATTR(gpio_rout, S_IRUGO | S_IWUSR, get_gpio_rout, set_gpio_rout); + +static struct attribute *pmc_attrs[] = { + &dev_attr_gpio_rout.attr, + NULL, +}; + +static struct attribute_group pmc_attrs_group= { + .attrs = pmc_attrs, +}; + +// SCI interrupt sysfs attributes + +static ssize_t get_sci_int_gpio_sus6(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = ich_data->int_gpio_sus6_count; + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sci_int_gpio_sus6(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + ich_data->int_gpio_sus6_count = devdata; + + return count; +} + +static DEVICE_ATTR(sci_int_gpio_sus6, S_IRUGO | S_IWUSR, get_sci_int_gpio_sus6, set_sci_int_gpio_sus6); + +static struct attribute *sci_attrs[] = { + &dev_attr_sci_int_gpio_sus6.attr, + NULL, +}; + +static struct attribute_group sci_attrs_group= { + .attrs = sci_attrs, +}; + +static u32 dell_ich_sci_handler(void *context) +{ + unsigned int data; + struct device *dev = (struct device *)context; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!dev) return ACPI_INTERRUPT_NOT_HANDLED; + + ich_data = dev_get_platdata(dev); + if(!ich_data) return ACPI_INTERRUPT_NOT_HANDLED; + + data=IO_REG_READ(ACPI_GPE0a_STS,ich_data->acpi_base); + if(data & GPIO_GPE0a_STS_SUS6) { + // Clear the SUS6 status + IO_REG_WRITE(data,ACPI_GPE0a_STS,ich_data->acpi_base); + ich_data->int_gpio_sus6_count++; + // and notify the user space clients + sysfs_notify(&dev->kobj, NULL, "sci_int_gpio_sus6"); + return ACPI_INTERRUPT_HANDLED; + } + + return ACPI_INTERRUPT_NOT_HANDLED; +} + +/* + * Setup GPIO SUS6 to generate an SCI interrupt for optics detection + * This can be alternatively be setup using sysfs + */ +int setup_gpio_sus6_sci_interrupt(struct device *dev) +{ + int ret=0; + unsigned int data; + struct resource *acpi_base, *pmc_base, *gpio_base; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + gpio_base = ich_data->gpio_base; + acpi_base = ich_data->acpi_base; + pmc_base = ich_data->pmc_base; + + // Enable GPIOSUS6_EN + data = IO_REG_READ(GPIO_SUS_USE_SEL,gpio_base); + data |= GPIOSUS6_EN; + IO_REG_WRITE(data,GPIO_SUS_USE_SEL,gpio_base); + + // GPIOSUS6_EN is input + data = IO_REG_READ(GPIO_SUS_IO_SEL,gpio_base); + data |= GPIOSUS6_EN; + IO_REG_WRITE(data,GPIO_SUS_IO_SEL,gpio_base); + + // Trigger on positive edge for GPIOSUS6_EN + data = IO_REG_READ(GPIO_SUS_TPE,gpio_base); + data |= GPIOSUS6_EN; + IO_REG_WRITE(data,GPIO_SUS_TPE,gpio_base); + + // Enable GPE for SUS6 to generate an SCI + data=IO_REG_READ(ACPI_GPE0a_EN,acpi_base); + data|=GPIO_GPE0a_EN_SUS6; + IO_REG_WRITE(data,ACPI_GPE0a_EN,acpi_base); + + data=readl(pmc_base); + data=(data & ~(0x3 << GPIO_ROUT_OFFSET_SUS6)) | (GPIO_SCI << GPIO_ROUT_OFFSET_SUS6); + writel(data,pmc_base); + + ret = acpi_install_sci_handler(dell_ich_sci_handler,(void*)dev); + if(ret) { + pr_info("dell_ich acpi_install_sci_handler failed %d\n",ret); + return ret; + } + + return ret; +} + +static int dell_ich_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + struct pci_dev *lpc_ich_dev; + struct lpc_ich_priv *priv; + struct resource *res; + unsigned int base_addr_cfg, base_addr; + int ret,i; + + // Get the PCU device + lpc_ich_dev=pci_get_device(PCI_VENDOR_ID_INTEL,AVOTON_PCU_DEVICE_ID,NULL); + priv=(struct lpc_ich_priv*) pci_get_drvdata(lpc_ich_dev); + if(!priv) { + pr_info("dell_ich: Unable to retrieve private data\n"); + return -ENODEV; + } + + // Retrieve the GPIO Base (that was initialized by lpc-ich) + pci_read_config_dword(lpc_ich_dev, priv->gbase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + pr_info("dell_ich I/O space for GPIO uninitialized\n"); + ret = -ENODEV; + goto probe_err; + } + + res = &gpio_ich_res[ICH_RES_GPIO]; + res->start = base_addr; + res->end = res->start + 0x9c - 1; + ret = acpi_check_resource_conflict(res); + if (ret) { + pr_info("dell_ich gpio resource conflict ret %d\n",ret); + } + + ich_data->gpio_base=res; + // Request regions for GPIO registers + for(i=0; istart+avoton_gpio_regs[i],GPIO_REG_LEN, "dell_ich_gpio")) { + pr_info("dell_ich: request_region failed for GPIO : %x\n",(unsigned int) res->start+avoton_gpio_regs[i]); + ret = -EBUSY; + goto probe_err; + } + ich_data->gpio_alloc |= (1<kobj, &gpio_attrs_group); + if (ret) { + pr_info("dell_ich cannot create sysfs for GPIO %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + // Retrieve the ACPI Base (that was initialized by lpc-ich) + pci_read_config_dword(lpc_ich_dev, priv->abase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + pr_info("dell_ich I/O space for ACPI uninitialized\n"); + ret = -ENODEV; + goto probe_err; + } + + res = &gpio_ich_res[ICH_RES_GPE0]; + res->start = base_addr; + res->end = base_addr + 0x40; + ret = acpi_check_resource_conflict(res); + if (ret) { + pr_info("dell_ich acpi resource conflict ret %d\n",ret); + } + + // ACPI region is requested by pnp 00:01/ACPI GPE0_BLK + ich_data->acpi_base=res; + + /* Register sysfs hooks for ACPI */ + ret = sysfs_create_group(&dev->kobj, &acpi_attrs_group); + if (ret) { + pr_info("dell_ich cannot create sysfs for ACPI %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + // Retrieve the PMC Base (that was initialized by lpc-ich) + pci_read_config_dword(lpc_ich_dev, priv->actrl_pbase, &base_addr_cfg); + base_addr = base_addr_cfg & 0xfffffe00; + pr_info("dell_ich base_addr_cfg %x base_addr %x\n",(int)base_addr_cfg,(int)base_addr); + if (!base_addr) { + pr_info("dell_ich PMC space for GPIO uninitialized\n"); + ret = -ENODEV; + goto probe_err; + } + + res = &pmc_res; + res->start = base_addr + PMC_GPIO_ROUT; + res->end = base_addr + PMC_GPIO_ROUT + PMC_REG_LEN - 1; + pr_info("dell_ich pmc res_start:end %x:%x\n",(int)res->start,(int)res->end); + + ret = acpi_check_resource_conflict(res); + if (ret) { + pr_info("dell_ich acpi resource conflict ret %d\n",ret); + } + + if (!request_mem_region(res->start,resource_size(res),"dell_ich_pmc")) { + pr_info("dell_ich pmc request_region failed\n"); + ret = -EBUSY; + goto probe_err; + } else { + ich_data->pmc_alloc=1; + } + + ich_data->pmc_base = ioremap(res->start, resource_size(res)); + if(!ich_data->pmc_base) { + pr_info("dell_ich pmc ioremap failed\n"); + ret = -ENOMEM; + goto probe_err; + } + + /* Register sysfs hooks for pmc */ + ret = sysfs_create_group(&dev->kobj, &pmc_attrs_group); + if (ret) { + pr_info("dell_ich cannot create sysfs for PMC %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + /* Register sysfs hooks for SCI interrupts*/ + ret = sysfs_create_group(&dev->kobj, &sci_attrs_group); + if (ret) { + pr_info("dell_ich cannot create sysfs for SCI %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + if((ich_data->kind == z9100smf) || (ich_data->kind == s6100smf)) { + ret = setup_gpio_sus6_sci_interrupt(dev); + if (ret) { + pr_info("dell_ich unable to setup SCI interrupt %d\n",ret); + goto probe_err; + } + } + + return 0; + +probe_err: + pr_info("dell_ich dell_ich_probe failed with : %d\n",ret); + return ret; +} + +static int dell_ich_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + int i,ret; + + // Release GPIO regions + for(i=0; igpio_alloc & (1<gpio_base->start+avoton_gpio_regs[i], GPIO_REG_LEN); + } + } + + // Unmap and release PMC regions + if(ich_data->pmc_base) iounmap(ich_data->pmc_base); + if(ich_data->pmc_alloc) release_region(pmc_res.start, PMC_REG_LEN); + + ret = acpi_remove_sci_handler(dell_ich_sci_handler); + if(ret) { + pr_info("dell_ich acpi_remove_sci_handler failed %d\n",ret); + return ret; + } + + pr_info("dell_ich : dell_ich_remove done.\n"); + + return 0; +} + +static struct platform_driver dell_ich_driver= { + .driver = { + .name = DRV_NAME, + }, + .probe = dell_ich_probe, + .remove = dell_ich_remove, +}; + +int __init +init_ich_data(int smf_address, struct dell_ich_data *ich_data) +{ + int val; + + memset(ich_data, 0, sizeof(struct dell_ich_data)); + + if (force_id) + val = force_id; + else + val = inb(smf_address + SIO_REG_DEVID); + + switch (val) { + case SIO_Z9100_ID: + ich_data->kind = z9100smf; + break; + case SIO_S6100_ID: + ich_data->kind = s6100smf; + break; + default: + if (val != 0xffff) + pr_debug("unsupported chip ID: 0x%04x\n", val); + return -ENODEV; + } + + pr_info("dell_ich: found SMF for ID %#x\n", ich_data->kind); + + return (0); +} + +static struct platform_device *pdev; + +static int __init dell_ich_init(void) +{ + int err; + struct dell_ich_data ich_data; + + if (init_ich_data(SMF_REG_ADDR, &ich_data)) + return -ENODEV; + + err = platform_driver_register(&dell_ich_driver); + if (err) + goto exit; + + pdev = platform_device_alloc(DRV_NAME, 0); + if (!pdev) { + err = -ENOMEM; + pr_err("dell_ich: Device allocation failed\n"); + goto exit_unregister; + } + + err = platform_device_add_data(pdev, &ich_data, + sizeof(struct dell_ich_data)); + if (err) { + pr_err("dell_ich: Platform data allocation failed\n"); + goto exit_device_put; + } + + /* platform_device_add calls probe() */ + err = platform_device_add(pdev); + if (err) { + pr_err("dell_ich: Device addition failed (%d)\n", err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); +exit_unregister: + platform_driver_unregister(&dell_ich_driver); +exit: + pr_err("dell_ich: dell_ich_init failed (%d)\n", err); + return err; +} + +static void __exit dell_ich_exit(void) +{ + platform_device_unregister(pdev); + platform_driver_unregister(&dell_ich_driver); + + /*Remove sysfs dell_kobj*/ + kobject_put(dell_kobj); +} + +MODULE_AUTHOR("Padmanabhan Narayanan"); +MODULE_DESCRIPTION("ICH driver for Dell Avoton/Rangeley switches"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:"DRV_NAME); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + +module_init(dell_ich_init); +module_exit(dell_ich_exit); diff --git a/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c b/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c new file mode 100644 index 000000000000..557976457503 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c @@ -0,0 +1,1919 @@ +/* Copyright (c) 2017 Dell Inc.* + * dell_s6100_smf.c - driver for Dell SMF + * + * Author: Per Fremrot + * Author: Paavaanan + * + * 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 +#include +#include + +#define SIO_DRVNAME "SMF" +#define DEBUG 1 +#define LABELS 1 + +#define FANIN_MAX 12 /* Counted from 1 */ +#define VSEN_MAX 48 /* VSEN1.. */ +#define CURR_MAX 6 +#define TCPU_MAX 15 +#define PSU_MAX 4 /* TODO change to actual sensors */ + +/* Where are the sensors address/data + registers relative to the region offset */ + +#define IOREGION_OFFSET 0x10 +#define IOREGION_LENGTH 0x4 +#define SMF_ADDR_REG_OFFSET 0 +#define SMF_READ_DATA_REG_OFFSET 2 +#define SMF_REG_ADDR 0x200 +#define SMF_PROBE_ADDR 0x210 + +#define SIO_REG_DEVID 0x1 +#define SIO_Z9100_ID 0x1 +#define SIO_S6100_ID 0x2 +#define SIO_S4200_ID 0x3 +#define SIO_S5148_ID 0x4 + +/* IOM presence */ +#define IO_MODULE_STATUS 0x0310 +#define IO_MODULE_PRESENCE 0x0311 + +/* FAN Tray */ +#define S6100_MAX_NUM_FAN_TRAYS 4 +#define Z9100_MAX_NUM_FAN_TRAYS 5 + +#define MAX_NUM_FAN_TRAYS 0x00F0 +#define MAX_NUM_FANS_PER_TRAY 0x00F1 +#define FAN_TRAY_PRESENCE 0x0113 +#define FAN_STATUS_GROUP_A 0x0114 +#define FAN_STATUS_GROUP_B 0x0115 +#define FAN_TRAY_AIRFLOW 0x0116 + + +/* FAN Z9100 */ +#define SMF_FAN_SPEED_ADDR 0x00F3 +#define FAN_TRAY_1_SPEED 0x00F3 +#define FAN_TRAY_1_FAN_2_SPEED 0x00F5 +#define FAN_TRAY_2_SPEED 0x00F7 +#define FAN_TRAY_2_FAN_2_SPEED 0x00F9 +#define FAN_TRAY_3_SPEED 0x00FB +#define FAN_TRAY_3_FAN_2_SPEED 0x00FD +#define FAN_TRAY_4_SPEED 0x00FF +#define FAN_TRAY_4_FAN_2_SPEED 0x0101 +#define FAN_TRAY_5_FAN_1_SPEED 0x0103 +#define FAN_TRAY_5_FAN_2_SPEED 0x0105 +#define FAN_TRAY_5 4 +#define FAN_601_FAULT (2 + 1) +#define IN28_INPUT (27 + 1) +#define IN404_INPUT (43 + 1) +#define IOM_PRESENCE (44 + 1) +#define IOM_PRESENCE_MAX (45 + 1) +#define IN602_INPUT (1 + 1) +#define CURR22_INPUT (1 + 1) +#define CURR602_INPUT (3 + 1) +#define TEMP13_INPUT (12 + 1) +#define TEMP601_INPUT (13 + 1) + +/* PSUs */ +#define S6100_MAX_NUM_PSUS 2 +#define MAX_NUM_PSUS 0x0231 +#define CURRENT_TOTAL_POWER 0x0232 + +/* PSU1 */ +#define PSU_1_MAX_POWER 0x0234 +#define PSU_1_FUNCTION_SUPPORT 0x0236 +#define PSU_1_STATUS 0x0237 +#define PSU_1_TEMPERATURE 0x0239 +#define PSU_1_FAN_SPEED 0x023B +#define PSU_1_FAN_STATUS 0x023D +#define PSU_1_INPUT_VOLTAGE 0x023E +#define PSU_1_OUTPUT_VOLTAGE 0x0240 +#define PSU_1_INPUT_CURRENT 0x0242 +#define PSU_1_OUTPUT_CURRENT 0x0244 +#define PSU_1_INPUT_POWER 0x0246 +#define PSU_1_OUTPUT_POWER 0x0248 +#define PSU_1_FAN_SPEED 0x023B + +/* PSU2 */ +#define PSU_2_MAX_POWER 0x026D +#define PSU_2_FUNCTION_SUPPORT 0x026F +#define PSU_2_STATUS 0x0270 +#define PSU_2_TEMPERATURE 0x0272 +#define PSU_2_FAN_SPEED 0x0274 +#define PSU_2_FAN_STATUS 0x0276 +#define PSU_2_INPUT_VOLTAGE 0x0277 +#define PSU_2_OUTPUT_VOLTAGE 0x0279 +#define PSU_2_INPUT_CURRENT 0x027B +#define PSU_2_OUTPUT_CURRENT 0x027D +#define PSU_2_INPUT_POWER 0x027F +#define PSU_2_OUTPUT_POWER 0x0281 + +/* TEMP */ +#define TEMP_SENSOR_1 0x0014 +#define TEMP_SENSOR_1_STATUS 0x00DC +#define TEMP_SENSOR_1_HW_LIMIT 0x003E + +/* VOLTAGE */ +#define CPU_1_VOLTAGE 0x02A8 +#define IO_MODULE_1_VOLTAGE 0x02E8 +#define SWITCH_CURRENT_S6100 0x02E4 +#define SWITCH_CURRENT_Z9100 0x02E2 + +/* VOLTAGE S6100 */ +#define CPU_1_MONITOR_STATUS 0x0308 +#define CPU_2_MONITOR_STATUS 0x0309 +#define CPU_3_MONITOR_STATUS 0x030A +#define CPU_4_MONITOR_STATUS 0x030B + +/* VOLTAGE Z9100 */ +#define CPU_5_MONITOR_STATUS 0x02E6 +#define CPU_6_MONITOR_STATUS 0x02E7 +#define CPU_7_MONITOR_STATUS 0x02E8 +#define CPU_8_MONITOR_STATUS 0x02E9 + + +unsigned long *mmio; +static struct kobject *dell_kobj; +static unsigned short force_id; +module_param(force_id, ushort, 0); +int smf_ver; + + +enum kinds { + z9100smf, s6100smf +}; + + +struct smf_devices { + const char *name; + u64 tcpu_mask; + u64 vsen_mask; + u32 curr_mask; + u64 fanin_mask; + u64 psu_mask; + const char *const *temp_label; + const char *const *vsen_label; + const char *const *curr_label; + const char *const *fan_label; + const char *const *psu_label; +}; + + +static const char *const z9100_temp_label[] = { + "CPU On-board (U2900)", + "BCM Switch On-Board #1 (U44)", + "Front BCM On-Board (U4)", + "Front BCM On-Board (U2)", + "Unused", + "BCM Switch On-Board #1 (U38)", + "Unused", + "Unused", + "Rear (U2900)", + "", + "", + "", + "", + "", + "PSU 1", + "PSU 2" +}; + + +static const char *const s6100_temp_label[] = { + "CPU On-board (U2900)", + "BCM On-Board #1 (U44)", + "Front BCM On-board (U4)", + "Front BCM On-board (U2)", + "IOM #1", + "IOM #2", + "IOM #3", + "IOM #4", + "U2 Switch board?", + "Front GE", + "Front SFP+", + "BCM Internal", + "CPU Internal", + "", + "PSU 1", + "PSU 2" +}; + + +static const char *const z9100_vsen_label[] = { + /* CPU Board */ + "CPU XP3R3V_EARLY", + "CPU XP5R0V_CP", + "CPU XP3R3V_STD", + "CPU XP3R3V_CP ", + "CPU XP0R75V_VTT_A", + "CPU XP0R75V_VTT_B", + "CPU XP1R07V_CPU", + "CPU XP1R0V_CPU", + "CPU XP12R0V", + "CPU VDDR_CPU_2", + "CPU VDDR_CPU_1", + "CPU XP1R5V_CLK", + "CPU XP1R35V_CPU", + "CPU XP1R8V_CPU", + "CPU XP1R0V_CPU_VNN", + "CPU XP1R0V_CPU_VCC", + "CPU XP1R5V_EARLY", + /* Switch Board */ + "SW XP12R0V_MON", + "SW XP3R3V_MON", + "SW XP1R8V_MON", + "SW XP1R25V_MON", + "SW XP1R2V_MON", + "SW XP1R0V_SW_MON", + "SW XP1R0V_ROV_SW_MON", + "SW XP5V_MB_MON", + "SW XP1R8V_FPGA_MON", + "SW XP3R3V_FPGA_MON", + "SW XP3R3V_EARLY_MON", + /* PSU */ + "PSU1 VIN", + "PSU1 VOUT", + "PSU2 VIN", + "PSU2 VOUT", + /* IOM 1 */ + "", + "", + "", + "", + /* IOM 2 */ + "", + "", + "", + "", + /* IOM 3 */ + "", + "", + "", + "", + /* IOM 4 */ + "", + "", + "", + "" +}; + + +static const char *const s6100_vsen_label[] = { + /* CPU Board */ + "CPU XP3R3V_EARLY", + "CPU XP5R0V_CP", + "CPU XP3R3V_STD", + "CPU XP3R3V_CP ", + "CPU XP0R75V_VTT_A", + "CPU XP0R75V_VTT_B", + "CPU XP1R07V_CPU", + "CPU XP1R0V_CPU", + "CPU XP12R0V", + "CPU VDDR_CPU_2", + "CPU VDDR_CPU_1", + "CPU XP1R5V_CLK", + "CPU XP1R35V_CPU", + "CPU XP1R8V_CPU", + "CPU XP1R0V_CPU_VNN", + "CPU XP1R0V_CPU_VCC", + "CPU XP1R5V_EARLY", + /* Switch Board */ + "SW XP12R0V_MON", + "SW XP3R3V_MON", + "SW XP1R8V_MON", + "SW XP1R25V_MON", + "SW XP1R2V_MON", + "SW XP1R0V_SW_MON", + "SW XP1R0V_ROV_SW_MON", + "XR1R0V_BCM84752_MON", + "SW XP5V_MB_MON", + "SW XP1R8V_FPGA_MON", + "SW XP3R3V_FPGA_MON", + + /* PSU */ + "PSU1 VIN", + "PSU1 VOUT", + "PSU2 VIN", + "PSU2 VOUT", + + /* IOM 1 */ + "IOM 1 #1", + "IOM 1 #2", + "IOM 1 #3", + "IOM 1 #4", + /* IOM 2 */ + "IOM 2 #1", + "IOM 2 #2", + "IOM 2 #3", + "IOM 2 #4", + /* IOM 1 */ + "IOM 3 #1", + "IOM 3 #2", + "IOM 3 #3", + "IOM 3 #4", + /* IOM 1 */ + "IOM 4 #1", + "IOM 4 #2", + "IOM 4 #3", + "IOM 4 #4" +}; + + +static const char *const z9100_curr_label[] = { + "XP1R0V", + "XP1R0V_ROV" +}; + + +static const char *const s6100_fan_label[] = { + "Tray1 Fan1", + "", + "Tray2 Fan1", + "", + "Tray3 Fan1", + "", + "Tray4 Fan1", + "", + "", + "", + "Psu1 Fan", + "Psu2 Fan" +}; + +static const char *const z9100_fan_label[] = { + "Tray1 Fan1", + "Tray1 Fan2", + "Tray2 Fan1", + "Tray2 Fan2", + "Tray3 Fan1", + "Tray3 Fan2", + "Tray4 Fan1", + "Tray4 Fan2", + "Tray5 Fan1", + "Tray5 Fan2", + "Psu1 Fan", + "Psu2 Fan" +}; + + +static const char *const s6100_psu_label[] = { + "Psu1 Input", + "Psu1 Output", + "Psu2 Input", + "Psu2 Output", +}; + +static const struct smf_devices smf_devices[] = { + [z9100smf] = { + .name = "SMF_Z9100_ON", + .tcpu_mask=0xe1ff, + .vsen_mask=0xfffdffff, + .curr_mask=0x3f, + .fanin_mask=0xfff, + .psu_mask=0xf, + .temp_label = z9100_temp_label, + .vsen_label = z9100_vsen_label, + .curr_label = z9100_curr_label, + .fan_label = z9100_fan_label, + .psu_label = s6100_psu_label + }, + [s6100smf] = { + .name = "SMF_S6100_ON", + .tcpu_mask=0x7fff, + .vsen_mask=0xfffffefdffff, + .curr_mask=0x3f, + .fanin_mask=0xc55, + .psu_mask=0xf, + .temp_label = s6100_temp_label, + .vsen_label = s6100_vsen_label, + .curr_label = z9100_curr_label, + .fan_label = s6100_fan_label, + .psu_label = s6100_psu_label + + } +}; + + +/* + * For each registered chip, we need to keep some data in memory. + * The structure is dynamically allocated. + */ +struct smf_data { + enum kinds kind; /* Inherited from SuperIO kind */ + unsigned short addr; + struct device *hwmon_dev; + struct mutex lock; + u64 tcpu_mask; + u64 vsen_mask; + u32 curr_mask; + u64 fanin_mask; + u64 psu_mask; + const char * const *temp_label; + const char * const *vsen_label; + const char * const *curr_label; + const char * const *fan_label; + const char * const *psu_label; +}; + + +struct smf_sio_data { + int sioreg; + enum kinds kind; +}; + + +static int smf_read_reg(struct smf_data *data, u16 reg) +{ + int res; + + mutex_lock(&data->lock); + outb_p(reg>> 8, data->addr + SMF_ADDR_REG_OFFSET); + outb_p(reg & 0xff, data->addr + SMF_ADDR_REG_OFFSET + 1); + res = inb_p(data->addr + SMF_READ_DATA_REG_OFFSET); + mutex_unlock(&data->lock); + return res; +} + + +static int smf_read_reg16(struct smf_data *data, u16 reg) +{ + int res; + + mutex_lock(&data->lock); + outb_p(reg>> 8, data->addr + SMF_ADDR_REG_OFFSET); + outb_p(reg & 0xff, data->addr + SMF_ADDR_REG_OFFSET + 1); + + res = inb_p(data->addr + SMF_READ_DATA_REG_OFFSET); + + outb_p((reg + 1)>> 8, data->addr + SMF_ADDR_REG_OFFSET); + outb_p((reg + 1) & 0xff, data->addr + SMF_ADDR_REG_OFFSET + 1); + + res = (res << 8) + inb_p(data->addr + SMF_READ_DATA_REG_OFFSET); + + mutex_unlock(&data->lock); + return res; +} + + +/* FANIN ATTR */ +static ssize_t +show_fan_label(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct smf_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%s\n", data->fan_label[nr]); +} + + +static ssize_t show_fan(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int export_hex=0; + unsigned int ret = -1; + unsigned rpm; + + + if (index <10) + ret = smf_read_reg16(data, SMF_FAN_SPEED_ADDR + index * 2); + else switch (index) { + case 10: + ret = smf_read_reg16(data, PSU_1_FAN_SPEED); + break; + case 11: + ret = smf_read_reg16(data, PSU_2_FAN_SPEED); + break; + case 12: + ret = ~smf_read_reg(data, FAN_TRAY_PRESENCE); + export_hex = 1; + break; + + default: + return ret; + } + + + if (ret < 0) + return ret; + + rpm = ret; + + if(export_hex) + return sprintf(buf, "%x\n", rpm); + else + return sprintf(buf, "%u\n", rpm); +} + + +static ssize_t show_fan_fault(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret=1, fan_status; + + index = index / 2; + fan_status = ~smf_read_reg(data, FAN_TRAY_PRESENCE); + + if (fan_status & (1 << (index))) + ret=0; + + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", ret); +} + + +static ssize_t show_fan_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret, psu_fan_status=0; + + if(index < 2) + psu_fan_status = smf_read_reg(data, FAN_STATUS_GROUP_B); + + if (psu_fan_status & (1 << (index))) + ret=0; + + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", ret); +} + + +static ssize_t show_fan_airflow(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret=1, fan_airflow; + + if (data->kind == s6100smf && index == FAN_TRAY_5) + return 0; + + fan_airflow = smf_read_reg(data, FAN_TRAY_AIRFLOW); + + if (fan_airflow & (1 << (index))) + ret=1; + + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", ret); +} + + +static ssize_t show_psu_fan(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret=0, fan_status; + + if (index < FAN_601_FAULT){ + fan_status = smf_read_reg(data, PSU_1_FAN_STATUS); + ret = fan_status & (1 << index); + + } + else{ + fan_status = smf_read_reg(data, PSU_2_FAN_STATUS); + ret = fan_status & (1 << (index - 3)); + } + + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", ret); +} + + + +static umode_t smf_fanin_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct smf_data *data = dev_get_drvdata(dev); + + if (data->fanin_mask & (1 << (n % FANIN_MAX))) + return a->mode; + + return 0; +} + +static umode_t smf_dell_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + return a->mode; + +} + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7); +static SENSOR_DEVICE_ATTR(fan9_input, S_IRUGO, show_fan, NULL, 8); +static SENSOR_DEVICE_ATTR(fan10_input, S_IRUGO, show_fan, NULL,9); +/* PSU1 FAN */ +static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, show_fan, NULL, 10); +/* PSU2 FAN */ +static SENSOR_DEVICE_ATTR(fan12_input, S_IRUGO, show_fan, NULL, 11); + +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(fan9_alarm, S_IRUGO, show_fan_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(fan10_alarm, S_IRUGO, show_fan_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(fan11_alarm, S_IRUGO, show_psu_fan, NULL, 1); +static SENSOR_DEVICE_ATTR(fan12_alarm, S_IRUGO, show_psu_fan, NULL, 4); + +static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3); +static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4); +static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5); +static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6); +static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7); +static SENSOR_DEVICE_ATTR(fan9_fault, S_IRUGO, show_fan_fault, NULL, 8); +static SENSOR_DEVICE_ATTR(fan10_fault, S_IRUGO, show_fan_fault, NULL, 9); +static SENSOR_DEVICE_ATTR(fan11_fault, S_IRUGO, show_psu_fan, NULL, 2); +static SENSOR_DEVICE_ATTR(fan12_fault, S_IRUGO, show_psu_fan, NULL, 5); + +static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, show_fan_label, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, show_fan_label, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_label, S_IRUGO, show_fan_label, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_label, S_IRUGO, show_fan_label, NULL, 3); +static SENSOR_DEVICE_ATTR(fan5_label, S_IRUGO, show_fan_label, NULL, 4); +static SENSOR_DEVICE_ATTR(fan6_label, S_IRUGO, show_fan_label, NULL, 5); +static SENSOR_DEVICE_ATTR(fan7_label, S_IRUGO, show_fan_label, NULL, 6); +static SENSOR_DEVICE_ATTR(fan8_label, S_IRUGO, show_fan_label, NULL, 7); +static SENSOR_DEVICE_ATTR(fan9_label, S_IRUGO, show_fan_label, NULL, 8); +static SENSOR_DEVICE_ATTR(fan10_label, S_IRUGO, show_fan_label, NULL, 9); +static SENSOR_DEVICE_ATTR(fan11_label, S_IRUGO, show_fan_label, NULL, 10); +static SENSOR_DEVICE_ATTR(fan12_label, S_IRUGO, show_fan_label, NULL, 11); + + +static struct attribute *smf_fanin_attrs[] = { + &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_fan9_input.dev_attr.attr, + &sensor_dev_attr_fan10_input.dev_attr.attr, + &sensor_dev_attr_fan11_input.dev_attr.attr, + &sensor_dev_attr_fan12_input.dev_attr.attr, + + &sensor_dev_attr_fan1_label.dev_attr.attr, + &sensor_dev_attr_fan2_label.dev_attr.attr, + &sensor_dev_attr_fan3_label.dev_attr.attr, + &sensor_dev_attr_fan4_label.dev_attr.attr, + &sensor_dev_attr_fan5_label.dev_attr.attr, + &sensor_dev_attr_fan6_label.dev_attr.attr, + &sensor_dev_attr_fan7_label.dev_attr.attr, + &sensor_dev_attr_fan8_label.dev_attr.attr, + &sensor_dev_attr_fan9_label.dev_attr.attr, + &sensor_dev_attr_fan10_label.dev_attr.attr, + &sensor_dev_attr_fan11_label.dev_attr.attr, + &sensor_dev_attr_fan12_label.dev_attr.attr, + + + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, + &sensor_dev_attr_fan3_alarm.dev_attr.attr, + &sensor_dev_attr_fan4_alarm.dev_attr.attr, + &sensor_dev_attr_fan5_alarm.dev_attr.attr, + &sensor_dev_attr_fan6_alarm.dev_attr.attr, + &sensor_dev_attr_fan7_alarm.dev_attr.attr, + &sensor_dev_attr_fan8_alarm.dev_attr.attr, + &sensor_dev_attr_fan9_alarm.dev_attr.attr, + &sensor_dev_attr_fan10_alarm.dev_attr.attr, + &sensor_dev_attr_fan11_alarm.dev_attr.attr, + &sensor_dev_attr_fan12_alarm.dev_attr.attr, + + &sensor_dev_attr_fan1_fault.dev_attr.attr, + &sensor_dev_attr_fan2_fault.dev_attr.attr, + &sensor_dev_attr_fan3_fault.dev_attr.attr, + &sensor_dev_attr_fan4_fault.dev_attr.attr, + &sensor_dev_attr_fan5_fault.dev_attr.attr, + &sensor_dev_attr_fan6_fault.dev_attr.attr, + &sensor_dev_attr_fan7_fault.dev_attr.attr, + &sensor_dev_attr_fan8_fault.dev_attr.attr, + &sensor_dev_attr_fan9_fault.dev_attr.attr, + &sensor_dev_attr_fan10_fault.dev_attr.attr, + &sensor_dev_attr_fan11_fault.dev_attr.attr, + &sensor_dev_attr_fan12_fault.dev_attr.attr, + + NULL +}; + + + + +/* VSEN ATTR */ +static ssize_t +show_voltage_label(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct smf_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%s\n", data->vsen_label[nr]); +} + + +static ssize_t show_voltage(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int volt, ret=0; + int export_hex=0; + + /*0 to 27 */ + if (index < IN28_INPUT) /* Voltage sensors */ + ret = smf_read_reg16(data, CPU_1_VOLTAGE + index * 2); + else if ((data->kind == s6100smf) && (index < IN404_INPUT)) + ret = smf_read_reg16(data, IO_MODULE_1_VOLTAGE + index * 2); + else if ((data->kind == s6100smf) && (index < IOM_PRESENCE)) + ret = smf_read_reg(data, IO_MODULE_STATUS); + else if ((data->kind == s6100smf) && (index < IOM_PRESENCE_MAX)) + ret = smf_read_reg(data, IO_MODULE_PRESENCE); + + if (ret < 0) + return ret; + + if(index < 44) + volt = ret*10; + else + export_hex=1; + + if(export_hex) + return sprintf(buf, "%x\n", ret); + else + return sprintf(buf, "%d\n", volt); +} + + +static ssize_t show_psu_voltage(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret; + + if (index < 2) /* PSU1 */ + ret = smf_read_reg16(data, PSU_1_INPUT_VOLTAGE + index * 2); + else /* PSU2 */ + ret = smf_read_reg16(data, PSU_2_INPUT_VOLTAGE + ((index - 2) * 2)); + + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", ret*10); +} + + +static ssize_t show_voltage_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + unsigned status=0; + int ret; + + if (index < 8) { + + if (data->kind == s6100smf) + status = smf_read_reg16(data, CPU_1_MONITOR_STATUS); + else + status = smf_read_reg16(data, CPU_5_MONITOR_STATUS); + + ret = status & (1 << index); + } + else if (index < 15) { + + if (data->kind == s6100smf) + ret = smf_read_reg16(data, CPU_2_MONITOR_STATUS); + else + ret = smf_read_reg16(data, CPU_6_MONITOR_STATUS); + + ret = status & (1 << index); + } + else if (index < 23) { + + if (data->kind == s6100smf) + ret = smf_read_reg16(data, CPU_3_MONITOR_STATUS); + else + ret = smf_read_reg16(data, CPU_7_MONITOR_STATUS); + + ret = status & (1 << index); + } + else { + + if (data->kind == s6100smf) + ret = smf_read_reg16(data, CPU_4_MONITOR_STATUS); + else + ret = smf_read_reg16(data, CPU_8_MONITOR_STATUS); + + ret = status & (1 << index); + } + + + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", ret); +} + + +static umode_t smf_vsen_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct smf_data *data = dev_get_drvdata(dev); + + if (data->vsen_mask & (1 << (n % VSEN_MAX))) + return a->mode; + return 0; +} + +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 0); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 1); +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_voltage, NULL, 2); +static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_voltage, NULL, 3); +static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 4); +static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 5); +static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 6); +static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_voltage, NULL, 7); +static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_voltage, NULL, 8); +static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_voltage, NULL, 9); +static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_voltage, NULL, 10); +static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_voltage, NULL, 11); +static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_voltage, NULL, 12); +static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, show_voltage, NULL, 13); +static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, show_voltage, NULL, 14); +static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_voltage, NULL, 15); +static SENSOR_DEVICE_ATTR(in17_input, S_IRUGO, show_voltage, NULL, 16); +static SENSOR_DEVICE_ATTR(in18_input, S_IRUGO, show_voltage, NULL, 17); +static SENSOR_DEVICE_ATTR(in19_input, S_IRUGO, show_voltage, NULL, 18); +static SENSOR_DEVICE_ATTR(in20_input, S_IRUGO, show_voltage, NULL, 19); +static SENSOR_DEVICE_ATTR(in21_input, S_IRUGO, show_voltage, NULL, 20); +static SENSOR_DEVICE_ATTR(in22_input, S_IRUGO, show_voltage, NULL, 21); +static SENSOR_DEVICE_ATTR(in23_input, S_IRUGO, show_voltage, NULL, 22); +static SENSOR_DEVICE_ATTR(in24_input, S_IRUGO, show_voltage, NULL, 23); +static SENSOR_DEVICE_ATTR(in25_input, S_IRUGO, show_voltage, NULL, 24); +static SENSOR_DEVICE_ATTR(in26_input, S_IRUGO, show_voltage, NULL, 25); +static SENSOR_DEVICE_ATTR(in27_input, S_IRUGO, show_voltage, NULL, 26); +static SENSOR_DEVICE_ATTR(in28_input, S_IRUGO, show_voltage, NULL, 27); + +/* PSU1 Voltage*/ +static SENSOR_DEVICE_ATTR(in29_input, S_IRUGO, show_psu_voltage, NULL, 0); +static SENSOR_DEVICE_ATTR(in30_input, S_IRUGO, show_psu_voltage, NULL, 1); + +/* PSU2 Voltage*/ +static SENSOR_DEVICE_ATTR(in31_input, S_IRUGO, show_psu_voltage, NULL, 2); +static SENSOR_DEVICE_ATTR(in32_input, S_IRUGO, show_psu_voltage, NULL, 3); + +/*IO Modules Voltage*/ +static SENSOR_DEVICE_ATTR(in101_input, S_IRUGO, show_voltage, NULL, 28); +static SENSOR_DEVICE_ATTR(in102_input, S_IRUGO, show_voltage, NULL, 29); +static SENSOR_DEVICE_ATTR(in103_input, S_IRUGO, show_voltage, NULL, 30); +static SENSOR_DEVICE_ATTR(in104_input, S_IRUGO, show_voltage, NULL, 31); +static SENSOR_DEVICE_ATTR(in201_input, S_IRUGO, show_voltage, NULL, 32); +static SENSOR_DEVICE_ATTR(in202_input, S_IRUGO, show_voltage, NULL, 33); +static SENSOR_DEVICE_ATTR(in203_input, S_IRUGO, show_voltage, NULL, 34); +static SENSOR_DEVICE_ATTR(in204_input, S_IRUGO, show_voltage, NULL, 35); +static SENSOR_DEVICE_ATTR(in301_input, S_IRUGO, show_voltage, NULL, 36); +static SENSOR_DEVICE_ATTR(in302_input, S_IRUGO, show_voltage, NULL, 37); +static SENSOR_DEVICE_ATTR(in303_input, S_IRUGO, show_voltage, NULL, 38); +static SENSOR_DEVICE_ATTR(in304_input, S_IRUGO, show_voltage, NULL, 39); +static SENSOR_DEVICE_ATTR(in401_input, S_IRUGO, show_voltage, NULL, 40); +static SENSOR_DEVICE_ATTR(in402_input, S_IRUGO, show_voltage, NULL, 41); +static SENSOR_DEVICE_ATTR(in403_input, S_IRUGO, show_voltage, NULL, 42); +static SENSOR_DEVICE_ATTR(in404_input, S_IRUGO, show_voltage, NULL, 43); + + + +static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_voltage_label, NULL, 0); +static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_voltage_label, NULL, 1); +static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_voltage_label, NULL, 2); +static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_voltage_label, NULL, 3); +static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_voltage_label, NULL, 4); +static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_voltage_label, NULL, 5); +static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_voltage_label, NULL, 6); +static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_voltage_label, NULL, 7); +static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_voltage_label, NULL, 8); +static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, show_voltage_label, NULL, 9); +static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, show_voltage_label, NULL, 10); +static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, show_voltage_label, NULL, 11); +static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, show_voltage_label, NULL, 12); +static SENSOR_DEVICE_ATTR(in14_label, S_IRUGO, show_voltage_label, NULL, 13); +static SENSOR_DEVICE_ATTR(in15_label, S_IRUGO, show_voltage_label, NULL, 14); +static SENSOR_DEVICE_ATTR(in16_label, S_IRUGO, show_voltage_label, NULL, 15); +static SENSOR_DEVICE_ATTR(in17_label, S_IRUGO, show_voltage_label, NULL, 16); +static SENSOR_DEVICE_ATTR(in18_label, S_IRUGO, show_voltage_label, NULL, 17); +static SENSOR_DEVICE_ATTR(in19_label, S_IRUGO, show_voltage_label, NULL, 18); +static SENSOR_DEVICE_ATTR(in20_label, S_IRUGO, show_voltage_label, NULL, 19); +static SENSOR_DEVICE_ATTR(in21_label, S_IRUGO, show_voltage_label, NULL, 20); +static SENSOR_DEVICE_ATTR(in22_label, S_IRUGO, show_voltage_label, NULL, 21); +static SENSOR_DEVICE_ATTR(in23_label, S_IRUGO, show_voltage_label, NULL, 22); +static SENSOR_DEVICE_ATTR(in24_label, S_IRUGO, show_voltage_label, NULL, 23); +static SENSOR_DEVICE_ATTR(in25_label, S_IRUGO, show_voltage_label, NULL, 24); +static SENSOR_DEVICE_ATTR(in26_label, S_IRUGO, show_voltage_label, NULL, 25); +static SENSOR_DEVICE_ATTR(in27_label, S_IRUGO, show_voltage_label, NULL, 26); +static SENSOR_DEVICE_ATTR(in28_label, S_IRUGO, show_voltage_label, NULL, 27); + +/* PSU1 Voltage Label*/ +static SENSOR_DEVICE_ATTR(in29_label, S_IRUGO, show_voltage_label, NULL, 28); +static SENSOR_DEVICE_ATTR(in30_label, S_IRUGO, show_voltage_label, NULL, 29); + +/* PSU2 Voltage Label*/ +static SENSOR_DEVICE_ATTR(in31_label, S_IRUGO, show_voltage_label, NULL, 30); +static SENSOR_DEVICE_ATTR(in32_label, S_IRUGO, show_voltage_label, NULL, 31); + +/*IO Modules Labels*/ +static SENSOR_DEVICE_ATTR(in101_label, S_IRUGO, show_voltage_label, NULL, 32); +static SENSOR_DEVICE_ATTR(in102_label, S_IRUGO, show_voltage_label, NULL, 33); +static SENSOR_DEVICE_ATTR(in103_label, S_IRUGO, show_voltage_label, NULL, 34); +static SENSOR_DEVICE_ATTR(in104_label, S_IRUGO, show_voltage_label, NULL, 35); +static SENSOR_DEVICE_ATTR(in201_label, S_IRUGO, show_voltage_label, NULL, 36); +static SENSOR_DEVICE_ATTR(in202_label, S_IRUGO, show_voltage_label, NULL, 37); +static SENSOR_DEVICE_ATTR(in203_label, S_IRUGO, show_voltage_label, NULL, 38); +static SENSOR_DEVICE_ATTR(in204_label, S_IRUGO, show_voltage_label, NULL, 39); +static SENSOR_DEVICE_ATTR(in301_label, S_IRUGO, show_voltage_label, NULL, 40); +static SENSOR_DEVICE_ATTR(in302_label, S_IRUGO, show_voltage_label, NULL, 41); +static SENSOR_DEVICE_ATTR(in303_label, S_IRUGO, show_voltage_label, NULL, 42); +static SENSOR_DEVICE_ATTR(in304_label, S_IRUGO, show_voltage_label, NULL, 43); +static SENSOR_DEVICE_ATTR(in401_label, S_IRUGO, show_voltage_label, NULL, 44); +static SENSOR_DEVICE_ATTR(in402_label, S_IRUGO, show_voltage_label, NULL, 45); +static SENSOR_DEVICE_ATTR(in403_label, S_IRUGO, show_voltage_label, NULL, 46); +static SENSOR_DEVICE_ATTR(in404_label, S_IRUGO, show_voltage_label, NULL, 47); + + + +/* CPU Voltage Alarm */ +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_voltage_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_voltage_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_voltage_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_voltage_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_voltage_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_voltage_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_voltage_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_voltage_alarm, NULL, 7); + +static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_voltage_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_voltage_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_voltage_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_voltage_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_voltage_alarm, NULL, 12); +static SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_voltage_alarm, NULL, 13); +static SENSOR_DEVICE_ATTR(in15_alarm, S_IRUGO, show_voltage_alarm, NULL, 14); +static SENSOR_DEVICE_ATTR(in16_alarm, S_IRUGO, show_voltage_alarm, NULL, 15); + +static SENSOR_DEVICE_ATTR(in17_alarm, S_IRUGO, show_voltage_alarm, NULL, 16); +static SENSOR_DEVICE_ATTR(in18_alarm, S_IRUGO, show_voltage_alarm, NULL, 17); +static SENSOR_DEVICE_ATTR(in19_alarm, S_IRUGO, show_voltage_alarm, NULL, 18); +static SENSOR_DEVICE_ATTR(in20_alarm, S_IRUGO, show_voltage_alarm, NULL, 19); +static SENSOR_DEVICE_ATTR(in21_alarm, S_IRUGO, show_voltage_alarm, NULL, 20); +static SENSOR_DEVICE_ATTR(in22_alarm, S_IRUGO, show_voltage_alarm, NULL, 21); +static SENSOR_DEVICE_ATTR(in23_alarm, S_IRUGO, show_voltage_alarm, NULL, 22); +static SENSOR_DEVICE_ATTR(in24_alarm, S_IRUGO, show_voltage_alarm, NULL, 23); + +static SENSOR_DEVICE_ATTR(in25_alarm, S_IRUGO, show_voltage_alarm, NULL, 24); +static SENSOR_DEVICE_ATTR(in26_alarm, S_IRUGO, show_voltage_alarm, NULL, 25); +static SENSOR_DEVICE_ATTR(in27_alarm, S_IRUGO, show_voltage_alarm, NULL, 26); +static SENSOR_DEVICE_ATTR(in28_alarm, S_IRUGO, show_voltage_alarm, NULL, 27); + + + +static struct attribute *smf_vsen_attrs[] = { + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in5_input.dev_attr.attr, + &sensor_dev_attr_in6_input.dev_attr.attr, + &sensor_dev_attr_in7_input.dev_attr.attr, + &sensor_dev_attr_in8_input.dev_attr.attr, + &sensor_dev_attr_in9_input.dev_attr.attr, + &sensor_dev_attr_in10_input.dev_attr.attr, + &sensor_dev_attr_in11_input.dev_attr.attr, + &sensor_dev_attr_in12_input.dev_attr.attr, + &sensor_dev_attr_in13_input.dev_attr.attr, + &sensor_dev_attr_in14_input.dev_attr.attr, + &sensor_dev_attr_in15_input.dev_attr.attr, + &sensor_dev_attr_in16_input.dev_attr.attr, + &sensor_dev_attr_in17_input.dev_attr.attr, + &sensor_dev_attr_in18_input.dev_attr.attr, + &sensor_dev_attr_in19_input.dev_attr.attr, + &sensor_dev_attr_in20_input.dev_attr.attr, + &sensor_dev_attr_in21_input.dev_attr.attr, + &sensor_dev_attr_in22_input.dev_attr.attr, + &sensor_dev_attr_in23_input.dev_attr.attr, + &sensor_dev_attr_in24_input.dev_attr.attr, + &sensor_dev_attr_in25_input.dev_attr.attr, + &sensor_dev_attr_in26_input.dev_attr.attr, + &sensor_dev_attr_in27_input.dev_attr.attr, + &sensor_dev_attr_in28_input.dev_attr.attr, + + &sensor_dev_attr_in29_input.dev_attr.attr, + &sensor_dev_attr_in30_input.dev_attr.attr, + &sensor_dev_attr_in31_input.dev_attr.attr, + &sensor_dev_attr_in32_input.dev_attr.attr, + + &sensor_dev_attr_in101_input.dev_attr.attr, + &sensor_dev_attr_in102_input.dev_attr.attr, + &sensor_dev_attr_in103_input.dev_attr.attr, + &sensor_dev_attr_in104_input.dev_attr.attr, + &sensor_dev_attr_in201_input.dev_attr.attr, + &sensor_dev_attr_in202_input.dev_attr.attr, + &sensor_dev_attr_in203_input.dev_attr.attr, + &sensor_dev_attr_in204_input.dev_attr.attr, + &sensor_dev_attr_in301_input.dev_attr.attr, + &sensor_dev_attr_in302_input.dev_attr.attr, + &sensor_dev_attr_in303_input.dev_attr.attr, + &sensor_dev_attr_in304_input.dev_attr.attr, + &sensor_dev_attr_in401_input.dev_attr.attr, + &sensor_dev_attr_in402_input.dev_attr.attr, + &sensor_dev_attr_in403_input.dev_attr.attr, + &sensor_dev_attr_in404_input.dev_attr.attr, + + + &sensor_dev_attr_in1_label.dev_attr.attr, + &sensor_dev_attr_in2_label.dev_attr.attr, + &sensor_dev_attr_in3_label.dev_attr.attr, + &sensor_dev_attr_in4_label.dev_attr.attr, + &sensor_dev_attr_in5_label.dev_attr.attr, + &sensor_dev_attr_in6_label.dev_attr.attr, + &sensor_dev_attr_in7_label.dev_attr.attr, + &sensor_dev_attr_in8_label.dev_attr.attr, + &sensor_dev_attr_in9_label.dev_attr.attr, + &sensor_dev_attr_in10_label.dev_attr.attr, + &sensor_dev_attr_in11_label.dev_attr.attr, + &sensor_dev_attr_in12_label.dev_attr.attr, + &sensor_dev_attr_in13_label.dev_attr.attr, + &sensor_dev_attr_in14_label.dev_attr.attr, + &sensor_dev_attr_in15_label.dev_attr.attr, + &sensor_dev_attr_in16_label.dev_attr.attr, + &sensor_dev_attr_in17_label.dev_attr.attr, + &sensor_dev_attr_in18_label.dev_attr.attr, + &sensor_dev_attr_in19_label.dev_attr.attr, + &sensor_dev_attr_in20_label.dev_attr.attr, + &sensor_dev_attr_in21_label.dev_attr.attr, + &sensor_dev_attr_in22_label.dev_attr.attr, + &sensor_dev_attr_in23_label.dev_attr.attr, + &sensor_dev_attr_in24_label.dev_attr.attr, + &sensor_dev_attr_in25_label.dev_attr.attr, + &sensor_dev_attr_in26_label.dev_attr.attr, + &sensor_dev_attr_in27_label.dev_attr.attr, + &sensor_dev_attr_in28_label.dev_attr.attr, + + &sensor_dev_attr_in29_label.dev_attr.attr, + &sensor_dev_attr_in30_label.dev_attr.attr, + &sensor_dev_attr_in31_label.dev_attr.attr, + &sensor_dev_attr_in32_label.dev_attr.attr, + + &sensor_dev_attr_in101_label.dev_attr.attr, + &sensor_dev_attr_in102_label.dev_attr.attr, + &sensor_dev_attr_in103_label.dev_attr.attr, + &sensor_dev_attr_in104_label.dev_attr.attr, + &sensor_dev_attr_in201_label.dev_attr.attr, + &sensor_dev_attr_in202_label.dev_attr.attr, + &sensor_dev_attr_in203_label.dev_attr.attr, + &sensor_dev_attr_in204_label.dev_attr.attr, + &sensor_dev_attr_in301_label.dev_attr.attr, + &sensor_dev_attr_in302_label.dev_attr.attr, + &sensor_dev_attr_in303_label.dev_attr.attr, + &sensor_dev_attr_in304_label.dev_attr.attr, + &sensor_dev_attr_in401_label.dev_attr.attr, + &sensor_dev_attr_in402_label.dev_attr.attr, + &sensor_dev_attr_in403_label.dev_attr.attr, + &sensor_dev_attr_in404_label.dev_attr.attr, + + + &sensor_dev_attr_in1_alarm.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, + &sensor_dev_attr_in5_alarm.dev_attr.attr, + &sensor_dev_attr_in6_alarm.dev_attr.attr, + &sensor_dev_attr_in7_alarm.dev_attr.attr, + &sensor_dev_attr_in8_alarm.dev_attr.attr, + &sensor_dev_attr_in9_alarm.dev_attr.attr, + &sensor_dev_attr_in10_alarm.dev_attr.attr, + &sensor_dev_attr_in11_alarm.dev_attr.attr, + &sensor_dev_attr_in12_alarm.dev_attr.attr, + &sensor_dev_attr_in13_alarm.dev_attr.attr, + &sensor_dev_attr_in14_alarm.dev_attr.attr, + &sensor_dev_attr_in15_alarm.dev_attr.attr, + &sensor_dev_attr_in16_alarm.dev_attr.attr, + &sensor_dev_attr_in17_alarm.dev_attr.attr, + &sensor_dev_attr_in18_alarm.dev_attr.attr, + &sensor_dev_attr_in19_alarm.dev_attr.attr, + &sensor_dev_attr_in20_alarm.dev_attr.attr, + &sensor_dev_attr_in21_alarm.dev_attr.attr, + &sensor_dev_attr_in22_alarm.dev_attr.attr, + &sensor_dev_attr_in23_alarm.dev_attr.attr, + &sensor_dev_attr_in24_alarm.dev_attr.attr, + &sensor_dev_attr_in25_alarm.dev_attr.attr, + &sensor_dev_attr_in26_alarm.dev_attr.attr, + &sensor_dev_attr_in27_alarm.dev_attr.attr, + &sensor_dev_attr_in28_alarm.dev_attr.attr, + + + NULL +}; + +static const struct attribute_group smf_vsen_group = { + .attrs = smf_vsen_attrs, + .is_visible = smf_vsen_is_visible, +}; + +/* CURRENT ATTR */ +static ssize_t +show_current_label(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct smf_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%s\n", data->curr_label[nr]); +} + +static ssize_t show_current(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret=0; + int curr; + + if (index < CURR22_INPUT) + if (data->kind == s6100smf) + ret = smf_read_reg16(data, SWITCH_CURRENT_S6100 + index * 2); + else + ret = smf_read_reg16(data, SWITCH_CURRENT_Z9100 + index * 2); + else if (index < CURR602_INPUT) + curr = smf_read_reg16(data, PSU_1_INPUT_CURRENT + (index % 4) * 2); + else + curr = smf_read_reg16(data, PSU_2_INPUT_CURRENT + (index % 4) * 2); + + + if (ret < 0) + return ret; + + /* TODO: docs say 10mA, value look like A? */ + if(index < 2) + curr = ret*1000; + + return sprintf(buf, "%d\n", curr); +} + + +static umode_t smf_curr_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct smf_data *data = dev_get_drvdata(dev); + + if (data->curr_mask & (1 << (n % CURR_MAX))) + return a->mode; + return 0; +} + + +static SENSOR_DEVICE_ATTR(curr21_input, S_IRUGO, show_current, NULL, 0); +static SENSOR_DEVICE_ATTR(curr22_input, S_IRUGO, show_current, NULL, 1); + +static SENSOR_DEVICE_ATTR(curr601_input, S_IRUGO, show_current, NULL, 2); +static SENSOR_DEVICE_ATTR(curr602_input, S_IRUGO, show_current, NULL, 3); + +static SENSOR_DEVICE_ATTR(curr701_input, S_IRUGO, show_current, NULL, 4); +static SENSOR_DEVICE_ATTR(curr702_input, S_IRUGO, show_current, NULL, 5); + +static SENSOR_DEVICE_ATTR(curr21_label, S_IRUGO, show_current_label, NULL, 0); +static SENSOR_DEVICE_ATTR(curr22_label, S_IRUGO, show_current_label, NULL, 1); + +static SENSOR_DEVICE_ATTR(curr601_label, S_IRUGO, show_current_label, NULL, 2); +static SENSOR_DEVICE_ATTR(curr602_label, S_IRUGO, show_current_label, NULL, 3); + +static SENSOR_DEVICE_ATTR(curr701_label, S_IRUGO, show_current_label, NULL, 4); +static SENSOR_DEVICE_ATTR(curr702_label, S_IRUGO, show_current_label, NULL, 5); + + +static struct attribute *smf_curr_attrs[] = { + &sensor_dev_attr_curr21_input.dev_attr.attr, + &sensor_dev_attr_curr22_input.dev_attr.attr, + + &sensor_dev_attr_curr601_input.dev_attr.attr, + &sensor_dev_attr_curr602_input.dev_attr.attr, + + &sensor_dev_attr_curr701_input.dev_attr.attr, + &sensor_dev_attr_curr702_input.dev_attr.attr, + + &sensor_dev_attr_curr21_label.dev_attr.attr, + &sensor_dev_attr_curr22_label.dev_attr.attr, + + &sensor_dev_attr_curr601_label.dev_attr.attr, + &sensor_dev_attr_curr602_label.dev_attr.attr, + + &sensor_dev_attr_curr701_label.dev_attr.attr, + &sensor_dev_attr_curr702_label.dev_attr.attr, + + NULL +}; + + +static const struct attribute_group smf_curr_group = { + .attrs = smf_curr_attrs, + .is_visible = smf_curr_is_visible, +}; + + +/* CPU_TEMP ATTR */ +static ssize_t +show_temp_label(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct smf_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%s\n", data->temp_label[nr]); +} + + +static ssize_t show_tcpu(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret; + int temp; + + if (index < TEMP13_INPUT) /* Temp sensors */ + ret = smf_read_reg16(data, TEMP_SENSOR_1 + index * 2); + else if(index < TEMP601_INPUT) + ret = smf_read_reg16(data, PSU_1_TEMPERATURE); + else + ret = smf_read_reg16(data, PSU_2_TEMPERATURE); + + if (ret < 0) + return ret; + + if (ret > 65500) + ret = 0; + + if (ret & 0x8000) + ret = - (ret & 0x7fff); + + temp = ret*100; + + return sprintf(buf, "%d\n", temp); +} + + +static ssize_t show_temp_crit(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret; + int temp; + + ret = smf_read_reg16(data, TEMP_SENSOR_1_HW_LIMIT + index * 2); + if (ret < 0) + return ret; + + if (ret == 65535) + ret = 0; + + if (ret & 0x8000) + ret = - (ret & 0x7fff); + + temp = ret*100; + + return sprintf(buf, "%d\n", temp); +} + + +/*static ssize_t show_temp_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret; + int temp; + + ret = smf_read_reg16(data, TEMP_SENSOR_1_STATUS + index * 2); + + if (ret < 0) + return ret; + + temp = ret; + + return sprintf(buf, "%d\n", temp); +}*/ + + +static umode_t smf_tcpu_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct smf_data *data = dev_get_drvdata(dev); + + if (data->tcpu_mask & (1 << (n % TCPU_MAX))) + return a->mode; + + return 0; +} + + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_tcpu, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_tcpu, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_tcpu, NULL, 2); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_tcpu, NULL, 3); +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_tcpu, NULL, 4); +static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_tcpu, NULL, 5); +static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_tcpu, NULL, 6); +static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_tcpu, NULL, 7); +static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_tcpu, NULL, 8); +static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_tcpu, NULL, 9); +static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO, show_tcpu, NULL, 10); +static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO, show_tcpu, NULL, 11); +static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO, show_tcpu, NULL, 12); + +/* PSU1 Fan Temp */ +static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO, show_tcpu, NULL, 13); + +/* PSU2 Fan Temp */ +static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO, show_tcpu, NULL, 14); + +static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2); +static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3); +static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, show_temp_label, NULL, 4); +static SENSOR_DEVICE_ATTR(temp6_label, S_IRUGO, show_temp_label, NULL, 5); +static SENSOR_DEVICE_ATTR(temp7_label, S_IRUGO, show_temp_label, NULL, 6); +static SENSOR_DEVICE_ATTR(temp8_label, S_IRUGO, show_temp_label, NULL, 7); +static SENSOR_DEVICE_ATTR(temp9_label, S_IRUGO, show_temp_label, NULL, 8); +static SENSOR_DEVICE_ATTR(temp10_label, S_IRUGO, show_temp_label, NULL, 9); +static SENSOR_DEVICE_ATTR(temp11_label, S_IRUGO, show_temp_label, NULL, 10); +static SENSOR_DEVICE_ATTR(temp12_label, S_IRUGO, show_temp_label, NULL, 11); +static SENSOR_DEVICE_ATTR(temp13_label, S_IRUGO, show_temp_label, NULL, 12); + +static SENSOR_DEVICE_ATTR(temp14_label, S_IRUGO, show_temp_label, NULL, 14); +static SENSOR_DEVICE_ATTR(temp15_label, S_IRUGO, show_temp_label, NULL, 15); + + +static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 1); +static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 5); +static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 9); +static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 13); +static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 17); +static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 21); +static SENSOR_DEVICE_ATTR(temp7_crit, S_IRUGO, show_temp_crit, NULL, 25); +static SENSOR_DEVICE_ATTR(temp8_crit, S_IRUGO, show_temp_crit, NULL, 29); +static SENSOR_DEVICE_ATTR(temp9_crit, S_IRUGO, show_temp_crit, NULL, 33); +static SENSOR_DEVICE_ATTR(temp10_crit, S_IRUGO, show_temp_crit, NULL, 37); +static SENSOR_DEVICE_ATTR(temp11_crit, S_IRUGO, show_temp_crit, NULL, 41); +static SENSOR_DEVICE_ATTR(temp12_crit, S_IRUGO, show_temp_crit, NULL, 45); +static SENSOR_DEVICE_ATTR(temp13_crit, S_IRUGO, show_temp_crit, NULL, 49); + +static SENSOR_DEVICE_ATTR(temp14_crit, S_IRUGO, show_temp_crit, NULL, 11); +static SENSOR_DEVICE_ATTR(temp15_crit, S_IRUGO, show_temp_crit, NULL, 11); + + +static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_crit, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_crit, NULL, 6); +static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_crit, NULL, 10); +static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_crit, NULL, 14); +static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_crit, NULL, 18); +static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_crit, NULL, 22); +static SENSOR_DEVICE_ATTR(temp7_max, S_IRUGO, show_temp_crit, NULL, 26); +static SENSOR_DEVICE_ATTR(temp8_max, S_IRUGO, show_temp_crit, NULL, 30); +static SENSOR_DEVICE_ATTR(temp9_max, S_IRUGO, show_temp_crit, NULL, 34); +static SENSOR_DEVICE_ATTR(temp10_max, S_IRUGO, show_temp_crit, NULL, 38); +static SENSOR_DEVICE_ATTR(temp11_max, S_IRUGO, show_temp_crit, NULL, 42); +static SENSOR_DEVICE_ATTR(temp12_max, S_IRUGO, show_temp_crit, NULL, 46); +static SENSOR_DEVICE_ATTR(temp13_max, S_IRUGO, show_temp_crit, NULL, 50); + +static SENSOR_DEVICE_ATTR(temp14_max, S_IRUGO, show_temp_crit, NULL, 46); +static SENSOR_DEVICE_ATTR(temp15_max, S_IRUGO, show_temp_crit, NULL, 50); + + +static struct attribute *smf_tcpu_attrs[] = { + &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_temp6_input.dev_attr.attr, + &sensor_dev_attr_temp7_input.dev_attr.attr, + &sensor_dev_attr_temp8_input.dev_attr.attr, + &sensor_dev_attr_temp9_input.dev_attr.attr, + &sensor_dev_attr_temp10_input.dev_attr.attr, + &sensor_dev_attr_temp11_input.dev_attr.attr, + &sensor_dev_attr_temp12_input.dev_attr.attr, + &sensor_dev_attr_temp13_input.dev_attr.attr, + &sensor_dev_attr_temp14_input.dev_attr.attr, + &sensor_dev_attr_temp15_input.dev_attr.attr, + + &sensor_dev_attr_temp1_label.dev_attr.attr, + &sensor_dev_attr_temp2_label.dev_attr.attr, + &sensor_dev_attr_temp3_label.dev_attr.attr, + &sensor_dev_attr_temp4_label.dev_attr.attr, + &sensor_dev_attr_temp5_label.dev_attr.attr, + &sensor_dev_attr_temp6_label.dev_attr.attr, + &sensor_dev_attr_temp7_label.dev_attr.attr, + &sensor_dev_attr_temp8_label.dev_attr.attr, + &sensor_dev_attr_temp9_label.dev_attr.attr, + &sensor_dev_attr_temp10_label.dev_attr.attr, + &sensor_dev_attr_temp11_label.dev_attr.attr, + &sensor_dev_attr_temp12_label.dev_attr.attr, + &sensor_dev_attr_temp13_label.dev_attr.attr, + &sensor_dev_attr_temp14_label.dev_attr.attr, + &sensor_dev_attr_temp15_label.dev_attr.attr, + + &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp2_crit.dev_attr.attr, + &sensor_dev_attr_temp3_crit.dev_attr.attr, + &sensor_dev_attr_temp4_crit.dev_attr.attr, + &sensor_dev_attr_temp5_crit.dev_attr.attr, + &sensor_dev_attr_temp6_crit.dev_attr.attr, + &sensor_dev_attr_temp7_crit.dev_attr.attr, + &sensor_dev_attr_temp8_crit.dev_attr.attr, + &sensor_dev_attr_temp9_crit.dev_attr.attr, + &sensor_dev_attr_temp10_crit.dev_attr.attr, + &sensor_dev_attr_temp11_crit.dev_attr.attr, + &sensor_dev_attr_temp12_crit.dev_attr.attr, + &sensor_dev_attr_temp13_crit.dev_attr.attr, + &sensor_dev_attr_temp14_crit.dev_attr.attr, + &sensor_dev_attr_temp15_crit.dev_attr.attr, + + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp4_max.dev_attr.attr, + &sensor_dev_attr_temp5_max.dev_attr.attr, + &sensor_dev_attr_temp6_max.dev_attr.attr, + &sensor_dev_attr_temp7_max.dev_attr.attr, + &sensor_dev_attr_temp8_max.dev_attr.attr, + &sensor_dev_attr_temp9_max.dev_attr.attr, + &sensor_dev_attr_temp10_max.dev_attr.attr, + &sensor_dev_attr_temp11_max.dev_attr.attr, + &sensor_dev_attr_temp12_max.dev_attr.attr, + &sensor_dev_attr_temp13_max.dev_attr.attr, + &sensor_dev_attr_temp14_max.dev_attr.attr, + &sensor_dev_attr_temp15_max.dev_attr.attr, + + NULL +}; + + +static const struct attribute_group smf_tcpu_group = { + .attrs = smf_tcpu_attrs, + .is_visible = smf_tcpu_is_visible, +}; + + +/* PSU ATTR */ +static ssize_t +show_psu_label(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct smf_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%s\n", data->psu_label[nr]); +} + + +static ssize_t show_psu(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret=0, export_hex=0; + int psu_status=0, pow; + + switch (index) { + + case 0: + pow = smf_read_reg16(data, PSU_1_MAX_POWER); + /* TODO Fix */ + if (data->kind == s6100smf) + ret = 1000000 * 1100; + else + ret = 1000000 * 750; + break; + case 1: + ret = smf_read_reg(data, PSU_1_STATUS); + export_hex=1; + break; + case 2: + ret = 100000 * smf_read_reg16(data, PSU_1_INPUT_POWER); + break; + case 3: + ret = 100000 * smf_read_reg16(data, PSU_1_OUTPUT_POWER); + break; + case 4: + psu_status = smf_read_reg(data, PSU_1_STATUS); + if (psu_status &(1)) + ret=1; + break; + case 5: + pow = smf_read_reg16(data, PSU_2_MAX_POWER); + ret = 1000000 * pow; + /* TODO Fix */ + if (data->kind == s6100smf) + ret = 1000000 * 1100; + else + ret = 1000000 * 750; + break; + case 6: + ret = smf_read_reg(data, PSU_2_STATUS); + export_hex=1; + break; + case 7: + ret = 100000 * smf_read_reg16(data, PSU_2_INPUT_POWER); + break; + case 8: + ret = 100000 * smf_read_reg16(data, PSU_2_OUTPUT_POWER); + break; + case 9: + psu_status = smf_read_reg(data, PSU_2_STATUS); + if (psu_status &(1)) + ret=1; + break; + case 10: + pow = smf_read_reg16(data, CURRENT_TOTAL_POWER); + ret = pow/10; + break; + default: + return ret; + } + + if (ret < 0) + return ret; + + pow = ret; + + if(export_hex) + return sprintf(buf, "%x\n", pow); + else + return sprintf(buf, "%u\n", pow); +} + + +static umode_t smf_psu_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct smf_data *data = dev_get_drvdata(dev); + + if (data->psu_mask & (1 << (n % PSU_MAX))) + return a->mode; + return 0; +} + +/* PSU */ +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_psu, NULL, 2); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_psu, NULL, 3); +static SENSOR_DEVICE_ATTR(power3_input, S_IRUGO, show_psu, NULL, 7); +static SENSOR_DEVICE_ATTR(power4_input, S_IRUGO, show_psu, NULL, 8); + +static SENSOR_DEVICE_ATTR(power1_label, S_IRUGO, show_psu_label, NULL, 0); +static SENSOR_DEVICE_ATTR(power2_label, S_IRUGO, show_psu_label, NULL, 1); +static SENSOR_DEVICE_ATTR(power3_label, S_IRUGO, show_psu_label, NULL, 2); +static SENSOR_DEVICE_ATTR(power4_label, S_IRUGO, show_psu_label, NULL, 3); + +static SENSOR_DEVICE_ATTR(power1_max, S_IRUGO, show_psu, NULL, 0); +static SENSOR_DEVICE_ATTR(power2_max, S_IRUGO, show_psu, NULL, 0); +static SENSOR_DEVICE_ATTR(power3_max, S_IRUGO, show_psu, NULL, 5); +static SENSOR_DEVICE_ATTR(power4_max, S_IRUGO, show_psu, NULL, 5); + + +/* PSU2 */ +//static SENSOR_DEVICE_ATTR(power602_alarm, S_IRUGO, show_psu, NULL, 4); +//static SENSOR_DEVICE_ATTR(power702_alarm, S_IRUGO, show_psu, NULL, 9); + + + +static struct attribute *smf_psu_attrs[] = { + + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_power3_input.dev_attr.attr, + &sensor_dev_attr_power4_input.dev_attr.attr, + + &sensor_dev_attr_power1_label.dev_attr.attr, + &sensor_dev_attr_power2_label.dev_attr.attr, + &sensor_dev_attr_power3_label.dev_attr.attr, + &sensor_dev_attr_power4_label.dev_attr.attr, + + &sensor_dev_attr_power1_max.dev_attr.attr, + &sensor_dev_attr_power2_max.dev_attr.attr, + &sensor_dev_attr_power3_max.dev_attr.attr, + &sensor_dev_attr_power4_max.dev_attr.attr, + + NULL +}; + + +static const struct attribute_group smf_psu_group = { + .attrs = smf_psu_attrs, + .is_visible = smf_psu_is_visible, +}; + + +static const struct attribute_group smf_fanin_group = { + .attrs = smf_fanin_attrs, + .is_visible = smf_fanin_is_visible, +}; + + +static SENSOR_DEVICE_ATTR(fan_tray_presence, S_IRUGO, show_fan, NULL, 12); +static SENSOR_DEVICE_ATTR(fan1_airflow, S_IRUGO, show_fan_airflow, NULL, 0); +static SENSOR_DEVICE_ATTR(fan3_airflow, S_IRUGO, show_fan_airflow, NULL, 1); +static SENSOR_DEVICE_ATTR(fan5_airflow, S_IRUGO, show_fan_airflow, NULL, 2); +static SENSOR_DEVICE_ATTR(fan7_airflow, S_IRUGO, show_fan_airflow, NULL, 3); +static SENSOR_DEVICE_ATTR(fan9_airflow, S_IRUGO, show_fan_airflow, NULL, 4); +static SENSOR_DEVICE_ATTR(fan11_airflow, S_IRUGO, show_psu_fan, NULL, 0); +static SENSOR_DEVICE_ATTR(fan12_airflow, S_IRUGO, show_psu_fan, NULL, 3); +/* IOM status */ +static SENSOR_DEVICE_ATTR(iom_status, S_IRUGO, show_voltage, NULL, 44); +static SENSOR_DEVICE_ATTR(iom_presence, S_IRUGO, show_voltage, NULL, 45); + +static SENSOR_DEVICE_ATTR(psu1_presence, S_IRUGO, show_psu, NULL, 1); +static SENSOR_DEVICE_ATTR(psu2_presence, S_IRUGO, show_psu, NULL, 6); +static SENSOR_DEVICE_ATTR(current_total_power, S_IRUGO, show_psu, NULL, 10); + +static struct attribute *smf_dell_attrs[] = { + &sensor_dev_attr_fan_tray_presence.dev_attr.attr, + &sensor_dev_attr_fan1_airflow.dev_attr.attr, + &sensor_dev_attr_fan3_airflow.dev_attr.attr, + &sensor_dev_attr_fan5_airflow.dev_attr.attr, + &sensor_dev_attr_fan7_airflow.dev_attr.attr, + &sensor_dev_attr_fan9_airflow.dev_attr.attr, + &sensor_dev_attr_fan11_airflow.dev_attr.attr, + &sensor_dev_attr_fan12_airflow.dev_attr.attr, + &sensor_dev_attr_iom_status.dev_attr.attr, + &sensor_dev_attr_iom_presence.dev_attr.attr, + &sensor_dev_attr_psu1_presence.dev_attr.attr, + &sensor_dev_attr_psu2_presence.dev_attr.attr, + &sensor_dev_attr_current_total_power.dev_attr.attr, + NULL +}; + +static const struct attribute_group smf_dell_group = { + .attrs = smf_dell_attrs, + .is_visible = smf_dell_is_visible, +}; + + +static const struct attribute_group *smf_groups[] = { + &smf_psu_group, + &smf_fanin_group, + &smf_vsen_group, + &smf_curr_group, + &smf_tcpu_group, + &smf_dell_group, + NULL +}; + + + +static int smf_probe(struct platform_device *pdev) +{ + struct smf_data *data; + struct device *dev = &pdev->dev; + struct smf_sio_data *sio_data = dev_get_platdata(dev); + struct resource *res; + int err = 0; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!request_region(res->start, IOREGION_LENGTH, + smf_devices[sio_data->kind].name)) { + err = -EBUSY; + dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", + (unsigned long)res->start, + (unsigned long)res->start + IOREGION_LENGTH - 1); + return err; + } + + data = devm_kzalloc(dev, sizeof(struct smf_data), GFP_KERNEL); + /* TODO Use probe address value */ + data->addr = SMF_PROBE_ADDR; + data->kind = sio_data->kind; + + if (!data) + return -ENOMEM; + + mutex_init(&data->lock); + + /* PSU attributes */ + data->psu_mask = smf_devices[data->kind].psu_mask; + data->psu_label = smf_devices[data->kind].psu_label; + + /* FANIN attributes */ + data->fanin_mask = smf_devices[data->kind].fanin_mask; + data->fan_label = smf_devices[data->kind].fan_label; + + /* VSEN attributes */ + data->vsen_mask = smf_devices[data->kind].vsen_mask; + data->vsen_label = smf_devices[data->kind].vsen_label; + + /* CURR attributes */ + data->curr_mask = smf_devices[data->kind].curr_mask; + data->curr_label = smf_devices[data->kind].curr_label; + + /* CPU_TEMP attributes */ + data->tcpu_mask = smf_devices[data->kind].tcpu_mask; + data->temp_label = smf_devices[data->kind].temp_label; + + data->hwmon_dev = devm_hwmon_device_register_with_groups(dev, + smf_devices[data->kind].name, + data, smf_groups); + + return PTR_ERR_OR_ZERO(data->hwmon_dev); +} + + +static int smf_remove(struct platform_device *pdev) +{ + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + release_region(res->start, IOREGION_LENGTH); + return 0; +} + + +static struct platform_driver smf_driver = { + .driver = { + .name = "SMF", + }, + .probe = smf_probe, + .remove = smf_remove +}; + +int __init +smf_find(int sioaddr, unsigned short *addr, struct smf_sio_data *sio_data) +{ + + int val; + + if (force_id) + val = force_id; + else + val = inb(sioaddr + SIO_REG_DEVID); + + switch (val) { + case SIO_Z9100_ID: + sio_data->kind = z9100smf; + break; + case SIO_S6100_ID: + sio_data->kind = s6100smf; + break; + + default: + if (val != 0xffff) + pr_debug("unsupported chip ID: 0x%04x\n", val); + return -ENODEV; + } + + /* TODO Use define, should this be 0x200 or 0x210??? */ + *addr = sioaddr; + + pr_info("Found %s chip at %#x\n", smf_devices[sio_data->kind].name, *addr); + sio_data->sioreg = sioaddr; + + return (0); +} + + +/* + * when Super-I/O functions move to a separate file, the Super-I/O + * bus will manage the lifetime of the device and this module will only keep + * track of the smf driver. But since we platform_device_alloc(), we + * must keep track of the device + */ +static struct platform_device *pdev; + +static int __init sensors_smf_init(void) +{ + int err; + unsigned short address; + struct resource res; + struct smf_sio_data sio_data; + + /* + * initialize sio_data->kind and sio_data->sioreg. + * when Super-I/O functions move to a separate file, the Super-I/O + * driver will probe and auto-detect the presence of a + * smf hardware monitor, and call probe() + */ + + if (smf_find(SMF_REG_ADDR, &address, &sio_data)) + return -ENODEV; + + err = platform_driver_register(&smf_driver); + if (err) + goto exit; + + pdev = platform_device_alloc(SIO_DRVNAME, address); + if (!pdev) { + err = -ENOMEM; + pr_err("Device allocation failed\n"); + goto exit_unregister; + } + + err = platform_device_add_data(pdev, &sio_data, + sizeof(struct smf_sio_data)); + if (err) { + pr_err("Platform data allocation failed\n"); + goto exit_device_put; + } + + memset(&res, 0, sizeof(res)); + res.name = SIO_DRVNAME; + res.start = address + IOREGION_OFFSET; + res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; + res.flags = IORESOURCE_IO; + + err = acpi_check_resource_conflict(&res); + if (err) + goto exit_device_put; + + err = platform_device_add_resources(pdev, &res, 1); + if (err) { + pr_err("Device resource addition failed (%d)\n", err); + goto exit_device_put; + } + + /* platform_device_add calls probe() */ + err = platform_device_add(pdev); + if (err) { + pr_err("Device addition failed (%d)\n", err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); +exit_unregister: + platform_driver_unregister(&smf_driver); +exit: + return err; +} + + +static void __exit sensors_smf_exit(void) +{ + platform_device_unregister(pdev); + platform_driver_unregister(&smf_driver); + + /*Remove sysfs dell_kobj*/ + kobject_put(dell_kobj); +} + + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SMF driver"); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); +MODULE_AUTHOR("Per Fremrot "); +MODULE_AUTHOR("Paavaanan "); + +module_init(sensors_smf_init); +module_exit(sensors_smf_exit); diff --git a/platform/broadcom/sonic-platform-modules-dell/common/fstrim.service b/platform/broadcom/sonic-platform-modules-dell/common/fstrim.service new file mode 100644 index 000000000000..cf740d3af34d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/fstrim.service @@ -0,0 +1,6 @@ +[Unit] +Description=Discard unused blocks + +[Service] +Type=oneshot +ExecStart=/sbin/fstrim -av diff --git a/platform/broadcom/sonic-platform-modules-dell/common/fstrim.timer b/platform/broadcom/sonic-platform-modules-dell/common/fstrim.timer new file mode 100644 index 000000000000..c6142dd94826 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/fstrim.timer @@ -0,0 +1,12 @@ +[Unit] +Description=Discard unused blocks once a week +Documentation=man:fstrim + +[Timer] +OnCalendar=weekly +OnBootSec=10min +AccuracySec=1h +Persistent=true + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/changelog b/platform/broadcom/sonic-platform-modules-dell/debian/changelog new file mode 100644 index 000000000000..90fed6f6d847 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/changelog @@ -0,0 +1,11 @@ +sonic-dell-platform-modules (1.1) unstable; urgency=low + + * Add support for Dell S6100 + + -- Dell Team Wed, 08 Feb 2017 15:57:40 -0800 + +sonic-dell-platform-modules (1.0) unstable; urgency=low + + * Initial release + + -- Dell Team Mon, 6 Feb 2017 10:10:10 -0800 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/compat b/platform/broadcom/sonic-platform-modules-dell/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/control b/platform/broadcom/sonic-platform-modules-dell/debian/control new file mode 100644 index 000000000000..15a88931c1c3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/control @@ -0,0 +1,22 @@ +Source: sonic-dell-platform-modules +Section: main +Priority: extra +Maintainer: Dell Team +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-z9264f +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-z9100 +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-s6100 +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.init b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.init new file mode 100755 index 000000000000..c798b24ef235 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.init @@ -0,0 +1,40 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S6100 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + /usr/local/bin/iom_power_on.sh + /usr/local/bin/s6100_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/s6100_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-s6100.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.install b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.install new file mode 100644 index 000000000000..7d56aee6e2f7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.install @@ -0,0 +1,9 @@ +s6100/scripts/io_rd_wr.py usr/local/bin +s6100/scripts/iom_power_*.sh usr/local/bin +s6100/scripts/s6100_platform.sh usr/local/bin +common/dell_i2c_utils.sh usr/local/bin +common/fstrim.timer etc/systemd/system +common/fstrim.service etc/systemd/system +s6100/scripts/platform_sensors.py usr/local/bin +s6100/scripts/sensors usr/bin +s6100/systemd/platform-modules-s6100.service etc/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.postinst b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.postinst new file mode 100644 index 000000000000..1c220633451d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.postinst @@ -0,0 +1,11 @@ +# postinst script for S6100 + +# Enable fstrim +systemctl enable fstrim.timer +systemctl start fstrim.timer + +# Enable Dell-S6100-platform-service +depmod -a +systemctl enable platform-modules-s6100.service +systemctl start platform-modules-s6100.service +#DEBHELPER# diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.init b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.init new file mode 100755 index 000000000000..aefecf1d8158 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.init @@ -0,0 +1,40 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Z9100 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + # /usr/local/bin/iom_power_on.sh + /usr/local/bin/z9100_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/z9100_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-z9100.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.install b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.install new file mode 100644 index 000000000000..410dcf16ea1b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.install @@ -0,0 +1,9 @@ +z9100/scripts/check_qsfp.sh usr/local/bin +z9100/scripts/z9100_platform.sh usr/local/bin +common/dell_i2c_utils.sh usr/local/bin +common/fstrim.timer etc/systemd/system +common/fstrim.service etc/systemd/system +z9100/scripts/platform_sensors.py usr/local/bin +z9100/scripts/sensors usr/bin +z9100/cfg/z9100-modules.conf etc/modules-load.d +z9100/systemd/platform-modules-z9100.service etc/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.postinst b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.postinst new file mode 100644 index 000000000000..61039dcd70d3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.postinst @@ -0,0 +1,13 @@ +# postinst script for Z9100 + +# Enable fstrim +systemctl enable fstrim.timer +systemctl start fstrim.timer + +# Enable Dell-Z9100-platform-service +depmod -a +systemctl enable platform-modules-z9100.service +systemctl start platform-modules-z9100.service + + +#DEBHELPER# diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.init b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.init new file mode 100755 index 000000000000..cc83662e7746 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.init @@ -0,0 +1,40 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Z9264f board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + # /usr/local/bin/iom_power_on.sh + /usr/local/bin/z9264f_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/z9100_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-z9264f.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.install b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.install new file mode 100644 index 000000000000..7887399e4964 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.install @@ -0,0 +1,6 @@ +z9264f/scripts/z9264f_platform.sh usr/local/bin +z9264f/scripts/check_qsfp.sh usr/local/bin +z9264f/scripts/platform_sensors.py usr/local/bin +z9264f/scripts/sensors usr/bin +z9264f/scripts/pcisysfs.py usr/bin +z9264f/cfg/z9264f-modules.conf etc/modules-load.d diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/rules b/platform/broadcom/sonic-platform-modules-dell/debian/rules new file mode 100755 index 000000000000..860e46bf7005 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/rules @@ -0,0 +1,49 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= s6100 z9100 z9264f +COMMON_DIR := common + +%: + dh $@ + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + if [ $$mod = "s6100" ]; then \ + cp $(COMMON_DIR)/dell_pmc.c $(MOD_SRC_DIR)/$${mod}/modules/dell_s6100_lpc.c; \ + cp $(COMMON_DIR)/dell_ich.c $(MOD_SRC_DIR)/$${mod}/modules/dell_ich.c; \ + elif [ $$mod = "z9100" ]; then \ + cp $(COMMON_DIR)/dell_pmc.c $(MOD_SRC_DIR)/$${mod}/modules/dell_mailbox.c; \ + cp $(COMMON_DIR)/dell_ich.c $(MOD_SRC_DIR)/$${mod}/modules/dell_ich.c; \ + fi; \ + echo "making man page alias $$mod -> $$mod APIs";\ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -pplatform-modules-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + if [ $$mod = "s6100" ]; then \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/dell_s6100_lpc.c; \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/dell_ich.c; \ + elif [ $$mod = "z9100" ]; then \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/dell_mailbox.c; \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/dell_ich.c; \ + fi; \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/modules/Makefile b/platform/broadcom/sonic-platform-modules-dell/s6100/modules/Makefile new file mode 100644 index 000000000000..63242a5cf123 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := dell_s6100_iom_cpld.o dell_s6100_lpc.o dell_ich.o + diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/modules/dell_s6100_iom_cpld.c b/platform/broadcom/sonic-platform-modules-dell/s6100/modules/dell_s6100_iom_cpld.c new file mode 100644 index 000000000000..7b9cf77a448e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/modules/dell_s6100_iom_cpld.c @@ -0,0 +1,484 @@ + +#include // included for all kernel modules +#include // included for KERN_INFO +#include // included for __init and __exit macros +#include +#include +#include +#include + + +//iom cpld slave address +#define IOM_CPLD_SLAVE_ADD 0x3e + +//iom cpld ver register +#define IOM_CPLD_SLAVE_VER 0x00 + +//qsfp reset cntrl reg on each iom +#define QSFP_RST_CRTL_REG0 0x10 +#define QSFP_RST_CRTL_REG1 0x11 + +//qsfp lp mode reg on each iom +#define QSFP_LPMODE_REG0 0x12 +#define QSFP_LPMODE_REG1 0x13 + +//qsfp mod presence reg on each iom +#define QSFP_MOD_PRS_REG0 0x16 +#define QSFP_MOD_PRS_REG1 0x17 + +//qsfp interrupt registers +#define QSFP_INT_STA_REG0 0x14 +#define QSFP_INT_STA_REG1 0x15 +#define QSFP_ABS_STA_REG0 0x16 +#define QSFP_ABS_STA_REG1 0x17 +#define QSFP_TRIG_MOD 0x20 +#define QSFP_INT_COMBINE 0x21 +#define QSFP_INT0 0x22 +#define QSFP_INT1 0x23 +#define QSFP_ABS_INT0 0x24 +#define QSFP_ABS_INT1 0x25 +#define QSFP_INT_MASK0 0x26 +#define QSFP_INT_MASK1 0x27 +#define QSFP_ABS_MASK0 0x28 +#define QSFP_ABS_MASK1 0x29 + +struct cpld_data { + struct i2c_client *client; + struct mutex update_lock; +}; + + +static void dell_s6100_iom_cpld_add_client(struct i2c_client *client) +{ + struct cpld_data *data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + + if (!data) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); +} + +static void dell_s6100_iom_cpld_remove_client(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + kfree(data); + return; +} + +int dell_s6100_iom_cpld_read(struct cpld_data *data,unsigned short cpld_addr, u8 reg) +{ + int ret = -EPERM; + u8 high_reg =0x00; + + mutex_lock(&data->update_lock); + ret = i2c_smbus_write_byte_data(data->client, high_reg,reg); + ret = i2c_smbus_read_byte(data->client); + mutex_unlock(&data->update_lock); + + return ret; +} + +int dell_s6100_iom_cpld_write(struct cpld_data *data,unsigned short cpld_addr, u8 reg, u8 value) +{ + int ret = -EIO; + u16 devdata=0; + u8 high_reg =0x00; + + mutex_lock(&data->update_lock); + devdata = (value << 8) | reg; + i2c_smbus_write_word_data(data->client,high_reg,devdata); + mutex_unlock(&data->update_lock); + + return ret; +} +static ssize_t get_cpldver(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,IOM_CPLD_SLAVE_VER); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u8)ret & 0xff; + return sprintf(buf,"IOM CPLD Version:0x%02x\n",devdata); +} + +static ssize_t get_modprs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_MOD_PRS_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_MOD_PRS_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_LPMODE_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_LPMODE_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_RST_CRTL_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_RST_CRTL_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_LPMODE_REG0,(u8)(devdata & 0xff)); + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_LPMODE_REG1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_RST_CRTL_REG0,(u8)(devdata & 0xff)); + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_RST_CRTL_REG1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static ssize_t get_int_sta(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_STA_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_STA_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_abs_sta(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_STA_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_STA_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_trig_mod(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_TRIG_MOD); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u8)ret & 0xff; + return sprintf(buf,"0x%02x\n",devdata); +} + +static ssize_t set_trig_mod(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_TRIG_MOD,(u8)(devdata & 0xff)); + + return count; +} + +static ssize_t get_int_combine(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_COMBINE); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u8)ret & 0xff; + return sprintf(buf,"0x%02x\n",devdata); +} + +static ssize_t get_int(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_abs_int(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_INT0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_INT1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_int_mask(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_MASK0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_MASK1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t set_int_mask(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_MASK0,(u8)(devdata & 0xff)); + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_MASK1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static ssize_t get_abs_mask(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_MASK0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_MASK1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t set_abs_mask(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_MASK0,(u8)(devdata & 0xff)); + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_MASK1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static DEVICE_ATTR(iom_cpld_vers,S_IRUGO,get_cpldver, NULL); +static DEVICE_ATTR(qsfp_modprs, S_IRUGO,get_modprs, NULL); +static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR,get_lpmode,set_lpmode); +static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR,get_reset, set_reset); +static DEVICE_ATTR(qsfp_int_sta, S_IRUGO, get_int_sta, NULL); +static DEVICE_ATTR(qsfp_abs_sta, S_IRUGO, get_abs_sta, NULL); +static DEVICE_ATTR(qsfp_trig_mod, S_IRUGO | S_IWUSR, get_trig_mod, set_trig_mod); +static DEVICE_ATTR(qsfp_int_combine, S_IRUGO, get_int_combine, NULL); +static DEVICE_ATTR(qsfp_int, S_IRUGO, get_int, NULL); +static DEVICE_ATTR(qsfp_abs_int, S_IRUGO, get_abs_int, NULL); +static DEVICE_ATTR(qsfp_int_mask, S_IRUGO | S_IWUSR, get_int_mask, set_int_mask); +static DEVICE_ATTR(qsfp_abs_mask, S_IRUGO | S_IWUSR, get_abs_mask, set_abs_mask); + +static struct attribute *i2c_cpld_attrs[] = { + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_iom_cpld_vers.attr, + &dev_attr_qsfp_int_sta.attr, + &dev_attr_qsfp_abs_sta.attr, + &dev_attr_qsfp_trig_mod.attr, + &dev_attr_qsfp_int_combine.attr, + &dev_attr_qsfp_int.attr, + &dev_attr_qsfp_abs_int.attr, + &dev_attr_qsfp_int_mask.attr, + &dev_attr_qsfp_abs_mask.attr, + NULL, +}; + +static struct attribute_group i2c_cpld_attr_grp = { + .attrs = i2c_cpld_attrs, +}; + +static int dell_s6100_iom_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + dell_s6100_iom_cpld_add_client(client); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &i2c_cpld_attr_grp); + if (status) { + printk(KERN_INFO "Cannot create sysfs\n"); + } + return 0; + +exit: + return status; +} + +static int dell_s6100_iom_cpld_remove(struct i2c_client *client) +{ + dell_s6100_iom_cpld_remove_client(client); + return 0; +} + + +static const struct i2c_device_id dell_s6100_iom_cpld_id[] = { + { "dell_s6100_iom_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dell_s6100_iom_cpld_id); + +static struct i2c_driver dell_s6100_iom_cpld_driver = { + .driver = { + .name = "dell_s6100_iom_cpld", + }, + .probe = dell_s6100_iom_cpld_probe, + .remove = dell_s6100_iom_cpld_remove, + .id_table = dell_s6100_iom_cpld_id, +}; + + + +static int __init dell_s6100_iom_cpld_init(void) +{ + return i2c_add_driver(&dell_s6100_iom_cpld_driver); +} + +static void __exit dell_s6100_iom_cpld_exit(void) +{ + i2c_del_driver(&dell_s6100_iom_cpld_driver); +} + +MODULE_AUTHOR("Srideep Devireddy "); +MODULE_DESCRIPTION("dell_s6100_iom_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(dell_s6100_iom_cpld_init); +module_exit(dell_s6100_iom_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/README b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/README new file mode 100644 index 000000000000..b141bb05e2e4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/README @@ -0,0 +1,146 @@ +Dell S6100 64x40G support +------------------------ + +summary:- +S6100 has 64 x 40G port capacity +S6100 supports 4 IO Modules which are pluggable. Below section covers how to power on IO modules +and initialize the device drivers and configure necessary mux to send traffic. + + +Necessary drivers and scripts to package + +1) Users are expected to build necessary drivers for kernel and package to acess it on the target + + a) Mgmt phy driver + This supports BCM 54616 phy driver ( enable CONFIG_IGB in kernel config) + b) driver-support-sff-8436-eeprom.patch + c) driver-support-sff-8436-eeprom-update.patch + This driver supports QSFP EEPROM + d) dell_s6100_iom_cpld.ko + This driver provides support for cpld on 4 x 40Gig-IOM modules + e) i2c_mux_pca954x.ko + This driver provides support for i2c mux/switch (pca954x) + f) dell_s6100_lpc.ko + This driver porivide support for reading all the platform info from SMF. + + +2) Users are also expected to package below scripts for platform initialization and i2c tree creation + + a) iom_power.sh + This script is used to power on IO modules on S6100 + b) io_rd_wr.py +This script is generic LPC/io read/write utility (can also access system cpld) + +steps to platform initialization (Tested with 3.16) + +1) After power up of S6100 + + a) power up the io modules by executing (./iom_power.sh) + b) insert i2c_mux_pca954x.ko,dell_s6100_iom_cpld.ko,dell_s6100_lpc.ko + + Above 2 steps can be called by including them in below 2 step + +2) Build i2c device tree/device initialization by calling below script + + ./s6100_platform_init.sh + +3) IOM cpld devices are created under "/sys/bus/i2c/drivers/dell_s6100_iom_cpld/" + QSFP handles via sysfs i2c bus #( 15,16,17,18-003e) + iom_cpld_vers -- Displays CPLD version(RO) + qsfp_lpmode -- lpmode settings(RW) + qsfp_modprs -- modules presence (RO) + qsfp_reset -- reset settings (RW) + + ls /sys/bus/i2c/drivers/dell_s6100_iom_cpld/15-003e/ + driver/ iom_cpld_vers modalias name power/ qsfp_lpmode qsfp_modprs qsfp_reset subsystem/ uevent + +4) step 2 script also builds/attach sfp device tress in sysfs + + Example for reading EEPROM data + + cat /sys/bus/i2c/devices/19-0050/eeprom | hexdump -C + 00000000 0d 00 00 0f 00 00 00 00 00 00 00 00 00 00 00 00 |................| + 00000010 00 00 00 00 00 00 18 1b 00 00 82 20 00 00 00 00 |........... ....| + 00000020 00 00 00 00 00 00 00 00 00 00 16 4d 16 4d 16 4d |...........M.M.M| + 00000030 16 4d 34 bf 44 bf 54 bf 64 bf 00 00 00 00 00 00 |.M4.D.T.d.......| + 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| + * + 00000070 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff 00 |................| + 00000080 0d 00 0c 04 00 00 00 40 40 02 d5 05 69 00 00 32 |.......@@...i..2| + 00000090 00 00 00 00 46 49 4e 49 53 41 52 20 43 4f 52 50 |....FINISAR CORP| + 000000a0 20 20 20 20 07 00 90 65 46 54 4c 34 31 30 51 45 | ...eFTL410QE| + 000000b0 31 43 20 20 20 20 20 20 41 33 42 68 07 d0 46 70 |1C A3Bh..Fp| + 000000c0 00 01 04 d0 4d 4c 54 30 30 51 33 20 20 20 20 20 |....MLT00Q3 | + 000000d0 20 20 20 20 31 32 30 31 31 35 20 20 08 00 00 38 | 120115 ...8| + 000000e0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | + 000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| + * + 00000200 4b 00 fb 00 46 00 00 00 00 00 00 00 00 00 00 00 |K...F...........| + 00000210 94 70 6e f0 86 c4 7b 0c 00 00 00 00 00 00 00 00 |.pn...{.........| + 00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| + * + 00000260 00 00 11 11 00 00 00 00 00 00 00 00 00 00 22 22 |..............""| + 00000270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| + 00000280 + +5)SMF driver details/Readme are as below + + S6100 SMF + --------- + + S6100 has one SMF soc on CPU board. This is via LPC interface, provide access to all the below functionality + + a) Read sensors details on the system + b) Read PSU details on the system + c) Read fans/Fan tray details on the system + d) Read/Write to system led + + dell_s6100_lpc create entry for all the above necessary platform components as attributes in below path. + + /sys/devices/platform/dell_s6100_lpc/ + + + LED:- + ---- + + Get /set operations on sys_led + + Get operation + cat /sys/devices/platform/dell_s6100_lpc/sys_led + 0x80 + + Set operation + echo 83 > sys/devices/platform/dell_s6100_lpc/sys_led + + Sensors:- + -------- + + Max no of sensors on the system ( 11 sensors are available on fully loaded system) + + cat /sys/devices/platform/dell_s6100_lpc/max_num_temp_sensors + b + + cat /sys/devices/platform/dell_s6100_lpc/temp_sensor_1 ( temp_sensor_1 <85>.temp_sensor_11) + + Fan tray speed:- + -------------- + + /sys/devices/platform/dell_s6100_lpc/fan_tray_1_speed (fan_tray_1_speed - fan_tray_4_speed) + 13700 + + cat /sys/devices/platform/dell_s6100_lpc/psu1_max_pwr + 110 + cat /sys/devices/platform/dell_s6100_lpc/psu2_max_pwr + 110 + + cat /sys/devices/platform/dell_s6100_lpc/psu_total_pwr + 232 + + + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/io_rd_wr.py b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/io_rd_wr.py new file mode 100755 index 000000000000..dc9dd09807c2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/io_rd_wr.py @@ -0,0 +1,93 @@ +#!/usr/bin/python +#Script to read/write the io based registers + +import sys +import os +import getopt +import struct + +io_resource='/dev/port' + +def usage(): + ''' This is the Usage Method ''' + + print 'Utility for IO read/write' + print '\t\t io_rd_wr.py --get --offset ' + print '\t\t io_rd_wr.py --set --val --offset ' + sys.exit(1) + +def io_reg_read(io_resource,offset): + fd=os.open(io_resource, os.O_RDONLY) + if(fd<0): + print 'file open failed %s"%io_resource' + return + if(os.lseek(fd, offset, os.SEEK_SET) != offset): + print 'lseek failed on %s'%io_resource + return + buf=os.read(fd,1) + reg_val1=ord(buf) + print 'reg value %x'%reg_val1 + os.close(fd) + +def io_reg_write(io_resource,offset,val): + fd=os.open(io_resource,os.O_RDWR) + if(fd<0): + print 'file open failed %s"%io_resource' + return + if(os.lseek(fd, offset, os.SEEK_SET) != offset): + print 'lseek failed on %s'%io_resource + return + ret=os.write(fd,struct.pack('B',val)) + if(ret != 1): + print 'write failed %d'%ret + return + os.close(fd) + +def main(argv): + + ''' The main function will read the user input from the + command line argument and process the request ''' + + opts = '' + val = '' + choice = '' + resouce = '' + offset = '' + + try: + opts, args = getopt.getopt(argv, "hgs:" , \ + ["val=","offset=","help", "get", "set"]) + + except getopt.GetoptError: + usage() + + for opt,arg in opts: + + if opt in ('-h','--help'): + choice = 'help' + + elif opt in ('-g', '--get'): + choice = 'get' + + elif opt in ('-s', '--set'): + choice = 'set' + + elif opt == '--offset': + offset = int(arg,16) + + elif opt == '--val': + val = int(arg,16) + + if choice == 'get' and offset != '': + io_reg_read(io_resource,offset) + + elif choice == 'set' and offset != '' and val != '': + io_reg_write(io_resource,offset,val) + + else: + usage() + +#Calling the main method +if __name__ == "__main__": + main(sys.argv[1:]) + diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/iom_power_off.sh b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/iom_power_off.sh new file mode 100755 index 000000000000..a7671cfe589c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/iom_power_off.sh @@ -0,0 +1,16 @@ +#!/bin/bash +#This script is used to power off IO modules +# IOM can be controlled via SMF using mailbox registers +# write 0x2 to 0x04D9 to power off IOM 1 +./io_rd_wr.py --set --val 0x04 --offset 0x210 +./io_rd_wr.py --set --val 0xd9 --offset 0x211 +./io_rd_wr.py --set --val 0x2 --offset 0x213 +# write 0x2 to 0x04DA to power off IOM 2 +./io_rd_wr.py --set --val 0xda --offset 0x211 +./io_rd_wr.py --set --val 0x2 --offset 0x213 +# write 0x2 to 0x04DB to power off IOM 3 +./io_rd_wr.py --set --val 0xdb --offset 0x211 +./io_rd_wr.py --set --val 0x2 --offset 0x213 +# write 0x2 to 0x04DC to power off IOM 4 +./io_rd_wr.py --set --val 0xdc --offset 0x211 +./io_rd_wr.py --set --val 0x2 --offset 0x213 diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/iom_power_on.sh b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/iom_power_on.sh new file mode 100755 index 000000000000..3d31170803e1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/iom_power_on.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# This script is used to power on IO modules +# IOM can be controlled via SMF using mailbox registers + +# write 0x1 to 0x04D9 to power up IOM 1 +/usr/local/bin/io_rd_wr.py --set --val 0x04 --offset 0x210 +/usr/local/bin/io_rd_wr.py --set --val 0xd9 --offset 0x211 +/usr/local/bin/io_rd_wr.py --set --val 0x1 --offset 0x213 +# write 0x1 to 0x04DA to power up IOM 2 +/usr/local/bin/io_rd_wr.py --set --val 0xda --offset 0x211 +/usr/local/bin/io_rd_wr.py --set --val 0x1 --offset 0x213 +# write 0x1 to 0x04DB to power up IOM 3 +/usr/local/bin/io_rd_wr.py --set --val 0xdb --offset 0x211 +/usr/local/bin/io_rd_wr.py --set --val 0x1 --offset 0x213 +# write 0x1 to 0x04DC to power up IOM 4 +/usr/local/bin/io_rd_wr.py --set --val 0xdc --offset 0x211 +/usr/local/bin/io_rd_wr.py --set --val 0x1 --offset 0x213 diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_sensors.py new file mode 100755 index 000000000000..a0231bc507cf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_sensors.py @@ -0,0 +1,324 @@ +#!/usr/bin/python + +# On S6100, the Platform Management Controller runs the +# thermal algorithm. It provides a mailbox for the Host +# to query relevant thermals. The dell_mailbox module +# provides the sysfs support for the following objects: +# * onboard temperature sensors +# * FAN trays +# * PSU +# +import os +import sys +import logging + +S6100_MAX_FAN_TRAYS = 4 +S6100_MAX_PSUS = 2 +S6100_MAX_IOMS = 4 + +HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" +HWMON_NODE = os.listdir(HWMON_DIR)[0] +MAILBOX_DIR = HWMON_DIR + HWMON_NODE +iom_status_list = [] + +# Get a mailbox register + + +def get_pmc_register(reg_name): + retval = 'ERR' + mb_reg_file = MAILBOX_DIR+'/'+reg_name + + if (not os.path.isfile(mb_reg_file)): + print mb_reg_file, 'not found !' + return retval + + try: + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", mb_reg_file, "file !") + + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + +logging.basicConfig(level=logging.DEBUG) + +if (os.path.isdir(MAILBOX_DIR)): + print 'dell-s6100-lpc' + print 'Adapter: S6100 Platform Management Controller' +else: + logging.error('S6100 Platform Management Controller module not loaded !') + # sys.exit(0) + +# Print the information for temperature sensors + + +def print_temperature_sensors(): + print("\nOnboard Temperature Sensors:") + print ' CPU: ',\ + int(get_pmc_register('temp1_input'))/1000, 'C' + print ' BCM56960 (PSU side): ',\ + int(get_pmc_register('temp2_input'))/1000, 'C' + print ' System Outlet 1 (switch board): ',\ + int(get_pmc_register('temp3_input'))/1000, 'C' + print ' BCM56960 (IO side): ',\ + int(get_pmc_register('temp4_input'))/1000, 'C' + print ' System Outlet 2 (CPU board): ',\ + int(get_pmc_register('temp9_input'))/1000, 'C' + print ' System Inlet Left (IO side): ',\ + int(get_pmc_register('temp10_input'))/1000, 'C' + print ' System Inlet Right (IO side): ',\ + int(get_pmc_register('temp11_input'))/1000, 'C' + + iom_status = get_pmc_register('iom_presence') + iom_status = int(iom_status, 16) + + iom_presence = get_pmc_register('iom_status') + + if (iom_presence != 'ERR'): + iom_presence = int(iom_presence, 16) + + # IOM presence : 0 => IOM present + # Temperature sensors 5..8 correspond to IOM 1..4 + for iom in range(0, S6100_MAX_IOMS): + if (~iom_presence & (1 << iom)): + iom_sensor_indx = iom + 5 + print ' IOM ' + str(iom + 1) + ':\t\t\t ',\ + int(get_pmc_register('temp'+str(iom_sensor_indx) + + '_input'))/1000, 'C' + + # Save the IOM Status for later use + if (~iom_status & (1 << iom)): + iom_status_list.append('ON') + else: + iom_status_list.append('OFF') + else: + iom_status_list.append('Not present') + print ' IOM ' + str(iom + 1) + ':\t\t\t ', 'Not present' + else: + logging.error('Unable to check IOM presence') + +print_temperature_sensors() + + +# Print the information for voltage sensors + + +def print_voltage_sensors(): + print("\nOnboard Voltage Sensors:") + + print ' CPU XP3R3V_EARLY ',\ + float(get_pmc_register('in1_input'))/1000, 'V' + print ' CPU XP5R0V_CP ',\ + float(get_pmc_register('in2_input'))/1000, 'V' + print ' CPU XP3R3V_STD ',\ + float(get_pmc_register('in3_input'))/1000, 'V' + print ' CPU XP3R3V_CP ',\ + float(get_pmc_register('in4_input'))/1000, 'V' + print ' CPU XP0R75V_VTT_A ',\ + float(get_pmc_register('in5_input'))/1000, 'V' + print ' CPU XPPR75V_VTT_B ',\ + float(get_pmc_register('in6_input'))/1000, 'V' + print ' CPU XP1R07V_CPU ',\ + float(get_pmc_register('in7_input'))/1000, 'V' + print ' CPU XP1R0V_CPU ',\ + float(get_pmc_register('in8_input'))/1000, 'V' + print ' CPU XP12R0V ',\ + float(get_pmc_register('in9_input'))/1000, 'V' + print ' CPU VDDR_CPU_2 ',\ + float(get_pmc_register('in10_input'))/1000, 'V' + print ' CPU VDDR_CPU_1 ',\ + float(get_pmc_register('in11_input'))/1000, 'V' + print ' CPU XP1R5V_CLK ',\ + float(get_pmc_register('in12_input'))/1000, 'V' + print ' CPU XP1R8V_CPU ',\ + float(get_pmc_register('in13_input'))/1000, 'V' + print ' CPU XP1R0V_CPU_VNN ',\ + float(get_pmc_register('in14_input'))/1000, 'V' + print ' CPU XP1R0V_CPU_VCC ',\ + float(get_pmc_register('in15_input'))/1000, 'V' + print ' CPU XP1R5V_EARLY ',\ + float(get_pmc_register('in16_input'))/1000, 'V' + print ' SW XP3R3V_MON ',\ + float(get_pmc_register('in17_input'))/1000, 'V' + print ' SW XP1R25V_MON ',\ + float(get_pmc_register('in19_input'))/1000, 'V' + print ' SW XP1R2V_MON ',\ + float(get_pmc_register('in20_input'))/1000, 'V' + print ' SW XP1R0V_SW_MON ',\ + float(get_pmc_register('in21_input'))/1000, 'V' + print ' SW XP1R0V_ROV_SW_MON ',\ + float(get_pmc_register('in22_input'))/1000, 'V' + print ' SW XR1R0V_BCM84752_MON ',\ + float(get_pmc_register('in23_input'))/1000, 'V' + print ' SW XP5V_MB_MON ',\ + float(get_pmc_register('in24_input'))/1000, 'V' + print ' SW XP3R3V_FPGA_MON ',\ + float(get_pmc_register('in26_input'))/1000, 'V' + print ' SW XP3R3V_EARLY_MON ',\ + float(get_pmc_register('in27_input'))/1000, 'V' + +print_voltage_sensors() + +# Print the information for 1 Fan Tray + + +def print_fan_tray(tray): + + Fan_Status = ['Normal', 'Abnormal'] + Airflow_Direction = ['B2F', 'F2B'] + + print ' Fan Tray ' + str(tray) + ':' + + if (tray == 1): + fan1_speed = get_pmc_register('fan1_input') + air_flow_reg = int(get_pmc_register('fan1_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + + print ' Fan Speed: ', fan1_speed, 'RPM' + print ' Fan State: ', Fan_Status[fan1_status] + print ' Air Flow: ', Airflow_Direction[air_flow_reg] + elif (tray == 2): + fan1_speed = get_pmc_register('fan3_input') + air_flow_reg = int(get_pmc_register('fan3_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + + print ' Fan Speed: ', fan1_speed, 'RPM' + print ' Fan State: ', Fan_Status[fan1_status] + print ' Air Flow: ', Airflow_Direction[air_flow_reg] + elif (tray == 3): + fan1_speed = get_pmc_register('fan5_input') + air_flow_reg = int(get_pmc_register('fan5_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + + print ' Fan Speed: ', fan1_speed, 'RPM' + print ' Fan State: ', Fan_Status[fan1_status] + print ' Air Flow: ', Airflow_Direction[air_flow_reg] + elif (tray == 4): + fan1_speed = get_pmc_register('fan7_input') + air_flow_reg = int(get_pmc_register('fan7_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + + print ' Fan Speed: ', fan1_speed, 'RPM' + print ' Fan State: ', Fan_Status[fan1_status] + print ' Air Flow: ', Airflow_Direction[air_flow_reg] + +print('\nFan Trays:') +fan_tray_presence = get_pmc_register('fan_tray_presence') + +if (fan_tray_presence != 'ERR'): + fan_tray_presence = int(fan_tray_presence, 16) + + for tray in range(0, S6100_MAX_FAN_TRAYS): + if (fan_tray_presence & (1 << tray)): + print_fan_tray(tray + 1) + else: + print '\n Fan Tray ' + str(tray + 1) + ': Not present' +else: + logging.error('Unable to read FAN presence') + +# Print the information for PSU1, PSU2 + + +def print_psu(psu): + Psu_Type = ['Mismatch', 'Normal'] + Psu_Input_Type = ['AC', 'DC'] + PSU_STATUS_TYPE_BIT = 4 + PSU_STATUS_INPUT_TYPE_BIT = 1 + PSU_FAN_PRESENT_BIT = 2 + PSU_FAN_STATUS_BIT = 1 + PSU_FAN_AIR_FLOW_BIT = 0 + Psu_Fan_Presence = ['Present', 'Absent'] + Psu_Fan_Status = ['Normal', 'Abnormal'] + Psu_Fan_Airflow = ['B2F', 'F2B'] + + print ' PSU ' + str(psu) + ':' + if (psu == 1): + psu_status = int(get_pmc_register('psu1_presence'), 16) + else: + psu_status = int(get_pmc_register('psu2_presence'), 16) + + psu_input_type = (psu_status & (1 << PSU_STATUS_INPUT_TYPE_BIT)) >>\ + PSU_STATUS_INPUT_TYPE_BIT + psu_type = (psu_status & (1 << PSU_STATUS_TYPE_BIT)) >>\ + PSU_STATUS_TYPE_BIT + + print ' Input: ', Psu_Input_Type[psu_input_type] + print ' Type: ', Psu_Type[psu_type] + + # PSU FAN details + if (psu == 1): + print ' FAN Speed: ', get_pmc_register('fan11_input'), 'RPM' + psu_fan_airflow = int(get_pmc_register('fan11_airflow')) + psu_fan_status = int(get_pmc_register('fan11_alarm')) + psu_fan_present = int(get_pmc_register('fan11_fault')) + input_voltage = float(get_pmc_register('in29_input')) / 1000 + output_voltage = float(get_pmc_register('in30_input')) / 1000 + input_current = float(get_pmc_register('curr601_input')) / 100 + output_current = float(get_pmc_register('curr602_input')) / 100 + input_power = float(get_pmc_register('power1_input')) / 1000000 + output_power = float(get_pmc_register('power2_input')) / 1000000 + if (input_power != 0): + psu_fan_temp = int(get_pmc_register('temp14_input'))/1000 + else: + print ' FAN Speed: ', get_pmc_register('fan12_input'), 'RPM' + psu_fan_airflow = int(get_pmc_register('fan12_airflow')) + psu_fan_status = int(get_pmc_register('fan12_alarm')) + psu_fan_present = int(get_pmc_register('fan12_fault')) + input_voltage = float(get_pmc_register('in31_input')) / 1000 + output_voltage = float(get_pmc_register('in32_input')) / 1000 + input_current = float(get_pmc_register('curr701_input')) / 100 + output_current = float(get_pmc_register('curr702_input')) / 100 + input_power = float(get_pmc_register('power3_input')) / 1000000 + output_power = float(get_pmc_register('power4_input')) / 1000000 + if (input_power != 0): + psu_fan_temp = int(get_pmc_register('temp15_input'))/1000 + print ' FAN: ', Psu_Fan_Presence[psu_fan_present] + print ' FAN Status: ', Psu_Fan_Status[psu_fan_status] + print ' FAN AIRFLOW: ', Psu_Fan_Airflow[psu_fan_airflow] + + # PSU input & output monitors + print ' Input Voltage: %6.2f' % (input_voltage), 'V' + + print ' Output Voltage: %6.2f' % (output_voltage), 'V' + + print ' Input Current: %6.2f' % (input_current), 'A' + + print ' Output Current: %6.2f' % (output_current), 'A' + + print ' Input Power: %6.2f' % (input_power), 'W' + + print ' Output Power: %6.2f' % (output_power), 'W' + + # PSU firmware gives spurious temperature reading without input power + if (input_power != 0): + print ' Temperature: ', psu_fan_temp, 'C' + else: + print ' Temperature: ', 'NA' + +print('\nPSUs:') +for psu in range(1, S6100_MAX_PSUS + 1): + + if (psu == 1): + psu_status = get_pmc_register('psu1_presence') + else: + psu_status = get_pmc_register('psu2_presence') + + if (psu_status != 'ERR'): + psu_status = int(psu_status, 16) + if (~psu_status & 0b1): + print_psu(psu) + else: + print '\n PSU ', psu, 'Not present' + else: + logging.error('Unable to check PSU presence') + +print '\n Total Power: ', get_pmc_register('current_total_power'), 'W' + +print('\nIO Modules:') + +for iom in range(1, S6100_MAX_IOMS+1): + print ' IOM ' + str(iom) + ' :' + iom_status_list[iom - 1] + +print '\n' diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_platform.sh b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_platform.sh new file mode 100755 index 000000000000..1d1e05f04258 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_platform.sh @@ -0,0 +1,229 @@ +#!/bin/bash + +#platform init script for Dell S6100 + +source dell_i2c_utils.sh + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [[ $found -eq 0 ]] && echo "cannot find iSMT" && exit 1 +} + +# Attach/Detach CPU board mux @ 0x70 +cpu_board_mux() { + case $1 in + "new_device") i2c_config "echo pca9547 0x70 > /sys/bus/i2c/devices/i2c-${devnum}/$1" + ;; + "delete_device") i2c_config "echo 0x70 > /sys/bus/i2c/devices/i2c-${devnum}/$1" + ;; + *) echo "s6100_platform: cpu_board_mux: invalid command !" + ;; + esac +} + +# Attach/Detach Switchboard MUX @ 0x71 +switch_board_mux() { + case $1 in + "new_device") i2c_config "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-4/$1" + ;; + "delete_device") i2c_config "echo 0x71 > /sys/bus/i2c/devices/i2c-4/$1" + ;; + *) echo "s6100_platform: switch_board_mux : invalid command !" + ;; + esac +} + +# Attach/Detach syseeprom on CPU board +sys_eeprom() { + case $1 in + "new_device") i2c_config "echo 24c02 0x50 > /sys/bus/i2c/devices/i2c-2/$1" + ;; + "delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-2/$1" + ;; + *) echo "s6100_platform: sys_eeprom : invalid command !" + ;; + esac +} + +#Attach/Detach CPLD devices to drivers for each IOM +switch_board_cpld() { + case $1 in + "new_device") + for ((i=14;i<=17;i++)); + do + i2c_config "echo dell_s6100_iom_cpld 0x3e > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + "delete_device") + for ((i=14;i<=17;i++)); + do + i2c_config "echo 0x3e > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + *) echo "s6100_platform: switch_board_cpld : invalid command !" + ;; + esac +} + +#Attach/Detach the MUX connecting all QSFPs on each IOM @0x71 and 0x72 +switch_board_qsfp_mux() { + case $1 in + "new_device") + for ((i=9;i>=6;i--)); + do + # 0x71 mux on the IOM 1 + mux_index=$(expr $i - 5) + echo "Attaching PCA9548 $mux_index" + i2c_config "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-$i/$1" + i2c_config "echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + "delete_device") + for ((i=9;i>=6;i--)); + do + # 0x71 mux on the IOM 1 + mux_index=$(expr $i - 5) + echo "Detaching PCA9548 $mux_index" + i2c_config "echo 0x71 > /sys/bus/i2c/devices/i2c-$devnum/i2c-$i/$1" + i2c_config "echo 0x72 > /sys/bus/i2c/devices/i2c-$devnum/i2c-$i/$1" + done + ;; + *) echo "s6100_platform: switch_board_qsfp_mux: invalid command !" + ;; + esac +} + +#Attach/Detach the SFP modules on PCA9548_2 +switch_board_sfp() { + case $1 in + "new_device") i2c_config "echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-11/$1" + i2c_config "echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-12/$1" + ;; + "delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-11/$1" + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-12/$1" + ;; + *) echo "s6100_platform: switch_board_sfp: invalid command !" + ;; + esac +} + +#Add/Delete ($1) a range ($2..$3) of QSFPs +qsfp_device_mod() { + case $1 in + "new_device") for ((i=$2;i<=$3;i++)); + do + i2c_config "echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + "delete_device") for ((i=$2;i<=$3;i++)); + do + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + *) echo "s6100_platform: qsfp_device_mod: invalid command $1:$2,$3!" + ;; + esac +} + +# Attach/Detach 16 instances of QSFP ports on each IO modules +# eeprom can dump data using below command +switch_board_qsfp() { + if i2c_poll_bus_exists "/sys/bus/i2c/devices/i2c-18"; then + qsfp_device_mod $1 18 33 + fi + + if i2c_poll_bus_exists "/sys/bus/i2c/devices/i2c-34"; then + qsfp_device_mod $1 34 49 + fi + + if i2c_poll_bus_exists "/sys/bus/i2c/devices/i2c-50"; then + qsfp_device_mod $1 50 65 + fi + + if i2c_poll_bus_exists "/sys/bus/i2c/devices/i2c-66"; then + qsfp_device_mod $1 66 81 + fi +} + +# Enable/Disable low power mode on all QSFP ports +switch_board_qsfp_lpmode() { + case $1 in + "enable") value=0xffff + ;; + "disable") value=0x0 + ;; + *) echo "s6100_platform: switch_board_qsfp_lpmode: invalid command $1!" + return + ;; + esac + echo $value > /sys/class/i2c-adapter/i2c-14/14-003e/qsfp_lpmode + echo $value > /sys/class/i2c-adapter/i2c-15/15-003e/qsfp_lpmode + echo $value > /sys/class/i2c-adapter/i2c-16/16-003e/qsfp_lpmode + echo $value > /sys/class/i2c-adapter/i2c-17/17-003e/qsfp_lpmode +} + +# Enable/Disable xcvr presence interrupts +xcvr_presence_interrupts() { + case $1 in + "enable") + for ((i=14;i<=17;i++)); + do + echo 0x0 > /sys/class/i2c-adapter/i2c-$i/$i-003e/qsfp_abs_mask + done + ;; + "disable") + for ((i=14;i<=17;i++)); + do + echo 0xffff > /sys/class/i2c-adapter/i2c-$i/$i-003e/qsfp_abs_mask + done + ;; + *) echo "s6100_platform: xcvr_presence_interrupts: invalid command !" + ;; + esac +} + +init_devnum + +if [[ "$1" == "init" ]]; then + modprobe i2c-dev + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + modprobe dell_ich + modprobe dell_s6100_iom_cpld + modprobe dell_s6100_lpc + + cpu_board_mux "new_device" + switch_board_mux "new_device" + sys_eeprom "new_device" + switch_board_cpld "new_device" + switch_board_qsfp_mux "new_device" + switch_board_sfp "new_device" + switch_board_qsfp "new_device" + switch_board_qsfp_lpmode "disable" + xcvr_presence_interrupts "enable" +elif [[ "$1" == "deinit" ]]; then + xcvr_presence_interrupts "disable" + switch_board_sfp "delete_device" + switch_board_cpld "delete_device" + switch_board_mux "delete_device" + sys_eeprom "delete_device" + switch_board_qsfp "delete_device" + switch_board_qsfp_mux "delete_device" + cpu_board_mux "delete_device" + + modprobe -r dell_s6100_lpc + modprobe -r dell_s6100_iom_cpld + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev + modprobe -r dell_ich +else + echo "s6100_platform : Invalid option !" +fi diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/sensors b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/sensors new file mode 100755 index 000000000000..030d636a1565 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/sensors @@ -0,0 +1,7 @@ +#!/bin/bash +docker exec -i pmon sensors "$@" + +#To probe sensors not part of lm-sensors +if [ -r /usr/local/bin/platform_sensors.py ]; then + python /usr/local/bin/platform_sensors.py +fi diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/platform-modules-s6100.service b/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/platform-modules-s6100.service new file mode 100644 index 000000000000..9b5805d5cbbb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/platform-modules-s6100.service @@ -0,0 +1,14 @@ +[Unit] +Description=Dell S6100 Platform modules +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStartPre=/usr/local/bin/iom_power_on.sh +ExecStart=/usr/local/bin/s6100_platform.sh init +ExecStop=/usr/local/bin/s6100_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/cfg/z9100-modules.conf b/platform/broadcom/sonic-platform-modules-dell/z9100/cfg/z9100-modules.conf new file mode 100644 index 000000000000..66f002a5fc94 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/cfg/z9100-modules.conf @@ -0,0 +1,15 @@ +# /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. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-gpio +i2c-mux-pca954x + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/modules/Makefile b/platform/broadcom/sonic-platform-modules-dell/z9100/modules/Makefile new file mode 100644 index 000000000000..24ef231b2a50 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := dell_mailbox.o dell_z9100_cpld.o dell_ich.o + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/modules/dell_z9100_cpld.c b/platform/broadcom/sonic-platform-modules-dell/z9100/modules/dell_z9100_cpld.c new file mode 100644 index 000000000000..6198771ab45a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/modules/dell_z9100_cpld.c @@ -0,0 +1,491 @@ + + +/* Includes only 3 things. + * a. QSFP Reset control + * b. LP Mode + * c. Module Presence + */ +#include // included for all kernel modules +#include // included for KERN_INFO +#include // included for __init and __exit macros +#include +#include +#include +#include + + +//iom cpld slave address +#define IOM_CPLD_SLAVE_ADD 0x3e + +//iom cpld ver register +#define IOM_CPLD_SLAVE_VER 0x00 + +//qsfp reset cntrl reg on each iom +#define QSFP_RST_CRTL_REG0 0x10 +#define QSFP_RST_CRTL_REG1 0x11 + +//qsfp lp mode reg on each iom +#define QSFP_LPMODE_REG0 0x12 +#define QSFP_LPMODE_REG1 0x13 + +//qsfp mod presence reg on each iom +#define QSFP_MOD_PRS_REG0 0x16 +#define QSFP_MOD_PRS_REG1 0x17 + +//qsfp interrupt registers +#define QSFP_INT_STA_REG0 0x14 +#define QSFP_INT_STA_REG1 0x15 +#define QSFP_ABS_STA_REG0 0x16 +#define QSFP_ABS_STA_REG1 0x17 +#define QSFP_TRIG_MOD 0x20 +#define QSFP_INT_COMBINE 0x21 +#define QSFP_INT0 0x22 +#define QSFP_INT1 0x23 +#define QSFP_ABS_INT0 0x24 +#define QSFP_ABS_INT1 0x25 +#define QSFP_INT_MASK0 0x26 +#define QSFP_INT_MASK1 0x27 +#define QSFP_ABS_MASK0 0x28 +#define QSFP_ABS_MASK1 0x29 + +struct cpld_data { + struct i2c_client *client; + struct mutex update_lock; +}; + + +static void dell_z9100_iom_cpld_add_client(struct i2c_client *client) +{ + struct cpld_data *data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + + if (!data) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); +} + +static void dell_z9100_iom_cpld_remove_client(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + kfree(data); + return ; +} + +int dell_z9100_iom_cpld_read(struct cpld_data *data, u8 reg) +{ + int ret = -EPERM; + u8 high_reg =0x00; + + mutex_lock(&data->update_lock); + + ret = i2c_smbus_write_byte_data(data->client, high_reg,reg); + ret = i2c_smbus_read_byte(data->client); + mutex_unlock(&data->update_lock); + + return ret; +} + +int dell_z9100_iom_cpld_write(struct cpld_data *data,u8 reg, u8 value) +{ + int ret = -EIO; + u16 devdata=0; + u8 high_reg =0x00; + + mutex_lock(&data->update_lock); + devdata = (value << 8) | reg; + i2c_smbus_write_word_data(data->client,high_reg,devdata); + mutex_unlock(&data->update_lock); + + return ret; +} +static ssize_t get_cpldver(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,IOM_CPLD_SLAVE_VER); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u8)ret & 0xff; + return sprintf(buf,"IOM CPLD Version:0x%02x\n",devdata); +} + +static ssize_t get_modprs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_MOD_PRS_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_MOD_PRS_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_LPMODE_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_LPMODE_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_RST_CRTL_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_RST_CRTL_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_z9100_iom_cpld_write(data,QSFP_LPMODE_REG0,(u8)(devdata & 0xff)); + dell_z9100_iom_cpld_write(data,QSFP_LPMODE_REG1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_z9100_iom_cpld_write(data,QSFP_RST_CRTL_REG0,(u8)(devdata & 0xff)); + dell_z9100_iom_cpld_write(data,QSFP_RST_CRTL_REG1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static ssize_t get_int_sta(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT_STA_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT_STA_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_abs_sta(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_ABS_STA_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_ABS_STA_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_trig_mod(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_TRIG_MOD); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u8)ret & 0xff; + return sprintf(buf,"0x%02x\n",devdata); +} + +static ssize_t set_trig_mod(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_z9100_iom_cpld_write(data,QSFP_TRIG_MOD,(u8)(devdata & 0xff)); + + return count; +} + +static ssize_t get_int_combine(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT_COMBINE); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u8)ret & 0xff; + return sprintf(buf,"0x%02x\n",devdata); +} + +static ssize_t get_int(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_abs_int(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_ABS_INT0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_ABS_INT1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_int_mask(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT_MASK0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT_MASK1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t set_int_mask(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_z9100_iom_cpld_write(data,QSFP_INT_MASK0,(u8)(devdata & 0xff)); + dell_z9100_iom_cpld_write(data,QSFP_INT_MASK1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static ssize_t get_abs_mask(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_ABS_MASK0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_ABS_MASK1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t set_abs_mask(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_z9100_iom_cpld_write(data,QSFP_ABS_MASK0,(u8)(devdata & 0xff)); + dell_z9100_iom_cpld_write(data,QSFP_ABS_MASK1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static DEVICE_ATTR(iom_cpld_vers,S_IRUGO,get_cpldver, NULL); +static DEVICE_ATTR(qsfp_modprs, S_IRUGO,get_modprs, NULL); +static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR,get_lpmode,set_lpmode); +static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR,get_reset, set_reset); +static DEVICE_ATTR(qsfp_int_sta, S_IRUGO, get_int_sta, NULL); +static DEVICE_ATTR(qsfp_abs_sta, S_IRUGO, get_abs_sta, NULL); +static DEVICE_ATTR(qsfp_trig_mod, S_IRUGO | S_IWUSR, get_trig_mod, set_trig_mod); +static DEVICE_ATTR(qsfp_int_combine, S_IRUGO, get_int_combine, NULL); +static DEVICE_ATTR(qsfp_int, S_IRUGO, get_int, NULL); +static DEVICE_ATTR(qsfp_abs_int, S_IRUGO, get_abs_int, NULL); +static DEVICE_ATTR(qsfp_int_mask, S_IRUGO | S_IWUSR, get_int_mask, set_int_mask); +static DEVICE_ATTR(qsfp_abs_mask, S_IRUGO | S_IWUSR, get_abs_mask, set_abs_mask); + +static struct attribute *i2c_cpld_attrs[] = { + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_iom_cpld_vers.attr, + &dev_attr_qsfp_int_sta.attr, + &dev_attr_qsfp_abs_sta.attr, + &dev_attr_qsfp_trig_mod.attr, + &dev_attr_qsfp_int_combine.attr, + &dev_attr_qsfp_int.attr, + &dev_attr_qsfp_abs_int.attr, + &dev_attr_qsfp_int_mask.attr, + &dev_attr_qsfp_abs_mask.attr, + NULL, +}; + +static struct attribute_group i2c_cpld_attr_grp = { + .attrs = i2c_cpld_attrs, +}; + +static int dell_z9100_iom_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + dev_info(&client->dev, "chip found- New\n"); + dell_z9100_iom_cpld_add_client(client); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &i2c_cpld_attr_grp); + if (status) { + printk(KERN_INFO "Cannot create sysfs\n"); + } + return 0; + +exit: + return status; +} + +static int dell_z9100_iom_cpld_remove(struct i2c_client *client) +{ + dell_z9100_iom_cpld_remove_client(client); + return 0; +} + + +static const struct i2c_device_id dell_z9100_iom_cpld_id[] = { + { "dell_z9100_iom_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dell_z9100_iom_cpld_id); + +static struct i2c_driver dell_z9100_iom_cpld_driver = { + .driver = { + .name = "dell_z9100_iom_cpld", + }, + .probe = dell_z9100_iom_cpld_probe, + .remove = dell_z9100_iom_cpld_remove, + .id_table = dell_z9100_iom_cpld_id, +}; + + + +static int __init dell_z9100_iom_cpld_init(void) +{ + return i2c_add_driver(&dell_z9100_iom_cpld_driver); +} + +static void __exit dell_z9100_iom_cpld_exit(void) +{ + i2c_del_driver(&dell_z9100_iom_cpld_driver); +} + +MODULE_AUTHOR("Srideep Devireddy "); +MODULE_DESCRIPTION("dell_z9100_iom_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(dell_z9100_iom_cpld_init); +module_exit(dell_z9100_iom_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/check_qsfp.sh b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/check_qsfp.sh new file mode 100755 index 000000000000..38f62013e46b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/check_qsfp.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +#Usage: +# check_qsfp.sh qsfp10 +# check_qsfp.sh sffp2 + +# There are 34 optics ports. 32 QSFP28, 2 SFP+ +# QSFP28 is orgainized is 3 banks +# CPLD-2 QSFP-1-12 +# CPLD-3 QSFP-13-22 +# CPLD-4 QSFP-23-32 +# SFF+ 2 ports on CPLD-4 + +optics=$1 +cpld_addr="003e" + +if [ `expr match $optics qsfp` -ne 0 ] +then + type=qsfp + id=${optics:4} + + if [ $id -le 0 -o $id -gt 32 ] + then + echo "Invalid QSFP id" + return -1 + fi + if [ $id -le 12 ] + then + #cpld=2 + cpld_bus=15 + elif [ $id -le 22 ] + then + #cpld=3 + cpld_bus=16 + else + #cpld=4 + cpld_bus=17 + fi + + if [ $id -le 8 ] + then + let qsfp_bus=42+$id + elif [ $id -le 16 ] + then + let qsfp_bus=34+${id}-8 + elif [ $id -le 24 ] + then + let qsfp_bus=26+${id}-16 + else + let qsfp_bus=18+${id}-24 + fi +else + type=sff + id=${optics:3} + cpld=4 +fi + +echo "Preence:`cat /sys/class/i2c-dev/i2c-${cpld_bus}/device/${cpld_bus}-${cpld_addr}/qsfp_modprs`" +echo "Hexdump:" +cat /sys/bus/i2c/devices/${qsfp_bus}-0050/eeprom | hexdump -C diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/platform_sensors.py new file mode 100755 index 000000000000..76e527e13d73 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/platform_sensors.py @@ -0,0 +1,326 @@ +#!/usr/bin/python +# +# On Z9100, the Platform Management Controller runs the +# thermal algorithm. It provides a mailbox for the Host +# to query relevant thermals. The dell_mailbox module +# provides the sysfs support for the following objects: +# * onboard temperature sensors +# * FAN trays +# * PSU + +import os +import sys +import logging + +Z9100_MAX_FAN_TRAYS = 5 +Z9100_MAX_PSUS = 2 +S6100_MAX_IOMS = 4 + +HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" +HWMON_NODE = os.listdir(HWMON_DIR)[0] +MAILBOX_DIR = HWMON_DIR + HWMON_NODE + +# Get a mailbox register + + +def get_pmc_register(reg_name): + retval = 'ERR' + mb_reg_file = MAILBOX_DIR+'/'+reg_name + + if (not os.path.isfile(mb_reg_file)): + print mb_reg_file, 'not found !' + return retval + + try: + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", mb_reg_file, "file !") + + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + +logging.basicConfig(level=logging.DEBUG) + +if (os.path.isdir(MAILBOX_DIR)): + print 'dell-z9100-lpc' + print 'Adapter: Z9100 Platform Management Controller' +else: + logging.error('Z9100 Platform Management Controller module not loaded !') + # sys.exit(0) + +# Print the information for temperature sensors + + +def print_temperature_sensors(): + print("\nOnboard Temperature Sensors:") + print ' CPU: ',\ + int(get_pmc_register('temp1_input'))/1000, 'C' + print ' BCM56960 (PSU side): ',\ + int(get_pmc_register('temp2_input'))/1000, 'C' + print ' System Outlet 1 (switch board): ',\ + int(get_pmc_register('temp3_input'))/1000, 'C' + print ' BCM56960 (IO side): ',\ + int(get_pmc_register('temp4_input'))/1000, 'C' + print ' System Outlet 2 (CPU board): ',\ + int(get_pmc_register('temp9_input'))/1000, 'C' + print ' System Inlet Left (IO side): ',\ + int(get_pmc_register('temp6_input'))/1000, 'C' + +print_temperature_sensors() + + +# Print the information for voltage sensors + + +def print_voltage_sensors(): + print("\nOnboard Voltage Sensors:") + + print ' CPU XP3R3V_EARLY ',\ + float(get_pmc_register('in1_input'))/1000, 'V' + print '\n CPU XP5R0V_CP ',\ + float(get_pmc_register('in2_input'))/1000, 'V' + print ' CPU XP3R3V_STD ',\ + float(get_pmc_register('in3_input'))/1000, 'V' + print ' CPU XP3R3V_CP ',\ + float(get_pmc_register('in4_input'))/1000, 'V' + print ' CPU XP0R75V_VTT_A ',\ + float(get_pmc_register('in5_input'))/1000, 'V' + print ' CPU XPPR75V_VTT_B ',\ + float(get_pmc_register('in6_input'))/1000, 'V' + print ' CPU XP1R07V_CPU ',\ + float(get_pmc_register('in7_input'))/1000, 'V' + print ' CPU XP1R0V_CPU ',\ + float(get_pmc_register('in8_input'))/1000, 'V' + print ' CPU XP12R0V ',\ + float(get_pmc_register('in9_input'))/1000, 'V' + print ' CPU VDDR_CPU_2 ',\ + float(get_pmc_register('in10_input'))/1000, 'V' + print ' CPU VDDR_CPU_1 ',\ + float(get_pmc_register('in11_input'))/1000, 'V' + print ' CPU XP1R5V_CLK ',\ + float(get_pmc_register('in12_input'))/1000, 'V' + print ' CPU XP1R8V_CPU ',\ + float(get_pmc_register('in13_input'))/1000, 'V' + print ' CPU XP1R0V_CPU_VNN ',\ + float(get_pmc_register('in14_input'))/1000, 'V' + print ' CPU XP1R0V_CPU_VCC ',\ + float(get_pmc_register('in15_input'))/1000, 'V' + print ' CPU XP1R5V_EARLY ',\ + float(get_pmc_register('in16_input'))/1000, 'V' + print ' SW XP3R3V_MON ',\ + float(get_pmc_register('in17_input'))/1000, 'V' + print ' SW XP1R8V_MON ',\ + float(get_pmc_register('in19_input'))/1000, 'V' + print ' SW XP1R2V_MON ',\ + float(get_pmc_register('in20_input'))/1000, 'V' + print ' SW XP1R0V_SW_MON ',\ + float(get_pmc_register('in21_input'))/1000, 'V' + print ' SW XP1R0V_ROV_SW_MON ',\ + float(get_pmc_register('in22_input'))/1000, 'V' + print ' SW XR1R0V_BCM84752_MON ',\ + float(get_pmc_register('in23_input'))/1000, 'V' + print ' SW XP5V_MB_MON ',\ + float(get_pmc_register('in24_input'))/1000, 'V' + print ' SW XP1R8V_FPGA_MON ',\ + float(get_pmc_register('in25_input'))/1000, 'V' + print ' SW XP3R3V_FPGA_MON ',\ + float(get_pmc_register('in26_input'))/1000, 'V' + print ' SW XP3R3V_EARLY_MON ',\ + float(get_pmc_register('in27_input'))/1000, 'V' + print ' SW XP1R0V_ ',\ + float(get_pmc_register('curr21_input'))/10000, 'A' + print ' SW XP1R0V_ROV ',\ + float(get_pmc_register('curr22_input'))/10000, 'A' + + + +print_voltage_sensors() + +# Print the information for 1 Fan Tray + + +def print_fan_tray(tray): + + Fan_Status = ['Normal', 'Abnormal'] + Airflow_Direction = ['B2F', 'F2B'] + + print ' Fan Tray ' + str(tray) + ':' + + if (tray == 1): + fan1_speed = get_pmc_register('fan1_input') + fan2_speed = get_pmc_register('fan2_input') + air_flow_reg = int(get_pmc_register('fan1_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + fan2_status = 0 if fan2_speed >= 1000 else 1 + + print ' Fan1 Speed: ', fan1_speed, 'RPM' + print ' Fan2 Speed: ', fan2_speed, 'RPM' + print ' Fan1 State: ', Fan_Status[fan1_status] + print ' Fan2 State: ', Fan_Status[fan2_status] + print ' Air Flow: ', Airflow_Direction[air_flow_reg] + elif (tray == 2): + fan1_speed = get_pmc_register('fan3_input') + fan2_speed = get_pmc_register('fan4_input') + air_flow_reg = int(get_pmc_register('fan3_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + fan2_status = 0 if fan2_speed >= 1000 else 1 + + print ' Fan1 Speed: ', fan1_speed, 'RPM' + print ' Fan2 Speed: ', fan2_speed, 'RPM' + print ' Fan1 State: ', Fan_Status[fan1_status] + print ' Fan2 State: ', Fan_Status[fan2_status] + print ' Air Flow: ', Airflow_Direction[air_flow_reg] + elif (tray == 3): + fan1_speed = get_pmc_register('fan5_input') + fan2_speed = get_pmc_register('fan6_input') + air_flow_reg = int(get_pmc_register('fan5_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + fan2_status = 0 if fan2_speed >= 1000 else 1 + + print ' Fan1 Speed: ', fan1_speed, 'RPM' + print ' Fan2 Speed: ', fan2_speed, 'RPM' + print ' Fan1 State: ', Fan_Status[fan1_status] + print ' Fan2 State: ', Fan_Status[fan2_status] + print ' Air Flow: ', Airflow_Direction[air_flow_reg] + elif (tray == 4): + fan1_speed = get_pmc_register('fan7_input') + fan2_speed = get_pmc_register('fan8_input') + air_flow_reg = int(get_pmc_register('fan7_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + fan2_status = 0 if fan2_speed >= 1000 else 1 + + print ' Fan1 Speed: ', fan1_speed, 'RPM' + print ' Fan2 Speed: ', fan2_speed, 'RPM' + print ' Fan1 State: ', Fan_Status[fan1_status] + print ' Fan2 State: ', Fan_Status[fan2_status] + print ' Air Flow: ', Airflow_Direction[air_flow_reg] + elif (tray == 5): + fan1_speed = get_pmc_register('fan9_input') + fan2_speed = get_pmc_register('fan10_input') + air_flow_reg = int(get_pmc_register('fan9_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + fan2_status = 0 if fan2_speed >= 1000 else 1 + + print ' Fan1 Speed: ', fan1_speed, 'RPM' + print ' Fan2 Speed: ', fan2_speed, 'RPM' + print ' Fan1 State: ', Fan_Status[fan1_status] + print ' Fan2 State: ', Fan_Status[fan2_status] + print ' Air Flow: ', Airflow_Direction[air_flow_reg] + + +print('\nFan Trays:') +fan_tray_presence = get_pmc_register('fan_tray_presence') + +if (fan_tray_presence != 'ERR'): + fan_tray_presence = int(fan_tray_presence, 16) + + for tray in range(0, Z9100_MAX_FAN_TRAYS): + if (fan_tray_presence & (1 << tray)): + print_fan_tray(tray + 1) + else: + print '\n Fan Tray ' + str(tray + 1) + ': Not present' +else: + logging.error('Unable to read FAN presence') + +# Print the information for PSU1, PSU2 + + +def print_psu(psu): + Psu_Type = ['Normal', 'Mismatch'] + Psu_Input_Type = ['AC', 'DC'] + PSU_STATUS_TYPE_BIT = 4 + PSU_STATUS_INPUT_TYPE_BIT = 1 + PSU_FAN_PRESENT_BIT = 2 + PSU_FAN_STATUS_BIT = 1 + PSU_FAN_AIR_FLOW_BIT = 0 + Psu_Fan_Presence = ['Present', 'Absent'] + Psu_Fan_Status = ['Normal', 'Abnormal'] + Psu_Fan_Airflow = ['B2F', 'F2B'] + + + print ' PSU ' + str(psu) + ':' + if (psu == 1): + psu_status = int(get_pmc_register('psu1_presence'), 16) + else: + psu_status = int(get_pmc_register('psu2_presence'), 16) + + psu_input_type = (psu_status & (1 << PSU_STATUS_INPUT_TYPE_BIT)) >>\ + PSU_STATUS_INPUT_TYPE_BIT + psu_type = (psu_status & (1 << PSU_STATUS_TYPE_BIT)) >>\ + PSU_STATUS_TYPE_BIT + + print ' Input: ', Psu_Input_Type[psu_input_type] + print ' Type: ', Psu_Type[psu_type] + + # PSU FAN details + if (psu == 1): + print ' FAN Speed: ', get_pmc_register('fan11_input'), 'RPM' + psu_fan_airflow = int(get_pmc_register('fan11_airflow')) + psu_fan_status = int(get_pmc_register('fan11_alarm')) + psu_fan_present = int(get_pmc_register('fan11_fault')) + input_voltage = float(get_pmc_register('in29_input')) / 1000 + output_voltage = float(get_pmc_register('in30_input')) / 1000 + input_current = float(get_pmc_register('curr601_input')) / 100 + output_current = float(get_pmc_register('curr602_input')) /100 + input_power = float(get_pmc_register('power1_input')) / 1000000 + output_power = float(get_pmc_register('power2_input')) / 1000000 + if (input_power != 0): + psu_fan_temp = int(get_pmc_register('temp14_input'))/1000 + else: + print ' FAN Speed: ', get_pmc_register('fan12_input'), 'RPM' + psu_fan_airflow = int(get_pmc_register('fan12_airflow')) + psu_fan_status = int(get_pmc_register('fan12_alarm')) + psu_fan_present = int(get_pmc_register('fan12_fault')) + input_voltage = float(get_pmc_register('in31_input')) / 1000 + output_voltage = float(get_pmc_register('in32_input')) / 1000 + input_current = float(get_pmc_register('curr701_input')) / 100 + output_current = float(get_pmc_register('curr702_input')) / 100 + input_power = float(get_pmc_register('power3_input')) / 1000000 + output_power = float(get_pmc_register('power4_input')) / 1000000 + if (input_power != 0): + psu_fan_temp = int(get_pmc_register('temp15_input'))/1000 + + print ' FAN: ', Psu_Fan_Presence[psu_fan_present] + print ' FAN Status: ', Psu_Fan_Status[psu_fan_status] + print ' FAN AIRFLOW: ', Psu_Fan_Airflow[psu_fan_airflow] + + # PSU input & output monitors + print ' Input Voltage: %6.2f' % (input_voltage), 'V' + + print ' Output Voltage: %6.2f' % (output_voltage), 'V' + + print ' Input Current: %6.2f' % (input_current), 'A' + + print ' Output Current: %6.2f' % (output_current), 'A' + + print ' Input Power: %6.2f' % (input_power), 'W' + + print ' Output Power: %6.2f' % (output_power), 'W' + + # PSU firmware gives spurious temperature reading without input power + if (input_power != 0): + print ' Temperature: ', psu_fan_temp, 'C' + else: + print ' Temperature: ', 'NA' + +print('\nPSUs:') +for psu in range(1, Z9100_MAX_PSUS + 1): + + if (psu == 1): + psu_status = get_pmc_register('psu1_presence') + else: + psu_status = get_pmc_register('psu2_presence') + + if (psu_status != 'ERR'): + psu_status = int(psu_status, 16) + + if (~psu_status & 0b1): + print_psu(psu) + else: + print '\n PSU ', psu, 'Not present' + else: + logging.error('Unable to check PSU presence') + +print '\n Total Power: ', get_pmc_register('current_total_power'), 'W' diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/sensors b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/sensors new file mode 100755 index 000000000000..030d636a1565 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/sensors @@ -0,0 +1,7 @@ +#!/bin/bash +docker exec -i pmon sensors "$@" + +#To probe sensors not part of lm-sensors +if [ -r /usr/local/bin/platform_sensors.py ]; then + python /usr/local/bin/platform_sensors.py +fi diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/z9100_platform.sh b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/z9100_platform.sh new file mode 100755 index 000000000000..e264ff6ce644 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/z9100_platform.sh @@ -0,0 +1,193 @@ +#!/bin/bash + +#platform init script for Dell Z9100 + +source dell_i2c_utils.sh + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [[ $found -eq 0 ]] && echo "cannot find iSMT" && exit 1 +} + +# Attach/Detach CPU board mux @ 0x70 +cpu_board_mux() { + case $1 in + "new_device") i2c_config "echo pca9547 0x70 > /sys/bus/i2c/devices/i2c-${devnum}/$1" + ;; + "delete_device") i2c_config "echo 0x70 > /sys/bus/i2c/devices/i2c-${devnum}/$1" + ;; + *) echo "z9100_platform: cpu_board_mux: invalid command !" + ;; + esac +} + +# Attach/Detach switch board MUX to IOM CPLDs @ 0x71 +switch_board_mux() { + case $1 in + "new_device") i2c_config "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-4/$1" + ;; + "delete_device") i2c_config "echo 0x71 > /sys/bus/i2c/devices/i2c-4/$1" + ;; + *) echo "z9100_platform: switch_board_mux : invalid command !" + ;; + esac +} + +# Attach/Detach syseeprom on CPU board +sys_eeprom() { + case $1 in + "new_device") i2c_config "echo 24c02 0x50 > /sys/bus/i2c/devices/i2c-2/$1" + ;; + "delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-2/$1" + ;; + *) echo "z9100_platform: sys_eeprom : invalid command !" + ;; + esac +} + +#Attach/Detach cpld devices to drivers for each iom +switch_board_cpld() { + case $1 in + "new_device") + for ((i=14;i<=17;i++)); + do + i2c_config "echo dell_z9100_iom_cpld 0x3e > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + "delete_device") + for ((i=14;i<=17;i++)); + do + i2c_config "echo 0x3e > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + *) echo "z9100_platform: switch_board_cpld : invalid command !" + ;; + esac +} + +#Attach/Detach the MUX connecting all QSFPs +switch_board_qsfp_mux() { + case $1 in + "new_device") + for ((i=9;i>=6;i--)); + do + # 0x71 mux on the IOM 1 + mux_index=$(expr $i - 5) + echo "Attaching PCA9548 $mux_index" + i2c_config "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + "delete_device") + for ((i=9;i>=6;i--)); + do + # 0x71 mux on the IOM 1 + mux_index=$(expr $i - 5) + echo "Detaching PCA9548 $mux_index" + i2c_config "echo 0x71 > /sys/bus/i2c/devices/i2c-$devnum/i2c-$i/$1" + done + ;; + *) echo "z9100_platform: switch_board_qsfp_mux: invalid command !" + ;; + esac +} + +#Attach/Detach the SFP modules on PCA9548_2 +switch_board_sfp() { + case $1 in + "new_device") i2c_config "echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-11/$1" + i2c_config "echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-12/$1" + ;; + "delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-11/$1" + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-12/$1" + ;; + *) echo "z9100_platform: switch_board_sfp: invalid command !" + ;; + esac +} + +# Attach/Detach 32 instances of EEPROM driver QSFP ports on IO module 1 +#eeprom can dump data using below command +switch_board_qsfp() { + case $1 in + "new_device") + for ((i=18;i<=49;i++)); + do + i2c_config "echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + "delete_device") + for ((i=18;i<=49;i++)); + do + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + + *) echo "z9100_platform: switch_board_qsfp: invalid command !" + ;; + esac +} + +# Enable/Disable xcvr presence interrupts +xcvr_presence_interrupts() { + case $1 in + "enable") + for ((i=14;i<=16;i++)); + do + echo 0x0 > /sys/class/i2c-adapter/i2c-$i/$i-003e/qsfp_abs_mask + done + ;; + "disable") + for ((i=14;i<=16;i++)); + do + echo 0xffff > /sys/class/i2c-adapter/i2c-$i/$i-003e/qsfp_abs_mask + done + ;; + *) echo "z9100_platform: xcvr_presence_interrupts: invalid command !" + ;; + esac +} + +init_devnum + +if [[ "$1" == "init" ]]; then + modprobe i2c-dev + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + modprobe dell_ich + modprobe dell_mailbox + modprobe dell_z9100_cpld + + cpu_board_mux "new_device" + switch_board_mux "new_device" + sys_eeprom "new_device" + switch_board_cpld "new_device" + switch_board_qsfp_mux "new_device" + switch_board_sfp "new_device" + switch_board_qsfp "new_device" + xcvr_presence_interrupts "enable" +elif [[ "$1" == "deinit" ]]; then + xcvr_presence_interrupts "disable" + switch_board_sfp "delete_device" + switch_board_cpld "delete_device" + switch_board_mux "delete_device" + sys_eeprom "delete_device" + switch_board_qsfp "delete_device" + switch_board_qsfp_mux "delete_device" + cpu_board_mux "delete_device" + + modprobe -r dell_z9100_cpld + modprobe -r dell_mailbox + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev + modprobe -r dell_ich +else + echo "z9100_platform : Invalid option !" +fi diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/systemd/platform-modules-z9100.service b/platform/broadcom/sonic-platform-modules-dell/z9100/systemd/platform-modules-z9100.service new file mode 100644 index 000000000000..00fbfa6803ef --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/systemd/platform-modules-z9100.service @@ -0,0 +1,13 @@ +[Unit] +Description=Dell Z9100 Platform modules +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/z9100_platform.sh init +ExecStop=/usr/local/bin/z9100_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/cfg/z9264f-modules.conf b/platform/broadcom/sonic-platform-modules-dell/z9264f/cfg/z9264f-modules.conf new file mode 100644 index 000000000000..959ac8290642 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/cfg/z9264f-modules.conf @@ -0,0 +1,19 @@ +# /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. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-gpio +i2c-mux-pca954x + +ipmi_devintf +ipmi_si +dell_z9264f_fpga_ocores +i2c_ocores diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/modules/Makefile b/platform/broadcom/sonic-platform-modules-dell/z9264f/modules/Makefile new file mode 100644 index 000000000000..a162f0d34bfc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := dell_z9264f_fpga_ocores.o + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/modules/dell_z9264f_fpga_ocores.c b/platform/broadcom/sonic-platform-modules-dell/z9264f/modules/dell_z9264f_fpga_ocores.c new file mode 100644 index 000000000000..35ea1f812e9e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/modules/dell_z9264f_fpga_ocores.c @@ -0,0 +1,1418 @@ + /* + * Copyright (C) 2018 Joyce Yu + * + * Licensed under the GNU General Public License Version 2 + * + * 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. + * + */ + +/** + * @file fpga_ocores.c + * @brief This is a driver to interface with Linux Open Cores driver for FPGA i2c access + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include //siginfo +#include //rcu_read_lock +#include //kernel_version +#include +#include +#include +#include +#include + + +void __iomem * fpga_base_addr = NULL; + +#define DRIVER_NAME "fpgapci" +#define PCI_NUM_BARS 4 + +/* Maximum size of driver buffer (allocated with kalloc()). + * Needed to copy data from user to kernel space, among other + * things. */ +static const size_t BUF_SIZE = PAGE_SIZE; + +/* Device data used by this driver. */ +struct fpgapci_dev { + /* the kernel pci device data structure */ + struct pci_dev *pci_dev; + + /* upstream root node */ + struct pci_dev *upstream; + + /* kernels virtual addr. for the mapped BARs */ + void * __iomem bar[PCI_NUM_BARS]; + + /* length of each memory region. Used for error checking. */ + size_t bar_length[PCI_NUM_BARS]; + + /* Debug data */ + /* number of hw interrupts handled. */ + int num_handled_interrupts; + int num_undelivered_signals; + int pci_gen; + int pci_num_lanes; + + unsigned int irq_first; + unsigned int irq_length; + unsigned int irq_assigned; + +}; + +static int use_irq = 0; +module_param(use_irq, int, 0644); +MODULE_PARM_DESC(use_irq, "Get an use_irq value from user...\n"); + + +/* Xilinx FPGA PCIE info: */ +/* Non-VGA unclassified device: Xilinx Corporation Device 7021*/ +/* Subsystem: Xilinx Corporation Device 0007 */ +//#define VENDOR 0x10EE +#define DEVICE 0x7021 +static phys_addr_t fpga_phys_addr; + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + + +/* struct to hold data related to the pcie device */ +struct pci_data_struct{ + struct pci_dev* dev; + unsigned long long phy_addr_bar0; + unsigned long long phy_len_bar0; + unsigned long long phy_flags_bar0; + unsigned int irq_first; + unsigned int irq_length; + unsigned int irq_assigned; + void * kvirt_addr_bar0; +}; + + +/* Static function declarations */ +static int fpgapci_probe(struct pci_dev *dev, const struct pci_device_id *id); +static void fpgapci_remove(struct pci_dev *dev); + +static int scan_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); +static int map_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); +static void free_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); + + +//#define kernel_debug + +struct ocores_i2c { + void __iomem *base; + u32 reg_shift; + u32 reg_io_width; + wait_queue_head_t wait; + //struct i2c_adapter adap; + struct i2c_msg *msg; + int pos; + int nmsgs; + int state; /* see STATE_ */ + //struct clk *clk; + int ip_clock_khz; + int bus_clock_khz; + void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value); + u8 (*getreg)(struct ocores_i2c *i2c, int reg); + u32 timeout; + struct mutex lock; +}; +/* registers */ +#define OCI2C_PRELOW 0 +#define OCI2C_PREHIGH 1 +#define OCI2C_CONTROL 2 +#define OCI2C_DATA 3 +#define OCI2C_CMD 4 /* write only */ +#define OCI2C_STATUS 4 /* read only, same address as OCI2C_CMD */ +#define OCI2C_VER 5 + + + +#define OCI2C_CTRL_IEN 0x40 +#define OCI2C_CTRL_EN 0x80 + +#define OCI2C_CMD_START 0x91 +#define OCI2C_CMD_STOP 0x41 +#define OCI2C_CMD_READ 0x21 +#define OCI2C_CMD_WRITE 0x11 +#define OCI2C_CMD_READ_ACK 0x21 +#define OCI2C_CMD_READ_NACK 0x29 +#define OCI2C_CMD_IACK 0x01 + +#define OCI2C_STAT_IF 0x01 +#define OCI2C_STAT_TIP 0x02 +#define OCI2C_STAT_ARBLOST 0x20 +#define OCI2C_STAT_BUSY 0x40 +#define OCI2C_STAT_NACK 0x80 + +/* SR[7:0] - Status register */ +#define OCI2C_SR_RXACK (1 << 7) /* Receive acknowledge from slave ‘1Â’ = No acknowledge received*/ +#define OCI2C_SR_BUSY (1 << 6) /* Busy, I2C bus busy (as defined by start / stop bits) */ +#define OCI2C_SR_AL (1 << 5) /* Arbitration lost - core lost arbitration */ +#define OCI2C_SR_TIP (1 << 1) /* Transfer in progress */ +#define OCI2C_SR_IF (1 << 0) /* Interrupt flag */ + +#if 0 +#define STATE_DONE 0 +#define STATE_START 1 +#define STATE_WRITE 2 +#define STATE_READ 3 +#define STATE_ERROR 4 +#else +enum { + STATE_DONE = 0, + STATE_INIT, + STATE_ADDR, + STATE_ADDR10, + STATE_START, + STATE_WRITE, + STATE_READ, + STATE_ERROR, +}; +#endif + +#define TYPE_OCORES 0 +#define TYPE_GRLIB 1 + +/*I2C_CH1 Offset address from PCIE BAR 0*/ +#define OCORES_I2C_BASE 0x00006000 +#define OCORES_CH_OFFSET 0x10 + +#define i2c_bus_controller_numb 1 +#define I2C_PCI_MAX_BUS (16) +#define CLS_I2C_CLOCK_LEGACY 0 +#define CLS_I2C_CLOCK_PRESERVE (~0U) + +static struct ocores_i2c opencores_i2c[I2C_PCI_MAX_BUS]; +static struct i2c_adapter i2c_pci_adap[I2C_PCI_MAX_BUS]; +static struct mutex i2c_xfer_lock[I2C_PCI_MAX_BUS]; + +static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite8(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_16(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite16(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite32(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_16be(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite16be(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_32be(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite32be(value, i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg) +{ + return ioread8(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_16(struct ocores_i2c *i2c, int reg) +{ + return ioread16(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg) +{ + return ioread32(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_16be(struct ocores_i2c *i2c, int reg) +{ + return ioread16be(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_32be(struct ocores_i2c *i2c, int reg) +{ + return ioread32be(i2c->base + (reg << i2c->reg_shift)); +} + +static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) +{ + i2c->setreg(i2c, reg, value); +} + +static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) +{ + return i2c->getreg(i2c, reg); +} + + +static void ocores_dump(struct ocores_i2c *i2c) +//static void __maybe_unused ocores_dump(struct ocores_i2c *i2c) +{ + u8 tmp; + + printk(KERN_DEBUG "Opencores register dump:\n"); + + tmp = oc_getreg(i2c, OCI2C_PRELOW); + printk(KERN_DEBUG "OCI2C_PRELOW (%d) = 0x%x\n",OCI2C_PRELOW,tmp); + + tmp = oc_getreg(i2c, OCI2C_PREHIGH); + printk(KERN_DEBUG "OCI2C_PREHIGH(%d) = 0x%x\n",OCI2C_PREHIGH,tmp); + + tmp = oc_getreg(i2c, OCI2C_CONTROL); + printk(KERN_DEBUG "OCI2C_CONTROL(%d) = 0x%x\n",OCI2C_CONTROL,tmp); + + tmp = oc_getreg(i2c, OCI2C_DATA); + printk(KERN_DEBUG "OCI2C_DATA (%d) = 0x%x\n",OCI2C_DATA,tmp); + + tmp = oc_getreg(i2c, OCI2C_CMD); + printk(KERN_DEBUG "OCI2C_CMD (%d) = 0x%x\n",OCI2C_CMD,tmp); +} + +static void ocores_stop(struct ocores_i2c *i2c) +{ + //unsigned long time_out = jiffies + msecs_to_jiffies(i2c->timeout); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); +} + +/* + * dell_get_mutex must be called prior to calling this function. + */ +static int ocores_poll(struct ocores_i2c *i2c) +{ + u8 stat = oc_getreg(i2c, OCI2C_STATUS); + struct i2c_msg *msg = i2c->msg; + u8 addr; + + /* Ready? */ + if (stat & OCI2C_STAT_TIP) + return -EBUSY; + + if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) { + /* Stop has been sent */ + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + if (i2c->state == STATE_ERROR) + return -EIO; + return 0; + } + + /* Error? */ + if (stat & OCI2C_STAT_ARBLOST) { + i2c->state = STATE_ERROR; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return -EAGAIN; + } + + if (i2c->state == STATE_INIT) { + if (stat & OCI2C_STAT_BUSY) + return -EBUSY; + + i2c->state = STATE_ADDR; + } + + if (i2c->state == STATE_ADDR) { + /* 10 bit address? */ + if (i2c->msg->flags & I2C_M_TEN) { + addr = 0xf0 | ((i2c->msg->addr >> 7) & 0x6); + i2c->state = STATE_ADDR10; + } else { + addr = (i2c->msg->addr << 1); + i2c->state = STATE_START; + } + + /* Set read bit if necessary */ + addr |= (i2c->msg->flags & I2C_M_RD) ? 1 : 0; + + oc_setreg(i2c, OCI2C_DATA, addr); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + + return 0; + } + + /* Second part of 10 bit addressing */ + if (i2c->state == STATE_ADDR10) { + oc_setreg(i2c, OCI2C_DATA, i2c->msg->addr & 0xff); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE); + + i2c->state = STATE_START; + return 0; + } + + if (i2c->state == STATE_START || i2c->state == STATE_WRITE) { + i2c->state = (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + + if (stat & OCI2C_STAT_NACK) { + i2c->state = STATE_ERROR; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return -ENXIO; + } + } else { + msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA); + } + + if (i2c->pos >= msg->len) { + i2c->nmsgs--; + i2c->msg++; + i2c->pos = 0; + msg = i2c->msg; + + if (i2c->nmsgs) { + if (!(msg->flags & I2C_M_NOSTART)) { + i2c->state = STATE_ADDR; + return 0; + } else { + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + } + } else { + i2c->state = STATE_DONE; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return 0; + } + } + + if (i2c->state == STATE_READ) { + oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len - 1) ? + OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK); + } else { + oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE); + } + + return 0; +} + +static void ocores_process(struct ocores_i2c *i2c) +{ + struct i2c_msg *msg = i2c->msg; + u8 stat = oc_getreg(i2c, OCI2C_STATUS); + //unsigned long timeout = jiffies + msecs_to_jiffies(1000); + + printk(KERN_DEBUG "ocores_process in. status reg :0x%x\n", stat); + if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) { + /* stop has been sent */ + printk(KERN_DEBUG "ocores_process OCI2C_CMD_IACK stat = 0x%x Set OCI2C_CMD(0%x) OCI2C_CMD_IACK = 0x%x\n",stat, OCI2C_CMD, OCI2C_CMD_IACK); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + wake_up(&i2c->wait); + return; + } + + /* error? */ + if (stat & OCI2C_STAT_ARBLOST) { + i2c->state = STATE_ERROR; + printk(KERN_DEBUG "ocores_process OCI2C_STAT_ARBLOST OCI2C_CMD_STOP\n"); + ocores_stop(i2c); + return; + } + + if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) { + i2c->state = + (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + printk(KERN_DEBUG "ocores_process i2c->state =%d\n",i2c->state); + + if (stat & OCI2C_STAT_NACK) { + i2c->state = STATE_ERROR; + printk(KERN_DEBUG "ocores_process OCI2C_STAT_NACK OCI2C_CMD_STOP\n"); + ocores_stop(i2c);//oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return; + } + } else + { + msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA); + printk(KERN_DEBUG "ocores_process oc_getreg OCI2C_DATA(0x%x) msg->buf[%d] = 0x%x\n",OCI2C_DATA, i2c->pos, msg->buf[i2c->pos]); + } + + /* end of msg? */ + if (i2c->pos == msg->len) { + i2c->nmsgs--; + i2c->msg++; + i2c->pos = 0; + msg = i2c->msg; + + if (i2c->nmsgs) { /* end? */ + /* send start? */ + if (!(msg->flags & I2C_M_NOSTART)) { + //addr = i2c_8bit_addr_from_msg(msg); + u8 addr = (msg->addr << 1); + + if (msg->flags & I2C_M_RD) + addr |= 1; + + i2c->state = STATE_START; + printk(KERN_DEBUG "Set OCI2C_CMD(0%x) addr = 0x%x\n",OCI2C_CMD, addr); + oc_setreg(i2c, OCI2C_DATA, addr); + printk(KERN_DEBUG "Set OCI2C_CMD(0%x) OCI2C_CMD_START = 0x%x\n",OCI2C_CMD, OCI2C_CMD_START); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + return; + } else + { + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + printk(KERN_DEBUG "ocores_process end i2c->state =%d\n",i2c->state); + } + } else { + i2c->state = STATE_DONE; + printk(KERN_DEBUG "ocores_process end i2c->state = STATE_DONE ocores_stop\n"); + ocores_stop(i2c);//oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return; + } + } + + if (i2c->state == STATE_READ) { + printk(KERN_DEBUG "ocores_poll STATE_READ i2c->pos=%d msg->len-1 = 0x%x set OCI2C_CMD = 0x%x\n",i2c->pos, msg->len-1, + i2c->pos == (msg->len-1) ? OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK); + oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len-1) ? + OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK); + } else { + printk(KERN_DEBUG "ocores_process set OCI2C_DATA(0x%x)\n",OCI2C_DATA); + oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]); + printk(KERN_DEBUG "ocores_process set OCI2C_CMD(0x%x) OCI2C_CMD_WRITE = 0x%x\n",OCI2C_CMD, OCI2C_CMD_WRITE); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE); + } +} + +static irqreturn_t ocores_isr(int irq, void *dev_id) +{ + struct ocores_i2c *i2c = dev_id; + ocores_process(i2c); + + return IRQ_HANDLED; +} +void dell_get_mutex(struct ocores_i2c *i2c) +{ + mutex_lock(&i2c->lock); +} + +/** + * dell_release_mutex - release mutex + */ +void dell_release_mutex(struct ocores_i2c *i2c) +{ + mutex_unlock(&i2c->lock); +} + +static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct ocores_i2c *i2c = i2c_get_adapdata(adap); + unsigned long orig_jiffies; + int ret; + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + //printk("%s(), line:%d\n", __func__, __LINE__); + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = (use_irq == 1) ? STATE_START : STATE_INIT; + + //printk(KERN_DEBUG "i2c->msg->addr = 0x%x i2c->msg->flags = 0x%x\n",i2c->msg->addr,i2c->msg->flags); + //printk(KERN_DEBUG "I2C_M_RD = 0x%x i2c->msg->addr << 1 = 0x%x\n",I2C_M_RD,i2c->msg->addr << 1); + + //ocores_dump(i2c); + if (!use_irq) { + /* Handle the transfer */ + while (time_before(jiffies, timeout)) { + dell_get_mutex(i2c); + ret = ocores_poll(i2c); + dell_release_mutex(i2c); + + if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) + return (i2c->state == STATE_DONE) ? num : ret; + + if (ret == 0) + timeout = jiffies + HZ; + + usleep_range(5, 15); + } + + i2c->state = STATE_ERROR; + + return -ETIMEDOUT; + + + } else { + printk(KERN_DEBUG "Set OCI2C_DATA(0%x) val = 0x%x\n",OCI2C_DATA, + (i2c->msg->addr << 1) | ((i2c->msg->flags & I2C_M_RD) ? 1:0)); + oc_setreg(i2c, OCI2C_DATA, + (i2c->msg->addr << 1) | + ((i2c->msg->flags & I2C_M_RD) ? 1:0)); + printk(KERN_DEBUG "Set OCI2C_CMD(0%x) val = 0x%x\n",OCI2C_CMD, OCI2C_CMD_START); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + + /* Interrupt mode */ + if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || + (i2c->state == STATE_DONE), HZ)) + return (i2c->state == STATE_DONE) ? num : -EIO; + else + return -ETIMEDOUT; + } +} + +static int ocores_init(struct ocores_i2c *i2c) +{ + int prescale; + int diff; + u8 ctrl; + + if (i2c->reg_io_width == 0) + i2c->reg_io_width = 1; /* Set to default value */ + + if (!i2c->setreg || !i2c->getreg) { + bool be = 0; //1:big_endian 0:little_endian + + switch (i2c->reg_io_width) { + case 1: + i2c->setreg = oc_setreg_8; + i2c->getreg = oc_getreg_8; + break; + + case 2: + i2c->setreg = be ? oc_setreg_16be : oc_setreg_16; + i2c->getreg = be ? oc_getreg_16be : oc_getreg_16; + break; + + case 4: + i2c->setreg = be ? oc_setreg_32be : oc_setreg_32; + i2c->getreg = be ? oc_getreg_32be : oc_getreg_32; + break; + + default: + printk(KERN_ERR "Unsupported I/O width (%d)\n", + i2c->reg_io_width); + return -EINVAL; + } + } + + ctrl = oc_getreg(i2c, OCI2C_CONTROL); + printk(KERN_DEBUG "%s(), line:%d\n", __func__, __LINE__); + printk(KERN_DEBUG "i2c->base = 0x%p\n",i2c->base); + + printk(KERN_DEBUG "ctrl = 0x%x\n",ctrl); + printk(KERN_DEBUG "set ctrl = 0x%x\n",ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); + + /* make sure the device is disabled */ + oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); + + /* + * I²C Frequency depends on host clock + * input clock of 100MHz + * prescale to 100MHz / ( 5*100kHz) -1 = 199 = 0x4F 100000/(5*100)-1=199=0xc7 + */ + printk(KERN_DEBUG "calculate prescale\n"); + prescale = (i2c->ip_clock_khz / (5 * i2c->bus_clock_khz)) - 1; + printk(KERN_DEBUG "calculate prescale = 0x%x\n",prescale); + prescale = clamp(prescale, 0, 0xffff); + printk(KERN_DEBUG "calculate clamp prescale = 0x%x\n",prescale); + + diff = i2c->ip_clock_khz / (5 * (prescale + 1)) - i2c->bus_clock_khz; + printk(KERN_DEBUG "calculate diff = 0x%x\n",diff); + if (abs(diff) > i2c->bus_clock_khz / 10) { + printk(KERN_ERR "Unsupported clock settings: core: %d KHz, bus: %d KHz\n", + i2c->ip_clock_khz, i2c->bus_clock_khz); + return -EINVAL; + } + + printk(KERN_DEBUG "OCI2C_PRELOW(%d) set = 0x%x\n",OCI2C_PRELOW,prescale & 0xff); + oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff); + printk(KERN_DEBUG "OCI2C_PRHIGH(%d) set = 0x%x\n",OCI2C_PREHIGH,prescale >> 8); + oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8); + + printk(KERN_DEBUG "Init the device\n"); + /* Init the device */ + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + printk(KERN_DEBUG "OCI2C_CONTROL(0x%x) set: 0x%x\n", OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN); + if (!use_irq) + oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_EN); + else + oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN); + + //ocores_dump(i2c); + + /* Initialize interrupt handlers if not already done */ + init_waitqueue_head(&i2c->wait); + + return 0; +} + + +static u32 ocores_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm ocores_algorithm = { + .master_xfer = ocores_xfer, + .functionality = ocores_func, +}; + +static int i2c_pci_add_bus (struct i2c_adapter *adap) +{ + int ret = 0; + /* Register new adapter */ + adap->algo = &ocores_algorithm; + ret = i2c_add_numbered_adapter(adap); + return ret; +} + +static int i2c_init_internal_data(void) +{ + int i; + printk(KERN_DEBUG "%s(), line:%d\n", __func__, __LINE__); + + for( i = 0; i < I2C_PCI_MAX_BUS; i++ ) + { + opencores_i2c[i].reg_shift = 0; /* 8 bit registers */ + opencores_i2c[i].reg_io_width = 1; /* 8 bit read/write */ + opencores_i2c[i].timeout = 1000;//1ms + opencores_i2c[i].ip_clock_khz = 100000;/* input clock of 100MHz */ + opencores_i2c[i].bus_clock_khz = 100; + //opencores_i2c[i].base = fpga_base_addr + OCORES_I2C_BASE + i*OCORES_CH_OFFSET; + opencores_i2c[i].base = fpga_base_addr + i*OCORES_CH_OFFSET; + mutex_init(&opencores_i2c[i].lock); + ocores_init(&opencores_i2c[i]); + } + +#if 0 + printk(KERN_DEBUG "FPGA PCIE access test\n"); + writel(0xdeadbeef, fpga_base_addr + 0x04); + printk(KERN_DEBUG "%s(), fpga_base_addr + 0x8000:0x%x\n", __func__, readl(fpga_base_addr + 0x8000)); + printk(KERN_DEBUG "%s(), SCRTCH_REG:0x%x\n", __func__, readl(fpga_base_addr + 0x04)); +#endif + return 0; +} + + +static int i2c_pci_init (void) +{ + int i; + + memset (&i2c_pci_adap, 0, sizeof(i2c_pci_adap)); + memset (&opencores_i2c, 0, sizeof(opencores_i2c)); + for(i=0; i < i2c_bus_controller_numb; i++) + mutex_init(&i2c_xfer_lock[i]); + + /* Initialize driver's itnernal data structures */ + i2c_init_internal_data(); + + for (i = 0 ; i < I2C_PCI_MAX_BUS ; i ++) { + + i2c_pci_adap[i].owner = THIS_MODULE; + i2c_pci_adap[i].class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + + i2c_pci_adap[i].algo_data = &opencores_i2c[i]; + /* /dev/i2c-600 ~ /dev/i2c-600 for Open core I2C channel controller 1-7 */ + i2c_pci_adap[i].nr = i+600; + sprintf( i2c_pci_adap[ i ].name, "i2c-pci-%d", i ); + /* Add the bus via the algorithm code */ + if( i2c_pci_add_bus( &i2c_pci_adap[ i ] ) != 0 ) + { + printk(KERN_ERR "Cannot add bus %d to algorithm layer\n", i ); + return( -ENODEV ); + } + i2c_set_adapdata(&i2c_pci_adap[i], &opencores_i2c[i]); + printk( KERN_DEBUG "Registered bus id: %s\n", kobject_name(&i2c_pci_adap[ i ].dev.kobj)); + } + + return 0; +} + +static void i2c_pci_deinit(void) +{ + int i; + for( i = 0; i < I2C_PCI_MAX_BUS; i++ ){ + i2c_del_adapter(&i2c_pci_adap[i]); + } + +} + +/* Find upstream PCIe root node. + * Used for re-training and disabling AER. */ +static struct pci_dev* find_upstream_dev (struct pci_dev *dev) +{ + struct pci_bus *bus = 0; + struct pci_dev *bridge = 0; + struct pci_dev *cur = 0; + int found_dev = 0; + + bus = dev->bus; + if (bus == 0) { + printk (KERN_DEBUG "Device doesn't have an associated bus!\n"); + return 0; + } + + bridge = bus->self; + if (bridge == 0) { + printk (KERN_DEBUG "Can't get the bridge for the bus!\n"); + return 0; + } + + printk (KERN_DEBUG "Upstream device %x/%x, bus:slot.func %02x:%02x.%02x\n", + bridge->vendor, bridge->device, + bridge->bus->number, PCI_SLOT(bridge->devfn), PCI_FUNC(bridge->devfn)); + + printk (KERN_DEBUG "List of downstream devices:"); + list_for_each_entry (cur, &bus->devices, bus_list) { + if (cur != 0) { + printk (KERN_DEBUG " %x/%x", cur->vendor, cur->device); + if (cur == dev) { + found_dev = 1; + } + } + } + printk (KERN_DEBUG "\n"); + if (found_dev) { + return bridge; + } else { + printk (KERN_DEBUG "Couldn't find upstream device!\n"); + return 0; + } +} + + +static int scan_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + int i; + + for (i = 0; i < PCI_NUM_BARS; i++) { + unsigned long bar_start = pci_resource_start(dev, i); + if (bar_start) { + unsigned long bar_end = pci_resource_end(dev, i); + unsigned long bar_flags = pci_resource_flags(dev, i); + printk (KERN_DEBUG "BAR[%d] 0x%08lx-0x%08lx flags 0x%08lx", + i, bar_start, bar_end, bar_flags); + } + } + + return 0; +} + + +/** + * Map the device memory regions into kernel virtual address space + * after verifying their sizes respect the minimum sizes needed, given + * by the bar_min_len[] array. + */ +static int map_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + int i; + + for (i = 0; i < PCI_NUM_BARS; i++){ + phys_addr_t bar_start = pci_resource_start(dev, i); + phys_addr_t bar_end = pci_resource_end(dev, i); + unsigned long bar_length = bar_end - bar_start + 1; + fpgapci->bar_length[i] = bar_length; + + + if (!bar_start || !bar_end) { + fpgapci->bar_length[i] = 0; + continue; + } + + if (bar_length < 1) { + printk ( "BAR #%d length is less than 1 byte\n", i); + continue; + } + + //printk ( "bar_start=%llx, bar_end=%llx, bar_length=%lx, flag=%lx\n", bar_start, + // bar_end, bar_length, pci_resource_flags(dev, i)); + + /* map the device memory or IO region into kernel virtual + * address space */ + fpgapci->bar[i] = ioremap_nocache (bar_start + OCORES_I2C_BASE, I2C_PCI_MAX_BUS * OCORES_CH_OFFSET); + if (!fpgapci->bar[i]) { + printk ( "Could not map BAR #%d.\n", i); + return -1; + } + + //printk ( "BAR[%d] mapped at 0x%p with length %lu.", i, + // fpgapci->bar[i], bar_length); + + if(i == 0) //FPGA register is in the BAR[0] + { + fpga_phys_addr = bar_start; + fpga_base_addr = fpgapci->bar[i]; + } + + printk (KERN_DEBUG "BAR[%d] mapped at 0x%p with length %lu.\n", i, + fpgapci->bar[i], bar_length); + } + return 0; +} + +static void free_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + int i; + + for (i = 0; i < PCI_NUM_BARS; i++) { + if (fpgapci->bar[i]) { + pci_iounmap(dev, fpgapci->bar[i]); + fpgapci->bar[i] = NULL; + } + } +} + +#define FPGA_PCI_NAME "FPGA_PCI" + +/** + * @brief Register specific function with msi interrupt line + * @param dev Pointer to pci-device, which should be allocated + * @param int interrupt number relative to global interrupt number + * @return Returns error code or zero if success + * */ +static int register_intr_handler(struct pci_dev *dev, int c) +{ + int err = 0; + struct fpgapci_dev *fpgapci = 0; + + fpgapci = (struct fpgapci_dev*) dev_get_drvdata(&dev->dev); + if (fpgapci == 0) { + printk (KERN_ERR ": fpgapci_dev is 0\n"); + return err; + } + + + /* Request interrupt line for unique function + * alternatively function will be called from free_irq as well with flag IRQF_SHARED */ + switch(c) { + /*Currently we only support test vector 2 for Open core I2C channel controller 1-7 interrupt*/ + case 0: + err = request_irq(dev->irq + c, ocores_isr, IRQF_EARLY_RESUME, FPGA_PCI_NAME, &opencores_i2c[0]); + fpgapci->irq_assigned++; + printk(KERN_DEBUG "Interrupt Line %d assigned with return value %d\n", dev->irq + c, err); + break; + + default: + printk(KERN_DEBUG "No more interrupt handler for number (%d)\n", dev->irq + c); + break; + } + return err; +} +/* Mask for MSI Multi message enable bits */ +#define MSI_MME 0x70 +/** + * These enums define the type of interrupt scheme that the overall + * system uses. + */ +enum fpga_irq_type { + INT_MSI_SINGLE, + INT_MSI_MULTI, + INT_MSIX, + INT_NONE, + INT_FENCE /* Last item to guard from loop run-overs */ +}; +/** + * @def PCI_DEVICE_STATUS + * define the offset for STS register + * from the start of PCI config space as specified in the + * NVME_Comliance 1.0b. offset 06h:STS - Device status. + * This register has error status for NVME PCI Exress + * Card. After reading data from this reagister, the driver + * will identify if any error is set during the operation and + * report as kernel alert message. + */ +#define PCI_DEVICE_STATUS 0x6 +/** + * @def NEXT_MASK + * This indicates the location of the next capability item + * in the list. + */ +#define NEXT_MASK 0xFF00 +/** + * @def MSIXCAP_ID + * This bit indicates if the pointer leading to this position + * is a capability. + */ +#define MSIXCAP_ID 0x11 +/** + * @def MSICAP_ID + * This bit indicates if the pointer leading to this position + * is a capability. + */ +#define MSICAP_ID 0x5 + +/** + * @def CL_MASK + * This bit position indicates Capabilities List of the controller + * The controller should support the PCI Power Management cap as a + * minimum. + */ +#define CL_MASK 0x0010 + +/** + * @def CAP_REG + * Set to offset defined in NVME Spec 1.0b. + */ +#define CAP_REG 0x34 +static void msi_set_enable(struct pci_dev *dev, int enable) +{ + int pos,maxvec; + u16 control; + int request_private_bits = 4; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + printk(KERN_DEBUG "pos = 0x%x\n", pos); + if (pos) { + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); + maxvec = 1 << ((control & PCI_MSI_FLAGS_QMASK) >> 1); + printk(KERN_DEBUG "control = 0x%x maxvec = 0x%x\n", control, maxvec); + control &= ~PCI_MSI_FLAGS_ENABLE; +#if 0 + if (enable) + control |= PCI_MSI_FLAGS_ENABLE; +#else + /* + * The PCI 2.3 spec mandates that there are at most 32 + * interrupts. If this device asks for more, only give it one. + */ + if (request_private_bits > 5) { + request_private_bits = 0; + } + + /* Update the number of IRQs the device has available to it */ + control &= ~PCI_MSI_FLAGS_QSIZE; + control |= (request_private_bits << 4); +#endif + + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); + } +} +static void msi_setup_enable(struct pci_dev *dev, int request_private_bits) +{ + int pos,maxvec; + u16 control; + int configured_private_bits = 4; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + + /* + * Read the MSI config to figure out how many IRQs this device + * wants. Most devices only want 1, which will give + * configured_private_bits and request_private_bits equal 0. + */ + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); + + /* + * If the number of private bits has been configured then use + * that value instead of the requested number. This gives the + * driver the chance to override the number of interrupts + * before calling pci_enable_msi(). + */ + configured_private_bits = (control & PCI_MSI_FLAGS_QSIZE) >> 4; + if (configured_private_bits == 0) { + /* Nothing is configured, so use the hardware requested size */ + request_private_bits = (control & PCI_MSI_FLAGS_QMASK) >> 1; + } + else { + /* + * Use the number of configured bits, assuming the + * driver wanted to override the hardware request + * value. + */ + request_private_bits = configured_private_bits; + } + + /* + * The PCI 2.3 spec mandates that there are at most 32 + * interrupts. If this device asks for more, only give it one. + */ + if (request_private_bits > 5) { + request_private_bits = 0; + } + + /* Update the number of IRQs the device has available to it */ + control &= ~PCI_MSI_FLAGS_QSIZE; + control |= (request_private_bits << 4); + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); +} +/** + * @brief Enables pcie-device and claims/remaps neccessary bar resources + * @param dev Pointer to pci-device, which should be allocated + * @return Returns error code or zero if success + * */ +static int claim_device(struct fpgapci_dev *fpgapci,struct pci_dev *dev) +{ + int err = 0; + u16 msi_offset; + u16 mc_val; + + /* wake up the pci device */ + err = pci_enable_device(dev); + if(err) { + printk(KERN_ERR "failed to enable pci device %d\n", err); + goto error_pci_en; + } + + /* on platforms with buggy ACPI, pdev->msi_enabled may be set to + * allow pci_enable_device to work. This indicates INTx was not routed + * and only MSI should be used + */ + + //dev->msi_enabled = 0; + pci_set_master(dev); + + /* Setup the BAR memory regions */ + err = pci_request_regions(dev, DRIVER_NAME); + if (err) { + printk(KERN_ERR "failed to enable pci device %d\n", err); + goto error_pci_req; + } + + scan_bars(fpgapci, dev); + + if (map_bars(fpgapci, dev)) { + goto fail_map_bars; + } + + i2c_pci_init(); + + return 0; + /* ERROR HANDLING */ +fail_map_bars: + pci_release_regions(dev); +error_pci_req: + pci_disable_device(dev); +error_pci_en: + return -ENODEV; +} +/** + * @brief Configures pcie-device and bit_mask settings + * @param dev Pointer to pci-device, which should be allocated + * @return Returns error code or zero if success + * */ +static int configure_device(struct pci_dev *dev) +{ + return 0; +} + + +/* + * Check if the controller supports the interrupt type requested. If it + * supports returns the offset, otherwise it will return invalid for the + * caller to indicate that the controller does not support the capability + * type. + */ +int check_cntlr_cap(struct pci_dev *dev, enum fpga_irq_type cap_type, + u16 *offset) +{ + u16 val = 0; + u16 pci_offset = 0; + int ret_val = -EINVAL; + + if (pci_read_config_word(dev, PCI_DEVICE_STATUS, &val) < 0) { + printk(KERN_ERR "pci_read_config failed...\n"); + return -EINVAL; + } + printk(KERN_DEBUG "PCI_DEVICE_STATUS = 0x%X\n", val); + if (!(val & CL_MASK)) { + printk(KERN_ERR "Controller does not support Capability list...\n"); + return -EINVAL; + } else { + if (pci_read_config_word(dev, CAP_REG, &pci_offset) < 0) { + printk(KERN_ERR "pci_read_config failed...\n"); + return -EINVAL; + } + } + printk(KERN_DEBUG "pci_offset = 0x%x\n", pci_offset); + /* Interrupt Type MSI-X*/ + if (cap_type == INT_MSIX) { + /* Loop through Capability list */ + while (pci_offset) {//0x40 + if (pci_read_config_word(dev, pci_offset, &val) < 0) { + printk(KERN_ERR "pci_read_config failed...\n"); + return -EINVAL; + } + /* exit when we find MSIX_capbility offset */ + if ((val & ~NEXT_MASK) == MSIXCAP_ID) { + /* write msix cap offset */ + *offset = pci_offset; + ret_val = 1; + /* break from while loop */ + break; + } + /* Next Capability offset. */ + pci_offset = (val & NEXT_MASK) >> 8; + } /* end of while loop */ + + } else if (cap_type == INT_MSI_SINGLE || cap_type == INT_MSI_MULTI) { + /* Loop through Capability list */ + while (pci_offset) {//0x40 + if (pci_read_config_word(dev, pci_offset, &val) < 0) { + printk(KERN_ERR "pci_read_config failed...\n"); + return -EINVAL; + } + printk(KERN_DEBUG "val = 0x%x ~NEXT_MASK= 0x%x val & ~NEXT_MASK = 0x%x\n", val,~NEXT_MASK, val & ~NEXT_MASK); + /* exit when we find MSIX_capbility offset */ + if ((val & ~NEXT_MASK) == MSICAP_ID) { + /* write the msi offset */ + *offset = pci_offset; + ret_val = 1; + printk(KERN_DEBUG "*offset = 0x%x\n", *offset); + /* break from while loop */ + break; + } + /* Next Capability offset. */ + pci_offset = (val & NEXT_MASK) >> 8; + printk(KERN_DEBUG "Next Capability offset pci_offset = 0x%x\n", pci_offset); + } /* end of while loop */ + + } else { + printk(KERN_DEBUG "Invalid capability type specified...\n"); + ret_val = -EINVAL; + } + + return ret_val; +} + +static int claim_msi(struct fpgapci_dev *fpgapci,struct pci_dev *dev) +{ + int err = 0, i; + int nvec, request_vec; + u16 msi_offset; + u16 mc_val; + + /* set up MSI interrupt vector to max size */ + nvec = pci_msi_vec_count(dev); + printk(KERN_DEBUG "Have %d MSI vectors\n", nvec); +#if 0 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))// || defined(WITH_BACKPORTS) + err = pci_enable_msi_range(dev, nvec, nvec); +#else + err = pci_enable_msi_block(dev, nvec + 1); +#endif +#endif + printk(KERN_DEBUG "Check MSI capability\n"); + /* Check if the card Supports MSI capability */ + if (check_cntlr_cap(dev, INT_MSI_MULTI, &msi_offset) < 0) { + printk(KERN_ERR "Controller does not support for MSI capability!!\n"); + return -EINVAL; + } + /* compute MSI MC offset if MSI is supported */ + printk(KERN_DEBUG "check_cntlr_cap return msi_offset = 0x%x\n", msi_offset); + msi_offset += 2; + printk(KERN_DEBUG "msi_offset = 0x%x\n", msi_offset); + /* Read MSI-MC value */ + pci_read_config_word(dev, msi_offset, &mc_val); + printk(KERN_DEBUG "read msi_offset(0x%x) mc_val = 0x%x\n", msi_offset, mc_val); + printk(KERN_DEBUG "(1 << ((mc_val & MSI_MME) >> 4)) = 0x%x\n",(1 << ((mc_val & MSI_MME) >> 4))); + if (nvec > (1 << ((mc_val & MSI_MME) >> 4))) { // power 2 + printk(KERN_DEBUG "IRQs = %d exceed MSI MME = %d\n", nvec, + (1 << ((mc_val & MSI_MME) >> 4))); + /* does not support the requested irq's*/ + } + msi_set_enable(dev,1); + printk(KERN_DEBUG "Check MSI capability after msi_set_enable\n"); + + /* Check if the card Supports MSI capability */ + if (check_cntlr_cap(dev, INT_MSI_MULTI, &msi_offset) < 0) { + printk(KERN_DEBUG "Controller does not support for MSI capability!!\n"); + return -EINVAL; + } + /* compute MSI MC offset if MSI is supported */ + printk(KERN_DEBUG "check_cntlr_cap return msi_offset = 0x%x\n", msi_offset); + msi_offset += 2; + printk(KERN_DEBUG "msi_offset = 0x%x\n", msi_offset); + /* Read MSI-MC value */ + pci_read_config_word(dev, msi_offset, &mc_val); + printk(KERN_DEBUG "read msi_offset(0x%x) mc_val = 0x%x\n", msi_offset, mc_val); + + printk(KERN_DEBUG "(1 << ((mc_val & MSI_MME) >> 4)) = 0x%x\n",(1 << ((mc_val & MSI_MME) >> 4))); + if (nvec > (1 << ((mc_val & MSI_MME) >> 4))) { // power 2 + printk(KERN_DEBUG "IRQs = %d exceed MSI MME = %d\n", nvec, + (1 << ((mc_val & MSI_MME) >> 4))); + /* does not support the requested irq's*/ + } + + /*Above 4.1.12*/ +#if 1 + request_vec = 1; + err = pci_alloc_irq_vectors(dev, request_vec, pci_msi_vec_count(dev), + PCI_IRQ_MSI);//PCI_IRQ_AFFINITY | PCI_IRQ_MSI); +#endif + + if (err <= 0) { + printk(KERN_ERR "Cannot set MSI vector (%d)\n", err); + goto error_no_msi; + } else { + printk(KERN_ERR "Got %d MSI vectors starting at %d\n", err, dev->irq); + } + fpgapci->irq_first = dev->irq; + fpgapci->irq_length = err; + fpgapci->irq_assigned = 0; + + + for(i = 0; i < fpgapci->irq_length; i++) { + err = register_intr_handler(dev, i); + if (err) { + printk(KERN_ERR "Cannot request Interrupt number %d\n", i); + goto error_pci_req_irq; + } + } + + return 0; + +error_pci_req_irq: + //for(i = i-1; i >= 0; i--) + free_irq(fpgapci->irq_first + 0, &opencores_i2c[0]); + pci_disable_msi(fpgapci->pci_dev); +error_no_msi: + return -ENOSPC; +} + +static int fpgapci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct fpgapci_dev *fpgapci = 0; + + printk (KERN_DEBUG " vendor = 0x%x, device = 0x%x, class = 0x%x, bus:slot.func = %02x:%02x.%02x\n", + dev->vendor, dev->device, dev->class, + dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + + fpgapci = kzalloc(sizeof(struct fpgapci_dev), GFP_KERNEL); + + if (!fpgapci) { + printk(KERN_ERR "Couldn't allocate memory!\n"); + goto fail_kzalloc; + } + + fpgapci->pci_dev = dev; + dev_set_drvdata(&dev->dev, (void*)fpgapci); + + fpgapci->upstream = find_upstream_dev (dev); + + if(claim_device(fpgapci,dev)) { + goto error_no_device; + } + + if(configure_device(dev)) { + goto error_cannot_configure; + } + if (use_irq) { + if(claim_msi(fpgapci,dev)) { + goto error_cannot_configure; + } + } + + + return 0; + /* ERROR HANDLING */ +error_cannot_configure: + printk(KERN_ERR "error_cannot_configure\n"); + free_bars (fpgapci, dev); + pci_release_regions(dev); + pci_disable_device(dev); +error_no_device: + i2c_pci_deinit(); + printk(KERN_ERR "error_no_device\n"); +fail_kzalloc: + return -1; +} + +static void fpgapci_remove(struct pci_dev *dev) +{ + struct fpgapci_dev *fpgapci = 0; + //int i; + printk (KERN_DEBUG ": dev is %p\n", dev); + + if (dev == 0) { + printk (KERN_ERR ": dev is 0\n"); + return; + } + + fpgapci = (struct fpgapci_dev*) dev_get_drvdata(&dev->dev); + if (fpgapci == 0) { + printk (KERN_ERR ": fpgapci_dev is 0\n"); + return; + } + i2c_pci_deinit(); + if (use_irq) + free_irq(fpgapci->irq_first + 0, &opencores_i2c[0]); + pci_disable_msi(fpgapci->pci_dev); + free_bars (fpgapci, dev); + pci_disable_device(dev); + pci_release_regions(dev); + + kfree (fpgapci); +} + +static const struct pci_device_id fpgapci_ids[] = { + {PCI_DEVICE(PCI_VENDOR_ID_XILINX, DEVICE)}, + {0, }, +}; + +MODULE_DEVICE_TABLE(pci, fpgapci_ids); + +static struct pci_driver fpgapci_driver = { + .name = DRIVER_NAME, + .id_table = fpgapci_ids, + .probe = fpgapci_probe, + .remove = fpgapci_remove, + /* resume, suspend are optional */ +}; + +/* Initialize the driver module (but not any device) and register + * the module with the kernel PCI subsystem. */ +static int __init fpgapci_init(void) +{ + + if (pci_register_driver(&fpgapci_driver)) { + printk(KERN_DEBUG "pci_unregister_driver\n"); + pci_unregister_driver(&fpgapci_driver); + return -ENODEV; + } + + return 0; +} + +static void __exit fpgapci_exit(void) +{ + printk (KERN_DEBUG "fpgapci_exit"); + /* unregister this driver from the PCI bus driver */ + pci_unregister_driver(&fpgapci_driver); + +} + + +module_init (fpgapci_init); +module_exit (fpgapci_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Joyce_Yu@Dell.com"); +MODULE_DESCRIPTION ("Driver for FPGA Opencores I2C bus"); +MODULE_SUPPORTED_DEVICE ("FPGA Opencores I2C bus"); + + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/check_qsfp.sh b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/check_qsfp.sh new file mode 100755 index 000000000000..7e7f1636a186 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/check_qsfp.sh @@ -0,0 +1,3 @@ +# Temporary dummy file for z9264f. +# Will be updated soon. + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/pcisysfs.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/pcisysfs.py new file mode 100755 index 000000000000..047618e057c8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/pcisysfs.py @@ -0,0 +1,102 @@ +#!/usr/bin/python +# Copyright (c) 2015 Dell Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +# +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. + +import struct +import sys +import getopt +from os import * +from mmap import * + +def usage(): + ''' This is the Usage Method ''' + + print '\t\t pcisysfs.py --get --offset --res ' + print '\t\t pcisysfs.py --set --val --offset --res ' + sys.exit(1) + +def pci_mem_read(mm,offset): + mm.seek(offset) + read_data_stream=mm.read(4) + print "" + reg_val=struct.unpack('I',read_data_stream) + print "reg_val read:%x"%reg_val + return reg_val + +def pci_mem_write(mm,offset,data): + mm.seek(offset) + print "data to write:%x"%data + mm.write(struct.pack('I',data)) + +def pci_set_value(resource,val,offset): + fd=open(resource,O_RDWR) + mm=mmap(fd,0) + pci_mem_write(mm,offset,val) + +def pci_get_value(resource,offset): + fd=open(resource,O_RDWR) + mm=mmap(fd,0) + pci_mem_read(mm,offset) + +def main(argv): + + ''' The main function will read the user input from the + command line argument and process the request ''' + + opts = '' + val = '' + choice = '' + resource = '' + offset = '' + + try: + opts, args = getopt.getopt(argv, "hgsv:" , \ + ["val=","res=","offset=","help", "get", "set"]) + + except getopt.GetoptError: + usage() + + for opt,arg in opts: + + if opt in ('-h','--help'): + choice = 'help' + + elif opt in ('-g', '--get'): + choice = 'get' + + elif opt in ('-s', '--set'): + choice = 'set' + + elif opt == '--res': + resource = arg + + elif opt == '--val': + val = int(arg,16) + + elif opt == '--offset': + offset = int(arg,16) + + if choice == 'set' and val != '' and offset !='' and resource !='': + pci_set_value(resource,val,offset) + + elif choice == 'get' and offset != '' and resource !='': + pci_get_value(resource,offset) + + else: + usage() + +#Calling the main method +if __name__ == "__main__": + main(sys.argv[1:]) + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/platform_sensors.py new file mode 100755 index 000000000000..c16aee1d4b8c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/platform_sensors.py @@ -0,0 +1,251 @@ +#!/usr/bin/python +# On Z9264f, the BaseBoard Management Controller is an +# autonomous subsystem provides monitoring and management +# facility independent of the host CPU. IPMI standard +# protocol is used with ipmitool to fetch sensor details. +# Current script support X00 board only. X01 support will +# be added soon. This provies support for the +# following objects: +# * Onboard temperature sensors +# * FAN trays +# * PSU + + +import os +import sys +import logging +import subprocess +import commands + +Z9264F_MAX_FAN_TRAYS = 4 +Z9264F_MAX_PSUS = 2 +IPMI_SENSOR_DATA = "ipmitool sdr list" +IPMI_SENSOR_DUMP = "/tmp/sdr" + +FAN_PRESENCE = "FAN{0}_prsnt" +PSU_PRESENCE = "PSU{0}_state" +# Use this for older firmware +# PSU_PRESENCE="PSU{0}_prsnt" + +ipmi_sdr_list = "" + +# Dump sensor registers + + +def ipmi_sensor_dump(): + + status = 1 + global ipmi_sdr_list + ipmi_cmd = IPMI_SENSOR_DATA + status, ipmi_sdr_list = commands.getstatusoutput(ipmi_cmd) + + if status: + logging.error('Failed to execute:' + ipmi_sdr_list) + sys.exit(0) + +# Fetch a BMC register + + +def get_pmc_register(reg_name): + + for item in ipmi_sdr_list.split("\n"): + if reg_name in item: + output = item.strip() + + if not output: + print('\nFailed to fetch: ' + reg_name + ' sensor ') + sys.exit(0) + + output = output.split('|')[1] + + logging.basicConfig(level=logging.DEBUG) + return output + + +# Print the information for temperature sensors + + +def print_temperature_sensors(): + + print("\nOnboard Temperature Sensors:") + + print ' PT_Left_temp: ',\ + (get_pmc_register('PT_Left_temp')) + print ' PT_Mid_temp: ',\ + (get_pmc_register('PT_Mid_temp')) + print ' PT_Right_temp: ',\ + (get_pmc_register('PT_Right_temp')) + print ' Broadcom Temp: ',\ + (get_pmc_register('TC_Near_temp')) + print ' Inlet Airflow Temp: ',\ + (get_pmc_register('ILET_AF_temp')) + print ' CPU Temp: ',\ + (get_pmc_register('CPU_Near_temp')) + print ' CPU Near Temp: ',\ + (get_pmc_register('CPU_temp')) + print ' DRAM Temp: ',\ + (get_pmc_register('DRAM1_temp')) + +ipmi_sensor_dump() + +print_temperature_sensors() + +# Print the information for 1 Fan Tray + + +def print_fan_tray(tray): + + Fan_Status = [' Normal', ' Abnormal'] + Airflow_Direction = ['B2F', 'F2B'] + + print ' Fan Tray ' + str(tray) + ':' + + if (tray == 1): + + fan1_status = int(get_pmc_register('Fan1_Front_state'), 16) + fan2_status = int(get_pmc_register('Fan1_Rear_state'), 16) + + print ' Fan1 Speed: ',\ + get_pmc_register('FAN1_Front_rpm') + print ' Fan2 Speed: ',\ + get_pmc_register('FAN1_Rear_rpm') + print ' Fan1 State: ',\ + Fan_Status[fan1_status] + print ' Fan2 State: ',\ + Fan_Status[fan2_status] + + elif (tray == 2): + + fan1_status = int(get_pmc_register('Fan2_Front_state'), 16) + fan2_status = int(get_pmc_register('Fan2_Rear_state'), 16) + + print ' Fan1 Speed: ',\ + get_pmc_register('FAN2_Front_rpm') + print ' Fan2 Speed: ',\ + get_pmc_register('FAN2_Rear_rpm') + print ' Fan1 State: ',\ + Fan_Status[fan1_status] + print ' Fan2 State: ',\ + Fan_Status[fan2_status] + + elif (tray == 3): + + fan1_status = int(get_pmc_register('Fan3_Front_state'), 16) + fan2_status = int(get_pmc_register('Fan3_Rear_state'), 16) + + print ' Fan1 Speed: ',\ + get_pmc_register('FAN3_Front_rpm') + print ' Fan2 Speed: ',\ + get_pmc_register('FAN3_Rear_rpm') + print ' Fan1 State: ',\ + Fan_Status[fan1_status] + print ' Fan2 State: ',\ + Fan_Status[fan2_status] + + elif (tray == 4): + + fan1_status = int(get_pmc_register('Fan4_Front_state'), 16) + fan2_status = int(get_pmc_register('Fan4_Rear_state'), 16) + + print ' Fan1 Speed: ',\ + get_pmc_register('FAN4_Front_rpm') + print ' Fan2 Speed: ',\ + get_pmc_register('FAN4_Rear_rpm') + print ' Fan1 State: ',\ + Fan_Status[fan1_status] + print ' Fan2 State: ',\ + Fan_Status[fan2_status] + + +print('\nFan Trays:') + +for tray in range(1, Z9264F_MAX_FAN_TRAYS + 1): + fan_presence = FAN_PRESENCE.format(tray) + if (get_pmc_register(fan_presence)): + print_fan_tray(tray) + else: + print '\n Fan Tray ' + str(tray + 1) + ': Not present' + + +# Print the information for PSU1, PSU2 +def print_psu(psu): + Psu_Type = ['Normal', 'Mismatch'] + Psu_Input_Type = ['AC', 'DC'] + PSU_STATUS_TYPE_BIT = 4 + PSU_STATUS_INPUT_TYPE_BIT = 1 + PSU_FAN_PRESENT_BIT = 2 + PSU_FAN_STATUS_BIT = 1 + PSU_FAN_AIR_FLOW_BIT = 0 + Psu_Fan_Presence = ['Present', 'Absent'] + Psu_Fan_Status = ['Normal', 'Abnormal'] + Psu_Fan_Airflow = ['B2F', 'F2B'] + + # print ' Input: ', Psu_Input_Type[psu_input_type] + # print ' Type: ', Psu_Type[psu_type] + + # PSU FAN details + if (psu == 1): + + # psu1_fan_status = int(get_pmc_register('PSU1_status'),16) + + print ' PSU1:' + print ' FAN Temperature: ',\ + get_pmc_register('PSU1_temp') + print ' FAN AirFlow Temperature: ',\ + get_pmc_register('PSU1_AF_temp') + print ' FAN RPM: ',\ + get_pmc_register('PSU1_rpm') + # print ' FAN Status: ', Psu_Fan_Status[psu1_fan_status] + + # PSU input & output monitors + print ' Input Voltage: ',\ + get_pmc_register('PSU1_In_volt') + print ' Output Voltage: ',\ + get_pmc_register('PSU1_Out_volt') + print ' Input Power: ',\ + get_pmc_register('PSU1_In_watt') + print ' Output Power: ',\ + get_pmc_register('PSU1_Out_watt') + print ' Input Current: ',\ + get_pmc_register('PSU1_In_amp') + print ' Output Current: ',\ + get_pmc_register('PSU1_Out_amp') + + else: + + # psu2_fan_status = int(get_pmc_register('PSU1_status'),16) + print ' PSU2:' + print ' FAN Temperature: ',\ + get_pmc_register('PSU2_temp') + print ' FAN AirFlow Temperature: ',\ + get_pmc_register('PSU2_AF_temp') + print ' FAN RPM: ',\ + get_pmc_register('PSU2_rpm') + # print ' FAN Status: ', Psu_Fan_Status[psu2_fan_status] + + # PSU input & output monitors + print ' Input Voltage: ',\ + get_pmc_register('PSU2_In_volt') + print ' Output Voltage: ',\ + get_pmc_register('PSU2_Out_volt') + print ' Input Power: ',\ + get_pmc_register('PSU2_In_watt') + print ' Output Power: ',\ + get_pmc_register('PSU2_Out_watt') + print ' Input Current: ',\ + get_pmc_register('PSU2_In_amp') + print ' Output Current: ',\ + get_pmc_register('PSU2_Out_amp') + + +print('\nPSUs:') +for psu in range(1, Z9264F_MAX_PSUS + 1): + psu_presence = PSU_PRESENCE.format(psu) + if (get_pmc_register(psu_presence)): + print_psu(psu) + else: + print '\n PSU ', psu, 'Not present' + +print '\n Total Power: ',\ + get_pmc_register('PSU_Total_watt') + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/sensors b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/sensors new file mode 100755 index 000000000000..ee53f2b0f325 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/sensors @@ -0,0 +1,8 @@ +#!/bin/bash +docker exec -i pmon sensors "$@" +docker exec -i pmon /usr/bin/platform_sensors.py "$@" + +#To probe sensors not part of lm-sensors +#if [ -r /usr/local/bin/platform_sensors.py ]; then +# python /usr/local/bin/platform_sensors.py +#fi diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/z9264f_platform.sh b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/z9264f_platform.sh new file mode 100755 index 000000000000..e38914319342 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/z9264f_platform.sh @@ -0,0 +1,124 @@ +#!/bin/bash + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find iSMT" && exit 1 +} + +# Attach/Detach syseeprom on CPU board +sys_eeprom() { + case $1 in + "new_device") echo 24c02 0x53 > /sys/bus/i2c/devices/i2c-0/$1 + ;; + "delete_device") echo 0x53 > /sys/bus/i2c/devices/i2c-0/$1 + ;; + *) echo "z9264f_platform: sys_eeprom : invalid command !" + ;; + esac +} + +#Attach/Detach the MUX connecting all QSFPs +switch_board_qsfp_mux() { + case $1 in + "new_device") + for ((i=74;i<=77;i++)); + do + echo "Attaching PCA9548 @ $i" + echo pca9548 0x$i > /sys/bus/i2c/devices/i2c-604/$1 + sleep 2 + done + + for ((i=74;i<=77;i++)); + do + echo "Attaching PCA9548 @ $i" + echo pca9548 0x$i > /sys/bus/i2c/devices/i2c-603/$1 + sleep 2 + done + ;; + "delete_device") + for ((i=74;i<=77;i++)); + do + echo "Detaching PCA9548 @ $i" + echo 0x$i > /sys/bus/i2c/devices/i2c-604/$1 + sleep 2 + done + + for ((i=74;i<=77;i++)); + do + echo "Detaching PCA9548 @ $i" + echo 0x$i > /sys/bus/i2c/devices/i2c-603/$1 + sleep 2 + done + ;; + *) echo "z9264f_platform: switch_board_qsfp_mux: invalid command !" + ;; + esac + sleep 2 +} + +#Attach/Detach 64 instances of EEPROM driver QSFP ports +#eeprom can dump data using below command +switch_board_qsfp() { + case $1 in + "new_device") + for ((i=2;i<=65;i++)); + do + echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + "delete_device") + for ((i=2;i<=65;i++)); + do + echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + *) echo "z9264f_platform: switch_board_qsfp: invalid command !" + ;; + esac +} + +#Modsel 64 ports to applicable QSFP type modules +#This enables the adapter to respond for i2c commands +switch_board_modsel() { + resource="/sys/bus/pci/devices/0000:04:00.0/resource0" + for ((i=1;i<=64;i++)); + do + port_addr=$( 16384 + ((i - 1) * 16)) + hex=$( printf "0x%x" $port_addr ) + python /bin/pcisysfs.py --set --offset $hex --val 0x41 --res $resource > /dev/null 2>&1 + done +} +init_devnum + +if [ "$1" == "init" ]; then + modprobe i2c-dev + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + modprobe i2c_ocores + modprobe dell_z9264f_fpga_ocores + sys_eeprom "new_device" + switch_board_qsfp_mux "new_device" + switch_board_qsfp "new_device" + switch_board_modsel + +elif [ "$1" == "deinit" ]; then + sys_eeprom "delete_device" + switch_board_qsfp "delete_device" + switch_board_qsfp_mux "delete_device" + + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev +else + echo "z9264f_platform : Invalid option !" +fi + diff --git a/platform/broadcom/sonic-platform-modules-delta/.gitignore b/platform/broadcom/sonic-platform-modules-delta/.gitignore new file mode 100644 index 000000000000..2490baa9d1e2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/.gitignore @@ -0,0 +1,59 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-delta/LICENSE b/platform/broadcom/sonic-platform-modules-delta/LICENSE new file mode 100644 index 000000000000..ea87fe9caabe --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2017 Delta Networks, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/cfg/ag5648-modules.conf b/platform/broadcom/sonic-platform-modules-delta/ag5648/cfg/ag5648-modules.conf new file mode 100644 index 000000000000..552b4103ed02 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/cfg/ag5648-modules.conf @@ -0,0 +1,13 @@ +# /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. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus +i2c-mux-gpio +i2c-mux-pca954x diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/Makefile b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/Makefile new file mode 100644 index 000000000000..012f708ec46a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := dni_ag5648_psu.o dni_emc2305.o delta_ag5648_platform.o + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/delta_ag5648_platform.c b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/delta_ag5648_platform.c new file mode 100644 index 000000000000..16b9ba2fbc4c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/delta_ag5648_platform.c @@ -0,0 +1,1644 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUS4_DEV_NUM 54 +#define DEFAULT_NUM 1 +#define BUS4_BASE_NUM 10 +#define BUS4_MUX_REG 0x18 + +#define TEMP_FAN_VAL 0x06 +#define FANIO_CTL_VAL 0x07 +#define FAN_CTRL_VAL 0x05 +#define PSU1_VAL 0x00 +#define PSU2_VAL 0x20 +#define HOT_SWAP1_VAL 0x10 +#define HOT_SWAP2_VAL 0x30 + +#define SYSTEM_CPLD_REG 0x31 +#define MASTER_CPLD_REG 0x35 +#define SLAVE_CPLD_REG 0x39 + +#define FAN_LED_REG 0x05 +#define LED_REG 0x04 + +#define SFP_PRESENCE_1 0x08 +#define SFP_PRESENCE_2 0x09 +#define SFP_PRESENCE_3 0x0a +#define SFP_PRESENCE_4 0x0b +#define SFP_PRESENCE_5 0x0c +#define SFP_PRESENCE_6 0x08 +#define SFP_PRESENCE_7 0x09 +#define QSFP_PRESENCE 0x12 + +#define QSFP_RESPONSE 0x10 +#define QSFP_LP_MODE 0x11 +#define QSFP_RESET 0x13 + + +#define SFF8436_INFO(data) \ + .type = "sff8436", .addr = 0x50, .platform_data = (data) + +#define SFF_8436_PORT(eedata) \ + .byte_len = 256, .page_size = 1, .flags = SFF_8436_FLAG_READONLY + +#define ag5648_i2c_device_num(NUM){ \ + .name = "delta-ag5648-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &ag5648_i2c_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +/*Define struct to get client of i2c_new_deivce */ +struct i2c_client * i2c_client_9548; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, +}; + +unsigned char reverse_8bits(unsigned char c) +{ + unsigned char s = 0; + int i; + for (i = 0; i < 8; ++i) { + s <<= 1; + s |= c & 1; + c >>= 1; + } + return s; +} +/*---------------- I2C device - start ------------- */ +static void device_release(struct device *dev) +{ + return; +} + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; +/* pca9548 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode[] = { + { .adap_id = 2, + .deselect_on_exit = 1, + }, + { .adap_id = 3, + .deselect_on_exit = 1, + }, + { .adap_id = 4, + .deselect_on_exit = 1, + }, + { .adap_id = 5, + .deselect_on_exit = 1, + }, + { .adap_id = 6, + .deselect_on_exit = 1, + }, + { .adap_id = 7, + .deselect_on_exit = 1, + }, + { .adap_id = 8, + .deselect_on_exit = 1, + }, + { .adap_id = 9, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_data pca954x_data = { + .modes = pca954x_mode, + .num_modes = ARRAY_SIZE(pca954x_mode), +}; + +static struct i2c_board_info __initdata i2c_info_pca9548[] = +{ + { + I2C_BOARD_INFO("pca9548", 0x70), + .platform_data = &pca954x_data, + }, +}; + + +static struct sff_8436_platform_data sff_8436_port[] = { + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, +}; + + +static struct i2c_device_platform_data ag5648_i2c_device_platform_data[] = { + { + /* id eeprom (0x53) */ + .parent = 2, + .info = { I2C_BOARD_INFO("24c02", 0x53) }, + .client = NULL, + }, + { + /* tmp75 (0x4d) */ + .parent = 2, + .info = { I2C_BOARD_INFO("tmp75", 0x4d) }, + .client = NULL, + }, + { + /* tmp75 (0x49) */ + .parent = 3, + .info = { I2C_BOARD_INFO("tmp75", 0x49) }, + .client = NULL, + }, + { + /* tmp75 (0x4b) */ + .parent = 3, + .info = { I2C_BOARD_INFO("tmp75", 0x4b) }, + }, + { + /* tmp75 (0x4c) */ + .parent = 3, + .info = { I2C_BOARD_INFO("tmp75", 0x4c) }, + .client = NULL, + }, + { + /* tmp75 (0x4e) */ + .parent = 3, + .info = { I2C_BOARD_INFO("tmp75", 0x4e) }, + .client = NULL, + }, + { + /* tmp75 (0x4f) */ + .parent = 3, + .info = { I2C_BOARD_INFO("tmp75", 0x4f) }, + }, + { + /* tmp75 (0x4d) */ + .parent = 3, + .info = { I2C_BOARD_INFO("emc2305", 0x4d) }, + .client = NULL, + }, + { + /* tmp75 (0x4d) */ + .parent = 5, + .info = { I2C_BOARD_INFO("emc2305", 0x4d) }, + .client = NULL, + }, + { + /* tmp75 (0x40) */ + .parent = 3, + .info = { I2C_BOARD_INFO("ltc4215", 0x40) }, + .client = NULL, + }, + { + /* tmp75 (0x42) */ + .parent = 3, + .info = { I2C_BOARD_INFO("ltc4215", 0x42) }, + }, + { + /* psu1 (0x59) */ + .parent = 6, + .info = { I2C_BOARD_INFO("dni_ag5648_psu", 0x59) }, + .client = NULL, + }, + { + /* psu2 (0x58) */ + .parent = 6, + .info = { I2C_BOARD_INFO("dni_ag5648_psu", 0x58) }, + }, + { + /* qsfp 1 (0x50) */ + .parent = 10, + .info = { SFF8436_INFO(&sff_8436_port[0]) }, + .client = NULL, + }, + { + /* qsfp 2 (0x50) */ + .parent = 11, + .info = { SFF8436_INFO(&sff_8436_port[1]) }, + .client = NULL, + }, + { + /* qsfp 3 (0x50) */ + .parent = 12, + .info = { SFF8436_INFO(&sff_8436_port[2]) }, + .client = NULL, + }, + { + /* qsfp 4 (0x50) */ + .parent = 13, + .info = { SFF8436_INFO(&sff_8436_port[3]) }, + .client = NULL, + }, + { + /* qsfp 5 (0x50) */ + .parent = 14, + .info = { SFF8436_INFO(&sff_8436_port[4]) }, + .client = NULL, + }, + { + /* qsfp 6 (0x50) */ + .parent = 15, + .info = { SFF8436_INFO(&sff_8436_port[5]) }, + .client = NULL, + }, + { + /* qsfp 7 (0x50) */ + .parent = 16, + .info = { SFF8436_INFO(&sff_8436_port[6]) }, + .client = NULL, + }, + { + /* qsfp 8 (0x50) */ + .parent = 17, + .info = { SFF8436_INFO(&sff_8436_port[7]) }, + .client = NULL, + }, + { + /* qsfp 9 (0x50) */ + .parent = 18, + .info = { SFF8436_INFO(&sff_8436_port[8]) }, + .client = NULL, + }, + { + /* qsfp 10 (0x50) */ + .parent = 19, + .info = { SFF8436_INFO(&sff_8436_port[9]) }, + .client = NULL, + }, + { + /* qsfp 11 (0x50) */ + .parent = 20, + .info = { SFF8436_INFO(&sff_8436_port[10]) }, + .client = NULL, + }, + { + /* qsfp 12 (0x50) */ + .parent = 21, + .info = { SFF8436_INFO(&sff_8436_port[11]) }, + .client = NULL, + }, + { + /* qsfp 13 (0x50) */ + .parent = 22, + .info = { SFF8436_INFO(&sff_8436_port[12]) }, + .client = NULL, + }, + { + /* qsfp 14 (0x50) */ + .parent = 23, + .info = { SFF8436_INFO(&sff_8436_port[13]) }, + .client = NULL, + }, + { + /* qsfp 15 (0x50) */ + .parent = 24, + .info = { SFF8436_INFO(&sff_8436_port[14]) }, + .client = NULL, + }, + { + /* qsfp 16 (0x50) */ + .parent = 25, + .info = { SFF8436_INFO(&sff_8436_port[15]) }, + .client = NULL, + }, + { + /* qsfp 17 (0x50) */ + .parent = 26, + .info = { SFF8436_INFO(&sff_8436_port[16]) }, + .client = NULL, + }, + { + /* qsfp 18 (0x50) */ + .parent = 27, + .info = { SFF8436_INFO(&sff_8436_port[17]) }, + .client = NULL, + }, + { + /* qsfp 19 (0x50) */ + .parent = 28, + .info = { SFF8436_INFO(&sff_8436_port[18]) }, + .client = NULL, + }, + { + /* qsfp 20 (0x50) */ + .parent = 29, + .info = { SFF8436_INFO(&sff_8436_port[19]) }, + .client = NULL, + }, + { + /* qsfp 21 (0x50) */ + .parent = 30, + .info = { SFF8436_INFO(&sff_8436_port[20]) }, + .client = NULL, + }, + { + /* qsfp 22 (0x50) */ + .parent = 31, + .info = { SFF8436_INFO(&sff_8436_port[21]) }, + .client = NULL, + }, + { + /* qsfp 23 (0x50) */ + .parent = 32, + .info = { SFF8436_INFO(&sff_8436_port[22]) }, + .client = NULL, + }, + { + /* qsfp 24 (0x50) */ + .parent = 33, + .info = { SFF8436_INFO(&sff_8436_port[23]) }, + .client = NULL, + }, + { + /* qsfp 25 (0x50) */ + .parent = 34, + .info = { SFF8436_INFO(&sff_8436_port[24]) }, + .client = NULL, + }, + { + /* qsfp 26 (0x50) */ + .parent = 35, + .info = { SFF8436_INFO(&sff_8436_port[25]) }, + .client = NULL, + }, + { + /* qsfp 27 (0x50) */ + .parent = 36, + .info = { SFF8436_INFO(&sff_8436_port[26]) }, + .client = NULL, + }, + { + /* qsfp 28 (0x50) */ + .parent = 37, + .info = { SFF8436_INFO(&sff_8436_port[27]) }, + .client = NULL, + }, + { + /* qsfp 29 (0x50) */ + .parent = 38, + .info = { SFF8436_INFO(&sff_8436_port[28]) }, + .client = NULL, + }, + { + /* qsfp 30 (0x50) */ + .parent = 39, + .info = { SFF8436_INFO(&sff_8436_port[29]) }, + .client = NULL, + }, + { + /* qsfp 31 (0x50) */ + .parent = 40, + .info = { SFF8436_INFO(&sff_8436_port[30]) }, + .client = NULL, + }, + { + /* qsfp 32 (0x50) */ + .parent = 41, + .info = { SFF8436_INFO(&sff_8436_port[31]) }, + .client = NULL, + }, + { + /* qsfp 33 (0x50) */ + .parent = 42, + .info = { SFF8436_INFO(&sff_8436_port[32]) }, + .client = NULL, + }, + { + /* qsfp 34 (0x50) */ + .parent = 43, + .info = { SFF8436_INFO(&sff_8436_port[33]) }, + .client = NULL, + }, + { + /* qsfp 35 (0x50) */ + .parent = 44, + .info = { SFF8436_INFO(&sff_8436_port[34]) }, + .client = NULL, + }, + { + /* qsfp 36 (0x50) */ + .parent = 45, + .info = { SFF8436_INFO(&sff_8436_port[35]) }, + .client = NULL, + }, + { + /* qsfp 37 (0x50) */ + .parent = 46, + .info = { SFF8436_INFO(&sff_8436_port[36]) }, + .client = NULL, + }, + { + /* qsfp 38 (0x50) */ + .parent = 47, + .info = { SFF8436_INFO(&sff_8436_port[37]) }, + .client = NULL, + }, + { + /* qsfp 39 (0x50) */ + .parent = 48, + .info = { SFF8436_INFO(&sff_8436_port[38]) }, + .client = NULL, + }, + { + /* qsfp 40 (0x50) */ + .parent = 49, + .info = { SFF8436_INFO(&sff_8436_port[39]) }, + .client = NULL, + }, + { + /* qsfp 41 (0x50) */ + .parent = 50, + .info = { SFF8436_INFO(&sff_8436_port[40]) }, + .client = NULL, + }, + { + /* qsfp 42 (0x50) */ + .parent = 51, + .info = { SFF8436_INFO(&sff_8436_port[41]) }, + .client = NULL, + }, + { + /* qsfp 43 (0x50) */ + .parent = 52, + .info = { SFF8436_INFO(&sff_8436_port[42]) }, + .client = NULL, + }, + { + /* qsfp 44 (0x50) */ + .parent = 53, + .info = { SFF8436_INFO(&sff_8436_port[43]) }, + .client = NULL, + }, + { + /* qsfp 45 (0x50) */ + .parent = 54, + .info = { SFF8436_INFO(&sff_8436_port[44]) }, + .client = NULL, + }, + { + /* qsfp 46 (0x50) */ + .parent = 55, + .info = { SFF8436_INFO(&sff_8436_port[45]) }, + .client = NULL, + }, + { + /* qsfp 47 (0x50) */ + .parent = 56, + .info = { SFF8436_INFO(&sff_8436_port[46]) }, + .client = NULL, + }, + { + /* qsfp 48 (0x50) */ + .parent = 57, + .info = { SFF8436_INFO(&sff_8436_port[47]) }, + .client = NULL, + }, + { + /* qsfp 49 (0x50) */ + .parent = 58, + .info = { SFF8436_INFO(&sff_8436_port[48]) }, + .client = NULL, + }, + { + /* qsfp 50 (0x50) */ + .parent = 59, + .info = { SFF8436_INFO(&sff_8436_port[49]) }, + .client = NULL, + }, + { + /* qsfp 51 (0x50) */ + .parent = 60, + .info = { SFF8436_INFO(&sff_8436_port[50]) }, + .client = NULL, + }, + { + /* qsfp 52 (0x50) */ + .parent = 61, + .info = { SFF8436_INFO(&sff_8436_port[51]) }, + .client = NULL, + }, + { + /* qsfp 53 (0x50) */ + .parent = 62, + .info = { SFF8436_INFO(&sff_8436_port[52]) }, + .client = NULL, + }, + { + /* qsfp 54 (0x50) */ + .parent = 63, + .info = { SFF8436_INFO(&sff_8436_port[53]) }, + .client = NULL, + }, +}; + + +static struct platform_device ag5648_i2c_device[] = { + ag5648_i2c_device_num(0), + ag5648_i2c_device_num(1), + ag5648_i2c_device_num(2), + ag5648_i2c_device_num(3), + ag5648_i2c_device_num(4), + ag5648_i2c_device_num(5), + ag5648_i2c_device_num(6), + ag5648_i2c_device_num(7), + ag5648_i2c_device_num(8), + ag5648_i2c_device_num(9), + ag5648_i2c_device_num(10), + ag5648_i2c_device_num(11), + ag5648_i2c_device_num(12), + ag5648_i2c_device_num(13), + ag5648_i2c_device_num(14), + ag5648_i2c_device_num(15), + ag5648_i2c_device_num(16), + ag5648_i2c_device_num(17), + ag5648_i2c_device_num(18), + ag5648_i2c_device_num(19), + ag5648_i2c_device_num(20), + ag5648_i2c_device_num(21), + ag5648_i2c_device_num(22), + ag5648_i2c_device_num(23), + ag5648_i2c_device_num(24), + ag5648_i2c_device_num(25), + ag5648_i2c_device_num(26), + ag5648_i2c_device_num(27), + ag5648_i2c_device_num(28), + ag5648_i2c_device_num(29), + ag5648_i2c_device_num(30), + ag5648_i2c_device_num(31), + ag5648_i2c_device_num(32), + ag5648_i2c_device_num(33), + ag5648_i2c_device_num(34), + ag5648_i2c_device_num(35), + ag5648_i2c_device_num(36), + ag5648_i2c_device_num(37), + ag5648_i2c_device_num(38), + ag5648_i2c_device_num(39), + ag5648_i2c_device_num(40), + ag5648_i2c_device_num(41), + ag5648_i2c_device_num(42), + ag5648_i2c_device_num(43), + ag5648_i2c_device_num(44), + ag5648_i2c_device_num(45), + ag5648_i2c_device_num(46), + ag5648_i2c_device_num(47), + ag5648_i2c_device_num(48), + ag5648_i2c_device_num(49), + ag5648_i2c_device_num(50), + ag5648_i2c_device_num(51), + ag5648_i2c_device_num(52), + ag5648_i2c_device_num(53), + ag5648_i2c_device_num(54), + ag5648_i2c_device_num(55), + ag5648_i2c_device_num(56), + ag5648_i2c_device_num(57), + ag5648_i2c_device_num(58), + ag5648_i2c_device_num(59), + ag5648_i2c_device_num(60), + ag5648_i2c_device_num(61), + ag5648_i2c_device_num(62), + ag5648_i2c_device_num(63), + ag5648_i2c_device_num(64), + ag5648_i2c_device_num(65), + ag5648_i2c_device_num(66), +}; + +/*---------------- I2C device - end ------------- */ + +/*---------------- I2C driver - start ------------- */ +static int __init i2c_device_probe(struct platform_device *pdev) +{ + struct i2c_device_platform_data *pdata; + struct i2c_adapter *parent; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + return 0; +} + +static int __exit i2c_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + if (pdata->client) { + parent = (pdata->client)->adapter; + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + } + + return 0; +} +static struct platform_driver i2c_device_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag5648-i2c-device", + } +}; + +/*---------------- I2C driver - end ------------- */ + +/*---------------- CPLD - start ------------- */ + +/* CPLD -- device */ + +enum cpld_type { + system_cpld, + master_cpld, + slave_cpld, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +static struct cpld_platform_data ag5648_cpld_platform_data[] = { + [system_cpld] = { + .reg_addr = SYSTEM_CPLD_REG, + }, + [master_cpld] = { + .reg_addr = MASTER_CPLD_REG, + }, + [slave_cpld] = { + .reg_addr = SLAVE_CPLD_REG, + }, +}; + +static struct platform_device ag5648_cpld = { + .name = "delta-ag5648-cpld", + .id = 0, + .dev = { + .platform_data = ag5648_cpld_platform_data, + .release = device_release + }, +}; + +static ssize_t get_present(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u32 data = 0; + u32 data2 = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, SFP_PRESENCE_1); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = (u32)(ret & 0xff); + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, SFP_PRESENCE_2); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(ret & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, SFP_PRESENCE_3); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(ret & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, SFP_PRESENCE_4); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(ret & 0xff) << 24; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, SFP_PRESENCE_5); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data2 = ((u32)(ret & 0xf)) ; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, SFP_PRESENCE_6); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data2 |= (u32)(ret & 0xff) << 4; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, SFP_PRESENCE_7); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data2 |= (u32)((ret >> 4) & 0xf) << 12; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, QSFP_PRESENCE); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data2 |= (u32)(ret & 0x3f) << 16; + + return sprintf(buf, "0x%06x%x\n", data2, data); +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, QSFP_LP_MODE); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = ((u8)ret & 0x3f) ; + + return sprintf(buf, "0x%02x%012x\n", data, 0); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + data = data >> 48; + i2c_smbus_write_byte_data(pdata[master_cpld].client, QSFP_LP_MODE, (u8)(data & 0xff)); + + return count; +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, QSFP_RESET); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + + data = ((u8)ret & 0x3f); + + return sprintf(buf, "0x%02x%012x\n", data, 0); +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + data = data >> 48; + i2c_smbus_write_byte_data(pdata[master_cpld].client, QSFP_RESET, (u8)(data & 0xff)); + + return count; +} + +static ssize_t get_response(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, QSFP_RESPONSE); + + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = (u8)ret & 0x3f; + + return sprintf(buf, "0x%02x%012x\n", data, 0); +} + +static ssize_t set_response(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + data = data >> 48; + i2c_smbus_write_byte_data(pdata[master_cpld].client, QSFP_RESPONSE, (u8)(data & 0xff)); + + return count; +} + +struct platform_led_status{ + int reg_data; + char *led_status; + int led_id; +}; + +static struct platform_led_status led_info[] = { + { + .reg_data = 0x00,//0000 0000 + .led_status = "fan_off", + .led_id = 0, + }, + { + .reg_data = 1 << 6,//0100 0000 + .led_status = "fan_Amber", + .led_id = 0, + }, + { + .reg_data = 2 << 6,//1000 0000 + .led_status = "fan_green", + .led_id = 0, + }, + { + .reg_data = 3 << 6,//1100 0000 + .led_status = "fan_Blinking_yellow", + .led_id = 0, + }, + { + .reg_data = 0x00, + .led_status = "sys_Blinking_green", + .led_id = 1, + }, + { + .reg_data = 1 << 4, + .led_status = "sys_green", + .led_id = 1, + }, + { + .reg_data = 2 << 4, + .led_status = "sys_Amber", + .led_id = 1, + }, + { + .reg_data = 3 << 4 , + .led_status = "sys_Amber", + .led_id = 1, + }, + { + .reg_data = 0x00, + .led_status = "pwr_off", + .led_id = 2, + }, + { + .reg_data = 1 << 1, + .led_status = "pwr_Amber", + .led_id = 2, + }, + { + .reg_data = 2 << 1, + .led_status = "pwr_green", + .led_id = 2, + }, + { + .reg_data = 3 << 1, + .led_status = "pwr_Blinking_Amber", + .led_id = 2, + }, + { + .reg_data = 0x00, + .led_status = "fan4_off", + .led_id = 3, + }, + { + .reg_data = 1 << 6, + .led_status = "fan4_green", + .led_id = 3, + }, + { + .reg_data = 2 << 6, + .led_status = "fan4_Amber", + .led_id = 3, + }, + { + .reg_data = 0x00, + .led_status = "fan3_off", + .led_id = 4, + }, + { + .reg_data = 1 << 4, + .led_status = "fan3_green", + .led_id = 4, + }, + { + .reg_data = 2 << 4, + .led_status = "fan3_Amber", + .led_id = 4, + }, + { + .reg_data = 0x00, + .led_status = "fan2_off", + .led_id = 5, + }, + { + .reg_data = 1 << 2, + .led_status = "fan2_green", + .led_id = 5, + }, + { + .reg_data = 1 << 3, + .led_status = "fan2_Amber", + .led_id = 5, + }, + { + .reg_data = 0x00, + .led_status = "fan1_off", + .led_id = 6, + }, + { + .reg_data = 1, + .led_status = "fan1_green", + .led_id = 6, + }, + { + .reg_data = 2, + .led_status = "fan1_Amber", + .led_id = 6, + }, +}; + +struct platform_led_data{ + int reg_addr; + int mask; +}; + +static struct platform_led_data led_data[] = { + { + .reg_addr = LED_REG, //0x04 + .mask = 0xc0,//1100 0000 + }, + { + .reg_addr = LED_REG, + .mask = 0x30,//0011 0000 + }, + { + .reg_addr = LED_REG, + .mask = 0x06,//0000 0110 + }, + { + .reg_addr = FAN_LED_REG,//0x05 + .mask = 0xc0,//1100 0000 + }, + { + .reg_addr = FAN_LED_REG, + .mask = 0x30,//0011 0000 + }, + { + .reg_addr = FAN_LED_REG, + .mask = 0x0c,//0000 1100 + }, + { + .reg_addr = FAN_LED_REG, + .mask = 0x03,//0000 0011 + }, +}; + + +static ssize_t get_led_color(struct device *dev, struct device_attribute *devattr, char *buf) +{ + char str[9][20] = {0}; + int board_data; + int led_data_number; + int led_info_number; + struct cpld_platform_data *pdata = dev->platform_data; + + for(led_data_number = 0; led_data_number < ARRAY_SIZE(led_data); led_data_number++){ + board_data = i2c_smbus_read_byte_data(pdata[slave_cpld].client, led_data[led_data_number].reg_addr); + if(board_data >= 0){ + board_data &= led_data[led_data_number].mask; + for(led_info_number = 0; led_info_number < ARRAY_SIZE(led_info); led_info_number++){ + if (led_data_number == led_info[led_info_number].led_id \ + && board_data == led_info[led_info_number].reg_data){ + sprintf(str[led_data_number], "%s", led_info[led_info_number].led_status); + } + } + } + else + printk( KERN_ERR "Missing LED board data\n"); + } + return sprintf(buf,"%s\n%s\n%s\n%s\n%s\n%s\n%s\n",str[0],str[1],str[2],str[3],str[4],str[5],str[6]); +} + +static ssize_t set_led_color(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int led_info_number; + int led_data_number; + int str_compar; + int led_reg_value; + struct cpld_platform_data *pdata = dev->platform_data; + + for(led_info_number = 0; led_info_number < ARRAY_SIZE(led_info); led_info_number++){ + str_compar = strncmp(buf,led_info[led_info_number].led_status,strlen(led_info[led_info_number].led_status)); + if(str_compar == 0){ + for(led_data_number = 0; led_data_number < ARRAY_SIZE(led_data); led_data_number++){ + if(led_info[led_info_number].led_id == led_data_number){ + led_reg_value = i2c_smbus_read_byte_data(pdata[slave_cpld].client, led_data[led_data_number].reg_addr); + if(led_reg_value >= 0){ + led_reg_value &= (~led_data[led_data_number].mask); + led_reg_value |= led_info[led_info_number].reg_data; + i2c_smbus_write_byte_data(pdata[slave_cpld].client, (u8)(led_data[led_data_number].reg_addr & 0xff), (u8)(led_reg_value & 0xff)); + } + else + printk( KERN_ERR "Missing LED reg. data\n"); + } + } + } + } + return count; +} + +static DEVICE_ATTR(sfp_response, S_IWUSR | S_IRUGO, get_response, set_response ); +static DEVICE_ATTR(sfp_present, S_IRUGO, get_present, NULL ); +static DEVICE_ATTR(sfp_lpmode, S_IWUSR | S_IRUGO, get_lpmode, set_lpmode ); +static DEVICE_ATTR(sfp_reset, S_IWUSR | S_IRUGO, get_reset, set_reset ); + +static DEVICE_ATTR(led_control, S_IRUGO | S_IWUSR, get_led_color, set_led_color); + +static struct attribute *ag5648_cpld_attrs[] = { + &dev_attr_sfp_response.attr, + &dev_attr_sfp_present.attr, + &dev_attr_sfp_lpmode.attr, + &dev_attr_sfp_reset.attr, + &dev_attr_led_control.attr, + NULL, +}; + +static struct attribute_group ag5648_cpld_attr_grp = { + .attrs = ag5648_cpld_attrs, +}; + +/* CPLD -- driver */ +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret,i; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS2); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n",BUS2); + return -ENODEV; + } + + for (i = 0; i < ARRAY_SIZE(ag5648_cpld_platform_data); i++) { + pdata[i].client = i2c_new_dummy(parent, pdata[i].reg_addr); + if (!pdata[i].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[i].reg_addr); + goto error; + } + } + + ret = sysfs_create_group(&pdev->dev.kobj, &ag5648_cpld_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + return 0; + +error: + i--; + for (; i >= 0; i--) { + if (pdata[i].client) { + i2c_unregister_device(pdata[i].client); + } + } + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + int i; + sysfs_remove_group(&pdev->dev.kobj, &ag5648_cpld_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + for (i = 0; i < ARRAY_SIZE(ag5648_cpld_platform_data); i++) { + if (pdata[i].client) { + if (!parent) { + parent = (pdata[i].client)->adapter; + } + i2c_unregister_device(pdata[i].client); + } + } + } + + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag5648-cpld", + }, +}; + +/*---------------- CPLD - end ------------- */ + +/*---------------- MUX - start ------------- */ + +struct swpld_mux_platform_data { + int parent; + int base_nr; + int reg_addr; + struct i2c_client *cpld; +}; + +struct swpld_mux { + struct i2c_adapter *parent; + struct i2c_adapter **child; + struct swpld_mux_platform_data data; +}; + +static struct swpld_mux_platform_data ag5648_swpld_mux_platform_data[] = { + { + .parent = BUS4, + .base_nr = BUS4_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS4_MUX_REG , + }, +}; + + +static struct platform_device ag5648_swpld_mux[] = { + { + .name = "delta-ag5648-swpld-mux", + .id = 0, + .dev = { + .platform_data = &ag5648_swpld_mux_platform_data[0], + .release = device_release, + }, + }, +}; + + +static int cpld_reg_write_byte(struct i2c_client *client, u8 regaddr, u8 val) +{ + union i2c_smbus_data data; + + data.byte = val; + return client->adapter->algo->smbus_xfer(client->adapter, client->addr, + client->flags, + I2C_SMBUS_WRITE, + regaddr, I2C_SMBUS_BYTE_DATA, &data); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int swpld_mux_select(struct i2c_adapter *adap, void *data, u8 chan) +{ + struct swpld_mux *mux = data; + u8 swpld_mux_val=0; + if ( mux->data.base_nr == BUS4_BASE_NUM ) + { + swpld_mux_val = (chan + 0x01); + } + else + { + swpld_mux_val = 0x00; + } + swpld_mux_val=swpld_mux_val & (u8)0x3F; + + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld_mux_val & 0xff)); +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int swpld_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct swpld_mux *mux = i2c_mux_priv(muxc); + u8 swpld_mux_val=0; + if ( mux->data.base_nr == BUS4_BASE_NUM ) + { + swpld_mux_val = (chan + 0x01); + } + else + { + swpld_mux_val = 0x00; + } + swpld_mux_val=swpld_mux_val & (u8)0x3F; + + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld_mux_val & 0xff)); +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct swpld_mux *mux; + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + ret = -ENOMEM; + printk(KERN_ERR "Failed to allocate memory for mux\n"); + goto alloc_failed; + } + + mux->parent = parent; + mux->data = *pdata; + mux->child = kzalloc(sizeof(struct i2c_adapter *) * dev_num, GFP_KERNEL); + if (!mux->child) { + ret = -ENOMEM; + printk(KERN_ERR "Failed to allocate memory for device on mux\n"); + goto alloc_failed2; + } + + for (i = 0; i < dev_num; i++) { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + mux->child[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, + nr, i, class, + swpld_mux_select, NULL); + if (!mux->child[i]) { + ret = -ENODEV; + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + platform_set_drvdata(pdev, mux); + return 0; + +add_adapter_failed: + for (; i > 0; i--) + i2c_del_mux_adapter(mux->child[i - 1]); + kfree(mux->child); +alloc_failed2: + kfree(mux); +alloc_failed: + i2c_put_adapter(parent); + + return ret; +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct swpld_mux *mux; + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + printk(KERN_ERR "Failed to allocate memory for mux\n"); + return -ENOMEM; + } + mux->data = *pdata; + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + kfree(mux); + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0, + swpld_mux_select, NULL); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = mux; + platform_set_drvdata(pdev, muxc); + + + for (i = 0; i < dev_num; i++) { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + dev_info(&pdev->dev, "%d port mux on %s adapter\n", dev_num, parent->name); + + return 0; + +add_adapter_failed: + i2c_mux_del_adapters(muxc); +alloc_failed: + kfree(mux); + i2c_put_adapter(parent); + + return ret; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + int i; + struct swpld_mux *mux = platform_get_drvdata(pdev); + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + switch (pdata->parent) { + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + for (i = 0; i < dev_num; i++) + i2c_del_mux_adapter(mux->child[i]); + + platform_set_drvdata(pdev, NULL); + i2c_put_adapter(mux->parent); + kfree(mux->child); + kfree(mux); + + return 0; +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + + i2c_mux_del_adapters(muxc); + i2c_put_adapter(muxc->parent); + + return 0; +} +#endif + +static struct platform_driver swpld_mux_driver = { + .probe = swpld_mux_probe, + .remove = __exit_p(swpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag5648-swpld-mux", + }, +}; +/*---------------- MUX - end ------------- */ + + +/*---------------- module initialization ------------- */ +static int __init delta_ag5648_platform_init(void) +{ + //struct i2c_client *client; + struct i2c_adapter *adapter; + struct cpld_platform_data *cpld_pdata; + struct swpld_mux_platform_data *swpld_pdata; + int ret,i = 0; + + //Use pca9548 in i2c_mux_pca954x.c + adapter = i2c_get_adapter(BUS1); + + i2c_client_9548 = i2c_new_device(adapter, &i2c_info_pca9548[0]); + i2c_put_adapter(adapter); + + // set the CPLD prob and remove + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpld driver\n"); + goto error_cpld_driver; + } + + // register the mux prob which call the CPLD + ret = platform_driver_register(&swpld_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld mux driver\n"); + goto error_swpld_mux_driver; + } + + // register the i2c devices + ret = platform_driver_register(&i2c_device_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_driver; + } + + // register the CPLD + ret = platform_device_register(&ag5648_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpld device\n"); + goto error_ag5648_cpld; + } + // link the CPLD and the Mux + cpld_pdata = ag5648_cpld.dev.platform_data; + + + swpld_pdata = ag5648_swpld_mux[0].dev.platform_data; + swpld_pdata->cpld = cpld_pdata[master_cpld].client; + ret = platform_device_register(&ag5648_swpld_mux[0]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld mux %d\n", i); + goto error_ag5648_swpld_mux; + } + + for (i = 0; i < ARRAY_SIZE(ag5648_i2c_device); i++) + { + ret = platform_device_register(&ag5648_i2c_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_ag5648_i2c_device; + } + } + + if (ret) + goto error_ag5648_swpld_mux; + return 0; + +error_ag5648_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag5648_i2c_device[i]); + } + i = ARRAY_SIZE(ag5648_swpld_mux); +error_ag5648_swpld_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag5648_swpld_mux[0]); + } + platform_device_unregister(&ag5648_cpld); +error_ag5648_cpld: + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + platform_driver_unregister(&swpld_mux_driver); +error_swpld_mux_driver: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +} + +static void __exit delta_ag5648_platform_exit(void) +{ + int i = 0; + + for ( i = 0; i < ARRAY_SIZE(ag5648_i2c_device); i++ ) { + platform_device_unregister(&ag5648_i2c_device[i]); + } + + for (i = 0; i < ARRAY_SIZE(ag5648_swpld_mux); i++) { + platform_device_unregister(&ag5648_swpld_mux[i]); + } + + platform_device_unregister(&ag5648_cpld); + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&cpld_driver); + platform_driver_unregister(&swpld_mux_driver); + i2c_unregister_device(i2c_client_9548); +} + +module_init(delta_ag5648_platform_init); +module_exit(delta_ag5648_platform_exit); + +MODULE_DESCRIPTION("DNI ag5648 Platform Support"); +MODULE_AUTHOR("Neal Tai "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/dni_ag5648_psu.c b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/dni_ag5648_psu.c new file mode 100644 index 000000000000..d7e8a3bf8e7c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/dni_ag5648_psu.c @@ -0,0 +1,552 @@ +/* + * An hwmon driver for delta AG5648 PSU + * dps_800ab_16_d.c - Support for DPS-800AB-16 D Power Supply Module + * + * Copyright (C) 2016 Delta Network Technology Corporation + * + * DNI + * + * Based on ym2651y.c + * Based on ad7414.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 +#define SWPLD_REG 0x31 +#define SWPLD_PSU_MUX_REG 0x21 +#define SELECT_PSU1_EEPROM 0x00 +#define SELECT_PSU2_EEPROM 0x20 + +u8 psu_member_data = 0x00; + +/* Address scanned */ +static const unsigned short normal_i2c[] = { 0x59, 0x58, I2C_CLIENT_END }; + +/* This is additional data */ +struct dps_800ab_16_d_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; + unsigned long last_updated; /* In jiffies */ + + /* Registers value */ + u8 vout_mode; + u16 in1_input; + u16 in2_input; + u16 curr1_input; + u16 curr2_input; + u16 power1_input; + u16 power2_input; + u16 temp_input[2]; + u8 fan_target; + u16 fan_duty_cycle_input[2]; + u16 fan_speed_input[2]; + u8 mfr_model[14]; + u8 mfr_serial[16]; +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask); +static ssize_t set_fan_duty_cycle_input(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count); +static ssize_t for_linear_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t for_fan_target(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static int dps_800ab_16_d_read_byte(struct i2c_client *client, u8 reg); +static int dps_800ab_16_d_read_word(struct i2c_client *client, u8 reg); +static int dps_800ab_16_d_write_word(struct i2c_client *client, u8 reg, \ + u16 value); +static int dps_800ab_16_d_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len); +static struct dps_800ab_16_d_data *dps_800ab_16_d_update_device( \ + struct device *dev); +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +/* +static ssize_t set_w_member_data(struct device *dev, struct device_attribute \ + *dev_att, const char *buf, size_t count); +static ssize_t for_r_member_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +*/ +enum dps_800ab_16_d_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_MFR_MODEL, + PSU_MFR_SERIAL, + PSU_SELECT_MEMBER, +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle_input(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct i2c_client *client = to_i2c_client(dev); + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + /* Select SWPLD PSU offset */ + + mutex_lock(&data->update_lock); + data->fan_duty_cycle_input[nr] = speed; + dps_800ab_16_d_write_word(client, 0x3B + nr, data->fan_duty_cycle_input[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t for_linear_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->in1_input; + break; + case PSU_I_IN: + value = data->curr1_input; + break; + case PSU_I_OUT: + value = data->curr2_input; + break; + case PSU_P_IN: + value = data->power1_input; + multiplier = 1000*1000; + break; + case PSU_P_OUT: + value = data->power2_input; + multiplier = 1000*1000; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle_input[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed_input[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", \ + (mantissa << exponent) * multiplier) : \ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t for_fan_target(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_target >> shift); +} + +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->in2_input; + + return (exponent > 0) ? sprintf(buf, "%d\n", \ + (mantissa * multiplier) / (1 << exponent)): \ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + +} + +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) + return 0; + + switch (attr->index) { + case PSU_MFR_MODEL: + ptr = data->mfr_model + 1; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial + 1; + break; + default: + return 0; + } + return sprintf(buf, "%s\n", ptr); +} +static int dps_800ab_16_d_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int dps_800ab_16_d_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int dps_800ab_16_d_write_word(struct i2c_client *client, u8 reg, \ + u16 value) +{ + union i2c_smbus_data data; + data.word = value; + return i2c_smbus_xfer(client->adapter, client->addr, + client->flags |= I2C_CLIENT_PEC, + I2C_SMBUS_WRITE, reg, + I2C_SMBUS_WORD_DATA, &data); + +} + +static int dps_800ab_16_d_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, + data); + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; +abort: + return result; + +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct dps_800ab_16_d_data *dps_800ab_16_d_update_device( \ + struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + /* Select SWPLD PSU offset */ + + if (time_after(jiffies, data->last_updated)) { + int i, status; + u8 command; + struct reg_data_byte regs_byte[] = { + {0x20, &data->vout_mode}, + {0x81, &data->fan_target} + }; + struct reg_data_word regs_word[] = { + {0x88, &data->in1_input}, + {0x8b, &data->in2_input}, + {0x89, &data->curr1_input}, + {0x8c, &data->curr2_input}, + {0x97, &data->power1_input}, + {0x96, &data->power2_input}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle_input[0])}, + {0x90, &(data->fan_speed_input[0])}, + }; + + dev_dbg(&client->dev, "start data update\n"); + /* one milliseconds from now */ + data->last_updated = jiffies + HZ / 1000; + + data->in1_input = 0; + data->in2_input = 0; + data->curr1_input = 0; + data->curr2_input = 0; + data->power1_input = 0; + data->power2_input = 0; + data->temp_input[0] = 0; + data->temp_input[1] = 0; + data->fan_duty_cycle_input[0] = 0; + data->fan_speed_input[0] = 0; + + data->mfr_model[0] = '\0'; + data->mfr_serial[0] = '\0'; + + command = 0x9a; /* PSU mfr_model */ + status = dps_800ab_16_d_read_block(client, command, + data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1); + data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, + status); + } + + command = 0x9e; /* PSU mfr_serial */ + status = dps_800ab_16_d_read_block(client, command, + data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1); + data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, + status); + } + + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = dps_800ab_16_d_read_byte(client, + regs_byte[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } else { + *(regs_byte[i].value) = status; + } + } + + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = dps_800ab_16_d_read_word(client, + regs_word[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } else { + *(regs_word[i].value) = status; + } + } +/* + command = 0x9a; / PSU mfr_model / + status = dps_800ab_16_d_read_block(client, command, + data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1); + data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, + status); + } + + command = 0x9e; / PSU mfr_serial / + status = dps_800ab_16_d_read_block(client, command, + data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1); + data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, + status); + } + */ + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; + +} + +/* sysfs attributes for hwmon */ +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, for_linear_data, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, for_vout_data, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, for_linear_data, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, for_linear_data, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, for_linear_data, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, for_linear_data, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(temp1_input, \ + S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_target, \ + S_IRUGO, for_fan_target, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(fan1_set_percentage, S_IWUSR | S_IRUGO, \ + for_linear_data, set_fan_duty_cycle_input, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(fan1_input, \ + S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_mfr_model, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL); +/* +static SENSOR_DEVICE_ATTR(psu_select_member, S_IWUGO | S_IRUGO, \ + for_r_member_data, set_w_member_data, PSU_SELECT_MEMBER); +*/ +static struct attribute *dps_800ab_16_d_attributes[] = { + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_target.dev_attr.attr, + &sensor_dev_attr_fan1_set_percentage.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + //&sensor_dev_attr_psu_select_member.dev_attr.attr, + NULL +}; + +static const struct attribute_group dps_800ab_16_d_group = { + .attrs = dps_800ab_16_d_attributes, +}; + +static int dps_800ab_16_d_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct dps_800ab_16_d_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "new chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &dps_800ab_16_d_group); + if (status) + goto exit_sysfs_create_group; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_hwmon_device_register; + } + + return 0; + +exit_hwmon_device_register: + sysfs_remove_group(&client->dev.kobj, &dps_800ab_16_d_group); +exit_sysfs_create_group: + kfree(data); +exit: + return status; +} + +static int dps_800ab_16_d_remove(struct i2c_client *client) +{ + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &dps_800ab_16_d_group); + kfree(data); + + return 0; +} + +enum id_name { + dni_ag5648_psu, + dps_800ab_16_d +}; + +static const struct i2c_device_id dps_800ab_16_d_id[] = { + { "dni_ag5648_psu", dni_ag5648_psu }, + { "dps_800ab_16_d", dps_800ab_16_d }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dps_800ab_16_d_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver dps_800ab_16_d_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "dps_800ab_16_d", + }, + .probe = dps_800ab_16_d_probe, + .remove = dps_800ab_16_d_remove, + .id_table = dps_800ab_16_d_id, + .address_list = normal_i2c, +}; + +static int __init dps_800ab_16_d_init(void) +{ + return i2c_add_driver(&dps_800ab_16_d_driver); +} + +static void __exit dps_800ab_16_d_exit(void) +{ + i2c_del_driver(&dps_800ab_16_d_driver); +} + + +MODULE_AUTHOR("Aries Lin "); +MODULE_DESCRIPTION("DPS_800AB_16_D Driver"); +MODULE_LICENSE("GPL"); + +module_init(dps_800ab_16_d_init); +module_exit(dps_800ab_16_d_exit); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/dni_emc2305.c b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/dni_emc2305.c new file mode 120000 index 000000000000..e8f7ae6b3f4d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/dni_emc2305.c @@ -0,0 +1 @@ +../../common/modules/dni_emc2305.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/scripts/ag5648_platform_init.sh b/platform/broadcom/sonic-platform-modules-delta/ag5648/scripts/ag5648_platform_init.sh new file mode 100755 index 000000000000..753649f01abe --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/scripts/ag5648_platform_init.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +#platform init script for Delta ag5648 + +#fan speed monitor start +/usr/share/sonic/device/x86_64-delta_ag5648-r0/fancontrol.service /usr/share/sonic/device/x86_64-delta_ag5648-r0/fancontrol & + +#led control +/usr/local/bin/led_control & + + +exit 0 + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/scripts/led_control b/platform/broadcom/sonic-platform-modules-delta/ag5648/scripts/led_control new file mode 100755 index 000000000000..bc1417f9ba5e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/scripts/led_control @@ -0,0 +1,221 @@ +#!/bin/bash + +FAN1_EEPROM="-y 3 0x51 0x0a" +FAN2_EEPROM="-y 3 0x52 0x0a" +FAN3_EEPROM="-y 3 0x53 0x0a" +FAN4_EEPROM="-y 3 0x54 0x0a" +LED_CONTROL="/sys/devices/platform/delta-ag5648-cpld.0/led_control" + +FAN1_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/3-004d/fan1_input" +FAN2_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/3-004d/fan2_input" +FAN3_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/3-004d/fan3_input" +FAN4_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/3-004d/fan4_input" + +FAN1_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-004d/fan1_input" +FAN2_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-004d/fan2_input" +FAN3_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-004d/fan3_input" +FAN4_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-004d/fan4_input" + +PSU1_EEPROM="-y 6 0x51 0x00" +PSU2_EEPROM="-y 6 0x50 0x00" +PSU1_FAN_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-6/6-0059/fan1_input" +PSU2_FAN_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-6/6-0058/fan1_input" + +catfaneeprom(){ + fan_eeprom_num=0 + fan1_eeprom_num=0 + i2cget $FAN1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan1_eeprom_num=$((fan1_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan1_eeprom_num=$((fan1_eeprom_num)) + fi + + fan2_eeprom_num=0 + i2cget $FAN2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan2_eeprom_num=$((fan2_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan2_eeprom_num=$((fan2_eeprom_num)) + fi + + fan3_eeprom_num=0 + i2cget $FAN3_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan3_eeprom_num=$((fan3_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan3_eeprom_num=$((fan3_eeprom_num)) + fi + + fan4_eeprom_num=0 + i2cget $FAN4_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan4_eeprom_num=$((fan4_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan4_eeprom_num=$((fan4_eeprom_num)) + fi + + fan_eeprom_num=$((fan1_eeprom_num+fan2_eeprom_num+fan3_eeprom_num+fan4_eeprom_num)) +} + +catfanspeed(){ + fan_rpm_normal_num=0 + fan1_rpm_normal_num=0 + fan1_front_rpm=`cat $FAN1_FRONT_RPM` + fan1_rear_rpm=`cat $FAN1_REAR_RPM` + if [ "${fan1_front_rpm}" -ne "960" ] && [ "${fan1_rear_rpm}" -ne "960" ] && [ "${fan1_front_rpm}" -ne "0" ] && [ "${fan1_rear_rpm}" -ne "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num+1)) + elif [ "${fan1_front_rpm}" -eq "960" ] || [ "${fan1_rear_rpm}" -eq "960" ] || [ "${fan1_front_rpm}" -eq "0" ] || [ "${fan1_rear_rpm}" -eq "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num)) + fi + + fan2_rpm_normal_num=0 + fan2_front_rpm=`cat $FAN2_FRONT_RPM` + fan2_rear_rpm=`cat $FAN2_REAR_RPM` + if [ "${fan2_front_rpm}" -ne "960" ] && [ "${fan2_rear_rpm}" -ne "960" ] && [ "${fan2_front_rpm}" -ne "0" ] && [ "${fan2_rear_rpm}" -ne "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num+1)) + elif [ "${fan2_front_rpm}" -eq "960" ] || [ "${fan2_rear_rpm}" -eq "960" ] || [ "${fan2_front_rpm}" -eq "0" ] || [ "${fan2_rear_rpm}" -eq "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num)) + fi + + fan3_rpm_normal_num=0 + fan3_front_rpm=`cat $FAN3_FRONT_RPM` + fan3_rear_rpm=`cat $FAN3_REAR_RPM` + if [ "${fan3_front_rpm}" -ne "960" ] && [ "${fan3_rear_rpm}" -ne "960" ] && [ "${fan3_front_rpm}" -ne "0" ] && [ "${fan3_rear_rpm}" -ne "0" ]; then + fan3_rpm_normal_num=$((fan3_rpm_normal_num+1)) + elif [ "${fan3_front_rpm}" -eq "960" ] || [ "${fan3_rear_rpm}" -eq "960" ] || [ "${fan3_front_rpm}" -eq "0" ] || [ "${fan3_rear_rpm}" -eq "0" ]; then + fan3_rpm_normal_num=$((fan3_rpm_normal_num)) + fi + + fan4_rpm_normal_num=0 + fan4_front_rpm=`cat $FAN4_FRONT_RPM` + fan4_rear_rpm=`cat $FAN4_REAR_RPM` + if [ "${fan4_front_rpm}" -ne "960" ] && [ "${fan4_rear_rpm}" -ne "960" ] && [ "${fan4_front_rpm}" -ne "0" ] && [ "${fan4_rear_rpm}" -ne "0" ]; then + fan4_rpm_normal_num=$((fan4_rpm_normal_num+1)) + elif [ "${fan4_front_rpm}" -eq "960" ] || [ "${fan4_rear_rpm}" -eq "960" ] || [ "${fan4_front_rpm}" -eq "0" ] || [ "${fan4_rear_rpm}" -eq "0" ]; then + fan4_rpm_normal_num=$((fan4_rpm_normal_num)) + fi + + fan_rpm_normal_num=$((fan1_rpm_normal_num+fan2_rpm_normal_num+fan3_rpm_normal_num+fan4_rpm_normal_num)) + +} + +catpsueeprom(){ + psu1_eeprom_num=0 + i2cget $PSU1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu1_eeprom_num=$((psu1_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + psu1_eeprom_num=$((psu1_eeprom_num)) + fi + + psu2_eeprom_num=0 + i2cget $PSU2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu2_eeprom_num=$((psu2_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + psu2_eeprom_num=$((psu2_eeprom_num)) + fi +} + +catpsufanspeed(){ + + psu1_rpm_normal_num=0 + psu1_rpm=`cat $PSU1_FAN_RPM` + + if [ "${psu1_rpm}" -ne "960" ] && [ "${psu1_rpm}" -ne "0" ]; then + psu1_rpm_normal_num=$((psu1_rpm_normal_num+1)) + elif [ "${psu1_rpm}" -eq "960" ] || [ "${psu1_rpm}" -eq "0" ]; then + psu1_rpm_normal_num=$((psu1_rpm_normal_num)) + fi + + psu2_rpm_normal_num=0 + psu2_rpm=`cat $PSU2_FAN_RPM` + + if [ "${psu2_rpm}" -ne "960" ] && [ "${psu2_rpm}" -ne "0" ]; then + psu2_rpm_normal_num=$((psu2_rpm_normal_num+1)) + elif [ "${psu2_rpm}" -eq "960" ] || [ "${psu2_rpm}" -eq "0" ]; then + psu2_rpm_normal_num=$((psu2_rpm_normal_num)) + fi + +} + +setfanled(){ + if [ "${fan_eeprom_num}" -eq "4" ] && [ "${fan_rpm_normal_num}" -eq "4" ]; then + echo "fan_green" > $LED_CONTROL + elif [ "${fan_eeprom_num}" -lt "4" ] && [ "${fan_rpm_normal_num}" -eq "4" ]; then + echo "fan_Amber" > $LED_CONTROL + elif [ "${psu1_eeprom_num}" -eq "0" ] && [ "${psu2_eeprom_num}" -eq "0" ]; then + echo "fan_off" > $LED_CONTROL + else + echo "fan_Blinking_yellow" > $LED_CONTROL + fi +} + +setpsuled(){ + if [ "${psu1_rpm_normal_num}" -eq "1" ] && [ "${psu2_rpm_normal_num}" -eq "1" ]; then + echo "pwr_green" > $LED_CONTROL + elif [ "${psu1_eeprom_num}" -eq "1" ] && [ "${psu2_eeprom_num}" -eq "1" ]; then + echo "pwr_Blinking_Amber" > $LED_CONTROL + elif [ "${psu1_eeprom_num}" -eq "0" ] || [ "${psu2_eeprom_num}" -eq "0" ]; then + echo "pwr_Amber" > $LED_CONTROL + else + echo "pwr_off" > $LED_CONTROL + fi + +} + +setfantrayled(){ + if [ "${fan1_rpm_normal_num}" -eq "1" ]; then + echo "fan1_green" > $LED_CONTROL + elif [ "${fan1_eeprom_num}" -eq "1" ]; then + echo "fan1_Amber" > $LED_CONTROL + else + echo "fan1_off" > $LED_CONTROL + fi + + if [ "${fan2_rpm_normal_num}" -eq "1" ]; then + echo "fan2_green" > $LED_CONTROL + elif [ "${fan2_eeprom_num}" -eq "1" ]; then + echo "fan2_Amber" > $LED_CONTROL + else + echo "fan2_off" > $LED_CONTROL + fi + + if [ "${fan3_rpm_normal_num}" -eq "1" ]; then + echo "fan3_green" > $LED_CONTROL + elif [ "${fan3_eeprom_num}" -eq "1" ]; then + echo "fan3_Amber" > $LED_CONTROL + else + echo "fan3_off" > $LED_CONTROL + fi + + if [ "${fan4_rpm_normal_num}" -eq "1" ]; then + echo "fan4_green" > $LED_CONTROL + elif [ "${fan4_eeprom_num}" -eq "1" ]; then + echo "fan4_Amber" > $LED_CONTROL + else + echo "fan4_off" > $LED_CONTROL + fi + +} + +platformstatus(){ + + echo "sys_green" > $LED_CONTROL + catfaneeprom + catfanspeed + setfanled + setfantrayled + + catpsueeprom + catpsufanspeed + setpsuled +} + +while true +do + platformstatus + sleep 5 +done + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/sensors.conf b/platform/broadcom/sonic-platform-modules-delta/ag5648/sensors.conf new file mode 100644 index 000000000000..c69567997a27 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/sensors.conf @@ -0,0 +1,94 @@ +# libsensors configuration file for AG5648 +# ------------------------------------------------ +# + +bus "i2c-2" "i2c-1-mux (chan_id 0)" +bus "i2c-3" "i2c-1-mux (chan_id 1)" +bus "i2c-4" "i2c-1-mux (chan_id 2)" +bus "i2c-5" "i2c-1-mux (chan_id 3)" +bus "i2c-6" "i2c-1-mux (chan_id 4)" +bus "i2c-7" "i2c-1-mux (chan_id 5)" + +# tmp75-i2c-2-4d board sensor near Left of front vents. +# tmp75-i2c-3-49 board sensor near MAC. +# tmp75-i2c-3-4b board sensor near Middle of front vents. +# tmp75-i2c-3-4c board sensor near Right of front vents. +# tmp75-i2c-3-4e board sensor near DC fan. +# tmp75-i2c-3-4f board sensor near CPU. + +chip "tmp75-i2c-*-4d" + label temp1 "board sensor near Left of front vents" + set temp1_max 60 + set temp1_max_hyst 55 + +chip "tmp75-i2c-*-49" + label temp1 "board sensor near MAC" + set temp1_max 85 + set temp1_max_hyst 80 + +chip "tmp75-i2c-*-4b" + label temp1 "board sensor near Middle of front vents" + set temp1_max 70 + set temp1_max_hyst 65 + +chip "tmp75-i2c-*-4c" + label temp1 "board sensor near Right of front vents" + set temp1_max 65 + set temp1_max_hyst 60 + +chip "tmp75-i2c-*-4e" + label temp1 "board sensor near DC fan" + set temp1_max 60 + set temp1_max_hyst 55 + +chip "tmp75-i2c-*-4f" + label temp1 "board sensor near CPU" + set temp1_max 80 + set temp1_max_hyst 75 + +chip "emc2305-i2c-3-4d" + label fan1 "FANTRAY 1 REAR" + label fan2 "FANTRAY 2 REAR" + label fan3 "FANTRAY 3 REAR" + label fan4 "FANTRAY 4 REAR" + label fan5 "FANTRAY 5 REAR" + +chip "emc2305-i2c-5-4d" + label fan1 "FANTRAY 1 FRONT" + label fan2 "FANTRAY 2 FRONT" + label fan3 "FANTRAY 3 FRONT" + label fan4 "FANTRAY 4 FRONT" + label fan5 "FANTRAY 5 FRONT" + +chip "ltc4215-i2c-*-40" + label in1 "PSU Hot-Swap voltage 1" + label in2 "PSU Hot-Swap voltage 2" + label power1 "PSU Hot-Swap power" + label curr1 "PSU Hot-Swap current" + +chip "ltc4215-i2c-*-42" + label in1 "PSU Hot-Swap voltage 1" + label in2 "PSU Hot-Swap voltage 2" + label power1 "PSU Hot-Swap power" + label curr1 "PSU Hot-Swap current" + +chip "dni_ag5648_psu-i2c-*-59" + label in1 "PSU voltage 1" + label in2 "PSU voltage 2" + label fan1 "PSU fan" + label temp1 "PSU temperature" + label power1 "PSU power1" + label power2 "PSU power2" + label curr1 "PSU current1" + label curr2 "PSU current2" + +chip "dni_ag5648_psu-i2c-*-58" + label in1 "PSU voltage 1" + label in2 "PSU voltage 2" + label fan1 "PSU fan" + label temp1 "PSU temperature" + label power1 "PSU power1" + label power2 "PSU power2" + label curr1 "PSU current1" + label curr2 "PSU current2" + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/cfg/ag9032v1-modules.conf b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/cfg/ag9032v1-modules.conf new file mode 100644 index 000000000000..552b4103ed02 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/cfg/ag9032v1-modules.conf @@ -0,0 +1,13 @@ +# /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. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus +i2c-mux-gpio +i2c-mux-pca954x diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/Makefile b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/Makefile new file mode 100644 index 000000000000..d77d3b78408f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/Makefile @@ -0,0 +1 @@ +obj-m := dni_ag9032v1_psu.o dni_emc2305.o delta_ag9032v1_platform.o delta_ag9032v1_cpupld.o diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_cpupld.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_cpupld.c new file mode 100644 index 000000000000..22f997e71fab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_cpupld.c @@ -0,0 +1,387 @@ +#include +#include +#include +#include +#include +#include + +#define CPUPLD_REG 0x31 + +enum cpld_type { + cpld, +}; + +struct platform_data { + int reg_addr; + struct i2c_client *client; +}; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, +}; + +enum cpld_attributes { + CPLD_VER, + CPU_BOARD_VER, + CPU_ID, + CPLD_RST, + MB_RST, + I2C_SW_RST, + MB_PWR, + PSU_FAN_INT, + SPI_WP_GBE, + EEPROM_WP, +}; + +static void device_release(struct device *dev) +{ + return; +} + +/*---------------- CPUPLD - start ------------- */ +static struct platform_data ag9032v1_cpld_platform_data[] = { + [cpld] = { + .reg_addr = CPUPLD_REG, + }, +}; + +static struct platform_device ag9032v1_cpld = { + .name = "delta-ag9032v1-cpupld", + .id = 0, + .dev = { + .platform_data = ag9032v1_cpld_platform_data, + .release = device_release + }, +}; +static unsigned char cpld_reg_addr; +static ssize_t get_cpld_reg_value(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + struct platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[cpld].client, cpld_reg_addr); + + return sprintf(buf, "0x%02x\n", ret); +} + +static ssize_t set_cpld_reg_value(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long data; + int err; + struct platform_data *pdata = dev->platform_data; + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + i2c_smbus_write_byte_data(pdata[cpld].client, cpld_reg_addr, data); + + return count; +} + +static ssize_t get_cpld_reg_addr(struct device *dev, struct device_attribute *devattr, char *buf) +{ + + return sprintf(buf, "0x%02x\n", cpld_reg_addr); +} + +static ssize_t set_cpld_reg_addr(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long data; + int err; + + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + cpld_reg_addr = data; + + return count; +} + +static ssize_t get_cpld_data(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + int ret; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct platform_data *pdata = dev->platform_data; + unsigned char reg; + int mask; + int value; + char note[180]; + switch (attr->index) { + case CPLD_VER: + reg = 0x01; + value = i2c_smbus_read_byte_data(pdata[cpld].client, reg); + sprintf(note, "\nCPLD Version, controlled by CPLD editor.\n"); + return sprintf(buf, "0x%02x%s", value, note); + break; + case CPU_BOARD_VER: + reg = 0x02; + ret = i2c_smbus_read_byte_data(pdata[cpld].client, reg); + value = ret >> 4; + sprintf(note, "\n“0x00”: proto A1\n“0x01”: proto A2\n“0x02”: proto B\n"); + return sprintf(buf, "0x%02x%s", value, note); + break; + case CPU_ID: + reg = 0x02; + ret = i2c_smbus_read_byte_data(pdata[cpld].client, reg); + value = ret & 0x0F; + sprintf(note, "\n“0x00”: P2041 ECC\n“0x01”: Rangeley ECC\n“0x02”: T2080 ECC\n"); + return sprintf(buf, "0x%02x%s", value, note); + break; + case CPLD_RST: + reg = 0x05; + mask = 7; + sprintf(note, "\n“1” = Normal operation\n“0” = Reset\n"); + break; + case MB_RST: + reg = 0x05; + mask = 1; + sprintf(note, "\n“1” = Normal operation\n“0” = Reset\n"); + break; + case I2C_SW_RST: + reg = 0x05; + mask = 0; + sprintf(note, "\n“1” = Normal operation\n“0” = Reset\n"); + break; + case MB_PWR: + reg = 0x08; + mask = 4; + sprintf(note, "\n“1” = Power rail is good\n“0” = Power rail is failed\n"); + break; + case PSU_FAN_INT: + reg = 0x0A; + mask = 0; + sprintf(note, "\n“1” = Interrupt doesn’t occur\n“0” = Interrupt occurs\n"); + break; + case SPI_WP_GBE: + reg = 0x10; + mask = 3; + sprintf(note, "\n“1” = overrides the lock-down function enabling blocks to be erased or programmed using software commands.\n“0” = enables the lock-down mechanism.\n"); + break; + case EEPROM_WP: + reg = 0x10; + mask = 2; + sprintf(note, "\n“1” = overrides the lock-down function enabling blocks to be erased or programmed using software commands.\n“0” = enables the lock-down mechanism.\n"); + break; + default: + return sprintf(buf, "%d not found", attr->index); + } + ret = i2c_smbus_read_byte_data(pdata[cpld].client, reg); + value = (ret & (1 << mask)) >> mask; + return sprintf(buf, "%d%s", value, note); +} + +static ssize_t set_cpld_data(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + int mask; + int err; + int ret; + unsigned long data; + unsigned char reg; + unsigned char mask_shift; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct platform_data *pdata = dev->platform_data; + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + switch (attr->index) { + case CPLD_RST: + reg = 0x05; + mask = 7; + break; + case MB_RST: + reg = 0x05; + mask = 1; + break; + case I2C_SW_RST: + reg = 0x05; + mask = 0; + break; + case SPI_WP_GBE: + reg = 0x10; + mask = 3; + break; + case EEPROM_WP: + reg = 0x10; + mask = 2; + break; + default: + return count; + } + + ret = i2c_smbus_read_byte_data(pdata[cpld].client, reg); + mask_shift = 1 << mask; + data = (ret & ~mask_shift) | (data << mask); + i2c_smbus_write_byte_data(pdata[cpld].client, cpld_reg_addr, data); + + return count; +} + +static DEVICE_ATTR(cpld_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg_value, set_cpld_reg_value); +static DEVICE_ATTR(cpld_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg_addr, set_cpld_reg_addr); + +static SENSOR_DEVICE_ATTR(cpld_ver, S_IRUGO, get_cpld_data, NULL, CPLD_VER); +static SENSOR_DEVICE_ATTR(cpu_board_ver, S_IRUGO, get_cpld_data, NULL, CPU_BOARD_VER); +static SENSOR_DEVICE_ATTR(cpu_id, S_IRUGO, get_cpld_data, NULL, CPU_ID); +static SENSOR_DEVICE_ATTR(cpld_rst, S_IRUGO | S_IWUSR, get_cpld_data, set_cpld_data, CPLD_RST); +static SENSOR_DEVICE_ATTR(mb_rst, S_IRUGO | S_IWUSR, get_cpld_data, set_cpld_data, MB_RST); +static SENSOR_DEVICE_ATTR(i2c_sw_rst, S_IRUGO | S_IWUSR, get_cpld_data, set_cpld_data, I2C_SW_RST); +static SENSOR_DEVICE_ATTR(mb_pwr, S_IRUGO, get_cpld_data, NULL, MB_PWR); +static SENSOR_DEVICE_ATTR(psu_fan_int, S_IRUGO, get_cpld_data, NULL, PSU_FAN_INT); +static SENSOR_DEVICE_ATTR(spi_wp_gbe, S_IRUGO | S_IWUSR, get_cpld_data, set_cpld_data, SPI_WP_GBE); +static SENSOR_DEVICE_ATTR(eeprom_wp, S_IRUGO | S_IWUSR, get_cpld_data, set_cpld_data, EEPROM_WP); + +static struct attribute *ag9032v1_cpld_attrs[] = { + &dev_attr_cpld_reg_value.attr, + &dev_attr_cpld_reg_addr.attr, + &sensor_dev_attr_cpld_ver.dev_attr.attr, + &sensor_dev_attr_cpu_board_ver.dev_attr.attr, + &sensor_dev_attr_cpu_id.dev_attr.attr, + &sensor_dev_attr_cpld_rst.dev_attr.attr, + &sensor_dev_attr_mb_rst.dev_attr.attr, + &sensor_dev_attr_i2c_sw_rst.dev_attr.attr, + &sensor_dev_attr_mb_pwr.dev_attr.attr, + &sensor_dev_attr_psu_fan_int.dev_attr.attr, + &sensor_dev_attr_spi_wp_gbe.dev_attr.attr, + &sensor_dev_attr_eeprom_wp.dev_attr.attr, + NULL, +}; + +static struct attribute_group ag9032v1_cpld_attr_group = { + .attrs = ag9032v1_cpld_attrs, +}; + +static int __init cpld_probe(struct platform_device *pdev) +{ + struct platform_data *pdata; + struct i2c_adapter *parent; + int ret; + int retval; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPUPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS2); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n",BUS2); + return -ENODEV; + } + + pdata[cpld].client = i2c_new_dummy(parent, pdata[cpld].reg_addr); + if (!pdata[cpld].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[cpld].reg_addr); + goto error; + } + + retval = sysfs_create_group(&pdev->dev.kobj, &ag9032v1_cpld_attr_group); + if (retval){ + printk(KERN_WARNING "Fail to create cpupld attribute group"); + goto error; + } + return 0; + +error: + i2c_unregister_device(pdata[cpld].client); + i2c_put_adapter(parent); + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &ag9032v1_cpld_attr_group); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[cpld].client) { + if (!parent) { + parent = (pdata[cpld].client)->adapter; + } + i2c_unregister_device(pdata[cpld].client); + } + } + i2c_put_adapter(parent); + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v1-cpupld", + }, +}; +/*---------------- CPUPLD - end ------------- */ + + +/*---------------- module initialization ------------- */ +static int __init delta_ag9032v1_cpupld_init(void) +{ + int ret; + printk(KERN_WARNING "ag9032v1_platform_cpupld module initialization\n"); + + // set the CPUPLD prob and remove + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpupld driver\n"); + goto error_cpupld_driver; + } + + // register the CPUPLD + ret = platform_device_register(&ag9032v1_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpupld device\n"); + goto error_ag9032v1_cpupld; + } + return 0; + +error_ag9032v1_cpupld: + platform_driver_unregister(&cpld_driver); +error_cpupld_driver: + return ret; +} + +static void __exit delta_ag9032v1_cpupld_exit(void) +{ + platform_device_unregister(&ag9032v1_cpld); + platform_driver_unregister(&cpld_driver); +} +module_init(delta_ag9032v1_cpupld_init); +module_exit(delta_ag9032v1_cpupld_exit); + +MODULE_DESCRIPTION("DNI ag9032v1 CPLD Platform Support"); +MODULE_AUTHOR("Stanley Chi "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_platform.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_platform.c new file mode 100644 index 000000000000..9b7a1958c77a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_platform.c @@ -0,0 +1,2554 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUS3_DEV_NUM 9 +#define BUS4_DEV_NUM 6 +#define BUS5_DEV_NUM 32 +#define DEFAULT_NUM 1 +#define BUS3_BASE_NUM 30 +#define BUS4_BASE_NUM 40 +#define BUS5_BASE_NUM 50 + +#define BUS3_MUX_REG 0x21 +#define BUS4_MUX_REG 0x21 +#define BUS5_MUX_REG 0x20 + +#define TEMP_FAN_VAL 0x06 +#define FANIO_CTL_VAL 0x07 +#define FAN_CTRL_VAL 0x05 +#define PSU1_VAL 0x00 +#define PSU2_VAL 0x20 +#define HOT_SWAP1_VAL 0x10 +#define HOT_SWAP2_VAL 0x30 +#define FAN_EEPROM1_VAL 0x00 +#define FAN_EEPROM2_VAL 0x01 +#define FAN_EEPROM3_VAL 0x02 +#define FAN_EEPROM4_VAL 0x03 +#define FAN_EEPROM5_VAL 0x04 + +#define SWPLD_REG 0x31 +#define SWPLD_SFP_MUX_REG 0x20 + +#define SYS_LED_REG 0x1C +#define FAN1_LED_REG 0x1D +#define FAN2_LED_REG 0x1E + +#define SFP_PRESENCE_1 0x38 +#define SFP_PRESENCE_2 0x39 +#define SFP_PRESENCE_3 0x3A +#define SFP_PRESENCE_4 0x3B + +#define SFP_LP_MODE_1 0x34 +#define SFP_LP_MODE_2 0x35 +#define SFP_LP_MODE_3 0x36 +#define SFP_LP_MODE_4 0x37 + +#define SFP_RESET_1 0x3C +#define SFP_RESET_2 0x3D +#define SFP_RESET_3 0x3E +#define SFP_RESET_4 0x3F + +#define SFP_RESPONSE_1 0x30 +#define SFP_RESPONSE_2 0x31 +#define SFP_RESPONSE_3 0x32 +#define SFP_RESPONSE_4 0x33 + +#define SFF8436_INFO(data) \ + .type = "sff8436", .addr = 0x50, .platform_data = (data) + +#define SFF_8346_PORT(eedata) \ + .byte_len = 256, .page_size = 1, .flags = SFF_8436_FLAG_READONLY + +#define ag9032v1_i2c_device_num(NUM){ \ + .name = "delta-ag9032v1-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &ag9032v1_i2c_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +/*Define struct to get client of i2c_new_deivce */ +struct i2c_client * i2c_client_9547; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, +}; + +unsigned char reverse_8bits(unsigned char c) +{ + unsigned char s = 0; + int i; + for (i = 0; i < 8; ++i) { + s <<= 1; + s |= c & 1; + c >>= 1; + } + return s; +} +/*---------------- I2C device - start ------------- */ +static void device_release(struct device *dev) +{ + return; +} + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; +/* pca9547 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode[] = { + { .adap_id = 2, + .deselect_on_exit = 1, + }, + { .adap_id = 3, + .deselect_on_exit = 1, + }, + { .adap_id = 4, + .deselect_on_exit = 1, + }, + { .adap_id = 5, + .deselect_on_exit = 1, + }, + { .adap_id = 6, + .deselect_on_exit = 1, + }, + { .adap_id = 7, + .deselect_on_exit = 1, + }, + { .adap_id = 8, + .deselect_on_exit = 1, + }, + { .adap_id = 9, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_data pca954x_data = { + .modes = pca954x_mode, + .num_modes = ARRAY_SIZE(pca954x_mode), +}; + +static struct i2c_board_info __initdata i2c_info_pca9547[] = +{ + { + I2C_BOARD_INFO("pca9547", 0x71), + .platform_data = &pca954x_data, + }, +}; + + +static struct sff_8436_platform_data sff_8436_port[] = { + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, +}; + +static struct i2c_device_platform_data ag9032v1_i2c_device_platform_data[] = { + { + /* tmp75 (0x4d) */ + .parent = 2, + .info = { I2C_BOARD_INFO("tmp75", 0x4d) }, + .client = NULL, + }, + { + /* id eeprom (0x53) */ + .parent = 2, + .info = { I2C_BOARD_INFO("24c02", 0x53) }, + .client = NULL, + }, + { + /* tmp75 (0x4c) */ + .parent = 7, + .info = { I2C_BOARD_INFO("tmp75", 0x4c) }, + .client = NULL, + }, + { + /* tmp75 (0x4d) */ + .parent = 7, + .info = { I2C_BOARD_INFO("tmp75", 0x4d) }, + .client = NULL, + }, + { + /* tmp75 (0x4e) */ + .parent = 7, + .info = { I2C_BOARD_INFO("tmp75", 0x4e) }, + .client = NULL, + }, + { + /* tmp75 (0x4f) */ + .parent = 30, + .info = { I2C_BOARD_INFO("tmp75", 0x4f) }, + .client = NULL, + }, + { + /* FAN 1 Controller (0x2c) */ + .parent = 37, + .info = { I2C_BOARD_INFO("emc2305", 0x2c) }, + .client = NULL, + }, + { + /* FAN 2 Controller (0x2d) */ + .parent = 38, + .info = { I2C_BOARD_INFO("emc2305", 0x2d) }, + .client = NULL, + }, + { + /* psu 1 (0x58) */ + .parent = 40, + .info = { .type = "dni_ag9032v1_psu", .addr = 0x58, .platform_data = (void *) 0 }, + .client = NULL, + }, + { + /* psu 2 (0x58) */ + .parent = 41, + .info = { .type = "dni_ag9032v1_psu", .addr = 0x58, .platform_data = (void *) 1 }, + .client = NULL, + }, + { + /* hot-swap 1 (0x40) */ + .parent = 42, + .info = { .type = "ltc4215", .addr = 0x40, .platform_data = (void *) 0 }, + .client = NULL, + }, + { + /* hot-swap 2 (0x40) */ + .parent = 43, + .info = { .type = "ltc4215", .addr = 0x40, .platform_data = (void *) 1 }, + .client = NULL, + }, + { + /* qsfp 1 (0x50) */ + .parent = 50, + .info = { SFF8436_INFO(&sff_8436_port[0]) }, + .client = NULL, + }, + { + /* qsfp 2 (0x50) */ + .parent = 51, + .info = { SFF8436_INFO(&sff_8436_port[1]) }, + .client = NULL, + }, + { + /* qsfp 3 (0x50) */ + .parent = 52, + .info = { SFF8436_INFO(&sff_8436_port[2]) }, + .client = NULL, + }, + { + /* qsfp 4 (0x50) */ + .parent = 53, + .info = { SFF8436_INFO(&sff_8436_port[3]) }, + .client = NULL, + }, + { + /* qsfp 5 (0x50) */ + .parent = 54, + .info = { SFF8436_INFO(&sff_8436_port[4]) }, + .client = NULL, + }, + { + /* qsfp 6 (0x50) */ + .parent = 55, + .info = { SFF8436_INFO(&sff_8436_port[5]) }, + .client = NULL, + }, + { + /* qsfp 7 (0x50) */ + .parent = 56, + .info = { SFF8436_INFO(&sff_8436_port[6]) }, + .client = NULL, + }, + { + /* qsfp 8 (0x50) */ + .parent = 57, + .info = { SFF8436_INFO(&sff_8436_port[7]) }, + .client = NULL, + }, + { + /* qsfp 9 (0x50) */ + .parent = 58, + .info = { SFF8436_INFO(&sff_8436_port[8]) }, + .client = NULL, + }, + { + /* qsfp 10 (0x50) */ + .parent = 59, + .info = { SFF8436_INFO(&sff_8436_port[9]) }, + .client = NULL, + }, + { + /* qsfp 11 (0x50) */ + .parent = 60, + .info = { SFF8436_INFO(&sff_8436_port[10]) }, + .client = NULL, + }, + { + /* qsfp 12 (0x50) */ + .parent = 61, + .info = { SFF8436_INFO(&sff_8436_port[11]) }, + .client = NULL, + }, + { + /* qsfp 13 (0x50) */ + .parent = 62, + .info = { SFF8436_INFO(&sff_8436_port[12]) }, + .client = NULL, + }, + { + /* qsfp 14 (0x50) */ + .parent = 63, + .info = { SFF8436_INFO(&sff_8436_port[13]) }, + .client = NULL, + }, + { + /* qsfp 15 (0x50) */ + .parent = 64, + .info = { SFF8436_INFO(&sff_8436_port[14]) }, + .client = NULL, + }, + { + /* qsfp 16 (0x50) */ + .parent = 65, + .info = { SFF8436_INFO(&sff_8436_port[15]) }, + .client = NULL, + }, + { + /* qsfp 17 (0x50) */ + .parent = 66, + .info = { SFF8436_INFO(&sff_8436_port[16]) }, + .client = NULL, + }, + { + /* qsfp 18 (0x50) */ + .parent = 67, + .info = { SFF8436_INFO(&sff_8436_port[17]) }, + .client = NULL, + }, + { + /* qsfp 19 (0x50) */ + .parent = 68, + .info = { SFF8436_INFO(&sff_8436_port[18]) }, + .client = NULL, + }, + { + /* qsfp 20 (0x50) */ + .parent = 69, + .info = { SFF8436_INFO(&sff_8436_port[19]) }, + .client = NULL, + }, + { + /* qsfp 21 (0x50) */ + .parent = 70, + .info = { SFF8436_INFO(&sff_8436_port[20]) }, + .client = NULL, + }, + { + /* qsfp 22 (0x50) */ + .parent = 71, + .info = { SFF8436_INFO(&sff_8436_port[21]) }, + .client = NULL, + }, + { + /* qsfp 23 (0x50) */ + .parent = 72, + .info = { SFF8436_INFO(&sff_8436_port[22]) }, + .client = NULL, + }, + { + /* qsfp 24 (0x50) */ + .parent = 73, + .info = { SFF8436_INFO(&sff_8436_port[23]) }, + .client = NULL, + }, + { + /* qsfp 25 (0x50) */ + .parent = 74, + .info = { SFF8436_INFO(&sff_8436_port[24]) }, + .client = NULL, + }, + { + /* qsfp 26 (0x50) */ + .parent = 75, + .info = { SFF8436_INFO(&sff_8436_port[25]) }, + .client = NULL, + }, + { + /* qsfp 27 (0x50) */ + .parent = 76, + .info = { SFF8436_INFO(&sff_8436_port[26]) }, + .client = NULL, + }, + { + /* qsfp 28 (0x50) */ + .parent = 77, + .info = { SFF8436_INFO(&sff_8436_port[27]) }, + .client = NULL, + }, + { + /* qsfp 29 (0x50) */ + .parent = 78, + .info = { SFF8436_INFO(&sff_8436_port[28]) }, + .client = NULL, + }, + { + /* qsfp 30 (0x50) */ + .parent = 79, + .info = { SFF8436_INFO(&sff_8436_port[29]) }, + .client = NULL, + }, + { + /* qsfp 31 (0x50) */ + .parent = 80, + .info = { SFF8436_INFO(&sff_8436_port[30]) }, + .client = NULL, + }, + { + /* qsfp 32 (0x50) */ + .parent = 81, + .info = { SFF8436_INFO(&sff_8436_port[31]) }, + .client = NULL, + }, +}; + + +static struct platform_device ag9032v1_i2c_device[] = { + ag9032v1_i2c_device_num(0), + ag9032v1_i2c_device_num(1), + ag9032v1_i2c_device_num(2), + ag9032v1_i2c_device_num(3), + ag9032v1_i2c_device_num(4), + ag9032v1_i2c_device_num(5), + ag9032v1_i2c_device_num(6), + ag9032v1_i2c_device_num(7), + ag9032v1_i2c_device_num(8), + ag9032v1_i2c_device_num(9), + ag9032v1_i2c_device_num(10), + ag9032v1_i2c_device_num(11), + ag9032v1_i2c_device_num(12), + ag9032v1_i2c_device_num(13), + ag9032v1_i2c_device_num(14), + ag9032v1_i2c_device_num(15), + ag9032v1_i2c_device_num(16), + ag9032v1_i2c_device_num(17), + ag9032v1_i2c_device_num(18), + ag9032v1_i2c_device_num(19), + ag9032v1_i2c_device_num(20), + ag9032v1_i2c_device_num(21), + ag9032v1_i2c_device_num(22), + ag9032v1_i2c_device_num(23), + ag9032v1_i2c_device_num(24), + ag9032v1_i2c_device_num(25), + ag9032v1_i2c_device_num(26), + ag9032v1_i2c_device_num(27), + ag9032v1_i2c_device_num(28), + ag9032v1_i2c_device_num(29), + ag9032v1_i2c_device_num(30), + ag9032v1_i2c_device_num(31), + ag9032v1_i2c_device_num(32), + ag9032v1_i2c_device_num(33), + ag9032v1_i2c_device_num(34), + ag9032v1_i2c_device_num(35), + ag9032v1_i2c_device_num(36), + ag9032v1_i2c_device_num(37), + ag9032v1_i2c_device_num(38), + ag9032v1_i2c_device_num(39), + ag9032v1_i2c_device_num(40), + ag9032v1_i2c_device_num(41), + ag9032v1_i2c_device_num(42), + ag9032v1_i2c_device_num(43), +}; + +/*---------------- I2C device - end ------------- */ + +/*---------------- I2C driver - start ------------- */ +static int __init i2c_device_probe(struct platform_device *pdev) +{ + struct i2c_device_platform_data *pdata; + struct i2c_adapter *parent; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + return 0; +} + +static int __exit i2c_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + if (pdata->client) { + parent = (pdata->client)->adapter; + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + } + + return 0; +} +static struct platform_driver i2c_device_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v1-i2c-device", + } +}; + +/*---------------- I2C driver - end ------------- */ + +/*---------------- CPLD - start ------------- */ + +/* CPLD -- device */ + +enum cpld_type { + system_cpld, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +enum swpld_attributes { + SW_BOARD_ID, + SW_BOARD_VER, + SWPLD_VER, + SYS_RST, + B56960_RST, + MB_A_PLD_RST, + MB_B_PLD_RST, + PSU1_PWR_OK, + PSU2_PWR_OK, + HS1_PWR_OK, + HS2_PWR_OK, + B54616_RST, + B54616_INT, + B54616_MASK_INT, + PB_HS_INT, + MB_HS_INT, + PB_PWR_INT, + MB_PWR_INT, + FAN_INT, + PB_HS_MASK_INT, + MB_HS_MASK_INT, + PB_PWR1_MASK_INT, + PB_PWR2_MASK_INT, + FAN_MASK_INT, + QSFP_01TO08_INT, + QSFP_08TO16_INT, + QSFP_17TO24_INT, + QSFP_25TO32_INT, + QSFP_01TO08_ABS, + QSFP_08TO16_ABS, + QSFP_17TO24_ABS, + QSFP_25TO32_ABS, + QSFP_01TO08_MASK_INT, + QSFP_08TO16_MASK_INT, + QSFP_17TO24_MASK_INT, + QSFP_25TO32_MASK_INT, + QSFP_01TO08_MASK_ABS, + QSFP_08TO16_MASK_ABS, + QSFP_17TO24_MASK_ABS, + QSFP_25TO32_MASK_ABS, + QSFP01_MOD_INT, + QSFP02_MOD_INT, + QSFP03_MOD_INT, + QSFP04_MOD_INT, + QSFP05_MOD_INT, + QSFP06_MOD_INT, + QSFP07_MOD_INT, + QSFP08_MOD_INT, + QSFP09_MOD_INT, + QSFP10_MOD_INT, + QSFP11_MOD_INT, + QSFP12_MOD_INT, + QSFP13_MOD_INT, + QSFP14_MOD_INT, + QSFP15_MOD_INT, + QSFP16_MOD_INT, + QSFP17_MOD_INT, + QSFP18_MOD_INT, + QSFP19_MOD_INT, + QSFP20_MOD_INT, + QSFP21_MOD_INT, + QSFP22_MOD_INT, + QSFP23_MOD_INT, + QSFP24_MOD_INT, + QSFP25_MOD_INT, + QSFP26_MOD_INT, + QSFP27_MOD_INT, + QSFP28_MOD_INT, + QSFP29_MOD_INT, + QSFP30_MOD_INT, + QSFP31_MOD_INT, + QSFP32_MOD_INT, +}; + +static struct cpld_platform_data ag9032v1_cpld_platform_data[] = { + [system_cpld] = { + .reg_addr = SWPLD_REG, + }, +}; + +static struct platform_device ag9032v1_cpld = { + .name = "delta-ag9032v1-swpld", + .id = 0, + .dev = { + .platform_data = ag9032v1_cpld_platform_data, + .release = device_release, + }, +}; + +static struct swpld_attribute_data { + int reg_addr; + int reg_mask; + char reg_note[150]; +}; + +static struct swpld_attribute_data controller_interrupt_data[] = { +//BOARD + [SYS_RST] = { + .reg_addr = 0x04, + .reg_mask = 7, + .reg_note = "“1” = Normal operation\n“0” = Reset" + }, + [B56960_RST] = { + .reg_addr = 0x04, + .reg_mask = 6, + .reg_note = "“1” = Normal operation\n“0” = Reset" + }, + [MB_A_PLD_RST] = { + .reg_addr = 0x04, + .reg_mask = 4, + .reg_note = "“1” = Normal operation\n“0” = Reset" + }, + [MB_B_PLD_RST] = { + .reg_addr = 0x04, + .reg_mask = 3, + .reg_note = "“1” = Normal operation\n“0” = Reset" + }, +//PSU + [PSU1_PWR_OK] = { + .reg_addr = 0x0a, + .reg_mask = 7, + .reg_note = "‘0’ = Power rail is failed\n‘1’ = Power rail is good" + }, + [PSU2_PWR_OK] = { + .reg_addr = 0x0a, + .reg_mask = 6, + .reg_note = "‘0’ = Power rail is failed\n‘1’ = Power rail is good" + }, +//HOT SWAP + [HS1_PWR_OK] = { + .reg_addr = 0x08, + .reg_mask = 5, + .reg_note = "‘0’ = Hot swap controller disabled\n‘1’ = Hot swap controller enabled" + }, + [HS2_PWR_OK] = { + .reg_addr = 0x08, + .reg_mask = 4, + .reg_note = "‘0’ = Hot swap controller disabled\n‘1’ = Hot swap controller enabled" + }, +//BCM54616S + [B54616_RST] = { + .reg_addr = 0x04, + .reg_mask = 5, + .reg_note = "“0” = Reset\n“1” = Normal operation" + }, + [B54616_INT] = { + .reg_addr = 0x16, + .reg_mask = 7, + .reg_note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [B54616_MASK_INT] = { + .reg_addr = 0x17, + .reg_mask = 7, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, +//QSFP + [PB_HS_INT] = { + .reg_addr = 0x10, + .reg_mask = 7, + .reg_note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [MB_HS_INT] = { + .reg_addr = 0x10, + .reg_mask = 6, + .reg_note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [PB_PWR_INT] = { + .reg_addr = 0x10, + .reg_mask = 5, + .reg_note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [MB_PWR_INT] = { + .reg_addr = 0x10, + .reg_mask = 4, + .reg_note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [FAN_INT] = { + .reg_addr = 0x10, + .reg_mask = 3, + .reg_note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [PB_HS_MASK_INT] = { + .reg_addr = 0x11, + .reg_mask = 7, + .reg_note = "‘0’ = Interrupt doesn’t masked\n‘1’ = Interrupt masked" + }, + [MB_HS_MASK_INT] = { + .reg_addr = 0x11, + .reg_mask = 6, + .reg_note = "‘0’ = Interrupt doesn’t masked\n‘1’ = Interrupt masked" + }, + [PB_PWR1_MASK_INT] = { + .reg_addr = 0x11, + .reg_mask = 5, + .reg_note = "‘0’ = Interrupt doesn’t masked\n‘1’ = Interrupt masked" + }, + [PB_PWR2_MASK_INT] = { + .reg_addr = 0x11, + .reg_mask = 4, + .reg_note = "‘0’ = Interrupt doesn’t masked\n‘1’ = Interrupt masked" + }, + [FAN_MASK_INT] = { + .reg_addr = 0x11, + .reg_mask = 3, + .reg_note = "‘0’ = Interrupt doesn’t masked\n‘1’ = Interrupt masked" + }, + [QSFP_01TO08_INT] = { + .reg_addr = 0x12, + .reg_mask = 7, + .reg_note = "“0” = Interrupt occurs\n“1” = Interrupt doesn’t occur" + }, + [QSFP_08TO16_INT] = { + .reg_addr = 0x12, + .reg_mask = 6, + .reg_note = "“0” = Interrupt occurs\n“1” = Interrupt doesn’t occur" + }, + [QSFP_17TO24_INT] = { + .reg_addr = 0x12, + .reg_mask = 5, + .reg_note = "“0” = Interrupt occurs\n“1” = Interrupt doesn’t occur" + }, + [QSFP_25TO32_INT] = { + .reg_addr = 0x12, + .reg_mask = 4, + .reg_note = "“0” = Interrupt occurs\n“1” = Interrupt doesn’t occur" + }, + [QSFP_01TO08_ABS] = { + .reg_addr = 0x12, + .reg_mask = 3, + .reg_note = "“0” = Absence status change\n“1” = Absence status not changes" + }, + [QSFP_08TO16_ABS] = { + .reg_addr = 0x12, + .reg_mask = 2, + .reg_note = "“0” = Absence status change\n“1” = Absence status not changes" + }, + [QSFP_17TO24_ABS] = { + .reg_addr = 0x12, + .reg_mask = 1, + .reg_note = "“0” = Absence status change\n“1” = Absence status not changes" + }, + [QSFP_25TO32_ABS] = { + .reg_addr = 0x12, + .reg_mask = 0, + .reg_note = "“0” = Absence status change\n“1” = Absence status not changes" + }, + [QSFP_01TO08_MASK_INT] = { + .reg_addr = 0x13, + .reg_mask = 7, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_08TO16_MASK_INT] = { + .reg_addr = 0x13, + .reg_mask = 6, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_17TO24_MASK_INT] = { + .reg_addr = 0x13, + .reg_mask = 5, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_25TO32_MASK_INT] = { + .reg_addr = 0x13, + .reg_mask = 4, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_01TO08_MASK_ABS] = { + .reg_addr = 0x13, + .reg_mask = 3, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_08TO16_MASK_ABS] = { + .reg_addr = 0x13, + .reg_mask = 2, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_17TO24_MASK_ABS] = { + .reg_addr = 0x13, + .reg_mask = 1, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_25TO32_MASK_ABS] = { + .reg_addr = 0x13, + .reg_mask = 0, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP01_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 7, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP02_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 6, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP03_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 5, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP04_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 4, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP05_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 3, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP06_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 2, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP07_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 1, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP08_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 0, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP09_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 7, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP10_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 6, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP11_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 5, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP12_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 4, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP13_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 3, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP14_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 2, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP15_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 1, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP16_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 0, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP17_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 7, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP18_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 6, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP19_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 5, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP20_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 4, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP21_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 3, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP22_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 2, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP23_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 1, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP24_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 0, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP25_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 7, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP26_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 6, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP27_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 5, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP28_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 4, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP29_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 3, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP30_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 2, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP31_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 1, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP32_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 0, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, +}; + +static ssize_t get_present(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_1); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = (u32)reverse_8bits(ret) & 0xff; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_2); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_3); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_4); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); //return 32bits data +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_1); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = (u32)(reverse_8bits(ret) & 0xff); + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_2); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_3); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_4); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); //return 32bits data +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_LP_MODE_1, (u8)reverse_8bits(data & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_LP_MODE_2, (u8)(reverse_8bits(data >> 8) & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_LP_MODE_3, (u8)(reverse_8bits(data >> 16) & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_LP_MODE_4, (u8)(reverse_8bits(data >> 24) & 0xff)); + + return count; +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_1); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = (u32)(reverse_8bits(ret) & 0xff); + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_2); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_3); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_4); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); //return 32bits data +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESET_1, (u8)reverse_8bits(data & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESET_2, (u8)reverse_8bits((data >> 8)& 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESET_3, (u8)reverse_8bits((data >> 16) & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESET_4, (u8)reverse_8bits((data >> 24) & 0xff)); + + return count; +} + +static ssize_t get_response(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_1); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = (u32)(reverse_8bits(ret) & 0xff); + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_2); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_3); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_4); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); //return 32bits data +} + +static ssize_t set_response(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESPONSE_1, (u8)reverse_8bits(data & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESPONSE_2, (u8)reverse_8bits((data >> 8)& 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESPONSE_3, (u8)reverse_8bits((data >> 16) & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESPONSE_4, (u8)reverse_8bits((data >> 24) & 0xff)); + + return count; +} + +struct platform_led_status{ + int reg_data; + char *led_status; + int led_id; +}; + +static struct platform_led_status led_info[] = { + { + .reg_data = 0x40, + .led_status = "pwr1_green", + .led_id = 0, + }, + { + .reg_data = 0x80, + .led_status = "pwr1_amber", + .led_id = 0, + }, + { + .reg_data = 0x00, + .led_status = "pwr1_off", + .led_id = 0, + }, + { + .reg_data = 0xc0, + .led_status = "pwr1_off", + .led_id = 0, + }, + { + .reg_data = 0x10, + .led_status = "pwr2_green", + .led_id = 1, + }, + { + .reg_data = 0x20, + .led_status = "pwr2_amber", + .led_id = 1, + }, + { + .reg_data = 0x00, + .led_status = "pwr2_off", + .led_id = 1, + }, + { + .reg_data = 0x30, + .led_status = "pwr2_off", + .led_id = 1, + }, + { + .reg_data = 0x04, + .led_status = "sys_green", + .led_id = 2, + }, + { + .reg_data = 0x08, + .led_status = "sys_blinking_green", + .led_id = 2, + }, + { + .reg_data = 0x0c, + .led_status = "sys_red", + .led_id = 2, + }, + { + .reg_data = 0x00, + .led_status = "sys_off", + .led_id = 2, + }, + { + .reg_data = 0x01, + .led_status = "fan_green", + .led_id = 3, + }, + { + .reg_data = 0x02, + .led_status = "fan_amber", + .led_id = 3, + }, + { + .reg_data = 0x00, + .led_status = "fan_off", + .led_id = 3, + }, + { + .reg_data = 0x03, + .led_status = "fan_off", + .led_id = 3, + }, + { + .reg_data = 0x40, + .led_status = "fan1_green", + .led_id = 4, + }, + { + .reg_data = 0x80, + .led_status = "fan1_red", + .led_id = 4, + }, + { + .reg_data = 0x00, + .led_status = "fan1_off", + .led_id = 4, + }, + { + .reg_data = 0x10, + .led_status = "fan2_green", + .led_id = 5, + }, + { + .reg_data = 0x20, + .led_status = "fan2_red", + .led_id = 5, + }, + { + .reg_data = 0x00, + .led_status = "fan2_off", + .led_id = 5, + }, + { + .reg_data = 0x04, + .led_status = "fan3_green", + .led_id = 6, + }, + { + .reg_data = 0x08, + .led_status = "fan3_red", + .led_id = 6, + }, + { + .reg_data = 0x00, + .led_status = "fan3_off", + .led_id = 6, + }, + { + .reg_data = 0x01, + .led_status = "fan4_green", + .led_id = 7, + }, + { + .reg_data = 0x02, + .led_status = "fan4_red", + .led_id = 7, + }, + { + .reg_data = 0x00, + .led_status = "fan4_off", + .led_id = 7, + }, + { + .reg_data = 0x40, + .led_status = "fan5_green", + .led_id = 8, + }, + { + .reg_data = 0x80, + .led_status = "fan5_red", + .led_id = 8, + }, + { + .reg_data = 0x00, + .led_status = "fan5_off", + .led_id = 8, + }, +}; + +struct platform_led_data{ + int reg_addr; + int mask; +}; + +static struct platform_led_data led_data[] = { + { + .reg_addr = SYS_LED_REG, + .mask = 0xc0, + }, + { + .reg_addr = SYS_LED_REG, + .mask = 0x30, + }, + { + .reg_addr = SYS_LED_REG, + .mask = 0x0c, + }, + { + .reg_addr = SYS_LED_REG, + .mask = 0x03, + }, + { + .reg_addr = FAN1_LED_REG, + .mask = 0xc0, + }, + { + .reg_addr = FAN1_LED_REG, + .mask = 0x30, + }, + { + .reg_addr = FAN1_LED_REG, + .mask = 0x0c, + }, + { + .reg_addr = FAN1_LED_REG, + .mask = 0x03, + }, + { + .reg_addr = FAN2_LED_REG, + .mask = 0xc0, + }, +}; + +static ssize_t get_led_color(struct device *dev, struct device_attribute *devattr, char *buf) +{ + char str[9][20] = {0}; + int board_data; + int led_data_number; + int led_info_number; + struct cpld_platform_data *pdata = dev->platform_data; + + for(led_data_number = 0; led_data_number < ARRAY_SIZE(led_data); led_data_number++){ + board_data = i2c_smbus_read_byte_data(pdata[system_cpld].client, led_data[led_data_number].reg_addr); + if(board_data >= 0){ + board_data &= led_data[led_data_number].mask; + for(led_info_number = 0; led_info_number < ARRAY_SIZE(led_info); led_info_number++){ + if (led_data_number == led_info[led_info_number].led_id){ + if(board_data == led_info[led_info_number].reg_data){ + sprintf(str[led_data_number], "%s", led_info[led_info_number].led_status); + } + } + } + } + else + printk( KERN_ERR "Missing LED board data\n"); + } + return sprintf(buf,"%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",str[0],str[1],str[2],str[3],str[4],str[5],str[6],str[7],str[8]); +} + +static ssize_t set_led_color(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int led_info_number; + int led_data_number; + int str_compar; + int led_reg_value; + struct cpld_platform_data *pdata = dev->platform_data; + + for(led_info_number = 0; led_info_number < ARRAY_SIZE(led_info); led_info_number++){ + str_compar = strncmp(buf,led_info[led_info_number].led_status,strlen(led_info[led_info_number].led_status)); + if(str_compar == 0){ + for(led_data_number = 0; led_data_number < ARRAY_SIZE(led_data); led_data_number++){ + if(led_info[led_info_number].led_id == led_data_number){ + led_reg_value = i2c_smbus_read_byte_data(pdata[system_cpld].client, led_data[led_data_number].reg_addr); + if(led_reg_value >= 0){ + led_reg_value &= (~led_data[led_data_number].mask); + led_reg_value |= led_info[led_info_number].reg_data; + i2c_smbus_write_byte_data(pdata[system_cpld].client, (u8)(led_data[led_data_number].reg_addr & 0xff), (u8)(led_reg_value & 0xff)); + } + else + printk( KERN_ERR "Missing LED reg. data\n"); + } + } + } + } + return count; +} + +static unsigned char swpld_reg_addr; +static ssize_t get_swpld_reg_value(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, swpld_reg_addr); + return sprintf(buf, "0x%02x\n", ret); +} + +static ssize_t set_swpld_reg_value(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + i2c_smbus_write_byte_data(pdata[system_cpld].client, swpld_reg_addr, data); + + return count; +} + +static ssize_t get_swpld_reg_addr(struct device *dev, struct device_attribute *devattr, char *buf) +{ + + return sprintf(buf, "0x%02x\n", swpld_reg_addr); +} + +static ssize_t set_swpld_reg_addr(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long data; + int err; + + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + swpld_reg_addr = data; + + return count; +} + +static DEVICE_ATTR(swpld_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg_value, set_swpld_reg_value); +static DEVICE_ATTR(swpld_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg_addr, set_swpld_reg_addr); +static DEVICE_ATTR(sfp_present, S_IRUGO, get_present, NULL ); +static DEVICE_ATTR(sfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode ); +static DEVICE_ATTR(sfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset ); +static DEVICE_ATTR(sfp_response, S_IRUGO | S_IWUSR, get_response, set_response ); +static DEVICE_ATTR(led_control, S_IRUGO | S_IWUSR, get_led_color, set_led_color); + +static struct attribute *ag9032v1_cpld_attrs[] = { + &dev_attr_swpld_reg_value.attr, + &dev_attr_swpld_reg_addr.attr, + &dev_attr_sfp_response.attr, + &dev_attr_sfp_present.attr, + &dev_attr_sfp_lpmode.attr, + &dev_attr_sfp_reset.attr, + &dev_attr_led_control.attr, + NULL, +}; + +static struct attribute_group ag9032v1_cpld_attr_grp = { + .attrs = ag9032v1_cpld_attrs, +}; + +static struct kobject *kobj_swpld; +static struct kobject *kobj_board; +static struct kobject *kobj_psu; +static struct kobject *kobj_hot_swap; +static struct kobject *kobj_controller_interrupt; +static struct kobject *kobj_BCM54616S; + +static ssize_t get_swpld_data(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + int ret; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_swpld); + struct cpld_platform_data *pdata = i2cdev->platform_data; + + + unsigned char reg; + int mask; + int value; + char note[150]; + + switch (attr->index) { + //attributes on BOARD + case SW_BOARD_ID: + reg = 0x00; + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + value = ret >> 4; + sprintf(note, "\n“0x00”: L9032NB-AL-R\n“0x01”: AK9032-R\n“0x02”: AG9032-R\n“0x03”: AG9032R-R\n“0x04”: AG9032 V1-R\n"); + return sprintf(buf, "0x%02x%s", value, note); + case SW_BOARD_VER: + reg = 0x00; + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + value = ret & 0x0F; + sprintf(note, "\n“0x00”: proto-A\n“0x01”: proto-B\n"); + return sprintf(buf, "0x%02x%s", value, note); + case SWPLD_VER: + reg = 0x01; + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + value = ret & 0xFF; + sprintf(note, " "); + return sprintf(buf, "0x%02x%s", value, note); + //other attributes + case SYS_RST ... QSFP32_MOD_INT: + reg = controller_interrupt_data[attr->index].reg_addr; + mask = controller_interrupt_data[attr->index].reg_mask; + sprintf(note, "\n%s\n",controller_interrupt_data[attr->index].reg_note); + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + value = (ret & (1 << mask)) >> mask; + return sprintf(buf, "%d%s", value, note); + default: + return sprintf(buf, "%d not found", attr->index); + } +} + +static ssize_t set_swpld_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + int ret; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_board->parent); + struct cpld_platform_data *pdata = i2cdev->platform_data; + unsigned char reg; + int mask; + int value; + char note[180]; + int data; + int val; + u8 mask_out; + + ret = kstrtoint(buf, 0, &val); + + if (ret) + { + return ret; + } + if (val > 1) + { + return -EINVAL; + } + + switch (attr->index) { + case SYS_RST ... MB_B_PLD_RST: + case HS1_PWR_OK ... HS2_PWR_OK: + case B54616_RST: + case QSFP_01TO08_MASK_INT... QSFP_25TO32_MASK_ABS: + reg = controller_interrupt_data[attr->index].reg_addr; + mask = controller_interrupt_data[attr->index].reg_mask; + break; + default: + return sprintf(buf, "%d not found", attr->index); + } + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + mask_out = ret & ~((u8)(1 << mask)); + data = mask_out | (val << mask); + i2c_smbus_write_byte_data(pdata[system_cpld].client, reg, (u8)(data & 0xff)); + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + return count; +} + +static SENSOR_DEVICE_ATTR(sw_board_id, S_IRUGO, get_swpld_data, NULL, SW_BOARD_ID); +static SENSOR_DEVICE_ATTR(sw_board_ver, S_IRUGO, get_swpld_data, NULL, SW_BOARD_VER); +static SENSOR_DEVICE_ATTR(swpld_ver, S_IRUGO, get_swpld_data, NULL, SWPLD_VER); +static SENSOR_DEVICE_ATTR(sys_rst, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, SYS_RST); +static SENSOR_DEVICE_ATTR(B56960_rst, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, B56960_RST); +static SENSOR_DEVICE_ATTR(mb_a_pld_rst, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, MB_A_PLD_RST); +static SENSOR_DEVICE_ATTR(mb_b_pld_rst, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, MB_B_PLD_RST); + +static struct attribute *ag9032v1_swpld_attrs_board[] = { + &sensor_dev_attr_sw_board_id.dev_attr.attr, + &sensor_dev_attr_sw_board_ver.dev_attr.attr, + &sensor_dev_attr_swpld_ver.dev_attr.attr, + &sensor_dev_attr_sys_rst.dev_attr.attr, + &sensor_dev_attr_B56960_rst.dev_attr.attr, + &sensor_dev_attr_mb_a_pld_rst.dev_attr.attr, + &sensor_dev_attr_mb_b_pld_rst.dev_attr.attr, + NULL, +}; + +static SENSOR_DEVICE_ATTR(psu1_pwr_ok, S_IRUGO, get_swpld_data, NULL, PSU1_PWR_OK); +static SENSOR_DEVICE_ATTR(psu2_pwr_ok, S_IRUGO, get_swpld_data, NULL, PSU2_PWR_OK); + +static struct attribute *ag9032v1_swpld_attrs_psu[] = { + &sensor_dev_attr_psu1_pwr_ok.dev_attr.attr, + &sensor_dev_attr_psu2_pwr_ok.dev_attr.attr, + NULL, +}; + +static SENSOR_DEVICE_ATTR(hs1_pwr_ok, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, HS1_PWR_OK); +static SENSOR_DEVICE_ATTR(hs2_pwr_ok, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, HS2_PWR_OK); + +static struct attribute *ag9032v1_swpld_attrs_hot_swap[] = { + &sensor_dev_attr_hs1_pwr_ok.dev_attr.attr, + &sensor_dev_attr_hs2_pwr_ok.dev_attr.attr, + NULL, +}; + +static SENSOR_DEVICE_ATTR(B54616_rst, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, B54616_RST ); +static SENSOR_DEVICE_ATTR(B54616_int, S_IRUGO, get_swpld_data, NULL, B54616_INT ); +static SENSOR_DEVICE_ATTR(B54616_mask_int, S_IRUGO, get_swpld_data, NULL, B54616_MASK_INT); + +static struct attribute *ag9032v1_swpld_attrs_BCM54616S[] = { + &sensor_dev_attr_B54616_rst.dev_attr.attr, + &sensor_dev_attr_B54616_int.dev_attr.attr, + &sensor_dev_attr_B54616_mask_int.dev_attr.attr, + NULL, +}; + +static SENSOR_DEVICE_ATTR(pb_hs_int, S_IRUGO, get_swpld_data, NULL, PB_HS_INT); +static SENSOR_DEVICE_ATTR(mb_hs_int, S_IRUGO, get_swpld_data, NULL, MB_HS_INT); +static SENSOR_DEVICE_ATTR(pb_pwr_int, S_IRUGO, get_swpld_data, NULL, PB_PWR_INT); +static SENSOR_DEVICE_ATTR(mb_pwr_int, S_IRUGO, get_swpld_data, NULL, MB_PWR_INT); +static SENSOR_DEVICE_ATTR(fan_int, S_IRUGO, get_swpld_data, NULL, FAN_INT); +static SENSOR_DEVICE_ATTR(pb_hs_mask_int, S_IRUGO, get_swpld_data, NULL, PB_HS_MASK_INT); +static SENSOR_DEVICE_ATTR(mb_hs_mask_int, S_IRUGO, get_swpld_data, NULL, MB_HS_MASK_INT); +static SENSOR_DEVICE_ATTR(pb_pwr1_mask_int, S_IRUGO, get_swpld_data, NULL, PB_PWR1_MASK_INT); +static SENSOR_DEVICE_ATTR(pb_pwr2_mask_int, S_IRUGO, get_swpld_data, NULL, PB_PWR2_MASK_INT); +static SENSOR_DEVICE_ATTR(fan_mask_int, S_IRUGO, get_swpld_data, NULL, FAN_MASK_INT); +static SENSOR_DEVICE_ATTR(qsfp_01to08_int, S_IRUGO, get_swpld_data, NULL, QSFP_01TO08_INT); +static SENSOR_DEVICE_ATTR(qsfp_08to16_int, S_IRUGO, get_swpld_data, NULL, QSFP_08TO16_INT); +static SENSOR_DEVICE_ATTR(qsfp_17to24_int, S_IRUGO, get_swpld_data, NULL, QSFP_17TO24_INT); +static SENSOR_DEVICE_ATTR(qsfp_25to32_int, S_IRUGO, get_swpld_data, NULL, QSFP_25TO32_INT); +static SENSOR_DEVICE_ATTR(qsfp_01to08_abs, S_IRUGO, get_swpld_data, NULL, QSFP_01TO08_ABS); +static SENSOR_DEVICE_ATTR(qsfp_08to16_abs, S_IRUGO, get_swpld_data, NULL, QSFP_08TO16_ABS); +static SENSOR_DEVICE_ATTR(qsfp_17to24_abs, S_IRUGO, get_swpld_data, NULL, QSFP_17TO24_ABS); +static SENSOR_DEVICE_ATTR(qsfp_25to32_abs, S_IRUGO, get_swpld_data, NULL, QSFP_25TO32_ABS); +static SENSOR_DEVICE_ATTR(qsfp_01to08_mask_int, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_01TO08_MASK_INT); +static SENSOR_DEVICE_ATTR(qsfp_08to16_mask_int, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_08TO16_MASK_INT); +static SENSOR_DEVICE_ATTR(qsfp_17to24_mask_int, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_17TO24_MASK_INT); +static SENSOR_DEVICE_ATTR(qsfp_25to32_mask_int, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_25TO32_MASK_INT); +static SENSOR_DEVICE_ATTR(qsfp_01to08_mask_abs, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_01TO08_MASK_ABS); +static SENSOR_DEVICE_ATTR(qsfp_08to16_mask_abs, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_08TO16_MASK_ABS); +static SENSOR_DEVICE_ATTR(qsfp_17to24_mask_abs, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_17TO24_MASK_ABS); +static SENSOR_DEVICE_ATTR(qsfp_25to32_mask_abs, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_25TO32_MASK_ABS); +static SENSOR_DEVICE_ATTR(qsfp01_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP01_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp02_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP02_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp03_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP03_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp04_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP04_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp05_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP05_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp06_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP06_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp07_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP07_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp08_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP08_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp09_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP09_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp10_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP10_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp11_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP11_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp12_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP12_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp13_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP13_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp14_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP14_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp15_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP15_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp16_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP16_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp17_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP17_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp18_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP18_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp19_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP19_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp20_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP20_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp21_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP21_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp22_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP22_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp23_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP23_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp24_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP24_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp25_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP25_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp26_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP26_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp27_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP27_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp28_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP28_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp29_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP29_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp30_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP30_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp31_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP31_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp32_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP32_MOD_INT); + +static struct attribute *ag9032v1_swpld_attrs_controller_interrupt[] = { + &sensor_dev_attr_pb_hs_int.dev_attr.attr, + &sensor_dev_attr_mb_hs_int.dev_attr.attr, + &sensor_dev_attr_pb_pwr_int.dev_attr.attr, + &sensor_dev_attr_mb_pwr_int.dev_attr.attr, + &sensor_dev_attr_fan_int.dev_attr.attr, + &sensor_dev_attr_pb_hs_mask_int.dev_attr.attr, + &sensor_dev_attr_mb_hs_mask_int.dev_attr.attr, + &sensor_dev_attr_pb_pwr1_mask_int.dev_attr.attr, + &sensor_dev_attr_pb_pwr2_mask_int.dev_attr.attr, + &sensor_dev_attr_fan_mask_int.dev_attr.attr, + &sensor_dev_attr_qsfp_01to08_int.dev_attr.attr, + &sensor_dev_attr_qsfp_08to16_int.dev_attr.attr, + &sensor_dev_attr_qsfp_17to24_int.dev_attr.attr, + &sensor_dev_attr_qsfp_25to32_int.dev_attr.attr, + &sensor_dev_attr_qsfp_01to08_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_08to16_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_17to24_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_25to32_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_01to08_mask_int.dev_attr.attr, + &sensor_dev_attr_qsfp_08to16_mask_int.dev_attr.attr, + &sensor_dev_attr_qsfp_17to24_mask_int.dev_attr.attr, + &sensor_dev_attr_qsfp_25to32_mask_int.dev_attr.attr, + &sensor_dev_attr_qsfp_01to08_mask_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_08to16_mask_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_17to24_mask_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_25to32_mask_abs.dev_attr.attr, + &sensor_dev_attr_qsfp01_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp02_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp03_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp04_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp05_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp06_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp07_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp08_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp09_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp10_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp11_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp12_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp13_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp14_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp15_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp16_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp17_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp18_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp19_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp20_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp21_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp22_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp23_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp24_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp25_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp26_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp27_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp28_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp29_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp30_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp31_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp32_mod_int.dev_attr.attr, + NULL, +}; + +static struct attribute_group ag9032v1_swpld_attr_grp_board = { + .attrs = ag9032v1_swpld_attrs_board, +}; +static struct attribute_group ag9032v1_swpld_attr_grp_psu = { + .attrs = ag9032v1_swpld_attrs_psu, +}; +static struct attribute_group ag9032v1_swpld_attr_grp_hot_swap = { + .attrs = ag9032v1_swpld_attrs_hot_swap, +}; +static struct attribute_group ag9032v1_swpld_attr_grp_BCM54616S = { + .attrs = ag9032v1_swpld_attrs_BCM54616S, +}; +static struct attribute_group ag9032v1_swpld_attr_grp_controller_interrupt = { + .attrs = ag9032v1_swpld_attrs_controller_interrupt, +}; + +/* CPLD -- driver */ +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS6); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", BUS6); + return -ENODEV; + } + + pdata[system_cpld].client = i2c_new_dummy(parent, pdata[system_cpld].reg_addr); + if (!pdata[system_cpld].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[system_cpld].reg_addr); + goto error; + } + + kobj_swpld = &pdev->dev.kobj; + kobj_board = kobject_create_and_add("Board", &pdev->dev.kobj); + if (!kobj_board){ + printk(KERN_WARNING "Fail to create directory"); + goto error; + } + + kobj_psu = kobject_create_and_add("PSU", &pdev->dev.kobj); + if (!kobj_psu){ + printk(KERN_WARNING "Fail to create directory"); + goto error; + } + + kobj_hot_swap = kobject_create_and_add("HOT_SWAP", &pdev->dev.kobj); + if (!kobj_hot_swap){ + printk(KERN_WARNING "Fail to create directory"); + goto error; + } + + kobj_controller_interrupt = kobject_create_and_add("Controller_interrupt", &pdev->dev.kobj); + if (!kobj_controller_interrupt){ + printk(KERN_WARNING "Fail to create directory"); + goto error; + } + + kobj_BCM54616S = kobject_create_and_add("BCM54616S", &pdev->dev.kobj); + if (!kobj_BCM54616S){ + printk(KERN_WARNING "Fail to create directory"); + goto error; + } + + ret = sysfs_create_group(kobj_board, &ag9032v1_swpld_attr_grp_board); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + ret = sysfs_create_group(kobj_psu, &ag9032v1_swpld_attr_grp_psu); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + ret = sysfs_create_group(kobj_hot_swap, &ag9032v1_swpld_attr_grp_hot_swap); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + ret = sysfs_create_group(kobj_BCM54616S, &ag9032v1_swpld_attr_grp_BCM54616S); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + ret = sysfs_create_group(kobj_controller_interrupt, &ag9032v1_swpld_attr_grp_controller_interrupt); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + ret = sysfs_create_group(&pdev->dev.kobj, &ag9032v1_cpld_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + return 0; + +error: + kobject_put(kobj_swpld); + kobject_put(kobj_board); + kobject_put(kobj_psu); + kobject_put(kobj_hot_swap); + kobject_put(kobj_controller_interrupt); + kobject_put(kobj_BCM54616S); + i2c_unregister_device(pdata[system_cpld].client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &ag9032v1_cpld_attr_grp); + sysfs_remove_group(kobj_board, &ag9032v1_swpld_attr_grp_board); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + kobject_put(kobj_swpld); + kobject_put(kobj_board); + kobject_put(kobj_psu); + kobject_put(kobj_hot_swap); + kobject_put(kobj_controller_interrupt); + kobject_put(kobj_BCM54616S); + if (pdata[system_cpld].client) { + if (!parent) { + parent = (pdata[system_cpld].client)->adapter; + } + i2c_unregister_device(pdata[system_cpld].client); + } + } + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v1-swpld", + }, +}; + +/*---------------- CPLD - end ------------- */ + +/*---------------- MUX - start ------------- */ + +struct swpld_mux_platform_data { + int parent; + int base_nr; + int reg_addr; + struct i2c_client *cpld; +}; + +struct swpld_mux { + struct i2c_adapter *parent; + struct i2c_adapter **child; + struct swpld_mux_platform_data data; +}; +static struct swpld_mux_platform_data ag9032v1_swpld_mux_platform_data[] = { + { + .parent = BUS3, + .base_nr = BUS3_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS3_MUX_REG ,// the i2c register address which for select mux TEMP(FAN) + }, + { + .parent = BUS4, + .base_nr = BUS4_BASE_NUM , + .cpld = NULL, + .reg_addr = BUS4_MUX_REG , + }, + { + .parent = BUS5, + .base_nr = BUS5_BASE_NUM , + .cpld = NULL, + .reg_addr = BUS5_MUX_REG , + }, +}; + +static struct platform_device ag9032v1_swpld_mux[] = { + { + .name = "delta-ag9032v1-swpld-mux", + .id = 0, + .dev = { + .platform_data = &ag9032v1_swpld_mux_platform_data[0], + .release = device_release, + }, + }, + { + .name = "delta-ag9032v1-swpld-mux", + .id = 1, + .dev = { + .platform_data = &ag9032v1_swpld_mux_platform_data[1], + .release = device_release, + }, + }, + { + .name = "delta-ag9032v1-swpld-mux", + .id = 2, + .dev = { + .platform_data = &ag9032v1_swpld_mux_platform_data[2], + .release = device_release, + }, + }, +}; + +static int cpld_reg_write_byte(struct i2c_client *client, u8 regaddr, u8 val) +{ + union i2c_smbus_data data; + + data.byte = val; + return client->adapter->algo->smbus_xfer(client->adapter, client->addr, + client->flags, + I2C_SMBUS_WRITE, + regaddr, I2C_SMBUS_BYTE_DATA, &data); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int swpld_mux_select(struct i2c_adapter *adap, void *data, u8 chan) +{ + struct swpld_mux *mux = data; + u8 swpld_mux_val=0; + + if ( mux->data.base_nr == BUS3_BASE_NUM ) + { + switch (chan) { + case 0: + swpld_mux_val = TEMP_FAN_VAL; + break; + case 1: + swpld_mux_val = FAN_EEPROM1_VAL; + break; + case 2: + swpld_mux_val = FAN_EEPROM2_VAL; + break; + case 3: + swpld_mux_val = FAN_EEPROM3_VAL; + break; + case 4: + swpld_mux_val = FAN_EEPROM4_VAL; + break; + case 5: + swpld_mux_val = FAN_EEPROM5_VAL; + break; + case 6: + swpld_mux_val = FANIO_CTL_VAL; + break; + case 7: + case 8: + swpld_mux_val = FAN_CTRL_VAL; + break; + } + } + else if ( mux->data.base_nr == BUS4_BASE_NUM ) + { + switch (chan) { + case 0: + swpld_mux_val = PSU1_VAL; + break; + case 1: + swpld_mux_val = PSU2_VAL; + break; + case 2: + swpld_mux_val = HOT_SWAP1_VAL; + break; + case 3: + swpld_mux_val = HOT_SWAP2_VAL; + break; + } + } + else if ( mux->data.base_nr == BUS5_BASE_NUM ){ + if (chan < 9){ + swpld_mux_val = (u8)(chan) + 0x01; + } + else if (8 < chan && chan < 19){ + swpld_mux_val = (u8)(chan - 9) + 0x10; + } + else if (18 < chan && chan < 29){ + swpld_mux_val = (u8)(chan - 19) + 0x20; + } + else if (28 < chan && chan < 39){ + swpld_mux_val = (u8)(chan - 29) + 0x30; + } + else{ + swpld_mux_val = 0x00; + } + } + else + { + swpld_mux_val = 0x00; + } + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld_mux_val & 0xff)); +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int swpld_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct swpld_mux *mux = i2c_mux_priv(muxc); + u8 swpld_mux_val=0; + + if ( mux->data.base_nr == BUS3_BASE_NUM ) + { + switch (chan) { + case 0: + swpld_mux_val = TEMP_FAN_VAL; + break; + case 1: + swpld_mux_val = FAN_EEPROM1_VAL; + break; + case 2: + swpld_mux_val = FAN_EEPROM2_VAL; + break; + case 3: + swpld_mux_val = FAN_EEPROM3_VAL; + break; + case 4: + swpld_mux_val = FAN_EEPROM4_VAL; + break; + case 5: + swpld_mux_val = FAN_EEPROM5_VAL; + break; + case 6: + swpld_mux_val = FANIO_CTL_VAL; + break; + case 7: + case 8: + swpld_mux_val = FAN_CTRL_VAL; + break; + } + } + else if ( mux->data.base_nr == BUS4_BASE_NUM ) + { + switch (chan) { + case 0: + swpld_mux_val = PSU1_VAL; + break; + case 1: + swpld_mux_val = PSU2_VAL; + break; + case 2: + swpld_mux_val = HOT_SWAP1_VAL; + break; + case 3: + swpld_mux_val = HOT_SWAP2_VAL; + break; + } + } + else if ( mux->data.base_nr == BUS5_BASE_NUM ){ + if (chan < 9){ + swpld_mux_val = (u8)(chan) + 0x01; + } + else if (8 < chan && chan < 19){ + swpld_mux_val = (u8)(chan - 9) + 0x10; + } + else if (18 < chan && chan < 29){ + swpld_mux_val = (u8)(chan - 19) + 0x20; + } + else if (28 < chan && chan < 39){ + swpld_mux_val = (u8)(chan - 29) + 0x30; + } + else{ + swpld_mux_val = 0x00; + } + } + else + { + swpld_mux_val = 0x00; + } + + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld_mux_val & 0xff)); +} +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct swpld_mux *mux; + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS3: + dev_num = BUS3_DEV_NUM; + break; + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + case BUS5: + dev_num = BUS5_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + ret = -ENOMEM; + printk(KERN_ERR "Failed to allocate memory for mux\n"); + goto alloc_failed; + } + + mux->parent = parent; + mux->data = *pdata; + mux->child = kzalloc(sizeof(struct i2c_adapter *) * dev_num, GFP_KERNEL); + if (!mux->child) { + ret = -ENOMEM; + printk(KERN_ERR "Failed to allocate memory for device on mux\n"); + goto alloc_failed2; + } + + for (i = 0; i < dev_num; i++) { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + mux->child[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, + nr, i, class, + swpld_mux_select, NULL); + if (!mux->child[i]) { + ret = -ENODEV; + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + platform_set_drvdata(pdev, mux); + return 0; + +add_adapter_failed: + for (; i > 0; i--) + i2c_del_mux_adapter(mux->child[i - 1]); + kfree(mux->child); +alloc_failed2: + kfree(mux); +alloc_failed: + i2c_put_adapter(parent); + + return ret; +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct swpld_mux *mux; + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + printk(KERN_ERR "Failed to allocate memory for mux\n"); + return -ENOMEM; + } + mux->data = *pdata; + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + kfree(mux); + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS3: + dev_num = BUS3_DEV_NUM; + break; + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + case BUS5: + dev_num = BUS5_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + + + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0, + swpld_mux_select, NULL); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = mux; + platform_set_drvdata(pdev, muxc); + + + for (i = 0; i < dev_num; i++) { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + dev_info(&pdev->dev, "%d port mux on %s adapter\n", dev_num, parent->name); + + return 0; + +add_adapter_failed: + i2c_mux_del_adapters(muxc); +alloc_failed: + kfree(mux); + i2c_put_adapter(parent); + + return ret; +} +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + int i; + struct swpld_mux *mux = platform_get_drvdata(pdev); + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + switch (pdata->parent) { + case BUS3: + dev_num = BUS3_DEV_NUM; + break; + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + case BUS5: + dev_num = BUS5_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + for (i = 0; i < dev_num; i++) + i2c_del_mux_adapter(mux->child[i]); + + platform_set_drvdata(pdev, NULL); + i2c_put_adapter(mux->parent); + kfree(mux->child); + kfree(mux); + + return 0; +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + struct i2c_adapter *parent=muxc->parent; + + i2c_mux_del_adapters(muxc); + i2c_put_adapter(parent); + + return 0; +} +#endif + +static struct platform_driver swpld_mux_driver = { + .probe = swpld_mux_probe, + .remove = __exit_p(swpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v1-swpld-mux", + }, +}; +/*---------------- MUX - end ------------- */ + +/*---------------- module initialization ------------- */ +static int __init delta_ag9032v1_platform_init(void) +{ +// struct i2c_client *client; + struct i2c_adapter *adapter; + struct cpld_platform_data *cpld_pdata; + struct swpld_mux_platform_data *swpld_mux_pdata; + int ret,i = 0; + printk("ag9032v1_platform module initialization\n"); + + //Use pca9547 in i2c_mux_pca954x.c + adapter = i2c_get_adapter(BUS1); + //client = i2c_new_device(adapter, &i2c_info_pca9547[0]); + i2c_client_9547 = i2c_new_device(adapter, &i2c_info_pca9547[0]); + + i2c_put_adapter(adapter); + + // set the CPLD prob and remove + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpld driver\n"); + goto error_cpld_driver; + } + // register the mux prob which call the CPLD + ret = platform_driver_register(&swpld_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld mux driver\n"); + goto error_swpld_mux_driver; + } + + // register the i2c devices + ret = platform_driver_register(&i2c_device_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_driver; + } + + // register the CPLD + ret = platform_device_register(&ag9032v1_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpld device\n"); + goto error_ag9032v1_cpld; + } + // link the CPLD and the Mux + cpld_pdata = ag9032v1_cpld.dev.platform_data; + + for (i = 0; i < ARRAY_SIZE(ag9032v1_swpld_mux); i++) + { + swpld_mux_pdata = ag9032v1_swpld_mux[i].dev.platform_data; + swpld_mux_pdata->cpld = cpld_pdata[system_cpld].client; + ret = platform_device_register(&ag9032v1_swpld_mux[i]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld mux %d\n", i); + goto error_ag9032v1_swpld_mux; + } + } + + for (i = 0; i < ARRAY_SIZE(ag9032v1_i2c_device); i++) + { + ret = platform_device_register(&ag9032v1_i2c_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_ag9032v1_i2c_device; + } + } + + if (ret) + goto error_ag9032v1_swpld_mux; + + return 0; + +error_ag9032v1_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag9032v1_i2c_device[i]); + } + i = ARRAY_SIZE(ag9032v1_swpld_mux); +error_ag9032v1_swpld_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag9032v1_swpld_mux[i]); + } + platform_driver_unregister((struct platform_driver *) &ag9032v1_cpld); +error_ag9032v1_cpld: + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + platform_driver_unregister(&swpld_mux_driver); +error_swpld_mux_driver: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +} + +static void __exit delta_ag9032v1_platform_exit(void) +{ + int i = 0; + + for ( i = 0; i < ARRAY_SIZE(ag9032v1_i2c_device); i++ ) { + platform_device_unregister(&ag9032v1_i2c_device[i]); + } + + for (i = 0; i < ARRAY_SIZE(ag9032v1_swpld_mux); i++) { + platform_device_unregister(&ag9032v1_swpld_mux[i]); + } + + platform_device_unregister(&ag9032v1_cpld); + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&cpld_driver); + platform_driver_unregister(&swpld_mux_driver); + + i2c_unregister_device(i2c_client_9547); +} + +module_init(delta_ag9032v1_platform_init); +module_exit(delta_ag9032v1_platform_exit); + +MODULE_DESCRIPTION("DNI ag9032v1 Platform Support"); +MODULE_AUTHOR("Neal Tai "); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_ag9032v1_psu.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_ag9032v1_psu.c new file mode 100644 index 000000000000..7d9350bc55bd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_ag9032v1_psu.c @@ -0,0 +1,550 @@ +/* + * An hwmon driver for delta AG9032v1 PSU + * dps_800ab_16_d.c - Support for DPS-800AB-16 D Power Supply Module + * + * Copyright (C) 2016 Delta Network Technology Corporation + * + * DNI + * + * Based on ym2651y.c + * Based on ad7414.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 +#define SWPLD_REG 0x31 +#define SWPLD_PSU_MUX_REG 0x21 +#define SELECT_PSU1_EEPROM 0x00 +#define SELECT_PSU2_EEPROM 0x20 + +u8 psu_member_data = 0x00; + + +/* Address scanned */ +static const unsigned short normal_i2c[] = { 0x58, I2C_CLIENT_END }; + +/* This is additional data */ +struct dps_800ab_16_d_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; + unsigned long last_updated; /* In jiffies */ + + /* Registers value */ + u8 vout_mode; + u16 in1_input; + u16 in2_input; + u16 curr1_input; + u16 curr2_input; + u16 power1_input; + u16 power2_input; + u16 temp_input[2]; + u8 fan_target; + u16 fan_duty_cycle_input[2]; + u16 fan_speed_input[2]; + u8 mfr_model[16]; + u8 mfr_serial[16]; +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask); +static ssize_t set_fan_duty_cycle_input(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count); +static ssize_t for_linear_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t for_fan_target(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static int dps_800ab_16_d_read_byte(struct i2c_client *client, u8 reg); +static int dps_800ab_16_d_read_word(struct i2c_client *client, u8 reg); +static int dps_800ab_16_d_write_word(struct i2c_client *client, u8 reg, \ + u16 value); +static int dps_800ab_16_d_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len); +static struct dps_800ab_16_d_data *dps_800ab_16_d_update_device( \ + struct device *dev); +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t set_w_member_data(struct device *dev, struct device_attribute \ + *dev_att, const char *buf, size_t count); +static ssize_t for_r_member_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); + +enum dps_800ab_16_d_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_MFR_MODEL, + PSU_MFR_SERIAL, + PSU_SELECT_MEMBER, +}; + +static ssize_t set_w_member_data(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + long data; + int error; + if (attr->index == PSU_SELECT_MEMBER) { + error = kstrtol(buf, 16, &data); + if (error) + return error; + if (SELECT_PSU1_EEPROM == data) { + psu_member_data = SELECT_PSU1_EEPROM; + } else if (SELECT_PSU2_EEPROM == data) { + psu_member_data = SELECT_PSU2_EEPROM; + } else { + return -EINVAL; + } + } + return count; +} + +static ssize_t for_r_member_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + return sprintf(buf, "0x%02X\n", psu_member_data); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle_input(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct i2c_client *client = to_i2c_client(dev); + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + /* Select SWPLD PSU offset */ + + mutex_lock(&data->update_lock); + data->fan_duty_cycle_input[nr] = speed; + dps_800ab_16_d_write_word(client, 0x3B + nr, data->fan_duty_cycle_input[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t for_linear_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->in1_input; + break; + case PSU_I_IN: + value = data->curr1_input; + break; + case PSU_I_OUT: + value = data->curr2_input; + break; + case PSU_P_IN: + value = data->power1_input; + multiplier = 1000*1000; + break; + case PSU_P_OUT: + value = data->power2_input; + multiplier = 1000*1000; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle_input[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed_input[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", \ + (mantissa << exponent) * multiplier) : \ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t for_fan_target(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_target >> shift); +} + +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->in2_input; + + return (exponent > 0) ? sprintf(buf, "%d\n", \ + (mantissa * multiplier) / (1 << exponent)): \ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) + return 0; + + switch (attr->index) { + case PSU_MFR_MODEL: + ptr = data->mfr_model + 1; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial + 1; + break; + default: + return 0; + } + return sprintf(buf, "%s\n", ptr); +} +static int dps_800ab_16_d_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int dps_800ab_16_d_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int dps_800ab_16_d_write_word(struct i2c_client *client, u8 reg, \ + u16 value) +{ + union i2c_smbus_data data; + data.word = value; + return i2c_smbus_xfer(client->adapter, client->addr, + client->flags |= I2C_CLIENT_PEC, + I2C_SMBUS_WRITE, reg, + I2C_SMBUS_WORD_DATA, &data); + +} + +static int dps_800ab_16_d_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, + data); + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; +abort: + return result; + +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct dps_800ab_16_d_data *dps_800ab_16_d_update_device( \ + struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + /* Select SWPLD PSU offset */ + + if (time_after(jiffies, data->last_updated)) { + int i, status; + u8 command; + struct reg_data_byte regs_byte[] = { + {0x20, &data->vout_mode}, + {0x81, &data->fan_target} + }; + struct reg_data_word regs_word[] = { + {0x88, &data->in1_input}, + {0x8b, &data->in2_input}, + {0x89, &data->curr1_input}, + {0x8c, &data->curr2_input}, + {0x96, &data->power2_input}, + {0x97, &data->power1_input}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle_input[0])}, + {0x90, &(data->fan_speed_input[0])}, + }; + + dev_dbg(&client->dev, "start data update\n"); + + /* one milliseconds from now */ + data->last_updated = jiffies + HZ / 1000; + + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = dps_800ab_16_d_read_byte(client, + regs_byte[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + *(regs_byte[i].value) = 0; + } else { + *(regs_byte[i].value) = status; + } + } + + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = dps_800ab_16_d_read_word(client, + regs_word[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + *(regs_word[i].value) = 0; + } else { + *(regs_word[i].value) = status; + } + } + + command = 0x9a; /* PSU mfr_model */ + //data->mfr_model[1] = '\0'; + status = dps_800ab_16_d_read_block(client, command, + data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1); + data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command,status); + data->mfr_model[1] = '\0'; + } + + command = 0x9e; /* PSU mfr_serial */ + //data->mfr_serial[1] = '\0'; + status = dps_800ab_16_d_read_block(client, command, + data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1); + data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command,status); + data->mfr_serial[1] = '\0'; + } + + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; + +} + +/* sysfs attributes for hwmon */ +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, for_linear_data, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, for_vout_data, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, for_linear_data, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, for_linear_data, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, for_linear_data, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, for_linear_data, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(temp1_input, \ + S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_target, \ + S_IRUGO, for_fan_target, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(fan1_set_percentage, S_IWUSR | S_IRUGO, \ + for_linear_data, set_fan_duty_cycle_input, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(fan1_input, \ + S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_mfr_model, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL); +static SENSOR_DEVICE_ATTR(psu_select_member, S_IWUSR | S_IRUGO, \ + for_r_member_data, set_w_member_data, PSU_SELECT_MEMBER); + +static struct attribute *dps_800ab_16_d_attributes[] = { + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_target.dev_attr.attr, + &sensor_dev_attr_fan1_set_percentage.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + &sensor_dev_attr_psu_select_member.dev_attr.attr, + NULL +}; + +static const struct attribute_group dps_800ab_16_d_group = { + .attrs = dps_800ab_16_d_attributes, +}; + +static int dps_800ab_16_d_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct dps_800ab_16_d_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "new chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &dps_800ab_16_d_group); + if (status) + goto exit_sysfs_create_group; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_hwmon_device_register; + } + + return 0; + +exit_hwmon_device_register: + sysfs_remove_group(&client->dev.kobj, &dps_800ab_16_d_group); +exit_sysfs_create_group: + kfree(data); +exit: + return status; +} + +static int dps_800ab_16_d_remove(struct i2c_client *client) +{ + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &dps_800ab_16_d_group); + kfree(data); + + return 0; +} + +enum id_name { + dni_ag9032v1_psu, + dps_800ab_16_d +}; + +static const struct i2c_device_id dps_800ab_16_d_id[] = { + { "dni_ag9032v1_psu", dni_ag9032v1_psu }, + { "dps_800ab_16_d", dps_800ab_16_d }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dps_800ab_16_d_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver dps_800ab_16_d_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "dps_800ab_16_d", + }, + .probe = dps_800ab_16_d_probe, + .remove = dps_800ab_16_d_remove, + .id_table = dps_800ab_16_d_id, + .address_list = normal_i2c, +}; + +static int __init dps_800ab_16_d_init(void) +{ + return i2c_add_driver(&dps_800ab_16_d_driver); +} + +static void __exit dps_800ab_16_d_exit(void) +{ + i2c_del_driver(&dps_800ab_16_d_driver); +} + + +MODULE_AUTHOR("Aries Lin "); +MODULE_DESCRIPTION("DPS_800AB_16_D Driver"); +MODULE_LICENSE("GPL"); + +module_init(dps_800ab_16_d_init); +module_exit(dps_800ab_16_d_exit); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_emc2305.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_emc2305.c new file mode 120000 index 000000000000..e8f7ae6b3f4d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_emc2305.c @@ -0,0 +1 @@ +../../common/modules/dni_emc2305.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/ag9032v1_platform_init.sh b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/ag9032v1_platform_init.sh new file mode 100755 index 000000000000..b199ff349446 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/ag9032v1_platform_init.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +#platform init script for Delta ag9032v1 + +#fan speed monitol start +/usr/share/sonic/device/x86_64-delta_ag9032v1-r0/fancontrol.service /usr/share/sonic/device/x86_64-delta_ag9032v1-r0/fancontrol & + +#set led status +/usr/local/bin/led_status.sh & + +exit 0 + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/led_status.sh b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/led_status.sh new file mode 100755 index 000000000000..825e09aa4cfb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/led_status.sh @@ -0,0 +1,225 @@ +#!/bin/bash + +FAN1_EEPROM="-y 31 0x51 0x0a" +FAN2_EEPROM="-y 32 0x52 0x0a" +FAN3_EEPROM="-y 33 0x53 0x0a" +FAN4_EEPROM="-y 34 0x54 0x0a" +FAN5_EEPROM="-y 35 0x55 0x0a" +LED_CONTROL="/sys/devices/platform/delta-ag9032v1-swpld.0/led_control" +FAN1_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan5_input" +FAN1_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan5_input" +FAN2_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan4_input" +FAN2_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan4_input" +FAN3_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan3_input" +FAN3_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan3_input" +FAN4_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan2_input" +FAN4_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan2_input" +FAN5_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan1_input" +FAN5_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan1_input" + +PSU1_EEPROM="-y 40 0x50 0x00" +PSU2_EEPROM="-y 41 0x50 0x00" +PSU1_FAN_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-4/i2c-40/40-0058/fan1_input" +PSU2_FAN_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-4/i2c-41/41-0058/fan1_input" + +catfaneeprom(){ + fan_eeprom_num=0 + i2cget $FAN1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi + i2cget $FAN2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num_num)) + fi + + i2cget $FAN3_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi + + i2cget $FAN4_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi + + i2cget $FAN5_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi +} + +catfanspeed(){ + fan_rpm_normal_num=0 + fan1_rpm_normal_num=0 + fan1_front_rpm=`cat $FAN1_FRONT_RPM` + fan1_rear_rpm=`cat $FAN1_REAR_RPM` + if [ "${fan1_front_rpm}" -ne "960" ] && [ "${fan1_rear_rpm}" -ne "960" ] && [ "${fan1_front_rpm}" -ne "0" ] && [ "${fan1_rear_rpm}" -ne "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num+1)) + elif [ "${fan1_front_rpm}" -eq "960" ] || [ "${fan1_rear_rpm}" -eq "960" ] || [ "${fan1_front_rpm}" -eq "0" ] || [ "${fan1_rear_rpm}" -eq "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num)) + fi + + fan2_rpm_normal_num=0 + fan2_front_rpm=`cat $FAN2_FRONT_RPM` + fan2_rear_rpm=`cat $FAN2_REAR_RPM` + if [ "${fan2_front_rpm}" -ne "960" ] && [ "${fan2_rear_rpm}" -ne "960" ] && [ "${fan2_front_rpm}" -ne "0" ] && [ "${fan2_rear_rpm}" -ne "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num+1)) + elif [ "${fan2_front_rpm}" -eq "960" ] || [ "${fan2_rear_rpm}" -eq "960" ] || [ "${fan2_front_rpm}" -eq "0" ] || [ "${fan2_rear_rpm}" -eq "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num)) + fi + + fan3_rpm_normal_num=0 + fan3_front_rpm=`cat $FAN3_FRONT_RPM` + fan3_rear_rpm=`cat $FAN3_REAR_RPM` + if [ "${fan3_front_rpm}" -ne "960" ] && [ "${fan3_rear_rpm}" -ne "960" ] && [ "${fan3_front_rpm}" -ne "0" ] && [ "${fan3_rear_rpm}" -ne "0" ]; then + fan3_rpm_normal_num=$((fan3_rpm_normal_num+1)) + elif [ "${fan3_front_rpm}" -eq "960" ] || [ "${fan3_rear_rpm}" -eq "960" ] || [ "${fan3_front_rpm}" -eq "0" ] || [ "${fan3_rear_rpm}" -eq "0" ]; then + fan3_rpm_normal_num=$((fan3_rpm_normal_num)) + fi + + fan4_rpm_normal_num=0 + fan4_front_rpm=`cat $FAN4_FRONT_RPM` + fan4_rear_rpm=`cat $FAN4_REAR_RPM` + if [ "${fan4_front_rpm}" -ne "960" ] && [ "${fan4_rear_rpm}" -ne "960" ] && [ "${fan4_front_rpm}" -ne "0" ] && [ "${fan4_rear_rpm}" -ne "0" ]; then + fan4_rpm_normal_num=$((fan4_rpm_normal_num+1)) + elif [ "${fan4_front_rpm}" -eq "960" ] || [ "${fan4_rear_rpm}" -eq "960" ] || [ "${fan4_front_rpm}" -eq "0" ] || [ "${fan4_rear_rpm}" -eq "0" ]; then + fan4_rpm_normal_num=$((fan4_rpm_normal_num)) + fi + + fan5_rpm_normal_num=0 + fan5_front_rpm=`cat $FAN5_FRONT_RPM` + fan5_rear_rpm=`cat $FAN5_REAR_RPM` + if [ "${fan5_front_rpm}" -ne "960" ] && [ "${fan5_rear_rpm}" -ne "960" ] && [ "${fan5_front_rpm}" -ne "0" ] && [ "${fan5_rear_rpm}" -ne "0" ]; then + fan5_rpm_normal_num=$((fan5_rpm_normal_num+1)) + elif [ "${fan5_front_rpm}" -eq "960" ] || [ "${fan5_rear_rpm}" -eq "960" ] || [ "${fan5_front_rpm}" -eq "0" ] || [ "${fan5_rear_rpm}" -eq "0" ]; then + fan5_rpm_normal_num=$((fan5_rpm_normal_num)) + fi + + fan_rpm_normal_num=$((fan1_rpm_normal_num+fan2_rpm_normal_num+fan3_rpm_normal_num+fan4_rpm_normal_num+fan5_rpm_normal_num)) + +} + +catpsueeprom(){ + psu1_eeprom_num=0 + i2cget $PSU1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu1_eeprom_num=$((psu1_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + psu1_eeprom_num=$((psu1_eeprom_num)) + fi + + psu2_eeprom_num=0 + i2cget $PSU2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu2_eeprom_num=$((psu2_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + psu2_eeprom_num=$((psu2_eeprom_num)) + fi +} + +catpsufanspeed(){ + + psu1_rpm_normal_num=0 + psu1_rpm=`cat $PSU1_FAN_RPM` + + if [ "${psu1_rpm}" -ne "960" ] && [ "${psu1_rpm}" -ne "0" ]; then + psu1_rpm_normal_num=$((psu1_rpm_normal_num+1)) + elif [ "${psu1_rpm}" -eq "960" ] || [ "${psu1_rpm}" -eq "0" ]; then + psu1_rpm_normal_num=$((psu1_rpm_normal_num)) + fi + + psu2_rpm_normal_num=0 + psu2_rpm=`cat $PSU2_FAN_RPM` + + if [ "${psu2_rpm}" -ne "960" ] && [ "${psu2_rpm}" -ne "0" ]; then + psu2_rpm_normal_num=$((psu2_rpm_normal_num+1)) + elif [ "${psu2_rpm}" -eq "960" ] || [ "${psu2_rpm}" -eq "0" ]; then + psu2_rpm_normal_num=$((psu2_rpm_normal_num)) + fi + +} + +setfanled(){ + if [ "${fan_eeprom_num}" -eq "5" ] && [ "${fan_rpm_normal_num}" -eq "5" ]; then + echo "fan_green" > $LED_CONTROL + elif [ "${fan_eeprom_num}" -lt "5" ] || [ "${fan_rpm_normal_num}" -lt "5" ]; then + echo "fan_amber" > $LED_CONTROL + fi +} + +setpsuled(){ + if [ "${psu1_eeprom_num}" -eq "1" ] && [ "${psu1_rpm_normal_num}" -eq "1" ]; then + echo "pwr1_green" > $LED_CONTROL + elif [ "${psu1_eeprom_num}" -eq "0" ] || [ "${psu1_rpm_normal_num}" -eq "0" ]; then + echo "pwr1_amber" > $LED_CONTROL + fi + + if [ "${psu2_eeprom_num}" -eq "1" ] && [ "${psu2_rpm_normal_num}" -eq "1" ]; then + echo "pwr2_green" > $LED_CONTROL + elif [ "${psu2_eeprom_num}" -eq "0" ] || [ "${psu2_rpm_normal_num}" -eq "0" ]; then + echo "pwr2_amber" > $LED_CONTROL + fi +} + +setfantrayled(){ + if [ "${fan1_rpm_normal_num}" -eq "1" ]; then + echo "fan1_green" > $LED_CONTROL + else + echo "fan1_red" > $LED_CONTROL + fi + + if [ "${fan2_rpm_normal_num}" -eq "1" ]; then + echo "fan2_green" > $LED_CONTROL + else + echo "fan2_red" > $LED_CONTROL + fi + + if [ "${fan3_rpm_normal_num}" -eq "1" ]; then + echo "fan3_green" > $LED_CONTROL + else + echo "fan3_red" > $LED_CONTROL + fi + + if [ "${fan4_rpm_normal_num}" -eq "1" ]; then + echo "fan4_green" > $LED_CONTROL + else + echo "fan4_red" > $LED_CONTROL + fi + + if [ "${fan5_rpm_normal_num}" -eq "1" ]; then + echo "fan5_green" > $LED_CONTROL + else + echo "fan5_red" > $LED_CONTROL + fi +} + +platformstatus(){ + + echo "sys_green" > $LED_CONTROL + catfaneeprom + catfanspeed + setfanled + setfantrayled + + catpsueeprom + catpsufanspeed + setpsuled +} + +while true +do + platformstatus + sleep 1 +done + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/cfg/ag9064-modules.conf b/platform/broadcom/sonic-platform-modules-delta/ag9064/cfg/ag9064-modules.conf new file mode 100644 index 000000000000..552b4103ed02 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/cfg/ag9064-modules.conf @@ -0,0 +1,13 @@ +# /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. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus +i2c-mux-gpio +i2c-mux-pca954x diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/Makefile b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/Makefile new file mode 100644 index 000000000000..5642e82fa058 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/Makefile @@ -0,0 +1,5 @@ +obj-m += delta_ag9064_platform.o +obj-m += delta_ag9064_cpld.o +obj-m += delta_ag9064_swpld.o +obj-m += i2c-mei.o +i2c-mei-objs := i2c-mei_io.o i2c-mei_main.o i2c-mei_rw.o \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/client.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/client.h new file mode 100644 index 000000000000..04e1aa39243f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/client.h @@ -0,0 +1,255 @@ +/* + * + * Intel Management Engine Interface (Intel MEI) Linux driver + * Copyright (c) 2003-2012, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + */ + +#ifndef _MEI_CLIENT_H_ +#define _MEI_CLIENT_H_ + +#include +#include +#include +#include + +#include "mei_dev.h" + +/* + * reference counting base function + */ +void mei_me_cl_init(struct mei_me_client *me_cl); +void mei_me_cl_put(struct mei_me_client *me_cl); +struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl); + +void mei_me_cl_add(struct mei_device *dev, struct mei_me_client *me_cl); +void mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl); + +struct mei_me_client *mei_me_cl_by_uuid(struct mei_device *dev, + const uuid_le *uuid); +struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id); +struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev, + const uuid_le *uuid, u8 client_id); +void mei_me_cl_rm_by_uuid(struct mei_device *dev, const uuid_le *uuid); +void mei_me_cl_rm_by_uuid_id(struct mei_device *dev, + const uuid_le *uuid, u8 id); +void mei_me_cl_rm_all(struct mei_device *dev); + +/** + * mei_me_cl_is_active - check whether me client is active in the fw + * + * @me_cl: me client + * + * Return: true if the me client is active in the firmware + */ +static inline bool mei_me_cl_is_active(const struct mei_me_client *me_cl) +{ + return !list_empty_careful(&me_cl->list); +} + +/** + * mei_me_cl_uuid - return me client protocol name (uuid) + * + * @me_cl: me client + * + * Return: me client protocol name + */ +static inline const uuid_le *mei_me_cl_uuid(const struct mei_me_client *me_cl) +{ + return &me_cl->props.protocol_name; +} + +/** + * mei_me_cl_ver - return me client protocol version + * + * @me_cl: me client + * + * Return: me client protocol version + */ +static inline u8 mei_me_cl_ver(const struct mei_me_client *me_cl) +{ + return me_cl->props.protocol_version; +} + +/* + * MEI IO Functions + */ +struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type, + struct file *fp); +void mei_io_cb_free(struct mei_cl_cb *priv_cb); +int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length); + + +/** + * mei_io_list_init - Sets up a queue list. + * + * @list: An instance cl callback structure + */ +static inline void mei_io_list_init(struct mei_cl_cb *list) +{ + INIT_LIST_HEAD(&list->list); +} +void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl); + +/* + * MEI Host Client Functions + */ + +struct mei_cl *mei_cl_allocate(struct mei_device *dev); +void mei_cl_init(struct mei_cl *cl, struct mei_device *dev); + + +int mei_cl_link(struct mei_cl *cl, int id); +int mei_cl_unlink(struct mei_cl *cl); + +struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id); + +struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, + const struct file *fp); +void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp); +struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, + enum mei_cb_file_ops type, struct file *fp); +int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp); + +int mei_cl_flow_ctrl_creds(struct mei_cl *cl); + +int mei_cl_flow_ctrl_reduce(struct mei_cl *cl); +/* + * MEI input output function prototype + */ + +/** + * mei_cl_is_connected - host client is connected + * + * @cl: host client + * + * Return: true if the host client is connected + */ +static inline bool mei_cl_is_connected(struct mei_cl *cl) +{ + return cl->state == MEI_FILE_CONNECTED; +} + +/** + * mei_cl_me_id - me client id + * + * @cl: host client + * + * Return: me client id or 0 if client is not connected + */ +static inline u8 mei_cl_me_id(const struct mei_cl *cl) +{ + return cl->me_cl ? cl->me_cl->client_id : 0; +} + +/** + * mei_cl_mtu - maximal message that client can send and receive + * + * @cl: host client + * + * Return: mtu + */ +static inline size_t mei_cl_mtu(const struct mei_cl *cl) +{ + return cl->me_cl->props.max_msg_length; +} + +/** + * mei_cl_is_fixed_address - check whether the me client uses fixed address + * + * @cl: host client + * + * Return: true if the client is connected and it has fixed me address + */ +static inline bool mei_cl_is_fixed_address(const struct mei_cl *cl) +{ + return cl->me_cl && cl->me_cl->props.fixed_address; +} + +/** + * mei_cl_is_single_recv_buf- check whether the me client + * uses single receiving buffer + * + * @cl: host client + * + * Return: true if single_recv_buf == 1; 0 otherwise + */ +static inline bool mei_cl_is_single_recv_buf(const struct mei_cl *cl) +{ + return cl->me_cl->props.single_recv_buf; +} + +/** + * mei_cl_uuid - client's uuid + * + * @cl: host client + * + * Return: return uuid of connected me client + */ +static inline const uuid_le *mei_cl_uuid(const struct mei_cl *cl) +{ + return mei_me_cl_uuid(cl->me_cl); +} + +/** + * mei_cl_host_addr - client's host address + * + * @cl: host client + * + * Return: 0 for fixed address client, host address for dynamic client + */ +static inline u8 mei_cl_host_addr(const struct mei_cl *cl) +{ + return mei_cl_is_fixed_address(cl) ? 0 : cl->host_client_id; +} + +int mei_cl_disconnect(struct mei_cl *cl); +void mei_cl_set_disconnected(struct mei_cl *cl); +int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb, + struct mei_cl_cb *cmpl_list); +int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl, + struct file *file); +int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb, + struct mei_cl_cb *cmpl_list); +int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp); +int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *hdr, + struct mei_cl_cb *cmpl_list); +int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking); +int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, + struct mei_cl_cb *cmpl_list); + +void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb); + +void mei_host_client_init(struct work_struct *work); + +u8 mei_cl_notify_fop2req(enum mei_cb_file_ops fop); +enum mei_cb_file_ops mei_cl_notify_req2fop(u8 request); +int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request); +int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb, + struct mei_cl_cb *cmpl_list); +int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev); +void mei_cl_notify(struct mei_cl *cl); + +void mei_cl_all_disconnect(struct mei_device *dev); +void mei_cl_all_wakeup(struct mei_device *dev); +void mei_cl_all_write_clear(struct mei_device *dev); + +#define MEI_CL_FMT "cl:host=%02d me=%02d " +#define MEI_CL_PRM(cl) (cl)->host_client_id, mei_cl_me_id(cl) + +#define cl_dbg(dev, cl, format, arg...) \ + dev_dbg((dev)->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg) + +#define cl_err(dev, cl, format, arg...) \ + dev_err((dev)->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg) + +#endif /* _MEI_CLIENT_H_ */ diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_common.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_common.h new file mode 100644 index 000000000000..5be2eb91fedf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_common.h @@ -0,0 +1,567 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IPMI_MAX_INTF (4) +#define DELTA_NETFN 0x38 +#define BMC_BUS_5 0x04 +#define CMD_SETDATA 0x03 +#define CMD_GETDATA 0x02 + +#define CPUPLD_ADDR 0x31 +#define SWPLD1_ADDR 0x35 +#define SWPLD2_ADDR 0x34 +#define SWPLD3_ADDR 0x33 +#define SWPLD4_ADDR 0x32 +#define QSFP_PORT_MUX_REG 0x13 + +#define DEFAULT_NUM 1 +#define BUS9_DEV_NUM 64 +#define BUS9_BASE_NUM 20 + +extern int dni_bmc_cmd(char set_cmd, char *cmd_data, int cmd_data_len); +extern int dni_create_user(void); +extern unsigned char dni_log2 (unsigned char num); + +extern void device_release(struct device *dev); +extern void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data); +extern void dummy_smi_free(struct ipmi_smi_msg *msg); +extern void dummy_recv_free(struct ipmi_recv_msg *msg); + +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 struct ipmi_smi_msg halt_smi_msg = { + .done = dummy_smi_free +}; +static struct ipmi_recv_msg halt_recv_msg = { + .done = dummy_recv_free +}; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, + BUS8, + BUS9, + BUS10, + BUS11, + BUS12, + BUS13, + BUS14, +}; + +static struct cpld_attribute_data { + uint8_t bus; + uint8_t addr; + uint8_t reg; + uint8_t mask; + char note[200]; +}; + + +enum cpld_type { + system_cpld, + swpld1, + swpld2, + swpld3, + swpld4, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +static struct cpld_platform_data ag9064_cpld_platform_data[] = { + [system_cpld] = { + .reg_addr = CPUPLD_ADDR, + }, +}; + +static struct cpld_platform_data ag9064_swpld1_platform_data[] = { + [swpld1] = { + .reg_addr = SWPLD1_ADDR, + }, +}; + +static struct cpld_platform_data ag9064_swpld2_platform_data[] = { + [swpld2] = { + .reg_addr = SWPLD2_ADDR, + }, +}; + +static struct cpld_platform_data ag9064_swpld3_platform_data[] = { + [swpld3] = { + .reg_addr = SWPLD3_ADDR, + }, +}; + +static struct cpld_platform_data ag9064_swpld4_platform_data[] = { + [swpld4] = { + .reg_addr = SWPLD4_ADDR, + }, +}; + +enum cpld_attributes { + CPLD_REG_ADDR, + CPLD_REG_VALUE, + SWPLD1_REG_ADDR, + SWPLD1_REG_VALUE, + SWPLD2_REG_ADDR, + SWPLD2_REG_VALUE, + SWPLD3_REG_ADDR, + SWPLD3_REG_VALUE, + SWPLD4_REG_ADDR, + SWPLD4_REG_VALUE, + //CPLD + CPLD_VER, + CPU_BOARD_VER, + CPU_ID, + MB_ID, + MB_VER, + CPU0_PWR_OK, + PSU_OVER_TEMP, + PWR_RAIL_OVER_TEMP, + CPU_DISOMIC_OVER_TEMP, + DDR_OVER_TEMP, + CPLD_PWR_ON_RST, + CPLD_HARD_RST, + CPLD_RST, + MB_PWR, + MB_RST, + PSU_FAN_INT, + OP_MODULE_INT, +//SWPLD1 + SWPLD1_MAJOR_VER, + SWPLD1_MINOR_VER, + SWPLD1_SCRTCH_REG, + PSU1_PWR_OK, + PSU1_INT, + PSU2_PWR_OK, + PSU2_INT, + SYNCE_INT, + SYNCE_RST, + SYNCE_EEPROM_WP, + PSU1_GREEN_LED, + PSU1_RED_LED, + PSU2_GREEN_LED, + PSU2_RED_LED, + PSU_LED_MODE, +//SWPLD2 + SWPLD2_MAJOR_VER, + SWPLD2_MINOR_VER, + SWPLD2_SCRTCH_REG, + FAN_LED, + SYS_LED, + FAN_MOD1_LED, + FAN_MOD2_LED, + FAN_MOD3_LED, + FAN_MOD4_LED, +//SWPLD3 + SWPLD3_MAJOR_VER, + SWPLD3_MINOR_VER, + SWPLD3_SCRTCH_REG, + SB_VER, + PLATFORM_TYPE, +//SWPLD4 + SWPLD4_MAJOR_VER, + SWPLD4_MINOR_VER, + SWPLD4_SCRTCH_REG, + BMC_RST, + CPLD_LPC_RST, + CPLD_SW_RST, + MB_CPLD_RST, + BCM56970_RST, + CPLD_UPGRADE_RST, + MB_RST_CPLD, + CPU_RST_MB_OOB, + GPIO_PHY_RST, + PSU_FAN_EVENT, + CPU_THERMAL_INT, + FAN_INT, + CPLD_SPI_WP, + RJ45_CONSOLE_SEL, + SYSTEM_INT, + CPLD_MB_RST_DONE, + MB_PWR_OK, + FAN_EEPROM_WP, +}; + +static struct cpld_attribute_data attribute_data[] = { + [CPLD_REG_ADDR] = { + }, + [CPLD_REG_VALUE] = { + }, + [SWPLD1_REG_ADDR] = { + }, + [SWPLD1_REG_VALUE] = { + }, + [SWPLD2_REG_ADDR] = { + }, + [SWPLD2_REG_VALUE] = { + }, + [SWPLD3_REG_ADDR] = { + }, + [SWPLD3_REG_VALUE] = { + }, + [SWPLD4_REG_ADDR] = { + }, + [SWPLD4_REG_VALUE] = { + }, +//CPLD + [CPLD_VER] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x01, .mask = 0xFF, + .note = "CPLD Version, controlled by CPLD editor" + }, + [CPU_BOARD_VER] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x02, .mask = 0xF0, + .note = "“0x0”: proto A1\n“0x1”: proto A2\n“0x2”: PR (Production)" + }, + [CPU_ID] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x02, .mask = 0x0F, + .note = "“0x0”: C2558 ECC\n“0x1”: Rangeley ECC\n“0x2”: BROADWELL-DE ECC" + }, + [MB_ID] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x03, .mask = 0xFF, + .note = "“0x00”: proto A1\n“0x01”: proto A2\n“0x02”: PR (Production)" + }, + [MB_VER] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x04, .mask = 0x0F, + .note = "“0x0”: proto-A\n“0x1”: proto-B" + }, + [CPU0_PWR_OK] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x08, .mask = 1 << 3, + .note = "“1” =Power rail is good\n“0” = Power rail is failed" + }, + [PSU_OVER_TEMP] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x0b, .mask = 1 << 4, + .note = "“1” = Not over temperature\n“0” = Over temperature" + }, + [PWR_RAIL_OVER_TEMP] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x0b, .mask = 1 << 3, + .note = "“1” = Not over temperature\n“0” = Over temperature" + }, + [CPU_DISOMIC_OVER_TEMP] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x0b, .mask = 1 << 1, + .note = "“1” = Not over temperature\n“0” = Over temperature" + }, + [DDR_OVER_TEMP] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x0b, .mask = 1 << 0, + .note = "“1” = Not over temperature\n“0” = Over temperature" + }, + [CPLD_PWR_ON_RST] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x11, .mask = 1 << 4, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [CPLD_HARD_RST] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x11, .mask = 1 << 2, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [CPLD_RST] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x11, .mask = 1 << 0, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [MB_PWR] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x12, .mask = 1 << 2, + .note = "“0” = Power rail is failed\n“1” =Power rail is good" + }, + [MB_RST] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x12, .mask = 1 << 0, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [PSU_FAN_INT] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x15, .mask = 1 << 1, + .note = "“0” = Interrupt occurs\n“1” = Interrupt doesn't occur" + }, + [OP_MODULE_INT] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x15, .mask = 1 << 0, + .note = "“0” = Interrupt occurs\n“1” = Interrupt doesn't occur" + }, +//SWPLD1 + [SWPLD1_MAJOR_VER] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x00, .mask = 0xF0, + .note = "CPLD Major Version, controlled by CPLD editor." + }, + [SWPLD1_MINOR_VER] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x00, .mask = 0x0F, + .note = "CPLD Minor Version, controlled by CPLD editor." + }, + [SWPLD1_SCRTCH_REG] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x01, .mask = 0xFF, + .note = "CPLD read/write test register, to provide a way to test CPLD access." + }, + [PSU1_PWR_OK] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x02, .mask = 1 << 6, + .note = "‘0’ = Power rail is good\n‘1’ = Power rail is failed" + }, + [PSU1_INT] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x02, .mask = 1 << 5, + .note = "‘0’ = Interrupt doesn’t occur\n‘1’ = Interrupt occurs" + }, + [PSU2_PWR_OK] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x02, .mask = 1 << 2, + .note = "‘0’ = Power rail is good\n‘1’ = Power rail is failed" + }, + [PSU2_INT] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x02, .mask = 1 << 1, + .note = "‘0’ = Interrupt doesn’t occur\n‘1’ = Interrupt occurs" + }, + [SYNCE_INT] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x12, .mask = 1 << 7, + .note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [SYNCE_RST] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x12, .mask = 1 << 6, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [SYNCE_EEPROM_WP] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x12, .mask = 1 << 5, + .note = "“1” = enables the lock-down mechanism.\n“0” = overrides the lock-down function enabling blocks to be erased or programmed using software commands." + }, + [PSU1_GREEN_LED] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x13, .mask = 1 << 7, + .note = "“0”: Solid Green – Power Supply 1 is supplied to the switch & operating normally\n“1”: OFF" + }, + [PSU1_RED_LED] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x13, .mask = 1 << 6, + .note = "“0”: Solid Red – Power Supply 1 is supplied to the switch & operating normally\n“1”: OFF" + }, + [PSU2_GREEN_LED] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x13, .mask = 1 << 5, + .note = "“0”: Solid Green – Power Supply 2 is supplied to the switch & operating normally\n“1”: OFF" + }, + [PSU2_RED_LED] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x13, .mask = 1 << 4, + .note = "“0”: Solid Red – Power Supply 1=2 is supplied to the switch & operating normally\n“1”: OFF" + }, + [PSU_LED_MODE] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x13, .mask = 1 << 0, + .note = "“0”: PSU LED can be changed manually\n“1”: PSU LED can’t be changed manually" + }, +//SWPLD2 + [SWPLD2_MAJOR_VER] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x00, .mask =0xF0 , + .note = "CPLD Major Version, controlled by CPLD editor." + }, + [SWPLD2_MINOR_VER] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x00, .mask = 0x0F, + .note = "CPLD Minor Version, controlled by CPLD editor." + }, + [SWPLD2_SCRTCH_REG] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x01, .mask = 0xFF, + .note = "CPLD read/write test register, to provide a way to test CPLD access." + }, + [FAN_LED] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x02, .mask = 0xC0, + .note = "“00’/”11”: OFF\n“01”: Solid Green – FANs are operating normally\n“10”: Solid Amber – FANs are Error" + }, + [SYS_LED] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x02, .mask = 0x30, + .note = "‘00’: Off\n‘01’: Solid Green – Normal operation\n‘10’: Blinking Green – Booting Progress\n‘11’: Solid Red – System Fail" + }, + [FAN_MOD1_LED] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x1b, .mask = 1 << 7, + .note = "‘0’ = Amber\n‘1’ = Green" + }, + [FAN_MOD2_LED] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x1b, .mask = 1 << 6, + .note = "‘0’ = Amber\n‘1’ = Green" + }, + [FAN_MOD3_LED] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x1b, .mask = 1 << 5, + .note = "‘0’ = Amber\n‘1’ = Green" + }, + [FAN_MOD4_LED] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x1b, .mask = 1 << 4, + .note = "‘0’ = Amber\n‘1’ = Green" + }, +//SWPLD3 + [SWPLD3_MAJOR_VER] = { + .bus = BUS0, .addr = SWPLD3_ADDR, + .reg = 0x00, .mask = 0xF0, + .note = "CPLD Major Version, controlled by CPLD editor." + }, + [SWPLD3_MINOR_VER] = { + .bus = BUS0, .addr = SWPLD3_ADDR, + .reg = 0x00, .mask = 0x0F, + .note = "CPLD Minor Version, controlled by CPLD editor." + }, + [SWPLD3_SCRTCH_REG] = { + .bus = BUS0, .addr = SWPLD3_ADDR, + .reg = 0x01, .mask = 0xFF, + .note = "CPLD read/write test register, to provide a way to test CPLD access." + }, + [SB_VER] = { + .bus = BUS0, .addr = SWPLD3_ADDR, + .reg = 0x02, .mask = 0xF0, + .note = "“0x0”: proto-A\n“0x1”: proto-B" + }, + [PLATFORM_TYPE] = { + .bus = BUS0, .addr = SWPLD3_ADDR, + .reg = 0x02, .mask = 0x0F, + .note = "“0x0”: 64X100G_2U\n“0x1”~”0xF” Reserved" + }, +//SWPLD4 + [SWPLD4_MAJOR_VER] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x00, .mask = 0xF0, + .note = "CPLD Major Version, controlled by CPLD editor." + }, + [SWPLD4_MINOR_VER] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x00, .mask = 0x0F, + .note = "CPLD Minor Version, controlled by CPLD editor." + }, + [SWPLD4_SCRTCH_REG] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x01, .mask = 0xFF, + .note = "CPLD read/write test register, to provide a way to test CPLD access." + }, + [BMC_RST] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x02, .mask = 1 << 6, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [CPLD_LPC_RST] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x02, .mask = 1 << 5, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [CPLD_SW_RST] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x02, .mask = 1 << 3, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [MB_CPLD_RST] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x02, .mask = 1 << 2, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [BCM56970_RST] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x02, .mask = 1 << 1, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [CPLD_UPGRADE_RST] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x03, .mask = 1 << 7, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [MB_RST_CPLD] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x03, .mask = 1 << 6, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [CPU_RST_MB_OOB] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x03, .mask = 1 << 5, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [GPIO_PHY_RST] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x03, .mask = 1 << 4, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [PSU_FAN_EVENT] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x04, .mask = 1 << 4, + .note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [CPU_THERMAL_INT] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x04, .mask = 1 << 1, + .note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [FAN_INT] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x04, .mask = 1 << 0, + .note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [CPLD_SPI_WP] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x06, .mask = 1 << 3, + .note = "“0” = SPI write operation is disabled\n“1” = SPI write operation is enabled" + }, + [RJ45_CONSOLE_SEL] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x06, .mask = 1 << 2, + .note = "“0” = Use BCM UART\n“1” = Use CPU UART" + }, + [SYSTEM_INT] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x07, .mask = 1 << 2, + .note = "“0” = Interrupt is asserted\n“1” = Interrupt is deasserted" + }, + [CPLD_MB_RST_DONE] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x07, .mask = 1 << 1, + .note = "“0” = Is done\n“1” = Is not done" + }, + [MB_PWR_OK] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x07, .mask = 1 << 0, + .note = "‘0’ = Power is failed\n‘1’ = Power is good" + }, + [FAN_EEPROM_WP] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x15, .mask = 1 << 2, + .note = "“1” = enables the lock-down mechanism.\n“0” = overrides the lock-down function enabling blocks to be erased or programmed using software commands." + }, +}; \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_cpld.c b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_cpld.c new file mode 100644 index 000000000000..97e1b640010b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_cpld.c @@ -0,0 +1,862 @@ +#include "delta_ag9064_common.h" + +#define QSFP_PRESENCE_1 0x03 +#define QSFP_PRESENCE_2 0x03 +#define QSFP_PRESENCE_3 0x24 +#define QSFP_PRESENCE_4 0x24 +#define QSFP_PRESENCE_5 0x04 +#define QSFP_PRESENCE_6 0x04 +#define QSFP_PRESENCE_7 0x25 +#define QSFP_PRESENCE_8 0x25 + +#define QSFP_LP_MODE_1 0x0c +#define QSFP_LP_MODE_2 0x0c +#define QSFP_LP_MODE_3 0x2a +#define QSFP_LP_MODE_4 0x2a +#define QSFP_LP_MODE_5 0x0d +#define QSFP_LP_MODE_6 0x0d +#define QSFP_LP_MODE_7 0x2b +#define QSFP_LP_MODE_8 0x2b + +#define QSFP_RESET_1 0x06 +#define QSFP_RESET_2 0x06 +#define QSFP_RESET_3 0x26 +#define QSFP_RESET_4 0x26 +#define QSFP_RESET_5 0x07 +#define QSFP_RESET_6 0x07 +#define QSFP_RESET_7 0x27 +#define QSFP_RESET_8 0x27 + +#define QSFP_RESPONSE_1 0x09 +#define QSFP_RESPONSE_2 0x09 +#define QSFP_RESPONSE_3 0x28 +#define QSFP_RESPONSE_4 0x28 +#define QSFP_RESPONSE_5 0x0a +#define QSFP_RESPONSE_6 0x0a +#define QSFP_RESPONSE_7 0x29 +#define QSFP_RESPONSE_8 0x29 + +#define QSFP_INTERRUPT_1 0x0f +#define QSFP_INTERRUPT_2 0x0f +#define QSFP_INTERRUPT_3 0x2c +#define QSFP_INTERRUPT_4 0x2c +#define QSFP_INTERRUPT_5 0x10 +#define QSFP_INTERRUPT_6 0x10 +#define QSFP_INTERRUPT_7 0x2d +#define QSFP_INTERRUPT_8 0x2d + +unsigned char cpupld_reg_addr; +/*---------------- CPLD - start ------------- */ +/* CPLD -- device */ +static struct platform_device ag9064_cpld = { + .name = "delta-ag9064-cpld", + .id = 0, + .dev = { + .platform_data = ag9064_cpld_platform_data, + .release = device_release + }, +}; + +static ssize_t get_present(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u64 data = 0; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + + set_cmd = CMD_GETDATA; + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_PRESENCE_1; + cmd_data[3] = 1; + cmd_data_len = sizeof(cmd_data); + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data = (u64)(ret & 0xff); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_PRESENCE_2; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 8; + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_PRESENCE_3; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 16; + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_PRESENCE_4; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 24; + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_PRESENCE_5; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 32; + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_PRESENCE_6; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 40; + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_PRESENCE_7; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 48; + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_PRESENCE_8; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 56; + + return sprintf(buf, "0x%016llx\n", data); +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u64 data = 0; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + + set_cmd = CMD_GETDATA; + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_LP_MODE_1; + cmd_data[3] = 1; + cmd_data_len = sizeof(cmd_data); + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data = (u64)(ret & 0xff); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_LP_MODE_2; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 8; + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_LP_MODE_3; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 16; + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_LP_MODE_4; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 24; + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_LP_MODE_5; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 32; + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_LP_MODE_6; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 40; + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_LP_MODE_7; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 48; + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_LP_MODE_8; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 56; + + return sprintf(buf, "0x%016llx\n", data); +} + +static ssize_t get_reset(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u64 data = 0; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + + set_cmd = CMD_GETDATA; + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESET_1; + cmd_data[3] = 1; + cmd_data_len = sizeof(cmd_data); + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data = (u64)(ret & 0xff); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESET_2; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 8; + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESET_3; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 16; + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESET_4; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 24; + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESET_5; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 32; + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESET_6; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 40; + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESET_7; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 48; + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESET_8; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 56; + + return sprintf(buf, "0x%016llx\n", data); +} + +static ssize_t get_response(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u64 data = 0; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + + set_cmd = CMD_GETDATA; + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESPONSE_1; + cmd_data[3] = 1; + cmd_data_len = sizeof(cmd_data); + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data = (u64)(ret & 0xff); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESPONSE_2; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 8; + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESPONSE_3; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 16; + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESPONSE_4; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 24; + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESPONSE_5; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 32; + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESPONSE_6; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 40; + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESPONSE_7; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 48; + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESPONSE_8; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 56; + + return sprintf(buf, "0x%016llx\n", data); +} + +static ssize_t get_interrupt(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u64 data = 0; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + + set_cmd = CMD_GETDATA; + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_INTERRUPT_1; + cmd_data[3] = 1; + cmd_data_len = sizeof(cmd_data); + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data = (u64)(ret & 0xff); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_INTERRUPT_2; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 8; + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_INTERRUPT_3; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 16; + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_INTERRUPT_4; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 24; + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_INTERRUPT_5; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 32; + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_INTERRUPT_6; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 40; + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_INTERRUPT_7; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 48; + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_INTERRUPT_8; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 56; + + return sprintf(buf, "0x%016llx\n", data); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long long set_data; + int err; + + err = kstrtoull(buf, 16, &set_data); + if (err){ + return err; + } + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + + set_cmd = CMD_SETDATA; + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_LP_MODE_1; + cmd_data[3] = (set_data & 0xff); + cmd_data_len = sizeof(cmd_data); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_LP_MODE_2; + cmd_data[3] = ((set_data >> 8 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_LP_MODE_3; + cmd_data[3] = ((set_data >> 16 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_LP_MODE_4; + cmd_data[3] = ((set_data >> 24 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_LP_MODE_5; + cmd_data[3] = ((set_data >> 32 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_LP_MODE_6; + cmd_data[3] = ((set_data >> 40 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_LP_MODE_7; + cmd_data[3] = ((set_data >> 48 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_LP_MODE_8; + cmd_data[3] = ((set_data >> 56 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + return count; +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long long set_data; + int err; + + err = kstrtoull(buf, 16, &set_data); + if (err){ + return err; + } + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + + set_cmd = CMD_SETDATA; + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESET_1; + cmd_data[3] = (set_data & 0xff); + cmd_data_len = sizeof(cmd_data); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESET_2; + cmd_data[3] = ((set_data >> 8 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESET_3; + cmd_data[3] = ((set_data >> 16 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESET_4; + cmd_data[3] = ((set_data >> 24 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESET_5; + cmd_data[3] = ((set_data >> 32 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESET_6; + cmd_data[3] = ((set_data >> 40 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESET_7; + cmd_data[3] = ((set_data >> 48 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESET_8; + cmd_data[3] = ((set_data >> 56 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + return count; +} + +static ssize_t set_response(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long long set_data; + int err; + + err = kstrtoull(buf, 16, &set_data); + if (err){ + return err; + } + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + + set_cmd = CMD_SETDATA; + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESPONSE_1; + cmd_data[3] = (set_data & 0xff); + cmd_data_len = sizeof(cmd_data); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESPONSE_2; + cmd_data[3] = ((set_data >> 8 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESPONSE_3; + cmd_data[3] = ((set_data >> 16 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESPONSE_4; + cmd_data[3] = ((set_data >> 24 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESPONSE_5; + cmd_data[3] = ((set_data >> 32 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESPONSE_6; + cmd_data[3] = ((set_data >> 40 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESPONSE_7; + cmd_data[3] = ((set_data >> 48 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESPONSE_8; + cmd_data[3] = ((set_data >> 56 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + return count; +} + +static ssize_t get_cpld_reg(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + int ret; + int mask; + int value; + char note[200]; + unsigned char reg; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cpld_platform_data *pdata = dev->platform_data; + + switch (attr->index) { + case CPLD_REG_ADDR: + return sprintf(buf, "0x%02x\n", cpupld_reg_addr); + case CPLD_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, cpupld_reg_addr); + return sprintf(buf, "0x%02x\n", ret); + case CPLD_VER ... OP_MODULE_INT: + reg = attribute_data[attr->index].reg; + mask = attribute_data[attr->index].mask; + value = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + sprintf(note, "\n%s\n",attribute_data[attr->index].note); + value = (value & mask); + break; + default: + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0xFF: + return sprintf(buf, "0x%02x%s", value, note); + case 0x0F: + return sprintf(buf, "0x%01x%s", value, note); + case 0xF0: + value = value >> 4; + return sprintf(buf, "0x%01x%s", value, note); + default : + value = value >> dni_log2(mask); + return sprintf(buf, "%d%s", value, note); + } +} + +static ssize_t set_cpld_reg(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + int err; + int value; + int set_data; + unsigned long set_data_ul; + unsigned char reg; + unsigned char mask; + unsigned char mask_out; + + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 0, &set_data_ul); + if (err){ + return err; + } + + set_data = (int)set_data_ul; + if (set_data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + switch (attr->index) { + case CPLD_REG_ADDR: + cpupld_reg_addr = set_data; + return count; + case CPLD_REG_VALUE: + i2c_smbus_write_byte_data(pdata[system_cpld].client, cpupld_reg_addr, set_data); + return count; + case CPLD_VER ... OP_MODULE_INT: + reg = attribute_data[attr->index].reg; + mask = attribute_data[attr->index].mask; + value = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + mask_out = value & ~(mask); + break; + default: + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0xFF: + set_data = mask_out | (set_data & mask); + break; + case 0x0F: + set_data = mask_out | (set_data & mask); + break; + case 0xF0: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + default : + set_data = mask_out | (set_data << dni_log2(mask) ); + } + + i2c_smbus_write_byte_data(pdata[system_cpld].client, reg, set_data); + return count; +} + +static DEVICE_ATTR(qsfp_present, S_IRUGO, get_present, NULL); +static DEVICE_ATTR(qsfp_lpmode, S_IWUSR | S_IRUGO, get_lpmode, set_lpmode); +static DEVICE_ATTR(qsfp_reset, S_IWUSR | S_IRUGO, get_reset, set_reset); +static DEVICE_ATTR(qsfp_modsel, S_IWUSR | S_IRUGO, get_response, set_response); +static DEVICE_ATTR(qsfp_interrupt, S_IRUGO, get_interrupt, NULL); + +static SENSOR_DEVICE_ATTR(cpld_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPLD_REG_ADDR); +static SENSOR_DEVICE_ATTR(cpld_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPLD_REG_VALUE); +static SENSOR_DEVICE_ATTR(cpld_ver, S_IRUGO, get_cpld_reg, NULL, CPLD_VER); +static SENSOR_DEVICE_ATTR(cpu_board_ver, S_IRUGO, get_cpld_reg, NULL, CPU_BOARD_VER); +static SENSOR_DEVICE_ATTR(cpu_id, S_IRUGO, get_cpld_reg, NULL, CPU_ID); +static SENSOR_DEVICE_ATTR(mb_id, S_IRUGO, get_cpld_reg, NULL, MB_ID); +static SENSOR_DEVICE_ATTR(mb_ver, S_IRUGO, get_cpld_reg, NULL, MB_VER); +static SENSOR_DEVICE_ATTR(cpu0_pwr_ok, S_IRUGO, get_cpld_reg, NULL, CPU0_PWR_OK); +static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, get_cpld_reg, NULL, PSU_OVER_TEMP); +static SENSOR_DEVICE_ATTR(pwr_rail_over_temp, S_IRUGO, get_cpld_reg, NULL, PWR_RAIL_OVER_TEMP); +static SENSOR_DEVICE_ATTR(cpu_disomic_over_temp, S_IRUGO, get_cpld_reg, NULL, CPU_DISOMIC_OVER_TEMP); +static SENSOR_DEVICE_ATTR(ddr_over_temp, S_IRUGO, get_cpld_reg, NULL, DDR_OVER_TEMP); +static SENSOR_DEVICE_ATTR(cpld_pwr_on_rst, S_IRUGO, get_cpld_reg, NULL, CPLD_PWR_ON_RST); +static SENSOR_DEVICE_ATTR(cpld_hard_rst, S_IRUGO, get_cpld_reg, NULL, CPLD_HARD_RST); +static SENSOR_DEVICE_ATTR(cpld_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPLD_RST); +static SENSOR_DEVICE_ATTR(mb_pwr, S_IRUGO, get_cpld_reg, NULL, MB_PWR); +static SENSOR_DEVICE_ATTR(mb_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, MB_RST); +static SENSOR_DEVICE_ATTR(psu_fan_int, S_IRUGO, get_cpld_reg, NULL, PSU_FAN_INT); +static SENSOR_DEVICE_ATTR(op_module_int, S_IRUGO, get_cpld_reg, NULL, OP_MODULE_INT); + +static struct attribute *ag9064_cpld_attrs[] = { + &dev_attr_qsfp_present.attr, + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_modsel.attr, + &dev_attr_qsfp_interrupt.attr, + &sensor_dev_attr_cpld_reg_value.dev_attr.attr, + &sensor_dev_attr_cpld_reg_addr.dev_attr.attr, + &sensor_dev_attr_cpld_ver.dev_attr.attr, + &sensor_dev_attr_cpu_board_ver.dev_attr.attr, + &sensor_dev_attr_cpu_id.dev_attr.attr, + &sensor_dev_attr_mb_id.dev_attr.attr, + &sensor_dev_attr_mb_ver.dev_attr.attr, + &sensor_dev_attr_cpu0_pwr_ok.dev_attr.attr, + &sensor_dev_attr_psu_over_temp.dev_attr.attr, + &sensor_dev_attr_pwr_rail_over_temp.dev_attr.attr, + &sensor_dev_attr_cpu_disomic_over_temp.dev_attr.attr, + &sensor_dev_attr_ddr_over_temp.dev_attr.attr, + &sensor_dev_attr_cpld_pwr_on_rst.dev_attr.attr, + &sensor_dev_attr_cpld_hard_rst.dev_attr.attr, + &sensor_dev_attr_cpld_rst.dev_attr.attr, + &sensor_dev_attr_mb_pwr.dev_attr.attr, + &sensor_dev_attr_mb_rst.dev_attr.attr, + &sensor_dev_attr_psu_fan_int.dev_attr.attr, + &sensor_dev_attr_op_module_int.dev_attr.attr, + NULL, +}; + +static struct attribute_group ag9064_cpld_attr_grp = { + .attrs = ag9064_cpld_attrs, +}; + +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS7); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n",BUS7); + return -ENODEV; + } + + pdata[system_cpld].client = i2c_new_dummy(parent, pdata[system_cpld].reg_addr); + if (!pdata[system_cpld].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[system_cpld].reg_addr); + goto error; + } + + ret = sysfs_create_group(&pdev->dev.kobj, &ag9064_cpld_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + return 0; + +error: + i2c_unregister_device(pdata[system_cpld].client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &ag9064_cpld_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[system_cpld].client) { + if (!parent) { + parent = (pdata[system_cpld].client)->adapter; + } + i2c_unregister_device(pdata[system_cpld].client); + } + } + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-cpld", + }, +}; + +/*---------------- CPLD - end ------------- */ + +/*---------------- module initialization ------------- */ +static int __init delta_ag9064_cpupld_init(void) +{ + int ret; + printk(KERN_WARNING "ag9064_platform_cpupld module initialization\n"); + + ret = dni_create_user(); + if (ret != 0){ + printk(KERN_WARNING "Fail to create IPMI user\n"); + } + + // set the CPUPLD prob and remove + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpupld driver\n"); + goto error_cpupld_driver; + } + + // register the CPUPLD + ret = platform_device_register(&ag9064_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpupld device\n"); + goto error_ag9064_cpupld; + } + return 0; + +error_ag9064_cpupld: + platform_driver_unregister(&cpld_driver); +error_cpupld_driver: + return ret; +} + +static void __exit delta_ag9064_cpupld_exit(void) +{ + platform_device_unregister(&ag9064_cpld); + platform_driver_unregister(&cpld_driver); +} +module_init(delta_ag9064_cpupld_init); +module_exit(delta_ag9064_cpupld_exit); + +MODULE_DESCRIPTION("DNI ag9064 CPLD Platform Support"); +MODULE_AUTHOR("Stanley Chi "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_platform.c b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_platform.c new file mode 100644 index 000000000000..099d7ea987da --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_platform.c @@ -0,0 +1,1178 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "delta_ag9064_common.h" + +#define SFF8436_INFO(data) \ + .type = "sff8436", .addr = 0x50, .platform_data = (data) + +#define SFF_8346_PORT(eedata) \ + .byte_len = 256, .page_size = 1, .flags = SFF_8436_FLAG_READONLY + +#define ag9064_i2c_device_num(NUM){ \ + .name = "delta-ag9064-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &ag9064_i2c_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +struct i2c_client * i2c_client_9548; + + +/* pca9548 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode[] = +{ + { + .adap_id = 7, + .deselect_on_exit = 1, + }, + { + .adap_id = 8, + .deselect_on_exit = 1, + }, + { + .adap_id = 9, + .deselect_on_exit = 1, + }, + { + .adap_id = 10, + .deselect_on_exit = 1, + }, + { + .adap_id = 11, + .deselect_on_exit = 1, + }, + { + .adap_id = 12, + .deselect_on_exit = 1, + }, + { + .adap_id = 13, + .deselect_on_exit = 1, + }, + { + .adap_id = 14, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_data pca954x_data = +{ + .modes = pca954x_mode, + .num_modes = ARRAY_SIZE(pca954x_mode), +}; + +static struct i2c_board_info __initdata i2c_info_pca9548[] = +{ + { + I2C_BOARD_INFO("pca9548", 0x70), + .platform_data = &pca954x_data, + }, +}; + +static struct sff_8436_platform_data sff_8436_port[] = { + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, +}; + +void device_release(struct device *dev) +{ + return; +} +EXPORT_SYMBOL(device_release); +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; +} +EXPORT_SYMBOL(msg_handler); +void dummy_smi_free(struct ipmi_smi_msg *msg) +{ + atomic_dec(&dummy_count); +} +EXPORT_SYMBOL(dummy_smi_free); +void dummy_recv_free(struct ipmi_recv_msg *msg) +{ + atomic_dec(&dummy_count); +} +EXPORT_SYMBOL(dummy_recv_free); +unsigned char dni_log2 (unsigned char num){ + unsigned char num_log2 = 0; + while(num > 0){ + num = num >> 1; + num_log2 += 1; + } + return num_log2 -1; +} +EXPORT_SYMBOL(dni_log2); + +/*---------------- IPMI - start ------------- */ + +int dni_create_user(void) +{ + int rv, i; + + for (i=0,rv=1; idev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + return 0; + +} + +static int __exit i2c_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + if (pdata->client) { + parent = (pdata->client)->adapter; + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + } + + return 0; +} +static struct platform_driver i2c_device_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-i2c-device", + } +}; + +/*---------------- I2C driver - end ------------- */ + +/*---------------- MUX - start ------------- */ + +struct swpld_mux_platform_data { + int parent; + int base_nr; +// struct i2c_client *cpld; +}; + +struct swpld_mux { + struct i2c_adapter *parent; + struct i2c_adapter **child; + struct swpld_mux_platform_data data; +}; + +static struct swpld_mux_platform_data ag9064_swpld_mux_platform_data[] = { + { + .parent = BUS9, + .base_nr = BUS9_BASE_NUM, +// .cpld = NULL, + }, +}; + +static struct platform_device ag9064_swpld_mux[] = +{ + { + .name = "delta-ag9064-swpld-mux", + .id = 0, + .dev = { + .platform_data = &ag9064_swpld_mux_platform_data[0], + .release = device_release, + }, + }, +}; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int swpld_mux_select(struct i2c_adapter *adap, void *data, u8 chan) +{ + uint8_t cmd_data[4]={0}; + struct swpld_mux *mux = data; + uint8_t set_cmd; + int cmd_data_len; + + if ( mux->data.base_nr == BUS9_BASE_NUM ) + { + set_cmd = CMD_SETDATA; + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_PORT_MUX_REG; + cmd_data[3] = chan + 1; + cmd_data_len = sizeof(cmd_data); + return dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + } + else + { + printk(KERN_ERR "Swpld mux QSFP select port error\n"); + return 0; + } +} +#else +static int swpld_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + uint8_t cmd_data[4]={0}; + struct swpld_mux *mux = i2c_mux_priv(muxc); + uint8_t set_cmd; + int cmd_data_len; + + if ( mux->data.base_nr == BUS9_BASE_NUM ) + { + set_cmd = CMD_SETDATA; + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_PORT_MUX_REG; + cmd_data[3] = chan + 1; + cmd_data_len = sizeof(cmd_data); + return dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + } + else + { + printk(KERN_ERR "Swpld mux QSFP select port error\n"); + return 0; + } + +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct swpld_mux *mux; + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS9: + dev_num = BUS9_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + ret = -ENOMEM; + printk(KERN_ERR "Failed to allocate memory for mux\n"); + goto alloc_failed; + } + + mux->parent = parent; + mux->data = *pdata; + mux->child = kzalloc(sizeof(struct i2c_adapter *) * dev_num, GFP_KERNEL); + if (!mux->child) { + ret = -ENOMEM; + printk(KERN_ERR "Failed to allocate memory for device on mux\n"); + goto alloc_failed2; + } + + for (i = 0; i < dev_num; i++) + { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + mux->child[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, + nr, i, class, + swpld_mux_select, NULL); + if (!mux->child[i]) + { + ret = -ENODEV; + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + platform_set_drvdata(pdev, mux); + return 0; + +add_adapter_failed: + for (; i > 0; i--) + i2c_del_mux_adapter(mux->child[i - 1]); + kfree(mux->child); +alloc_failed2: + kfree(mux); +alloc_failed: + i2c_put_adapter(parent); + + return ret; +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct swpld_mux *mux; + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + printk(KERN_ERR "Failed to allocate memory for mux\n"); + return -ENOMEM; + } + mux->data = *pdata; + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + kfree(mux); + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS9: + dev_num = BUS9_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0,swpld_mux_select, NULL); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = mux; + platform_set_drvdata(pdev, muxc); + + for (i = 0; i < dev_num; i++) + { + int nr = pdata->base_nr + i; + unsigned int class = 0; + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + dev_info(&pdev->dev, "%d port mux on %s adapter\n", dev_num, parent->name); + return 0; + +add_adapter_failed: + i2c_mux_del_adapters(muxc); +alloc_failed2: + kfree(mux); +alloc_failed: + i2c_put_adapter(parent); + + return ret; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + int i; + struct swpld_mux *mux = platform_get_drvdata(pdev); + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + switch (pdata->parent) { + case BUS9: + dev_num = BUS9_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + for (i = 0; i < dev_num; i++) + i2c_del_mux_adapter(mux->child[i]); + + platform_set_drvdata(pdev, NULL); + i2c_put_adapter(mux->parent); + kfree(mux->child); + kfree(mux); + + return 0; +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + struct i2c_adapter *parent=muxc->parent; + + i2c_mux_del_adapters(muxc); + i2c_put_adapter(parent); + + return 0; +} +#endif + +static struct platform_driver swpld_mux_driver = { + .probe = swpld_mux_probe, + .remove = __exit_p(swpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-swpld-mux", + }, +}; + +/*---------------- MUX - end ------------- */ + +/*---------------- module initialization ------------- */ + +static int __init delta_ag9064_platform_init(void) +{ +// struct i2c_client *client; + struct i2c_adapter *adapter; + struct swpld_mux_platform_data *swpld_pdata; +// struct cpld_platform_data * cpld_pdata; + int ret,i = 0; + + printk("ag9064_platform module initialization\n"); + + adapter = i2c_get_adapter(BUS2); + i2c_client_9548 = i2c_new_device(adapter, &i2c_info_pca9548[0]); + i2c_put_adapter(adapter); + + ret = dni_create_user(); + if (ret != 0){ + printk(KERN_WARNING "Fail to create IPMI user\n"); + } + + // register the mux prob which call the SWPLD + ret = platform_driver_register(&swpld_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld mux driver\n"); + goto error_swpld_mux_driver; + } + + // register the i2c devices + ret = platform_driver_register(&i2c_device_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_driver; + } + + swpld_pdata = ag9064_swpld_mux[0].dev.platform_data; + ret = platform_device_register(&ag9064_swpld_mux[0]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld mux\n"); + goto error_ag9064_swpld_mux; + } + + for (i = 0; i < ARRAY_SIZE(ag9064_i2c_device); i++) + { + ret = platform_device_register(&ag9064_i2c_device[i]); + if (ret) + { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_ag9064_i2c_device; + } + } + if (ret) + goto error_ag9064_swpld_mux; + + return 0; + +error_ag9064_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag9064_i2c_device[i]); + } + i = ARRAY_SIZE(ag9064_swpld_mux); +error_ag9064_swpld_mux: + platform_device_unregister(&ag9064_swpld_mux[0]); + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + platform_driver_unregister(&swpld_mux_driver); +error_swpld_mux_driver: + return ret; +} + +static void __exit delta_ag9064_platform_exit(void) +{ + int i = 0; + + for ( i = 0; i < ARRAY_SIZE(ag9064_i2c_device); i++ ) { + platform_device_unregister(&ag9064_i2c_device[i]); + } + + platform_device_unregister(&ag9064_swpld_mux[0]); + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&swpld_mux_driver); + i2c_unregister_device(i2c_client_9548); +} + +module_init(delta_ag9064_platform_init); +module_exit(delta_ag9064_platform_exit); + +MODULE_DESCRIPTION("DELTA ag9064 Platform Support"); +MODULE_AUTHOR("Johnson Lu "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_swpld.c b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_swpld.c new file mode 100644 index 000000000000..cab54a43bb07 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_swpld.c @@ -0,0 +1,623 @@ +#include "delta_ag9064_common.h" + +unsigned char swpld1_reg_addr; +unsigned char swpld2_reg_addr; +unsigned char swpld3_reg_addr; +unsigned char swpld4_reg_addr; + +/*---------------- CPLD - start ------------- */ +/* SWPLD1 -- device */ +static struct platform_device swpld1_device = { + .name = "delta-ag9064-swpld1", + .id = 0, + .dev = { + .platform_data = ag9064_swpld1_platform_data, + .release = device_release + }, +}; + +static struct platform_device swpld2_device = { + .name = "delta-ag9064-swpld2", + .id = 0, + .dev = { + .platform_data = ag9064_swpld2_platform_data, + .release = device_release + }, +}; +static struct platform_device swpld3_device = { + .name = "delta-ag9064-swpld3", + .id = 0, + .dev = { + .platform_data = ag9064_swpld3_platform_data, + .release = device_release + }, +}; +static struct platform_device swpld4_device = { + .name = "delta-ag9064-swpld4", + .id = 0, + .dev = { + .platform_data = ag9064_swpld4_platform_data, + .release = device_release + }, +}; + +static ssize_t get_swpld_reg(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + int ret; + int mask; + int value; + int cmd_data_len; + char note[200]; + uint8_t cmd_data[4]={0}; + uint8_t get_cmd; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + + cmd_data_len = sizeof(cmd_data); + get_cmd = CMD_GETDATA; + cmd_data[0] = BMC_BUS_5; + cmd_data[3] = 1; + mask = attribute_data[attr->index].mask; + sprintf(note, "\n%s\n",attribute_data[attr->index].note); + + if (attr->index <= SWPLD4_REG_VALUE){ + switch (attr->index) { + case SWPLD1_REG_ADDR: + return sprintf(buf, "0x%02x\n", swpld1_reg_addr); + case SWPLD2_REG_ADDR: + return sprintf(buf, "0x%02x\n", swpld2_reg_addr); + case SWPLD3_REG_ADDR: + return sprintf(buf, "0x%02x\n", swpld3_reg_addr); + case SWPLD4_REG_ADDR: + return sprintf(buf, "0x%02x\n", swpld4_reg_addr); + case SWPLD1_REG_VALUE: + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = swpld1_reg_addr; + break; + case SWPLD2_REG_VALUE: + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = swpld2_reg_addr; + break; + case SWPLD3_REG_VALUE: + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = swpld3_reg_addr; + break; + case SWPLD4_REG_VALUE: + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = swpld4_reg_addr; + break; + default: + return sprintf(buf, "%d not found", attr->index); + } + ret = dni_bmc_cmd(get_cmd, cmd_data, cmd_data_len); + ret = ret & 0xff; + return sprintf(buf, "0x%02x\n", ret); + }else{ + + switch (attr->index) { + case SWPLD1_MAJOR_VER ... PSU_LED_MODE : + cmd_data[1] = SWPLD1_ADDR; + break; + case SWPLD2_MAJOR_VER ... FAN_MOD4_LED : + cmd_data[1] = SWPLD2_ADDR; + break; + case SWPLD3_MAJOR_VER ... PLATFORM_TYPE : + cmd_data[1] = SWPLD3_ADDR; + break; + case SWPLD4_MAJOR_VER ... FAN_EEPROM_WP : + cmd_data[1] = SWPLD4_ADDR; + break; + default: + return sprintf(buf, "%d not found", attr->index); + } + cmd_data[2] = attribute_data[attr->index].reg; + value = dni_bmc_cmd(get_cmd, cmd_data, cmd_data_len); + value = value & mask; + switch (mask) { + case 0xFF: + return sprintf(buf, "0x%02x%s", value, note); + case 0x0F: + return sprintf(buf, "0x%01x%s", value, note); + case 0xF0: + value = value >> 4; + return sprintf(buf, "0x%01x%s", value, note); + case 0xC0: + value = value >> 6; + return sprintf(buf, "0x%01x%s", value, note); + case 0x30: + value = value >> 4; + return sprintf(buf, "0x%01x%s", value, note); + default : + value = value >> dni_log2(mask); + return sprintf(buf, "%d%s", value, note); + } + } +} + +static ssize_t set_swpld_reg(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + int err; + int value; + int set_data; + int cmd_data_len; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + uint8_t get_cmd; + unsigned long set_data_ul; + unsigned char mask; + unsigned char mask_out; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + + cmd_data_len = sizeof(cmd_data); + set_cmd = CMD_SETDATA; + get_cmd = CMD_GETDATA; + + err = kstrtoul(buf, 0, &set_data_ul); + if (err){ + return err; + } + + if (set_data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + set_data = (int)set_data_ul; + if (attr->index <= SWPLD4_REG_VALUE){ + cmd_data[0] = BMC_BUS_5; + cmd_data[3] = set_data; + switch (attr->index) { + //reg_addr + case SWPLD1_REG_ADDR: + swpld1_reg_addr = set_data; + return count; + case SWPLD2_REG_ADDR: + swpld2_reg_addr = set_data; + return count; + case SWPLD3_REG_ADDR: + swpld3_reg_addr = set_data; + return count; + case SWPLD4_REG_ADDR: + swpld4_reg_addr = set_data; + return count; + //reg_value + case SWPLD1_REG_VALUE: + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = swpld1_reg_addr; + break; + case SWPLD2_REG_VALUE: + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = swpld2_reg_addr; + break; + case SWPLD3_REG_VALUE: + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = swpld3_reg_addr; + break; + case SWPLD4_REG_VALUE: + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = swpld4_reg_addr; + break; + default : + return sprintf(buf, "%d not found", attr->index); + } + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + return count; + } + else{ + cmd_data[0] = BMC_BUS_5; + cmd_data[2] = attribute_data[attr->index].reg; + cmd_data[3] = 1; + switch (attr->index) { + //attributes + case SWPLD1_MAJOR_VER ... PSU_LED_MODE://SWPLD1 + cmd_data[1] = SWPLD1_ADDR; + break; + case SWPLD2_MAJOR_VER ... FAN_MOD4_LED://SWPLD2 + cmd_data[1] = SWPLD2_ADDR; + break; + case SWPLD3_MAJOR_VER ... PLATFORM_TYPE://SWPLD3 + cmd_data[1] = SWPLD3_ADDR; + break; + case SWPLD4_MAJOR_VER ... FAN_EEPROM_WP://SWPLD4 + cmd_data[1] = SWPLD4_ADDR; + break; + default: + return sprintf(buf, "%d not found", attr->index); + } + + value = dni_bmc_cmd(get_cmd, cmd_data, cmd_data_len); + mask = attribute_data[attr->index].mask; + mask_out = value & ~(mask); + cmd_data[3] = set_data; + switch (mask) { + case 0xFF: + set_data = mask_out | (set_data & mask); + break; + case 0x0F: + set_data = mask_out | (set_data & mask); + break; + case 0xF0: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + case 0xC0: + set_data = set_data << 6; + set_data = mask_out | (set_data & mask); + break; + case 0x30: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + default : + set_data = mask_out | (set_data << dni_log2(mask) ); + } + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + return count; + } +} + +//SWPLD +static SENSOR_DEVICE_ATTR(swpld1_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD1_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld1_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD1_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld2_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD2_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld2_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD2_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld3_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD3_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld3_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD3_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld4_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD4_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld4_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD4_REG_VALUE); +//SWPLD1 +static SENSOR_DEVICE_ATTR(swpld1_major_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD1_MAJOR_VER); +static SENSOR_DEVICE_ATTR(swpld1_minor_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD1_MINOR_VER); +static SENSOR_DEVICE_ATTR(swpld1_scrtch_reg, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD1_SCRTCH_REG); +static SENSOR_DEVICE_ATTR(psu1_pwr_ok, S_IRUGO, get_swpld_reg, NULL, PSU1_PWR_OK); +static SENSOR_DEVICE_ATTR(psu1_int, S_IRUGO, get_swpld_reg, NULL, PSU1_INT); +static SENSOR_DEVICE_ATTR(psu2_pwr_ok, S_IRUGO, get_swpld_reg, NULL, PSU2_PWR_OK); +static SENSOR_DEVICE_ATTR(psu2_int, S_IRUGO, get_swpld_reg, NULL, PSU2_INT); +static SENSOR_DEVICE_ATTR(synce_int, S_IRUGO, get_swpld_reg, NULL, SYNCE_INT); +static SENSOR_DEVICE_ATTR(synce_rst, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SYNCE_RST); +static SENSOR_DEVICE_ATTR(synce_eeprom_wp, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SYNCE_EEPROM_WP); +static SENSOR_DEVICE_ATTR(psu1_green_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, PSU1_GREEN_LED); +static SENSOR_DEVICE_ATTR(psu1_red_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, PSU1_RED_LED); +static SENSOR_DEVICE_ATTR(psu2_green_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, PSU2_GREEN_LED); +static SENSOR_DEVICE_ATTR(psu2_red_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, PSU2_RED_LED); +static SENSOR_DEVICE_ATTR(psu_led_mode, S_IRUGO, get_swpld_reg, NULL, PSU_LED_MODE); +//SWPLD2 +static SENSOR_DEVICE_ATTR(swpld2_major_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD2_MAJOR_VER); +static SENSOR_DEVICE_ATTR(swpld2_minor_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD2_MINOR_VER); +static SENSOR_DEVICE_ATTR(swpld2_scrtch_reg, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD2_SCRTCH_REG); +static SENSOR_DEVICE_ATTR(fan_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_LED); +static SENSOR_DEVICE_ATTR(sys_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SYS_LED); +static SENSOR_DEVICE_ATTR(fan_mod1_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_MOD1_LED); +static SENSOR_DEVICE_ATTR(fan_mod2_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_MOD2_LED); +static SENSOR_DEVICE_ATTR(fan_mod3_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_MOD3_LED); +static SENSOR_DEVICE_ATTR(fan_mod4_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_MOD4_LED); +//SWPLD3 +static SENSOR_DEVICE_ATTR(swpld3_major_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD3_MAJOR_VER); +static SENSOR_DEVICE_ATTR(swpld3_minor_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD3_MINOR_VER); +static SENSOR_DEVICE_ATTR(swpld3_scrtch_reg, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD3_SCRTCH_REG); +static SENSOR_DEVICE_ATTR(sb_ver, S_IRUGO, get_swpld_reg, NULL, SB_VER); +static SENSOR_DEVICE_ATTR(platform_type, S_IRUGO, get_swpld_reg, NULL, PLATFORM_TYPE); + +//SWPLD4 +static SENSOR_DEVICE_ATTR(swpld4_major_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD4_MAJOR_VER); +static SENSOR_DEVICE_ATTR(swpld4_minor_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD4_MINOR_VER); +static SENSOR_DEVICE_ATTR(swpld4_scrtch_reg, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD4_SCRTCH_REG); +static SENSOR_DEVICE_ATTR(bmc_rst, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, BMC_RST); +static SENSOR_DEVICE_ATTR(cpld_lpc_rst, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, CPLD_LPC_RST); +static SENSOR_DEVICE_ATTR(cpld_sw_rst, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, CPLD_SW_RST); +static SENSOR_DEVICE_ATTR(mb_cpld_rst, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, MB_CPLD_RST); +static SENSOR_DEVICE_ATTR(bcm56970_rst, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, BCM56970_RST); + +static SENSOR_DEVICE_ATTR(cpld_upgrade_rst, S_IRUGO, get_swpld_reg, NULL, CPLD_UPGRADE_RST); +static SENSOR_DEVICE_ATTR(mb_rst_cpld, S_IRUGO, get_swpld_reg, NULL, MB_RST_CPLD); +static SENSOR_DEVICE_ATTR(cpu_rst_mb_oob, S_IRUGO, get_swpld_reg, NULL, CPU_RST_MB_OOB); +static SENSOR_DEVICE_ATTR(gpio_phy_rst, S_IRUGO, get_swpld_reg, NULL, GPIO_PHY_RST); +static SENSOR_DEVICE_ATTR(psu_fan_event, S_IRUGO, get_swpld_reg, NULL, PSU_FAN_EVENT); +static SENSOR_DEVICE_ATTR(cpu_thermal_int, S_IRUGO, get_swpld_reg, NULL, CPU_THERMAL_INT); +static SENSOR_DEVICE_ATTR(fan_int, S_IRUGO, get_swpld_reg, NULL, FAN_INT); + +static SENSOR_DEVICE_ATTR(cpld_spi_wp, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, CPLD_SPI_WP); +static SENSOR_DEVICE_ATTR(rj45_console_sel, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, RJ45_CONSOLE_SEL); +static SENSOR_DEVICE_ATTR(system_int, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SYSTEM_INT); +static SENSOR_DEVICE_ATTR(cpld_mb_rst_done, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, CPLD_MB_RST_DONE); +static SENSOR_DEVICE_ATTR(mb_pwr_ok, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, MB_PWR_OK); +static SENSOR_DEVICE_ATTR(fan_eeprom_wp, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_EEPROM_WP); + +static struct attribute *swpld1_device_attrs[] = { + &sensor_dev_attr_swpld1_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld1_reg_addr.dev_attr.attr, + &sensor_dev_attr_swpld1_major_ver.dev_attr.attr, + &sensor_dev_attr_swpld1_minor_ver.dev_attr.attr, + &sensor_dev_attr_swpld1_scrtch_reg.dev_attr.attr, + &sensor_dev_attr_psu1_pwr_ok.dev_attr.attr, + &sensor_dev_attr_psu1_int.dev_attr.attr, + &sensor_dev_attr_psu2_pwr_ok.dev_attr.attr, + &sensor_dev_attr_psu2_int.dev_attr.attr, + &sensor_dev_attr_synce_int.dev_attr.attr, + &sensor_dev_attr_synce_rst.dev_attr.attr, + &sensor_dev_attr_synce_eeprom_wp.dev_attr.attr, + &sensor_dev_attr_psu1_green_led.dev_attr.attr, + &sensor_dev_attr_psu1_red_led.dev_attr.attr, + &sensor_dev_attr_psu2_green_led.dev_attr.attr, + &sensor_dev_attr_psu2_red_led.dev_attr.attr, + &sensor_dev_attr_psu_led_mode.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld2_device_attrs[] = { + &sensor_dev_attr_swpld2_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld2_reg_addr.dev_attr.attr, + &sensor_dev_attr_swpld2_major_ver.dev_attr.attr, + &sensor_dev_attr_swpld2_minor_ver.dev_attr.attr, + &sensor_dev_attr_swpld2_scrtch_reg.dev_attr.attr, + &sensor_dev_attr_fan_led.dev_attr.attr, + &sensor_dev_attr_sys_led.dev_attr.attr, + &sensor_dev_attr_fan_mod1_led.dev_attr.attr, + &sensor_dev_attr_fan_mod2_led.dev_attr.attr, + &sensor_dev_attr_fan_mod3_led.dev_attr.attr, + &sensor_dev_attr_fan_mod4_led.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld3_device_attrs[] = { + &sensor_dev_attr_swpld3_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld3_reg_addr.dev_attr.attr, + &sensor_dev_attr_swpld3_major_ver.dev_attr.attr, + &sensor_dev_attr_swpld3_minor_ver.dev_attr.attr, + &sensor_dev_attr_swpld3_scrtch_reg.dev_attr.attr, + &sensor_dev_attr_sb_ver.dev_attr.attr, + &sensor_dev_attr_platform_type.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld4_device_attrs[] = { + &sensor_dev_attr_swpld4_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld4_reg_addr.dev_attr.attr, + &sensor_dev_attr_swpld4_major_ver.dev_attr.attr, + &sensor_dev_attr_swpld4_minor_ver.dev_attr.attr, + &sensor_dev_attr_swpld4_scrtch_reg.dev_attr.attr, + &sensor_dev_attr_bmc_rst.dev_attr.attr, + &sensor_dev_attr_cpld_lpc_rst.dev_attr.attr, + &sensor_dev_attr_cpld_sw_rst.dev_attr.attr, + &sensor_dev_attr_mb_cpld_rst.dev_attr.attr, + &sensor_dev_attr_bcm56970_rst.dev_attr.attr, + &sensor_dev_attr_cpld_upgrade_rst.dev_attr.attr, + &sensor_dev_attr_mb_rst_cpld.dev_attr.attr, + &sensor_dev_attr_cpu_rst_mb_oob.dev_attr.attr, + &sensor_dev_attr_gpio_phy_rst.dev_attr.attr, + &sensor_dev_attr_psu_fan_event.dev_attr.attr, + &sensor_dev_attr_cpu_thermal_int.dev_attr.attr, + &sensor_dev_attr_fan_int.dev_attr.attr, + &sensor_dev_attr_cpld_spi_wp.dev_attr.attr, + &sensor_dev_attr_rj45_console_sel.dev_attr.attr, + &sensor_dev_attr_system_int.dev_attr.attr, + &sensor_dev_attr_cpld_mb_rst_done.dev_attr.attr, + &sensor_dev_attr_mb_pwr_ok.dev_attr.attr, + &sensor_dev_attr_fan_eeprom_wp.dev_attr.attr, + NULL, +}; + +static struct attribute_group swpld1_device_attr_grp = { + .attrs = swpld1_device_attrs, +}; + +static struct attribute_group swpld2_device_attr_grp = { + .attrs = swpld2_device_attrs, +}; + +static struct attribute_group swpld3_device_attr_grp = { + .attrs = swpld3_device_attrs, +}; + +static struct attribute_group swpld4_device_attr_grp = { + .attrs = swpld4_device_attrs, +}; + +static int __init swpld1_probe(struct platform_device *pdev) +{ + int ret; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld1_device_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + return -ENODEV; + } + return 0; +} + +static int __init swpld2_probe(struct platform_device *pdev) +{ + int ret; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld2_device_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + return -ENODEV; + } + return 0; +} + +static int __init swpld3_probe(struct platform_device *pdev) +{ + int ret; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld3_device_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + return -ENODEV; + } + return 0; +} + +static int __init swpld4_probe(struct platform_device *pdev) +{ + int ret; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld4_device_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + return -ENODEV; + } + return 0; +} + +static int __exit swpld1_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &swpld1_device_attr_grp); + return 0; +} + +static int __exit swpld2_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &swpld2_device_attr_grp); + return 0; +} + +static int __exit swpld3_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &swpld3_device_attr_grp); + return 0; +} + +static int __exit swpld4_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &swpld4_device_attr_grp); + return 0; +} + +static struct platform_driver swpld1_driver = { + .probe = swpld1_probe, + .remove = __exit_p(swpld1_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-swpld1", + }, +}; + +static struct platform_driver swpld2_driver = { + .probe = swpld2_probe, + .remove = __exit_p(swpld2_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-swpld2", + }, +}; + +static struct platform_driver swpld3_driver = { + .probe = swpld3_probe, + .remove = __exit_p(swpld3_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-swpld3", + }, +}; + +static struct platform_driver swpld4_driver = { + .probe = swpld4_probe, + .remove = __exit_p(swpld4_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-swpld4", + }, +}; +/*---------------- CPLD - end ------------- */ + +/*---------------- module initialization ------------- */ +static int __init delta_ag9064_swpld_init(void) +{ + int ret; + printk(KERN_WARNING "ag9064_platform_swpld module initialization\n"); + + ret = dni_create_user(); + if (ret != 0){ + printk(KERN_WARNING "Fail to create IPMI user\n"); + } + + // set the SWPLD prob and remove + ret = platform_driver_register(&swpld1_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld driver\n"); + goto error_swpld1_driver; + } + + // register the SWPLD + ret = platform_device_register(&swpld1_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld device\n"); + goto error_swpld1_device; + } + + // set the SWPLD prob and remove + ret = platform_driver_register(&swpld2_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld driver\n"); + goto error_swpld2_driver; + } + + // register the SWPLD + ret = platform_device_register(&swpld2_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld device\n"); + goto error_swpld2_device; + } + + // set the SWPLD prob and remove + ret = platform_driver_register(&swpld3_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld driver\n"); + goto error_swpld3_driver; + } + + // register the SWPLD + ret = platform_device_register(&swpld3_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld device\n"); + goto error_swpld3_device; + } + + // set the SWPLD prob and remove + ret = platform_driver_register(&swpld4_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld driver\n"); + goto error_swpld4_driver; + } + + // register the SWPLD + ret = platform_device_register(&swpld4_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld device\n"); + goto error_swpld4_device; + } + return 0; + +error_swpld4_device: + platform_driver_unregister(&swpld4_driver); +error_swpld4_driver: + platform_device_unregister(&swpld3_device); +error_swpld3_device: + platform_driver_unregister(&swpld3_driver); +error_swpld3_driver: + platform_device_unregister(&swpld2_device); +error_swpld2_device: + platform_driver_unregister(&swpld2_driver); +error_swpld2_driver: + platform_device_unregister(&swpld1_device); +error_swpld1_device: + platform_driver_unregister(&swpld1_driver); +error_swpld1_driver: + return ret; +} + +static void __exit delta_ag9064_swpld_exit(void) +{ + platform_device_unregister(&swpld1_device); + platform_driver_unregister(&swpld1_driver); + platform_device_unregister(&swpld2_device); + platform_driver_unregister(&swpld2_driver); + platform_device_unregister(&swpld3_device); + platform_driver_unregister(&swpld3_driver); + platform_device_unregister(&swpld4_device); + platform_driver_unregister(&swpld4_driver); +} +module_init(delta_ag9064_swpld_init); +module_exit(delta_ag9064_swpld_exit); + +MODULE_DESCRIPTION("DNI ag9064 CPLD Platform Support"); +MODULE_AUTHOR("Stanley Chi "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/hbm.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/hbm.h new file mode 100644 index 000000000000..a2025a5083a3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/hbm.h @@ -0,0 +1,62 @@ +/* + * + * Intel Management Engine Interface (Intel MEI) Linux driver + * Copyright (c) 2003-2012, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + */ + +#ifndef _MEI_HBM_H_ +#define _MEI_HBM_H_ + +struct mei_device; +struct mei_msg_hdr; +struct mei_cl; + +/** + * enum mei_hbm_state - host bus message protocol state + * + * @MEI_HBM_IDLE : protocol not started + * @MEI_HBM_STARTING : start request message was sent + * @MEI_HBM_ENUM_CLIENTS : enumeration request was sent + * @MEI_HBM_CLIENT_PROPERTIES : acquiring clients properties + * @MEI_HBM_STARTED : enumeration was completed + * @MEI_HBM_STOPPED : stopping exchange + */ +enum mei_hbm_state { + MEI_HBM_IDLE = 0, + MEI_HBM_STARTING, + MEI_HBM_ENUM_CLIENTS, + MEI_HBM_CLIENT_PROPERTIES, + MEI_HBM_STARTED, + MEI_HBM_STOPPED, +}; + +const char *mei_hbm_state_str(enum mei_hbm_state state); + +int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr); + +void mei_hbm_idle(struct mei_device *dev); +void mei_hbm_reset(struct mei_device *dev); +int mei_hbm_start_req(struct mei_device *dev); +int mei_hbm_start_wait(struct mei_device *dev); +int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl); +int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl); +int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl); +int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl); +bool mei_hbm_version_is_supported(struct mei_device *dev); +int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd); +void mei_hbm_pg_resume(struct mei_device *dev); +int mei_hbm_cl_notify_req(struct mei_device *dev, + struct mei_cl *cl, u8 request); + +#endif /* _MEI_HBM_H_ */ + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/hw.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/hw.h new file mode 100644 index 000000000000..4cebde85924f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/hw.h @@ -0,0 +1,426 @@ +/* + * + * Intel Management Engine Interface (Intel MEI) Linux driver + * Copyright (c) 2003-2012, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + */ + +#ifndef _MEI_HW_TYPES_H_ +#define _MEI_HW_TYPES_H_ + +#include + +/* + * Timeouts in Seconds + */ +#define MEI_HW_READY_TIMEOUT 2 /* Timeout on ready message */ +#define MEI_CONNECT_TIMEOUT 3 /* HPS: at least 2 seconds */ + +#define MEI_CL_CONNECT_TIMEOUT 15 /* HPS: Client Connect Timeout */ +#define MEI_CLIENTS_INIT_TIMEOUT 15 /* HPS: Clients Enumeration Timeout */ + +#define MEI_IAMTHIF_STALL_TIMER 12 /* HPS */ +#define MEI_IAMTHIF_READ_TIMER 10 /* HPS */ + +#define MEI_PGI_TIMEOUT 1 /* PG Isolation time response 1 sec */ +#define MEI_D0I3_TIMEOUT 5 /* D0i3 set/unset max response time */ +#define MEI_HBM_TIMEOUT 1 /* 1 second */ + +/* + * MEI Version + */ +#define HBM_MINOR_VERSION 0 +#define HBM_MAJOR_VERSION 2 + +/* + * MEI version with PGI support + */ +#define HBM_MINOR_VERSION_PGI 1 +#define HBM_MAJOR_VERSION_PGI 1 + +/* + * MEI version with Dynamic clients support + */ +#define HBM_MINOR_VERSION_DC 0 +#define HBM_MAJOR_VERSION_DC 2 + +/* + * MEI version with disconnect on connection timeout support + */ +#define HBM_MINOR_VERSION_DOT 0 +#define HBM_MAJOR_VERSION_DOT 2 + +/* + * MEI version with notifcation support + */ +#define HBM_MINOR_VERSION_EV 0 +#define HBM_MAJOR_VERSION_EV 2 + +/* Host bus message command opcode */ +#define MEI_HBM_CMD_OP_MSK 0x7f +/* Host bus message command RESPONSE */ +#define MEI_HBM_CMD_RES_MSK 0x80 + +/* + * MEI Bus Message Command IDs + */ +#define HOST_START_REQ_CMD 0x01 +#define HOST_START_RES_CMD 0x81 + +#define HOST_STOP_REQ_CMD 0x02 +#define HOST_STOP_RES_CMD 0x82 + +#define ME_STOP_REQ_CMD 0x03 + +#define HOST_ENUM_REQ_CMD 0x04 +#define HOST_ENUM_RES_CMD 0x84 + +#define HOST_CLIENT_PROPERTIES_REQ_CMD 0x05 +#define HOST_CLIENT_PROPERTIES_RES_CMD 0x85 + +#define CLIENT_CONNECT_REQ_CMD 0x06 +#define CLIENT_CONNECT_RES_CMD 0x86 + +#define CLIENT_DISCONNECT_REQ_CMD 0x07 +#define CLIENT_DISCONNECT_RES_CMD 0x87 + +#define MEI_FLOW_CONTROL_CMD 0x08 + +#define MEI_PG_ISOLATION_ENTRY_REQ_CMD 0x0a +#define MEI_PG_ISOLATION_ENTRY_RES_CMD 0x8a +#define MEI_PG_ISOLATION_EXIT_REQ_CMD 0x0b +#define MEI_PG_ISOLATION_EXIT_RES_CMD 0x8b + +#define MEI_HBM_ADD_CLIENT_REQ_CMD 0x0f +#define MEI_HBM_ADD_CLIENT_RES_CMD 0x8f + +#define MEI_HBM_NOTIFY_REQ_CMD 0x10 +#define MEI_HBM_NOTIFY_RES_CMD 0x90 +#define MEI_HBM_NOTIFICATION_CMD 0x11 + +/* + * MEI Stop Reason + * used by hbm_host_stop_request.reason + */ +enum mei_stop_reason_types { + DRIVER_STOP_REQUEST = 0x00, + DEVICE_D1_ENTRY = 0x01, + DEVICE_D2_ENTRY = 0x02, + DEVICE_D3_ENTRY = 0x03, + SYSTEM_S1_ENTRY = 0x04, + SYSTEM_S2_ENTRY = 0x05, + SYSTEM_S3_ENTRY = 0x06, + SYSTEM_S4_ENTRY = 0x07, + SYSTEM_S5_ENTRY = 0x08 +}; + + +/** + * enum mei_hbm_status - mei host bus messages return values + * + * @MEI_HBMS_SUCCESS : status success + * @MEI_HBMS_CLIENT_NOT_FOUND : client not found + * @MEI_HBMS_ALREADY_EXISTS : connection already established + * @MEI_HBMS_REJECTED : connection is rejected + * @MEI_HBMS_INVALID_PARAMETER : invalid parameter + * @MEI_HBMS_NOT_ALLOWED : operation not allowed + * @MEI_HBMS_ALREADY_STARTED : system is already started + * @MEI_HBMS_NOT_STARTED : system not started + * + * @MEI_HBMS_MAX : sentinel + */ +enum mei_hbm_status { + MEI_HBMS_SUCCESS = 0, + MEI_HBMS_CLIENT_NOT_FOUND = 1, + MEI_HBMS_ALREADY_EXISTS = 2, + MEI_HBMS_REJECTED = 3, + MEI_HBMS_INVALID_PARAMETER = 4, + MEI_HBMS_NOT_ALLOWED = 5, + MEI_HBMS_ALREADY_STARTED = 6, + MEI_HBMS_NOT_STARTED = 7, + + MEI_HBMS_MAX +}; + + +/* + * Client Connect Status + * used by hbm_client_connect_response.status + */ +enum mei_cl_connect_status { + MEI_CL_CONN_SUCCESS = MEI_HBMS_SUCCESS, + MEI_CL_CONN_NOT_FOUND = MEI_HBMS_CLIENT_NOT_FOUND, + MEI_CL_CONN_ALREADY_STARTED = MEI_HBMS_ALREADY_EXISTS, + MEI_CL_CONN_OUT_OF_RESOURCES = MEI_HBMS_REJECTED, + MEI_CL_CONN_MESSAGE_SMALL = MEI_HBMS_INVALID_PARAMETER, + MEI_CL_CONN_NOT_ALLOWED = MEI_HBMS_NOT_ALLOWED, +}; + +/* + * Client Disconnect Status + */ +enum mei_cl_disconnect_status { + MEI_CL_DISCONN_SUCCESS = MEI_HBMS_SUCCESS +}; + +/* + * MEI BUS Interface Section + */ +struct mei_msg_hdr { + u32 me_addr:8; + u32 host_addr:8; + u32 length:9; + u32 reserved:5; + u32 internal:1; + u32 msg_complete:1; +} __packed; + + +struct mei_bus_message { + u8 hbm_cmd; + u8 data[0]; +} __packed; + +/** + * struct hbm_cl_cmd - client specific host bus command + * CONNECT, DISCONNECT, and FlOW CONTROL + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @host_addr: address of the client in the driver + * @data: generic data + */ +struct mei_hbm_cl_cmd { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 data; +}; + +struct hbm_version { + u8 minor_version; + u8 major_version; +} __packed; + +struct hbm_host_version_request { + u8 hbm_cmd; + u8 reserved; + struct hbm_version host_version; +} __packed; + +struct hbm_host_version_response { + u8 hbm_cmd; + u8 host_version_supported; + struct hbm_version me_max_version; +} __packed; + +struct hbm_host_stop_request { + u8 hbm_cmd; + u8 reason; + u8 reserved[2]; +} __packed; + +struct hbm_host_stop_response { + u8 hbm_cmd; + u8 reserved[3]; +} __packed; + +struct hbm_me_stop_request { + u8 hbm_cmd; + u8 reason; + u8 reserved[2]; +} __packed; + +/** + * struct hbm_host_enum_request - enumeration request from host to fw + * + * @hbm_cmd: bus message command header + * @allow_add: allow dynamic clients add HBM version >= 2.0 + * @reserved: reserved + */ +struct hbm_host_enum_request { + u8 hbm_cmd; + u8 allow_add; + u8 reserved[2]; +} __packed; + +struct hbm_host_enum_response { + u8 hbm_cmd; + u8 reserved[3]; + u8 valid_addresses[32]; +} __packed; + +struct mei_client_properties { + uuid_le protocol_name; + u8 protocol_version; + u8 max_number_of_connections; + u8 fixed_address; + u8 single_recv_buf; + u32 max_msg_length; +} __packed; + +struct hbm_props_request { + u8 hbm_cmd; + u8 me_addr; + u8 reserved[2]; +} __packed; + +struct hbm_props_response { + u8 hbm_cmd; + u8 me_addr; + u8 status; + u8 reserved[1]; + struct mei_client_properties client_properties; +} __packed; + +/** + * struct hbm_add_client_request - request to add a client + * might be sent by fw after enumeration has already completed + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @reserved: reserved + * @client_properties: client properties + */ +struct hbm_add_client_request { + u8 hbm_cmd; + u8 me_addr; + u8 reserved[2]; + struct mei_client_properties client_properties; +} __packed; + +/** + * struct hbm_add_client_response - response to add a client + * sent by the host to report client addition status to fw + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @status: if HBMS_SUCCESS then the client can now accept connections. + * @reserved: reserved + */ +struct hbm_add_client_response { + u8 hbm_cmd; + u8 me_addr; + u8 status; + u8 reserved[1]; +} __packed; + +/** + * struct hbm_power_gate - power gate request/response + * + * @hbm_cmd: bus message command header + * @reserved: reserved + */ +struct hbm_power_gate { + u8 hbm_cmd; + u8 reserved[3]; +} __packed; + +/** + * struct hbm_client_connect_request - connect/disconnect request + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @host_addr: address of the client in the driver + * @reserved: reserved + */ +struct hbm_client_connect_request { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 reserved; +} __packed; + +/** + * struct hbm_client_connect_response - connect/disconnect response + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @host_addr: address of the client in the driver + * @status: status of the request + */ +struct hbm_client_connect_response { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 status; +} __packed; + + +#define MEI_FC_MESSAGE_RESERVED_LENGTH 5 + +struct hbm_flow_control { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 reserved[MEI_FC_MESSAGE_RESERVED_LENGTH]; +} __packed; + +#define MEI_HBM_NOTIFICATION_START 1 +#define MEI_HBM_NOTIFICATION_STOP 0 +/** + * struct hbm_notification_request - start/stop notification request + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @host_addr: address of the client in the driver + * @start: start = 1 or stop = 0 asynchronous notifications + */ +struct hbm_notification_request { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 start; +} __packed; + +/** + * struct hbm_notification_response - start/stop notification response + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @host_addr: - address of the client in the driver + * @status: (mei_hbm_status) response status for the request + * - MEI_HBMS_SUCCESS: successful stop/start + * - MEI_HBMS_CLIENT_NOT_FOUND: if the connection could not be found. + * - MEI_HBMS_ALREADY_STARTED: for start requests for a previously + * started notification. + * - MEI_HBMS_NOT_STARTED: for stop request for a connected client for whom + * asynchronous notifications are currently disabled. + * + * @start: start = 1 or stop = 0 asynchronous notifications + * @reserved: reserved + */ +struct hbm_notification_response { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 status; + u8 start; + u8 reserved[3]; +} __packed; + +/** + * struct hbm_notification - notification event + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @host_addr: address of the client in the driver + * @reserved: reserved for alignment + */ +struct hbm_notification { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 reserved[1]; +} __packed; + +#endif diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_io.c b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_io.c new file mode 100644 index 000000000000..97c93c6122bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_io.c @@ -0,0 +1,636 @@ + +#include "i2c-mei_rw.h" + + +/* ========== IoLibGcc.c ========= */ + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +//__inline__ +UINT8 +IoRead8 ( + IN UINTN Port + ) +{ + UINT8 Data; + + __asm__ __volatile__ ("inb %w1,%b0" : "=a" (Data) : "d" ((UINT16)Port)); + return Data; +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +//__inline__ +UINT8 +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + __asm__ __volatile__ ("outb %b0,%w1" : : "a" (Value), "d" ((UINT16)Port)); + return Value;; +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +//__inline__ +UINT16 +IoRead16 ( + IN UINTN Port + ) +{ + UINT16 Data; + + if((Port & 1) != 0) + printk("Failed\n"); + __asm__ __volatile__ ("inw %w1,%w0" : "=a" (Data) : "d" ((UINT16)Port)); + return Data; +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +//__inline__ +UINT16 +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + if((Port & 1) != 0) + printk("Failed\n"); + __asm__ __volatile__ ("outw %w0,%w1" : : "a" (Value), "d" ((UINT16)Port)); + return Value;; +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +//__inline__ +UINT32 +IoRead32 ( + IN UINTN Port + ) +{ + UINT32 Data; + + if((Port & 3) != 0) + printk("Failed\n"); + __asm__ __volatile__ ("inl %w1,%0" : "=a" (Data) : "d" ((UINT16)Port)); + return Data; +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +//__inline__ +UINT32 +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + if((Port & 3) != 0) + printk("Failed\n"); + __asm__ __volatile__ ("outl %0,%w1" : : "a" (Value), "d" ((UINT16)Port)); + return Value; +} + + + +/* ========== GccInline.c ========= */ + +/** + Enables CPU interrupts. + + Enables CPU interrupts. + +**/ +VOID +EnableInterrupts ( + VOID + ) +{ + __asm__ __volatile__ ("sti"::: "memory"); +} + +/** + Disables CPU interrupts. + + Disables CPU interrupts. + +**/ +VOID +DisableInterrupts ( + VOID + ) +{ + __asm__ __volatile__ ("cli"::: "memory"); +} + +/** + Reads the current value of the EFLAGS register. + + Reads and returns the current value of the EFLAGS register. This function is + only available on IA-32 and X64. This returns a 32-bit value on IA-32 and a + 64-bit value on X64. + + @return EFLAGS on IA-32 or RFLAGS on X64. + +**/ +UINTN +AsmReadEflags ( + VOID + ) +{ + UINTN Eflags; + + __asm__ __volatile__ ( + "pushfq \n\t" + "pop %0 " + : "=r" (Eflags) // %0 + ); + + return Eflags; +} + + + +/* ========== X86GetInterruptState.c ========= */ + +/** + Retrieves the current CPU interrupt state. + + Returns TRUE is interrupts are currently enabled. Otherwise + returns FALSE. + + @retval TRUE CPU interrupts are enabled. + @retval FALSE CPU interrupts are disabled. + +**/ +BOOLEAN +GetInterruptState ( + VOID + ) +{ + IA32_EFLAGS32 EFlags; + + EFlags.UintN = AsmReadEflags (); + return (BOOLEAN)(1 == EFlags.Bits.IF); +} + + + +/* ========== Cpu.c ========= */ + +/** + Disables CPU interrupts and returns the interrupt state prior to the disable + operation. + + @retval TRUE CPU interrupts were enabled on entry to this call. + @retval FALSE CPU interrupts were disabled on entry to this call. + +**/ +BOOLEAN +SaveAndDisableInterrupts ( + VOID + ) +{ + BOOLEAN InterruptState; + + InterruptState = GetInterruptState (); + DisableInterrupts (); + return InterruptState; +} + +/** + Set the current CPU interrupt state. + + Sets the current CPU interrupt state to the state specified by + InterruptState. If InterruptState is TRUE, then interrupts are enabled. If + InterruptState is FALSE, then interrupts are disabled. InterruptState is + returned. + + @param InterruptState TRUE if interrupts should be enabled. FALSE if + interrupts should be disabled. + + @return InterruptState + +**/ +BOOLEAN +SetInterruptState ( + IN BOOLEAN InterruptState + ) +{ + if (InterruptState) { + EnableInterrupts (); + } else { + DisableInterrupts (); + } + return InterruptState; +} + + + +/* ========== pciLib.c ========= */ + +// +// Declare I/O Ports used to perform PCI Confguration Cycles +// +#define PCI_CONFIGURATION_ADDRESS_PORT 0xCF8 +#define PCI_CONFIGURATION_DATA_PORT 0xCFC + +/** + Convert a PCI Library address to PCI CF8 formatted address. + + Declare macro to convert PCI Library address to PCI CF8 formatted address. + Bit fields of PCI Library and CF8 formatted address is as follows: + PCI Library formatted address CF8 Formatted Address + ============================= ====================== + Bits 00..11 Register Bits 00..07 Register + Bits 12..14 Function Bits 08..10 Function + Bits 15..19 Device Bits 11..15 Device + Bits 20..27 Bus Bits 16..23 Bus + Bits 28..31 Reserved(MBZ) Bits 24..30 Reserved(MBZ) + Bits 31..31 Must be 1 + + @param A The address to convert. + + @retval The coverted address. + +**/ +#define PCI_TO_CF8_ADDRESS(A) \ + ((UINT32) ((((A) >> 4) & 0x00ffff00) | ((A) & 0xfc) | 0x80000000)) + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +PciCf8Read8 ( + IN UINTN Address + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoRead8 (PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3)); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +PciCf8Write8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoWrite8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + Value + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +PciCf8Read16 ( + IN UINTN Address + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoRead16 (PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2)); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +PciCf8Write16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoWrite16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + Value + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +PciCf8Read32 ( + IN UINTN Address + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoRead32 (PCI_CONFIGURATION_DATA_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +PciCf8Write32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoWrite32 ( + PCI_CONFIGURATION_DATA_PORT, + Value + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + + + +/* ========== Other ========= */ + +// UINT8 PciRead8(UINT64 addr) +// { +// printf("[%s] addr: %8X.\n", __func__, addr); +// return 0x01; +// } + +// UINT8 PciWrite8(UINT64 addr, UINT8 data) +// { +// printf("[%s] addr: %8X data: %2X.\n", __func__, addr, data); +// return 0x02; +// } + + +// UINT16 PciRead16(UINT64 addr) +// { +// printf("[%s] addr: %8X.\n", __func__, addr); +// return 0x03; +// } + +// UINT16 PciWrite16(UINT64 addr, UINT8 data) +// { +// printf("[%s] addr: %8X data: %2X.\n", __func__, addr, data); +// return 0x04; +// } + + +// UINT32 PciRead32(UINT64 addr) +// { +// printf("[%s] addr: %8X.\n", __func__, addr); +// return 0x05; +// } + +// UINT32 PciWrite32(UINT64 addr, UINT8 data) +// { +// printf("[%s] addr: %8X data: %2X.\n", __func__, addr, data); +// return 0x06; +// } + +UINT8 PciRead8(UINT64 addr) +{ + return PciCf8Read8 (addr); +} + +UINT8 PciWrite8(UINT64 addr, UINT8 data) +{ + return PciCf8Write8 (addr, data); +} + + +UINT16 PciRead16(UINT64 addr) +{ + return PciCf8Read16 (addr); +} + +UINT16 PciWrite16(UINT64 addr, UINT8 data) +{ + return PciCf8Write16 (addr, data); +} + + +UINT32 PciRead32(UINT64 addr) +{ + return PciCf8Read32 (addr); +} + +UINT32 PciWrite32(UINT64 addr, UINT8 data) +{ + return PciCf8Write32 (addr, data); +} diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_io.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_io.h new file mode 100644 index 000000000000..5180cc47e736 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_io.h @@ -0,0 +1,46 @@ + +#include "i2c-mei_type.h" + + + +/* ========== PciLib.h ========= */ + +/** + Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an + address that can be passed to the PCI Library functions. + + @param Bus PCI Bus number. Range 0..255. + @param Device PCI Device number. Range 0..31. + @param Function PCI Function number. Range 0..7. + @param Register PCI Register number. Range 0..255 for PCI. Range 0..4095 + for PCI Express. + + @return The encoded PCI address. + +**/ +#define PCI_LIB_ADDRESS(Bus,Device,Function,Register) \ + (((Register) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20)) + + + +/* ========== Qubbing ========= */ + +UINT8 PciRead8(UINT64 addr); + +UINT8 PciWrite8(UINT64 addr, UINT8 data); + +UINT16 PciRead16(UINT64 addr); + +UINT16 PciWrite16(UINT64 addr, UINT8 data); + +UINT32 PciRead32(UINT64 addr); + +UINT32 PciWrite32(UINT64 addr, UINT8 data); + + +void I2C_Set(UINT8 smbus, UINT8 daddr, INT32 reg, UINT8 *data, UINT8 dlen); + +void I2C_Read(UINT8 smbus, UINT8 daddr, INT32 reg, UINT8 dlen); + +void VersionRead(void); +void I2C_Probe(void); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_main.c b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_main.c new file mode 100644 index 000000000000..a5dbbd22b4a5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_main.c @@ -0,0 +1,579 @@ +/* + * MEI-I2C driver + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mei_dev.h" +#include "client.h" +#include "i2c-mei_rw.h" + +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ + defined CONFIG_DMI +#include +#include +#endif + +/* PCI Address Constants */ +#define SMBBAR 0 +#define SMBPCICTL 0x004 +#define SMBPCISTS 0x006 +#define SMBHSTCFG 0x040 +#define TCOBASE 0x050 +#define TCOCTL 0x054 + +/* Other settings */ +#define MAX_RETRIES 400 + +/* I801 command constants */ +#define I801_QUICK 0x00 +#define I801_BYTE 0x04 +#define I801_BYTE_DATA 0x08 +#define I801_WORD_DATA 0x0C +#define I801_PROC_CALL 0x10 /* unimplemented */ +#define I801_BLOCK_DATA 0x14 +#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */ + +#define HECI_PEC_FLAG 0x80 + +#define PCI_DEVICE_ID_INTEL_LPT_H 0x8C3A /* Lynx Point H */ + +struct mei_i2c_mux_config { + char *gpio_chip; + unsigned values[3]; + int n_values; + unsigned classes[3]; + unsigned gpios[2]; /* Relative to gpio_chip->base */ + int n_gpios; +}; + +#define FEATURE_SMBUS_PEC (1 << 0) +#define FEATURE_BLOCK_BUFFER (1 << 1) +#define FEATURE_BLOCK_PROC (1 << 2) +#define FEATURE_I2C_BLOCK_READ (1 << 3) +#define FEATURE_IRQ (1 << 4) +/* Not really a feature, but it's convenient to handle it as such */ +#define FEATURE_IDF (1 << 15) +#define FEATURE_TCO (1 << 16) + +static const char *mei_i2c_feature_names[] = { + "SMBus PEC", + "Block buffer", + "Block process call", + "I2C block read", + "Interrupt", +}; + +static unsigned int disable_features; +module_param(disable_features, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(disable_features, "Disable selected driver features:\n" + "\t\t 0x01 disable SMBus PEC\n" + "\t\t 0x02 disable the block buffer\n" + "\t\t 0x08 disable the I2C block read functionality\n" + "\t\t 0x10 don't use interrupts "); + + +/*MEI SMB Sensor Bus (when MEI_FLAG_SMB_DEV_ADD_FMAT_EXT)*/ +#define MEI_SMB_BUS_SMBUS 0x0 +#define MEI_SMB_BUS_SMLINK0 0x1 +#define MEI_SMB_BUS_SMLINK1 0x2 +#define MEI_SMB_BUS_SMLINK2 0x3 +#define MEI_SMB_BUS_SMLINK3 0x4 +#define MEI_SMB_BUS_SMLINK4 0x5 + +struct mei_smb_priv{ + struct i2c_adapter adapter; + unsigned long smba; + unsigned char original_hstcfg; + struct pci_dev *pci_dev; + unsigned int features; + unsigned char sensorbus; + /* isr processing */ + wait_queue_head_t waitq; + u8 status; + /* Command state used by isr for byte-by-byte block transactions */ + u8 cmd; + bool is_read; + int count; + int len; + u8 *data; +}; + + +struct mei_i2c_data_ext{ + char Cmd; + char Flag; + char Sensor_Bus; + char Psu_Addr; + char Mux_Addr; + char Mux_Channel; + char Mux_Conf; + char Reserved; + char W_Length; + char R_Length; + char PMbus_data[21]; +}; + +struct mei_msg{ + struct mei_msg_hdr hdr; + struct mei_i2c_data_ext data; +}; + +#define DEBUG_MSG 0 +static int mei_TxRx(u8 sensor_bus, u16 addr, u8 command, char read_write, int size, union i2c_smbus_data * data, int pec) +{ + struct mei_msg_hdr mei_hdr; + int rets; + unsigned char * recv_buf; + int retry = 0; + int len = 0; + int i = 0; + + struct mei_msg * msg; +// unsigned char blen; + + UINT32 timeout, dwTimeout; + UINT32 blen; + HECI_DEVICE sHeciDev; + + recv_buf = kmalloc(sizeof(unsigned char) * (32), GFP_KERNEL); + msg = kmalloc(sizeof(struct mei_msg), GFP_KERNEL); + + dwTimeout = 2000000 / HECI_TIMEOUT_UNIT; + + sHeciDev.Bus = HECI_BUS; + sHeciDev.Dev = HECI_DEV; + sHeciDev.Fun = HECI_FUN; + sHeciDev.Hidm = HECI_HIDM_MSI; + sHeciDev.Mbar = HECI_MBAR_DEFAULT; + HeciInit(&sHeciDev, &dwTimeout); + + msg->data.Cmd = 0x0A; + if(read_write){ + if(size == I2C_SMBUS_WORD_DATA){ + msg->data.Flag = 0x56; + msg->data.W_Length = 1; + msg->data.R_Length = 2; + } + else if(size == I2C_SMBUS_BYTE_DATA || size == I2C_SMBUS_QUICK){ + msg->data.Flag = 0x52; + msg->data.W_Length = 1; + msg->data.R_Length = 1; + }else if(size == I2C_SMBUS_BYTE){ + msg->data.Flag = 0x50; + msg->data.W_Length = 0; + msg->data.R_Length = 1; + }else if(size == I2C_SMBUS_BLOCK_DATA){ + msg->data.Flag = 0x5A; + msg->data.W_Length = 1; + } + + } + else{ + if(size == I2C_SMBUS_WORD_DATA){ + msg->data.Flag = 0x58; + msg->data.W_Length = 3; + } + else if(size == I2C_SMBUS_BYTE_DATA){ + msg->data.Flag = 0x54; + msg->data.W_Length = 2; + } + else if((size == I2C_SMBUS_BYTE) || (size == I2C_SMBUS_QUICK)){ + msg->data.Flag = 0x50; + msg->data.W_Length = 1; + }else if(size == I2C_SMBUS_BLOCK_DATA){ + msg->data.Flag = 0x5C; + msg->data.W_Length = data->block[0]; + } + + msg->data.R_Length = 0x0; + if(data !=NULL){ + if(size == I2C_SMBUS_WORD_DATA){ + msg->data.PMbus_data[1] = data->word & 0xff; + msg->data.PMbus_data[2] = (data->word & 0xff00) >> 8; + }else if(size == I2C_SMBUS_BYTE_DATA){ + msg->data.PMbus_data[1] = data->byte; + }else if(size == I2C_SMBUS_BLOCK_DATA){ + for (i = 0; i < msg->data.W_Length; i++) + msg->data.PMbus_data[i+1] = data->block[i+1]; + } + + }else{ + msg->data.PMbus_data[1] = 0; + } + } + + if (pec == 1) + msg->data.Flag |= HECI_PEC_FLAG; + + msg->data.Sensor_Bus = sensor_bus; + msg->data.Psu_Addr =(char) addr << 1; + msg->data.Mux_Addr = 0x0; + msg->data.Mux_Channel = 0x0; + msg->data.Mux_Conf = 0x0; + msg->data.Reserved = 0x0; + msg->data.PMbus_data[0] = command; + + + msg->hdr.host_addr = 0;//mei_cl_host_addr(cl); + msg->hdr.me_addr = 0x20; + msg->hdr.reserved = 0; + msg->hdr.msg_complete = 0; + msg->hdr.internal = 0; //cb->internal; + msg->hdr.length = 10 + msg->data.W_Length; + msg->hdr.msg_complete = 1; + +#if (DEBUG_MSG) + printk("Cmd : 0x%02x , Flag : 0x%02x , Sensor_Bus : 0x%02x , Psu_Addr : 0x%02x\n" , msg->data.Cmd, msg->data.Flag, msg->data.Sensor_Bus, msg->data.Psu_Addr); + printk("Mux_Addr : 0x%02x , Mux_Channel : 0x%02x , Mux_Conf : 0x%02x , W_Length : 0x%02x\n" , msg->data.Mux_Addr, msg->data.Mux_Channel, msg->data.Mux_Conf, msg->data.W_Length); + printk("R_Length : 0x%02x , PMbus_data[0] : 0x%02x , size : 0x%x\n" , msg->data.R_Length, msg->data.PMbus_data[0], size); + if(!read_write){ + if(size == I2C_SMBUS_BLOCK_DATA){ + for (i = 0; i < msg->data.W_Length; i++){ + printk("PMbus_data[%d] : 0x%02x , ", i, msg->data.PMbus_data[i]); + } + printk("\n"); + }else{ + printk("PMbus_data[1] : 0x%02x , PMbus_data[2] : 0x%02x\n", msg->data.PMbus_data[1], msg->data.PMbus_data[2]); + } + } +#endif + retry = 3; + while(retry){ + timeout = HECI_SEND_TIMEOUT / HECI_TIMEOUT_UNIT; + rets = HeciMsgSend(&sHeciDev, &timeout, (HECI_MSG_HEADER *)msg); + if (rets != 0){ + printk("HeciMsgSend ret: %d\n",rets); + retry --; + continue; + }else{ + break; + } + } + if(read_write) + { + if(size == I2C_SMBUS_WORD_DATA){ + blen = 8; + HeciMsgRecv(&sHeciDev, &timeout, (HECI_MSG_HEADER *)recv_buf, &blen); + } + else if(size == I2C_SMBUS_BYTE_DATA || size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE){ + blen = 7; + HeciMsgRecv(&sHeciDev, &timeout, (HECI_MSG_HEADER *)recv_buf, &blen); + } +#if (DEBUG_MSG) + if(size == I2C_SMBUS_BLOCK_DATA){ + printk("recv_len %d hdr: 0x%02x%02x%02x%02x\n", blen, recv_buf[3], recv_buf[2], recv_buf[1], recv_buf[0]); + for (i = 0; i < blen ; i++){ + printk("0x%02x , ", recv_buf[4 + i]); + } + printk("\n"); + }else{ + printk("recv_len %d recv: 0x%02x%02x%02x%02x\n0x%02x , 0x%02x , 0x%02x, 0x%02x \n", blen, recv_buf[3], recv_buf[2], recv_buf[1], recv_buf[0], recv_buf[4], recv_buf[5], recv_buf[6], recv_buf[7]); + } +#endif + if(data !=NULL){ + if(size == I2C_SMBUS_WORD_DATA){ + data->word = ((recv_buf[7] << 8) & 0xff00) | (recv_buf[6] & 0xff); + } + else if(size == I2C_SMBUS_BYTE_DATA){ + data->byte = recv_buf[6] & 0xff; + } + else if(size == I2C_SMBUS_BLOCK_DATA){ + for (i = 0; i < blen; i++){ + data->block[i] = recv_buf[6+i] & 0xff; + } + } + } + } + else + { + blen = 6; + HeciMsgRecv(&sHeciDev, &timeout, (HECI_MSG_HEADER *)recv_buf, &blen); +#if (DEBUG_MSG) + printk("recv: 0x%02x%02x%02x%02x , 0x%02x , 0x%02x \n", recv_buf[3], recv_buf[2], recv_buf[1], recv_buf[0], recv_buf[4], recv_buf[5]); +#endif + } + + rets = recv_buf[5]; + + kfree(recv_buf); + kfree(msg); + if(rets) + return -1; + else + return 0; +} + +/* Return negative errno on error. */ +static s32 mei_i2c_access(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, u8 command, + int size, union i2c_smbus_data *data) +{ + int hwpec; + int block = 0; + int ret = 0, xact = 0; + int pec = 0; + char byte = 0; + struct mei_smb_priv *priv = i2c_get_adapdata(adap); + + if (flags & I2C_CLIENT_PEC) + pec = 1; + + switch (size) { + case I2C_SMBUS_QUICK: + + command = 0; + read_write = 1; + ret = mei_TxRx(priv->sensorbus, addr, command, read_write, size, NULL, pec); + xact = I801_QUICK; + break; + case I2C_SMBUS_BYTE: + if (read_write == I2C_SMBUS_READ) + command = 0; + ret = mei_TxRx(priv->sensorbus, addr, command, read_write, size, data, pec); + xact = I801_BYTE; + break; + case I2C_SMBUS_BYTE_DATA: + ret = mei_TxRx(priv->sensorbus, addr, command, read_write, size, data, pec); + xact = I801_BYTE_DATA; + break; + case I2C_SMBUS_WORD_DATA: + ret = mei_TxRx(priv->sensorbus, addr, command, read_write, size, data, pec); + xact = I801_WORD_DATA; + break; + case I2C_SMBUS_BLOCK_DATA: + ret = mei_TxRx(priv->sensorbus, addr, command, read_write, size, data, pec); + break; + case I2C_SMBUS_I2C_BLOCK_DATA: + printk("I2C_SMBUS_I2C_BLOCK_DATA unsupported!!%d\n",size); + break; + default: + dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n", + size); + return -EOPNOTSUPP; + } + + if (ret) + return ret; + return 0; +} + +static u32 mei_i2c_func(struct i2c_adapter *adapter) +{ + struct mei_smb_priv *priv = i2c_get_adapdata(adapter); + + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA ; +} + +static const struct i2c_algorithm smbus_algorithm = { + .smbus_xfer = mei_i2c_access, + .functionality = mei_i2c_func, +}; + +static const struct pci_device_id mei_i2c_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LPT_H) }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, mei_i2c_ids); + +/* richard + priv_table */ +struct mei_smb_priv_table { + struct mei_smb_priv *priv_tbl[MEI_SMB_BUS_SMLINK4]; + int count; +}; + +static int mei_i2c_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + unsigned char temp; + int err, i; + struct mei_smb_priv *priv_sml_0, *priv_sml_1, *priv_sml_2, *priv_sml_3, *priv_sml_4, *priv_smb; + +//richard + priv_table + struct mei_smb_priv_table *priv_table; + + priv_table = kzalloc(sizeof(*priv_table), GFP_KERNEL); + if(!priv_table) + return -ENOMEM; + + priv_sml_0= kzalloc(sizeof(struct mei_smb_priv), GFP_KERNEL); + if (!priv_sml_0) + return -ENOMEM; + i2c_set_adapdata(&priv_sml_0->adapter, priv_sml_0); + priv_sml_0->adapter.owner = THIS_MODULE; + priv_sml_0->adapter.algo = &smbus_algorithm; + priv_sml_0->adapter.dev.parent = &pdev->dev; + priv_sml_0->adapter.retries = 3; + priv_sml_0->sensorbus = MEI_SMB_BUS_SMLINK0; + priv_sml_0->pci_dev = pdev; + + priv_sml_1 = kzalloc(sizeof(*priv_sml_1), GFP_KERNEL); + if (!priv_sml_1) + return -ENOMEM; + i2c_set_adapdata(&priv_sml_1->adapter, priv_sml_1); + priv_sml_1->adapter.owner = THIS_MODULE; + priv_sml_1->adapter.algo = &smbus_algorithm; + priv_sml_1->adapter.dev.parent = &pdev->dev; + priv_sml_1->adapter.retries = 3; + priv_sml_1->sensorbus = MEI_SMB_BUS_SMLINK1; + priv_sml_1->pci_dev = pdev; + + priv_sml_2 = kzalloc(sizeof(*priv_sml_2), GFP_KERNEL); + if (!priv_sml_2) + return -ENOMEM; + i2c_set_adapdata(&priv_sml_2->adapter, priv_sml_2); + priv_sml_2->adapter.owner = THIS_MODULE; + priv_sml_2->adapter.algo = &smbus_algorithm; + priv_sml_2->adapter.dev.parent = &pdev->dev; + priv_sml_2->adapter.retries = 3; + priv_sml_2->sensorbus = MEI_SMB_BUS_SMLINK2; + priv_sml_2->pci_dev = pdev; + + priv_sml_3 = kzalloc(sizeof(*priv_sml_3), GFP_KERNEL); + if (!priv_sml_3) + return -ENOMEM; + i2c_set_adapdata(&priv_sml_3->adapter, priv_sml_3); + priv_sml_3->adapter.owner = THIS_MODULE; + priv_sml_3->adapter.algo = &smbus_algorithm; + priv_sml_3->adapter.dev.parent = &pdev->dev; + priv_sml_3->adapter.retries = 3; + priv_sml_3->sensorbus = MEI_SMB_BUS_SMLINK3; + priv_sml_3->pci_dev = pdev; + + priv_sml_4 = kzalloc(sizeof(*priv_sml_4), GFP_KERNEL); + if (!priv_sml_4) + return -ENOMEM; + i2c_set_adapdata(&priv_sml_4->adapter, priv_sml_4); + priv_sml_4->adapter.owner = THIS_MODULE; + priv_sml_4->adapter.algo = &smbus_algorithm; + priv_sml_4->adapter.dev.parent = &pdev->dev; + priv_sml_4->adapter.retries = 3; + priv_sml_4->sensorbus = MEI_SMB_BUS_SMLINK4; + priv_sml_4->pci_dev = pdev; + + printk("mei_i2c_probe 0x%x 0x%x\n", pdev->device, pdev->dev.id); + + snprintf(priv_sml_0->adapter.name, sizeof(priv_sml_0->adapter.name), + "ME-SMLINK0"); + err = i2c_add_adapter(&priv_sml_0->adapter); + printk("i2c nr : %d \n", priv_sml_0->adapter.nr); + if (err) { + dev_err(&pdev->dev, "Failed to add SMBus adapter ME-SMLINK0\n"); + return err; + } + + snprintf(priv_sml_1->adapter.name, sizeof(priv_sml_1->adapter.name), + "ME-SMLINK1"); + err = i2c_add_adapter(&priv_sml_1->adapter); + if (err) { + dev_err(&pdev->dev, "Failed to add SMBus adapter ME-SMLINK1\n"); + return err; + } + + snprintf(priv_sml_2->adapter.name, sizeof(priv_sml_2->adapter.name), + "ME-SMLINK2"); + err = i2c_add_adapter(&priv_sml_2->adapter); + if (err) { + dev_err(&pdev->dev, "Failed to add SMBus adapter ME-SMLINK2\n"); + return err; + } + + snprintf(priv_sml_3->adapter.name, sizeof(priv_sml_3->adapter.name), + "ME-SMLINK3"); + err = i2c_add_adapter(&priv_sml_3->adapter); + if (err) { + dev_err(&pdev->dev, "Failed to add SMBus adapter ME-SMLINK3\n"); + return err; + } + + snprintf(priv_sml_4->adapter.name, sizeof(priv_sml_4->adapter.name), + "ME-SMLINK4"); + err = i2c_add_adapter(&priv_sml_4->adapter); + if (err) { + dev_err(&pdev->dev, "Failed to add SMBus adapter ME-SMLINK4\n"); + return err; + } + + priv_table->count = 0; + priv_table->priv_tbl[priv_table->count++] = priv_sml_0; + priv_table->priv_tbl[priv_table->count++] = priv_sml_1; + priv_table->priv_tbl[priv_table->count++] = priv_sml_2; + priv_table->priv_tbl[priv_table->count++] = priv_sml_3; + priv_table->priv_tbl[priv_table->count++] = priv_sml_4; + + pci_set_drvdata(pdev, priv_table); + + return 0; +} + +static void mei_i2c_remove(struct pci_dev *dev) +{ + struct mei_smb_priv *priv = pci_get_drvdata(dev); + // richard + priv_table + struct mei_smb_priv_table *priv_table = pci_get_drvdata(dev); + int i; + + for(i=0; icount; i++) { + i2c_del_adapter(&priv_table->priv_tbl[i]->adapter); + } + pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); + + /* + * do not call pci_disable_device(dev) since it can cause hard hangs on + * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010) + */ +} + +#define mei_i2c_suspend NULL +#define mei_i2c_resume NULL + +static struct pci_driver mei_i2c_driver = { + .name = "mei_i2c", + .id_table = mei_i2c_ids, + .probe = mei_i2c_probe, + .remove = mei_i2c_remove, + .suspend = mei_i2c_suspend, + .resume = mei_i2c_resume, +}; + +static int __init mei_i2c_init(void) +{ + int ret = 16; + u32 status = 0; + struct pci_dev *pdev = NULL; + struct mei_device *dev; + struct pci_driver *pci_drv; + + return pci_register_driver(&mei_i2c_driver); +} + +static void __exit mei_i2c_exit(void) +{ + pci_unregister_driver(&mei_i2c_driver); +} + +MODULE_AUTHOR("Delta Networks, Inc."); +MODULE_DESCRIPTION("MEI SMBus driver"); +MODULE_LICENSE("GPL"); + +module_init(mei_i2c_init); +module_exit(mei_i2c_exit); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_rw.c b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_rw.c new file mode 100644 index 000000000000..215df220f096 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_rw.c @@ -0,0 +1,591 @@ +#include "i2c-mei_rw.h" + +#define MicroSecondDelay(time) udelay(time) + +/****** Parameter *****/ + +/****** Struct *****/ +typedef struct +{ + volatile UINT32 CB_WW; // Circular Buffer Write Window + volatile UINT32 H_CSR; // Host Control and Status Register + volatile UINT32 CB_RW; // Circular Buffer Read Window + volatile UINT32 ME_CSR; // ME Control and Status Register (read only) +} HECI_MBAR_REGS; + + +typedef union +{ + UINT32 DWord; + struct + { + UINT32 H_IE : 1, // 0 - Interrupt Enable ME + H_IS : 1, // 1 - Interrupt Status ME + H_IG : 1, // 2 - Interrupt Generate + H_RDY : 1, // 3 - Ready + H_RST : 1, // 4 - Reset + Reserved: 3, // 5~7 + H_CBRP : 8, // 8~15 - CB Read Pointer + H_CBWP : 8, // 16~23 - CB Write Pointer + H_CBD : 8; // 24~31 - Circular Buffer Depth + } Bits; +} HECI_HOST_CSR; + +// HECI_MBAR_REGS::ME_CSR - ME Control and Status Register +typedef union +{ + UINT32 DWord; + struct + { + UINT32 ME_IE : 1, // 0 - Interrupt Enable (Host Read Access) + ME_IS : 1, // 1 - Interrupt Status (Host Read Access) + ME_IG : 1, // 2 - Interrupt Generate (Host Read Access) + ME_RDY : 1, // 3 - Ready (Host Read Access) + ME_RST : 1, // 4 - Reset (Host Read Access) + Reserved: 3, // 5~7 + ME_CBRP : 8, // 8~15 - CB Read Pointer (Host Read Access) + ME_CBWP : 8, // 16~23 - CB Write Pointer (Host Read Access) + ME_CBD : 8; // 24~31 - Circular Buffer Depth (Host Read Access) + } Bits; +} HECI_ME_CSR; + +/****** Function *****/ +VOID* HeciMbarRead(IN HECI_DEVICE *pThis); +VOID HeciTrace(IN HECI_DEVICE*, IN CHAR8*, IN HECI_MSG_HEADER*, IN INT32); + +EFI_STATUS HeciInit ( HECI_DEVICE *pThis, + UINT32 *pTimeout) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT32 Timeout = 0; + HECI_HOST_CSR sHCsr; + HECI_ME_CSR sMeCsr; + HECI_MBAR_REGS *pMbarRegs; + VOID *pAddrPoint; + + if (pThis == NULL || (pThis->Mbar & 0xF) != 0 || pThis->Hidm > HECI_HIDM_LAST) + { + printk("Heci Init Failed"); + return EFI_INVALID_PARAMETER; + } + if (pTimeout != NULL) + { + Timeout = *pTimeout; + } + + // HECI vendor and device information away + pThis->PciCfg = PCI_LIB_ADDRESS(pThis->Bus, pThis->Dev, pThis->Fun, 0); + pThis->Vid = PciRead16(pThis->PciCfg + HECI_REG_VENDORID); + pThis->Did = PciRead16(pThis->PciCfg + HECI_REG_DEVICEID); + + if (pThis->Vid != 0x8086) + { + printk("[HECI] Init failed, PCI device %d/%d/%d not valid HECI (%2X-%2X)\n", + pThis->Bus, pThis->Dev, pThis->Fun, pThis->Vid, pThis->Did); + return EFI_DEVICE_ERROR; + } + + // Check MBAR, + pAddrPoint = HeciMbarRead(pThis); + pMbarRegs = (HECI_MBAR_REGS*)ioremap_nocache(pAddrPoint, 0x1000); + if (pMbarRegs == NULL) + { + printk("[HECI-%d] Init failed (device disabled)\n", pThis->Fun); + printk("Check MBAR Failed"); + Status = EFI_DEVICE_ERROR; + goto GO_FAIL; + } + + // Set HECI interrupt delivery mode. + sHCsr.DWord = pMbarRegs->H_CSR; + sHCsr.Bits.H_IE = 0; + pMbarRegs->H_CSR = sHCsr.DWord; + PciWrite8(pThis->PciCfg + HECI_REG_HIDM, pThis->Hidm); + + // Check HECI was free + sMeCsr.DWord = pMbarRegs->ME_CSR; + if (!sMeCsr.Bits.ME_RDY) + { + Status = HecClearQue(pThis, &Timeout); + } + else + { + if (!sHCsr.Bits.H_RDY) + { + sHCsr.Bits.H_IG = 1; + sHCsr.Bits.H_RDY = 1; + sHCsr.Bits.H_RST = 0; + pMbarRegs->H_CSR = sHCsr.DWord; + } + pThis->HMtu = sHCsr.Bits.H_CBD * sizeof(UINT32) - sizeof(HECI_MSG_HEADER); + pThis->MeMtu = sMeCsr.Bits.ME_CBD * sizeof(UINT32) - sizeof(HECI_MSG_HEADER); + } + + GO_FAIL: + if (pTimeout != NULL) + { + *pTimeout = Timeout; + } + pThis->Mefs1.DWord = HeciPciReadMefs1(); + iounmap((VOID *)pMbarRegs); + return Status; +} + +EFI_STATUS HecClearQue ( HECI_DEVICE *pThis, + UINT32 *pTimeout) +{ + EFI_STATUS Status; + UINT32 Timeout = 0; + HECI_HOST_CSR sHCsr; + HECI_ME_CSR sMeCsr; + HECI_MBAR_REGS *pMbarRegs; + VOID *pAddrPoint; + + if (pThis == NULL) + { + printk("Failed"); + return EFI_INVALID_PARAMETER; + } + + // Check for HECI availability on PCI + pAddrPoint = HeciMbarRead(pThis); + pMbarRegs = (HECI_MBAR_REGS*)ioremap_nocache(pAddrPoint, 0x1000); + printk("pMbarRegs: %x\n", pMbarRegs); + + if (pMbarRegs == NULL) + { + printk("[HECI-%d] Reset failed (device disabled)\n", pThis->Fun); + printk("Failed"); + return EFI_DEVICE_ERROR; + } + if (pTimeout != NULL) + { + Timeout = *pTimeout; + } + printk("[HECI-%d] Resetting HECI interface (CSR %X/%X)\n", + pThis->Fun, pMbarRegs->H_CSR, pMbarRegs->ME_CSR); + + sHCsr.DWord = pMbarRegs->H_CSR; + if (!sHCsr.Bits.H_RST) + { + sHCsr.Bits.H_RST = 1; + sHCsr.Bits.H_IG = 1; + pMbarRegs->H_CSR = sHCsr.DWord; + } + + // Wait for H_RDY cleared to make sure that the reset started. + while (1) + { + sHCsr.DWord = pMbarRegs->H_CSR; + if (!sHCsr.Bits.H_RDY) + { + break; + } + if (Timeout == 0) + { + printk("[HECI-%d] Reset failed (timeout)(CSR %X/%X)\n", + pThis->Fun, pMbarRegs->H_CSR, pMbarRegs->ME_CSR); + Status = EFI_TIMEOUT; + goto GO_FAIL; + } + MicroSecondDelay(HECI_TIMEOUT_UNIT); + Timeout--; + } + + // Wait for ME to perform reset and signal it is ready. + while (1) + { + sMeCsr.DWord = pMbarRegs->ME_CSR; + if (sMeCsr.Bits.ME_RDY) + { + break; + } + if (Timeout == 0) + { + printk("[HECI-%d] Reset failed (timeout)(CSR %X/%X)\n", + pThis->Fun, pMbarRegs->H_CSR, pMbarRegs->ME_CSR); + Status = EFI_TIMEOUT; + goto GO_FAIL; + } + MicroSecondDelay(HECI_TIMEOUT_UNIT); + Timeout--; + } + + // ME side is ready, signal host side is ready too. + sHCsr.DWord = pMbarRegs->H_CSR; + sHCsr.Bits.H_RST = 0; + sHCsr.Bits.H_RDY = 1; + sHCsr.Bits.H_IG = 1; + pMbarRegs->H_CSR = sHCsr.DWord; + + // Update MTU, ME could change it during reset. + pThis->HMtu = sHCsr.Bits.H_CBD * sizeof(UINT32) - sizeof(HECI_MSG_HEADER); + pThis->MeMtu = sMeCsr.Bits.ME_CBD * sizeof(UINT32) - sizeof(HECI_MSG_HEADER); + Status = EFI_SUCCESS; + +GO_FAIL: + if (pTimeout != NULL) + { + *pTimeout = Timeout; + } + pThis->Mefs1.DWord = HeciPciReadMefs1(); + iounmap((VOID *)pMbarRegs); + return Status; +} + +EFI_STATUS HeciMsgRecv ( HECI_DEVICE *pThis, + UINT32 *pTimeout, + HECI_MSG_HEADER *pMsgBuf, + UINT32 *pBufLen ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT32 Timeout = 0; + UINT32 DWord, dwDataReads, dwBufLen; + UINT8 bFilledSlots, bMsgLen = 0; + HECI_HOST_CSR sHCsr; + HECI_ME_CSR sMeCsr; + HECI_MBAR_REGS *pMbarRegs; + VOID *pAddrPoint; + + if (pThis == NULL || pMsgBuf == NULL || + pBufLen == NULL || *pBufLen < sizeof(HECI_MSG_HEADER)) + { + printk("Heci MsgRecv Failed\n"); + return EFI_INVALID_PARAMETER; + } + + // Check for HECI availability on PCI + pAddrPoint = HeciMbarRead(pThis); + pMbarRegs = (HECI_MBAR_REGS*)ioremap_nocache(pAddrPoint, 0x1000); + if (pMbarRegs == NULL) + { + printk("[HECI-%d] Receive failed (device disabled)\n", pThis->Fun); + printk("pMbarRegs Failed\n"); + return EFI_DEVICE_ERROR; + } + if (pTimeout != NULL) + { + Timeout = *pTimeout; + } + + + // read from queue. + dwBufLen = *pBufLen; + *pBufLen = dwDataReads = 0; + while (1) + { + sHCsr.DWord = pMbarRegs->H_CSR; + sMeCsr.DWord = pMbarRegs->ME_CSR; + + bFilledSlots = (UINT8)((INT8)sMeCsr.Bits.ME_CBWP - (INT8)sMeCsr.Bits.ME_CBRP); + // Is it ready ? + if (!sMeCsr.Bits.ME_RDY || !sHCsr.Bits.H_RDY || bFilledSlots > sHCsr.Bits.H_CBD) + { + Status = HecClearQue(pThis, &Timeout); + if (EFI_ERROR(Status)) + { + goto GO_FAIL; + } + continue; + } + + // Read queue + while (bFilledSlots-- > 0) + { + + DWord = pMbarRegs->CB_RW; + if (*pBufLen < dwBufLen) + { + + if (dwDataReads < dwBufLen / sizeof(UINT32)) + { + ((UINT32*)pMsgBuf)[dwDataReads] = DWord; + *pBufLen += sizeof(UINT32); + } + else + { + switch (dwBufLen % sizeof(UINT32)) + { + case 3: ((UINT8*)pMsgBuf)[*pBufLen + 2] = (UINT8)(DWord >> 16); + case 2: ((UINT8*)pMsgBuf)[*pBufLen + 1] = (UINT8)(DWord >> 8); + case 1: ((UINT8*)pMsgBuf)[*pBufLen + 0] = (UINT8)DWord; + } + *pBufLen += dwBufLen % sizeof(UINT32); + } + } + else + { + printk("[HECI-%d] Message 0x%08X exceeds buffer size (%dB)\n", + pThis->Fun, pMsgBuf[0].DWord, dwBufLen); + } + dwDataReads++; + + // Read message length. + if (bMsgLen == 0) + { + bMsgLen = (UINT8)((pMsgBuf[0].Bits.Length + sizeof(UINT32) - 1) / sizeof(UINT32)); + bMsgLen++; // One more double word for message header + // + // Sanity check. If message length exceeds queue length this is + // not valid header. We are out of synch, let's reset the queue. + // + if (bMsgLen > sMeCsr.Bits.ME_CBD) + { + printk("[HECI-%d] 0x%08X does not seem to be msg header, reseting...\n", + pThis->Fun, pMsgBuf[0].DWord); + Status = HecClearQue(pThis, &Timeout); + if (EFI_ERROR(Status)) + { + goto GO_FAIL; + } + *pBufLen = dwDataReads = bMsgLen = 0; + break; // while (bFilledSlots) + } + } + + // If message is complete set interrupt to ME to let it know that next + // message can be sent and exit. + if (dwDataReads >= bMsgLen) + { + + sMeCsr.DWord = pMbarRegs->ME_CSR; + sHCsr.DWord = pMbarRegs->H_CSR; + if (!sMeCsr.Bits.ME_RDY) + { + HecClearQue(pThis, &Timeout); + Status = EFI_ABORTED; + } + else + { + HeciTrace(pThis, " Got msg: ", pMsgBuf, *pBufLen); + sHCsr.Bits.H_IG = 1; + pMbarRegs->H_CSR = sHCsr.DWord; + } + goto GO_FAIL; + } + } + if (Timeout == 0) + { + printk("[HECI-%d] Receive failed (timeout)\n", pThis->Fun); + Status = EFI_TIMEOUT; + goto GO_FAIL; + } + MicroSecondDelay(HECI_TIMEOUT_UNIT); + Timeout--; + } + GO_FAIL: + if (pTimeout != NULL) + { + *pTimeout = Timeout; + } + pThis->Mefs1.DWord = HeciPciReadMefs1(); + iounmap((VOID *)pMbarRegs); + return Status; +} + +EFI_STATUS HeciMsgSend ( HECI_DEVICE *pThis, + UINT32 *pTimeout, + HECI_MSG_HEADER *pMessage) +{ + EFI_STATUS Status; + UINT32 Timeout = 0; + UINT8 bEmptySlots; + UINT8 i, bMsgLen; + HECI_HOST_CSR sHCsr; + HECI_ME_CSR sMeCsr; + HECI_MBAR_REGS *pMbarRegs; + VOID *pAddrPoint; + + if (pThis == NULL || pMessage == NULL) + { + printk("HeciMsgSend Failed\n"); + return EFI_INVALID_PARAMETER; + } + HeciTrace(pThis, "Send msg: ", pMessage, sizeof(HECI_MSG_HEADER) + pMessage->Bits.Length); + + // Check for HECI availability + pAddrPoint = HeciMbarRead(pThis); + pMbarRegs = (HECI_MBAR_REGS*)ioremap_nocache(pAddrPoint, 0x1000); + if (pMbarRegs == NULL) + { + printk("[HECI-%d] Send failed (device disabled)\n", pThis->Fun); + printk("Failed\n"); + return EFI_DEVICE_ERROR; + } + if (pTimeout != NULL) + { + Timeout = *pTimeout; + } + + bMsgLen = (UINT8)((pMessage->Bits.Length + sizeof(UINT32) - 1) / sizeof(UINT32)); + bMsgLen++; //message header + while (1) + { + sHCsr.DWord = pMbarRegs->H_CSR; + sMeCsr.DWord = pMbarRegs->ME_CSR; + + // If message is more than queue length go fail. + if (bMsgLen > sHCsr.Bits.H_CBD) + { + printk("[HECI-%d] Send failed (msg %d B, queue %d B only)\n", + pThis->Fun, pMessage->Bits.Length, sHCsr.Bits.H_CBD * sizeof(UINT32)); + Status = EFI_BAD_BUFFER_SIZE; + goto GO_FAIL; + } + bEmptySlots = (UINT8)sHCsr.Bits.H_CBD - + (UINT8)((INT8)sHCsr.Bits.H_CBWP - (INT8)sHCsr.Bits.H_CBRP); + + // Is it ready ? + if (!sMeCsr.Bits.ME_RDY || !sHCsr.Bits.H_RDY || bEmptySlots > sHCsr.Bits.H_CBD) + { + Status = HecClearQue(pThis, &Timeout); + if (EFI_ERROR(Status)) + { + goto GO_FAIL; + } + continue; + } + + if (bMsgLen <= bEmptySlots) + { + for (i = 0; i < bMsgLen; i++) + { + pMbarRegs->CB_WW = ((UINT32*)pMessage)[i]; + } + + + sMeCsr.DWord = pMbarRegs->ME_CSR; + if (!sMeCsr.Bits.ME_RDY) + { + printk("[HECI-%d] Queue has been reset while sending\n", pThis->Fun); + continue; + } + + sHCsr.DWord = pMbarRegs->H_CSR; + sHCsr.Bits.H_IS = 0; + sHCsr.Bits.H_IG = 1; + pMbarRegs->H_CSR = sHCsr.DWord; + Status = EFI_SUCCESS; + goto GO_FAIL; + } + + + if (Timeout == 0) + { + printk("[HECI-%d] Send failed (timeout)\n", pThis->Fun); + Status = EFI_TIMEOUT; + goto GO_FAIL; + } + MicroSecondDelay(HECI_TIMEOUT_UNIT); + Timeout--; + } + GO_FAIL: + if (pTimeout != NULL) + { + *pTimeout = Timeout; + } + pThis->Mefs1.DWord = HeciPciReadMefs1(); + iounmap((VOID *)pMbarRegs); + return Status; +} + + +VOID *HeciMbarRead(HECI_DEVICE *pThis) +{ + VOID *start; + + UINT16 Cmd; + union + { + UINT64 QWord; + struct + { + UINT32 DWordL; + UINT32 DWordH; + } Bits; + } Mbar; + + // + // Read MBAR. + Mbar.QWord = 0; + Mbar.Bits.DWordL = PciRead32(pThis->PciCfg + HECI_REG_MBAR); + if (Mbar.Bits.DWordL == 0xFFFFFFFF) + { + printk("[HECI-%d] Device disabled\n", pThis->Fun); + Mbar.Bits.DWordL = 0; + goto GO_FAIL; + } + if (Mbar.Bits.DWordL & 0x4) // if 64-bit address add the upper half + { + Mbar.Bits.DWordH = PciRead32(pThis->PciCfg + HECI_REG_MBAR + 4); + } + Mbar.Bits.DWordL &= 0xFFFFFFF0; + if (Mbar.QWord == 0) + { + if (pThis->Mbar == 0) + { + printk("[HECI-%d] MBAR not programmed\n", pThis->Fun); + goto GO_FAIL; + } + else + { + Mbar.QWord = pThis->Mbar; + printk("[HECI-%d] MBAR not programmed, using default 0x%08X%08X\n", + pThis->Fun, Mbar.Bits.DWordH, Mbar.Bits.DWordL); + + // Programm the MBAR, set the 64-bit support bit regardless of the size + // of the address currently used. + PciWrite32(pThis->PciCfg + HECI_REG_MBAR + 4, Mbar.Bits.DWordH); + PciWrite32(pThis->PciCfg + HECI_REG_MBAR, Mbar.Bits.DWordL | 4); + } + } + else + { + pThis->Mbar = Mbar.QWord; + } + + // Enable the MBAR + Cmd = PciRead16(pThis->PciCfg + HECI_REG_COMMAND); + if (!(Cmd & HECI_CMD_MSE)) + { + PciWrite16(pThis->PciCfg + HECI_REG_COMMAND, Cmd | HECI_CMD_BME | HECI_CMD_MSE); + } + GO_FAIL: + return (VOID*)(INTN)Mbar.QWord; +} + + + +VOID HeciTrace( HECI_DEVICE *pThis, + CHAR8 *pPrefix, + HECI_MSG_HEADER *pMsg, + INT32 MsgLen) +{ +#if 0 /// Trace Enable or Disable + if (MsgLen > 4) + { + UINT32 dwLineBreak = 0; + UINT32 dwIndex = 0; + UINT8 *pMsgBody = (UINT8*)&pMsg[1]; + + MsgLen -= 4; + while (MsgLen-- > 0) + { + if (dwLineBreak == 0) + printk("%02x: ", (dwIndex & 0xF0)); + printk("%02x ", pMsgBody[dwIndex++]); + dwLineBreak++; + if (dwLineBreak == 16) + { + printk("\n"); + dwLineBreak = 0; + } + if (dwLineBreak == 8) + { + printk("-"); + } + } + printk("\n"); + } +#endif +} \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_rw.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_rw.h new file mode 100644 index 000000000000..a22728c058fe --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_rw.h @@ -0,0 +1,143 @@ + +#include "i2c-mei_io.h" + +/****** Parameter *****/ + +#define HECI_READ_TIMEOUT 12500000 // 12.5sec +#define HECI_SEND_TIMEOUT 12500000 // 12.5sec +#define HECI_TIMEOUT_UNIT 10 + + +// HECI functions location +#define HECI_BUS 0 +#define HECI_DEV 22 +#define HECI_FUN 0 + +// HECI register +#define HECI_REG_VENDORID 0x00 +#define HECI_REG_DEVICEID 0x02 +#define HECI_REG_COMMAND 0x04 +#define HECI_REG_REVID 0x08 +#define HECI_REG_MBAR 0x10 +#define HECI_REG_IRQ 0x3C +#define HECI_REG_HIDM 0xA0 +#define HECI_REG_HFS 0x40 +#define HECI_REG_MISC_SHDW 0x44 +#define HECI_REG_GS_SHDW 0x48 +#define HECI_REG_H_GS 0x4C +#define HECI_REG_GS_SHDW2 0x60 +#define HECI_REG_GS_SHDW3 0x64 +#define HECI_REG_GS_SHDW4 0x68 +#define HECI_REG_GS_SHDW5 0x6C +#define HECI_REG_H_GS2 0x70 +#define HECI_REG_H_GS3 0x74 +#define HECI_REG_MEFS1 HECI_REG_HFS +#define HECI_REG_MEFS2 HECI_REG_GS_SHDW + +#define HECI_MBAR_DEFAULT 0xFEDB0000 + +// HECI Interrupt Delivery Mode to be set in HECI_REG_HIDM. +#define HECI_HIDM_MSI 0 +#define HECI_HIDM_SCI 1 +#define HECI_HIDM_SMI 2 +#define HECI_HIDM_LAST HECI_HIDM_SMI + +// HECI command register bits +#define HECI_CMD_BME 0x04 // Bus master enable +#define HECI_CMD_MSE 0x02 // Memory space enable + + +/****** Struct *****/ + +typedef union +{ + UINT32 DWord; + struct + { + UINT32 MeAddress : 8, // Addressee on ME side + HostAddress: 8, // Addressee on host siede, zero for BIOS + Length : 9, // Number of bytes following the header + Reserved : 6, + MsgComplete: 1; // Whether this is last fragment of a message + } Bits; +} HECI_MSG_HEADER; + +// ME Firmware Status 1 register basics. offset:40h +typedef union +{ + UINT32 DWord; + struct + { + UINT32 CurrentState : 4, // 0~3 Current ME firmware state + Reserved_5 : 5, // 4~8 + InitComplete : 1, // 9 ME firmware finished initialization + Reserved_10 : 2, // 10~11 + ErrorCode : 4, // 12~15 If set means fatal error + OperatingMode: 4, // 16~19 Current ME operating mode + Reserved_20 : 5, // 20~24 + MsgAckData : 3, // 25~27 MSG ACK Data specific for acknowledged BIOS message + MsgAck : 4; // 28~31 Acknowledge for register based BIOS message + } Bits; +} HECI_MEFS1; + + +typedef struct +{ + + UINT8 Bus; // PCI bus + UINT8 Dev; // PCI device + UINT8 Fun; // PCI function number + + UINTN PciCfg; + UINT16 Vid; // Device ID + UINT16 Did; // Vendor ID + UINT8 Hidm; // interrupt mode + UINT64 Mbar; + UINT32 HMtu; // Max transfer unit configured by ME minus header + UINT32 MeMtu; // Max transfer unit configured by ME minus header + HECI_MEFS1 Mefs1; // ME Firmware Status at recent operation +} HECI_DEVICE; + +/****** Function *****/ + + + +/** + * @param pThis Pointer to HECI device structure + * @param pTimeout On input timeout in ms, on exit time left + */ +EFI_STATUS HeciInit ( HECI_DEVICE *pThis, + UINT32 *pTimeout); + +/** + * @param pThis Pointer to HECI device structure + * @param pTimeout On input timeout in ms, on exit time left + */ +EFI_STATUS HecClearQue ( HECI_DEVICE *pThis, + UINT32 *pTimeout); + +/** + * @param pThis Pointer to HECI device structure + * @param pTimeout On input timeout in ms, on exit time left + * @param pMsgBuf Buffer for the received message + * @param pBufLen On input buffer size, on exit message, in bytes + */ +EFI_STATUS HeciMsgRecv ( HECI_DEVICE *pThis, + UINT32 *pTimeout, + HECI_MSG_HEADER *pMsgBuf, + UINT32 *pBufLen ); + + + +/** + * @param pThis Pointer to HECI device structure + * @param pTimeout On input timeout in ms, on exit time left + * @param pMessage The header of the message to send + */ +EFI_STATUS HeciMsgSend ( HECI_DEVICE *pThis, + UINT32 *pTimeout, + HECI_MSG_HEADER *pMessage); + + + +#define HeciPciReadMefs1() PciRead32(PCI_LIB_ADDRESS(HECI_BUS, HECI_DEV, HECI_FUN, HECI_REG_MEFS1)) \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_type.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_type.h new file mode 100644 index 000000000000..e9b60c7573d5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_type.h @@ -0,0 +1,448 @@ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef EFIAPI +#define EFIAPI +#endif + + // + // Assume standard AARCH64 alignment. + // + typedef unsigned long long UINT64; + typedef long long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef signed char INT8; + +/// +/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// + typedef UINT64 UINTN; + +/// +/// Signed value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// + typedef INT64 INTN; + + + +/* ========== ProcessBind.h ========= */ + +/// +/// A value of native width with the highest bit set. +/// +#define MAX_BIT 0x8000000000000000ULL + + + +/* ========== Base.h ========= */ + +// +// Modifiers to abstract standard types to aid in debug of problems +// + +/// +/// Datum is read-only. +/// +#define CONST const + +/// +/// Datum is scoped to the current file or function. +/// +#define STATIC static + +/// +/// Undeclared type. +/// +#define VOID void + +// +// Modifiers for Data Types used to self document code. +// This concept is borrowed for UEFI specification. +// + +/// +/// Datum is passed to the function. +/// +#define IN + +/// +/// Datum is returned from the function. +/// +#define OUT + +/// +/// Passing the datum to the function is optional, and a NULL +/// is passed if the value is not supplied. +/// +#define OPTIONAL + +// +// UEFI specification claims 1 and 0. We are concerned about the +// complier portability so we did it this way. +// + +/// +/// Boolean true value. UEFI Specification defines this value to be 1, +/// but this form is more portable. +/// +#define TRUE ((BOOLEAN)(1==1)) + +/// +/// Boolean false value. UEFI Specification defines this value to be 0, +/// but this form is more portable. +/// +#define FALSE ((BOOLEAN)(0==1)) + +/// +/// NULL pointer (VOID *) +/// +#define NULL ((VOID *) 0) + +// +// Status codes common to all execution phases +// +typedef UINTN RETURN_STATUS; + +/** + Produces a RETURN_STATUS code with the highest bit set. + + @param StatusCode The status code value to convert into a warning code. + StatusCode must be in the range 0x00000000..0x7FFFFFFF. + + @return The value specified by StatusCode with the highest bit set. + +**/ +#define ENCODE_ERROR(StatusCode) ((RETURN_STATUS)(MAX_BIT | (StatusCode))) + +/** + Produces a RETURN_STATUS code with the highest bit clear. + + @param StatusCode The status code value to convert into a warning code. + StatusCode must be in the range 0x00000000..0x7FFFFFFF. + + @return The value specified by StatusCode with the highest bit clear. + +**/ +#define ENCODE_WARNING(StatusCode) ((RETURN_STATUS)(StatusCode)) + +/** + Returns TRUE if a specified RETURN_STATUS code is an error code. + + This function returns TRUE if StatusCode has the high bit set. Otherwise, FALSE is returned. + + @param StatusCode The status code value to evaluate. + + @retval TRUE The high bit of StatusCode is set. + @retval FALSE The high bit of StatusCode is clear. + +**/ +#define RETURN_ERROR(StatusCode) (((INTN)(RETURN_STATUS)(StatusCode)) < 0) + +/// +/// The operation completed successfully. +/// +#define RETURN_SUCCESS 0 + +/// +/// The image failed to load. +/// +#define RETURN_LOAD_ERROR ENCODE_ERROR (1) + +/// +/// The parameter was incorrect. +/// +#define RETURN_INVALID_PARAMETER ENCODE_ERROR (2) + +/// +/// The operation is not supported. +/// +#define RETURN_UNSUPPORTED ENCODE_ERROR (3) + +/// +/// The buffer was not the proper size for the request. +/// +#define RETURN_BAD_BUFFER_SIZE ENCODE_ERROR (4) + +/// +/// The buffer was not large enough to hold the requested data. +/// The required buffer size is returned in the appropriate +/// parameter when this error occurs. +/// +#define RETURN_BUFFER_TOO_SMALL ENCODE_ERROR (5) + +/// +/// There is no data pending upon return. +/// +#define RETURN_NOT_READY ENCODE_ERROR (6) + +/// +/// The physical device reported an error while attempting the +/// operation. +/// +#define RETURN_DEVICE_ERROR ENCODE_ERROR (7) + +/// +/// The device can not be written to. +/// +#define RETURN_WRITE_PROTECTED ENCODE_ERROR (8) + +/// +/// The resource has run out. +/// +#define RETURN_OUT_OF_RESOURCES ENCODE_ERROR (9) + +/// +/// An inconsistency was detected on the file system causing the +/// operation to fail. +/// +#define RETURN_VOLUME_CORRUPTED ENCODE_ERROR (10) + +/// +/// There is no more space on the file system. +/// +#define RETURN_VOLUME_FULL ENCODE_ERROR (11) + +/// +/// The device does not contain any medium to perform the +/// operation. +/// +#define RETURN_NO_MEDIA ENCODE_ERROR (12) + +/// +/// The medium in the device has changed since the last +/// access. +/// +#define RETURN_MEDIA_CHANGED ENCODE_ERROR (13) + +/// +/// The item was not found. +/// +#define RETURN_NOT_FOUND ENCODE_ERROR (14) + +/// +/// Access was denied. +/// +#define RETURN_ACCESS_DENIED ENCODE_ERROR (15) + +/// +/// The server was not found or did not respond to the request. +/// +#define RETURN_NO_RESPONSE ENCODE_ERROR (16) + +/// +/// A mapping to the device does not exist. +/// +#define RETURN_NO_MAPPING ENCODE_ERROR (17) + +/// +/// A timeout time expired. +/// +#define RETURN_TIMEOUT ENCODE_ERROR (18) + +/// +/// The protocol has not been started. +/// +#define RETURN_NOT_STARTED ENCODE_ERROR (19) + +/// +/// The protocol has already been started. +/// +#define RETURN_ALREADY_STARTED ENCODE_ERROR (20) + +/// +/// The operation was aborted. +/// +#define RETURN_ABORTED ENCODE_ERROR (21) + +/// +/// An ICMP error occurred during the network operation. +/// +#define RETURN_ICMP_ERROR ENCODE_ERROR (22) + +/// +/// A TFTP error occurred during the network operation. +/// +#define RETURN_TFTP_ERROR ENCODE_ERROR (23) + +/// +/// A protocol error occurred during the network operation. +/// +#define RETURN_PROTOCOL_ERROR ENCODE_ERROR (24) + +/// +/// A function encountered an internal version that was +/// incompatible with a version requested by the caller. +/// +#define RETURN_INCOMPATIBLE_VERSION ENCODE_ERROR (25) + +/// +/// The function was not performed due to a security violation. +/// +#define RETURN_SECURITY_VIOLATION ENCODE_ERROR (26) + +/// +/// A CRC error was detected. +/// +#define RETURN_CRC_ERROR ENCODE_ERROR (27) + +/// +/// The beginning or end of media was reached. +/// +#define RETURN_END_OF_MEDIA ENCODE_ERROR (28) + +/// +/// The end of the file was reached. +/// +#define RETURN_END_OF_FILE ENCODE_ERROR (31) + +/// +/// The language specified was invalid. +/// +#define RETURN_INVALID_LANGUAGE ENCODE_ERROR (32) + +/// +/// The security status of the data is unknown or compromised +/// and the data must be updated or replaced to restore a valid +/// security status. +/// +#define RETURN_COMPROMISED_DATA ENCODE_ERROR (33) + +/// +/// The string contained one or more characters that +/// the device could not render and were skipped. +/// +#define RETURN_WARN_UNKNOWN_GLYPH ENCODE_WARNING (1) + +/// +/// The handle was closed, but the file was not deleted. +/// +#define RETURN_WARN_DELETE_FAILURE ENCODE_WARNING (2) + +/// +/// The handle was closed, but the data to the file was not +/// flushed properly. +/// +#define RETURN_WARN_WRITE_FAILURE ENCODE_WARNING (3) + +/// +/// The resulting buffer was too small, and the data was +/// truncated to the buffer size. +/// +#define RETURN_WARN_BUFFER_TOO_SMALL ENCODE_WARNING (4) + +/// +/// The data has not been updated within the timeframe set by +/// local policy for this type of data. +/// +#define RETURN_WARN_STALE_DATA ENCODE_WARNING (5) + + + +/* ========== UefiBaseType.h ========= */ + +/// +/// Function return status for EFI API. +/// +typedef RETURN_STATUS EFI_STATUS; + +/// +/// Enumeration of EFI_STATUS. +///@{ +#define EFI_SUCCESS RETURN_SUCCESS +#define EFI_LOAD_ERROR RETURN_LOAD_ERROR +#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER +#define EFI_UNSUPPORTED RETURN_UNSUPPORTED +#define EFI_BAD_BUFFER_SIZE RETURN_BAD_BUFFER_SIZE +#define EFI_BUFFER_TOO_SMALL RETURN_BUFFER_TOO_SMALL +#define EFI_NOT_READY RETURN_NOT_READY +#define EFI_DEVICE_ERROR RETURN_DEVICE_ERROR +#define EFI_WRITE_PROTECTED RETURN_WRITE_PROTECTED +#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES +#define EFI_VOLUME_CORRUPTED RETURN_VOLUME_CORRUPTED +#define EFI_VOLUME_FULL RETURN_VOLUME_FULL +#define EFI_NO_MEDIA RETURN_NO_MEDIA +#define EFI_MEDIA_CHANGED RETURN_MEDIA_CHANGED +#define EFI_NOT_FOUND RETURN_NOT_FOUND +#define EFI_ACCESS_DENIED RETURN_ACCESS_DENIED +#define EFI_NO_RESPONSE RETURN_NO_RESPONSE +#define EFI_NO_MAPPING RETURN_NO_MAPPING +#define EFI_TIMEOUT RETURN_TIMEOUT +#define EFI_NOT_STARTED RETURN_NOT_STARTED +#define EFI_ALREADY_STARTED RETURN_ALREADY_STARTED +#define EFI_ABORTED RETURN_ABORTED +#define EFI_ICMP_ERROR RETURN_ICMP_ERROR +#define EFI_TFTP_ERROR RETURN_TFTP_ERROR +#define EFI_PROTOCOL_ERROR RETURN_PROTOCOL_ERROR +#define EFI_INCOMPATIBLE_VERSION RETURN_INCOMPATIBLE_VERSION +#define EFI_SECURITY_VIOLATION RETURN_SECURITY_VIOLATION +#define EFI_CRC_ERROR RETURN_CRC_ERROR +#define EFI_END_OF_MEDIA RETURN_END_OF_MEDIA +#define EFI_END_OF_FILE RETURN_END_OF_FILE +#define EFI_INVALID_LANGUAGE RETURN_INVALID_LANGUAGE +#define EFI_COMPROMISED_DATA RETURN_COMPROMISED_DATA + +#define EFI_WARN_UNKNOWN_GLYPH RETURN_WARN_UNKNOWN_GLYPH +#define EFI_WARN_DELETE_FAILURE RETURN_WARN_DELETE_FAILURE +#define EFI_WARN_WRITE_FAILURE RETURN_WARN_WRITE_FAILURE +#define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL +#define EFI_WARN_STALE_DATA RETURN_WARN_STALE_DATA +///@} + +/// +/// Define macro to encode the status code. +/// +#define EFIERR(_a) ENCODE_ERROR(_a) + +#define EFI_ERROR(A) RETURN_ERROR(A) + + + +/* ========== BaseLib.h ========= */ + +/// +/// Byte packed structure for EFLAGS/RFLAGS. +/// 32-bits on IA-32. +/// 64-bits on x64. The upper 32-bits on x64 are reserved. +/// +typedef union { + struct { + UINT32 CF:1; ///< Carry Flag. + UINT32 Reserved_0:1; ///< Reserved. + UINT32 PF:1; ///< Parity Flag. + UINT32 Reserved_1:1; ///< Reserved. + UINT32 AF:1; ///< Auxiliary Carry Flag. + UINT32 Reserved_2:1; ///< Reserved. + UINT32 ZF:1; ///< Zero Flag. + UINT32 SF:1; ///< Sign Flag. + UINT32 TF:1; ///< Trap Flag. + UINT32 IF:1; ///< Interrupt Enable Flag. + UINT32 DF:1; ///< Direction Flag. + UINT32 OF:1; ///< Overflow Flag. + UINT32 IOPL:2; ///< I/O Privilege Level. + UINT32 NT:1; ///< Nested Task. + UINT32 Reserved_3:1; ///< Reserved. + UINT32 RF:1; ///< Resume Flag. + UINT32 VM:1; ///< Virtual 8086 Mode. + UINT32 AC:1; ///< Alignment Check. + UINT32 VIF:1; ///< Virtual Interrupt Flag. + UINT32 VIP:1; ///< Virtual Interrupt Pending. + UINT32 ID:1; ///< ID Flag. + UINT32 Reserved_4:10; ///< Reserved. + } Bits; + UINTN UintN; +} IA32_EFLAGS32; \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/mei_dev.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/mei_dev.h new file mode 100644 index 000000000000..4250555d5e72 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/mei_dev.h @@ -0,0 +1,832 @@ +/* + * + * Intel Management Engine Interface (Intel MEI) Linux driver + * Copyright (c) 2003-2012, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + */ + +#ifndef _MEI_DEV_H_ +#define _MEI_DEV_H_ + +#include +#include +#include +#include +#include + +#include "hw.h" +#include "hbm.h" + +/* + * watch dog definition + */ +#define MEI_WD_HDR_SIZE 4 +#define MEI_WD_STOP_MSG_SIZE MEI_WD_HDR_SIZE +#define MEI_WD_START_MSG_SIZE (MEI_WD_HDR_SIZE + 16) + +#define MEI_WD_DEFAULT_TIMEOUT 120 /* seconds */ +#define MEI_WD_MIN_TIMEOUT 120 /* seconds */ +#define MEI_WD_MAX_TIMEOUT 65535 /* seconds */ + +#define MEI_WD_STOP_TIMEOUT 10 /* msecs */ + +#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) + +#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) + + +/* + * AMTHI Client UUID + */ +extern const uuid_le mei_amthif_guid; + +/* + * Watchdog Client UUID + */ +extern const uuid_le mei_wd_guid; + +/* + * Number of Maximum MEI Clients + */ +#define MEI_CLIENTS_MAX 256 + +/* + * maximum number of consecutive resets + */ +#define MEI_MAX_CONSEC_RESET 3 + +/* + * Number of File descriptors/handles + * that can be opened to the driver. + * + * Limit to 255: 256 Total Clients + * minus internal client for MEI Bus Messages + */ +#define MEI_MAX_OPEN_HANDLE_COUNT (MEI_CLIENTS_MAX - 1) + +/* + * Internal Clients Number + */ +#define MEI_HOST_CLIENT_ID_ANY (-1) +#define MEI_HBM_HOST_CLIENT_ID 0 /* not used, just for documentation */ +#define MEI_WD_HOST_CLIENT_ID 1 +#define MEI_IAMTHIF_HOST_CLIENT_ID 2 + + +/* File state */ +enum file_state { + MEI_FILE_INITIALIZING = 0, + MEI_FILE_CONNECTING, + MEI_FILE_CONNECTED, + MEI_FILE_DISCONNECTING, + MEI_FILE_DISCONNECT_REPLY, + MEI_FILE_DISCONNECT_REQUIRED, + MEI_FILE_DISCONNECTED, +}; + +/* MEI device states */ +enum mei_dev_state { + MEI_DEV_INITIALIZING = 0, + MEI_DEV_INIT_CLIENTS, + MEI_DEV_ENABLED, + MEI_DEV_RESETTING, + MEI_DEV_DISABLED, + MEI_DEV_POWER_DOWN, + MEI_DEV_POWER_UP +}; + +const char *mei_dev_state_str(int state); + +enum iamthif_states { + MEI_IAMTHIF_IDLE, + MEI_IAMTHIF_WRITING, + MEI_IAMTHIF_FLOW_CONTROL, + MEI_IAMTHIF_READING, + MEI_IAMTHIF_READ_COMPLETE +}; + +enum mei_file_transaction_states { + MEI_IDLE, + MEI_WRITING, + MEI_WRITE_COMPLETE, + MEI_FLOW_CONTROL, + MEI_READING, + MEI_READ_COMPLETE +}; + +enum mei_wd_states { + MEI_WD_IDLE, + MEI_WD_RUNNING, + MEI_WD_STOPPING, +}; + +/** + * enum mei_cb_file_ops - file operation associated with the callback + * @MEI_FOP_READ: read + * @MEI_FOP_WRITE: write + * @MEI_FOP_CONNECT: connect + * @MEI_FOP_DISCONNECT: disconnect + * @MEI_FOP_DISCONNECT_RSP: disconnect response + * @MEI_FOP_NOTIFY_START: start notification + * @MEI_FOP_NOTIFY_STOP: stop notification + */ +enum mei_cb_file_ops { + MEI_FOP_READ = 0, + MEI_FOP_WRITE, + MEI_FOP_CONNECT, + MEI_FOP_DISCONNECT, + MEI_FOP_DISCONNECT_RSP, + MEI_FOP_NOTIFY_START, + MEI_FOP_NOTIFY_STOP, +}; + +/* + * Intel MEI message data struct + */ +struct mei_msg_data { + u32 size; + unsigned char *data; +}; + +/* Maximum number of processed FW status registers */ +#define MEI_FW_STATUS_MAX 6 +/* Minimal buffer for FW status string (8 bytes in dw + space or '\0') */ +#define MEI_FW_STATUS_STR_SZ (MEI_FW_STATUS_MAX * (8 + 1)) + + +/* + * struct mei_fw_status - storage of FW status data + * + * @count: number of actually available elements in array + * @status: FW status registers + */ +struct mei_fw_status { + int count; + u32 status[MEI_FW_STATUS_MAX]; +}; + +/** + * struct mei_me_client - representation of me (fw) client + * + * @list: link in me client list + * @refcnt: struct reference count + * @props: client properties + * @client_id: me client id + * @mei_flow_ctrl_creds: flow control credits + * @connect_count: number connections to this client + * @bus_added: added to bus + */ +struct mei_me_client { + struct list_head list; + struct kref refcnt; + struct mei_client_properties props; + u8 client_id; + u8 mei_flow_ctrl_creds; + u8 connect_count; + u8 bus_added; +}; + + +struct mei_cl; + +/** + * struct mei_cl_cb - file operation callback structure + * + * @list: link in callback queue + * @cl: file client who is running this operation + * @fop_type: file operation type + * @buf: buffer for data associated with the callback + * @buf_idx: last read index + * @read_time: last read operation time stamp (iamthif) + * @file_object: pointer to file structure + * @status: io status of the cb + * @internal: communication between driver and FW flag + * @completed: the transfer or reception has completed + */ +struct mei_cl_cb { + struct list_head list; + struct mei_cl *cl; + enum mei_cb_file_ops fop_type; + struct mei_msg_data buf; + unsigned long buf_idx; + unsigned long read_time; + struct file *file_object; + int status; + u32 internal:1; + u32 completed:1; +}; + +/** + * struct mei_cl - me client host representation + * carried in file->private_data + * + * @link: link in the clients list + * @dev: mei parent device + * @state: file operation state + * @tx_wait: wait queue for tx completion + * @rx_wait: wait queue for rx completion + * @wait: wait queue for management operation + * @ev_wait: notification wait queue + * @ev_async: event async notification + * @status: connection status + * @me_cl: fw client connected + * @host_client_id: host id + * @mei_flow_ctrl_creds: transmit flow credentials + * @timer_count: watchdog timer for operation completion + * @reserved: reserved for alignment + * @notify_en: notification - enabled/disabled + * @notify_ev: pending notification event + * @writing_state: state of the tx + * @rd_pending: pending read credits + * @rd_completed: completed read + * + * @cldev: device on the mei client bus + */ +struct mei_cl { + struct list_head link; + struct mei_device *dev; + enum file_state state; + wait_queue_head_t tx_wait; + wait_queue_head_t rx_wait; + wait_queue_head_t wait; + wait_queue_head_t ev_wait; + struct fasync_struct *ev_async; + int status; + struct mei_me_client *me_cl; + u8 host_client_id; + u8 mei_flow_ctrl_creds; + u8 timer_count; + u8 reserved; + u8 notify_en; + u8 notify_ev; + enum mei_file_transaction_states writing_state; + struct list_head rd_pending; + struct list_head rd_completed; + + struct mei_cl_device *cldev; +}; + +/** + * struct mei_hw_ops - hw specific ops + * + * @host_is_ready : query for host readiness + * + * @hw_is_ready : query if hw is ready + * @hw_reset : reset hw + * @hw_start : start hw after reset + * @hw_config : configure hw + * + * @fw_status : get fw status registers + * @pg_state : power gating state of the device + * @pg_in_transition : is device now in pg transition + * @pg_is_enabled : is power gating enabled + * + * @intr_clear : clear pending interrupts + * @intr_enable : enable interrupts + * @intr_disable : disable interrupts + * + * @hbuf_free_slots : query for write buffer empty slots + * @hbuf_is_ready : query if write buffer is empty + * @hbuf_max_len : query for write buffer max len + * + * @write : write a message to FW + * + * @rdbuf_full_slots : query how many slots are filled + * + * @read_hdr : get first 4 bytes (header) + * @read : read a buffer from the FW + */ +struct mei_hw_ops { + + bool (*host_is_ready)(struct mei_device *dev); + + bool (*hw_is_ready)(struct mei_device *dev); + int (*hw_reset)(struct mei_device *dev, bool enable); + int (*hw_start)(struct mei_device *dev); + void (*hw_config)(struct mei_device *dev); + + + int (*fw_status)(struct mei_device *dev, struct mei_fw_status *fw_sts); + enum mei_pg_state (*pg_state)(struct mei_device *dev); + bool (*pg_in_transition)(struct mei_device *dev); + bool (*pg_is_enabled)(struct mei_device *dev); + + void (*intr_clear)(struct mei_device *dev); + void (*intr_enable)(struct mei_device *dev); + void (*intr_disable)(struct mei_device *dev); + + int (*hbuf_free_slots)(struct mei_device *dev); + bool (*hbuf_is_ready)(struct mei_device *dev); + size_t (*hbuf_max_len)(const struct mei_device *dev); + + int (*write)(struct mei_device *dev, + struct mei_msg_hdr *hdr, + unsigned char *buf); + + int (*rdbuf_full_slots)(struct mei_device *dev); + + u32 (*read_hdr)(const struct mei_device *dev); + int (*read)(struct mei_device *dev, + unsigned char *buf, unsigned long len); +}; + +/* MEI bus API*/ +void mei_cl_bus_rescan(struct mei_device *bus); +void mei_cl_bus_dev_fixup(struct mei_cl_device *dev); +ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, + bool blocking); +ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length); +void mei_cl_bus_rx_event(struct mei_cl *cl); +void mei_cl_bus_notify_event(struct mei_cl *cl); +void mei_cl_bus_remove_devices(struct mei_device *bus); +int mei_cl_bus_init(void); +void mei_cl_bus_exit(void); + +/** + * enum mei_pg_event - power gating transition events + * + * @MEI_PG_EVENT_IDLE: the driver is not in power gating transition + * @MEI_PG_EVENT_WAIT: the driver is waiting for a pg event to complete + * @MEI_PG_EVENT_RECEIVED: the driver received pg event + * @MEI_PG_EVENT_INTR_WAIT: the driver is waiting for a pg event interrupt + * @MEI_PG_EVENT_INTR_RECEIVED: the driver received pg event interrupt + */ +enum mei_pg_event { + MEI_PG_EVENT_IDLE, + MEI_PG_EVENT_WAIT, + MEI_PG_EVENT_RECEIVED, + MEI_PG_EVENT_INTR_WAIT, + MEI_PG_EVENT_INTR_RECEIVED, +}; + +/** + * enum mei_pg_state - device internal power gating state + * + * @MEI_PG_OFF: device is not power gated - it is active + * @MEI_PG_ON: device is power gated - it is in lower power state + */ +enum mei_pg_state { + MEI_PG_OFF = 0, + MEI_PG_ON = 1, +}; + +const char *mei_pg_state_str(enum mei_pg_state state); + +/** + * struct mei_device - MEI private device struct + * + * @dev : device on a bus + * @cdev : character device + * @minor : minor number allocated for device + * + * @write_list : write pending list + * @write_waiting_list : write completion list + * @ctrl_wr_list : pending control write list + * @ctrl_rd_list : pending control read list + * + * @file_list : list of opened handles + * @open_handle_count: number of opened handles + * + * @device_lock : big device lock + * @timer_work : MEI timer delayed work (timeouts) + * + * @recvd_hw_ready : hw ready message received flag + * + * @wait_hw_ready : wait queue for receive HW ready message form FW + * @wait_pg : wait queue for receive PG message from FW + * @wait_hbm_start : wait queue for receive HBM start message from FW + * @wait_stop_wd : wait queue for receive WD stop message from FW + * + * @reset_count : number of consecutive resets + * @dev_state : device state + * @hbm_state : state of host bus message protocol + * @init_clients_timer : HBM init handshake timeout + * + * @pg_event : power gating event + * @pg_domain : runtime PM domain + * + * @rd_msg_buf : control messages buffer + * @rd_msg_hdr : read message header storage + * + * @hbuf_depth : depth of hardware host/write buffer is slots + * @hbuf_is_ready : query if the host host/write buffer is ready + * @wr_msg : the buffer for hbm control messages + * + * @version : HBM protocol version in use + * @hbm_f_pg_supported : hbm feature pgi protocol + * @hbm_f_dc_supported : hbm feature dynamic clients + * @hbm_f_dot_supported : hbm feature disconnect on timeout + * @hbm_f_ev_supported : hbm feature event notification + * + * @me_clients_rwsem: rw lock over me_clients list + * @me_clients : list of FW clients + * @me_clients_map : FW clients bit map + * @host_clients_map : host clients id pool + * @me_client_index : last FW client index in enumeration + * + * @allow_fixed_address: allow user space to connect a fixed client + * + * @wd_cl : watchdog client + * @wd_state : watchdog client state + * @wd_pending : watchdog command is pending + * @wd_timeout : watchdog expiration timeout + * @wd_data : watchdog message buffer + * + * @amthif_cmd_list : amthif list for cmd waiting + * @amthif_rd_complete_list : amthif list for reading completed cmd data + * @iamthif_file_object : file for current amthif operation + * @iamthif_cl : amthif host client + * @iamthif_current_cb : amthif current operation callback + * @iamthif_open_count : number of opened amthif connections + * @iamthif_timer : time stamp of current amthif command completion + * @iamthif_stall_timer : timer to detect amthif hang + * @iamthif_state : amthif processor state + * @iamthif_canceled : current amthif command is canceled + * + * @init_work : work item for the device init + * @reset_work : work item for the device reset + * + * @device_list : mei client bus list + * @cl_bus_lock : client bus list lock + * + * @dbgfs_dir : debugfs mei root directory + * + * @ops: : hw specific operations + * @hw : hw specific data + */ +struct mei_device { + struct device *dev; + struct cdev cdev; + int minor; + + struct mei_cl_cb write_list; + struct mei_cl_cb write_waiting_list; + struct mei_cl_cb ctrl_wr_list; + struct mei_cl_cb ctrl_rd_list; + + struct list_head file_list; + long open_handle_count; + + struct mutex device_lock; + struct delayed_work timer_work; + + bool recvd_hw_ready; + /* + * waiting queue for receive message from FW + */ + wait_queue_head_t wait_hw_ready; + wait_queue_head_t wait_pg; + wait_queue_head_t wait_hbm_start; + wait_queue_head_t wait_stop_wd; + + /* + * mei device states + */ + unsigned long reset_count; + enum mei_dev_state dev_state; + enum mei_hbm_state hbm_state; + u16 init_clients_timer; + + /* + * Power Gating support + */ + enum mei_pg_event pg_event; +#ifdef CONFIG_PM + struct dev_pm_domain pg_domain; +#endif /* CONFIG_PM */ + + unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; + u32 rd_msg_hdr; + + /* write buffer */ + u8 hbuf_depth; + bool hbuf_is_ready; + + /* used for control messages */ + struct { + struct mei_msg_hdr hdr; + unsigned char data[128]; + } wr_msg; + + struct hbm_version version; + unsigned int hbm_f_pg_supported:1; + unsigned int hbm_f_dc_supported:1; + unsigned int hbm_f_dot_supported:1; + unsigned int hbm_f_ev_supported:1; + + struct rw_semaphore me_clients_rwsem; + struct list_head me_clients; + DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX); + DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX); + unsigned long me_client_index; + + bool allow_fixed_address; + + struct mei_cl wd_cl; + enum mei_wd_states wd_state; + bool wd_pending; + u16 wd_timeout; + unsigned char wd_data[MEI_WD_START_MSG_SIZE]; + + + /* amthif list for cmd waiting */ + struct mei_cl_cb amthif_cmd_list; + /* driver managed amthif list for reading completed amthif cmd data */ + struct mei_cl_cb amthif_rd_complete_list; + struct file *iamthif_file_object; + struct mei_cl iamthif_cl; + struct mei_cl_cb *iamthif_current_cb; + long iamthif_open_count; + unsigned long iamthif_timer; + u32 iamthif_stall_timer; + enum iamthif_states iamthif_state; + bool iamthif_canceled; + + struct work_struct init_work; + struct work_struct reset_work; + + /* List of bus devices */ + struct list_head device_list; + struct mutex cl_bus_lock; + +#if IS_ENABLED(CONFIG_DEBUG_FS) + struct dentry *dbgfs_dir; +#endif /* CONFIG_DEBUG_FS */ + + + const struct mei_hw_ops *ops; + char hw[0] __aligned(sizeof(void *)); +}; + +static inline unsigned long mei_secs_to_jiffies(unsigned long sec) +{ + return msecs_to_jiffies(sec * MSEC_PER_SEC); +} + +/** + * mei_data2slots - get slots - number of (dwords) from a message length + * + size of the mei header + * + * @length: size of the messages in bytes + * + * Return: number of slots + */ +static inline u32 mei_data2slots(size_t length) +{ + return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4); +} + +/** + * mei_slots2data - get data in slots - bytes from slots + * + * @slots: number of available slots + * + * Return: number of bytes in slots + */ +static inline u32 mei_slots2data(int slots) +{ + return slots * 4; +} + +/* + * mei init function prototypes + */ +void mei_device_init(struct mei_device *dev, + struct device *device, + const struct mei_hw_ops *hw_ops); +int mei_reset(struct mei_device *dev); +int mei_start(struct mei_device *dev); +int mei_restart(struct mei_device *dev); +void mei_stop(struct mei_device *dev); +void mei_cancel_work(struct mei_device *dev); + +/* + * MEI interrupt functions prototype + */ + +void mei_timer(struct work_struct *work); +int mei_irq_read_handler(struct mei_device *dev, + struct mei_cl_cb *cmpl_list, s32 *slots); + +int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list); +void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list); + +/* + * AMTHIF - AMT Host Interface Functions + */ +void mei_amthif_reset_params(struct mei_device *dev); + +int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl); + +int mei_amthif_read(struct mei_device *dev, struct file *file, + char __user *ubuf, size_t length, loff_t *offset); + +unsigned int mei_amthif_poll(struct mei_device *dev, + struct file *file, poll_table *wait); + +int mei_amthif_release(struct mei_device *dev, struct file *file); + +struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, + struct file *file); + +int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb); +int mei_amthif_run_next_cmd(struct mei_device *dev); +int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, + struct mei_cl_cb *cmpl_list); + +void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb); +int mei_amthif_irq_read_msg(struct mei_cl *cl, + struct mei_msg_hdr *mei_hdr, + struct mei_cl_cb *complete_list); +int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); + +/* + * NFC functions + */ +int mei_nfc_host_init(struct mei_device *dev, struct mei_me_client *me_cl); +void mei_nfc_host_exit(struct mei_device *dev); + +/* + * NFC Client UUID + */ +extern const uuid_le mei_nfc_guid; + +int mei_wd_send(struct mei_device *dev); +int mei_wd_stop(struct mei_device *dev); +int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl); +/* + * mei_watchdog_register - Registering watchdog interface + * once we got connection to the WD Client + * @dev: mei device + */ +int mei_watchdog_register(struct mei_device *dev); +/* + * mei_watchdog_unregister - Unregistering watchdog interface + * @dev: mei device + */ +void mei_watchdog_unregister(struct mei_device *dev); + +/* + * Register Access Function + */ + + +static inline void mei_hw_config(struct mei_device *dev) +{ + dev->ops->hw_config(dev); +} + +static inline enum mei_pg_state mei_pg_state(struct mei_device *dev) +{ + return dev->ops->pg_state(dev); +} + +static inline bool mei_pg_in_transition(struct mei_device *dev) +{ + return dev->ops->pg_in_transition(dev); +} + +static inline bool mei_pg_is_enabled(struct mei_device *dev) +{ + return dev->ops->pg_is_enabled(dev); +} + +static inline int mei_hw_reset(struct mei_device *dev, bool enable) +{ + return dev->ops->hw_reset(dev, enable); +} + +static inline int mei_hw_start(struct mei_device *dev) +{ + return dev->ops->hw_start(dev); +} + +static inline void mei_clear_interrupts(struct mei_device *dev) +{ + dev->ops->intr_clear(dev); +} + +static inline void mei_enable_interrupts(struct mei_device *dev) +{ + dev->ops->intr_enable(dev); +} + +static inline void mei_disable_interrupts(struct mei_device *dev) +{ + dev->ops->intr_disable(dev); +} + +static inline bool mei_host_is_ready(struct mei_device *dev) +{ + return dev->ops->host_is_ready(dev); +} +static inline bool mei_hw_is_ready(struct mei_device *dev) +{ + return dev->ops->hw_is_ready(dev); +} + +static inline bool mei_hbuf_is_ready(struct mei_device *dev) +{ + return dev->ops->hbuf_is_ready(dev); +} + +static inline int mei_hbuf_empty_slots(struct mei_device *dev) +{ + return dev->ops->hbuf_free_slots(dev); +} + +static inline size_t mei_hbuf_max_len(const struct mei_device *dev) +{ + return dev->ops->hbuf_max_len(dev); +} + +static inline int mei_write_message(struct mei_device *dev, + struct mei_msg_hdr *hdr, + unsigned char *buf) +{ + return dev->ops->write(dev, hdr, buf); +} + +static inline u32 mei_read_hdr(const struct mei_device *dev) +{ + return dev->ops->read_hdr(dev); +} + +static inline void mei_read_slots(struct mei_device *dev, + unsigned char *buf, unsigned long len) +{ + dev->ops->read(dev, buf, len); +} + +static inline int mei_count_full_read_slots(struct mei_device *dev) +{ + return dev->ops->rdbuf_full_slots(dev); +} + +static inline int mei_fw_status(struct mei_device *dev, + struct mei_fw_status *fw_status) +{ + return dev->ops->fw_status(dev, fw_status); +} + +bool mei_hbuf_acquire(struct mei_device *dev); + +bool mei_write_is_idle(struct mei_device *dev); + +#if IS_ENABLED(CONFIG_DEBUG_FS) +int mei_dbgfs_register(struct mei_device *dev, const char *name); +void mei_dbgfs_deregister(struct mei_device *dev); +#else +static inline int mei_dbgfs_register(struct mei_device *dev, const char *name) +{ + return 0; +} +static inline void mei_dbgfs_deregister(struct mei_device *dev) {} +#endif /* CONFIG_DEBUG_FS */ + +int mei_register(struct mei_device *dev, struct device *parent); +void mei_deregister(struct mei_device *dev); + +#define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d internal=%1d comp=%1d" +#define MEI_HDR_PRM(hdr) \ + (hdr)->host_addr, (hdr)->me_addr, \ + (hdr)->length, (hdr)->internal, (hdr)->msg_complete + +ssize_t mei_fw_status2str(struct mei_fw_status *fw_sts, char *buf, size_t len); +/** + * mei_fw_status_str - fetch and convert fw status registers to printable string + * + * @dev: the device structure + * @buf: string buffer at minimal size MEI_FW_STATUS_STR_SZ + * @len: buffer len must be >= MEI_FW_STATUS_STR_SZ + * + * Return: number of bytes written or < 0 on failure + */ +static inline ssize_t mei_fw_status_str(struct mei_device *dev, + char *buf, size_t len) +{ + struct mei_fw_status fw_status; + int ret; + + buf[0] = '\0'; + + ret = mei_fw_status(dev, &fw_status); + if (ret) + return ret; + + ret = mei_fw_status2str(&fw_status, buf, MEI_FW_STATUS_STR_SZ); + + return ret; +} + + +#endif diff --git a/platform/broadcom/sonic-platform-modules-delta/common/modules/dni_emc2305.c b/platform/broadcom/sonic-platform-modules-delta/common/modules/dni_emc2305.c new file mode 100644 index 000000000000..73d9900af5b4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/common/modules/dni_emc2305.c @@ -0,0 +1,381 @@ +/* + * + * + * Copyright (C) 2017 Delta Networks, Inc. + * + * This program is free software; you can redistribute it + * and/or modify it under the terms ofthe GNU General Public License as + * published by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * + * + * + * + * A hwmon driver for the SMSC EMC2305 fan controller + * Complete datasheet is available (6/2013) at: + * http://www.smsc.com/media/Downloads_Public/Data_Sheets/2305.pdf + */ + +#include +#include +#include +#include +#include + + +static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t set_fan(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t set_fan_percentage(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_fan_percentage(struct device *dev, struct device_attribute * devattr, + char *buf); +static const unsigned short normal_i2c[] = { 0x2C, 0x2D, 0x2E, 0x2F, 0x4C, + 0x4D, I2C_CLIENT_END + }; + + +#define EMC2305_REG_DEVICE 0xFD +#define EMC2305_REG_VENDOR 0xFE + +//#define FAN_MINIMUN 0x33 /*20%*/ +#define FAN_MINIMUN 0x0 /*0%*/ +#define FAN_RPM_BASED 0xAB + +#define EMC2305_REG_FAN_DRIVE(n) (0x30 + 0x10 * n) +#define EMC2305_REG_FAN_MIN_DRIVE(n) (0x38 + 0x10 * n) +#define EMC2305_REG_FAN_TACH(n) (0x3E + 0x10 * n) +#define EMC2305_REG_FAN_CONF(n) (0x32 + 0x10 * n) +#define EMC2305_REG_FAN_REAR_H_RPM(n) (0x3D + 0x10 * n) +#define EMC2305_REG_FAN_REAR_L_RPM(n) (0x3C + 0x10 * n) + +#define EMC2305_DEVICE 0x34 +#define EMC2305_VENDOR 0x5D +#define MAX_FAN_SPEED 23000 + +struct emc2305_data +{ + struct device *hwmon_dev; + struct attribute_group attrs; + struct mutex lock; +}; + +static int emc2305_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int emc2305_detect(struct i2c_client *client, + struct i2c_board_info *info); +static int emc2305_remove(struct i2c_client *client); + +static const struct i2c_device_id emc2305_id[] = +{ + { "emc2305", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, emc2305_id); + +static struct i2c_driver emc2305_driver = +{ + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc2305", + }, + .probe = emc2305_probe, + .remove = emc2305_remove, + .id_table = emc2305_id, + .detect = emc2305_detect, + .address_list = normal_i2c, +}; + +static SENSOR_DEVICE_ATTR(fan1_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 4); +static SENSOR_DEVICE_ATTR(fan1_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 0); +static SENSOR_DEVICE_ATTR(fan2_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 1); +static SENSOR_DEVICE_ATTR(fan3_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 2); +static SENSOR_DEVICE_ATTR(fan4_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 3); +static SENSOR_DEVICE_ATTR(fan5_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 4); +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(pwm5, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 4); + +static struct attribute *emc2305_attr[] = +{ + &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_fan1_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan2_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan3_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan4_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan5_input_percentage.dev_attr.attr, + &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_pwm5.dev_attr.attr, + NULL +}; + +static ssize_t show_fan_percentage(struct device *dev, struct device_attribute * devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + int val; + + mutex_lock(&data->lock); + val = i2c_smbus_read_word_swapped(client, + EMC2305_REG_FAN_TACH(attr->index)); + mutex_unlock(&data->lock); + /* Left shift 3 bits for showing correct RPM */ + val = val >> 3; + if ((int)(3932160 * 2 / (val > 0 ? val : 1) == 960))return sprintf(buf, "%d\n", 0); + return sprintf(buf, "%d\n", (int)(3932160 * 2 / (val > 0 ? val : 1) * 100 / MAX_FAN_SPEED)); +} + + +static ssize_t set_fan_percentage(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 emc2305_data *data = i2c_get_clientdata(client); + unsigned long hsb, lsb; + unsigned long tech; + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 100) + { + return -EINVAL; + } + + if (val <= 5) + { + hsb = 0xff; /*high bit*/ + lsb = 0xe0; /*low bit*/ + } + else + { + val = val * 230; + tech = (3932160 * 2) / (val > 0 ? val : 1); + hsb = (uint8_t)(((tech << 3) >> 8) & 0x0ff); + lsb = (uint8_t)((tech << 3) & 0x0f8); + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_H_RPM(attr->index), hsb); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_L_RPM(attr->index), lsb); + mutex_unlock(&data->lock); + return count; +} + + +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + int val; + + + mutex_lock(&data->lock); + val = i2c_smbus_read_word_swapped(client, + EMC2305_REG_FAN_TACH(attr->index)); + mutex_unlock(&data->lock); + /* Left shift 3 bits for showing correct RPM */ + val = val >> 3; + return sprintf(buf, "%d\n", 3932160 * 2 / (val > 0 ? val : 1)); +} + +static ssize_t set_fan(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 emc2305_data *data = i2c_get_clientdata(client); + unsigned long hsb, lsb; + unsigned long tech; + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 23000) + { + return -EINVAL; + } + + if (val <= 960) + { + hsb = 0xff; /*high bit*/ + lsb = 0xe0; /*low bit*/ + } + else + { + tech = (3932160 * 2) / (val > 0 ? val : 1); + hsb = (uint8_t)(((tech << 3) >> 8) & 0x0ff); + lsb = (uint8_t)((tech << 3) & 0x0f8); + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_H_RPM(attr->index), hsb); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_L_RPM(attr->index), lsb); + mutex_unlock(&data->lock); + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + int val; + + mutex_lock(&data->lock); + val = i2c_smbus_read_byte_data(client, + EMC2305_REG_FAN_DRIVE(attr->index)); + mutex_unlock(&data->lock); + return sprintf(buf, "%d\n", val); +} + +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 emc2305_data *data = i2c_get_clientdata(client); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 255) + { + return -EINVAL; + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, + EMC2305_REG_FAN_DRIVE(attr->index), + val); + mutex_unlock(&data->lock); + return count; +} + +static int emc2305_detect(struct i2c_client *client, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + int vendor, device; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + { + return -ENODEV; + } + + vendor = i2c_smbus_read_byte_data(client, EMC2305_REG_VENDOR); + if (vendor != EMC2305_VENDOR) + { + return -ENODEV; + } + + device = i2c_smbus_read_byte_data(client, EMC2305_REG_DEVICE); + if (device != EMC2305_DEVICE) + { + return -ENODEV; + } + + strlcpy(info->type, "emc2305", I2C_NAME_SIZE); + + return 0; +} + +static int emc2305_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct emc2305_data *data; + int err; + int i; + + data = devm_kzalloc(&client->dev, sizeof(struct emc2305_data), + GFP_KERNEL); + if (!data) + { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s chip found\n", client->name); + + data->attrs.attrs = emc2305_attr; + err = sysfs_create_group(&client->dev.kobj, &data->attrs); + if (err) + { + return err; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) + { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + for (i = 0; i < 5; i++) + { + /* set minimum drive to 0% */ + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_MIN_DRIVE(i), FAN_MINIMUN); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_CONF(i), FAN_RPM_BASED); + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->attrs); + return err; +} + +static int emc2305_remove(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->attrs); + return 0; +} + +module_i2c_driver(emc2305_driver); + +MODULE_AUTHOR("Neal Tai"); +MODULE_DESCRIPTION("SMSC EMC2305 fan controller driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/changelog b/platform/broadcom/sonic-platform-modules-delta/debian/changelog new file mode 100644 index 000000000000..ec8327e8ae7a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/changelog @@ -0,0 +1,5 @@ +sonic-delta-platform-modules (1.1) unstable; urgency=low + + * Initial release + + -- Neal Tai Fri, 21 APR 2017 11:11:11 -0800 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/compat b/platform/broadcom/sonic-platform-modules-delta/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/control b/platform/broadcom/sonic-platform-modules-delta/debian/control new file mode 100644 index 000000000000..0bcceccf6b18 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/control @@ -0,0 +1,27 @@ +Source: sonic-delta-platform-modules +Section: main +Priority: extra +Maintainer: Neal Tai +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-ag9032v1 +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-ag9064 +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-ag5648 +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-et-6248brb +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag5648.init b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag5648.init new file mode 100755 index 000000000000..d69534035a54 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag5648.init @@ -0,0 +1,49 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup ag5648 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + depmod -a + rmmod i2c-i801 + rmmod i2c-ismt + modprobe i2c-dev + modprobe i2c-i801 + modprobe i2c-ismt + modprobe i2c-mux-pca954x + modprobe dni_ag5648_psu + modprobe dni_emc2305 + modprobe at24 + modprobe delta_ag5648_platform + + /usr/local/bin/ag5648_platform_init.sh + + echo "done." + ;; + +stop) + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-ag5648.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag5648.install b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag5648.install new file mode 100644 index 000000000000..06d536770167 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag5648.install @@ -0,0 +1,4 @@ +ag5648/scripts/ag5648_platform_init.sh usr/local/bin +ag5648/cfg/ag5648-modules.conf etc/modules-load.d +ag5648/scripts/led_control usr/local/bin +systemd/platform-modules-ag5648.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.init b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.init new file mode 100755 index 000000000000..3734ab362a2f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.init @@ -0,0 +1,49 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup ag9032v1 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + depmod -a + rmmod i2c-i801 + rmmod i2c-ismt + modprobe i2c-dev + modprobe i2c-i801 + modprobe i2c-ismt + modprobe i2c-mux-pca954x + modprobe dni_ag9032v1_psu + modprobe dni_emc2305 + modprobe at24 + modprobe delta_ag9032v1_platform + modprobe delta_ag9032v1_cpupld + + /usr/local/bin/ag9032v1_platform_init.sh + echo "done." + ;; + +stop) + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-ag9032v1.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.install b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.install new file mode 100644 index 000000000000..beca4f51b1f8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.install @@ -0,0 +1,4 @@ +ag9032v1/scripts/ag9032v1_platform_init.sh usr/local/bin +ag9032v1/scripts/led_status.sh usr/local/bin +ag9032v1/cfg/ag9032v1-modules.conf etc/modules-load.d +systemd/platform-modules-ag9032v1.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.init b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.init new file mode 100755 index 000000000000..57665353e3c7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.init @@ -0,0 +1,52 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup ag9064 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + depmod -a + rmmod i2c-i801 + rmmod i2c-ismt + modprobe i2c-dev + modprobe i2c-i801 + modprobe i2c-ismt + modprobe ipmi_devintf + modprobe ipmi_si ports=0xca2 + modprobe i2c-mei + modprobe i2c-mux-pca954x + modprobe at24 + modprobe delta_ag9064_platform + modprobe delta_ag9064_cpld + modprobe delta_ag9064_swpld + + /usr/local/bin/ag9064_platform_init.sh + + echo "done." + ;; + +stop) + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-ag9064.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.install b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.install new file mode 100644 index 000000000000..ad7c793da3c0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.install @@ -0,0 +1,2 @@ +ag9064/cfg/ag9064-modules.conf etc/modules-load.d +systemd/platform-modules-ag9064.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.init b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.init new file mode 100755 index 000000000000..726e0ba6923b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.init @@ -0,0 +1,80 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup et-6248brb board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + depmod -a + rmmod i2c-i801 + rmmod i2c-ismt + modprobe i2c-dev + modprobe i2c-i801 + modprobe i2c-ismt + modprobe i2c-mux-pca954x + modprobe i2c-mux-gpio + modprobe dni_gpio + modprobe delta_et-6248brb_platform + + if [ `uname -a | awk '{print $3}'` = "4.9.0-7-amd64" ]; then + echo "453" > "/sys/class/gpio/export" + echo "454" > "/sys/class/gpio/export" + echo "455" > "/sys/class/gpio/export" + echo "485" > "/sys/class/gpio/export" + echo "489" > "/sys/class/gpio/export" + echo "494" > "/sys/class/gpio/export" + echo "out" > "/sys/class/gpio/gpio453/direction" + echo "out" > "/sys/class/gpio/gpio454/direction" + echo "out" > "/sys/class/gpio/gpio455/direction" + echo "out" > "/sys/class/gpio/gpio485/direction" + echo "out" > "/sys/class/gpio/gpio489/direction" + echo "out" > "/sys/class/gpio/gpio494/direction" + else + echo "197" > "/sys/class/gpio/export" + echo "198" > "/sys/class/gpio/export" + echo "199" > "/sys/class/gpio/export" + echo "229" > "/sys/class/gpio/export" + echo "233" > "/sys/class/gpio/export" + echo "238" > "/sys/class/gpio/export" + echo "out" > "/sys/class/gpio/gpio197/direction" + echo "out" > "/sys/class/gpio/gpio198/direction" + echo "out" > "/sys/class/gpio/gpio199/direction" + echo "out" > "/sys/class/gpio/gpio229/direction" + echo "out" > "/sys/class/gpio/gpio233/direction" + echo "out" > "/sys/class/gpio/gpio238/direction" + fi + + /usr/local/bin/et-6248brb_platform_init.sh + + sleep 1 + echo "Ethernet48" > "/sys/bus/i2c/devices/4-0050/port_name" + echo "Ethernet49" > "/sys/bus/i2c/devices/5-0050/port_name" + + echo "done." + ;; + +stop) + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-et-6248brb.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.install b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.install new file mode 100644 index 000000000000..936c43679d5c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.install @@ -0,0 +1,4 @@ +et-6248brb/scripts/et-6248brb_platform_init.sh usr/local/bin +et-6248brb/cfg/et-6248brb-modules.conf etc/modules-load.d +et-6248brb/scripts/led_status.sh usr/local/bin +systemd/platform-modules-et-6248brb.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/rules b/platform/broadcom/sonic-platform-modules-delta/debian/rules new file mode 100755 index 000000000000..63949e3a5399 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/rules @@ -0,0 +1,33 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= ag9032v1 ag9064 ag5648 et-6248brb + +%: + dh $@ --with=systemd + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -pplatform-modules-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/broadcom/sonic-platform-modules-delta/et-6248brb/cfg/et-6248brb-modules.conf b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/cfg/et-6248brb-modules.conf new file mode 100644 index 000000000000..552b4103ed02 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/cfg/et-6248brb-modules.conf @@ -0,0 +1,13 @@ +# /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. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus +i2c-mux-gpio +i2c-mux-pca954x diff --git a/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/Makefile b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/Makefile new file mode 100644 index 000000000000..fb5b18ed5b4c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := delta_et-6248brb_platform.o dni_gpio.o + diff --git a/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/delta_et-6248brb_platform.c b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/delta_et-6248brb_platform.c new file mode 100644 index 000000000000..72fccd9aa0e8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/delta_et-6248brb_platform.c @@ -0,0 +1,918 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define OPTOE_INFO(data) \ + .type = "optoe2", .addr = 0x50 + +#define et6248brb_i2c_device_num(NUM){ \ + .name = "delta-et6248brb-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &et6248brb_i2c_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +#define et6248brb_gpio_num(NUM){ \ + .name = "delta-et6248brb-gpio", \ + .id = NUM, \ + .dev = { \ + .platform_data = &et6248brb_gpio_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +#define PCA9555_A 0x20 +#define PCA9555_B 0x21 +#define PCA9555_C 0x23 + +static struct kobject *kobj_gpio; +static struct kobject *kobj_psu; +static struct kobject *kobj_fan; +static struct kobject *kobj_sfp; +static struct kobject *kobj_others; + +/*Define struct to get client of i2c_new_deivce */ +struct i2c_client * i2c_client_9547; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, + BUS8, + BUS9, + BUS10, +}; + +/*---------------- I2C device - start ------------- */ +static void device_release(struct device *dev) +{ + return; +} + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; +/* pca9547 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode[] = { + { .adap_id = 2, + .deselect_on_exit = 1, + }, + { .adap_id = 3, + .deselect_on_exit = 1, + }, + { .adap_id = 4, + .deselect_on_exit = 1, + }, + { .adap_id = 5, + .deselect_on_exit = 1, + }, + { .adap_id = 6, + .deselect_on_exit = 1, + }, + { .adap_id = 7, + .deselect_on_exit = 1, + }, + { .adap_id = 8, + .deselect_on_exit = 1, + }, + { .adap_id = 9, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_data pca954x_data = { + .modes = pca954x_mode, + .num_modes = ARRAY_SIZE(pca954x_mode), +}; + +static struct i2c_board_info __initdata i2c_info_pca9547[] = +{ + { + I2C_BOARD_INFO("pca9547", 0x71), + .platform_data = &pca954x_data, + }, +}; + +static struct i2c_device_platform_data et6248brb_i2c_device_platform_data[] = { + { + /* FAN controller (0x2e) */ + .parent = 0, + .info = { I2C_BOARD_INFO("adt7473", 0x2e) }, + .client = NULL, + }, + { + /* tmp75 (0x48) */ + .parent = 0, + .info = { I2C_BOARD_INFO("tmp75", 0x48) }, + .client = NULL, + }, + { + /* EEPROM (0x54) */ + .parent = 1, + .info = { I2C_BOARD_INFO("24c08", 0x54) }, + .client = NULL, + }, + { + /* sfp 1 (0x50) */ + .parent = 4, + .info = { OPTOE_INFO() }, + .client = NULL, + }, + { + /* sfp 2 (0x50) */ + .parent = 5, + .info = { OPTOE_INFO() }, + .client = NULL, + }, + { + /* tmp75 (0x49) */ + .parent = 7, + .info = { I2C_BOARD_INFO("tmp75", 0x49) }, + .client = NULL, + }, + { + /* tmp75 (0x4a) */ + .parent = 8, + .info = { I2C_BOARD_INFO("tmp75", 0x4a) }, + .client = NULL, + }, +}; + +static struct platform_device et6248brb_i2c_device[] = { + et6248brb_i2c_device_num(0), + et6248brb_i2c_device_num(1), + et6248brb_i2c_device_num(2), + et6248brb_i2c_device_num(3), + et6248brb_i2c_device_num(4), + et6248brb_i2c_device_num(5), + et6248brb_i2c_device_num(6), +}; + +/*---------------- I2C device - end ------------- */ +/*---------------- I2C driver - start ------------- */ +static int __init i2c_device_probe(struct platform_device *pdev) +{ + struct i2c_device_platform_data *pdata; + struct i2c_adapter *parent; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + return 0; +} + +static int __exit i2c_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + if (pdata->client) { + parent = (pdata->client)->adapter; + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + } + + return 0; +} +static struct platform_driver i2c_device_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-et6248brb-i2c-device", + } +}; +/*---------------- I2C driver - end ------------- */ + +/*---------------- gpio device - start ----------- */ +static struct pca953x_platform_data pca9555_data_0 = { + .gpio_base = 200, +}; +static struct pca953x_platform_data pca9555_data_1 = { + .gpio_base = 216, +}; +static struct pca953x_platform_data pca9555_data_2 = { + .gpio_base = 232, +}; + +static struct i2c_board_info __initdata i2c_info_pca9555[] = +{ + { + I2C_BOARD_INFO("pca9555", 0x20), + .platform_data = &pca9555_data_0, + }, + { + I2C_BOARD_INFO("pca9555", 0x21), + .platform_data = &pca9555_data_1, + }, + { + I2C_BOARD_INFO("pca9555", 0x23), + .platform_data = &pca9555_data_2, + }, +}; + +static struct i2c_device_platform_data et6248brb_gpio_device_platform_data[] = { + { + /* GPIO expander A (0x20) */ + .parent = 0, + .info = { I2C_BOARD_INFO("pca9555", 0x20) }, + .client = NULL, + }, + { + /* GPIO expander B (0x21) */ + .parent = 0, + .info = { I2C_BOARD_INFO("pca9555", 0x21) }, + .client = NULL, + }, + { + /* GPIO expander C (0x23) */ + .parent = 0, + .info = { I2C_BOARD_INFO("pca9555", 0x23) }, + .client = NULL, + }, +}; + +static struct platform_device et6248brb_gpio_device[] = { + et6248brb_gpio_num(0), + et6248brb_gpio_num(1), + et6248brb_gpio_num(2), +}; + +static struct gpio_attribute_data { + uint8_t bus; + uint8_t addr; + uint8_t reg; + uint8_t mask; + char note[150]; +}; + +enum gpio_attributes { + PSU1_SMB_ALERT, + PSU2_SMB_ALERT, + EEPROM_WP, + FAN1_LED_AG, + FAN2_LED_AG, + D_FAN_ALERT, + PSU1_PRES, + PSU2_PRES, + FAN_EEPROM_WP, + D_FAN_M_PRESENT2, + D_FAN_M_PRESENT1, + PSU1_PG, + PSU2_PG, + BCM54282_INT, + SFP_MOD_P1, + SFP_RXLOS_P1, + SFP_MOD_P2, + SFP_RXLOS_P2, + SFP_TX_FAULT_P1, + SFP_TX_FAULT_P2, + SFP_TX_DIS_P1, + SFP_TX_DIS_P2, + OOB_BCM54616S_INT, +}; + +static struct gpio_attribute_data attribute_data[] = { +//PCA9555_A + [PSU1_SMB_ALERT] = { + .bus = BUS0, .addr = PCA9555_A, + .reg = 0x00, .mask = 1 << 0, + .note = "0=PSU1 interrupt is occurr\n1=PSU1 interrupt is NOT occurr" + }, + [PSU2_SMB_ALERT] = { + .bus = BUS0, .addr = PCA9555_A, + .reg = 0x00, .mask = 1 << 3, + .note = "0=PSU2 interrupt is occurr\n1=PSU2 interrupt is NOT occurr" + }, + [EEPROM_WP] = { + .bus = BUS0, .addr = PCA9555_A, + .reg = 0x03, .mask = 1 << 3, + .note = "0=SYS eeprom write protect is disable\n1=SYS eeprom write protect is enable and can not be programmed" + + }, + [FAN1_LED_AG] = { + .bus = BUS0, .addr = PCA9555_A, + .reg = 0x03, .mask = 0x30, + .note = "00=LED off or FAN tray1 is not present\n01=LED Red,FAN tray1 fail\n10=LED Green,FAN tray1 is present\n11=reserved" + }, + [FAN2_LED_AG] = { + .bus = BUS0, .addr = PCA9555_A, + .reg = 0x03, .mask = 0xc0, + .note = "00=LED off or FAN tray1 is not present\n01=LED Red,FAN tray1 fail\n10=LED Green,FAN tray1 is present\n11=reserved" + }, +//PCA9555_B + [D_FAN_ALERT] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x00, .mask = 1 << 0, + .note ="0=FAN is NOT issue the alram\n1=FAN issue the alarm" + + }, + [PSU1_PRES] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x00, .mask = 1 << 2, + .note ="0=PSU1 is present\n1=PSU1 is NOT present" + }, + [PSU2_PRES] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x00, .mask = 1 << 3, + .note ="0=PSU2 is present\n1=PSU2 is NOT present" + }, + [FAN_EEPROM_WP] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x01, .mask = 1 << 1, + .note ="0=FAN eeprom write protect is disable\n1=FAN eeprom write protect is enable and can not be programmed" + }, + [D_FAN_M_PRESENT2] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x01, .mask = 1 << 2, + .note ="0=FAN2 module is present\n1=FAN2 module is NOT present" + }, + [D_FAN_M_PRESENT1] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x01, .mask = 1 << 3, + .note ="0=FAN1 moduel is present\n1=FAN1 module is NOT present" + }, + [PSU1_PG] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x01, .mask = 1 << 4, + .note ="0=PSU1 is FAIL or not present\n1=PSU1 is GOOD" + }, + [PSU2_PG] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x01, .mask = 1 << 5, + .note ="0=PSU2 is FAIL or not present\n1=PSU2 is GOOD" + }, + [BCM54282_INT] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x01, .mask = 1 << 6, + .note ="0=BCM54282 PHY interrupt occurrs\n1=BCM54282 PHY interrupt is not occurrs" + }, +//PCA9555_C + [SFP_MOD_P1] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x00, .mask = 1 << 0, + .note ="0=SFP1 transceiver is present\n1=SFP1 transceiver is NOT present" + }, + [SFP_RXLOS_P1] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x00, .mask = 1 << 1, + .note ="0=SFP1 transceiver is NOT asserted Loss of signal\n1=SFP1 transceiver is asserted Loss of signal" + }, + [SFP_MOD_P2] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x00, .mask = 1 << 2, + .note ="0=SFP1 transceiver is present\n1=SFP1 transceiver is NOT present" + }, + [SFP_RXLOS_P2] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x00, .mask = 1 << 3, + .note ="0=SFP1 transceiver is NOT asserted Loss of signal\n1=SFP1 transceiver is asserted Loss of signal" + }, + [SFP_TX_FAULT_P1] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x00, .mask = 1 << 4, + .note ="0=SFP1 transceiver is NOT asserted TXFAULT signal\n1=SFP1 transceiver is asserted TXFAULT signal" + }, + [SFP_TX_FAULT_P2] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x00, .mask = 1 << 5, + .note ="0=SFP1 transceiver is NOT asserted TXFAULT signal\n1=SFP1 transceiver is asserted TXFAULT signal" + }, + [SFP_TX_DIS_P1] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x02, .mask = 1 << 6, + .note ="0=SFP1 transceiver is turn ON\n1=SFP1 transceiver is turn OFF" + }, + [SFP_TX_DIS_P2] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x02, .mask = 1 << 7, + .note ="0=SFP2 transceiver is turn ON\n1=SFP2 transceiver is turn OFF" + }, + [OOB_BCM54616S_INT] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x01, .mask = 1 << 3, + .note ="0=BCM54616S PHY interrupt occurrs\n1=BCM54616S PHY interrupt is not occurrs" + }, +}; + +unsigned char dni_log2 (unsigned char num){ + unsigned char num_log2 = 0; + while(num > 0){ + num = num >> 1; + num_log2 += 1; + } + return num_log2 -1; +} + +void set_direction(struct i2c_device_platform_data *pdata, unsigned char reg, unsigned char mask){ + + int value; + int read_only; + unsigned char mask_out; + unsigned char set_data; + + read_only = 1; //Configuration:GPI + if (reg > 0x1){ + reg = reg - 0x02; + read_only = 0; //Configuration:GPO + } + + value = i2c_smbus_read_byte_data(pdata->client, reg + 0x06); + mask_out = value & ~(mask); + + if(read_only){ + set_data = mask_out | mask; + } + else{ + set_data = mask_out; + } + + i2c_smbus_write_byte_data(pdata->client, reg + 0x06, set_data); + return; +} + +static ssize_t get_gpio_reg(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + int ret; + int mask; + int value; + char note[150]; + unsigned char pca9555_num; + unsigned char reg; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_gpio); + struct i2c_device_platform_data *pdata = i2cdev->platform_data; + + switch(attribute_data[attr->index].addr){ + case PCA9555_A: + pca9555_num = 0; + break; + case PCA9555_B: + pca9555_num = 1; + break; + case PCA9555_C: + pca9555_num = 2; + break; + default: + return sprintf(buf, "attribute address error"); + } + + set_direction(&pdata[pca9555_num], attribute_data[attr->index].reg, attribute_data[attr->index].mask); + + switch (attr->index) { + case PSU1_SMB_ALERT ... OOB_BCM54616S_INT: + reg = attribute_data[attr->index].reg; + mask = attribute_data[attr->index].mask; + value = i2c_smbus_read_byte_data(pdata[pca9555_num].client, reg); + sprintf(note, "\n%s\n",attribute_data[attr->index].note); + value = (value & mask); + break; + default: + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0xFF: + return sprintf(buf, "0x%02x%s", value, note); + case 0x0F: + return sprintf(buf, "0x%01x%s", value, note); + case 0xF0: + value = value >> 4; + return sprintf(buf, "0x%01x%s", value, note); + case 0xC0: + value = value >> 6; + return sprintf(buf, "0x%01x%s", value, note); + case 0x30: + value = value >> 4; + return sprintf(buf, "0x%01x%s", value, note); + default : + value = value >> dni_log2(mask); + return sprintf(buf, "%d%s", value, note); + } +} + + +static ssize_t set_gpio_reg(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + int err; + int value; + unsigned long set_data; + unsigned char set_reg; + unsigned char mask; + unsigned char mask_out; + unsigned char pca9555_num; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_gpio); + struct i2c_device_platform_data *pdata = i2cdev->platform_data; + + err = kstrtoul(buf, 0, &set_data); + if (err){ + return err; + } + + if (set_data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + switch(attribute_data[attr->index].addr){ + case PCA9555_A: + pca9555_num = 0; + break; + case PCA9555_B: + pca9555_num = 1; + break; + case PCA9555_C: + pca9555_num = 2; + break; + default: + return sprintf(buf, "attribute address error"); + } + + set_direction(&pdata[pca9555_num], attribute_data[attr->index].reg, attribute_data[attr->index].mask); + + switch (attr->index) { + case PSU1_SMB_ALERT ... OOB_BCM54616S_INT: + set_reg = attribute_data[attr->index].reg; + mask = attribute_data[attr->index].mask; + value = i2c_smbus_read_byte_data(pdata[pca9555_num].client, set_reg); + mask_out = value & ~(mask); + break; + default: + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0xFF: + set_data = mask_out | (set_data & mask); + break; + case 0x0F: + set_data = mask_out | (set_data & mask); + break; + case 0xF0: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + case 0xC0: + set_data = set_data << 6; + set_data = mask_out | (set_data & mask); + break; + case 0x30: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + default : + set_data = mask_out | (set_data << dni_log2(mask) ); + } + + i2c_smbus_write_byte_data(pdata[pca9555_num].client, set_reg, set_data); + return count; +} +static SENSOR_DEVICE_ATTR(psu1_smb_alert, S_IRUGO, get_gpio_reg, NULL, PSU1_SMB_ALERT); +static SENSOR_DEVICE_ATTR(psu2_smb_alert, S_IRUGO, get_gpio_reg, NULL, PSU2_SMB_ALERT); +static SENSOR_DEVICE_ATTR(eeprom_wp, S_IRUGO | S_IWUSR, get_gpio_reg, set_gpio_reg, EEPROM_WP); +static SENSOR_DEVICE_ATTR(fan1_led_ag, S_IRUGO | S_IWUSR, get_gpio_reg, set_gpio_reg, FAN1_LED_AG); +static SENSOR_DEVICE_ATTR(fan2_led_ag, S_IRUGO | S_IWUSR, get_gpio_reg, set_gpio_reg, FAN2_LED_AG); +static SENSOR_DEVICE_ATTR(d_fan_alert, S_IRUGO, get_gpio_reg, NULL, D_FAN_ALERT); +static SENSOR_DEVICE_ATTR(psu1_pres, S_IRUGO, get_gpio_reg, NULL, PSU1_PRES); +static SENSOR_DEVICE_ATTR(psu2_pres, S_IRUGO, get_gpio_reg, NULL, PSU2_PRES); +static SENSOR_DEVICE_ATTR(fan_eeprom_wp, S_IRUGO | S_IWUSR, get_gpio_reg, set_gpio_reg, FAN_EEPROM_WP); +static SENSOR_DEVICE_ATTR(d_fan_m_present2, S_IRUGO, get_gpio_reg, NULL, D_FAN_M_PRESENT2); +static SENSOR_DEVICE_ATTR(d_fan_m_present1, S_IRUGO, get_gpio_reg, NULL, D_FAN_M_PRESENT1); +static SENSOR_DEVICE_ATTR(psu1_pg, S_IRUGO, get_gpio_reg, NULL, PSU1_PG); +static SENSOR_DEVICE_ATTR(psu2_pg, S_IRUGO, get_gpio_reg, NULL, PSU2_PG); +static SENSOR_DEVICE_ATTR(bcm54282_int, S_IRUGO, get_gpio_reg, NULL, BCM54282_INT); + +static SENSOR_DEVICE_ATTR(sfp_mod_p1, S_IRUGO, get_gpio_reg, NULL, SFP_MOD_P1); +static SENSOR_DEVICE_ATTR(sfp_rxlos_p1, S_IRUGO, get_gpio_reg, NULL, SFP_RXLOS_P1); +static SENSOR_DEVICE_ATTR(sfp_mod_p2, S_IRUGO, get_gpio_reg, NULL, SFP_MOD_P2); +static SENSOR_DEVICE_ATTR(sfp_rxlos_p2, S_IRUGO, get_gpio_reg, NULL, SFP_RXLOS_P2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault_p1, S_IRUGO, get_gpio_reg, NULL, SFP_TX_FAULT_P1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault_p2, S_IRUGO , get_gpio_reg, NULL, SFP_TX_FAULT_P2); +static SENSOR_DEVICE_ATTR(sfp_tx_dis_p1, S_IRUGO | S_IWUSR, get_gpio_reg, set_gpio_reg, SFP_TX_DIS_P1); +static SENSOR_DEVICE_ATTR(sfp_tx_dis_p2, S_IRUGO | S_IWUSR, get_gpio_reg, set_gpio_reg, SFP_TX_DIS_P2); +static SENSOR_DEVICE_ATTR(oob_bcm54616s_int, S_IRUGO, get_gpio_reg, NULL, OOB_BCM54616S_INT); + +static struct attribute *et6248brb_psu_attrs[] = { + &sensor_dev_attr_psu1_smb_alert.dev_attr.attr, + &sensor_dev_attr_psu2_smb_alert.dev_attr.attr, + &sensor_dev_attr_psu1_pres.dev_attr.attr, + &sensor_dev_attr_psu2_pres.dev_attr.attr, + &sensor_dev_attr_psu1_pg.dev_attr.attr, + &sensor_dev_attr_psu2_pg.dev_attr.attr, + NULL, +}; + +static struct attribute *et6248brb_fan_attrs[] = { + &sensor_dev_attr_fan1_led_ag.dev_attr.attr, + &sensor_dev_attr_fan2_led_ag.dev_attr.attr, + &sensor_dev_attr_d_fan_alert.dev_attr.attr, + &sensor_dev_attr_fan_eeprom_wp.dev_attr.attr, + &sensor_dev_attr_d_fan_m_present1.dev_attr.attr, + &sensor_dev_attr_d_fan_m_present2.dev_attr.attr, + NULL, +}; + +static struct attribute *et6248brb_sfp_attrs[] = { + &sensor_dev_attr_sfp_mod_p1.dev_attr.attr, + &sensor_dev_attr_sfp_rxlos_p1.dev_attr.attr, + &sensor_dev_attr_sfp_mod_p2.dev_attr.attr, + &sensor_dev_attr_sfp_rxlos_p2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault_p1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault_p2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_dis_p1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_dis_p2.dev_attr.attr, + NULL, +}; + +static struct attribute *et6248brb_others_attrs[] = { + &sensor_dev_attr_eeprom_wp.dev_attr.attr, + &sensor_dev_attr_bcm54282_int.dev_attr.attr, + &sensor_dev_attr_oob_bcm54616s_int.dev_attr.attr, + NULL, +}; + +static struct attribute_group et6248brb_psu_attr_grp = { + .attrs = et6248brb_psu_attrs, +}; + +static struct attribute_group et6248brb_fan_attr_grp = { + .attrs = et6248brb_fan_attrs, + +}; +static struct attribute_group et6248brb_sfp_attr_grp = { + .attrs = et6248brb_sfp_attrs, +}; + +static struct attribute_group et6248brb_others_attr_grp = { + .attrs = et6248brb_others_attrs, +}; +/*---------------- gpio device - end ------------- */ + +/*---------------- gpio driver - start ----------- */ +static int __init gpio_device_probe(struct platform_device *pdev) +{ + struct i2c_device_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + if(pdata->info.addr == PCA9555_A){ + kobj_gpio = &pdev->dev.kobj; + kobj_psu = kobject_create_and_add("PSU", &pdev->dev.kobj); + if (!kobj_psu){ + printk(KERN_WARNING "Fail to create 'PSU' directory"); + goto error; + } + + kobj_fan = kobject_create_and_add("FAN", &pdev->dev.kobj); + if (!kobj_fan){ + printk(KERN_WARNING "Fail to create 'FAN' directory"); + goto error; + } + + kobj_sfp = kobject_create_and_add("SFP", &pdev->dev.kobj); + if (!kobj_sfp){ + printk(KERN_WARNING "Fail to create 'SFP' directory"); + goto error; + } + kobj_others = kobject_create_and_add("Others", &pdev->dev.kobj); + if (!kobj_others){ + printk(KERN_WARNING "Fail to create 'Others' directory"); + goto error; + } + ret = sysfs_create_group(kobj_psu, &et6248brb_psu_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create 'psu' attribute group"); + goto error; + } + ret = sysfs_create_group(kobj_fan, &et6248brb_fan_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create 'fan' attribute group"); + goto error; + } + ret = sysfs_create_group(kobj_sfp, &et6248brb_sfp_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create 'sfp' attribute group"); + goto error; + } + ret = sysfs_create_group(kobj_others, &et6248brb_others_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create 'others' attribute group"); + goto error; + } + } + return 0; + +error: + kobject_put(kobj_gpio); + kobject_put(kobj_psu); + kobject_put(kobj_fan); + kobject_put(kobj_sfp); + kobject_put(kobj_others); + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit gpio_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else if(pdata->info.addr == PCA9555_A){ + sysfs_remove_group(kobj_gpio, &et6248brb_psu_attr_grp); + sysfs_remove_group(kobj_fan, &et6248brb_fan_attr_grp); + sysfs_remove_group(kobj_sfp, &et6248brb_sfp_attr_grp); + sysfs_remove_group(kobj_others, &et6248brb_others_attr_grp); + kobject_put(kobj_gpio); + kobject_put(kobj_fan); + kobject_put(kobj_psu); + kobject_put(kobj_sfp); + kobject_put(kobj_others); + } + + if (pdata->client) { + if (!parent) { + parent = (pdata->client)->adapter; + } + i2c_unregister_device(pdata->client); + } + + i2c_put_adapter(parent); + return 0; +} + +static struct platform_driver gpio_device_driver = { + .probe = gpio_device_probe, + .remove = __exit_p(gpio_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-et6248brb-gpio", + } +}; +/*---------------- gpio driver - end ------------- */ + +/*---------------- module initialization ------------- */ +static int __init delta_et6248brb_platform_init(void) +{ + struct i2c_adapter *adapter; + + int ret, i = 0, j = 0; + printk("et6248brb_platform module initialization\n"); + + //Use pca9547 in i2c_mux_pca954x.c + adapter = i2c_get_adapter(BUS1); + i2c_client_9547 = i2c_new_device(adapter, &i2c_info_pca9547[0]); + i2c_put_adapter(adapter); + + // register the i2c devices + ret = platform_driver_register(&i2c_device_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_driver; + } + + // register the i2c devices + ret = platform_driver_register(&gpio_device_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_gpio_device_driver; + } + + for (i = 0; i < ARRAY_SIZE(et6248brb_i2c_device); i++) + { + ret = platform_device_register(&et6248brb_i2c_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_et6248brb_i2c_device; + } + } + + for (j = 0; j < ARRAY_SIZE(et6248brb_gpio_device); j++) + { + ret = platform_device_register(&et6248brb_gpio_device[j]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", j); + goto error_et6248brb_gpio_device; + } + } + + return 0; +error_et6248brb_gpio_device: + j--; + for (; j >= 0; j--) { + platform_device_unregister(&et6248brb_gpio_device[j]); + } +error_et6248brb_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&et6248brb_i2c_device[i]); + } + platform_driver_unregister(&gpio_device_driver); +error_gpio_device_driver: + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + return ret; +} + +static void __exit delta_et6248brb_platform_exit(void) +{ + int i = 0; + + for ( i = 0; i < ARRAY_SIZE(et6248brb_i2c_device); i++ ) { + platform_device_unregister(&et6248brb_i2c_device[i]); + } + + for ( i = 0; i < ARRAY_SIZE(et6248brb_gpio_device); i++ ) { + platform_device_unregister(&et6248brb_gpio_device[i]); + } + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&gpio_device_driver); + i2c_unregister_device(i2c_client_9547); +} + +module_init(delta_et6248brb_platform_init); +module_exit(delta_et6248brb_platform_exit); + +MODULE_DESCRIPTION("DNI et6248brb Platform Support"); +MODULE_AUTHOR("Jacky Liu "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/dni_gpio.c b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/dni_gpio.c new file mode 100644 index 000000000000..127cf6af13ab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/dni_gpio.c @@ -0,0 +1,697 @@ +/* + * Intel ICH6-10, Series 5 and 6, Atom C2000 (Avoton/Rangeley) GPIO driver + * + * Copyright (C) 2010 Extreme Engineering Solutions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +#include +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + +#include +#include +#include +#include +#include + +#define DRV_NAME "gpio_ich" + +/* + * GPIO register offsets in GPIO I/O space. + * Each chunk of 32 GPIOs is manipulated via its own USE_SELx, IO_SELx, and + * LVLx registers. Logic in the read/write functions takes a register and + * an absolute bit number and determines the proper register offset and bit + * number in that register. For example, to read the value of GPIO bit 50 + * the code would access offset ichx_regs[2(=GPIO_LVL)][1(=50/32)], + * bit 18 (50%32). + */ +enum GPIO_REG { + GPIO_USE_SEL = 0, + GPIO_IO_SEL, + GPIO_LVL, + GPO_BLINK +}; + +static const u8 ichx_regs[4][3] = { + {0x00, 0x30, 0x40}, /* USE_SEL[1-3] offsets */ + {0x04, 0x34, 0x44}, /* IO_SEL[1-3] offsets */ + {0x0c, 0x38, 0x48}, /* LVL[1-3] offsets */ + {0x18, 0x18, 0x18}, /* BLINK offset */ +}; + +static const u8 ichx_reglen[3] = { + 0x30, 0x10, 0x10, +}; + +static const u8 avoton_regs[4][3] = { + {0x00, 0x80, 0x00}, + {0x04, 0x84, 0x00}, + {0x08, 0x88, 0x00}, +}; + +static const u8 avoton_reglen[3] = { + 0x10, 0x10, 0x00, +}; + +#define ICHX_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start) +#define ICHX_READ(reg, base_res) inl((reg) + (base_res)->start) + +struct ichx_desc { + /* Max GPIO pins the chipset can have */ + uint ngpio; + + /* chipset registers */ + const u8 (*regs)[3]; + const u8 *reglen; + + /* GPO_BLINK is available on this chipset */ + bool have_blink; + + /* Whether the chipset has GPIO in GPE0_STS in the PM IO region */ + bool uses_gpe0; + + /* USE_SEL is bogus on some chipsets, eg 3100 */ + u32 use_sel_ignore[3]; + + /* Some chipsets have quirks, let these use their own request/get */ + int (*request)(struct gpio_chip *chip, unsigned offset); + int (*get)(struct gpio_chip *chip, unsigned offset); + + /* + * Some chipsets don't let reading output values on GPIO_LVL register + * this option allows driver caching written output values + */ + bool use_outlvl_cache; +}; + +static struct { + spinlock_t lock; + struct platform_device *dev; + struct gpio_chip chip; + struct resource *gpio_base; /* GPIO IO base */ + struct resource *pm_base; /* Power Mangagment IO base */ + struct ichx_desc *desc; /* Pointer to chipset-specific description */ + u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */ + u8 use_gpio; /* Which GPIO groups are usable */ + int outlvl_cache[3]; /* cached output values */ +} ichx_priv; + +static int modparam_gpiobase = -1; /* dynamic */ +module_param_named(gpiobase, modparam_gpiobase, int, 0444); +MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, " + "which is the default."); + +static int ichx_write_bit(int reg, unsigned nr, int val, int verify) +{ + unsigned long flags; + u32 data, tmp; + int reg_nr = nr / 32; + int bit = nr & 0x1f; + int ret = 0; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + { + data = ichx_priv.outlvl_cache[reg_nr]; + } + else + { + data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + } + if (val) + data |= 1 << bit; + else + data &= ~(1 << bit); + + ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + ichx_priv.outlvl_cache[reg_nr] = data; + + tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + if (verify && data != tmp) + ret = -EPERM; + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return ret; +} + +static int ichx_read_bit(int reg, unsigned nr) +{ + unsigned long flags; + u32 data; + int reg_nr = nr / 32; + int bit = nr & 0x1f; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + data = ichx_priv.outlvl_cache[reg_nr] | data; + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return data & (1 << bit) ? 1 : 0; +} + +static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) +{ + return !!(ichx_priv.use_gpio & (1 << (nr / 32))); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr) +{ + return ichx_read_bit(GPIO_IO_SEL, nr) ? GPIOF_DIR_IN : GPIOF_DIR_OUT; +} +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + +static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) +{ + /* + * Try setting pin as an input and verify it worked since many pins + * are output-only. + */ + if (ichx_write_bit(GPIO_IO_SEL, nr, 1, 1)) + return -EINVAL; + + return 0; +} + +static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, + int val) +{ + /* Disable blink hardware which is available for GPIOs from 0 to 31. */ + if (nr < 32 && ichx_priv.desc->have_blink) + ichx_write_bit(GPO_BLINK, nr, 0, 0); + + /* Set GPIO output value. */ + ichx_write_bit(GPIO_LVL, nr, val, 0); + + /* + * Try setting pin as an output and verify it worked since many pins + * are input-only. + */ + if (ichx_write_bit(GPIO_IO_SEL, nr, 0, 1)) + return -EINVAL; + + return 0; +} + +static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr) +{ + return ichx_read_bit(GPIO_LVL, nr); +} + +static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr) +{ + unsigned long flags; + u32 data; + + /* + * GPI 0 - 15 need to be read from the power management registers on + * a ICH6/3100 bridge. + */ + if (nr < 16) { + if (!ichx_priv.pm_base) + return -ENXIO; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + /* GPI 0 - 15 are latched, write 1 to clear*/ + ICHX_WRITE(1 << (16 + nr), 0, ichx_priv.pm_base); + data = ICHX_READ(0, ichx_priv.pm_base); + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return (data >> 16) & (1 << nr) ? 1 : 0; + } else { + return ichx_gpio_get(chip, nr); + } +} + +static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr) +{ + if (!ichx_gpio_check_available(chip, nr)) + return -ENXIO; + + /* + * Note we assume the BIOS properly set a bridge's USE value. Some + * chips (eg Intel 3100) have bogus USE values though, so first see if + * the chipset's USE value can be trusted for this specific bit. + * If it can't be trusted, assume that the pin can be used as a GPIO. + */ + if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f))) + return 0; + + return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV; +} + +static int ich6_gpio_request(struct gpio_chip *chip, unsigned nr) +{ + /* + * Fixups for bits 16 and 17 are necessary on the Intel ICH6/3100 + * bridge as they are controlled by USE register bits 0 and 1. See + * "Table 704 GPIO_USE_SEL1 register" in the i3100 datasheet for + * additional info. + */ + if (nr == 16 || nr == 17) + nr -= 16; + + return ichx_gpio_request(chip, nr); +} + +static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val) +{ + ichx_write_bit(GPIO_LVL, nr, val, 0); +} + +static void ichx_gpiolib_setup(struct gpio_chip *chip) +{ + chip->owner = THIS_MODULE; + chip->label = DRV_NAME; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + chip->dev = &ichx_priv.dev->dev; +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) + chip->parent = &ichx_priv.dev->dev; + chip->get_direction = ichx_gpio_get_direction; +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + + /* Allow chip-specific overrides of request()/get() */ + chip->request = ichx_priv.desc->request ? + ichx_priv.desc->request : ichx_gpio_request; + chip->get = ichx_priv.desc->get ? + ichx_priv.desc->get : ichx_gpio_get; + + chip->set = ichx_gpio_set; + chip->direction_input = ichx_gpio_direction_input; + chip->direction_output = ichx_gpio_direction_output; + chip->base = modparam_gpiobase; + chip->ngpio = ichx_priv.desc->ngpio; + chip->can_sleep = false; + chip->dbg_show = NULL; +} + +/* ICH6-based, 631xesb-based */ +static struct ichx_desc ich6_desc = { + /* Bridges using the ICH6 controller need fixups for GPIO 0 - 17 */ + .request = ich6_gpio_request, + .get = ich6_gpio_get, + + /* GPIO 0-15 are read in the GPE0_STS PM register */ + .uses_gpe0 = true, + + .ngpio = 50, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Intel 3100 */ +static struct ichx_desc i3100_desc = { + /* + * Bits 16,17, 20 of USE_SEL and bit 16 of USE_SEL2 always read 0 on + * the Intel 3100. See "Table 712. GPIO Summary Table" of 3100 + * Datasheet for more info. + */ + .use_sel_ignore = {0x00130000, 0x00010000, 0x0}, + + /* The 3100 needs fixups for GPIO 0 - 17 */ + .request = ich6_gpio_request, + .get = ich6_gpio_get, + + /* GPIO 0-15 are read in the GPE0_STS PM register */ + .uses_gpe0 = true, + + .ngpio = 50, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH7 and ICH8-based */ +static struct ichx_desc ich7_desc = { + .ngpio = 50, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH9-based */ +static struct ichx_desc ich9_desc = { + .ngpio = 61, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH10-based - Consumer/corporate versions have different amount of GPIO */ +static struct ichx_desc ich10_cons_desc = { + .ngpio = 61, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; +static struct ichx_desc ich10_corp_desc = { + .ngpio = 72, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Intel 5 series, 6 series, 3400 series, and C200 series */ +static struct ichx_desc intel5_desc = { + .ngpio = 76, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Avoton */ +static struct ichx_desc avoton_desc = { + /* Avoton has only 59 GPIOs, but we assume the first set of register + * (Core) has 32 instead of 31 to keep gpio-ich compliance + */ + .ngpio = 60, + .regs = avoton_regs, + .reglen = avoton_reglen, + .use_outlvl_cache = true, +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int ichx_gpio_request_regions(struct resource *res_base, + const char *name, u8 use_gpio) +{ + int i; + + if (!res_base || !res_base->start || !res_base->end) + return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { + if (!(use_gpio & (1 << i))) + continue; + if (!request_region( + res_base->start + ichx_priv.desc->regs[0][i], + ichx_priv.desc->reglen[i], name)) + goto request_err; + } + return 0; + +request_err: + /* Clean up: release already requested regions, if any */ + for (i--; i >= 0; i--) { + if (!(use_gpio & (1 << i))) + continue; + release_region(res_base->start + ichx_priv.desc->regs[0][i], + ichx_priv.desc->reglen[i]); + } + return -EBUSY; +} + +static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { + if (!(use_gpio & (1 << i))) + continue; + release_region(res_base->start + ichx_priv.desc->regs[0][i], + ichx_priv.desc->reglen[i]); + } +} + +static int ichx_gpio_probe(struct platform_device *pdev) +{ + struct resource *res_base, *res_pm; + int err; + struct lpc_ich_info *ich_info = dev_get_platdata(&pdev->dev); + + if (!ich_info) + return -ENODEV; + + ichx_priv.dev = pdev; + + switch (ich_info->gpio_version) { + case ICH_I3100_GPIO: + ichx_priv.desc = &i3100_desc; + break; + case ICH_V5_GPIO: + ichx_priv.desc = &intel5_desc; + break; + case ICH_V6_GPIO: + ichx_priv.desc = &ich6_desc; + break; + case ICH_V7_GPIO: + ichx_priv.desc = &ich7_desc; + break; + case ICH_V9_GPIO: + ichx_priv.desc = &ich9_desc; + break; + case ICH_V10CORP_GPIO: + ichx_priv.desc = &ich10_corp_desc; + break; + case ICH_V10CONS_GPIO: + ichx_priv.desc = &ich10_cons_desc; + break; + case AVOTON_GPIO: + ichx_priv.desc = &avoton_desc; + ichx_priv.outlvl_cache[0] = 0x06; /*core output values*/ + ichx_priv.outlvl_cache[1] = 0x7c0008; /*sus output values*/ + ichx_priv.outlvl_cache[2] = 0x0; /*no used*/ + + break; + default: + return -ENODEV; + } + + spin_lock_init(&ichx_priv.lock); + res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO); + ichx_priv.use_gpio = ich_info->use_gpio; + err = ichx_gpio_request_regions(res_base, pdev->name, + ichx_priv.use_gpio); + if (err) + return err; + + ichx_priv.gpio_base = res_base; + + /* + * If necessary, determine the I/O address of ACPI/power management + * registers which are needed to read the the GPE0 register for GPI pins + * 0 - 15 on some chipsets. + */ + if (!ichx_priv.desc->uses_gpe0) + goto init; + + res_pm = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPE0); + if (!res_pm) { + pr_warn("ACPI BAR is unavailable, GPI 0 - 15 unavailable\n"); + goto init; + } + + if (!request_region(res_pm->start, resource_size(res_pm), + pdev->name)) { + pr_warn("ACPI BAR is busy, GPI 0 - 15 unavailable\n"); + goto init; + } + + ichx_priv.pm_base = res_pm; + +init: + ichx_gpiolib_setup(&ichx_priv.chip); + err = gpiochip_add(&ichx_priv.chip); + if (err) { + pr_err("Failed to register GPIOs\n"); + goto add_err; + } + + pr_info("GPIO from %d to %d on %s\n", ichx_priv.chip.base, + ichx_priv.chip.base + ichx_priv.chip.ngpio - 1, DRV_NAME); + + return 0; + +add_err: + ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio); + if (ichx_priv.pm_base) + release_region(ichx_priv.pm_base->start, + resource_size(ichx_priv.pm_base)); + return err; +} + +static int ichx_gpio_remove(struct platform_device *pdev) +{ + int err; + + err = gpiochip_remove(&ichx_priv.chip); + if (err) { + dev_err(&pdev->dev, "%s failed, %d\n", + "gpiochip_remove()", err); + return err; + } + + ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio); + if (ichx_priv.pm_base) + release_region(ichx_priv.pm_base->start, + resource_size(ichx_priv.pm_base)); + + return 0; +} + +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int ichx_gpio_request_regions(struct device *dev, + struct resource *res_base, const char *name, u8 use_gpio) +{ + int i; + + if (!res_base || !res_base->start || !res_base->end) + return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { + if (!(use_gpio & (1 << i))) + continue; + if (!devm_request_region(dev, + res_base->start + ichx_priv.desc->regs[0][i], + ichx_priv.desc->reglen[i], name)) + return -EBUSY; + } + return 0; +} + +static int ichx_gpio_probe(struct platform_device *pdev) +{ + struct resource *res_base, *res_pm; + int err; + struct lpc_ich_info *ich_info = dev_get_platdata(&pdev->dev); + + if (!ich_info) + return -ENODEV; + + ichx_priv.dev = pdev; + + switch (ich_info->gpio_version) { + case ICH_I3100_GPIO: + ichx_priv.desc = &i3100_desc; + break; + case ICH_V5_GPIO: + ichx_priv.desc = &intel5_desc; + break; + case ICH_V6_GPIO: + ichx_priv.desc = &ich6_desc; + break; + case ICH_V7_GPIO: + ichx_priv.desc = &ich7_desc; + break; + case ICH_V9_GPIO: + ichx_priv.desc = &ich9_desc; + break; + case ICH_V10CORP_GPIO: + ichx_priv.desc = &ich10_corp_desc; + break; + case ICH_V10CONS_GPIO: + ichx_priv.desc = &ich10_cons_desc; + break; + case AVOTON_GPIO: + ichx_priv.desc = &avoton_desc; + ichx_priv.outlvl_cache[0] = 0x06; /*core output values*/ + ichx_priv.outlvl_cache[1] = 0x7c0008; /*sus output values*/ + ichx_priv.outlvl_cache[2] = 0x0; /*no used*/ + break; + default: + return -ENODEV; + } + + spin_lock_init(&ichx_priv.lock); + res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO); + ichx_priv.use_gpio = ich_info->use_gpio; + err = ichx_gpio_request_regions(&pdev->dev, res_base, pdev->name, + ichx_priv.use_gpio); + if (err) + return err; + + ichx_priv.gpio_base = res_base; + + /* + * If necessary, determine the I/O address of ACPI/power management + * registers which are needed to read the the GPE0 register for GPI pins + * 0 - 15 on some chipsets. + */ + if (!ichx_priv.desc->uses_gpe0) + goto init; + + res_pm = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPE0); + if (!res_pm) { + pr_warn("ACPI BAR is unavailable, GPI 0 - 15 unavailable\n"); + goto init; + } + + if (!devm_request_region(&pdev->dev, res_pm->start, + resource_size(res_pm), pdev->name)) { + pr_warn("ACPI BAR is busy, GPI 0 - 15 unavailable\n"); + goto init; + } + + ichx_priv.pm_base = res_pm; + +init: + ichx_gpiolib_setup(&ichx_priv.chip); + err = gpiochip_add_data(&ichx_priv.chip, NULL); + if (err) { + pr_err("Failed to register GPIOs\n"); + return err; + } + + pr_info("GPIO from %d to %d on %s\n", ichx_priv.chip.base, + ichx_priv.chip.base + ichx_priv.chip.ngpio - 1, DRV_NAME); + + return 0; +} + +static int ichx_gpio_remove(struct platform_device *pdev) +{ + gpiochip_remove(&ichx_priv.chip); + + return 0; +} +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + +static struct platform_driver ichx_gpio_driver = { + .driver = { +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + .owner = THIS_MODULE, +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + .name = DRV_NAME, + }, + .probe = ichx_gpio_probe, + .remove = ichx_gpio_remove, +}; + +module_platform_driver(ichx_gpio_driver); + +MODULE_AUTHOR("Johnson Lu "); +MODULE_DESCRIPTION("GPIO interface for Intel ICH series"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:"DRV_NAME); diff --git a/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/et-6248brb_platform_init.sh b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/et-6248brb_platform_init.sh new file mode 100755 index 000000000000..3779e4684d84 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/et-6248brb_platform_init.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +#platform init script for Delta et-6248brb + +#fan speed monitol start +/usr/share/sonic/device/x86_64-delta_et-6248brb-r0/fancontrol.service /usr/share/sonic/device/x86_64-delta_et-6248brb-r0/fancontrol & +sh /usr/local/bin/led_status.sh & + + +exit 0 + diff --git a/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/led_status.sh b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/led_status.sh new file mode 100644 index 000000000000..74276a6d31f3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/led_status.sh @@ -0,0 +1,165 @@ +#!/bin/bash + +FAN1_EEPROM="-y 0 0x55 0x0a" +FAN2_EEPROM="-y 0 0x56 0x0a" +FAN1_RPM="/sys/bus/i2c/devices/0-002e/fan1_input" +FAN2_RPM="/sys/bus/i2c/devices/0-002e/fan2_input" +FAN_TRAY1_LED="/sys/devices/platform/delta-et6248brb-gpio.0/FAN/fan1_led_ag" +FAN_TRAY2_LED="/sys/devices/platform/delta-et6248brb-gpio.0/FAN/fan2_led_ag" + +if [ `uname -a | awk '{print $3}'` = "4.9.0-7-amd64" ]; then + SYS_LED_G="/sys/class/gpio/gpio453/value" + SYS_LED_R="/sys/class/gpio/gpio454/value" + PWR_LED_G="/sys/class/gpio/gpio455/value" + PWR_LED_R="/sys/class/gpio/gpio489/value" + FAN_LED_G="/sys/class/gpio/gpio485/value" + FAN_LED_R="/sys/class/gpio/gpio494/value" +else + SYS_LED_G="/sys/class/gpio/gpio197/value" + SYS_LED_R="/sys/class/gpio/gpio198/value" + PWR_LED_G="/sys/class/gpio/gpio199/value" + PWR_LED_R="/sys/class/gpio/gpio233/value" + FAN_LED_G="/sys/class/gpio/gpio229/value" + FAN_LED_R="/sys/class/gpio/gpio238/value" +fi + +PSU1_EEPROM="-y 2 0x50 0x00" +PSU2_EEPROM="-y 3 0x51 0x00" +PSU1_PG="/sys/devices/platform/delta-et6248brb-gpio.0/PSU/psu1_pg" +PSU2_PG="/sys/devices/platform/delta-et6248brb-gpio.0/PSU/psu2_pg" + +catfaneeprom(){ + fan_eeprom_num=0 + i2cget $FAN1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -ne "0" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi + + i2cget $FAN2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -ne "0" ]; then + fan_eeprom_num=$((fan_eeprom_num_num)) + fi +} + +catfanspeed(){ + + fan_rpm_normal_num=0 + fan1_rpm_normal_num=0 + fan1_rpm=`cat $FAN1_RPM` + + if [ "${fan1_rpm}" -ne "960" ] && [ "${fan1_rpm}" -ne "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num+1)) + elif [ "${fan1_rpm}" -eq "960" ] || [ "${fan1_rpm}" -eq "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num)) + fi + + fan2_rpm_normal_num=0 + fan2_rpm=`cat $FAN2_RPM` + + if [ "${fan2_rpm}" -ne "960" ] && [ "${fan2_rpm}" -ne "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num+1)) + elif [ "${fan2_rpm}" -eq "960" ] || [ "${fan2_rpm}" -eq "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num)) + fi + + fan_rpm_normal_num=$((fan1_rpm_normal_num+fan2_rpm_normal_num)) +} + +setfanled(){ + if [ "${fan_eeprom_num}" -eq "2" ] && [ "${fan_rpm_normal_num}" -eq "2" ]; then + echo "1" > $FAN_LED_G + echo "0" > $FAN_LED_R + elif [ "${fan_eeprom_num}" -lt "2" ] || [ "${fan_rpm_normal_num}" -lt "2" ]; then + echo "1" > $FAN_LED_R + echo "0" > $FAN_LED_G + fi +} + +setfantrayled(){ + if [ "${fan1_rpm_normal_num}" -eq "1" ]; then + echo "0x02" > $FAN_TRAY1_LED + else + echo "0x01" > $FAN_TRAY1_LED + fi + + if [ "${fan2_rpm_normal_num}" -eq "1" ]; then + echo "0x02" > $FAN_TRAY2_LED + else + echo "0x01" > $FAN_TRAY2_LED + fi +} + +catpsueeprom(){ + psu_eeprom_num=0 + i2cget $PSU1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu_eeprom_num=$((psu_eeprom_num+1)) + elif [ "`echo $?`" -ne "0" ]; then + psu_eeprom_num=$((psu_eeprom_num)) + fi + + i2cget $PSU2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu_eeprom_num=$((psu_eeprom_num+1)) + elif [ "`echo $?`" -ne "0" ]; then + psu_eeprom_num=$((psu_eeprom_num)) + fi +} + +catpsupowergood(){ + + psu_normal_num=0 + psu1_normal_num=0 + psu1_good=`cat $PSU1_PG | head -n 1` + + if [ "${psu1_good}" -eq "1" ]; then + psu1_normal_num=$((psu1_normal_num+1)) + elif [ "${psu1_good}" -eq "0" ]; then + psu1_normal_num=$((psu1_normal_num)) + fi + + psu2_normal_num=0 + psu2_good=`cat $PSU2_PG | head -n 1` + + if [ "${psu2_good}" -eq "1" ]; then + psu2_normal_num=$((psu2_normal_num+1)) + elif [ "${psu2_good}" -eq "0" ]; then + psu2_normal_num=$((psu2_normal_num)) + fi + + psu_normal_num=$((psu1_normal_num+psu2_normal_num)) +} + +setpsuled(){ + if [ "${psu_eeprom_num}" -eq "2" ] && [ "${psu_normal_num}" -eq "2" ]; then + echo "1" > $PWR_LED_G + echo "0" > $PWR_LED_R + elif [ "${psu_eeprom_num}" -lt "2" ] || [ "${psu_normal_num}" -lt "2" ]; then + echo "1" > $PWR_LED_R + echo "0" > $PWR_LED_G + fi +} + +platformstatus(){ + echo "1" > $SYS_LED_G + echo "0" > $SYS_LED_R + catfaneeprom + catfanspeed + setfanled + setfantrayled + + catpsueeprom + catpsupowergood + setpsuled +} + +while true +do + platformstatus + sleep 1 +done + diff --git a/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag5648.service b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag5648.service new file mode 100644 index 000000000000..7a74c0155473 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag5648.service @@ -0,0 +1,13 @@ +[Unit] +Description=Delta ag5648 Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-ag5648 start +ExecStop=-/etc/init.d/platform-modules-ag5648 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9032v1.service b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9032v1.service new file mode 100644 index 000000000000..bfa0fd296f59 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9032v1.service @@ -0,0 +1,13 @@ +[Unit] +Description=Delta ag9032v1 Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-ag9032v1 start +ExecStop=-/etc/init.d/platform-modules-ag9032v1 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9064.service b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9064.service new file mode 100644 index 000000000000..80f6836bfdbc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9064.service @@ -0,0 +1,13 @@ +[Unit] +Description=Delta ag9064 Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-ag9064 start +ExecStop=-/etc/init.d/platform-modules-ag9064 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-et-6248brb.service b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-et-6248brb.service new file mode 100644 index 000000000000..901bcffaea8e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-et-6248brb.service @@ -0,0 +1,13 @@ +[Unit] +Description=Delta et-6248brb Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-et-6248brb start +ExecStop=-/etc/init.d/platform-modules-et-6248brb stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/.gitignore b/platform/broadcom/sonic-platform-modules-ingrasys/.gitignore new file mode 100644 index 000000000000..7f287d538227 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/.gitignore @@ -0,0 +1,50 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/LICENSE b/platform/broadcom/sonic-platform-modules-ingrasys/LICENSE new file mode 100644 index 000000000000..9cecc1d4669e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/changelog b/platform/broadcom/sonic-platform-modules-ingrasys/debian/changelog new file mode 100644 index 000000000000..338234f97c45 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/changelog @@ -0,0 +1,22 @@ +platform-driver (1.1.0) unstable; urgency=low + + * Add support for s9200-64x + + -- developer Fri, 26 May 2017 11:00:00 +0800 + +platform-driver (1.1.0) unstable; urgency=low + + * Add support for s8810-32q + + -- developer Fri, 26 May 2017 11:00:00 +0800 +platform-driver (1.1.0) unstable; urgency=low + + * Add support for s8900 series + + -- developer Wed, 29 Mar 2017 11:00:00 +0800 + +platform-driver (1.0.0) unstable; urgency=low + + * Initial release (Closes: #nnnn) + + -- developer Wed, 05 Oct 2016 16:30:45 +0800 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/compat b/platform/broadcom/sonic-platform-modules-ingrasys/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/control b/platform/broadcom/sonic-platform-modules-ingrasys/debian/control new file mode 100644 index 000000000000..99c87f772ed5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/control @@ -0,0 +1,26 @@ +Source: platform-driver +Section: unknown +Priority: optional +Maintainer: Wade He +Build-Depends: debhelper (>= 9), dh-systemd +Standards-Version: 1.0.0 + +Package: sonic-platform-ingrasys-s9100 +Architecture: amd64 +Description: This package contains S9100 platform driver utility for SONiC project. + +Package: sonic-platform-ingrasys-s8900-64xc +Architecture: amd64 +Description: This package contains S8900-64XC platform driver utility for SONiC project. + +Package: sonic-platform-ingrasys-s8900-54xc +Architecture: amd64 +Description: This package contains S8900-54XC platform driver utility for SONiC project. + +Package: sonic-platform-ingrasys-s8810-32q +Architecture: amd64 +Description: This package contains S8810-32Q platform driver utility for SONiC project. + +Package: sonic-platform-ingrasys-s9200-64x +Architecture: amd64 +Description: This package contains S9200-64X platform driver utility for SONiC project. diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/rules b/platform/broadcom/sonic-platform-modules-ingrasys/debian/rules new file mode 100755 index 000000000000..759d26c5c4d1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/rules @@ -0,0 +1,42 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_PRE_NAME := sonic-platform-ingrasys +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= s9100 s8900-64xc s8900-54xc s8810-32q s9200-64x +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CONF_DIR := conf + +%: + dh $@ --with systemd + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/sbin; \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/*.sh \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/sbin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + done) + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8810-32q.init b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8810-32q.init new file mode 100644 index 000000000000..19f51c0a9666 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8810-32q.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S8810-32Q board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s8810-32q.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8900-54xc.init b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8900-54xc.init new file mode 100644 index 000000000000..f2e4932b3294 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8900-54xc.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S8900-54XC board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s8900-54xc.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8900-64xc.init b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8900-64xc.init new file mode 100644 index 000000000000..2790ca3517c6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8900-64xc.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S8900-64XC board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s8900-64xc.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9100.init b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9100.init new file mode 100644 index 000000000000..017708708786 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9100.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S9100 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9100.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9200-64x.init b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9200-64x.init new file mode 100644 index 000000000000..076838e1aa0d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9200-64x.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S9200-64X board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9200-64x.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/README.md b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/README.md new file mode 100644 index 000000000000..dec38cb33393 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/README.md @@ -0,0 +1,185 @@ +# Ingrasys S8810-32Q Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, 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 . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S8810-32Q is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S8810-32Q platform. + +### I2C i801 + +The I2C i801 on Ingrasys S8810-32Q can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S8810-32Q. + +### I2C iSMT + +The I2C iSMT module on S8810-32Q can be found in +`/sys/bus/i2c/devices/i2c-1/` + +This is I2C bus for CPLD, HWM, power controller and I2C Switches. + +The i801 module must be loaded third on Ingrasys S8810-32Q. + +### I2C PCA9548 +The PCA9548 module on S8810-32Q can be found in +`/sys/bus/i2c/devices/i2c-2/` , `/sys/bus/i2c/devices/i2c-3/`, +`/sys/bus/i2c/devices/i2c-4/`, `/sys/bus/i2c/devices/i2c-5/`, +`/sys/bus/i2c/devices/i2c-6/`, `/sys/bus/i2c/devices/i2c-7/`, +`/sys/bus/i2c/devices/i2c-8/`, `/sys/bus/i2c/devices/i2c-9/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S8810-32Q. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S8810-32Q platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s8810-32q package is installed on the S8810-32Q, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-9/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/9-0054/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber on|off + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/Makefile b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/Makefile new file mode 100755 index 000000000000..7c782163f402 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := eeprom_mb.o +obj-m += ingrasys_s8810_32q_psu.o diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/eeprom_mb.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/eeprom_mb.c new file mode 100755 index 000000000000..2040e3cfc5db --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/eeprom_mb.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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 + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, I2C_CLIENT_END }; + + +/* 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 mb_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 mb_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++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x56) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_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, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys S8810-32Q Mother Board EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/ingrasys_s8810_32q_platform.h b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/ingrasys_s8810_32q_platform.h new file mode 100644 index 000000000000..a88755946e9a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/ingrasys_s8810_32q_platform.h @@ -0,0 +1,148 @@ +#ifndef _S8810_32Q_PLATFORM_H +#define _S8810_32Q_PLATFORM_H + +#include + +// remove debug before release +#define DEBUG + +enum bus_order { + I2C_BUS_MAIN, + MUX_9548_0_CH0, + MUX_9548_0_CH1, + MUX_9548_0_CH2, + MUX_9548_0_CH3, + MUX_9548_0_CH4, + MUX_9548_0_CH5, + MUX_9548_0_CH6, + MUX_9548_0_CH7, + MUX_9548_1_CH0, + MUX_9548_1_CH1, + MUX_9548_1_CH2, + MUX_9548_1_CH3, + MUX_9548_1_CH4, + MUX_9548_1_CH5, + MUX_9548_1_CH6, + MUX_9548_1_CH7, + MUX_9546_0_CH0, + MUX_9546_0_CH1, + MUX_9546_0_CH2, + MUX_9546_0_CH3, + MUX_9546_1_CH0, + MUX_9546_1_CH1, + MUX_9546_1_CH2, + MUX_9546_1_CH3, + MUX_9548_2_CH0, + MUX_9548_2_CH1, + MUX_9548_2_CH2, + MUX_9548_2_CH3, + MUX_9548_2_CH4, + MUX_9548_2_CH5, + MUX_9548_2_CH6, + MUX_9548_2_CH7, + MUX_9548_3_CH0, + MUX_9548_3_CH1, + MUX_9548_3_CH2, + MUX_9548_3_CH3, + MUX_9548_3_CH4, + MUX_9548_3_CH5, + MUX_9548_3_CH6, + MUX_9548_3_CH7, + MUX_9548_4_CH0, + MUX_9548_4_CH1, + MUX_9548_4_CH2, + MUX_9548_4_CH3, + MUX_9548_4_CH4, + MUX_9548_4_CH5, + MUX_9548_4_CH6, + MUX_9548_4_CH7, + MUX_9548_5_CH0, + MUX_9548_5_CH1, + MUX_9548_5_CH2, + MUX_9548_5_CH3, + MUX_9548_5_CH4, + MUX_9548_5_CH5, + MUX_9548_5_CH6, + MUX_9548_5_CH7, + MUX_9548_6_CH0, + MUX_9548_6_CH1, + MUX_9548_6_CH2, + MUX_9548_6_CH3, + MUX_9548_6_CH4, + MUX_9548_6_CH5, + MUX_9548_6_CH6, + MUX_9548_6_CH7, + MUX_9548_7_CH0, + MUX_9548_7_CH1, + MUX_9548_7_CH2, + MUX_9548_7_CH3, + MUX_9548_7_CH4, + MUX_9548_7_CH5, + MUX_9548_7_CH6, + MUX_9548_7_CH7, + MUX_9548_8_CH0, + MUX_9548_8_CH1, + MUX_9548_8_CH2, + MUX_9548_8_CH3, + MUX_9548_8_CH4, + MUX_9548_8_CH5, + MUX_9548_8_CH6, + MUX_9548_8_CH7, + MUX_9548_9_CH0, + MUX_9548_9_CH1, + MUX_9548_9_CH2, + MUX_9548_9_CH3, + MUX_9548_9_CH4, + MUX_9548_9_CH5, + MUX_9548_9_CH6, + MUX_9548_9_CH7, + MUX_9548_10_CH0, + MUX_9548_10_CH1, + MUX_9548_10_CH2, + MUX_9548_10_CH3, + MUX_9548_10_CH4, + MUX_9548_10_CH5, + MUX_9548_10_CH6, + MUX_9548_10_CH7, +}; + +#define I2C_ADDR_MUX_9555_0 (0x20) +#define I2C_ADDR_MUX_9555_1 (0x24) +#define I2C_ADDR_MUX_9555_2 (0x25) +#define I2C_ADDR_MUX_9555_3 (0x26) +#define I2C_ADDR_MUX_9539_0 (0x76) +#define I2C_ADDR_MUX_9539_1 (0x76) +#define I2C_BUS_FAN_STATUS (I2C_BUS_MAIN) +#define I2C_BUS_SYS_LED (MUX_9548_1_CH1) + +#define NUM_OF_I2C_MUX (11) +#define NUM_OF_CPLD (5) +#define NUM_OF_QSFP_PORT (64) +#define NUM_OF_SFP_PORT (2) +#define QSFP_EEPROM_I2C_ADDR (0x50) + +enum gpio_reg { + REG_PORT0_IN, + REG_PORT1_IN, + REG_PORT0_OUT, + REG_PORT1_OUT, + REG_PORT0_POL, + REG_PORT1_POL, + REG_PORT0_DIR, + REG_PORT1_DIR, +}; + +struct ing_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +struct i2c_init_data { + __u16 ch; + __u16 addr; + __u8 reg; + __u8 value; +}; + +#endif diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/ingrasys_s8810_32q_psu.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/ingrasys_s8810_32q_psu.c new file mode 100644 index 000000000000..ae34c8eb33ed --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/ingrasys_s8810_32q_psu.c @@ -0,0 +1,393 @@ +/* + * S8810-32Q PSU driver + * + * Copyright (C) 2017 Ingrasys, 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 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s8810_32q_platform.h" + +static ssize_t show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf); +static struct s8810_psu_data *s8810_psu_update_status(struct device *dev); +static struct s8810_psu_data *s8810_psu_update_eeprom(struct device *dev); +static int s8810_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len); + + +#define DRIVER_NAME "psu" + +// Addresses scanned +static const unsigned short normal_i2c[] = { 0x51, I2C_CLIENT_END }; + +/* PSU EEPROM SIZE */ +#define EEPROM_SZ 256 +#define READ_EEPROM 1 +#define NREAD_EEPROM 0 + +static struct i2c_client cpld_client; + +/* CPLD Registers */ +#define REG_PSU_PG 0x02 +#define REG_PSU_PRSNT 0x03 + +/* CPLD Pins */ +#define PSU1_PRSNT_L 0 +#define PSU2_PRSNT_L 1 +#define PSU1_PWROK 3 +#define PSU2_PWROK 4 + + +/* Driver Private Data */ +struct s8810_psu_data { + struct mutex lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + char eeprom[EEPROM_SZ]; /* psu eeprom data */ + char psuABS; /* PSU absent */ + char psuPG; /* PSU power good */ +}; + +enum psu_index +{ + s8810_psu1, + s8810_psu2 +}; + +/* + * display power good attribute + */ +static ssize_t +show_psu_pg(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s8810_psu_data *data = s8810_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuPG; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + +/* + * display power absent attribute + */ +static ssize_t +show_psu_abs(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s8810_psu_data *data = s8810_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuABS; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + + +/* + * sysfs attributes for psu + */ +static DEVICE_ATTR(psu_pg, S_IRUGO, show_psu_pg, NULL); +static DEVICE_ATTR(psu_abs, S_IRUGO, show_psu_abs, NULL); +static DEVICE_ATTR(psu_eeprom, S_IRUGO, show_psu_eeprom, NULL); + +static struct attribute *s8810_psu_attributes[] = { + &dev_attr_psu_pg.attr, + &dev_attr_psu_abs.attr, + &dev_attr_psu_eeprom.attr, + NULL +}; + +/* + * display psu eeprom content + */ +static ssize_t +show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct s8810_psu_data *data = s8810_psu_update_eeprom(dev); + + memcpy(buf, (char *)data->eeprom, EEPROM_SZ); + return EEPROM_SZ; +} + +static const struct attribute_group s8810_psu_group = { + .attrs = s8810_psu_attributes, +}; + +/* + * check gpio expander is accessible + */ +static int +cpld_detect(struct i2c_client *client) +{ + if (i2c_smbus_read_byte_data(client, REG_PSU_PG) < 0) { + return -ENODEV; + } + + return 0; +} + +/* + * client address init + */ +static void +i2c_devices_client_address_init(struct i2c_client *client) +{ + cpld_client = *client; + cpld_client.addr = 0x33; +} + +static int +s8810_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct s8810_psu_data *data; + int status, err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct s8810_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct s8810_psu_data)); + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + i2c_devices_client_address_init(client); + + err = cpld_detect(&cpld_client); + if (err) { + dev_info(&client->dev, "cpld detect failure\n"); + return err; + } + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &s8810_psu_group); + if (status) { + goto exit_free; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &s8810_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int +s8810_psu_remove(struct i2c_client *client) +{ + struct s8810_psu_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &s8810_psu_group); + kfree(data); + + return 0; +} + + +/* + * psu eeprom read utility + */ +static int +s8810_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len) +{ + int i=0, ret=0; + int blk_max = 32; //max block read size + + /* read eeprom, 32 * 8 = 256 bytes */ + for (i=0; i < EEPROM_SZ/blk_max; i++) { + ret = i2c_smbus_read_i2c_block_data(client, (i*blk_max), blk_max, + data + (i*blk_max)); + if (ret < 0) { + return ret; + } + } + return ret; +} + +/* + * update eeprom content + */ +static struct s8810_psu_data +*s8810_psu_update_eeprom(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s8810_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + char psu_pg = 0; + char psu_prsnt = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + if (time_after(jiffies, data->last_updated + 300 * HZ) + || !data->valid) { + + /* Read psu status */ + + psu_pg = i2c_smbus_read_byte_data(&(cpld_client), REG_PSU_PG); + psu_prsnt = i2c_smbus_read_byte_data(&(cpld_client), REG_PSU_PRSNT); + + /*read psu status from io expander*/ + + if (data->index == s8810_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (psu_pg >> psu_pwrok) & 0x1; + data->psuABS = (psu_prsnt >> psu_prsnt_l) & 0x1; + + /* Read eeprom */ + if (!data->psuABS) { + //clear local eeprom data + memset(data->eeprom, 0, EEPROM_SZ); + + //read eeprom + status = s8810_psu_read_block(client, 0, data->eeprom, + ARRAY_SIZE(data->eeprom)); + + if (status < 0) { + memset(data->eeprom, 0, EEPROM_SZ); + dev_err(&client->dev, "Read eeprom failed, status=(%d)\n", status); + } else { + data->valid = 1; + } + } else { + memset(data->eeprom, 0, EEPROM_SZ); + } + data->last_updated = jiffies; + } + + mutex_unlock(&data->lock); + + return data; +} + +/* + * update psu status + */ +static struct s8810_psu_data +*s8810_psu_update_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s8810_psu_data *data = i2c_get_clientdata(client); + char psu_pg = 0; + char psu_prsnt = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + /* Read psu status */ + + psu_pg = i2c_smbus_read_byte_data(&(cpld_client), REG_PSU_PG); + psu_prsnt = i2c_smbus_read_byte_data(&(cpld_client), REG_PSU_PRSNT); + + /*read psu status from io expander*/ + + if (data->index == s8810_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (psu_pg >> psu_pwrok) & 0x1; + data->psuABS = (psu_prsnt >> psu_prsnt_l) & 0x1; + + mutex_unlock(&data->lock); + + return data; +} + +static const struct i2c_device_id s8810_psu_id[] = { + { "psu1", s8810_psu1 }, + { "psu2", s8810_psu2 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, s8810_psu_id); + +static struct i2c_driver s8810_psu_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = s8810_psu_probe, + .remove = s8810_psu_remove, + .id_table = s8810_psu_id, + .address_list = normal_i2c, +}; + +static int __init s8810_psu_init(void) +{ + return i2c_add_driver(&s8810_psu_driver); +} + +static void __exit s8810_psu_exit(void) +{ + i2c_del_driver(&s8810_psu_driver); +} + +module_init(s8810_psu_init); +module_exit(s8810_psu_exit); + +MODULE_AUTHOR("Jason Tsai "); +MODULE_DESCRIPTION("S8810-32Q psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/service/qsfp-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/service/qsfp-monitor.service new file mode 100644 index 000000000000..3d69fdae0f87 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s8810-32q-monitor.service +After=s8810-32q-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/service/s8810-32q-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/service/s8810-32q-monitor.service new file mode 100644 index 000000000000..644efe443256 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/service/s8810-32q-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s8810_32q_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/i2c_utils.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/i2c_utils.sh new file mode 100644 index 000000000000..416e631423a7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/i2c_utils.sh @@ -0,0 +1,1489 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, 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 . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.1.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +QSFP_ACTION=${2} +MB_EEPROM_ACTION=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_I801_DEVICE=0 +NUM_ISMT_DEVICE=$(( ${NUM_I801_DEVICE} + 1 )) + +#MUX PCA9548#0 +NUM_MUX_9548_0_CHAN0=$(( ${NUM_I801_DEVICE} + 2 )) +NUM_MUX_9548_0_CHAN1=$(( ${NUM_I801_DEVICE} + 3 )) +NUM_MUX_9548_0_CHAN2=$(( ${NUM_I801_DEVICE} + 4 )) +#NUM_MUX_9548_0_CHAN3=$(( ${NUM_I801_DEVICE} + 5 )) +#NUM_MUX_9548_0_CHAN4=$(( ${NUM_I801_DEVICE} + 6 )) +#NUM_MUX_9548_0_CHAN5=$(( ${NUM_I801_DEVICE} + 7 )) +#NUM_MUX_9548_0_CHAN6=$(( ${NUM_I801_DEVICE} + 8 )) +#NUM_MUX_9548_0_CHAN7=$(( ${NUM_I801_DEVICE} + 9 )) + +#MUX PCA9548#1 +NUM_MUX_9548_1_CHAN0=$(( ${NUM_I801_DEVICE} + 10 )) +NUM_MUX_9548_1_CHAN1=$(( ${NUM_I801_DEVICE} + 11 )) +NUM_MUX_9548_1_CHAN2=$(( ${NUM_I801_DEVICE} + 12 )) +NUM_MUX_9548_1_CHAN3=$(( ${NUM_I801_DEVICE} + 13 )) +NUM_MUX_9548_1_CHAN4=$(( ${NUM_I801_DEVICE} + 14 )) +NUM_MUX_9548_1_CHAN5=$(( ${NUM_I801_DEVICE} + 15 )) +NUM_MUX_9548_1_CHAN6=$(( ${NUM_I801_DEVICE} + 16 )) +NUM_MUX_9548_1_CHAN7=$(( ${NUM_I801_DEVICE} + 17 )) + +NUM_MUX_9548_2_CHAN0=$(( ${NUM_I801_DEVICE} + 18 )) +NUM_MUX_9548_3_CHAN0=$(( ${NUM_I801_DEVICE} + 26 )) +NUM_MUX_9548_4_CHAN0=$(( ${NUM_I801_DEVICE} + 34 )) +NUM_MUX_9548_5_CHAN0=$(( ${NUM_I801_DEVICE} + 42 )) + +#MUX Alias +I2C_BUS_PSU1_EEPROM=${NUM_MUX_9548_0_CHAN1} +I2C_BUS_PSU2_EEPROM=${NUM_MUX_9548_0_CHAN2} +I2C_BUS_FAN_STATUS=${NUM_MUX_9548_1_CHAN0} +I2C_BUS_LED_BOARD=${NUM_MUX_9548_1_CHAN0} +I2C_BUS_MB_EEPROM=${NUM_MUX_9548_1_CHAN2} + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_SYS_GPIO="/sys/class/gpio" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon1" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_ISMT_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_ISMT_DEVICE}" +#PATH for MUX PCA9548#0 +PATH_MUX_9548_0_CHAN0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CHAN0}" +PATH_MUX_9548_0_CHAN1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CHAN1}" +PATH_MUX_9548_0_CHAN2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CHAN2}" +#PATH for MUX PCA9548#1 +PATH_MUX_9548_1_CHAN0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN0}" +PATH_MUX_9548_1_CHAN1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}" +PATH_MUX_9548_1_CHAN2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}" +PATH_MUX_9548_1_CHAN3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN3}" +PATH_MUX_9548_1_CHAN4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN4}" +PATH_MUX_9548_1_CHAN5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN5}" +PATH_MUX_9548_1_CHAN6="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN6}" +PATH_MUX_9548_1_CHAN7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN7}" + +#i2cmap and gpiomap path +PATH_GPIOMAP=/tmp/gpiomap +PATH_I2CMAP=/tmp/i2cmap + +I2C_ADDR_MUX_9548_0=0x70 +I2C_ADDR_MUX_9548_1=0x70 +I2C_ADDR_MUX_9548_2=0x71 +I2C_ADDR_MUX_9548_3=0x71 +I2C_ADDR_MUX_9548_4=0x71 +I2C_ADDR_MUX_9548_5=0x71 +I2C_ADDR_DDR3=0x50 +I2C_ADDR_RTC=0x68 +I2C_ADDR_CPLD=0x33 +I2C_ADDR_HWM=0x2F +I2C_ADDR_MUX_9535_FAN=0x20 +I2C_ADDR_MUX_9535_LED=0x22 +I2C_ADDR_MUX_9535_0=0x20 +I2C_ADDR_MUX_9535_1=0x21 +I2C_ADDR_MUX_9535_2=0x22 +I2C_ADDR_MUX_9535_3=0x23 +I2C_ADDR_MUX_9535_4=0x20 +I2C_ADDR_MUX_9535_5=0x21 +I2C_ADDR_MUX_9535_6=0x22 +I2C_ADDR_MUX_9535_7=0x23 +I2C_ADDR_MUX_9535_8=0x20 +I2C_ADDR_MUX_9535_9=0x21 +I2C_ADDR_MUX_9535_10=0x22 +I2C_ADDR_MB_EEPROM=0x56 +I2C_ADDR_QSFP_EEPROM=0x50 +I2C_ADDR_PSU_EEPROM=0x51 + +#sysfs +PATH_SYSFS_PSU1="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU1_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU_EEPROM)" +PATH_SYSFS_PSU2="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU2_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU_EEPROM)" + +#Active High/Low +ACTIVE_LOW=1 +ACTIVE_HIGH=0 +#GPIO Direction In/Out +DIR_IN=in +DIR_OUT=out + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +#W83795 Registers +REG_BANK_SEL=0x00 +REG_VOLT_CTRL1=0x02 +REG_VOLT_CTRL2=0x03 +REG_TEMP_CTRL1=0x04 +REG_TEMP_CTRL2=0x05 + +#PCA9535 Registers +REG_IN_0=0 +REG_IN_1=1 +REG_OUT_0=2 +REG_OUT_1=3 +REG_POLARITY_0=4 +REG_POLARITY_1=5 +REG_CFG_0=6 +REG_CFG_1=7 + +#Bit Mask +BIT_MASK=(1 2 4 8 16 32 64 128) + +#GPIO Offset +GPIO_OFFSET=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "# Version : ${VERSION}" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_temp_init" + echo " : ${0} i2c_fan_init" + echo " : ${0} i2c_volmon_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_gpio_init" + echo " : ${0} i2c_gpio_deinit" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [1-32]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [1-32]" + echo " : ${0} i2c_qsfp_type_get [1-32]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_led_fan_tray_test" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_sys_led green|amber on|off" + echo " : ${0} i2c_fan_led green|amber on|off" + echo " : ${0} i2c_psu1_led green|amber on|off" + echo " : ${0} i2c_psu2_led green|amber on|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +#set i2cmap +function _set_i2cmap { + local i2c_n=$1 + local alias=$2 + + #create i2cmap dir if not exist + mkdir -p $PATH_I2CMAP + + #check i2c_n exists in sysfs + if [ ! -L ${PATH_SYS_I2C_DEVICES}/i2c-${i2c_n} ]; then + echo "${PATH_SYS_I2C_DEVICES}/i2c-${i2c_n} does not exist." + return + fi + + #create or update link + ln -sf ${PATH_SYS_I2C_DEVICES}/i2c-${i2c_n} ${PATH_I2CMAP}/${alias} +} + +#clear i2cmap +function _clear_i2cmap { + #delete i2cmap dir + rm -rf ${PATH_I2CMAP}/ +} + + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + rmmod i2c_ismt + rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_ismt + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + #add MUX PCA9548#0 on I801 + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CHAN0}" ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_0}' > ${PATH_I801_DEVICE}/new_device" + _set_i2cmap ${NUM_MUX_9548_0_CHAN0} "PCA9548_0" + else + echo "pca9548#0 ${I2C_ADDR_MUX_9548_0} already init." + fi + #add MUX PCA9548#1 on ISMT + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN0}" ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_1}' > ${PATH_ISMT_DEVICE}/new_device" + _set_i2cmap ${NUM_MUX_9548_1_CHAN0} "PCA9548_1" + else + echo "pca9548#1 ${I2C_ADDR_MUX_9548_1} already init." + fi + #add MUX PCA9548#2 on PCA9548#1 + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CHAN0}" ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_2}' > ${PATH_MUX_9548_1_CHAN4}/new_device" + _set_i2cmap ${NUM_MUX_9548_2_CHAN0} "PCA9548_2" + else + echo "pca9548#2 ${I2C_ADDR_MUX_9548_2} already init." + fi + #add MUX PCA9548#3 on PCA9548#1 + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_3_CHAN0}" ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_3}' > ${PATH_MUX_9548_1_CHAN5}/new_device" + _set_i2cmap ${NUM_MUX_9548_3_CHAN0} "PCA9548_3" + else + echo "pca9548#3 ${I2C_ADDR_MUX_9548_3} already init." + fi + #add MUX PCA9548#4 on PCA9548#1 + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_4_CHAN0}" ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_4}' > ${PATH_MUX_9548_1_CHAN6}/new_device" + _set_i2cmap ${NUM_MUX_9548_4_CHAN0} "PCA9548_4" + else + echo "pca9548#4 ${I2C_ADDR_MUX_9548_4} already init." + fi + #add MUX PCA9548#5 on PCA9548#1 + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_5_CHAN0}" ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_5}' > ${PATH_MUX_9548_1_CHAN7}/new_device" + _set_i2cmap ${NUM_MUX_9548_5_CHAN0} "PCA9548_5" + else + echo "pca9548#5 ${I2C_ADDR_MUX_9548_5} already init." + fi + #Init CPLD LED_CLR Register (Front Port LED) + i2cset -y ${NUM_I801_DEVICE} ${I2C_ADDR_CPLD} 0x34 0x10 + + rmmod coretemp + rmmod jc42 + rmmod w83795 + _i2c_temp_init + _i2c_volmon_init + modprobe coretemp + modprobe w83795 + modprobe jc42 + modprobe eeprom + modprobe eeprom_mb + modprobe gpio-pca953x + _i2c_fan_init + _i2c_io_exp_init + rmmod gpio_ich + _i2c_gpio_init + modprobe gpio_ich + _i2c_psu_init + _i2c_qsfp_eeprom_init "new" + _i2c_mb_eeprom_init "new" + _i2c_led_psu_status_set + _i2c_led_fan_status_set + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + _i2c_gpio_deinit + for mod in coretemp jc42 w83795 eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_ismt i2c_i801 ingrasys_s8810_32q_psu; + do + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod + done + _clear_i2cmap +} + +#Temperature sensor Init +function _i2c_temp_init { + echo -n "TEMP INIT..." + #select bank0 + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} ${REG_BANK_SEL} 0x80 + #enable TR1, TR2, TR3 temperature monitoring + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} ${REG_TEMP_CTRL2} 0x7F + + # CLKIN clock frequency set as 48Mhz + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} 0x01 0x1C +} + +#FAN Init +function _i2c_fan_init { + + local init_fan_speed=120 + echo -n "FAN INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + #Init Fan Speed + echo $init_fan_speed > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo $init_fan_speed > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL, W83795 not found in path ${PATH_HWMON_W83795_DEVICE}" + fi +} + +#VOLMON Init +function _i2c_volmon_init { + #3.3V 3VDD + #VSEN1 ROV + #VSEN4 1V + #VSEN5 1.8V + #VSEN7 5V + echo -n "VOLMON INIT..." + #select bank0 + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} ${REG_BANK_SEL} 0x80 + #enable voltage monitoring VSEN1-8 + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} ${REG_VOLT_CTRL1} 0xFF + #enable voltage monitoring 3VDD and 3VBAT + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} ${REG_VOLT_CTRL2} 0x50 + #disable voltage monitoring VSEN12 and VSEN13 + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} ${REG_TEMP_CTRL1} 0x00 + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expander Init" + echo "=========================================================" + + #SMBUS1 + + echo "Init FAN Status IO Expander" + #PCA9535_FAN FAN_STATUS + #command byte 2/3, output logic level is 0 + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is input + i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} ${REG_OUT_0} 0x11 + i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} ${REG_OUT_1} 0x11 + i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} ${REG_CFG_0} 0xCC + i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} ${REG_CFG_1} 0xCC + + echo "Init LED Status IO Expander" + #PCA9535_LED LED_BOARD + #command byte 2/3, output logic level is 0 + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is output + i2cset -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_OUT_0} 0xFF #active low + i2cset -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_OUT_1} 0xFF #active low + i2cset -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_CFG_0} 0x00 + i2cset -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_CFG_1} 0x00 + + #PCA9535#0-10 zQSFP + + echo "Init ZQSFP IO Expander" + + echo "set ZQSFP ABS" + #zQSFP 0-31 ABS + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is input + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_0} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_0} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_0} ${REG_CFG_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_0} ${REG_CFG_1} 0xFF + + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_1} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_1} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_1} ${REG_CFG_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_1} ${REG_CFG_1} 0xFF + + echo "set ZQSFP INT" + #zQSFP 0-31 INT + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is input + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_2} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_2} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_2} ${REG_CFG_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_2} ${REG_CFG_1} 0xFF + + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_3} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_3} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_3} ${REG_CFG_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_3} ${REG_CFG_1} 0xFF + + echo "set ZQSFP LP_MODE" + #zQSFP 0-31 LP_MODE + #command byte 2/3, output logic level is 0 + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is output + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_4} ${REG_OUT_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_4} ${REG_OUT_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_4} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_4} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_4} ${REG_CFG_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_4} ${REG_CFG_1} 0x00 + + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_5} ${REG_OUT_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_5} ${REG_OUT_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_5} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_5} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_5} ${REG_CFG_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_5} ${REG_CFG_1} 0x00 + + echo "set ZQSFP RST" + #zQSFP 0-31 RST + #command byte 2/3, output logic level is 0 + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is output + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_6} ${REG_OUT_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_6} ${REG_OUT_1} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_6} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_6} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_6} ${REG_CFG_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_6} ${REG_CFG_1} 0x00 + + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_7} ${REG_OUT_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_7} ${REG_OUT_1} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_7} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_7} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_7} ${REG_CFG_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_7} ${REG_CFG_1} 0x00 + + echo "set ZQSFP Mode Select" + #zQSFP 0-31 Mode Select + #command byte 2/3, output logic level is 0 + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is output + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_8} ${REG_OUT_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_8} ${REG_OUT_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_8} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_8} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_8} ${REG_CFG_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_8} ${REG_CFG_1} 0x00 + + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_9} ${REG_OUT_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_9} ${REG_OUT_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_9} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_9} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_9} ${REG_CFG_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_9} ${REG_CFG_1} 0x00 + + #ZQSFP ABS0_15, ABS16_31, INT0_15, INT16_31, PSU1_PWROFF, PSU2_PWROFF + #command byte 2/3, output logic level is 0 + #command byte 4/5, polarity is not inverted + #command byte 6/7, I/O 1.0 and I/O 1.1 are output, others are input + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_10} ${REG_OUT_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_10} ${REG_OUT_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_10} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_10} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_10} ${REG_CFG_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_10} ${REG_CFG_1} 0xFC +} + +#GPIO Init Utility Function +function _gpio_export { + local gpio_n=$1 + local direction=$2 + local active_low=$3 + local value=$4 + + if [ -z "${gpio_n}" ]; then + echo "[_gpio_init] gpio_n(${gpio_n}) is not provided" + return + fi + if [ "${gpio_n}" -lt "0" ] || [ "${gpio_n}" -gt "255" ]; then + echo "[_gpio_init] gpio_n(${gpio_n}) is invalid value" + return + fi + + #export gpio + echo ${gpio_n} > ${PATH_SYS_GPIO}/export + + #set gpio direction + echo ${direction} > ${PATH_SYS_GPIO}/gpio${gpio_n}/direction + + #set gpio active_low + echo ${active_low} > ${PATH_SYS_GPIO}/gpio${gpio_n}/active_low + + #set value + if [ ! -z "${value}" ]; then + echo ${value} > ${PATH_SYS_GPIO}/gpio${gpio_n}/value + fi +} + +#set gpiomap +function _set_gpiomap { + local gpio_n=$1 + local alias=$2 + + #create gpiomap dir if not exist + mkdir -p $PATH_GPIOMAP + + #check gpio_n exists in sysfs + if [ ! -L ${PATH_SYS_GPIO}/gpio${gpio_n} ]; then + echo "${PATH_SYS_GPIO}/gpio${gpio_n} does not exist." + return + fi + + #create or update link + ln -sf ${PATH_SYS_GPIO}/gpio${gpio_n} ${PATH_GPIOMAP}/${alias} +} + +#clear gpiomap +function _clear_gpiomap { + #delete gpiomap dir + rm -rf ${PATH_GPIOMAP} +} + +# To set the global variable GPIO_OFFSET +function _set_gpio_offset { + GPIO_OFFSET=0 + for d in `ls /sys/class/gpio/ | grep gpiochip` + do + gpiochip_no=${d##gpiochip} + if [ $gpiochip_no -gt 255 ]; then + GPIO_OFFSET=256 + break + fi + done + #echo "set GPIO_OFFSET=${GPIO_OFFSET}" +} + +#GPIO Init +function _i2c_gpio_init { + local i=0 + + #ABS Port 0-31 + echo "pca9535 ${I2C_ADDR_MUX_9535_1}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/new_device + _set_gpio_offset + echo "pca9535 ${I2C_ADDR_MUX_9535_0}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/new_device + #for i in {224..255} + for((i=${GPIO_OFFSET}+224;i<=${GPIO_OFFSET}+255;i++)); + do + _gpio_export ${i} ${DIR_IN} ${ACTIVE_LOW} + _set_gpiomap ${i} "QSFP$(( i - 223 ))_ABS" + done + + #INT Port 0-31 + echo "pca9535 ${I2C_ADDR_MUX_9535_3}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/new_device + echo "pca9535 ${I2C_ADDR_MUX_9535_2}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/new_device + #for i in {192..223} + for((i=${GPIO_OFFSET}+192;i<=${GPIO_OFFSET}+223;i++)); + do + _gpio_export ${i} ${DIR_IN} ${ACTIVE_LOW} + _set_gpiomap ${i} "QSFP$(( i - 191 ))_INT" + done + + #LP Mode Port 0-31 + echo "pca9535 ${I2C_ADDR_MUX_9535_5}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}/new_device + echo "pca9535 ${I2C_ADDR_MUX_9535_4}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}/new_device + #for i in {160..191} + for((i=${GPIO_OFFSET}+160;i<=${GPIO_OFFSET}+191;i++)); + do + _gpio_export ${i} ${DIR_OUT} ${ACTIVE_HIGH} + _set_gpiomap ${i} "QSFP$(( i - 159 ))_LPMODE" + done + + #RST Port 0-31 + echo "pca9535 ${I2C_ADDR_MUX_9535_7}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}/new_device + echo "pca9535 ${I2C_ADDR_MUX_9535_6}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}/new_device + #for i in {128..159} + for((i=${GPIO_OFFSET}+128;i<=${GPIO_OFFSET}+159;i++)); + do + _gpio_export ${i} ${DIR_OUT} ${ACTIVE_LOW} + _set_gpiomap ${i} "QSFP$(( i - 127 ))_RST" + #Reset QSFP + echo "${ACTIVE_LOW}" > ${PATH_SYS_GPIO}/gpio${i}/value + echo "${ACTIVE_HIGH}" > ${PATH_SYS_GPIO}/gpio${i}/value + done + + #MODSEL Port 0-31 + echo "pca9535 ${I2C_ADDR_MUX_9535_9}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN3}/new_device + echo "pca9535 ${I2C_ADDR_MUX_9535_8}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN3}/new_device + #for i in {96..127} + for((i=${GPIO_OFFSET}+96;i<=${GPIO_OFFSET}+127;i++)); + do + _gpio_export ${i} ${DIR_OUT} ${ACTIVE_LOW} + _set_gpiomap ${i} "QSFP$(( i - 95 ))_MODSEL" + done +} + +#GPIO DeInit +function _i2c_gpio_deinit { + echo ${I2C_ADDR_MUX_9535_0} > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/delete_device + echo ${I2C_ADDR_MUX_9535_1} > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/delete_device + echo ${I2C_ADDR_MUX_9535_2} > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/delete_device + echo ${I2C_ADDR_MUX_9535_3} > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/delete_device + echo ${I2C_ADDR_MUX_9535_4} > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}/delete_device + echo ${I2C_ADDR_MUX_9535_5} > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}/delete_device + _clear_gpiomap +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + + #check W83795 exists in hwmon2 + if [ ! -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo "FAIL, W83795 not found in path ${PATH_HWMON_W83795_DEVICE}" + return + fi + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + FAN_TRAY=1 + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + FAN_TRAY=2 + if [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + FAN_TRAY=3 + if [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + FAN_TRAY=4 + if [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi +} + +#Test FAN Tray LED +function _i2c_led_fan_tray_test { + echo "FAN Tray LED Test" + + for i in {1..4} + do + FAN_TRAY=$i + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + _pause 'Check Fan Tray ${FAN_TRAY} LED green light and Press [Enter] key to continue...' + + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + _pause 'Check Fan Tray ${FAN_TRAY} LED amber light and Press [Enter] key to continue...' + done +} +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + + #check W83795 exists in hwmon2 + if [ ! -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo "FAIL, W83795 not found in path ${PATH_HWMON_W83795_DEVICE}" + return + fi + + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + fi +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C LED TEST..." + echo "=========================================================" + #sys led (green) + _i2c_reset_led + COLOR_LED="green" + ONOFF_LED="on" + _i2c_sys_led + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + _i2c_reset_led + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_sys_led + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + _i2c_reset_led + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_led + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + _i2c_reset_led + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_led + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + _i2c_reset_led + COLOR_LED="green" + ONOFF_LED="on" + _i2c_psu2_led + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + _i2c_reset_led + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_psu2_led + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + _i2c_reset_led + COLOR_LED="green" + ONOFF_LED="on" + _i2c_psu1_led + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + _i2c_reset_led + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_psu1_led + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED + _i2c_reset_led + _pause 'Check turn off all LEDs and Press [Enter] key to continue...' + echo "done..." + + #sys led (green) + COLOR_LED="green" + ONOFF_LED="on" + _i2c_sys_led +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + local port=$1 + case ${port} in + 1|2|3|4|5|6|7|8) + i2cbus=${NUM_MUX_9548_1_CHAN1} + regAddr=0x20 + dataAddr=0 + eeprombusbase=${NUM_MUX_9548_2_CHAN0} + gpioBase=$((${GPIO_OFFSET}+224)) + #gpioBase=224 + ;; + 9|10|11|12|13|14|15|16) + i2cbus=${NUM_MUX_9548_1_CHAN1} + regAddr=0x20 + dataAddr=1 + eeprombusbase=${NUM_MUX_9548_3_CHAN0} + gpioBase=$((${GPIO_OFFSET}+224)) + #gpioBase=224 + ;; + 17|18|19|20|21|22|23|24) + i2cbus=${NUM_MUX_9548_1_CHAN1} + regAddr=0x21 + dataAddr=0 + eeprombusbase=${NUM_MUX_9548_4_CHAN0} + gpioBase=$((${GPIO_OFFSET}+240)) + #gpioBase=240 + ;; + 25|26|27|28|29|30|31|32) + i2cbus=${NUM_MUX_9548_1_CHAN1} + regAddr=0x21 + dataAddr=1 + eeprombusbase=${NUM_MUX_9548_5_CHAN0} + gpioBase=$((${GPIO_OFFSET}+240)) + #gpioBase=240 + ;; + *) + echo "Please input 1~32" + exit + ;; + esac +} + +#Set QSFP Port variable +function _qsfp_eeprom_var_set { + local port=$1 + eeprombusidx=$(( ${port} % 8)) + case $eeprombusidx in + 1) + eeprombus=$(( $eeprombusbase + 0 )) + ;; + 2) + eeprombus=$(( $eeprombusbase + 1 )) + ;; + 3) + eeprombus=$(( $eeprombusbase + 2 )) + ;; + 4) + eeprombus=$(( $eeprombusbase + 3 )) + ;; + 5) + eeprombus=$(( $eeprombusbase + 4 )) + ;; + 6) + eeprombus=$(( $eeprombusbase + 5 )) + ;; + 7) + eeprombus=$(( $eeprombusbase + 6 )) + ;; + 0) + eeprombus=$(( $eeprombusbase + 7 )) + ;; + esac + eepromAddr=${I2C_ADDR_QSFP_EEPROM} +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + status=`cat ${PATH_SYS_GPIO}/gpio$(( gpioBase + (QSFP_PORT-1)%16 ))/value` + echo $status + + if [ $status = 0 ]; then + exit + fi + + _qsfp_eeprom_var_set ${QSFP_PORT} + + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo -n "QSFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-32 ports EEPROM + local i + for i in {1..32}; + do + _qsfp_port_i2c_var_set ${i} + + _qsfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/delete_device + fi + done + echo "DONE" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + echo -n "Main Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init MB EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_MB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "${I2C_ADDR_MB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/delete_device + fi + echo "DONE" +} + +#get QSFP Status +function _i2c_qsfp_status_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + + status=`cat ${PATH_SYS_GPIO}/gpio$(( gpioBase + (QSFP_PORT-1)%16 ))/value` + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + _qsfp_eeprom_var_set ${QSFP_PORT} + + #Get QSFP EEPROM info + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Init PSU Kernel Module +function _i2c_psu_init { + echo "=========================================================" + echo "# Description: I2C PSU Init" + echo "=========================================================" + modprobe ingrasys_s8810_32q_psu + + echo "psu1 ${I2C_ADDR_PSU_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/new_device + echo "psu2 ${I2C_ADDR_PSU_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/new_device +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + local eeprom_psu1="" + local eeprom_psu2="" + + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + eeprom_psu1="${PATH_SYSFS_PSU1}/psu_eeprom" + cat ${eeprom_psu1} | hexdump -C + + eeprom_psu2="${PATH_SYSFS_PSU2}/psu_eeprom" + cat ${eeprom_psu2} | hexdump -C +} + +#Get MotherBoard EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom | hexdump -C + echo "done..." +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + local value=0 + case ${FAN_TRAY} in + 1) + ioPort=$REG_OUT_0 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + ioPort=$REG_OUT_0 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + ioPort=$REG_OUT_1 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + ioPort=$REG_OUT_1 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + if [ "${ONOFF_LED}" == "on" ]; then + value=0xFF + elif [ "${ONOFF_LED}" == "off" ]; then + value=0x00 + else + echo "Invalid Parameters ${ONOFF_LED}, Exit!!!" + _help + exit ${FALSE} + fi + i2cset -m $mask -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} $ioPort $value + + #echo "done..." +} + +#Set System Status LED +function _i2c_sys_led { + local green_mask=${BIT_MASK[7]} + local amber_mask=${BIT_MASK[6]} + + _i2c_set_led $green_mask $amber_mask +} + +#Set FAN LED +function _i2c_fan_led { + local green_mask=${BIT_MASK[3]} + local amber_mask=${BIT_MASK[2]} + + _i2c_set_led $green_mask $amber_mask +} + +#Set PSU1 LED +function _i2c_psu1_led { + local green_mask=${BIT_MASK[1]} + local amber_mask=${BIT_MASK[0]} + + _i2c_set_led $green_mask $amber_mask +} + +#Set PSU2 LED +function _i2c_psu2_led { + local green_mask=${BIT_MASK[5]} + local amber_mask=${BIT_MASK[4]} + + _i2c_set_led $green_mask $amber_mask +} + +#Set LEDs in LED Board +function _i2c_set_led { + local green_mask=$1 + local amber_mask=$2 + local mask=0 + local value=0 + + + if [ "${COLOR_LED}" == "green" ]; then + mask=$green_mask + elif [ "${COLOR_LED}" == "amber" ]; then + mask=$amber_mask + else + echo "Invalid Parameters ${COLOR_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + # Singals are active_low + if [ "${ONOFF_LED}" == "on" ]; then + value=0x00 + elif [ "${ONOFF_LED}" == "off" ]; then + value=0xFF + else + echo "Invalid Parameters ${ONOFF_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + i2cset -m $mask -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_OUT_0} $value +} + +#Reset all system leds +function _i2c_reset_led { + i2cset -y ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_OUT_0} 0xFF +} + +#Get Board Version and Type +function _i2c_board_type_get { + local reg_board=0x00 + local reg_ext_board=0x07 + local boardType=0 + local boardBuildRev=0 + local boardHwRev=0 + local boardId=0 + local extBoardType=0 + + boardType=`i2cget -y ${NUM_I801_DEVICE} ${I2C_ADDR_CPLD} ${reg_board}` + #Bit 0-1 + boardBuildRev=$((($boardType) & 0x03)) + #Bit 2-3 + boardHwRev=$((($boardType) >> 2 & 0x03)) + #Bit 4-7 + boardId=$((($boardType) >> 4)) + + extBoardType=`i2cget -y ${NUM_I801_DEVICE} ${I2C_ADDR_CPLD} ${reg_ext_board}` + #Bit 0-3 + extBoardType=$((($extBoardType) & 0x0F)) + + printf "BOARD_ID=0x%02x, HW Rev=%d, Build Rev=%d, Ext_BOARD_ID=0x%02x\n" $boardId $boardHwRev $boardBuildRev $extBoardType + +} + +#Get CPLD Version +function _i2c_cpld_version { + local reg_cpld_rev=0x01 + cpldRev=`i2cget -y ${NUM_I801_DEVICE} ${I2C_ADDR_CPLD} ${reg_cpld_rev}` + cpldRelease=$((($cpldRev) >> 6 & 0x01)) + cpldVersion=$((($cpldRev) & 0x3F)) + printf "CPLD is %s version(0:RD 1:Release), Revision is 0x%02x\n" $cpldRelease $cpldVersion + +} + +#Get PSU Status +function _i2c_psu_status { + local psu_abs="" + + psu1PwGood=`cat ${PATH_SYSFS_PSU1}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU1}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu1Exist=1 + else + psu1Exist=0 + fi + + psu2PwGood=`cat ${PATH_SYSFS_PSU2}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU2}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu2Exist=1 + else + psu2Exist=0 + fi + + printf "PSU1 Exist:%x PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Main Function +function _main { + start_time_str=`date` + start_time_sec=$(date +%s) + + _set_gpio_offset + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_fan_init" ]; then + _i2c_fan_init + elif [ "${EXEC_FUNC}" == "i2c_volmon_init" ]; then + _i2c_volmon_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_init" ]; then + _i2c_gpio_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_deinit" ]; then + _i2c_gpio_deinit + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_test" ]; then + _i2c_led_fan_tray_test + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_deinit + _i2c_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_board_type_get + _i2c_cpld_version + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/qsfp_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/qsfp_monitor.sh new file mode 100755 index 000000000000..249f179216a6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/qsfp_monitor.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, 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 . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..31}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/s8810_32q_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/s8810_32q_monitor.sh new file mode 100755 index 000000000000..974da6d5001f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/s8810_32q_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, 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 . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/README.md b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/README.md new file mode 100644 index 000000000000..2042625f631c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/README.md @@ -0,0 +1,185 @@ +# Ingrasys S8900-54XC Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, 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 . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S8900-54XC is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S8900-54XC platform. + +### I2C i801 + +The I2C i801 on Ingrasys S8900-54XC can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S8900-54XC. + +### I2C iSMT + +The I2C iSMT module on S8900-54XC can be found in +`/sys/bus/i2c/devices/i2c-1/` + +This is I2C bus for CPLD, HWM, power controller and I2C Switches. + +The i801 module must be loaded third on Ingrasys S8900-54XC. + +### I2C PCA9548 +The PCA9548 module on S8900-54XC can be found in +`/sys/bus/i2c/devices/i2c-2/` , `/sys/bus/i2c/devices/i2c-3/`, +`/sys/bus/i2c/devices/i2c-4/`, `/sys/bus/i2c/devices/i2c-5/`, +`/sys/bus/i2c/devices/i2c-6/`, `/sys/bus/i2c/devices/i2c-7/`, +`/sys/bus/i2c/devices/i2c-8/`, `/sys/bus/i2c/devices/i2c-9/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S8900-54XC. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S8900-54XC platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s8900-54xc package is installed on the S8900-54XC, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-9/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/9-0054/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber on|off + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/Makefile b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/Makefile new file mode 100644 index 000000000000..a0042543dff5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := eeprom_mb.o +obj-m+= i2c_cpld.o diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/eeprom_mb.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/eeprom_mb.c new file mode 100644 index 000000000000..0886cad58eb3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/eeprom_mb.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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 + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, I2C_CLIENT_END }; + + +/* 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 mb_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 mb_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++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_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, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys S8900 Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/i2c_cpld.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/i2c_cpld.c new file mode 100644 index 000000000000..626c63177b50 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/i2c_cpld.c @@ -0,0 +1,448 @@ +/* + * S9100-32X I2C CPLD driver + * + * Copyright (C) 2017 Ingrasys, Inc. + * Wade He + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c_cpld.h" + +#ifdef DEBUG + #define DEBUG_PRINT(fmt, args...) \ + printk(KERN_INFO "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define I2C_READ_BYTE_DATA(ret, lock, i2c_client, reg) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_read_byte_data(i2c_client, reg); \ + mutex_unlock(lock); \ +} +#define I2C_WRITE_BYTE_DATA(ret, lock, i2c_client, reg, val) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_write_byte_data(i2c_client, reg, val); \ + mutex_unlock(lock); \ +} + +/* CPLD sysfs attributes index */ +enum i2c_cpld_sysfs_attributes { + CPLD_ACCESS_REG, + CPLD_REGISTER_VAL, + CPLD_PORT_START, + CPLD_PORTS, + CPLD_VERSION, + CPLD_ID, + CPLD_BOARD_TYPE, + CPLD_EXT_BOARD_TYPE, + CPLD_PW_GOOD, + CPLD_PW_ABS, +}; + +/* CPLD sysfs attributes hook functions */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_pw_good(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_pw_abs(struct device *dev, + struct device_attribute *da, char *buf); + +static LIST_HEAD(cpld_client_list); /* client list for cpld */ +static struct mutex list_lock; /* mutex for client list */ + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +struct cpld_data { + int index; /* CPLD index */ + struct mutex access_lock; /* mutex for cpld access */ + u8 access_reg; /* register to access */ +}; + +/* CPLD device id and data */ +static const struct i2c_device_id i2c_cpld_id[] = { + { "i2c_cpld", i2c_cpld }, + {} +}; + +/* Addresses scanned for i2c_cpld */ +static const unsigned short cpld_i2c_addr[] = { 0x33, I2C_CLIENT_END }; +/* platform sysfs object */ +extern struct kobject *s9230_64x_kobj; + + +/* define all support register access of cpld in attribute */ +static SENSOR_DEVICE_ATTR(cpld_access_register, S_IWUSR | S_IRUGO, + read_access_register, write_access_register, CPLD_ACCESS_REG); +static SENSOR_DEVICE_ATTR(cpld_register_value, S_IWUSR | S_IRUGO, + read_register_value, write_register_value, CPLD_REGISTER_VAL); +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, + read_cpld_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(cpld_board_type, S_IRUGO, + read_board_type, NULL, CPLD_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_ext_board_type, S_IRUGO, + read_ext_board_type, NULL, CPLD_EXT_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_pw_good, S_IRUGO, + read_pw_good, NULL, CPLD_PW_GOOD); +static SENSOR_DEVICE_ATTR(cpld_pw_abs, S_IRUGO, + read_pw_abs, NULL, CPLD_PW_ABS); + + +/* define support attributes of cpldx , total 5 */ +/* cpld 1 */ +static struct attribute *i2c_cpld_attributes[] = { + &sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_ext_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_pw_good.dev_attr.attr, + &sensor_dev_attr_cpld_pw_abs.dev_attr.attr, + NULL +}; + +/* cpld 1 attributes group */ +static const struct attribute_group i2c_cpld_group = { + .attrs = i2c_cpld_attributes, +}; + +/* read access register from cpld data */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + + return sprintf(buf, "0x%x\n", reg); +} + +/* write access register to cpld data */ +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + + if (kstrtou8(buf, 0, ®) < 0) + return -EINVAL; + + data->access_reg = reg; + return count; +} + +/* read the value of access register in cpld data */ +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + int reg_val; + + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + + if (reg_val < 0) + return -1; + + return sprintf(buf, "0x%x\n", reg_val); +} + +/* wrtie the value to access register in cpld data */ +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ret = -EIO; + u8 reg = data->access_reg; + u8 reg_val; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, client, reg, reg_val); + + return count; +} + +/* get cpdl version register value */ +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_VERSION) { + reg = CPLD_VERSION_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get board type register value */ +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BOARD_TYPE) { + reg = CPLD_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_EXT_BOARD_TYPE) { + reg = CPLD_EXT_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_pw_good(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_PW_GOOD) { + reg = CPLD_PW_GOOD_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_pw_abs(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_PW_ABS) { + reg = CPLD_PW_ABS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* add valid cpld client to list */ +static void i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = NULL; + + node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + if (!node) { + dev_info(&client->dev, + "Can't allocate cpld_client_node for index %d\n", + client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +/* remove exist cpld client in list */ +static void i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + mutex_unlock(&list_lock); +} + +/* cpld drvier probe */ +static int i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct cpld_data *data = NULL; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* init cpld data for client */ + i2c_set_clientdata(client, data); + mutex_init(&data->access_lock); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_info(&client->dev, + "i2c_check_functionality failed (0x%x)\n", + client->addr); + status = -EIO; + goto exit; + } + + + status = sysfs_create_group(&client->dev.kobj,&i2c_cpld_group); + + if (status) + goto exit; + + dev_info(&client->dev, "chip found\n"); + + /* add probe chip to client list */ + i2c_cpld_add_client(client); + + return 0; +exit: + sysfs_remove_group(&client->dev.kobj, &i2c_cpld_group); + return status; +} + +/* cpld drvier remove */ +static int i2c_cpld_remove(struct i2c_client *client) +{ + + sysfs_remove_group(&client->dev.kobj, &i2c_cpld_group); + + i2c_cpld_remove_client(client); + return 0; +} + +MODULE_DEVICE_TABLE(i2c, i2c_cpld_id); + +static struct i2c_driver i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "i2c_cpld", + }, + .probe = i2c_cpld_probe, + .remove = i2c_cpld_remove, + .id_table = i2c_cpld_id, + .address_list = cpld_i2c_addr, +}; + +static int __init i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&i2c_cpld_driver); +} + +static void __exit i2c_cpld_exit(void) +{ + i2c_del_driver(&i2c_cpld_driver); +} + +MODULE_AUTHOR("Wade He "); +MODULE_DESCRIPTION("Ingrasys S9100-32X Platform i2c cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_cpld_init); +module_exit(i2c_cpld_exit); + + + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/i2c_cpld.h b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/i2c_cpld.h new file mode 100644 index 000000000000..e103b05c717a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/i2c_cpld.h @@ -0,0 +1,197 @@ +/* + * + * S9100-32X I2C CPLD driver header file + * + * Copyright (C) 2017 Ingrasys, Inc. + * Wade He + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef I2C_CPLD_H +#define I2C_CPLD_H + +// remove debug before release +#define DEBUG + +/* CPLD device index value */ +enum cpld_id { + i2c_cpld +}; + +/* port number on CPLD */ +#define CPLD_1_PORT_NUM 12 +#define CPLD_2_PORT_NUM 13 + +/* QSFP port number */ +#define QSFP_MAX_PORT_NUM 64 +#define QSFP_MIN_PORT_NUM 1 + +/* SFP+ port number */ +#define SFP_MAX_PORT_NUM 2 +#define SFP_MIN_PORT_NUM 1 + + +/* CPLD registers */ +#define CPLD_BOARD_TYPE_REG 0x0 +#define CPLD_EXT_BOARD_TYPE_REG 0x7 +#define CPLD_VERSION_REG 0x1 +#define CPLD_PW_GOOD_REG 0x2 +#define CPLD_PW_ABS_REG 0x3 + + +/* bit definition for register value */ + +enum CPLD_RESET_CONTROL_BITS { + CPLD_RESET_CONTROL_SWRST_BIT, + CPLD_RESET_CONTROL_CP2104RST_BIT, + CPLD_RESET_CONTROL_82P33814RST_BIT, + CPLD_RESET_CONTROL_BMCRST_BIT, +}; + +/* bit field structure for register value */ +struct cpld_reg_board_type_t { + u8 build_rev:2; + u8 hw_rev:2; + u8 board_id:4; +}; + +struct cpld_reg_version_t { + u8 revision:6; + u8 release:1; + u8 reserve:1; +}; + +struct cpld_reg_pw_good_t { + u8 reserve1:3; + u8 psu1:1; + u8 psu2:1; + u8 reserve2:3; +}; + +struct cpld_reg_pw_abs_t { + u8 psu1:1; + u8 psu2:1; + u8 reserve:6; +}; + +/* common manipulation */ +#define INVALID(i, min, max) ((i < min) || (i > max) ? 1u : 0u) +#define READ_BIT(val, bit) ((0u == (val & (1<bf_name) +#define READ_BF_1(bf_struct, val, bf_name, bf_value) \ + bf_struct bf; \ + bf.data = val; \ + bf_value = bf.bf_name +#define BOARD_TYPE_BUILD_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, build_rev, res) +#define BOARD_TYPE_HW_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, hw_rev, res) +#define BOARD_TYPE_BOARD_ID_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, board_id, res) +#define CPLD_VERSION_REV_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, revision, res) +#define CPLD_VERSION_REL_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, release, res) +#define CPLD_PSU1_PW_GOOD_GET(val, res) \ + READ_BF(cpld_reg_pw_good_t, val, psu1, res) +#define CPLD_PSU2_PW_GOOD_GET(val, res) \ + READ_BF(cpld_reg_pw_good_t, val, psu2, res) +#define CPLD_PSU1_PW_ABS_GET(val, res) \ + READ_BF(cpld_reg_pw_abs_t, val, psu1, res) +#define CPLD_PSU2_PW_ABS_GET(val, res) \ + READ_BF(cpld_reg_pw_abs_t, val, psu2, res) +/* QSFP/SFP registers manipulation */ +#define QSFP_TO_CPLD_IDX(qsfp_port, cpld_index, cpld_port) \ +{ \ + if (QSFP_MIN_PORT_NUM <= qsfp_port && qsfp_port <= CPLD_1_PORT_NUM) { \ + cpld_index = cpld1; \ + cpld_port = qsfp_port - 1; \ + } else if (CPLD_1_PORT_NUM < qsfp_port \ + && qsfp_port <= QSFP_MAX_PORT_NUM) { \ + cpld_index = cpld2 + (qsfp_port - 1 - CPLD_1_PORT_NUM) \ + / CPLD_2_PORT_NUM; \ + cpld_port = (qsfp_port - 1 - CPLD_1_PORT_NUM) % \ + CPLD_2_PORT_NUM; \ + } else { \ + cpld_index = 0; \ + cpld_port = 0; \ + } \ +} +#define SFP_TO_CPLD_IDX(sfp_port, cpld_index) \ + (cpld_index = sfp_port - SFP_MIN_PORT_NUM) +#define QSFP_PORT_STATUS_REG(cpld_port) \ + (CPLD_QSFP_PORT_STATUS_BASE_REG + cpld_port) +#define QSFP_PORT_CONFIG_REG(cpld_port) \ + (CPLD_QSFP_PORT_CONFIG_BASE_REG + cpld_port) +#define QSFP_PORT_INT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_INT_BIT) +#define QSFP_PORT_ABS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_ABS_BIT) +#define QSFP_PORT_RESET_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_RESET_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_RESET_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_LPMODE_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define SFP_PORT_PRESENT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_PRESENT_BIT) + + #define SFP_PORT_TXFAULT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_TXFAULT_BIT) + #define SFP_PORT_RXLOS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_RXLOS_BIT) + #define SFP_PORT_TXDIS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TXDIS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_TXDIS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_RS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) + +/* CPLD access functions */ +extern int i2c_cpld_get_qsfp_port_status_val(u8 port_num); +extern int i2c_cpld_get_qsfp_port_config_val(u8 port_num); +extern int i2c_cpld_set_qsfp_port_config_val(u8 port_num, u8 reg_val); +extern int i2c_cpld_get_sfp_port_status_val(u8 port_num); +extern int i2c_cpld_get_sfp_port_config_val(u8 port_num); +extern int i2c_cpld_set_sfp_port_config_val(u8 port_num, u8 reg_val); +extern u8 fp_port_to_phy_port(u8 fp_port); +#endif + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/service/qsfp-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/service/qsfp-monitor.service new file mode 100644 index 000000000000..e33c2fdae122 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s8900-54xc-monitor.service +After=s8900-54xc-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/service/s8900-54xc-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/service/s8900-54xc-monitor.service new file mode 100644 index 000000000000..e43fddc9b857 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/service/s8900-54xc-monitor.service @@ -0,0 +1,18 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s8900_54xc_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/i2c_utils.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/i2c_utils.sh new file mode 100644 index 000000000000..dbea63786621 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/i2c_utils.sh @@ -0,0 +1,1561 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, 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 . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.1.0" +TRUE=200 +FALSE=404 +PORT_START=1 +PORT_END=54 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_IGB_DEVICE=0 +NUM_I801_DEVICE=0 +NUM_ISMT_DEVICE=$(( ${NUM_I801_DEVICE} + 1 )) +NUM_MUX1_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 2 )) +NUM_MUX1_CHAN1_DEVICE=$(( ${NUM_I801_DEVICE} + 3 )) +NUM_MUX1_CHAN2_DEVICE=$(( ${NUM_I801_DEVICE} + 4 )) +NUM_MUX1_CHAN3_DEVICE=$(( ${NUM_I801_DEVICE} + 5 )) +NUM_MUX1_CHAN4_DEVICE=$(( ${NUM_I801_DEVICE} + 6 )) +NUM_MUX1_CHAN5_DEVICE=$(( ${NUM_I801_DEVICE} + 7 )) +NUM_MUX1_CHAN6_DEVICE=$(( ${NUM_I801_DEVICE} + 8 )) +NUM_MUX1_CHAN7_DEVICE=$(( ${NUM_I801_DEVICE} + 9 )) +NUM_MUX2_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 10 )) +NUM_MUX2_CHAN1_DEVICE=$(( ${NUM_I801_DEVICE} + 11 )) +NUM_MUX2_CHAN2_DEVICE=$(( ${NUM_I801_DEVICE} + 12 )) +NUM_MUX2_CHAN3_DEVICE=$(( ${NUM_I801_DEVICE} + 13 )) +NUM_MUX2_CHAN4_DEVICE=$(( ${NUM_I801_DEVICE} + 14 )) +NUM_MUX2_CHAN5_DEVICE=$(( ${NUM_I801_DEVICE} + 15 )) +NUM_MUX2_CHAN6_DEVICE=$(( ${NUM_I801_DEVICE} + 16 )) +NUM_MUX2_CHAN7_DEVICE=$(( ${NUM_I801_DEVICE} + 17 )) +NUM_MUX3_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 18 )) +NUM_MUX4_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 26 )) +NUM_MUX5_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 34 )) +NUM_MUX6_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 42 )) +NUM_MUX7_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 50 )) +NUM_MUX8_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 58 )) +NUM_MUX9_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 66 )) + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon1" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_ISMT_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_ISMT_DEVICE}" +PATH_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" +PATH_MUX_CHAN1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN1_DEVICE}" +PATH_MUX_CHAN2_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN2_DEVICE}" +PATH_MUX_CHAN3_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN3_DEVICE}" +PATH_MUX_CHAN4_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN4_DEVICE}" +PATH_MUX_CHAN5_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN5_DEVICE}" +PATH_MUX_CHAN6_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN6_DEVICE}" +PATH_MUX_CHAN7_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}" + +#SFP/QSFP EEPROM i2c bus index +SFP_EEPROM_BUS_IDX=0 + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +#GPIO Index for QSFP +ZQSFP_PORT0_15_ABS_GPIO_IDX=192 +ZQSFP_PORT16_31_ABS_GPIO_IDX=176 +ZQSFP_PORT32_47_ABS_GPIO_IDX=160 + +#GPIO Offset +GPIO_OFFSET=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "# Version : ${VERSION}" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_temp_init" + echo " : ${0} i2c_fan_init" + echo " : ${0} i2c_volmon_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_gpio_init" + echo " : ${0} i2c_gpio_deinit" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [1-54]" + echo " : ${0} i2c_qsfp_status_get [1-54]" + echo " : ${0} i2c_qsfp_type_get [1-54]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_front_temp" + echo " : ${0} i2c_rear_temp" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber on|off" + echo " : ${0} i2c_fan_led green|amber on|off" + echo " : ${0} i2c_psu1_led green|amber on|off" + echo " : ${0} i2c_psu2_led green|amber on|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + rmmod i2c_ismt + rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_ismt + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x70' > ${PATH_ISMT_DEVICE}/new_device" + else + echo "pca9548 0x70 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX2_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x72' > ${PATH_ISMT_DEVICE}/new_device" + else + echo "pca9548 0x72 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX3_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN0_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX4_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN1_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX5_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN2_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX6_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN3_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX7_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN4_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX8_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN5_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX9_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN6_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + + #Init CPLD LED_CLR Register (Front Port LED) + i2cset -y ${NUM_I801_DEVICE} 0x33 0x34 0x10 + + rmmod coretemp + rmmod jc42 + rmmod w83795 + _i2c_temp_init + _i2c_volmon_init + _i2c_hwmon_init + modprobe coretemp + modprobe w83795 + modprobe jc42 + modprobe sff_8436_eeprom + modprobe eeprom + modprobe eeprom_mb + _i2c_fan_init + _i2c_io_exp_init + rmmod gpio_ich + _i2c_gpio_init + modprobe gpio_ich + _i2c_cpld_init + _i2c_psu_eeprom_init + _i2c_led_psu_status_set + _i2c_led_fan_status_set + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + echo "Mount Main Board EEPROM" + echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-17/new_device + for (( i=$PORT_START; i<=$PORT_END; i++ )) + do + _i2c_mount_sfp_eeprom $i + done + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + _i2c_gpio_deinit + for mod in coretemp jc42 w83795 eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_ismt i2c_i801; + do + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod + done +} + +#Temperature sensor Init +function _i2c_temp_init { + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x05 0x7F + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x04 0x0A + echo "TEMP INIT Done" +} + +#FAN Init +function _i2c_fan_init { + echo -n "FAN INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi + +} + +#VOLMON Init +function _i2c_volmon_init { + echo -n "VOLMON INIT..." + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x02 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x03 0x50 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x04 0x0A + echo "Done" +} + +#HWMON Init +function _i2c_hwmon_init { + echo -n "HWMON INIT..." + i2cset -y ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y ${NUM_I801_DEVICE} 0x2F 0x06 0xFF + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + #SMBUS0 IO_EXPENDER + i2cset -y -r ${NUM_I801_DEVICE} 0x27 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 6 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x27 7 0xFF + + #SMBUS1 + #SFP+ ABS + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x22 5 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x20 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x21 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x21 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x22 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x22 7 0xFF + + #QSFP/ZQSFP ABS + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x23 6 0xFF + + #QSFP/ZQSFP INT + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x23 7 0xFF + + #SFP+ RX_LOS + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x22 5 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x20 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x21 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x21 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x22 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x22 7 0xFF + + #SFP+ TX_FAULT + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x22 5 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x20 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x21 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x21 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x22 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x22 7 0xFF + + #SFP+ TX_RS + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x22 5 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x20 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x20 3 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x21 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x21 3 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x22 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x22 3 0xFF + + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x20 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x21 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x21 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x22 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x22 7 0xFF + + #QSFP/zQSFP LPMODE + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x23 2 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x23 6 0x00 + + #QSFP/zQSFP MODSEL + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x23 3 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x23 7 0x00 + + #SFP+ RX_RS + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x22 5 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x20 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x20 3 0xFF + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x21 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x21 3 0xFF + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x22 3 0xFF + + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x20 6 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x20 7 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x21 6 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x21 7 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x22 7 0x00 + + #SFP+ TX_DIS + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x22 5 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x20 2 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x20 3 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x21 2 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x21 3 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x22 2 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x22 3 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x20 6 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x20 7 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x21 6 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x21 7 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x22 7 0x00 + + #QSFP/zQSFP RST + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x23 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x23 6 0x00 + + #SFP/QSFP/zQSFP I/O + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x24 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x24 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x24 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x24 7 0xFF + + #ZQSFP/SFP+/E-Card General + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x21 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x21 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x21 6 0xF4 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x21 7 0xF4 + + #LED board after PVT (S8900_IO_EXP_LED_ID) + echo "Init LED IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 7 0x00 + + #PSU I/O (S8900_IO_EXP_PSU_ID) + echo "Init PSU IO Expender" + i2cset -y -r ${NUM_MUX2_CHAN6_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN6_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN6_DEVICE} 0x20 2 0x00 + i2cset -y -r ${NUM_MUX2_CHAN6_DEVICE} 0x20 3 0x00 + i2cset -y -r ${NUM_MUX2_CHAN6_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN6_DEVICE} 0x20 7 0xFF + + #FAN I/O (S8900_IO_EXP_FAN_ID) + echo "Init FAN IO Expender" + i2cset -y -r ${NUM_MUX2_CHAN7_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN7_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN7_DEVICE} 0x20 2 0x11 + i2cset -y -r ${NUM_MUX2_CHAN7_DEVICE} 0x20 3 0x11 + i2cset -y -r ${NUM_MUX2_CHAN7_DEVICE} 0x20 6 0xCC + i2cset -y -r ${NUM_MUX2_CHAN7_DEVICE} 0x20 7 0xCC +} + +function _get_sfp_eeprom_bus_idx { + case $1 in + 1|2|3|4|5|6|7|8) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX3_CHAN0_DEVICE} + $1 - 1) )) + ;; + 9|10|11|12|13|14|15|16) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX4_CHAN0_DEVICE} + $1 - 9) )) + ;; + 17|18|19|20|21|22|23|24) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX5_CHAN0_DEVICE} + $1 - 17) )) + ;; + 25|26|27|28|29|30|31|32) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX6_CHAN0_DEVICE} + $1 - 25) )) + ;; + 33|34|35|36|37|38|39|40) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX7_CHAN0_DEVICE} + $1 - 33) )) + ;; + 41|42|43|44|45|46|47|48) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX8_CHAN0_DEVICE} + $1 - 41) )) + ;; + 49|50|51|52|53|54) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX9_CHAN0_DEVICE} + $1 - 49) )) + ;; + *) + SFP_EEPROM_BUS_IDX=-1 + ;; + esac +} + +#Mount SFP/QSFP EEPROM +function _i2c_mount_sfp_eeprom { + _get_sfp_eeprom_bus_idx $1 + eeprombus=${SFP_EEPROM_BUS_IDX} + eepromAddr=0x50 + echo "sff8436 $eepromAddr" > /sys/bus/i2c/devices/i2c-$eeprombus/new_device + echo "Mount Port $1 EEPROM" +} + +#Unmount SFP/QSFP EEPROM +function _i2c_unmount_sfp_eeprom { + _get_sfp_eeprom_bus_idx $1 + eeprombus=${SFP_EEPROM_BUS_IDX} + eepromAddr=0x50 + echo "$eepromAddr" > /sys/bus/i2c/devices/i2c-$eeprombus/new_device + echo "Unmount Port $1 EEPROM" +} + +# To set the global variable GPIO_OFFSET +function _set_gpio_offset { + GPIO_OFFSET=0 + for d in `ls /sys/class/gpio/ | grep gpiochip` + do + gpiochip_no=${d##gpiochip} + if [ $gpiochip_no -gt 255 ]; then + GPIO_OFFSET=256 + break + fi + done + #echo "set GPIO_OFFSET=${GPIO_OFFSET}" +} + +#GPIO Init +function _i2c_gpio_init { + + #QSFP/ZQSFP ABS+INT + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/new_device + _set_gpio_offset + for((i=${GPIO_OFFSET}+240;i<=${GPIO_OFFSET}+255;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #_retry "echo 240 > /sys/class/gpio/export" + #echo 241 > /sys/class/gpio/export + #echo 242 > /sys/class/gpio/export + #echo 243 > /sys/class/gpio/export + #echo 244 > /sys/class/gpio/export + #echo 245 > /sys/class/gpio/export + #echo 246 > /sys/class/gpio/export + #echo 247 > /sys/class/gpio/export + #echo 248 > /sys/class/gpio/export + #echo 249 > /sys/class/gpio/export + #echo 250 > /sys/class/gpio/export + #echo 251 > /sys/class/gpio/export + #echo 252 > /sys/class/gpio/export + #echo 253 > /sys/class/gpio/export + #echo 254 > /sys/class/gpio/export + #echo 255 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio241/active_low #QSFP49 ABS + #echo 1 > /sys/class/gpio/gpio240/active_low #QSFP48 ABS + #echo 1 > /sys/class/gpio/gpio243/active_low #QSFP51 ABS + #echo 1 > /sys/class/gpio/gpio242/active_low #QSFP50 ABS + #echo 1 > /sys/class/gpio/gpio245/active_low #QSFP53 ABS + #echo 1 > /sys/class/gpio/gpio244/active_low #QSFP52 ABS + #echo 1 > /sys/class/gpio/gpio247/active_low #NA + #echo 1 > /sys/class/gpio/gpio246/active_low #NA + #echo 1 > /sys/class/gpio/gpio249/active_low #QSFP49 INT + #echo 1 > /sys/class/gpio/gpio248/active_low #QSFP48 INT + #echo 1 > /sys/class/gpio/gpio251/active_low #QSFP51 INT + #echo 1 > /sys/class/gpio/gpio250/active_low #QSFP50 INT + #echo 1 > /sys/class/gpio/gpio253/active_low #QSFP53 INT + #echo 1 > /sys/class/gpio/gpio252/active_low #QSFP52 INT + #echo 1 > /sys/class/gpio/gpio255/active_low #NA + #echo 1 > /sys/class/gpio/gpio254/active_low #NA + + #QSFP/zQSFP LPMODE+MODSEL + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN3_DEVICE}/new_device + for((i=${GPIO_OFFSET}+224;i<=${GPIO_OFFSET}+239;i++)); + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + done + + #echo 224 > /sys/class/gpio/export #QSFP0 LPMODE + #echo 225 > /sys/class/gpio/export #QSFP1 LPMODE + #echo 226 > /sys/class/gpio/export #QSFP2 LPMODE + #echo 227 > /sys/class/gpio/export #QSFP3 LPMODE + #echo 228 > /sys/class/gpio/export #QSFP4 LPMODE + #echo 229 > /sys/class/gpio/export #QSFP5 LPMODE + #echo 230 > /sys/class/gpio/export #NA + #echo 231 > /sys/class/gpio/export #NA + #echo 232 > /sys/class/gpio/export #QSFP0 MODSEL + #echo 233 > /sys/class/gpio/export #QSFP1 MODSEL + #echo 234 > /sys/class/gpio/export #QSFP2 MODSEL + #echo 235 > /sys/class/gpio/export #QSFP3 MODSEL + #echo 236 > /sys/class/gpio/export #QSFP4 MODSEL + #echo 237 > /sys/class/gpio/export #QSFP5 MODSEL + #echo 238 > /sys/class/gpio/export #NA + #echo 239 > /sys/class/gpio/export #NA + #echo out > /sys/class/gpio/gpio224/direction + #echo out > /sys/class/gpio/gpio225/direction + #echo out > /sys/class/gpio/gpio226/direction + #echo out > /sys/class/gpio/gpio227/direction + #echo out > /sys/class/gpio/gpio228/direction + #echo out > /sys/class/gpio/gpio229/direction + #echo out > /sys/class/gpio/gpio230/direction + #echo out > /sys/class/gpio/gpio231/direction + #echo out > /sys/class/gpio/gpio232/direction + #echo out > /sys/class/gpio/gpio233/direction + #echo out > /sys/class/gpio/gpio234/direction + #echo out > /sys/class/gpio/gpio235/direction + #echo out > /sys/class/gpio/gpio236/direction + #echo out > /sys/class/gpio/gpio237/direction + #echo out > /sys/class/gpio/gpio238/direction + #echo out > /sys/class/gpio/gpio239/direction + + #QSFP RST + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN5_DEVICE}/new_device + for((i=${GPIO_OFFSET}+208;i<=${GPIO_OFFSET}+213;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + echo low > /sys/class/gpio/gpio${i}/direction + #echo out > /sys/class/gpio/gpio${i}/direction + #echo 0 > /sys/class/gpio/gpio${i}/value + done + for((i=${GPIO_OFFSET}+214;i<=${GPIO_OFFSET}+223;i++)); + do + echo $i > /sys/class/gpio/export + done + + #echo 208 > /sys/class/gpio/export #QSFP0 RST + #echo 209 > /sys/class/gpio/export #QSFP1 RST + #echo 210 > /sys/class/gpio/export #QSFP2 RST + #echo 211 > /sys/class/gpio/export #QSFP3 RST + #echo 212 > /sys/class/gpio/export #QSFP4 RST + #echo 213 > /sys/class/gpio/export #QSFP5 RST + #echo 214 > /sys/class/gpio/export #NA + #echo 215 > /sys/class/gpio/export #NA + #echo 216 > /sys/class/gpio/export #NA + #echo 217 > /sys/class/gpio/export #NA + #echo 218 > /sys/class/gpio/export #NA + #echo 219 > /sys/class/gpio/export #NA + #echo 220 > /sys/class/gpio/export #NA + #echo 221 > /sys/class/gpio/export #NA + #echo 222 > /sys/class/gpio/export #NA + #echo 223 > /sys/class/gpio/export #NA + #echo out > /sys/class/gpio/gpio208/direction + #echo out > /sys/class/gpio/gpio209/direction + #echo out > /sys/class/gpio/gpio210/direction + #echo out > /sys/class/gpio/gpio211/direction + #echo out > /sys/class/gpio/gpio212/direction + #echo out > /sys/class/gpio/gpio213/direction + #echo 1 > /sys/class/gpio/gpio208/active_low + #echo 1 > /sys/class/gpio/gpio209/active_low + #echo 1 > /sys/class/gpio/gpio210/active_low + #echo 1 > /sys/class/gpio/gpio211/active_low + #echo 1 > /sys/class/gpio/gpio212/active_low + #echo 1 > /sys/class/gpio/gpio213/active_low + #echo 0 > /sys/class/gpio/gpio208/value + #echo 0 > /sys/class/gpio/gpio209/value + #echo 0 > /sys/class/gpio/gpio210/value + #echo 0 > /sys/class/gpio/gpio211/value + #echo 0 > /sys/class/gpio/gpio212/value + #echo 0 > /sys/class/gpio/gpio213/value + + + #SFP+ ABS 0-15 + echo "pca9535 0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/new_device + for((i=${GPIO_OFFSET}+192;i<=${GPIO_OFFSET}+207;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 192 > /sys/class/gpio/export + #echo 193 > /sys/class/gpio/export + #echo 194 > /sys/class/gpio/export + #echo 195 > /sys/class/gpio/export + #echo 196 > /sys/class/gpio/export + #echo 197 > /sys/class/gpio/export + #echo 198 > /sys/class/gpio/export + #echo 199 > /sys/class/gpio/export + #echo 200 > /sys/class/gpio/export + #echo 201 > /sys/class/gpio/export + #echo 202 > /sys/class/gpio/export + #echo 203 > /sys/class/gpio/export + #echo 204 > /sys/class/gpio/export + #echo 205 > /sys/class/gpio/export + #echo 206 > /sys/class/gpio/export + #echo 207 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio192/active_low #SFP+00 + #echo 1 > /sys/class/gpio/gpio193/active_low #SFP+01 + #echo 1 > /sys/class/gpio/gpio194/active_low #SFP+02 + #echo 1 > /sys/class/gpio/gpio195/active_low #SFP+03 + #echo 1 > /sys/class/gpio/gpio196/active_low #SFP+04 + #echo 1 > /sys/class/gpio/gpio197/active_low #SFP+05 + #echo 1 > /sys/class/gpio/gpio198/active_low #SFP+06 + #echo 1 > /sys/class/gpio/gpio199/active_low #SFP+07 + #echo 1 > /sys/class/gpio/gpio200/active_low #SFP+08 + #echo 1 > /sys/class/gpio/gpio201/active_low #SFP+09 + #echo 1 > /sys/class/gpio/gpio202/active_low #SFP+10 + #echo 1 > /sys/class/gpio/gpio203/active_low #SFP+11 + #echo 1 > /sys/class/gpio/gpio204/active_low #SFP+12 + #echo 1 > /sys/class/gpio/gpio205/active_low #SFP+13 + #echo 1 > /sys/class/gpio/gpio206/active_low #SFP+14 + #echo 1 > /sys/class/gpio/gpio207/active_low #SFP+15 + + #SFP+ ABS 16-31 + echo "pca9535 0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/new_device + for((i=${GPIO_OFFSET}+176;i<=${GPIO_OFFSET}+191;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 176 > /sys/class/gpio/export + #echo 177 > /sys/class/gpio/export + #echo 178 > /sys/class/gpio/export + #echo 179 > /sys/class/gpio/export + #echo 180 > /sys/class/gpio/export + #echo 181 > /sys/class/gpio/export + #echo 182 > /sys/class/gpio/export + #echo 183 > /sys/class/gpio/export + #echo 184 > /sys/class/gpio/export + #echo 185 > /sys/class/gpio/export + #echo 186 > /sys/class/gpio/export + #echo 187 > /sys/class/gpio/export + #echo 188 > /sys/class/gpio/export + #echo 189 > /sys/class/gpio/export + #echo 190 > /sys/class/gpio/export + #echo 191 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio176/active_low #SFP+16 + #echo 1 > /sys/class/gpio/gpio177/active_low #SFP+17 + #echo 1 > /sys/class/gpio/gpio178/active_low #SFP+18 + #echo 1 > /sys/class/gpio/gpio179/active_low #SFP+19 + #echo 1 > /sys/class/gpio/gpio180/active_low #SFP+20 + #echo 1 > /sys/class/gpio/gpio181/active_low #SFP+21 + #echo 1 > /sys/class/gpio/gpio182/active_low #SFP+22 + #echo 1 > /sys/class/gpio/gpio183/active_low #SFP+23 + #echo 1 > /sys/class/gpio/gpio184/active_low #SFP+24 + #echo 1 > /sys/class/gpio/gpio185/active_low #SFP+25 + #echo 1 > /sys/class/gpio/gpio186/active_low #SFP+26 + #echo 1 > /sys/class/gpio/gpio187/active_low #SFP+27 + #echo 1 > /sys/class/gpio/gpio188/active_low #SFP+28 + #echo 1 > /sys/class/gpio/gpio189/active_low #SFP+29 + #echo 1 > /sys/class/gpio/gpio190/active_low #SFP+30 + #echo 1 > /sys/class/gpio/gpio191/active_low #SFP+31 + + #SFP+ ABS 32-47 + echo "pca9535 0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/new_device + for((i=${GPIO_OFFSET}+160;i<=${GPIO_OFFSET}+175;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 160 > /sys/class/gpio/export + #echo 161 > /sys/class/gpio/export + #echo 162 > /sys/class/gpio/export + #echo 163 > /sys/class/gpio/export + #echo 164 > /sys/class/gpio/export + #echo 165 > /sys/class/gpio/export + #echo 166 > /sys/class/gpio/export + #echo 167 > /sys/class/gpio/export + #echo 168 > /sys/class/gpio/export + #echo 169 > /sys/class/gpio/export + #echo 170 > /sys/class/gpio/export + #echo 171 > /sys/class/gpio/export + #echo 172 > /sys/class/gpio/export + #echo 173 > /sys/class/gpio/export + #echo 174 > /sys/class/gpio/export + #echo 175 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio160/active_low #SFP+32 + #echo 1 > /sys/class/gpio/gpio161/active_low #SFP+33 + #echo 1 > /sys/class/gpio/gpio162/active_low #SFP+34 + #echo 1 > /sys/class/gpio/gpio163/active_low #SFP+35 + #echo 1 > /sys/class/gpio/gpio164/active_low #SFP+36 + #echo 1 > /sys/class/gpio/gpio165/active_low #SFP+37 + #echo 1 > /sys/class/gpio/gpio166/active_low #SFP+38 + #echo 1 > /sys/class/gpio/gpio167/active_low #SFP+39 + #echo 1 > /sys/class/gpio/gpio168/active_low #SFP+40 + #echo 1 > /sys/class/gpio/gpio169/active_low #SFP+41 + #echo 1 > /sys/class/gpio/gpio170/active_low #SFP+42 + #echo 1 > /sys/class/gpio/gpio171/active_low #SFP+43 + #echo 1 > /sys/class/gpio/gpio172/active_low #SFP+44 + #echo 1 > /sys/class/gpio/gpio173/active_low #SFP+45 + #echo 1 > /sys/class/gpio/gpio174/active_low #SFP+46 + #echo 1 > /sys/class/gpio/gpio175/active_low #SFP+47 + +} + +#GPIO DeInit +function _i2c_gpio_deinit { + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN3_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN5_DEVICE}/delete_device + echo "0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/delete_device + echo "0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/delete_device + echo "0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/delete_device +} + +#I2C CPLD init +function _i2c_cpld_init { + echo "=========================================================" + echo "# Description: I2C CPLD Init..." + echo "=========================================================" + + ## modprobe i2c_cpld + modprobe i2c_cpld + ## Add CPLD device + echo "i2c_cpld 0x33" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}/new_device + + echo "done..." +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ]; then + FAN_TRAY=1 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=1 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ]; then + FAN_TRAY=2 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=2 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ]; then + FAN_TRAY=3 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=3 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + FAN_TRAY=4 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=4 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + fi +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C LED TEST..." + echo "=========================================================" + #sys led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x7F + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xBF + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xF7 + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFB + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xDF + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xEF + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFD + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFE + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + _pause 'Check turn off all LEDs and Press [Enter] key to continue...' + echo "done..." +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + local port=$1 + case ${port} in + 1|2|3|4|5|6|7|8) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x20 + dataAddr=0 + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT0_15_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT0_15_ABS_GPIO_IDX} + ;; + 9|10|11|12|13|14|15|16) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x20 + dataAddr=1 + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT0_15_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT0_15_ABS_GPIO_IDX} + ;; + 17|18|19|20|21|22|23|24) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x21 + dataAddr=0 + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT16_31_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT16_31_ABS_GPIO_IDX} + ;; + 25|26|27|28|29|30|31|32) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x21 + dataAddr=1 + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT16_31_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT16_31_ABS_GPIO_IDX} + ;; + 33|34|35|36|37|38|39|40) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x22 + dataAddr=0 + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT32_47_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT32_47_ABS_GPIO_IDX} + ;; + 41|42|43|44|45|46|47|48) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x22 + dataAddr=1 + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT32_47_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT32_47_ABS_GPIO_IDX} + ;; + 49|50|51|52|53|54) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x23 + dataAddr=0 + gpioBase=$((${GPIO_OFFSET}+240-48)) + #gpioBase=$((240 - 48)) + ;; + *) + echo "Please input 1~54" + exit ${FALSE} + ;; + esac +} + +#Get QSFP present +function _i2c_qsfp_status_get { + local status + _qsfp_port_i2c_var_set ${QSFP_PORT} + if [ ${QSFP_PORT} -lt 49 ] && [ ${QSFP_PORT} -gt 0 ]; then + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) % 16 )) ))/value` + elif [ ${QSFP_PORT} -ge 49 ] && [ ${QSFP_PORT} -le 54 ]; then + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1))) ))/value` + fi + + echo "status=$status" +} + +#Get QSFP type +function _i2c_qsfp_type_get { + _get_sfp_eeprom_bus_idx ${QSFP_PORT} + eeprombus=${SFP_EEPROM_BUS_IDX} + eepromAddr=0x50 + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom) + + if [ ${QSFP_PORT} -ge 1 ] && [ ${QSFP_PORT} -le 48 ]; then + echo "sfp" + # 1~48 port is sfp port + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 0 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 2 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 3 -n 1 -e '"%x"') + else + echo "qsfp" + # 49~54 port is qsfp port + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + fi + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + if [ ${QSFP_PORT} -lt 49 ] && [ ${QSFP_PORT} -gt 0 ]; then + + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) % 16 )) ))/value` + echo $status + + if [ $status = 0 ]; then + exit + fi + + _get_sfp_eeprom_bus_idx ${QSFP_PORT} + eeprombus=${SFP_EEPROM_BUS_IDX} + eepromAddr=0x50 + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C + elif [ ${QSFP_PORT} -ge 49 ] && [ ${QSFP_PORT} -le 54 ]; then + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1))) ))/value` + echo $status + + if [ $status = 0 ]; then + exit + fi + _get_sfp_eeprom_bus_idx ${QSFP_PORT} + eeprombus=${SFP_EEPROM_BUS_IDX} + eepromAddr=0x50 + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi +} + +#PSU EEPROM init +function _i2c_psu_eeprom_init { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Init..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom + ## PUS(0) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX2_CHAN6_DEVICE}/new_device + + ## PUS(1) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX2_CHAN7_DEVICE}/new_device + + echo "done..." +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom + ## PUS(0) EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX2_CHAN6_DEVICE}-0050/eeprom | hexdump -C + + ## PUS(1) EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX2_CHAN7_DEVICE}-0050/eeprom | hexdump -C + + echo "done..." +} + +#Get MotherBoard EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom_mb + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX2_CHAN7_DEVICE}-0054/eeprom | hexdump -C + echo "done..." +} + +#Set System Status LED +function _i2c_sys_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x80 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x80 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x40 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x40 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU2 LED +function _i2c_psu2_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x20 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x20 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x10 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x10 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + case ${FAN_TRAY} in + 1) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_MUX2_CHAN7_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_MUX2_CHAN7_DEVICE} $i2cAddr $ioPort 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_MUX2_CHAN7_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_MUX2_CHAN7_DEVICE} $i2cAddr $ioPort 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x08 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x08 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x04 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x04 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU1 LED +function _i2c_psu1_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x02 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x02 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x01 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x01 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Get Board Version and Type +function _i2c_board_type_get { + boardType=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_board_type` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BOARD_ID is 0x%02x, HW Rev %d, Build Rev %d\n" $boardId $boardHwRev $boardBuildRev + +} + +#Get CPLD Version +function _i2c_cpld_version { + cpldRev=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_version` + cpldRelease=$((($cpldRev) >> 6 & 0x01)) + cpldVersion=$((($cpldRev) & 0x3F)) + printf "CPLD is %s version(0:RD 1:Release), Revision is 0x%02x\n" $cpldRelease $cpldVersion + +} + +#Get PSU Status +function _i2c_psu_status { + psuPresent=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_pw_abs` + psu1Exist=$(($((($psuPresent) & 0x01))?0:1)) + psu2Exist=$(($((($psuPresent) & 0x02))?0:1)) + psuPwGood=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_pw_good` + psu1PwGood=$(($((($psuPwGood) >> 3 & 0x01))?1:0)) + psu2PwGood=$(($((($psuPwGood) >> 3 & 0x02))?1:0)) + printf "PSU1 Exist:%d PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Get Front Sensor Temperature +function _i2c_front_temp { + #Front MAC + sensors | grep 'Front MAC Temp' -A 1 +} + +#Get Rear Sensor Temperature +function _i2c_rear_temp { + #Rear MAC + sensors | grep 'Rear MAC Temp' -A 1 +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Main Function +function _main { + tart_time_str=`date` + start_time_sec=$(date +%s) + + _set_gpio_offset + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_fan_init" ]; then + _i2c_fan_init + elif [ "${EXEC_FUNC}" == "i2c_volmon_init" ]; then + _i2c_volmon_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_init" ]; then + _i2c_gpio_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_deinit" ]; then + _i2c_gpio_deinit + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_front_temp" ]; then + _i2c_front_temp + elif [ "${EXEC_FUNC}" == "i2c_rear_temp" ]; then + _i2c_rear_temp + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_temp_init + _i2c_fan_init + _i2c_io_exp_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_board_type_get + _i2c_cpld_version + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_monitor.sh new file mode 100644 index 000000000000..7f50d137bcb7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_monitor.sh @@ -0,0 +1,106 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, 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 . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..53}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + # identifier 11 for qsfp, 3 for sfp + if [ "${identifier}" == "11" ] || [ "${identifier}" == "3" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #AOC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to AOC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} aoc $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_si_cfg.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_si_cfg.sh new file mode 100644 index 000000000000..6ded3e522bce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_si_cfg.sh @@ -0,0 +1,331 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, 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 . + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +TYPE=${1} +PORT=${2} + +# port number +MIN_PORT=0 +MAX_PORT=53 + +# INDEX of value field in array +SI_PRE_IDX=1 +SI_POST_IDX=2 +SI_MAIN_IDX=3 +SI_AMP_IDX=4 +SI_DRI_IDX=5 + +# type string +AOC_TYPE="aoc" +DAC_TYPE="dac" + +# si value for bcm command +SI_VAL="" + +# "PRE POST MAIN AMP DRIVERMODE" for each port in array +# TODO: need to change aoc si value when available +xe_aoc_si_value=( + "0x00 0x3e 0x32 0xf 0x0" #port 0 + "0x00 0x3a 0x36 0xf 0x0" #port 1 + "0x00 0x3a 0x36 0xf 0x0" #port 2 + "0x00 0x38 0x38 0xf 0x0" #port 3 + "0x00 0x37 0x39 0xf 0x0" #port 4 + "0x00 0x2e 0x42 0xf 0x0" #port 5 + "0x00 0x33 0x3d 0xf 0x0" #port 6 + "0x00 0x30 0x40 0xc 0x0" #port 7 + "0x00 0x2f 0x43 0xe 0x0" #port 8 + "0x00 0x2d 0x43 0xc 0x0" #port 9 + "0x00 0x2c 0x44 0xc 0x0" #port 10 + "0x00 0x2d 0x43 0xc 0x0" #port 11 + "0x00 0x29 0x47 0xc 0x0" #port 12 + "0x00 0x28 0x48 0xc 0x0" #port 13 + "0x00 0x29 0x47 0xa 0x0" #port 14 + "0x00 0x29 0x47 0xf 0x0" #port 15 + "0x00 0x18 0x58 0x9 0x0" #port 16 + "0x00 0x1d 0x53 0x9 0x0" #port 17 + "0x00 0x1c 0x54 0x9 0x0" #port 18 + "0x00 0x1c 0x54 0x9 0x0" #port 19 + "0x00 0x1c 0x54 0x9 0x0" #port 20 + "0x00 0x1c 0x54 0x9 0x0" #port 21 + "0x00 0x1c 0x54 0x9 0x0" #port 22 + "0x00 0x1c 0x54 0x9 0x0" #port 23 + "0x00 0x1c 0x54 0x8 0x0" #port 24 + "0x00 0x1c 0x54 0x8 0x0" #port 25 + "0x00 0x18 0x58 0x8 0x0" #port 26 + "0x00 0x18 0x58 0x8 0x0" #port 27 + "0x00 0x14 0x5c 0x8 0x0" #port 28 + "0x00 0x19 0x57 0x8 0x0" #port 29 + "0x00 0x19 0x57 0x8 0x0" #port 30 + "0x00 0x19 0x57 0x8 0x0" #port 31 + "0x00 0x19 0x57 0xc 0x0" #port 32 + "0x00 0x20 0x50 0x9 0x0" #port 33 + "0x00 0x21 0x4f 0xc 0x0" #port 34 + "0x00 0x24 0x4c 0xc 0x0" #port 35 + "0x00 0x24 0x4c 0xc 0x0" #port 36 + "0x00 0x24 0x4c 0xc 0x0" #port 37 + "0x00 0x24 0x4c 0xc 0x0" #port 38 + "0x00 0x24 0x4c 0xc 0x0" #port 39 + "0x00 0x28 0x48 0xd 0x0" #port 40 + "0x00 0x28 0x48 0xc 0x0" #port 41 + "0x00 0x29 0x47 0xe 0x0" #port 42 + "0x00 0x29 0x47 0xe 0x0" #port 43 + "0x00 0x29 0x47 0xe 0x0" #port 44 + "0x00 0x28 0x48 0xf 0x0" #port 45 + "0x00 0x28 0x48 0xf 0x0" #port 46 + "0x00 0x30 0x40 0xf 0x0" #port 47 +) + +# TODO: need to change aoc si value when available +ce_aoc_si_value=( + "0x00 0x28 0x48 0xc 0x0" #port 0 lane 0 + "0x00 0x29 0x41 0xc 0x0" #port 0 lane 1 + "0x00 0x29 0x41 0xf 0x0" #port 0 lane 2 + "0x00 0x29 0x41 0xc 0x0" #port 0 lane 3 + "0x00 0x28 0x42 0xc 0x0" #port 1 lane 0 + "0x00 0x3a 0x36 0xf 0x0" #port 1 lane 1 + "0x00 0x2c 0x44 0xc 0x0" #port 1 lane 2 + "0x00 0x2c 0x44 0xc 0x0" #port 1 lane 3 + "0x00 0x2f 0x41 0xc 0x0" #port 2 lane 0 + "0x00 0x38 0x38 0xc 0x0" #port 2 lane 1 + "0x00 0x2f 0x41 0xc 0x0" #port 2 lane 2 + "0x00 0x30 0x40 0xc 0x0" #port 2 lane 3 + "0x00 0x30 0x40 0xc 0x0" #port 3 lane 0 + "0x00 0x3f 0x31 0xf 0x0" #port 3 lane 1 + "0x00 0x31 0x3f 0xc 0x0" #port 3 lane 2 + "0x00 0x30 0x40 0xa 0x0" #port 3 lane 3 + "0x00 0x30 0x40 0xc 0x0" #port 4 lane 0 + "0x00 0x31 0x3f 0xf 0x0" #port 4 lane 1 + "0x00 0x2f 0x41 0xc 0x0" #port 4 lane 2 + "0x00 0x2e 0x42 0xc 0x0" #port 4 lane 3 + "0x00 0x30 0x40 0xe 0x0" #port 5 lane 0 + "0x00 0x3f 0x31 0xf 0x0" #port 5 lane 1 + "0x00 0x38 0x38 0xf 0x0" #port 5 lane 2 + "0x00 0x3f 0x31 0xf 0x0" #port 5 lane 3 +) + +xe_dac_si_value=( + "0x00 0x3e 0x32 0xf 0x0" #port 0 + "0x00 0x3a 0x36 0xf 0x0" #port 1 + "0x00 0x3a 0x36 0xf 0x0" #port 2 + "0x00 0x38 0x38 0xf 0x0" #port 3 + "0x00 0x37 0x39 0xf 0x0" #port 4 + "0x00 0x2e 0x42 0xf 0x0" #port 5 + "0x00 0x33 0x3d 0xf 0x0" #port 6 + "0x00 0x30 0x40 0xc 0x0" #port 7 + "0x00 0x2f 0x43 0xe 0x0" #port 8 + "0x00 0x2d 0x43 0xc 0x0" #port 9 + "0x00 0x2c 0x44 0xc 0x0" #port 10 + "0x00 0x2d 0x43 0xc 0x0" #port 11 + "0x00 0x29 0x47 0xc 0x0" #port 12 + "0x00 0x28 0x48 0xc 0x0" #port 13 + "0x00 0x29 0x47 0xa 0x0" #port 14 + "0x00 0x29 0x47 0xf 0x0" #port 15 + "0x00 0x18 0x58 0x9 0x0" #port 16 + "0x00 0x1d 0x53 0x9 0x0" #port 17 + "0x00 0x1c 0x54 0x9 0x0" #port 18 + "0x00 0x1c 0x54 0x9 0x0" #port 19 + "0x00 0x1c 0x54 0x9 0x0" #port 20 + "0x00 0x1c 0x54 0x9 0x0" #port 21 + "0x00 0x1c 0x54 0x9 0x0" #port 22 + "0x00 0x1c 0x54 0x9 0x0" #port 23 + "0x00 0x1c 0x54 0x8 0x0" #port 24 + "0x00 0x1c 0x54 0x8 0x0" #port 25 + "0x00 0x18 0x58 0x8 0x0" #port 26 + "0x00 0x18 0x58 0x8 0x0" #port 27 + "0x00 0x14 0x5c 0x8 0x0" #port 28 + "0x00 0x19 0x57 0x8 0x0" #port 29 + "0x00 0x19 0x57 0x8 0x0" #port 30 + "0x00 0x19 0x57 0x8 0x0" #port 31 + "0x00 0x19 0x57 0xc 0x0" #port 32 + "0x00 0x20 0x50 0x9 0x0" #port 33 + "0x00 0x21 0x4f 0xc 0x0" #port 34 + "0x00 0x24 0x4c 0xc 0x0" #port 35 + "0x00 0x24 0x4c 0xc 0x0" #port 36 + "0x00 0x24 0x4c 0xc 0x0" #port 37 + "0x00 0x24 0x4c 0xc 0x0" #port 38 + "0x00 0x24 0x4c 0xc 0x0" #port 39 + "0x00 0x28 0x48 0xd 0x0" #port 40 + "0x00 0x28 0x48 0xc 0x0" #port 41 + "0x00 0x29 0x47 0xe 0x0" #port 42 + "0x00 0x29 0x47 0xe 0x0" #port 43 + "0x00 0x29 0x47 0xe 0x0" #port 44 + "0x00 0x28 0x48 0xf 0x0" #port 45 + "0x00 0x28 0x48 0xf 0x0" #port 46 + "0x00 0x30 0x40 0xf 0x0" #port 47 +) + +ce_dac_si_value=( + "0x00 0x28 0x48 0xc 0x0" #port 0 lane 0 + "0x00 0x29 0x41 0xc 0x0" #port 0 lane 1 + "0x00 0x29 0x41 0xf 0x0" #port 0 lane 2 + "0x00 0x29 0x41 0xc 0x0" #port 0 lane 3 + "0x00 0x28 0x42 0xc 0x0" #port 1 lane 0 + "0x00 0x3a 0x36 0xf 0x0" #port 1 lane 1 + "0x00 0x2c 0x44 0xc 0x0" #port 1 lane 2 + "0x00 0x2c 0x44 0xc 0x0" #port 1 lane 3 + "0x00 0x2f 0x41 0xc 0x0" #port 2 lane 0 + "0x00 0x38 0x38 0xc 0x0" #port 2 lane 1 + "0x00 0x2f 0x41 0xc 0x0" #port 2 lane 2 + "0x00 0x30 0x40 0xc 0x0" #port 2 lane 3 + "0x00 0x30 0x40 0xc 0x0" #port 3 lane 0 + "0x00 0x3f 0x31 0xf 0x0" #port 3 lane 1 + "0x00 0x31 0x3f 0xc 0x0" #port 3 lane 2 + "0x00 0x30 0x40 0xa 0x0" #port 3 lane 3 + "0x00 0x30 0x40 0xc 0x0" #port 4 lane 0 + "0x00 0x31 0x3f 0xf 0x0" #port 4 lane 1 + "0x00 0x2f 0x41 0xc 0x0" #port 4 lane 2 + "0x00 0x2e 0x42 0xc 0x0" #port 4 lane 3 + "0x00 0x30 0x40 0xe 0x0" #port 5 lane 0 + "0x00 0x3f 0x31 0xf 0x0" #port 5 lane 1 + "0x00 0x38 0x38 0xf 0x0" #port 5 lane 2 + "0x00 0x3f 0x31 0xf 0x0" #port 5 lane 3 +) + +#get field value in si value array for xe port +function get_xe_si { + local port=$1 + local field=$2 + local type=$3 + local index=$port + if [ "$type" == "${AOC_TYPE}" ]; then + SI_VAL=$(echo "${xe_aoc_si_value[$index]}" | awk '{print $'$field'}') + else + SI_VAL=$(echo "${xe_dac_si_value[$index]}" | awk '{print $'$field'}') + fi +} + +#get field value in si value array for ce port +function get_ce_si { + local port=$1 + local lane=$2 + local field=$3 + local type=$4 + index=$(( (${port}-1)*4+${lane} )) + if [ "$type" == "${AOC_TYPE}" ]; then + SI_VAL=$(echo "${ce_aoc_si_value[$index]}" | awk '{print $'$field'}') + else + SI_VAL=$(echo "${ce_dac_si_value[$index]}" | awk '{print $'$field'}') + fi +} + +# set si value for xe port +function _qsfp_xe_si_set { + # convert PORT to xe port index + local xe_port=$PORT + # generate command for SI PRE value + get_xe_si $xe_port $SI_PRE_IDX $TYPE + local pre_cmd="phy xe${xe_port} CL93N72_UT_CTL2r CL93N72_TXFIR_PRE=${SI_VAL}" + # generate command for SI POST value + get_xe_si $xe_port $SI_POST_IDX $TYPE + local post_cmd="phy xe${xe_port} CL93N72_UT_CTL2r CL93N72_TXFIR_POST=${SI_VAL}" + # generate command for SI MAIN value + get_xe_si $xe_port $SI_MAIN_IDX $TYPE + local main_cmd="phy xe${xe_port} CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=${SI_VAL}" + # generate command for SI AMP CONTROL value + get_xe_si $xe_port $SI_AMP_IDX $TYPE + local amp_val=$SI_VAL + get_xe_si $xe_port $SI_DRI_IDX $TYPE + local dri_val=$SI_VAL + local amp_cmd="phy xe${xe_port} AMS_TX_CTL2r AMS_TX_AMP_CTL=${amp_val} AMS_TX_DRIVERMODE=${dri_val}" + # apply bcmcmd + bcmcmd "${pre_cmd};${post_cmd};${main_cmd};${amp_cmd}" +} + +# set aoc si value for ce port +function _qsfp_ce_si_set { + # convert PORT to ce port index + local ce_port=$(( $PORT - 48 )) + for lane in {0..3}; + do + # generate command for SI PRE value + get_ce_si $ce_port $lane $SI_PRE_IDX $TYPE + local pre_cmd="phy ce${ce_port} CL93N72_UT_CTL2r.${lane} CL93N72_TXFIR_PRE=${SI_VAL}" + # generate command for SI POST value + get_ce_si $ce_port $lane $SI_POST_IDX $TYPE + local post_cmd="phy ce${ce_port} CL93N72_UT_CTL2r.${lane} CL93N72_TXFIR_POST=${SI_VAL}" + # generate command for SI MAIN value + get_ce_si $ce_port $lane $SI_MAIN_IDX $TYPE + local main_cmd="phy ce${ce_port} CL93N72_UT_CTL3r.${lane} CL93N72_TXFIR_MAIN=${SI_VAL}" + # generate command for SI AMP CONTROL value + get_ce_si $ce_port $lane $SI_AMP_IDX $TYPE + local amp_val=$SI_VAL + get_ce_si $ce_port $lane $SI_AMP_IDX $TYPE + local dri_val=$SI_VAL + local amp_cmd="phy ce${ce_port} AMS_TX_CTL2r.${lane} AMS_TX_AMP_CTL=${amp_val} AMS_TX_DRIVERMODE=${dri_val}" + # apply bcmcmd + bcmcmd "${pre_cmd};${post_cmd};${main_cmd};${amp_cmd}" + done +} + +#QSFP SI value set +function _qsfp_si_set { + if [[ $PORT -le 47 && $PORT -ge 0 ]]; then + # xe port + _qsfp_xe_si_set + else + # ce port + _qsfp_ce_si_set + fi +} + +function _util_input_check { + # input parameter validation + if [[ $1 -lt $2 || $1 -gt $3 ]]; then + echo "Please input number $2~$3" + exit + fi +} + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} ${AOC_TYPE} [${MIN_PORT}-${MAX_PORT}]" + echo " : ${0} ${DAC_TYPE} [${MIN_PORT}-${MAX_PORT}]" + echo "----------------------------------------------------" +} + +#Main Function +function _main { + + # TODO: remove after SI value ready + #exit ${TRUE} + + if [ -z $PORT ]; then + _help + exit ${FALSE} + fi + + if [ "${TYPE}" == "help" ]; then + _help + elif [ "${TYPE}" == "${AOC_TYPE}" ] || [ "${TYPE}" == "${DAC_TYPE}" ]; then + _util_input_check "$PORT" "$MIN_PORT" "$MAX_PORT" + _qsfp_si_set + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/s8900_54xc_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/s8900_54xc_monitor.sh new file mode 100755 index 000000000000..974da6d5001f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/s8900_54xc_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, 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 . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/README.md b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/README.md new file mode 100644 index 000000000000..28f395216e3c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/README.md @@ -0,0 +1,185 @@ +# Ingrasys S8900-64XC Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, 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 . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S8900-64XC is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S8900-64XC platform. + +### I2C i801 + +The I2C i801 on Ingrasys S8900-64XC can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S8900-64XC. + +### I2C iSMT + +The I2C iSMT module on S8900-64XC can be found in +`/sys/bus/i2c/devices/i2c-1/` + +This is I2C bus for CPLD, HWM, power controller and I2C Switches. + +The i801 module must be loaded third on Ingrasys S8900-64XC. + +### I2C PCA9548 +The PCA9548 module on S8900-64XC can be found in +`/sys/bus/i2c/devices/i2c-2/` , `/sys/bus/i2c/devices/i2c-3/`, +`/sys/bus/i2c/devices/i2c-4/`, `/sys/bus/i2c/devices/i2c-5/`, +`/sys/bus/i2c/devices/i2c-6/`, `/sys/bus/i2c/devices/i2c-7/`, +`/sys/bus/i2c/devices/i2c-8/`, `/sys/bus/i2c/devices/i2c-9/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S8900-64XC. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S8900-64XC platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s8900-64xc package is installed on the S8900-64XC, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-9/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/9-0054/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber on|off + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/Makefile b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/Makefile new file mode 100644 index 000000000000..bf7d4baed71b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/Makefile @@ -0,0 +1,4 @@ +#ccflags-y += -DDEBUG +obj-m := eeprom_mb.o +obj-m+= qsfp_cpld.o +obj-m+= i2c_cpld.o diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/eeprom_mb.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/eeprom_mb.c new file mode 100644 index 000000000000..0886cad58eb3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/eeprom_mb.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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 + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, I2C_CLIENT_END }; + + +/* 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 mb_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 mb_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++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_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, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys S8900 Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/i2c_cpld.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/i2c_cpld.c new file mode 100644 index 000000000000..626c63177b50 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/i2c_cpld.c @@ -0,0 +1,448 @@ +/* + * S9100-32X I2C CPLD driver + * + * Copyright (C) 2017 Ingrasys, Inc. + * Wade He + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c_cpld.h" + +#ifdef DEBUG + #define DEBUG_PRINT(fmt, args...) \ + printk(KERN_INFO "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define I2C_READ_BYTE_DATA(ret, lock, i2c_client, reg) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_read_byte_data(i2c_client, reg); \ + mutex_unlock(lock); \ +} +#define I2C_WRITE_BYTE_DATA(ret, lock, i2c_client, reg, val) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_write_byte_data(i2c_client, reg, val); \ + mutex_unlock(lock); \ +} + +/* CPLD sysfs attributes index */ +enum i2c_cpld_sysfs_attributes { + CPLD_ACCESS_REG, + CPLD_REGISTER_VAL, + CPLD_PORT_START, + CPLD_PORTS, + CPLD_VERSION, + CPLD_ID, + CPLD_BOARD_TYPE, + CPLD_EXT_BOARD_TYPE, + CPLD_PW_GOOD, + CPLD_PW_ABS, +}; + +/* CPLD sysfs attributes hook functions */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_pw_good(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_pw_abs(struct device *dev, + struct device_attribute *da, char *buf); + +static LIST_HEAD(cpld_client_list); /* client list for cpld */ +static struct mutex list_lock; /* mutex for client list */ + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +struct cpld_data { + int index; /* CPLD index */ + struct mutex access_lock; /* mutex for cpld access */ + u8 access_reg; /* register to access */ +}; + +/* CPLD device id and data */ +static const struct i2c_device_id i2c_cpld_id[] = { + { "i2c_cpld", i2c_cpld }, + {} +}; + +/* Addresses scanned for i2c_cpld */ +static const unsigned short cpld_i2c_addr[] = { 0x33, I2C_CLIENT_END }; +/* platform sysfs object */ +extern struct kobject *s9230_64x_kobj; + + +/* define all support register access of cpld in attribute */ +static SENSOR_DEVICE_ATTR(cpld_access_register, S_IWUSR | S_IRUGO, + read_access_register, write_access_register, CPLD_ACCESS_REG); +static SENSOR_DEVICE_ATTR(cpld_register_value, S_IWUSR | S_IRUGO, + read_register_value, write_register_value, CPLD_REGISTER_VAL); +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, + read_cpld_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(cpld_board_type, S_IRUGO, + read_board_type, NULL, CPLD_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_ext_board_type, S_IRUGO, + read_ext_board_type, NULL, CPLD_EXT_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_pw_good, S_IRUGO, + read_pw_good, NULL, CPLD_PW_GOOD); +static SENSOR_DEVICE_ATTR(cpld_pw_abs, S_IRUGO, + read_pw_abs, NULL, CPLD_PW_ABS); + + +/* define support attributes of cpldx , total 5 */ +/* cpld 1 */ +static struct attribute *i2c_cpld_attributes[] = { + &sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_ext_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_pw_good.dev_attr.attr, + &sensor_dev_attr_cpld_pw_abs.dev_attr.attr, + NULL +}; + +/* cpld 1 attributes group */ +static const struct attribute_group i2c_cpld_group = { + .attrs = i2c_cpld_attributes, +}; + +/* read access register from cpld data */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + + return sprintf(buf, "0x%x\n", reg); +} + +/* write access register to cpld data */ +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + + if (kstrtou8(buf, 0, ®) < 0) + return -EINVAL; + + data->access_reg = reg; + return count; +} + +/* read the value of access register in cpld data */ +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + int reg_val; + + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + + if (reg_val < 0) + return -1; + + return sprintf(buf, "0x%x\n", reg_val); +} + +/* wrtie the value to access register in cpld data */ +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ret = -EIO; + u8 reg = data->access_reg; + u8 reg_val; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, client, reg, reg_val); + + return count; +} + +/* get cpdl version register value */ +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_VERSION) { + reg = CPLD_VERSION_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get board type register value */ +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BOARD_TYPE) { + reg = CPLD_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_EXT_BOARD_TYPE) { + reg = CPLD_EXT_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_pw_good(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_PW_GOOD) { + reg = CPLD_PW_GOOD_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_pw_abs(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_PW_ABS) { + reg = CPLD_PW_ABS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* add valid cpld client to list */ +static void i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = NULL; + + node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + if (!node) { + dev_info(&client->dev, + "Can't allocate cpld_client_node for index %d\n", + client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +/* remove exist cpld client in list */ +static void i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + mutex_unlock(&list_lock); +} + +/* cpld drvier probe */ +static int i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct cpld_data *data = NULL; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* init cpld data for client */ + i2c_set_clientdata(client, data); + mutex_init(&data->access_lock); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_info(&client->dev, + "i2c_check_functionality failed (0x%x)\n", + client->addr); + status = -EIO; + goto exit; + } + + + status = sysfs_create_group(&client->dev.kobj,&i2c_cpld_group); + + if (status) + goto exit; + + dev_info(&client->dev, "chip found\n"); + + /* add probe chip to client list */ + i2c_cpld_add_client(client); + + return 0; +exit: + sysfs_remove_group(&client->dev.kobj, &i2c_cpld_group); + return status; +} + +/* cpld drvier remove */ +static int i2c_cpld_remove(struct i2c_client *client) +{ + + sysfs_remove_group(&client->dev.kobj, &i2c_cpld_group); + + i2c_cpld_remove_client(client); + return 0; +} + +MODULE_DEVICE_TABLE(i2c, i2c_cpld_id); + +static struct i2c_driver i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "i2c_cpld", + }, + .probe = i2c_cpld_probe, + .remove = i2c_cpld_remove, + .id_table = i2c_cpld_id, + .address_list = cpld_i2c_addr, +}; + +static int __init i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&i2c_cpld_driver); +} + +static void __exit i2c_cpld_exit(void) +{ + i2c_del_driver(&i2c_cpld_driver); +} + +MODULE_AUTHOR("Wade He "); +MODULE_DESCRIPTION("Ingrasys S9100-32X Platform i2c cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_cpld_init); +module_exit(i2c_cpld_exit); + + + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/i2c_cpld.h b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/i2c_cpld.h new file mode 100644 index 000000000000..e103b05c717a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/i2c_cpld.h @@ -0,0 +1,197 @@ +/* + * + * S9100-32X I2C CPLD driver header file + * + * Copyright (C) 2017 Ingrasys, Inc. + * Wade He + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef I2C_CPLD_H +#define I2C_CPLD_H + +// remove debug before release +#define DEBUG + +/* CPLD device index value */ +enum cpld_id { + i2c_cpld +}; + +/* port number on CPLD */ +#define CPLD_1_PORT_NUM 12 +#define CPLD_2_PORT_NUM 13 + +/* QSFP port number */ +#define QSFP_MAX_PORT_NUM 64 +#define QSFP_MIN_PORT_NUM 1 + +/* SFP+ port number */ +#define SFP_MAX_PORT_NUM 2 +#define SFP_MIN_PORT_NUM 1 + + +/* CPLD registers */ +#define CPLD_BOARD_TYPE_REG 0x0 +#define CPLD_EXT_BOARD_TYPE_REG 0x7 +#define CPLD_VERSION_REG 0x1 +#define CPLD_PW_GOOD_REG 0x2 +#define CPLD_PW_ABS_REG 0x3 + + +/* bit definition for register value */ + +enum CPLD_RESET_CONTROL_BITS { + CPLD_RESET_CONTROL_SWRST_BIT, + CPLD_RESET_CONTROL_CP2104RST_BIT, + CPLD_RESET_CONTROL_82P33814RST_BIT, + CPLD_RESET_CONTROL_BMCRST_BIT, +}; + +/* bit field structure for register value */ +struct cpld_reg_board_type_t { + u8 build_rev:2; + u8 hw_rev:2; + u8 board_id:4; +}; + +struct cpld_reg_version_t { + u8 revision:6; + u8 release:1; + u8 reserve:1; +}; + +struct cpld_reg_pw_good_t { + u8 reserve1:3; + u8 psu1:1; + u8 psu2:1; + u8 reserve2:3; +}; + +struct cpld_reg_pw_abs_t { + u8 psu1:1; + u8 psu2:1; + u8 reserve:6; +}; + +/* common manipulation */ +#define INVALID(i, min, max) ((i < min) || (i > max) ? 1u : 0u) +#define READ_BIT(val, bit) ((0u == (val & (1<bf_name) +#define READ_BF_1(bf_struct, val, bf_name, bf_value) \ + bf_struct bf; \ + bf.data = val; \ + bf_value = bf.bf_name +#define BOARD_TYPE_BUILD_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, build_rev, res) +#define BOARD_TYPE_HW_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, hw_rev, res) +#define BOARD_TYPE_BOARD_ID_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, board_id, res) +#define CPLD_VERSION_REV_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, revision, res) +#define CPLD_VERSION_REL_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, release, res) +#define CPLD_PSU1_PW_GOOD_GET(val, res) \ + READ_BF(cpld_reg_pw_good_t, val, psu1, res) +#define CPLD_PSU2_PW_GOOD_GET(val, res) \ + READ_BF(cpld_reg_pw_good_t, val, psu2, res) +#define CPLD_PSU1_PW_ABS_GET(val, res) \ + READ_BF(cpld_reg_pw_abs_t, val, psu1, res) +#define CPLD_PSU2_PW_ABS_GET(val, res) \ + READ_BF(cpld_reg_pw_abs_t, val, psu2, res) +/* QSFP/SFP registers manipulation */ +#define QSFP_TO_CPLD_IDX(qsfp_port, cpld_index, cpld_port) \ +{ \ + if (QSFP_MIN_PORT_NUM <= qsfp_port && qsfp_port <= CPLD_1_PORT_NUM) { \ + cpld_index = cpld1; \ + cpld_port = qsfp_port - 1; \ + } else if (CPLD_1_PORT_NUM < qsfp_port \ + && qsfp_port <= QSFP_MAX_PORT_NUM) { \ + cpld_index = cpld2 + (qsfp_port - 1 - CPLD_1_PORT_NUM) \ + / CPLD_2_PORT_NUM; \ + cpld_port = (qsfp_port - 1 - CPLD_1_PORT_NUM) % \ + CPLD_2_PORT_NUM; \ + } else { \ + cpld_index = 0; \ + cpld_port = 0; \ + } \ +} +#define SFP_TO_CPLD_IDX(sfp_port, cpld_index) \ + (cpld_index = sfp_port - SFP_MIN_PORT_NUM) +#define QSFP_PORT_STATUS_REG(cpld_port) \ + (CPLD_QSFP_PORT_STATUS_BASE_REG + cpld_port) +#define QSFP_PORT_CONFIG_REG(cpld_port) \ + (CPLD_QSFP_PORT_CONFIG_BASE_REG + cpld_port) +#define QSFP_PORT_INT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_INT_BIT) +#define QSFP_PORT_ABS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_ABS_BIT) +#define QSFP_PORT_RESET_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_RESET_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_RESET_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_LPMODE_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define SFP_PORT_PRESENT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_PRESENT_BIT) + + #define SFP_PORT_TXFAULT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_TXFAULT_BIT) + #define SFP_PORT_RXLOS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_RXLOS_BIT) + #define SFP_PORT_TXDIS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TXDIS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_TXDIS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_RS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) + +/* CPLD access functions */ +extern int i2c_cpld_get_qsfp_port_status_val(u8 port_num); +extern int i2c_cpld_get_qsfp_port_config_val(u8 port_num); +extern int i2c_cpld_set_qsfp_port_config_val(u8 port_num, u8 reg_val); +extern int i2c_cpld_get_sfp_port_status_val(u8 port_num); +extern int i2c_cpld_get_sfp_port_config_val(u8 port_num); +extern int i2c_cpld_set_sfp_port_config_val(u8 port_num, u8 reg_val); +extern u8 fp_port_to_phy_port(u8 fp_port); +#endif + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/qsfp_cpld.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/qsfp_cpld.c new file mode 100644 index 000000000000..8ec03ecea340 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/qsfp_cpld.c @@ -0,0 +1,1771 @@ +/* + * S8900-64XC QSFP CPLD driver + * + * Copyright (C) 2017 Ingrasys, 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 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef DEBUG + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define ERROR_MSG(fmt, args...) \ + printk(KERN_ERR "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) + + + + +#define SFF_8436_MMAP_SIZE (256) +#define EEPROM_SIZE (5 * 128) /* 640 byte eeprom */ +#define EEPROM_PAGE_SIZE (128) +#define EEPROM_DEFAULT_PAGE (0) +#define I2C_RW_RETRY_COUNT (3) +#define I2C_RW_RETRY_INTERVAL (100) /* ms */ +#define USE_I2C_BLOCK_READ (1) + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) + +#define SFF_8436_PAGE_PROV_ADDR (0xC3) /* Memory Page 01/02 Provided */ +#define SFF_8436_PAGE_01_PRESENT (1 << 6) /* Memory Page 01 present */ +#define SFF_8436_PAGE_02_PRESENT (1 << 7) /* Memory Page 02 present */ +#define SFF_8436_PAGE_SELECT_ADDR (0x7F) +#define SFF_8436_STATUS_ADDR (0x02) +#define SFF_8436_STATUS_PAGE_03_PRESENT_L (1 << 2) /* Flat Memory:0-Paging, 1-Page 0 only */ + +#define S8900_64XC_MUX_BASE_NR 1 +#define S8900_64XC_SFP_EEPROM_BASE_NR 2 +#define CPLD_DEVICE_NUM 3 +#define SFP_CPLD_DEVICE_NUM 2 +#define QSFP_EEPROM_DEVICE_NUM 3 +#define TOTAL_PORT_NUM 64 +#define CPLD_MUX_OFFSET 24 +#define SFP_EEPROM_DEV_NUM 3 +#define SFP_EEPROM_NAME_LEN 16 +/* CPLD registers */ +#define CPLD_REG_REV 0x01 +#define CPLD_REG_ID 0x02 +#define CPLD_MUX_REG 0x4a + +/* QSFP signal bit in register */ +#define BIT_RST 0 +#define BIT_LPM 2 +#define BIT_INT 0 +#define BIT_ABS 1 +#define BIT_ABS_2 5 + +static ssize_t sfp_eeprom_read(struct i2c_client *, loff_t, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, loff_t, const char *,int); + + +enum port_numbers { + sfp1, sfp2, sfp3, sfp4, sfp5, sfp6, sfp7, sfp8, + sfp9, sfp10, sfp11, sfp12, sfp13, sfp14, sfp15, sfp16, + sfp17, sfp18, sfp19, sfp20, sfp21, sfp22, sfp23, sfp24, + sfp25, sfp26, sfp27, sfp28, sfp29, sfp30, sfp31, sfp32, + sfp33, sfp34, sfp35, sfp36, sfp37, sfp38, sfp39, sfp40, + sfp41, sfp42, sfp43, sfp44, sfp45, sfp46, sfp47, sfp48, + qsfp49, qsfp50, qsfp51, qsfp52, qsfp53, qsfp54, qsfp55, qsfp56, + qsfp57, qsfp58, qsfp59, qsfp60, qsfp61, qsfp62, qsfp63, qsfp64 +}; + +static const struct platform_device_id qsfp_device_id[] = { + {"sfp1", sfp1}, {"sfp2", sfp2}, {"sfp3", sfp3}, {"sfp4", sfp4}, + {"sfp5", sfp5}, {"sfp6", sfp6}, {"sfp7", sfp7}, {"sfp8", sfp8}, + {"sfp9", sfp9}, {"sfp10", sfp10}, {"sfp11", sfp11}, {"sfp12", sfp12}, + {"sfp13", sfp13}, {"sfp14", sfp14}, {"sfp15", sfp15}, {"sfp16", sfp16}, + {"sfp17", sfp17}, {"sfp18", sfp18}, {"sfp19", sfp19}, {"sfp20", sfp20}, + {"sfp21", sfp21}, {"sfp22", sfp22}, {"sfp23", sfp23}, {"sfp24", sfp24}, + {"sfp25", sfp25}, {"sfp26", sfp26}, {"sfp27", sfp27}, {"sfp28", sfp28}, + {"sfp29", sfp29}, {"sfp30", sfp30}, {"sfp31", sfp31}, {"sfp32", sfp32}, + {"sfp33", sfp33}, {"sfp34", sfp34}, {"sfp35", sfp35}, {"sfp36", sfp36}, + {"sfp37", sfp37}, {"sfp38", sfp38}, {"sfp39", sfp39}, {"sfp40", sfp40}, + {"sfp41", sfp41}, {"sfp42", sfp42}, {"sfp43", sfp43}, {"sfp44", sfp44}, + {"sfp45", sfp45}, {"sfp46", sfp46}, {"sfp47", sfp47}, {"sfp48", sfp48}, + {"qsfp49", qsfp49}, {"qsfp50", qsfp50}, {"qsfp51", qsfp51}, {"qsfp52", qsfp52}, + {"qsfp53", qsfp53}, {"qsfp54", qsfp54}, {"qsfp55", qsfp55}, {"qsfp56", qsfp56}, + {"qsfp57", qsfp57}, {"qsfp58", qsfp58}, {"qsfp59", qsfp59}, {"qsfp60", qsfp60}, + {"qsfp61", qsfp61}, {"qsfp62", qsfp62}, {"qsfp63", qsfp63}, {"qsfp64", qsfp64}, + {} +}; +MODULE_DEVICE_TABLE(platform, qsfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28 +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +typedef enum eeprom_operation_e { + EEPROM_READ, + EEPROM_WRITE +} eeprom_operation_t; + +/* + * Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss + */ + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + TX_DISABLE_ALL, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL, +}; + +static void device_release(struct device *dev) +{ + return; +} + +/* + * S8900-64XC CPLD register addresses + */ +static const int int_abs_reg[CPLD_DEVICE_NUM][2]= { + {0x20, 0x31}, + {0x20, 0x31}, + {0x20, 0x2F}, +}; + +static const int rst_lp_reg[CPLD_DEVICE_NUM][2]= { + {0xFF, 0xFF}, /*dummy*/ + {0xFF, 0xFF}, /*dummy*/ + {0x30, 0x3F}, +}; + +/* + * S8900-64XC CPLD + */ + +enum cpld_type { + cpld_1, + cpld_2, + cpld_3, +}; + +enum qsfp_signal { + sig_int, + sig_abs, + sig_rst, + sig_lpm +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +struct sfp_platform_data { + int reg_addr; + int parent; + int cpld_reg; + struct i2c_client *client; +}; + +static struct cpld_platform_data s8900_64xc_cpld_platform_data[] = { + [cpld_1] = { + .reg_addr = 0x33, + }, + + [cpld_2] = { + .reg_addr = 0x33, + }, + + [cpld_3] = { + .reg_addr = 0x33, + } +}; + +static struct sfp_platform_data s8900_64xc_sfp_platform_data[] = { + [sfp1] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x01, + }, + + [sfp2] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x02, + }, + + [sfp3] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x03, + }, + [sfp4] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x04, + }, + + [sfp5] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x05, + }, + + [sfp6] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x06, + }, + [sfp7] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x07, + }, + + [sfp8] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x08, + }, + + [sfp9] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x09, + }, + [sfp10] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x0A, + }, + + [sfp11] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x0B, + }, + + [sfp12] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x0C, + }, + [sfp13] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x0D, + }, + + [sfp14] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x0E, + }, + + [sfp15] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x0F, + }, + [sfp16] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x10, + }, + + [sfp17] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x11, + }, + + [sfp18] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x12, + }, + [sfp19] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x13, + }, + + [sfp20] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x14, + }, + + [sfp21] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x15, + }, + [sfp22] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x16, + }, + + [sfp23] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x17, + }, + + [sfp24] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x18, + }, + [sfp25] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x01, + }, + + [sfp26] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x02, + }, + [sfp27] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x03, + }, + + [sfp28] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x04, + }, + + [sfp29] = { + .reg_addr = 0x50, + + .parent = 3, + .cpld_reg = 0x05, + }, + [sfp30] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x06, + }, + [sfp31] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x07, + }, + [sfp32] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x08, + }, + [sfp33] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x09, + }, + [sfp34] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x0A, + }, + [sfp35] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x0B, + }, + [sfp36] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x0C, + }, + [sfp37] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x0D, + }, + [sfp38] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x0E, + }, + [sfp39] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x0F, + }, + [sfp40] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x10, + }, + [sfp41] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x11, + }, + [sfp42] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x12, + }, + [sfp43] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x13, + }, + [sfp44] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x14, + }, + [sfp45] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x15, + }, + [sfp46] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x16, + }, + [sfp47] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x17, + }, + [sfp48] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x18, + }, + [qsfp49] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x01, + }, + [qsfp50] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x02, + }, + [qsfp51] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x03, + }, + [qsfp52] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x04, + }, + [qsfp53] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x05, + }, + [qsfp54] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x06, + }, + [qsfp55] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x07, + }, + [qsfp56] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x08, + }, + [qsfp57] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x09, + }, + [qsfp58] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x0A, + }, + [qsfp59] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x0B, + }, + [qsfp60] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x0C, + }, + [qsfp61] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x0D, + }, + [qsfp62] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x0E, + }, + [qsfp63] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x0F, + }, + [qsfp64] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x10, + } +}; + +static struct platform_device s8900_64xc_cpld = { + .name = "ingrasys-s8900-64xc-cpld", + .id = 0, + .dev = { + .platform_data = s8900_64xc_cpld_platform_data, + .release = device_release + }, +}; + +static struct platform_device s8900_64xc_sfp = { + .name = "ingrasys-s8900-64xc-sfp", + .id = 0, + .dev = { + .platform_data = s8900_64xc_sfp_platform_data, + .release = device_release + }, +}; + +/* + * S8900-64XC I2C DEVICES + */ + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; + +/* module_platform_driver */ +static ssize_t +get_prs_cpld_reg(struct device *dev, + struct device_attribute *devattr, + char *buf, int signal) +{ + int ret; + u64 data = 0; + u64 shift = 0; + int i = 0; + int j = 0; + int port = 0; + int bit = 0; + int bit_mask = 0; + int bit_mask_2 = 0; + int (*reg)[CPLD_DEVICE_NUM][2]; + struct cpld_platform_data *pdata = NULL; + + pdata = dev->platform_data; + + switch(signal) { + case sig_int: + bit = BIT_INT; + reg = (typeof(reg)) &int_abs_reg; + break; + case sig_abs: + bit = BIT_ABS; + reg = (typeof(reg)) &int_abs_reg; + break; + default: + return sprintf(buf, "signal/na"); + } + bit_mask = 0x1 << bit; + bit_mask_2 = 0x1 << BIT_ABS_2; + + for (i=0; i= 0x2a && j <= 0x2f && i < SFP_CPLD_DEVICE_NUM) { + continue; + } + ret = i2c_smbus_read_byte_data(pdata[i].client, j); + if (ret < 0) { + return sprintf((char *)buf, "i2c_smbus_read_byte_data/na"); + } + shift = ((u64) ((ret & bit_mask) >> bit)) << port; + data |= shift; + DEBUG_PRINT("port=%d, shift=0x%016llx, ret=%x, bit_mask=%08x, bit=%08x, data=0x%016llx\n", port, shift, ret, bit_mask, bit, data); + /* CPLD2 and CPLD3 have BIT 1 and BIT 5 for present */ + if (i < SFP_CPLD_DEVICE_NUM) { + port++; + shift = ((u64) ((ret & bit_mask_2) >> BIT_ABS_2)) << port; + data |= shift; + DEBUG_PRINT("port=%d, shift=0x%016llx, ret=%x, bit_mask_2=0x%x, bit=%x, data=0x%016llx\n", port, shift, ret, bit_mask_2, bit, data); + } + + port++; + } + } + + return sprintf((char *)buf, "0x%016llx\n", data); +} + +/* module_platform_driver */ +static ssize_t +get_rst_lp_cpld_reg(struct device *dev, + struct device_attribute *devattr, + char *buf, int signal) +{ + int ret; + u64 data = 0; + u64 shift = 0; + int i = 0; + int j = 0; + int port = 0; + int bit = 0; + int bit_mask = 0; + int (*reg)[CPLD_DEVICE_NUM][2]; + struct cpld_platform_data *pdata = NULL; + + pdata = dev->platform_data; + + switch(signal) { + case sig_rst: + bit = BIT_RST; + reg = (typeof(reg)) &rst_lp_reg; + break; + case sig_lpm: + bit = BIT_LPM; + reg = (typeof(reg)) &rst_lp_reg; + break; + default: + return sprintf(buf, "na"); + } + bit_mask = 0x1 << bit; + + for (i=2; i> bit)) << port; + data |= shift; + port++; + } + } + + return sprintf(buf, "0x%04llx\n", data); +} + +static ssize_t +set_rst_lp_cpld_reg(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count, int signal) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + u8 current_reg_val = 0; + u8 new_reg_val = 0; + int value; + int i = 0; + int j = 0; + int port = 0; + int ret = 0; + int bit = 0; + int (*reg)[CPLD_DEVICE_NUM][2]; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + switch(signal) { + case sig_rst: + bit = BIT_RST; + reg = (typeof(reg)) &rst_lp_reg; + break; + case sig_lpm: + bit = BIT_LPM; + reg = (typeof(reg)) &rst_lp_reg; + break; + default: + return sprintf((char *)buf, "signal/na"); + } + + for (i=2; i> port) & 0x1; + + //set value on bit N of new_reg_val + if (value > 0) { + new_reg_val = current_reg_val | (u8) (0x1 << bit); + } else { + new_reg_val = current_reg_val & (u8) ~(0x1 << bit); + } + //write reg value if changed + if (current_reg_val != new_reg_val) { + ret = i2c_smbus_write_byte_data(pdata[i].client, j, + (u8)(new_reg_val)); + if (ret < 0){ + return ret; + } + } + port++; + } + } + + return count; +} + +static ssize_t +get_lpmode(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return get_rst_lp_cpld_reg(dev, devattr, buf, sig_lpm); +} + +static ssize_t +set_lpmode(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + return set_rst_lp_cpld_reg(dev, devattr, buf, count, sig_lpm); +} + +static ssize_t +get_reset(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return get_rst_lp_cpld_reg(dev, devattr, buf, sig_rst); +} + +static ssize_t +set_reset(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + return set_rst_lp_cpld_reg(dev, devattr, buf, count, sig_rst); +} + +static ssize_t +get_modprs(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return get_prs_cpld_reg(dev, devattr, buf, sig_abs); +} + +static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL); +static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode); +static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset); + +static struct attribute *s8900_64xc_cpld_attrs[] = { + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_modprs.attr, + NULL, +}; + +static struct attribute_group s8900_64xc_cpld_attr_grp = { + .attrs = s8900_64xc_cpld_attrs, +}; + +/* + * Assumes that sanity checks for offset happened at sysfs-layer. + * Offset within Lower Page 00h and Upper Page 00h are not recomputed + */ +static uint8_t +sff_8436_translate_offset(loff_t *offset) +{ + unsigned page = 0; + + if (*offset < SFF_8436_MMAP_SIZE) { + return 0; + } + + page = (*offset >> 7)-1; + + if (page > 0 ) { + *offset = 0x80 + (*offset & 0x7f); + } else { + *offset &= 0xff; + } + + return page; +} + +static ssize_t +eeprom_read(struct i2c_client *client, + u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_read_i2c_block_data(client, command, + data_len, (u8 *)data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + goto abort; + } + + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + +abort: + return result; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_read_byte_data(client, command); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, " \\ + "command(0x%2x), data(0x%2x)\r\n", + command, result); + goto abort; + } + + *data = (u8)result; + result = 1; + +abort: + return result; +#endif +} + +static ssize_t +eeprom_write(struct i2c_client *client, + u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return data_len; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_write_byte_data(client, command, *data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return 1; +#endif +} + +static ssize_t +sfp_eeprom_read_write(struct i2c_client *client, + eeprom_operation_t op, + loff_t off, + const char *data, + int data_len) +{ + u8 page, phy_page; + u8 val, refresh_page = 0; + int ret; + ssize_t retval = 0; + size_t pending_len = 0, page_len = 0; + loff_t page_offset = 0, page_start_offset = 0; + loff_t phy_offset; + + + if (off > EEPROM_SIZE) { + return 0; + } + + if (off + data_len > EEPROM_SIZE) { + data_len = EEPROM_SIZE - off; + } + + /* + * Refresh pages which covers the requested data + * from offset to off + len + * Only refresh pages which contain requested bytes + * + */ + + pending_len = data_len; + + for (page = off >> 7; page <= (off + data_len - 1) >> 7; page++) { + refresh_page = 0; + switch (page) { + case 0: + /* Lower page 00h */ + refresh_page = 1; + break; + case 1: + /* Upper page 00h */ + refresh_page = 1; + break; + case 2: + /* Upper page 01h */ + ret = eeprom_read(client, SFF_8436_PAGE_PROV_ADDR, &val, sizeof(val)); + if (ret < 0) { + DEBUG_PRINT("Can't read EEPROM offset %d.\n", + SFF_8436_PAGE_PROV_ADDR); + goto error; + } + if (val & SFF_8436_PAGE_01_PRESENT) { + DEBUG_PRINT("Offset:%d Value:(0x%02x & 0x%02x)", + SFF_8436_PAGE_PROV_ADDR, val, + SFF_8436_PAGE_01_PRESENT); + refresh_page = 1; + } + break; + case 3: + /* Upper page 02h */ + ret = eeprom_read(client, SFF_8436_PAGE_PROV_ADDR, &val, sizeof(val)); + if (ret < 0) { + ERROR_MSG("Can't read EEPROM offset %d.\n", + SFF_8436_PAGE_PROV_ADDR); + goto error; + } + if (val & SFF_8436_PAGE_02_PRESENT) { + DEBUG_PRINT("Offset:%d Value:(0x%02x & 0x%02x)", + SFF_8436_PAGE_PROV_ADDR, val, + SFF_8436_PAGE_02_PRESENT); + refresh_page = 1; + } + break; + case 4: + /* Upper page 03h */ + ret = eeprom_read(client, SFF_8436_STATUS_ADDR, &val, sizeof(val)); + if (ret < 0) { + ERROR_MSG("Can't read EEPROM offset %d.\n", + SFF_8436_STATUS_ADDR); + goto error; + } + if (!(val & SFF_8436_STATUS_PAGE_03_PRESENT_L)) { + DEBUG_PRINT("Offset:%d Value:(0x%02x & 0x%02x)", + SFF_8436_STATUS_ADDR, val, + SFF_8436_STATUS_PAGE_03_PRESENT_L); + refresh_page = 1; + } + break; + default: + DEBUG_PRINT("Invalid Page %d\n", page); + ret = retval; + goto error; + break; + } + + if (!refresh_page) { + /* if page is not valid or already refreshed */ + continue; + } + + /* + * Compute the offset and number of bytes to be read/write + * w.r.t requested page + * + * 1. start at offset 0 (within the page), and read/write the entire page + * 2. start at offset 0 (within the page) and read/write less than entire page + * 3. start at an offset not equal to 0 and read/write the rest of the page + * 4. start at an offset not equal to 0 and read/write less than (end of page - offset) + * + */ + page_start_offset = page * EEPROM_PAGE_SIZE; + + if (page_start_offset < off) { + page_offset = off; + if (off + pending_len < page_start_offset + EEPROM_PAGE_SIZE) { + page_len = pending_len; + } else { + page_len = EEPROM_PAGE_SIZE - off; + } + } else { + page_offset = page_start_offset; + if (pending_len > EEPROM_PAGE_SIZE) { + page_len = EEPROM_PAGE_SIZE; + } else { + page_len = pending_len; + } + } + + pending_len = pending_len - page_len; + + /* Change current EEPROM page */ + phy_offset = page_offset; + phy_page = sff_8436_translate_offset(&phy_offset); + if (phy_page > 0) { + ret = eeprom_write(client, SFF_8436_PAGE_SELECT_ADDR, + &phy_page, sizeof(phy_page)); + if (ret < 0) { + ERROR_MSG("Can't write EEPROM offset %d.\n", + SFF_8436_PAGE_SELECT_ADDR); + goto error; + } + } + + /* + * If page_len > 32, I2C client continue read or write EEPROM. + */ + while (page_len) { + if (op == EEPROM_READ) { + ret = eeprom_read(client, phy_offset, data, page_len); + } else if (op == EEPROM_WRITE) { + ret = eeprom_write(client, phy_offset, data, page_len); + } else { + ERROR_MSG("Bad EEPROM operation %d.\n", op); + break; + } + + if (ret <= 0) { + if (retval == 0) { + retval = ret; + } + break; + } + phy_offset += ret; + off += ret; + data += ret; + page_len -= ret; + retval += ret; + } + + /* Restore EEPROM page to default */ + if (phy_page > 0) { + phy_page = EEPROM_DEFAULT_PAGE; + ret = eeprom_write(client, SFF_8436_PAGE_SELECT_ADDR, + &phy_page, sizeof(phy_page)); + if (ret < 0) { + ERROR_MSG("Can't write EEPROM offset %d.\n", + SFF_8436_PAGE_SELECT_ADDR); + goto error; + } + } + } + + return retval; + +error: + return ret; +} + + +static inline ssize_t +sfp_eeprom_read(struct i2c_client *client, + loff_t off, u8 *data, + int data_len) +{ + return sfp_eeprom_read_write(client, EEPROM_READ, + off, data, data_len); +} + + +static inline ssize_t +sfp_eeprom_write(struct i2c_client *client, + loff_t off, const char *data, + int data_len) +{ + return sfp_eeprom_read_write(client, EEPROM_WRITE, + off, data, data_len); +} + +static struct i2c_client * +cpld_sfp_port_client(int port, + int *data_reg) +{ + *data_reg = s8900_64xc_sfp_platform_data[port].cpld_reg; + if (port >= sfp1 && port <= sfp24) { + return s8900_64xc_cpld_platform_data[cpld_1].client; + } else if (port >= sfp25 && port <= sfp48) { + return s8900_64xc_cpld_platform_data[cpld_2].client; + } else if (port >= qsfp49 && port <= qsfp64) { + return s8900_64xc_cpld_platform_data[cpld_3].client; + } else { + ERROR_MSG("Unknown port: %d", port); + return NULL; + } +} + +static ssize_t +sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, + size_t count, int port) +{ + ssize_t retval = 0; + int data_reg = 0; + struct i2c_client *cpld_client = NULL; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + //CPLD MUX select + cpld_client = cpld_sfp_port_client(port, &data_reg); + DEBUG_PRINT("data_reg=%d, port=%d", data_reg, port); + if (!cpld_client) { + ERROR_MSG("Error i2c client for port %d", port); + return 0; + } + i2c_smbus_write_byte_data(cpld_client, CPLD_MUX_REG ,data_reg); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + //CPLD MUX deselect + i2c_smbus_write_byte_data(cpld_client, CPLD_MUX_REG ,0x0); + + mutex_unlock(&data->update_lock); + return retval; +} + +static ssize_t +sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + struct platform_device_id *dev_id = NULL; + + dev_id = (struct platform_device_id *)attr->private; + + DEBUG_PRINT("offset = (%lld), count = (%ld) dev_port=%d", off, count, (int)dev_id->driver_data); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + return sfp_port_read(data, buf, off, count, (int)dev_id->driver_data); +} + +static ssize_t +sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, + size_t count, int port) +{ + ssize_t retval = 0; + int data_reg = 0; + struct i2c_client *cpld_client = NULL; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + //CPLD MUX select + cpld_client = cpld_sfp_port_client(port, &data_reg); + DEBUG_PRINT("data_reg=%d, port=%d", data_reg, port); + if (!cpld_client) { + ERROR_MSG("Error i2c client for port %d", port); + } + i2c_smbus_write_byte_data(cpld_client, CPLD_MUX_REG ,data_reg); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + //CPLD MUX deselect + i2c_smbus_write_byte_data(cpld_client, CPLD_MUX_REG ,0x0); + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t +sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + struct platform_device_id *dev_id = NULL; + + dev_id = (struct platform_device_id *)attr->private; + + DEBUG_PRINT("offset = (%lld), count = (%ld) dev_port=%d", + off, count, (int)dev_id->driver_data); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + return sfp_port_write(data, buf, off, count, (int)dev_id->driver_data); +} + +static int +sfp_sysfs_eeprom_init(struct kobject *kobj, + struct bin_attribute *eeprom, + const struct platform_device_id *dev_id) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = dev_id->name; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->private = (void *)dev_id; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + DEBUG_PRINT("err=%d", err); + return err; + } + + return 0; +} + +static int +sfp_sysfs_eeprom_cleanup(struct kobject *kobj, + struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + + return 0; +} + +static int +sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int +qsfp_probe(struct i2c_client *client, + const struct platform_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + DEBUG_PRINT("No memory."); + goto exit; + } + + /* Register sysfs hooks */ //TBD: must remove + /* status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } */ + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin, dev_id); + if (status) { + DEBUG_PRINT("sfp_sysfs_eeprom_init error"); + goto exit_free; + } + + //TBD: Must remove + /*if (s9130_32x_kobj) { + status = sysfs_create_link(s9130_32x_kobj, &client->dev.kobj, client->name); + if (status) { + goto exit_remove; + } + }*/ + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_free: + kfree(qsfp); +exit: + + return status; +} + +static int +qsfp_device_probe(struct platform_device *pdev) +{ + struct sfp_platform_data *pdata; + struct sfp_port_data *data[TOTAL_PORT_NUM]; + struct i2c_adapter *parent[SFP_EEPROM_DEV_NUM]; + struct i2c_client *sfp_client[SFP_EEPROM_DEV_NUM]; + int i; + int ret=0; + + DEBUG_PRINT("Start"); + + pdata = pdev->dev.platform_data; + if (!pdata) { + ERROR_MSG("Missing platform data\n"); + return -ENODEV; + } + + //New eeprom device + for (i=0; i < SFP_EEPROM_DEV_NUM; i++) { + parent[i] = i2c_get_adapter(i+S8900_64XC_SFP_EEPROM_BASE_NR); + if (!parent[i]) { + ERROR_MSG("Parent adapter (%d) not found\n", i+S8900_64XC_SFP_EEPROM_BASE_NR); + ret=-ENODEV; + goto error; + } + sfp_client[i] = i2c_new_dummy(parent[i], SFP_EEPROM_A0_I2C_ADDR); + if (!sfp_client[i]) { + ERROR_MSG("[%d]: Fail to create dummy i2c client for parent %d addr 0x%x\n", i, i+S8900_64XC_SFP_EEPROM_BASE_NR, SFP_EEPROM_A0_I2C_ADDR); + ret=-ENODEV; + goto error; + } + } + + //Assign client to dummy device + for (i = 0; i < TOTAL_PORT_NUM; i++) { + switch (pdata[i].parent) { + case 2: + pdata[i].client = sfp_client[0]; + break; + case 3: + pdata[i].client = sfp_client[1]; + break; + case 4: + pdata[i].client = sfp_client[2]; + break; + default: + ERROR_MSG("Error parent number: %d, ", i); + break; + } + + if (!pdata[i].client) { + ERROR_MSG("[%d]: Fail to create dummy i2c client for parent %d addr 0x%x\n", i, pdata[i].parent, pdata[i].reg_addr); + ret=-ENODEV; + goto error; + } + } + + + for (i = 0; i < TOTAL_PORT_NUM; i++) { + data[i] = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data[i]) { + ret=-ENOMEM; + ERROR_MSG("No memory"); + goto error; + } + + i2c_set_clientdata(pdata[i].client, data[i]); + mutex_init(&data[i]->update_lock); + data[i]->port = qsfp_device_id[i].driver_data; + data[i]->client = pdata[i].client; + + DEBUG_PRINT("data[%d]->port=%d", i, data[i]->port); + + if (pdata[i].client->addr != SFP_EEPROM_A0_I2C_ADDR) { + ret=-ENODEV; + ERROR_MSG("Not approve device address"); + goto error; + } + + data[i]->driver_type = DRIVER_TYPE_QSFP; + + ret |= qsfp_probe(pdata[i].client, &qsfp_device_id[i], &data[i]->qsfp); + } + + if (ret) { + ERROR_MSG("qsfp_probe failed someone."); + //goto error; + } + return 0; +error: + DEBUG_PRINT("error start"); + i2c_put_adapter(parent[i]); + i--; + for (; i >= 0; i--) { + if (pdata[i].client) { + i2c_unregister_device(pdata[i].client); + i2c_put_adapter(parent[i]); + } + } + + return ret; +} + +static int +qsfp_remove(struct i2c_client *client, + struct qsfp_data *data) +{ + //TBD: Must remove + /*if (s9130_32x_kobj) { + sysfs_remove_link(s9130_32x_kobj, client->name); + }*/ + + //TBD: Must remove all ports EEPROM BIN + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + //TBD: Must remove sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + + return 0; +} + +static int __exit +qsfp_device_remove(struct platform_device *pdev) +{ + struct sfp_port_data *data = NULL; + struct sfp_platform_data *pdata = pdev->dev.platform_data; + struct i2c_adapter *parent = NULL; + int i; + + + + if (!pdata) { + ERROR_MSG("Missing platform data\n"); + return -ENOENT; + } + + for (i = 0; i < TOTAL_PORT_NUM; i+=CPLD_MUX_OFFSET) { + data = i2c_get_clientdata(pdata[i].client); + if (!data) { + ERROR_MSG("Empty data. skip. i=%d", i); + continue; + } + qsfp_remove(pdata[i].client, data->qsfp); + if (pdata[i].client) { + parent = (pdata[i].client)->adapter; + i2c_unregister_device(pdata[i].client); + i2c_put_adapter(parent); + } + kfree(data); + } + + + return 0; +} + +static int +cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent[CPLD_DEVICE_NUM]; + int i; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + ERROR_MSG("Missing platform data\n"); + return -ENODEV; + } + + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + parent[i] = i2c_get_adapter(S8900_64XC_MUX_BASE_NR + i + 1); + if (!parent[i]) { + ERROR_MSG("Parent adapter (%d) not found\n", + S8900_64XC_MUX_BASE_NR + i + 1); + return -ENODEV; + } + pdata[i].client = i2c_new_dummy(parent[i], pdata[i].reg_addr); + if (!pdata[i].client) { + ERROR_MSG("Fail to create dummy i2c client for addr %d\n", pdata[i].reg_addr); + goto error; + } + } + + ret = sysfs_create_group(&pdev->dev.kobj, &s8900_64xc_cpld_attr_grp); + if (ret) + goto error; + + return 0; + +error: + if (i < CPLD_DEVICE_NUM) { + i2c_put_adapter(parent[i]); + } + i--; + for (; i >= 0; i--) { + if (pdata[i].client) { + i2c_unregister_device(pdata[i].client); + i2c_put_adapter(parent[i]); + } + } + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + int i; + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + + sysfs_remove_group(&pdev->dev.kobj, &s8900_64xc_cpld_attr_grp); + + if (!pdata) { + ERROR_MSG("Missing platform data\n"); + } else { + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + if (pdata[i].client) { + parent = (pdata[i].client)->adapter; + i2c_unregister_device(pdata[i].client); + i2c_put_adapter(parent); + } + } + } + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "ingrasys-s8900-64xc-cpld", + }, +}; + +static struct platform_driver qsfp_driver = { + .probe = qsfp_device_probe, + .remove = __exit_p(qsfp_device_remove), + //.id_table = qsfp_device_id, + .driver = { + .owner = THIS_MODULE, + .name = "ingrasys-s8900-64xc-sfp", + }, +}; + + +static int __init ingrasys_s8900_64xc_platform_init(void) +{ + int ret = 0; + + DEBUG_PRINT("ingrasysl_s8900_64xc_platform module initialization\n"); + + //mdelay(10000); + + ret = platform_driver_register(&cpld_driver); + if (ret) { + ERROR_MSG("Fail to register cpld driver\n"); + goto error_cpld_driver; + } + ret = platform_device_register(&s8900_64xc_cpld); + if (ret) { + ERROR_MSG("Fail to create cpld device\n"); + goto error_cpld; + } + + ret = platform_driver_register(&qsfp_driver); + if (ret) { + ERROR_MSG("Fail to register sfp driver\n"); + goto error_cpld_driver; + } + + ret = platform_device_register(&s8900_64xc_sfp); + if (ret) { + ERROR_MSG("Fail to create sfp device\n"); + goto error_cpld; + } + + return 0; + +error_cpld: + platform_driver_unregister(&cpld_driver); + platform_driver_unregister(&qsfp_driver); +error_cpld_driver: + return ret; +} + +static void __exit ingrasys_s8900_64xc_platform_exit(void) +{ + platform_device_unregister(&s8900_64xc_sfp); + platform_device_unregister(&s8900_64xc_cpld); + platform_driver_unregister(&qsfp_driver); + platform_driver_unregister(&cpld_driver); +} + +module_init(ingrasys_s8900_64xc_platform_init); +module_exit(ingrasys_s8900_64xc_platform_exit); + +MODULE_DESCRIPTION("Ingrasys S8900-64XC Platform Support"); +MODULE_AUTHOR("Wade He "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/service/qsfp-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/service/qsfp-monitor.service new file mode 100644 index 000000000000..99c91b98ab52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s8900-64xc-monitor.service +After=s8900-64xc-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/service/s8900-64xc-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/service/s8900-64xc-monitor.service new file mode 100644 index 000000000000..decb0f943a9d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/service/s8900-64xc-monitor.service @@ -0,0 +1,18 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s8900_64xc_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/i2c_utils.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/i2c_utils.sh new file mode 100644 index 000000000000..e1df54ad0fe2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/i2c_utils.sh @@ -0,0 +1,1163 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, 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 . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_IGB_DEVICE=0 +NUM_I801_DEVICE=0 +NUM_ISMT_DEVICE=$(( ${NUM_I801_DEVICE} + 1 )) +NUM_MUX1_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 2 )) +NUM_MUX1_CHAN1_DEVICE=$(( ${NUM_I801_DEVICE} + 3 )) +NUM_MUX1_CHAN2_DEVICE=$(( ${NUM_I801_DEVICE} + 4 )) +NUM_MUX1_CHAN3_DEVICE=$(( ${NUM_I801_DEVICE} + 5 )) +NUM_MUX1_CHAN4_DEVICE=$(( ${NUM_I801_DEVICE} + 6 )) +NUM_MUX1_CHAN5_DEVICE=$(( ${NUM_I801_DEVICE} + 7 )) +NUM_MUX1_CHAN6_DEVICE=$(( ${NUM_I801_DEVICE} + 8 )) +NUM_MUX1_CHAN7_DEVICE=$(( ${NUM_I801_DEVICE} + 9 )) + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon1" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_ISMT_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_ISMT_DEVICE}" +PATH_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" +PATH_MUX_CHAN1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN1_DEVICE}" +PATH_MUX_CHAN2_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN2_DEVICE}" +PATH_MUX_CHAN3_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN3_DEVICE}" +PATH_MUX_CHAN4_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN4_DEVICE}" +PATH_MUX_CHAN5_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN5_DEVICE}" +PATH_MUX_CHAN6_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN6_DEVICE}" +PATH_MUX_CHAN7_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}" + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_temp_init" + echo " : ${0} i2c_fan_init" + echo " : ${0} i2c_volmon_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [1-64]" + echo " : ${0} i2c_qsfp_status_get [1-64]" + echo " : ${0} i2c_qsfp_type_get [1-64]" + echo " : ${0} i2c_qsfp_abs_get [1-64]" + echo " : ${0} i2c_qsfp_rst_get [49-64]" + echo " : ${0} i2c_qsfp_lpmode_get [49-64]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_front_temp" + echo " : ${0} i2c_rear_temp" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber on|off" + echo " : ${0} i2c_fan_led green|amber on|off" + echo " : ${0} i2c_psu1_led green|amber on|off" + echo " : ${0} i2c_psu2_led green|amber on|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-5]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + rmmod i2c_ismt + rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_ismt + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x72' > ${PATH_ISMT_DEVICE}/new_device" + else + echo "pca9548 0x72 already init." + fi + #Init CPLD LED_CLR Register (Front Port LED) + i2cset -y ${NUM_I801_DEVICE} 0x33 0x34 0x10 + + rmmod coretemp + rmmod jc42 + rmmod w83795 + rmmod lm75 + _i2c_temp_init + _i2c_volmon_init + _i2c_hwmon_init + modprobe coretemp + modprobe w83795 + modprobe lm75 + modprobe jc42 + modprobe sff_8436_eeprom + modprobe eeprom + modprobe eeprom_mb + modprobe qsfp_cpld + _i2c_fan_init + _i2c_io_exp_init + _i2c_cpld_init + _i2c_psu_eeprom_init + _i2c_led_psu_status_set + _i2c_led_fan_status_set + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + + echo "tmp75 0x48" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN3_DEVICE}/new_device + echo "tmp75 0x49" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN3_DEVICE}/new_device + echo "Mount Main Board EEPROM" + echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-7/new_device + + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + for mod in coretemp jc42 w83795 lm75 eeprom_mb i2c_mux_pca954x i2c_ismt i2c_i801; + do + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod + done +} + +#Temperature sensor Init +function _i2c_temp_init { + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x05 0xFF + echo "TEMP INIT Done" +} + +#FAN Init +function _i2c_fan_init { + echo -n "FAN INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi + +} + +#VOLMON Init +function _i2c_volmon_init { + echo -n "VOLMON INIT..." + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x02 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x03 0x50 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x04 0x0A + echo "Done" +} + +#HWMON Init +function _i2c_hwmon_init { + echo -n "HWMON INIT..." + i2cset -y ${NUM_I801_DEVICE} 0x2f 0x00 0x80 + i2cset -y ${NUM_I801_DEVICE} 0x2f 0x06 0xFF + i2cset -y ${NUM_I801_DEVICE} 0x2f 0x07 0x03 + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + #SMBUS0 IO_EXPENDER + i2cset -y -r ${NUM_I801_DEVICE} 0x27 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 2 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 3 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 6 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x27 7 0xFF + + #LED board after PVT (S8900_IO_EXP_LED_ID) + echo "Init LED IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 7 0xFF + + #PSU I/O (S8900_IO_EXP_PSU_ID) + echo "Init PSU IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 2 0x44 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 6 0xBB + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 7 0xFF + + #FAN I/O (S8900_IO_EXP_FAN_ID) + echo "Init FAN1 IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x20 2 0x11 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x20 3 0x11 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x20 6 0xCC + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x20 7 0xCC + + #FAN I/O (S8900_IO_EXP_FAN_ID) + echo "Init FAN2 IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x21 2 0x10 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x21 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x21 6 0xCC + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x21 7 0xFF +} + +#I2C CPLD init +function _i2c_cpld_init { + echo "=========================================================" + echo "# Description: I2C CPLD Init..." + echo "=========================================================" + + ## modprobe i2c_cpld + modprobe i2c_cpld + ## Add CPLD device + echo "i2c_cpld 0x33" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}/new_device + + echo "done..." +} +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + FAN9_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan9_alarm` + FAN10_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan10_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ]; then + FAN_TRAY=1 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=1 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + if [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ]; then + FAN_TRAY=2 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=2 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + if [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ]; then + FAN_TRAY=3 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=3 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + if [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + FAN_TRAY=4 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=4 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + if [ "${FAN9_ALARM}" == "0" ] && [ "${FAN10_ALARM}" == "0" ]; then + FAN_TRAY=5 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=5 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + FAN9_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan9_alarm` + FAN10_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan10_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ] \ + && [ "${FAN9_ALARM}" == "0" ] && [ "${FAN10_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + fi +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C LED TEST..." + echo "=========================================================" + #sys led (green) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xBF + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x7F + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xEF + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xDF + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFB + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xF7 + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFE + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFD + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + _pause 'Check turn off all LEDs and Press [Enter] key to continue...' + echo "done..." +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + local port=$1 + case ${port} in + 1|2|3|4|5|6|7|8) + i2cbus=${NUM_MUX1_CHAN0_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 1) / 2) )) + dataAddr=$(( (32 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN0_DEVICE} + eepromidx=${port} + eepromAddr=0x50 + ;; + 9|10|11|12|13|14|15|16) + i2cbus=${NUM_MUX1_CHAN0_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 1) / 2) )) + dataAddr=$(( (32 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN0_DEVICE} + eepromidx=${port} + eepromAddr=0x50 + ;; + 17|18|19|20) + i2cbus=${NUM_MUX1_CHAN0_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 1) / 2) )) + dataAddr=$(( (32 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN0_DEVICE} + eepromidx=${port} + eepromAddr=0x50 + ;; + 21|22|23|24) + i2cbus=${NUM_MUX1_CHAN0_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 1) / 2) )) + dataAddr=$(( (38 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN0_DEVICE} + eepromidx=${port} + eepromAddr=0x50 + ;; + 25|26|27|28|29|30|31|32) + i2cbus=${NUM_MUX1_CHAN1_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 25) / 2) )) + dataAddr=$(( (32 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN1_DEVICE} + eepromidx=$(( (${port} - 24) )) + eepromAddr=0x50 + ;; + 33|34|35|36|37|38|39|40) + i2cbus=${NUM_MUX1_CHAN1_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 25) / 2) )) + dataAddr=$(( (32 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN1_DEVICE} + eepromidx=$(( (${port} - 24) )) + eepromAddr=0x50 + ;; + 41|42|43|44) + i2cbus=${NUM_MUX1_CHAN1_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 25) / 2) )) + dataAddr=$(( (32 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN1_DEVICE} + eepromidx=$(( (${port} - 24) )) + eepromAddr=0x50 + ;; + 45|46|47|48) + i2cbus=${NUM_MUX1_CHAN1_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 25) / 2) )) + dataAddr=$(( (38 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN1_DEVICE} + eepromidx=$(( (${port} - 24) )) + eepromAddr=0x50 + ;; + 49|50|51|52|53|54|55|56) + i2cbus=${NUM_MUX1_CHAN2_DEVICE} + regAddr=0x33 + idx=$(( (${port} - 49) )) + dataAddr=$(( (32 + $idx) )) + rstsellpdataAddr=$(( (48 + $idx) )) + intChan=0x0 + rstChan=0x0 + presentChan=0x1 + modselChan=0x1 + lpmodeChan=0x2 + eeprombus=${NUM_MUX1_CHAN2_DEVICE} + eepromidx=$(( (${port} - 48) )) + intabsidx=$(( (${port} - 28) )) + rstsellpidx=$(( (${port} - 18) )) + eepromAddr=0x50 + ;; + 57|58|59|60|61|62|63|64) + i2cbus=${NUM_MUX1_CHAN2_DEVICE} + regAddr=0x33 + idx=$(( (${port} - 49) )) + dataAddr=$(( (32 + $idx) )) + rstsellpdataAddr=$(( (48 + $idx) )) + intChan=0x0 + rstChan=0x0 + presentChan=0x1 + modselChan=0x1 + lpmodeChan=0x2 + eeprombus=${NUM_MUX1_CHAN2_DEVICE} + eepromidx=$(( (${port} - 48) )) + intabsidx=$(( (${port} - 28) )) + rstsellpidx=$(( (${port} - 18) )) + eepromAddr=0x50 + ;; + *) + echo "Please input 1~64" + exit + ;; + esac +} + +#Get SFP/QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + _qsfp_port_i2c_var_set ${QSFP_PORT} + + regData=`cat /sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_modprs` + port_num=$(( ${QSFP_PORT} - 1 )) + + #status: 0 -> Down, 1 -> Up + status=$(( $(($regData & ( 1 << $port_num))) != 0 ? 0 : 1 )) + + + if [ $status = 0 ]; then + echo "Module not present." + exit + fi + + #Read SFP/QSFP EEPROM + if [ ${QSFP_PORT} -lt 49 ]; then + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/sfp${QSFP_PORT} | hexdump -C + elif [ ${QSFP_PORT} -ge 49 ]; then + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/qsfp${QSFP_PORT} | hexdump -C + fi +} + +#Get QSFP Status for QSFP monitor service +function _i2c_qsfp_status_get { + _i2c_qsfp_abs_get + echo "status=$status" +} + +#Get QSFP type for QSFP monitor server +function _i2c_qsfp_type_get { + _qsfp_port_i2c_var_set ${QSFP_PORT} + + regData=`cat /sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_modprs` + port_num=$(( ${QSFP_PORT} - 1 )) + + #status: 0 -> Down, 1 -> Up + status=$(( $(($regData & ( 1 << $port_num))) != 0 ? 0 : 1 )) + + if [ $status = 0 ]; then + echo "Module not present." + exit + fi + + #Read SFP/QSFP EEPROM + if [ ${QSFP_PORT} -lt 49 ]; then + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/sfp${QSFP_PORT}) + elif [ ${QSFP_PORT} -ge 49 ]; then + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/qsfp${QSFP_PORT}) + fi + + if [ ${QSFP_PORT} -ge 1 ] && [ ${QSFP_PORT} -le 48 ]; then + echo "sfp" + # 1~48 port is sfp port + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 0 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 2 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 3 -n 1 -e '"%x"') + else + echo "qsfp" + # 49~64 port is qsfp port + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + fi + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Get QSFP ABS +function _i2c_qsfp_abs_get { + _qsfp_port_i2c_var_set ${QSFP_PORT} + + regData=`cat /sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_modprs` + port_num=$(( ${QSFP_PORT} - 1 )) + + #status: 0 -> Down, 1 -> Up + status=$(( $(($regData & ( 1 << $port_num))) != 0 ? 0 : 1 )) + echo "ABS=$status regData=$regData" + + +} + +#Get QSFP RST +function _i2c_qsfp_rst_get { + + if [ ${QSFP_PORT} -lt 49 ] || [ ${QSFP_PORT} -gt 64 ]; then + echo "Please input 49~64" + exit + fi + _qsfp_port_i2c_var_set ${QSFP_PORT} + + + regData=`cat /sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_reset` + port_num=$(( ${QSFP_PORT} - 49 )) + + #status: 0 -> Down, 1 -> Up + status=$(( $(($regData & ( 1 << $port_num))) != 0 ? 0 : 1 )) + echo "RST=$status regData=$regData" + +} + +#Get QSFP LPMODE +function _i2c_qsfp_lpmode_get { + + if [ ${QSFP_PORT} -lt 49 ] || [ ${QSFP_PORT} -gt 64 ]; then + echo "Please input 49~64" + exit + fi + _qsfp_port_i2c_var_set ${QSFP_PORT} + + + regData=`cat /sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_lpmode` + port_num=$(( ${QSFP_PORT} - 49 )) + + #status: 0 -> Down, 1 -> Up + status=$(( $(($regData & ( 1 << $port_num))) != 0 ? 1 : 0 )) + echo "LPMODE=$status regData=$regData" + +} +#PSU EEPROM init +function _i2c_psu_eeprom_init { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Init..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom + ## PUS(0) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN6_DEVICE}/new_device + + ## PUS(1) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}/new_device + + echo "done..." +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom + ## PUS(0) EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN6_DEVICE}-0050/eeprom | hexdump -C + + ## PUS(1) EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN7_DEVICE}-0050/eeprom | hexdump -C + echo "done..." +} + +#Get MotherBoard EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom_mb + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN5_DEVICE}-0054/eeprom | hexdump -C + echo "done..." +} + +#Set System Status LED +function _i2c_sys_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x40 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x40 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x80 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x80 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU2 LED +function _i2c_psu2_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x04 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x04 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x08 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x08 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + + case ${FAN_TRAY} in + 1) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 5) + i2cAddr=0x21 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~5" + exit + ;; + esac + + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN3_DEVICE} $i2cAddr $ioPort 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN3_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN3_DEVICE} $i2cAddr $ioPort 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN3_DEVICE} $i2cAddr $ioPort 0x33 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x10 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x10 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x20 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x20 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU1 LED +function _i2c_psu1_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x01 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x01 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x02 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x02 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Get Board Version and Type +function _i2c_board_type_get { + boardType=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_board_type` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BOARD_ID is 0x%02x, HW Rev %d, Build Rev %d\n" $boardId $boardHwRev $boardBuildRev + +} + +#Get CPLD Version +function _i2c_cpld_version { + cpldRev=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_version` + cpldRelease=$((($cpldRev) >> 6 & 0x01)) + cpldVersion=$((($cpldRev) & 0x3F)) + printf "CPLD is %s version(0:RD 1:Release), Revision is 0x%02x\n" $cpldRelease $cpldVersion + +} + +#Get PSU Status +function _i2c_psu_status { + psuPresent=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_pw_abs` + psu1Exist=$(($((($psuPresent) & 0x01))?0:1)) + psu2Exist=$(($((($psuPresent) & 0x02))?0:1)) + psuPwGood=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_pw_good` + psu1PwGood=$(($((($psuPwGood) >> 2 & 0x01))?1:0)) + psu2PwGood=$(($((($psuPwGood) >> 2 & 0x02))?1:0)) + printf "PSU1 Exist:%d PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Get Front Sensor Temperature +function _i2c_front_temp { + #Front MAC + sensors | grep 'Front MAC Temp' -A 1 +} + +#Get Rear Sensor Temperature +function _i2c_rear_temp { + #Rear MAC + sensors | grep 'Rear MAC Temp' -A 1 +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Main Function +function _main { + tart_time_str=`date` + start_time_sec=$(date +%s) + + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_fan_init" ]; then + _i2c_fan_init + elif [ "${EXEC_FUNC}" == "i2c_volmon_init" ]; then + _i2c_volmon_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_abs_get" ]; then + _i2c_qsfp_abs_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_rst_get" ]; then + _i2c_qsfp_rst_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_lpmode_get" ]; then + _i2c_qsfp_lpmode_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_front_temp" ]; then + _i2c_front_temp + elif [ "${EXEC_FUNC}" == "i2c_rear_temp" ]; then + _i2c_rear_temp + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_temp_init + _i2c_fan_init + _i2c_io_exp_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_board_type_get + _i2c_cpld_version + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_monitor.sh new file mode 100644 index 000000000000..36f9e53ef108 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_monitor.sh @@ -0,0 +1,106 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, 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 . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..63}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + # identifier 11 for qsfp, 3 for sfp + if [ "${identifier}" == "11" ] || [ "${identifier}" == "3" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #AOC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to AOC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} aoc $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_si_cfg.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_si_cfg.sh new file mode 100644 index 000000000000..3d132641f516 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_si_cfg.sh @@ -0,0 +1,409 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, 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 . + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +TYPE=${1} +PORT=${2} + +# port number +MIN_PORT=0 +MAX_PORT=63 + +# INDEX of value field in array +SI_PRE_IDX=1 +SI_POST_IDX=2 +SI_MAIN_IDX=3 +SI_AMP_IDX=4 +SI_DRI_IDX=5 + +# type string +AOC_TYPE="aoc" +DAC_TYPE="dac" + +# si value for bcm command +SI_VAL="" + +# "PRE POST MAIN AMP DRIVERMODE" for each port in array +xe_aoc_si_value=( + "0x00 0x30 0x40 0x9 0x0" #port 0 + "0x00 0x30 0x40 0x9 0x0" #port 1 + "0x00 0x30 0x40 0x9 0x0" #port 2 + "0x00 0x2c 0x44 0x9 0x0" #port 3 + "0x00 0x30 0x40 0x9 0x0" #port 4 + "0x00 0x30 0x40 0x9 0x0" #port 5 + "0x00 0x2c 0x44 0x9 0x0" #port 6 + "0x00 0x2c 0x44 0x9 0x0" #port 7 + "0x00 0x2c 0x44 0x9 0x0" #port 8 + "0x00 0x28 0x48 0x9 0x0" #port 9 + "0x00 0x2c 0x44 0x9 0x0" #port 10 + "0x00 0x2c 0x44 0x9 0x0" #port 11 + "0x00 0x2c 0x44 0x9 0x0" #port 12 + "0x00 0x2c 0x44 0x9 0x0" #port 13 + "0x00 0x2c 0x44 0x9 0x0" #port 14 + "0x00 0x2c 0x44 0x9 0x0" #port 15 + "0x00 0x2c 0x44 0xb 0x0" #port 16 + "0x00 0x30 0x40 0xb 0x0" #port 17 + "0x00 0x2c 0x44 0xa 0x0" #port 18 + "0x00 0x2c 0x44 0x9 0x0" #port 19 + "0x00 0x30 0x40 0xa 0x0" #port 20 + "0x00 0x2c 0x44 0x9 0x0" #port 21 + "0x00 0x2c 0x44 0x9 0x0" #port 22 + "0x00 0x30 0x40 0xc 0x0" #port 23 + "0x00 0x30 0x40 0xc 0x0" #port 24 + "0x00 0x2c 0x44 0x9 0x0" #port 25 + "0x00 0x30 0x40 0x9 0x0" #port 26 + "0x00 0x30 0x40 0x9 0x0" #port 27 + "0x00 0x30 0x40 0xa 0x0" #port 28 + "0x00 0x28 0x48 0x9 0x0" #port 29 + "0x00 0x2c 0x44 0x9 0x0" #port 30 + "0x00 0x2c 0x44 0xa 0x0" #port 31 + "0x00 0x28 0x48 0x9 0x0" #port 32 + "0x00 0x28 0x48 0x7 0x0" #port 33 + "0x00 0x28 0x48 0x9 0x0" #port 34 + "0x00 0x28 0x48 0x9 0x0" #port 35 + "0x00 0x28 0x48 0x9 0x0" #port 36 + "0x00 0x2c 0x44 0x9 0x0" #port 37 + "0x00 0x28 0x48 0x9 0x0" #port 38 + "0x00 0x28 0x48 0x9 0x0" #port 39 + "0x00 0x28 0x48 0xa 0x0" #port 40 + "0x00 0x2c 0x44 0x9 0x0" #port 41 + "0x00 0x2c 0x44 0x9 0x0" #port 42 + "0x00 0x2e 0x42 0xa 0x0" #port 43 + "0x00 0x2e 0x42 0xa 0x0" #port 44 + "0x00 0x2c 0x44 0xa 0x0" #port 45 + "0x00 0x2c 0x44 0x9 0x0" #port 46 + "0x00 0x2c 0x44 0x9 0x0" #port 47 +) + +ce_aoc_si_value=( + "0x00 0x2c 0x44 0x9 0x0" #port 0 lane 0 + "0x00 0x34 0x3c 0xf 0x0" #port 0 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 0 lane 2 + "0x00 0x2c 0x44 0x9 0x0" #port 0 lane 3 + "0x00 0x28 0x48 0x9 0x0" #port 1 lane 0 + "0x00 0x28 0x48 0x9 0x0" #port 1 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 1 lane 2 + "0x00 0x2c 0x44 0xe 0x0" #port 1 lane 3 + "0x00 0x28 0x48 0x9 0x0" #port 2 lane 0 + "0x00 0x34 0x3c 0xf 0x0" #port 2 lane 1 + "0x00 0x28 0x48 0x9 0x0" #port 2 lane 2 + "0x00 0x30 0x40 0xd 0x0" #port 2 lane 3 + "0x00 0x2c 0x44 0x9 0x0" #port 3 lane 0 + "0x00 0x30 0x40 0xd 0x0" #port 3 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 3 lane 2 + "0x00 0x30 0x40 0xd 0x0" #port 3 lane 3 + "0x00 0x2c 0x44 0x9 0x0" #port 4 lane 0 + "0x00 0x2c 0x44 0x9 0x0" #port 4 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 4 lane 2 + "0x00 0x30 0x40 0xd 0x0" #port 4 lane 3 + "0x00 0x2c 0x44 0x9 0x0" #port 5 lane 0 + "0x00 0x38 0x38 0xf 0x0" #port 5 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 5 lane 2 + "0x00 0x2c 0x44 0x9 0x0" #port 5 lane 3 + "0x00 0x2c 0x44 0x9 0x0" #port 6 lane 0 + "0x00 0x2c 0x44 0x9 0x0" #port 6 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 6 lane 2 + "0x00 0x30 0x40 0xe 0x0" #port 6 lane 3 + "0x00 0x28 0x48 0x9 0x0" #port 7 lane 0 + "0x00 0x30 0x40 0xa 0x0" #port 7 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 7 lane 2 + "0x00 0x34 0x3c 0xe 0x0" #port 7 lane 3 + "0x00 0x2c 0x44 0x9 0x0" #port 8 lane 0 + "0x00 0x30 0x40 0xe 0x0" #port 8 lane 1 + "0x00 0x34 0x3c 0xf 0x0" #port 8 lane 2 + "0x00 0x30 0x40 0xe 0x0" #port 8 lane 3 + "0x00 0x2c 0x44 0x9 0x0" #port 9 lane 0 + "0x00 0x34 0x3c 0xd 0x0" #port 9 lane 1 + "0x00 0x34 0x3c 0xd 0x0" #port 9 lane 2 + "0x00 0x34 0x3c 0xf 0x0" #port 9 lane 3 + "0x00 0x34 0x3c 0xd 0x0" #port 10 lane 0 + "0x00 0x34 0x3c 0xe 0x0" #port 10 lane 1 + "0x00 0x34 0x3c 0xd 0x0" #port 10 lane 2 + "0x00 0x34 0x3c 0xd 0x0" #port 10 lane 3 + "0x00 0x34 0x3c 0xd 0x0" #port 11 lane 0 + "0x00 0x34 0x3c 0xd 0x0" #port 11 lane 1 + "0x00 0x30 0x40 0xd 0x0" #port 11 lane 2 + "0x00 0x30 0x40 0xd 0x0" #port 11 lane 3 + "0x00 0x34 0x3c 0xd 0x0" #port 12 lane 0 + "0x00 0x34 0x3c 0xd 0x0" #port 12 lane 1 + "0x00 0x34 0x3c 0xd 0x0" #port 12 lane 2 + "0x00 0x34 0x3c 0xd 0x0" #port 12 lane 3 + "0x00 0x34 0x3c 0xd 0x0" #port 13 lane 0 + "0x00 0x34 0x3c 0xd 0x0" #port 13 lane 1 + "0x00 0x34 0x3c 0xd 0x0" #port 13 lane 2 + "0x00 0x34 0x3c 0xf 0x0" #port 13 lane 3 + "0x00 0x38 0x38 0xe 0x0" #port 14 lane 0 + "0x00 0x34 0x3c 0xd 0x0" #port 14 lane 1 + "0x00 0x34 0x3c 0xd 0x0" #port 14 lane 2 + "0x00 0x38 0x38 0xe 0x0" #port 14 lane 3 + "0x00 0x34 0x3c 0xd 0x0" #port 15 lane 0 + "0x00 0x30 0x40 0xc 0x0" #port 15 lane 1 + "0x00 0x30 0x40 0xc 0x0" #port 15 lane 2 + "0x00 0x34 0x3c 0xd 0x0" #port 15 lane 3 +) + +xe_dac_si_value=( + "0x14 0x00 0x3c 0xf 0x0" #port 0 + "0x1c 0x00 0x3c 0xf 0x0" #port 1 + "0x08 0x00 0x3c 0xf 0x0" #port 2 + "0x08 0x00 0x3c 0xf 0x0" #port 3 + "0x08 0x00 0x3c 0xf 0x0" #port 4 + "0x10 0x00 0x3c 0xf 0x0" #port 5 + "0x08 0x08 0x3c 0xf 0x0" #port 6 + "0x10 0x04 0x3c 0xf 0x0" #port 7 + "0x08 0x00 0x3c 0x9 0x0" #port 8 + "0x08 0x00 0x3c 0x9 0x0" #port 9 + "0x08 0x00 0x3c 0x9 0x0" #port 10 + "0x08 0x00 0x3c 0x9 0x0" #port 11 + "0x08 0x00 0x3c 0x9 0x0" #port 12 + "0x08 0x00 0x3c 0x9 0x0" #port 13 + "0x08 0x00 0x3c 0x9 0x0" #port 14 + "0x08 0x00 0x3c 0x9 0x0" #port 15 + "0x08 0x0c 0x3c 0xb 0x0" #port 16 + "0x10 0x0c 0x3c 0xb 0x0" #port 17 + "0x08 0x08 0x3c 0xa 0x0" #port 18 + "0x10 0x0c 0x3c 0x9 0x0" #port 19 + "0x08 0x04 0x3c 0xc 0x0" #port 20 + "0x08 0x08 0x3c 0x9 0x0" #port 21 + "0x08 0x08 0x3c 0xc 0x0" #port 22 + "0x10 0x08 0x3c 0xa 0x0" #port 23 + "0x08 0x08 0x3c 0x9 0x0" #port 24 + "0x08 0x04 0x3c 0x9 0x0" #port 25 + "0x08 0x00 0x3c 0x9 0x0" #port 26 + "0x08 0x08 0x3c 0xc 0x0" #port 27 + "0x10 0x00 0x3c 0xa 0x0" #port 28 + "0x10 0x04 0x3c 0x9 0x0" #port 29 + "0x14 0x00 0x3c 0x9 0x0" #port 30 + "0x14 0x00 0x3c 0xa 0x0" #port 31 + "0x08 0x00 0x3c 0x9 0x0" #port 32 + "0x08 0x00 0x3c 0x7 0x0" #port 33 + "0x08 0x00 0x3c 0x9 0x0" #port 34 + "0x08 0x00 0x3c 0x9 0x0" #port 35 + "0x08 0x00 0x3c 0x9 0x0" #port 36 + "0x0c 0x00 0x3c 0x9 0x0" #port 37 + "0x08 0x00 0x3c 0x9 0x0" #port 38 + "0x08 0x00 0x3c 0x9 0x0" #port 39 + "0x10 0x00 0x3c 0xa 0x0" #port 40 + "0x10 0x00 0x3c 0x9 0x0" #port 41 + "0x08 0x08 0x3c 0xc 0x0" #port 42 + "0x10 0x00 0x3c 0xa 0x0" #port 43 + "0x08 0x00 0x3c 0xa 0x0" #port 44 + "0x10 0x00 0x3c 0x9 0x0" #port 45 + "0x08 0x04 0x3c 0x9 0x0" #port 46 + "0x08 0x00 0x3c 0xa 0x0" #port 47 +) + +ce_dac_si_value=( + "0x08 0x00 0x3c 0x9 0x0" #port 0 lane 0 + "0x08 0x00 0x3c 0xf 0x0" #port 0 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 0 lane 2 + "0x08 0x00 0x3c 0x9 0x0" #port 0 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 1 lane 0 + "0x08 0x00 0x3c 0x9 0x0" #port 1 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 1 lane 2 + "0x08 0x00 0x3c 0xe 0x0" #port 1 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 2 lane 0 + "0x08 0x00 0x3c 0xf 0x0" #port 2 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 2 lane 2 + "0x08 0x00 0x3c 0xd 0x0" #port 2 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 3 lane 0 + "0x08 0x00 0x3c 0xd 0x0" #port 3 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 3 lane 2 + "0x08 0x00 0x3c 0xd 0x0" #port 3 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 4 lane 0 + "0x08 0x00 0x3c 0x9 0x0" #port 4 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 4 lane 2 + "0x08 0x00 0x3c 0xd 0x0" #port 4 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 5 lane 0 + "0x08 0x00 0x3c 0xf 0x0" #port 5 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 5 lane 2 + "0x08 0x00 0x3c 0x9 0x0" #port 5 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 6 lane 0 + "0x08 0x00 0x3c 0x9 0x0" #port 6 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 6 lane 2 + "0x08 0x00 0x3c 0xe 0x0" #port 6 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 7 lane 0 + "0x08 0x00 0x3c 0xa 0x0" #port 7 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 7 lane 2 + "0x08 0x00 0x3c 0xe 0x0" #port 7 lane 3 + "0x08 0x04 0x3c 0xf 0x0" #port 8 lane 0 + "0x08 0x00 0x3c 0xf 0x0" #port 8 lane 1 + "0x08 0x04 0x3c 0xf 0x0" #port 8 lane 2 + "0x08 0x00 0x3c 0xf 0x0" #port 8 lane 3 + "0x08 0x04 0x3c 0xf 0x0" #port 9 lane 0 + "0x08 0x04 0x3c 0xf 0x0" #port 9 lane 1 + "0x08 0x04 0x3c 0xf 0x0" #port 9 lane 2 + "0x08 0x04 0x3c 0xf 0x0" #port 9 lane 3 + "0x08 0x04 0x3c 0xf 0x0" #port 10 lane 0 + "0x10 0x08 0x3c 0xf 0x0" #port 10 lane 1 + "0x08 0x04 0x3c 0xf 0x0" #port 10 lane 2 + "0x08 0x04 0x3c 0xf 0x0" #port 10 lane 3 + "0x08 0x08 0x3c 0xf 0x0" #port 11 lane 0 + "0x08 0x04 0x3c 0xf 0x0" #port 11 lane 1 + "0x08 0x04 0x3c 0xf 0x0" #port 11 lane 2 + "0x08 0x04 0x3c 0xf 0x0" #port 11 lane 3 + "0x08 0x0c 0x3c 0xf 0x0" #port 12 lane 0 + "0x08 0x08 0x3c 0xf 0x0" #port 12 lane 1 + "0x08 0x0c 0x3c 0xf 0x0" #port 12 lane 2 + "0x08 0x08 0x3c 0xf 0x0" #port 12 lane 3 + "0x08 0x08 0x3c 0xf 0x0" #port 13 lane 0 + "0x08 0x0c 0x3c 0xf 0x0" #port 13 lane 1 + "0x08 0x08 0x3c 0xf 0x0" #port 13 lane 2 + "0x08 0x0c 0x3c 0xf 0x0" #port 13 lane 3 + "0x10 0x10 0x3c 0xf 0x0" #port 14 lane 0 + "0x08 0x0c 0x3c 0xf 0x0" #port 14 lane 1 + "0x08 0x0c 0x3c 0xf 0x0" #port 14 lane 2 + "0x08 0x0c 0x3c 0xf 0x0" #port 14 lane 3 + "0x08 0x14 0x3c 0xf 0x0" #port 15 lane 0 + "0x08 0x10 0x3c 0xf 0x0" #port 15 lane 1 + "0x08 0x10 0x3c 0xf 0x0" #port 15 lane 2 + "0x08 0x10 0x3c 0xf 0x0" #port 15 lane 3 +) + +#get field value in si value array for xe port +function get_xe_si { + local port=$1 + local field=$2 + local type=$3 + local index=$port + if [ "$type" == "${AOC_TYPE}" ]; then + SI_VAL=$(echo "${xe_aoc_si_value[$index]}" | awk '{print $'$field'}') + else + SI_VAL=$(echo "${xe_dac_si_value[$index]}" | awk '{print $'$field'}') + fi +} + +#get field value in si value array for ce port +function get_ce_si { + local port=$1 + local lane=$2 + local field=$3 + local type=$4 + index=$(( (${port}-1)*4+${lane} )) + if [ "$type" == "${AOC_TYPE}" ]; then + SI_VAL=$(echo "${ce_aoc_si_value[$index]}" | awk '{print $'$field'}') + else + SI_VAL=$(echo "${ce_dac_si_value[$index]}" | awk '{print $'$field'}') + fi +} + +# set si value for xe port +function _qsfp_xe_si_set { + # convert PORT to xe port index + local xe_port=$PORT + # generate command for SI PRE value + get_xe_si $xe_port $SI_PRE_IDX $TYPE + local pre_cmd="phy xe${xe_port} CL93N72_UT_CTL2r CL93N72_TXFIR_PRE=${SI_VAL}" + # generate command for SI POST value + get_xe_si $xe_port $SI_POST_IDX $TYPE + local post_cmd="phy xe${xe_port} CL93N72_UT_CTL2r CL93N72_TXFIR_POST=${SI_VAL}" + # generate command for SI MAIN value + get_xe_si $xe_port $SI_MAIN_IDX $TYPE + local main_cmd="phy xe${xe_port} CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=${SI_VAL}" + # generate command for SI AMP CONTROL value + get_xe_si $xe_port $SI_AMP_IDX $TYPE + local amp_val=$SI_VAL + get_xe_si $xe_port $SI_DRI_IDX $TYPE + local dri_val=$SI_VAL + local amp_cmd="phy xe${xe_port} AMS_TX_CTL2r AMS_TX_AMP_CTL=${amp_val} AMS_TX_DRIVERMODE=${dri_val}" + # apply bcmcmd + bcmcmd "${pre_cmd};${post_cmd};${main_cmd};${amp_cmd}" +} + +# set aoc si value for ce port +function _qsfp_ce_si_set { + # convert PORT to ce port index + local ce_port=$(( $PORT - 48 )) + for lane in {0..3}; + do + # generate command for SI PRE value + get_ce_si $ce_port $lane $SI_PRE_IDX $TYPE + local pre_cmd="phy ce${ce_port} CL93N72_UT_CTL2r.${lane} CL93N72_TXFIR_PRE=${SI_VAL}" + # generate command for SI POST value + get_ce_si $ce_port $lane $SI_POST_IDX $TYPE + local post_cmd="phy ce${ce_port} CL93N72_UT_CTL2r.${lane} CL93N72_TXFIR_POST=${SI_VAL}" + # generate command for SI MAIN value + get_ce_si $ce_port $lane $SI_MAIN_IDX $TYPE + local main_cmd="phy ce${ce_port} CL93N72_UT_CTL3r.${lane} CL93N72_TXFIR_MAIN=${SI_VAL}" + # generate command for SI AMP CONTROL value + get_ce_si $ce_port $lane $SI_AMP_IDX $TYPE + local amp_val=$SI_VAL + get_ce_si $ce_port $lane $SI_AMP_IDX $TYPE + local dri_val=$SI_VAL + local amp_cmd="phy ce${ce_port} AMS_TX_CTL2r.${lane} AMS_TX_AMP_CTL=${amp_val} AMS_TX_DRIVERMODE=${dri_val}" + # apply bcmcmd + bcmcmd "${pre_cmd};${post_cmd};${main_cmd};${amp_cmd}" + done +} + +#QSFP SI value set +function _qsfp_si_set { + if [[ $PORT -le 47 && $PORT -ge 0 ]]; then + # xe port + _qsfp_xe_si_set + else + # ce port + _qsfp_ce_si_set + fi +} + +function _util_input_check { + # input parameter validation + if [[ $1 -lt $2 || $1 -gt $3 ]]; then + echo "Please input number $2~$3" + exit + fi +} + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} ${AOC_TYPE} [${MIN_PORT}-${MAX_PORT}]" + echo " : ${0} ${DAC_TYPE} [${MIN_PORT}-${MAX_PORT}]" + echo "----------------------------------------------------" +} + +#Main Function +function _main { + + # TODO: remove after SI value ready + #exit ${TRUE} + + if [ -z $PORT ]; then + _help + exit ${FALSE} + fi + + if [ "${TYPE}" == "help" ]; then + _help + elif [ "${TYPE}" == "${AOC_TYPE}" ] || [ "${TYPE}" == "${DAC_TYPE}" ]; then + _util_input_check "$PORT" "$MIN_PORT" "$MAX_PORT" + _qsfp_si_set + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/s8900_64xc_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/s8900_64xc_monitor.sh new file mode 100755 index 000000000000..8bfb22328003 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/s8900_64xc_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, 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 . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/README.md b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/README.md new file mode 100644 index 000000000000..78f828e25310 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/README.md @@ -0,0 +1,185 @@ +# Ingrasys S9100-32X Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, 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 . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S9100-32X is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S9100-32X platform. + +### I2C i801 + +The I2C i801 on Ingrasys S9100-32X can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S9100-32X. + +### I2C iSMT + +The I2C iSMT module on S9100-32X can be found in +`/sys/bus/i2c/devices/i2c-1/` + +This is I2C bus for CPLD, HWM, power controller and I2C Switches. + +The i801 module must be loaded third on Ingrasys S9100-32X. + +### I2C PCA9548 +The PCA9548 module on S9100-32X can be found in +`/sys/bus/i2c/devices/i2c-2/` , `/sys/bus/i2c/devices/i2c-3/`, +`/sys/bus/i2c/devices/i2c-4/`, `/sys/bus/i2c/devices/i2c-5/`, +`/sys/bus/i2c/devices/i2c-6/`, `/sys/bus/i2c/devices/i2c-7/`, +`/sys/bus/i2c/devices/i2c-8/`, `/sys/bus/i2c/devices/i2c-9/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S9100-32X. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S9100-32X platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s9100 package is installed on the S9100-32X, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-9/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/9-0054/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber on|off + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/Makefile b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/Makefile new file mode 100755 index 000000000000..0247bd586f63 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := eeprom_mb.o +obj-m+= i2c_cpld.o \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/eeprom_mb.c b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/eeprom_mb.c new file mode 100755 index 000000000000..01ce44ad3fee --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/eeprom_mb.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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 + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, I2C_CLIENT_END }; + + +/* 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 mb_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 mb_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++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_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, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys S9100 Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/i2c_cpld.c b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/i2c_cpld.c new file mode 100755 index 000000000000..626c63177b50 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/i2c_cpld.c @@ -0,0 +1,448 @@ +/* + * S9100-32X I2C CPLD driver + * + * Copyright (C) 2017 Ingrasys, Inc. + * Wade He + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c_cpld.h" + +#ifdef DEBUG + #define DEBUG_PRINT(fmt, args...) \ + printk(KERN_INFO "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define I2C_READ_BYTE_DATA(ret, lock, i2c_client, reg) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_read_byte_data(i2c_client, reg); \ + mutex_unlock(lock); \ +} +#define I2C_WRITE_BYTE_DATA(ret, lock, i2c_client, reg, val) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_write_byte_data(i2c_client, reg, val); \ + mutex_unlock(lock); \ +} + +/* CPLD sysfs attributes index */ +enum i2c_cpld_sysfs_attributes { + CPLD_ACCESS_REG, + CPLD_REGISTER_VAL, + CPLD_PORT_START, + CPLD_PORTS, + CPLD_VERSION, + CPLD_ID, + CPLD_BOARD_TYPE, + CPLD_EXT_BOARD_TYPE, + CPLD_PW_GOOD, + CPLD_PW_ABS, +}; + +/* CPLD sysfs attributes hook functions */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_pw_good(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_pw_abs(struct device *dev, + struct device_attribute *da, char *buf); + +static LIST_HEAD(cpld_client_list); /* client list for cpld */ +static struct mutex list_lock; /* mutex for client list */ + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +struct cpld_data { + int index; /* CPLD index */ + struct mutex access_lock; /* mutex for cpld access */ + u8 access_reg; /* register to access */ +}; + +/* CPLD device id and data */ +static const struct i2c_device_id i2c_cpld_id[] = { + { "i2c_cpld", i2c_cpld }, + {} +}; + +/* Addresses scanned for i2c_cpld */ +static const unsigned short cpld_i2c_addr[] = { 0x33, I2C_CLIENT_END }; +/* platform sysfs object */ +extern struct kobject *s9230_64x_kobj; + + +/* define all support register access of cpld in attribute */ +static SENSOR_DEVICE_ATTR(cpld_access_register, S_IWUSR | S_IRUGO, + read_access_register, write_access_register, CPLD_ACCESS_REG); +static SENSOR_DEVICE_ATTR(cpld_register_value, S_IWUSR | S_IRUGO, + read_register_value, write_register_value, CPLD_REGISTER_VAL); +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, + read_cpld_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(cpld_board_type, S_IRUGO, + read_board_type, NULL, CPLD_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_ext_board_type, S_IRUGO, + read_ext_board_type, NULL, CPLD_EXT_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_pw_good, S_IRUGO, + read_pw_good, NULL, CPLD_PW_GOOD); +static SENSOR_DEVICE_ATTR(cpld_pw_abs, S_IRUGO, + read_pw_abs, NULL, CPLD_PW_ABS); + + +/* define support attributes of cpldx , total 5 */ +/* cpld 1 */ +static struct attribute *i2c_cpld_attributes[] = { + &sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_ext_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_pw_good.dev_attr.attr, + &sensor_dev_attr_cpld_pw_abs.dev_attr.attr, + NULL +}; + +/* cpld 1 attributes group */ +static const struct attribute_group i2c_cpld_group = { + .attrs = i2c_cpld_attributes, +}; + +/* read access register from cpld data */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + + return sprintf(buf, "0x%x\n", reg); +} + +/* write access register to cpld data */ +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + + if (kstrtou8(buf, 0, ®) < 0) + return -EINVAL; + + data->access_reg = reg; + return count; +} + +/* read the value of access register in cpld data */ +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + int reg_val; + + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + + if (reg_val < 0) + return -1; + + return sprintf(buf, "0x%x\n", reg_val); +} + +/* wrtie the value to access register in cpld data */ +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ret = -EIO; + u8 reg = data->access_reg; + u8 reg_val; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, client, reg, reg_val); + + return count; +} + +/* get cpdl version register value */ +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_VERSION) { + reg = CPLD_VERSION_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get board type register value */ +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BOARD_TYPE) { + reg = CPLD_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_EXT_BOARD_TYPE) { + reg = CPLD_EXT_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_pw_good(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_PW_GOOD) { + reg = CPLD_PW_GOOD_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_pw_abs(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_PW_ABS) { + reg = CPLD_PW_ABS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* add valid cpld client to list */ +static void i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = NULL; + + node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + if (!node) { + dev_info(&client->dev, + "Can't allocate cpld_client_node for index %d\n", + client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +/* remove exist cpld client in list */ +static void i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + mutex_unlock(&list_lock); +} + +/* cpld drvier probe */ +static int i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct cpld_data *data = NULL; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* init cpld data for client */ + i2c_set_clientdata(client, data); + mutex_init(&data->access_lock); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_info(&client->dev, + "i2c_check_functionality failed (0x%x)\n", + client->addr); + status = -EIO; + goto exit; + } + + + status = sysfs_create_group(&client->dev.kobj,&i2c_cpld_group); + + if (status) + goto exit; + + dev_info(&client->dev, "chip found\n"); + + /* add probe chip to client list */ + i2c_cpld_add_client(client); + + return 0; +exit: + sysfs_remove_group(&client->dev.kobj, &i2c_cpld_group); + return status; +} + +/* cpld drvier remove */ +static int i2c_cpld_remove(struct i2c_client *client) +{ + + sysfs_remove_group(&client->dev.kobj, &i2c_cpld_group); + + i2c_cpld_remove_client(client); + return 0; +} + +MODULE_DEVICE_TABLE(i2c, i2c_cpld_id); + +static struct i2c_driver i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "i2c_cpld", + }, + .probe = i2c_cpld_probe, + .remove = i2c_cpld_remove, + .id_table = i2c_cpld_id, + .address_list = cpld_i2c_addr, +}; + +static int __init i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&i2c_cpld_driver); +} + +static void __exit i2c_cpld_exit(void) +{ + i2c_del_driver(&i2c_cpld_driver); +} + +MODULE_AUTHOR("Wade He "); +MODULE_DESCRIPTION("Ingrasys S9100-32X Platform i2c cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_cpld_init); +module_exit(i2c_cpld_exit); + + + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/i2c_cpld.h b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/i2c_cpld.h new file mode 100755 index 000000000000..e103b05c717a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/i2c_cpld.h @@ -0,0 +1,197 @@ +/* + * + * S9100-32X I2C CPLD driver header file + * + * Copyright (C) 2017 Ingrasys, Inc. + * Wade He + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef I2C_CPLD_H +#define I2C_CPLD_H + +// remove debug before release +#define DEBUG + +/* CPLD device index value */ +enum cpld_id { + i2c_cpld +}; + +/* port number on CPLD */ +#define CPLD_1_PORT_NUM 12 +#define CPLD_2_PORT_NUM 13 + +/* QSFP port number */ +#define QSFP_MAX_PORT_NUM 64 +#define QSFP_MIN_PORT_NUM 1 + +/* SFP+ port number */ +#define SFP_MAX_PORT_NUM 2 +#define SFP_MIN_PORT_NUM 1 + + +/* CPLD registers */ +#define CPLD_BOARD_TYPE_REG 0x0 +#define CPLD_EXT_BOARD_TYPE_REG 0x7 +#define CPLD_VERSION_REG 0x1 +#define CPLD_PW_GOOD_REG 0x2 +#define CPLD_PW_ABS_REG 0x3 + + +/* bit definition for register value */ + +enum CPLD_RESET_CONTROL_BITS { + CPLD_RESET_CONTROL_SWRST_BIT, + CPLD_RESET_CONTROL_CP2104RST_BIT, + CPLD_RESET_CONTROL_82P33814RST_BIT, + CPLD_RESET_CONTROL_BMCRST_BIT, +}; + +/* bit field structure for register value */ +struct cpld_reg_board_type_t { + u8 build_rev:2; + u8 hw_rev:2; + u8 board_id:4; +}; + +struct cpld_reg_version_t { + u8 revision:6; + u8 release:1; + u8 reserve:1; +}; + +struct cpld_reg_pw_good_t { + u8 reserve1:3; + u8 psu1:1; + u8 psu2:1; + u8 reserve2:3; +}; + +struct cpld_reg_pw_abs_t { + u8 psu1:1; + u8 psu2:1; + u8 reserve:6; +}; + +/* common manipulation */ +#define INVALID(i, min, max) ((i < min) || (i > max) ? 1u : 0u) +#define READ_BIT(val, bit) ((0u == (val & (1<bf_name) +#define READ_BF_1(bf_struct, val, bf_name, bf_value) \ + bf_struct bf; \ + bf.data = val; \ + bf_value = bf.bf_name +#define BOARD_TYPE_BUILD_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, build_rev, res) +#define BOARD_TYPE_HW_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, hw_rev, res) +#define BOARD_TYPE_BOARD_ID_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, board_id, res) +#define CPLD_VERSION_REV_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, revision, res) +#define CPLD_VERSION_REL_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, release, res) +#define CPLD_PSU1_PW_GOOD_GET(val, res) \ + READ_BF(cpld_reg_pw_good_t, val, psu1, res) +#define CPLD_PSU2_PW_GOOD_GET(val, res) \ + READ_BF(cpld_reg_pw_good_t, val, psu2, res) +#define CPLD_PSU1_PW_ABS_GET(val, res) \ + READ_BF(cpld_reg_pw_abs_t, val, psu1, res) +#define CPLD_PSU2_PW_ABS_GET(val, res) \ + READ_BF(cpld_reg_pw_abs_t, val, psu2, res) +/* QSFP/SFP registers manipulation */ +#define QSFP_TO_CPLD_IDX(qsfp_port, cpld_index, cpld_port) \ +{ \ + if (QSFP_MIN_PORT_NUM <= qsfp_port && qsfp_port <= CPLD_1_PORT_NUM) { \ + cpld_index = cpld1; \ + cpld_port = qsfp_port - 1; \ + } else if (CPLD_1_PORT_NUM < qsfp_port \ + && qsfp_port <= QSFP_MAX_PORT_NUM) { \ + cpld_index = cpld2 + (qsfp_port - 1 - CPLD_1_PORT_NUM) \ + / CPLD_2_PORT_NUM; \ + cpld_port = (qsfp_port - 1 - CPLD_1_PORT_NUM) % \ + CPLD_2_PORT_NUM; \ + } else { \ + cpld_index = 0; \ + cpld_port = 0; \ + } \ +} +#define SFP_TO_CPLD_IDX(sfp_port, cpld_index) \ + (cpld_index = sfp_port - SFP_MIN_PORT_NUM) +#define QSFP_PORT_STATUS_REG(cpld_port) \ + (CPLD_QSFP_PORT_STATUS_BASE_REG + cpld_port) +#define QSFP_PORT_CONFIG_REG(cpld_port) \ + (CPLD_QSFP_PORT_CONFIG_BASE_REG + cpld_port) +#define QSFP_PORT_INT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_INT_BIT) +#define QSFP_PORT_ABS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_ABS_BIT) +#define QSFP_PORT_RESET_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_RESET_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_RESET_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_LPMODE_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define SFP_PORT_PRESENT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_PRESENT_BIT) + + #define SFP_PORT_TXFAULT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_TXFAULT_BIT) + #define SFP_PORT_RXLOS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_RXLOS_BIT) + #define SFP_PORT_TXDIS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TXDIS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_TXDIS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_RS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) + +/* CPLD access functions */ +extern int i2c_cpld_get_qsfp_port_status_val(u8 port_num); +extern int i2c_cpld_get_qsfp_port_config_val(u8 port_num); +extern int i2c_cpld_set_qsfp_port_config_val(u8 port_num, u8 reg_val); +extern int i2c_cpld_get_sfp_port_status_val(u8 port_num); +extern int i2c_cpld_get_sfp_port_config_val(u8 port_num); +extern int i2c_cpld_set_sfp_port_config_val(u8 port_num, u8 reg_val); +extern u8 fp_port_to_phy_port(u8 fp_port); +#endif + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/service/qsfp-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/service/qsfp-monitor.service new file mode 100644 index 000000000000..584d6fcae895 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s9100-monitor.service +After=s9100-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/service/s9100-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/service/s9100-monitor.service new file mode 100644 index 000000000000..5e074782a852 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/service/s9100-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s9100_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/i2c_utils.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/i2c_utils.sh new file mode 100755 index 000000000000..4aefe153a67b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/i2c_utils.sh @@ -0,0 +1,1607 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, 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 . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.1.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +QSFP_ACTION=${2} +MB_EEPROM_ACTION=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_IGB_DEVICE=0 +NUM_I801_DEVICE=0 +NUM_ISMT_DEVICE=$(( ${NUM_I801_DEVICE} + 1 )) +NUM_MUX1_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 2 )) +NUM_MUX1_CHAN1_DEVICE=$(( ${NUM_I801_DEVICE} + 3 )) +NUM_MUX1_CHAN2_DEVICE=$(( ${NUM_I801_DEVICE} + 4 )) +NUM_MUX1_CHAN3_DEVICE=$(( ${NUM_I801_DEVICE} + 5 )) +NUM_MUX1_CHAN4_DEVICE=$(( ${NUM_I801_DEVICE} + 6 )) +NUM_MUX1_CHAN5_DEVICE=$(( ${NUM_I801_DEVICE} + 7 )) +NUM_MUX1_CHAN6_DEVICE=$(( ${NUM_I801_DEVICE} + 8 )) +NUM_MUX1_CHAN7_DEVICE=$(( ${NUM_I801_DEVICE} + 9 )) +NUM_MUX3_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 10 )) +NUM_MUX4_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 18 )) +NUM_MUX5_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 26 )) +NUM_MUX6_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 34 )) + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon1" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_ISMT_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_ISMT_DEVICE}" +PATH_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" +PATH_MUX_CHAN1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN1_DEVICE}" +PATH_MUX_CHAN2_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN2_DEVICE}" +PATH_MUX_CHAN3_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN3_DEVICE}" +PATH_MUX_CHAN4_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN4_DEVICE}" +PATH_MUX_CHAN5_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN5_DEVICE}" +PATH_MUX_CHAN6_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN6_DEVICE}" +PATH_MUX_CHAN7_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}" + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +#GPIO Offset +GPIO_OFFSET=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "# Version : ${VERSION}" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_temp_init" + echo " : ${0} i2c_fan_init" + echo " : ${0} i2c_volmon_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_gpio_init" + echo " : ${0} i2c_gpio_deinit" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [1-32]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [1-32]" + echo " : ${0} i2c_qsfp_type_get [1-32]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_front_temp" + echo " : ${0} i2c_rear_temp" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber on|off" + echo " : ${0} i2c_fan_led green|amber on|off" + echo " : ${0} i2c_psu1_led green|amber on|off" + echo " : ${0} i2c_psu2_led green|amber on|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + rmmod i2c_ismt + rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_ismt + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x70' > ${PATH_ISMT_DEVICE}/new_device" + else + echo "pca9548 0x70 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX3_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN0_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX4_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x72' > ${PATH_MUX_CHAN1_DEVICE}/new_device" + else + echo "pca9548 0x72 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX5_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x73' > ${PATH_MUX_CHAN2_DEVICE}/new_device" + else + echo "pca9548 0x73 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX6_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x74' > ${PATH_MUX_CHAN3_DEVICE}/new_device" + else + echo "pca9548 0x74 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN6_DEVICE}-0075" ]; then + _retry "echo 'pca9546 0x75' > ${PATH_MUX_CHAN6_DEVICE}/new_device" + else + echo "pca9548 0x75 already init." + fi + #Init CPLD LED_CLR Register (Front Port LED) + i2cset -y ${NUM_I801_DEVICE} 0x33 0x34 0x10 + + rmmod coretemp + rmmod jc42 + rmmod w83795 + _i2c_temp_init + _i2c_volmon_init + modprobe coretemp + modprobe w83795 + modprobe jc42 + modprobe eeprom + modprobe eeprom_mb + modprobe gpio-pca953x + _i2c_fan_init + _i2c_io_exp_init + rmmod gpio_ich + _i2c_gpio_init + modprobe gpio_ich + _i2c_cpld_init + _i2c_qsfp_eeprom_init "new" + _i2c_mb_eeprom_init "new" + _i2c_psu_eeprom_init + _i2c_led_psu_status_set + _i2c_led_fan_status_set + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + _i2c_gpio_deinit + for mod in i2c_cpld coretemp jc42 w83795 eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_ismt i2c_i801; + do + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod + done +} + +#Temperature sensor Init +function _i2c_temp_init { + echo -n "TEMP INIT..." + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x05 0x7F + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x04 0x0A + echo "Done" +} + +#FAN Init +function _i2c_fan_init { + echo -n "FAN INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi + +} + +#VOLMON Init +function _i2c_volmon_init { + echo -n "VOLMON INIT..." + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x02 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x03 0x50 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x04 0x0A + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + #SMBUS0 IO_EXPENDER + i2cset -y -r ${NUM_I801_DEVICE} 0x27 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 2 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 3 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 6 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x27 7 0xFF + + #SMBUS1 + #ABS + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 7 0xFF + + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 7 0xFF + + #Transcevior INT + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 7 0xFF + + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 7 0xFF + + echo "Init ZQSFP IO Expender" + echo "set ZQSFP LP_MODE = 0" + #set ZQSFP LP_MODE = 0 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 7 0x00 + + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 7 0x00 + + echo "set ZQSFP RST = 1" + #set ZQSFP RST = 1 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 2 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 3 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 7 0x00 + + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 2 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 3 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 7 0x00 + + echo "set ZQSFP mode" + #ZQSFP mode + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x24 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x24 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x24 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x24 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x24 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x24 7 0x00 + + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x25 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x25 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x25 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x25 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x25 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x25 7 0x00 + + #ZQSFP/SFP+/E-Card General + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x20 7 0xFF + + #LED board after PVT (S9100_IO_EXP_LED_ID) + echo "Init LED IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 7 0x00 + + #PSU I/O (S9100_IO_EXP_PSU_ID) + echo "Init PSU IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x23 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x23 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x23 6 0xBB + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x23 7 0xFF + + #FAN I/O (S9100_IO_EXP_FAN_ID) + echo "Init FAN IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x20 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x20 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x20 6 0xCC + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x20 7 0xCC +} + +# To set the global variable GPIO_OFFSET +function _set_gpio_offset { + GPIO_OFFSET=0 + for d in `ls /sys/class/gpio/ | grep gpiochip` + do + gpiochip_no=${d##gpiochip} + if [ $gpiochip_no -gt 255 ]; then + GPIO_OFFSET=256 + break + fi + done + #echo "set GPIO_OFFSET=${GPIO_OFFSET}" +} + +#GPIO Init +function _i2c_gpio_init { + #ABS Port 0-15 (zQSFP00 ~ zQSFP15) + echo "pca9535 0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + _set_gpio_offset + for((i=${GPIO_OFFSET}+240;i<=${GPIO_OFFSET}+255;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 240 > /sys/class/gpio/export + #echo 241 > /sys/class/gpio/export + #echo 242 > /sys/class/gpio/export + #echo 243 > /sys/class/gpio/export + #echo 244 > /sys/class/gpio/export + #echo 245 > /sys/class/gpio/export + #echo 246 > /sys/class/gpio/export + #echo 247 > /sys/class/gpio/export + #echo 248 > /sys/class/gpio/export + #echo 249 > /sys/class/gpio/export + #echo 250 > /sys/class/gpio/export + #echo 251 > /sys/class/gpio/export + #echo 252 > /sys/class/gpio/export + #echo 253 > /sys/class/gpio/export + #echo 254 > /sys/class/gpio/export + #echo 255 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio241/active_low #zQSFP00 + #echo 1 > /sys/class/gpio/gpio240/active_low #zQSFP01 + #echo 1 > /sys/class/gpio/gpio243/active_low #zQSFP02 + #echo 1 > /sys/class/gpio/gpio242/active_low #zQSFP03 + #echo 1 > /sys/class/gpio/gpio245/active_low #zQSFP04 + #echo 1 > /sys/class/gpio/gpio244/active_low #zQSFP05 + #echo 1 > /sys/class/gpio/gpio247/active_low #zQSFP06 + #echo 1 > /sys/class/gpio/gpio246/active_low #zQSFP07 + #echo 1 > /sys/class/gpio/gpio249/active_low #zQSFP08 + #echo 1 > /sys/class/gpio/gpio248/active_low #zQSFP09 + #echo 1 > /sys/class/gpio/gpio251/active_low #zQSFP10 + #echo 1 > /sys/class/gpio/gpio250/active_low #zQSFP11 + #echo 1 > /sys/class/gpio/gpio253/active_low #zQSFP12 + #echo 1 > /sys/class/gpio/gpio252/active_low #zQSFP13 + #echo 1 > /sys/class/gpio/gpio255/active_low #zQSFP14 + #echo 1 > /sys/class/gpio/gpio254/active_low #zQSFP15 + + #ABS Port 16-31 (zQSFP16 ~ zQSFP31) + echo "pca9535 0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + for((i=${GPIO_OFFSET}+224;i<=${GPIO_OFFSET}+239;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 224 > /sys/class/gpio/export + #echo 225 > /sys/class/gpio/export + #echo 226 > /sys/class/gpio/export + #echo 227 > /sys/class/gpio/export + #echo 228 > /sys/class/gpio/export + #echo 229 > /sys/class/gpio/export + #echo 230 > /sys/class/gpio/export + #echo 231 > /sys/class/gpio/export + #echo 232 > /sys/class/gpio/export + #echo 233 > /sys/class/gpio/export + #echo 234 > /sys/class/gpio/export + #echo 235 > /sys/class/gpio/export + #echo 236 > /sys/class/gpio/export + #echo 237 > /sys/class/gpio/export + #echo 238 > /sys/class/gpio/export + #echo 239 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio225/active_low #zQSFP16 + #echo 1 > /sys/class/gpio/gpio224/active_low #zQSFP17 + #echo 1 > /sys/class/gpio/gpio227/active_low #zQSFP18 + #echo 1 > /sys/class/gpio/gpio226/active_low #zQSFP19 + #echo 1 > /sys/class/gpio/gpio229/active_low #zQSFP20 + #echo 1 > /sys/class/gpio/gpio228/active_low #zQSFP21 + #echo 1 > /sys/class/gpio/gpio231/active_low #zQSFP22 + #echo 1 > /sys/class/gpio/gpio230/active_low #zQSFP23 + #echo 1 > /sys/class/gpio/gpio233/active_low #zQSFP24 + #echo 1 > /sys/class/gpio/gpio232/active_low #zQSFP25 + #echo 1 > /sys/class/gpio/gpio235/active_low #zQSFP26 + #echo 1 > /sys/class/gpio/gpio234/active_low #zQSFP27 + #echo 1 > /sys/class/gpio/gpio237/active_low #zQSFP28 + #echo 1 > /sys/class/gpio/gpio236/active_low #zQSFP29 + #echo 1 > /sys/class/gpio/gpio239/active_low #zQSFP30 + #echo 1 > /sys/class/gpio/gpio238/active_low #zQSFP31 + + #INT Port 0-15 (zQSFP00 ~ zQSFP15) + echo "pca9535 0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + for((i=${GPIO_OFFSET}+208;i<=${GPIO_OFFSET}+223;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 208 > /sys/class/gpio/export + #echo 209 > /sys/class/gpio/export + #echo 210 > /sys/class/gpio/export + #echo 211 > /sys/class/gpio/export + #echo 212 > /sys/class/gpio/export + #echo 213 > /sys/class/gpio/export + #echo 214 > /sys/class/gpio/export + #echo 215 > /sys/class/gpio/export + #echo 216 > /sys/class/gpio/export + #echo 217 > /sys/class/gpio/export + #echo 218 > /sys/class/gpio/export + #echo 219 > /sys/class/gpio/export + #echo 220 > /sys/class/gpio/export + #echo 221 > /sys/class/gpio/export + #echo 222 > /sys/class/gpio/export + #echo 223 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio208/active_low + #echo 1 > /sys/class/gpio/gpio209/active_low + #echo 1 > /sys/class/gpio/gpio210/active_low + #echo 1 > /sys/class/gpio/gpio211/active_low + #echo 1 > /sys/class/gpio/gpio212/active_low + #echo 1 > /sys/class/gpio/gpio213/active_low + #echo 1 > /sys/class/gpio/gpio214/active_low + #echo 1 > /sys/class/gpio/gpio215/active_low + #echo 1 > /sys/class/gpio/gpio216/active_low + #echo 1 > /sys/class/gpio/gpio217/active_low + #echo 1 > /sys/class/gpio/gpio218/active_low + #echo 1 > /sys/class/gpio/gpio219/active_low + #echo 1 > /sys/class/gpio/gpio220/active_low + #echo 1 > /sys/class/gpio/gpio221/active_low + #echo 1 > /sys/class/gpio/gpio222/active_low + #echo 1 > /sys/class/gpio/gpio223/active_low + + #INT Port 16-31 (zQSFP16 ~ zQSFP31) + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + for((i=${GPIO_OFFSET}+192;i<=${GPIO_OFFSET}+207;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 192 > /sys/class/gpio/export + #echo 193 > /sys/class/gpio/export + #echo 194 > /sys/class/gpio/export + #echo 195 > /sys/class/gpio/export + #echo 196 > /sys/class/gpio/export + #echo 197 > /sys/class/gpio/export + #echo 198 > /sys/class/gpio/export + #echo 199 > /sys/class/gpio/export + #echo 200 > /sys/class/gpio/export + #echo 201 > /sys/class/gpio/export + #echo 202 > /sys/class/gpio/export + #echo 203 > /sys/class/gpio/export + #echo 204 > /sys/class/gpio/export + #echo 205 > /sys/class/gpio/export + #echo 206 > /sys/class/gpio/export + #echo 207 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio192/active_low + #echo 1 > /sys/class/gpio/gpio193/active_low + #echo 1 > /sys/class/gpio/gpio194/active_low + #echo 1 > /sys/class/gpio/gpio195/active_low + #echo 1 > /sys/class/gpio/gpio196/active_low + #echo 1 > /sys/class/gpio/gpio197/active_low + #echo 1 > /sys/class/gpio/gpio198/active_low + #echo 1 > /sys/class/gpio/gpio199/active_low + #echo 1 > /sys/class/gpio/gpio200/active_low + #echo 1 > /sys/class/gpio/gpio201/active_low + #echo 1 > /sys/class/gpio/gpio202/active_low + #echo 1 > /sys/class/gpio/gpio203/active_low + #echo 1 > /sys/class/gpio/gpio204/active_low + #echo 1 > /sys/class/gpio/gpio205/active_low + #echo 1 > /sys/class/gpio/gpio206/active_low + #echo 1 > /sys/class/gpio/gpio207/active_low + + #LP Mode Port 0-15 + echo "pca9535 0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + for((i=${GPIO_OFFSET}+176;i<=${GPIO_OFFSET}+191;i++)); + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + done + + #echo 176 > /sys/class/gpio/export + #echo 177 > /sys/class/gpio/export + #echo 178 > /sys/class/gpio/export + #echo 179 > /sys/class/gpio/export + #echo 180 > /sys/class/gpio/export + #echo 181 > /sys/class/gpio/export + #echo 182 > /sys/class/gpio/export + #echo 183 > /sys/class/gpio/export + #echo 184 > /sys/class/gpio/export + #echo 185 > /sys/class/gpio/export + #echo 186 > /sys/class/gpio/export + #echo 187 > /sys/class/gpio/export + #echo 188 > /sys/class/gpio/export + #echo 189 > /sys/class/gpio/export + #echo 190 > /sys/class/gpio/export + #echo 191 > /sys/class/gpio/export + #echo out > /sys/class/gpio/gpio176/direction + #echo out > /sys/class/gpio/gpio177/direction + #echo out > /sys/class/gpio/gpio178/direction + #echo out > /sys/class/gpio/gpio179/direction + #echo out > /sys/class/gpio/gpio180/direction + #echo out > /sys/class/gpio/gpio181/direction + #echo out > /sys/class/gpio/gpio182/direction + #echo out > /sys/class/gpio/gpio183/direction + #echo out > /sys/class/gpio/gpio184/direction + #echo out > /sys/class/gpio/gpio185/direction + #echo out > /sys/class/gpio/gpio186/direction + #echo out > /sys/class/gpio/gpio187/direction + #echo out > /sys/class/gpio/gpio188/direction + #echo out > /sys/class/gpio/gpio189/direction + #echo out > /sys/class/gpio/gpio190/direction + #echo out > /sys/class/gpio/gpio191/direction + + #LP Mode Port 16-31 + echo "pca9535 0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + for((i=${GPIO_OFFSET}+160;i<=${GPIO_OFFSET}+175;i++)); + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + done + + #echo 160 > /sys/class/gpio/export + #echo 161 > /sys/class/gpio/export + #echo 162 > /sys/class/gpio/export + #echo 163 > /sys/class/gpio/export + #echo 164 > /sys/class/gpio/export + #echo 165 > /sys/class/gpio/export + #echo 166 > /sys/class/gpio/export + #echo 167 > /sys/class/gpio/export + #echo 168 > /sys/class/gpio/export + #echo 169 > /sys/class/gpio/export + #echo 170 > /sys/class/gpio/export + #echo 171 > /sys/class/gpio/export + #echo 172 > /sys/class/gpio/export + #echo 173 > /sys/class/gpio/export + #echo 174 > /sys/class/gpio/export + #echo 175 > /sys/class/gpio/export + #echo out > /sys/class/gpio/gpio160/direction + #echo out > /sys/class/gpio/gpio161/direction + #echo out > /sys/class/gpio/gpio162/direction + #echo out > /sys/class/gpio/gpio163/direction + #echo out > /sys/class/gpio/gpio164/direction + #echo out > /sys/class/gpio/gpio165/direction + #echo out > /sys/class/gpio/gpio166/direction + #echo out > /sys/class/gpio/gpio167/direction + #echo out > /sys/class/gpio/gpio168/direction + #echo out > /sys/class/gpio/gpio169/direction + #echo out > /sys/class/gpio/gpio170/direction + #echo out > /sys/class/gpio/gpio171/direction + #echo out > /sys/class/gpio/gpio172/direction + #echo out > /sys/class/gpio/gpio173/direction + #echo out > /sys/class/gpio/gpio174/direction + #echo out > /sys/class/gpio/gpio175/direction + + #RST Port 0-15 + echo "pca9535 0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + for((i=${GPIO_OFFSET}+144;i<=${GPIO_OFFSET}+159;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + echo low > /sys/class/gpio/gpio${i}/direction + #echo out > /sys/class/gpio/gpio${i}/direction + #echo 0 > /sys/class/gpio/gpio${i}/value + done + + #echo 144 > /sys/class/gpio/export + #echo 145 > /sys/class/gpio/export + #echo 146 > /sys/class/gpio/export + #echo 147 > /sys/class/gpio/export + #echo 148 > /sys/class/gpio/export + #echo 149 > /sys/class/gpio/export + #echo 150 > /sys/class/gpio/export + #echo 151 > /sys/class/gpio/export + #echo 152 > /sys/class/gpio/export + #echo 153 > /sys/class/gpio/export + #echo 154 > /sys/class/gpio/export + #echo 155 > /sys/class/gpio/export + #echo 156 > /sys/class/gpio/export + #echo 157 > /sys/class/gpio/export + #echo 158 > /sys/class/gpio/export + #echo 159 > /sys/class/gpio/export + #echo out > /sys/class/gpio/gpio144/direction + #echo out > /sys/class/gpio/gpio145/direction + #echo out > /sys/class/gpio/gpio146/direction + #echo out > /sys/class/gpio/gpio147/direction + #echo out > /sys/class/gpio/gpio148/direction + #echo out > /sys/class/gpio/gpio149/direction + #echo out > /sys/class/gpio/gpio150/direction + #echo out > /sys/class/gpio/gpio151/direction + #echo out > /sys/class/gpio/gpio152/direction + #echo out > /sys/class/gpio/gpio153/direction + #echo out > /sys/class/gpio/gpio154/direction + #echo out > /sys/class/gpio/gpio155/direction + #echo out > /sys/class/gpio/gpio156/direction + #echo out > /sys/class/gpio/gpio157/direction + #echo out > /sys/class/gpio/gpio158/direction + #echo out > /sys/class/gpio/gpio159/direction + #echo 1 > /sys/class/gpio/gpio144/active_low + #echo 1 > /sys/class/gpio/gpio145/active_low + #echo 1 > /sys/class/gpio/gpio146/active_low + #echo 1 > /sys/class/gpio/gpio147/active_low + #echo 1 > /sys/class/gpio/gpio148/active_low + #echo 1 > /sys/class/gpio/gpio149/active_low + #echo 1 > /sys/class/gpio/gpio150/active_low + #echo 1 > /sys/class/gpio/gpio151/active_low + #echo 1 > /sys/class/gpio/gpio152/active_low + #echo 1 > /sys/class/gpio/gpio153/active_low + #echo 1 > /sys/class/gpio/gpio154/active_low + #echo 1 > /sys/class/gpio/gpio155/active_low + #echo 1 > /sys/class/gpio/gpio156/active_low + #echo 1 > /sys/class/gpio/gpio157/active_low + #echo 1 > /sys/class/gpio/gpio158/active_low + #echo 1 > /sys/class/gpio/gpio159/active_low + #echo 0 > /sys/class/gpio/gpio144/value + #echo 0 > /sys/class/gpio/gpio145/value + #echo 0 > /sys/class/gpio/gpio146/value + #echo 0 > /sys/class/gpio/gpio147/value + #echo 0 > /sys/class/gpio/gpio148/value + #echo 0 > /sys/class/gpio/gpio149/value + #echo 0 > /sys/class/gpio/gpio150/value + #echo 0 > /sys/class/gpio/gpio151/value + #echo 0 > /sys/class/gpio/gpio152/value + #echo 0 > /sys/class/gpio/gpio153/value + #echo 0 > /sys/class/gpio/gpio154/value + #echo 0 > /sys/class/gpio/gpio155/value + #echo 0 > /sys/class/gpio/gpio156/value + #echo 0 > /sys/class/gpio/gpio157/value + #echo 0 > /sys/class/gpio/gpio158/value + #echo 0 > /sys/class/gpio/gpio159/value + + #RST Port 16-31 + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + for((i=${GPIO_OFFSET}+128;i<=${GPIO_OFFSET}+143;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + echo low > /sys/class/gpio/gpio${i}/direction + #echo out > /sys/class/gpio/gpio${i}/direction + #echo 0 > /sys/class/gpio/gpio${i}/value + done + + #echo 128 > /sys/class/gpio/export + #echo 129 > /sys/class/gpio/export + #echo 130 > /sys/class/gpio/export + #echo 131 > /sys/class/gpio/export + #echo 132 > /sys/class/gpio/export + #echo 133 > /sys/class/gpio/export + #echo 134 > /sys/class/gpio/export + #echo 135 > /sys/class/gpio/export + #echo 136 > /sys/class/gpio/export + #echo 137 > /sys/class/gpio/export + #echo 138 > /sys/class/gpio/export + #echo 139 > /sys/class/gpio/export + #echo 140 > /sys/class/gpio/export + #echo 141 > /sys/class/gpio/export + #echo 142 > /sys/class/gpio/export + #echo 143 > /sys/class/gpio/export + #echo out > /sys/class/gpio/gpio128/direction + #echo out > /sys/class/gpio/gpio129/direction + #echo out > /sys/class/gpio/gpio130/direction + #echo out > /sys/class/gpio/gpio131/direction + #echo out > /sys/class/gpio/gpio132/direction + #echo out > /sys/class/gpio/gpio133/direction + #echo out > /sys/class/gpio/gpio134/direction + #echo out > /sys/class/gpio/gpio135/direction + #echo out > /sys/class/gpio/gpio136/direction + #echo out > /sys/class/gpio/gpio137/direction + #echo out > /sys/class/gpio/gpio138/direction + #echo out > /sys/class/gpio/gpio139/direction + #echo out > /sys/class/gpio/gpio140/direction + #echo out > /sys/class/gpio/gpio141/direction + #echo out > /sys/class/gpio/gpio142/direction + #echo out > /sys/class/gpio/gpio143/direction + #echo 1 > /sys/class/gpio/gpio128/active_low + #echo 1 > /sys/class/gpio/gpio129/active_low + #echo 1 > /sys/class/gpio/gpio130/active_low + #echo 1 > /sys/class/gpio/gpio131/active_low + #echo 1 > /sys/class/gpio/gpio132/active_low + #echo 1 > /sys/class/gpio/gpio133/active_low + #echo 1 > /sys/class/gpio/gpio134/active_low + #echo 1 > /sys/class/gpio/gpio135/active_low + #echo 1 > /sys/class/gpio/gpio136/active_low + #echo 1 > /sys/class/gpio/gpio137/active_low + #echo 1 > /sys/class/gpio/gpio138/active_low + #echo 1 > /sys/class/gpio/gpio139/active_low + #echo 1 > /sys/class/gpio/gpio140/active_low + #echo 1 > /sys/class/gpio/gpio141/active_low + #echo 1 > /sys/class/gpio/gpio142/active_low + #echo 1 > /sys/class/gpio/gpio143/active_low + #echo 0 > /sys/class/gpio/gpio128/value + #echo 0 > /sys/class/gpio/gpio129/value + #echo 0 > /sys/class/gpio/gpio130/value + #echo 0 > /sys/class/gpio/gpio131/value + #echo 0 > /sys/class/gpio/gpio132/value + #echo 0 > /sys/class/gpio/gpio133/value + #echo 0 > /sys/class/gpio/gpio134/value + #echo 0 > /sys/class/gpio/gpio135/value + #echo 0 > /sys/class/gpio/gpio136/value + #echo 0 > /sys/class/gpio/gpio137/value + #echo 0 > /sys/class/gpio/gpio138/value + #echo 0 > /sys/class/gpio/gpio139/value + #echo 0 > /sys/class/gpio/gpio140/value + #echo 0 > /sys/class/gpio/gpio141/value + #echo 0 > /sys/class/gpio/gpio142/value + #echo 0 > /sys/class/gpio/gpio143/value + +} + +#GPIO DeInit +function _i2c_gpio_deinit { + echo "0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device +} + +#I2C CPLD init +function _i2c_cpld_init { + echo "=========================================================" + echo "# Description: I2C CPLD Init..." + echo "=========================================================" + + ## modprobe i2c_cpld + modprobe i2c_cpld + ## Add CPLD device + echo "i2c_cpld 0x33" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}/new_device + + echo "done..." +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ]; then + FAN_TRAY=1 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=1 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ]; then + FAN_TRAY=2 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=2 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ]; then + FAN_TRAY=3 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=3 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + FAN_TRAY=4 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=4 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + fi +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C LED TEST..." + echo "=========================================================" + #sys led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x7F + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xBF + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xF7 + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFB + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xDF + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xEF + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFD + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFE + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + _pause 'Check turn off all LEDs and Press [Enter] key to continue...' + echo "done..." +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + local port=$1 + case ${port} in + 1|2|3|4|5|6|7|8) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x20 + dataAddr=0 + eeprombusbase=${NUM_MUX3_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+240)) + #gpioBase=240 + ;; + 9|10|11|12|13|14|15|16) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x20 + dataAddr=1 + eeprombusbase=${NUM_MUX4_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+240)) + #gpioBase=240 + ;; + 17|18|19|20|21|22|23|24) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x21 + dataAddr=0 + eeprombusbase=${NUM_MUX5_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+224-16)) + #gpioBase=$((224 - 16)) + ;; + 25|26|27|28|29|30|31|32) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x21 + dataAddr=1 + eeprombusbase=${NUM_MUX6_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+224-16)) + #gpioBase=$((224 - 16)) + ;; + #33) + # i2cbus=${NUM_MUX1_CHAN7_DEVICE} + # regAddr=0x22 + # dataAddr=0 + # gpioBase=${GPIO_OFFSET} + #;; + #34) + # i2cbus=${NUM_MUX1_CHAN7_DEVICE} + # regAddr=0x22 + # dataAddr=1 + # gpioBase=${GPIO_OFFSET} + #;; + *) + echo "Please input 1~32" + exit + ;; + esac +} + +#Set QSFP Port variable +function _qsfp_eeprom_var_set { + local port=$1 + eeprombusidx=$(( ${port} % 8)) + case $eeprombusidx in + 1) + eeprombus=$(( $eeprombusbase + 1 )) + eepromAddr=0x50 + ;; + 2) + eeprombus=$(( $eeprombusbase + 0 )) + eepromAddr=0x50 + ;; + 3) + eeprombus=$(( $eeprombusbase + 3 )) + eepromAddr=0x50 + ;; + 4) + eeprombus=$(( $eeprombusbase + 2 )) + eepromAddr=0x50 + ;; + 5) + eeprombus=$(( $eeprombusbase + 5 )) + eepromAddr=0x50 + ;; + 6) + eeprombus=$(( $eeprombusbase + 4 )) + eepromAddr=0x50 + ;; + 7) + eeprombus=$(( $eeprombusbase + 7 )) + eepromAddr=0x50 + ;; + 0) + eeprombus=$(( $eeprombusbase + 6 )) + eepromAddr=0x50 + ;; + esac +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) ^ 1)) ))/value` + echo $status + + if [ $status = 0 ]; then + exit + fi + + _qsfp_eeprom_var_set ${QSFP_PORT} + + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo -n "QSFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-32 ports EEPROM + local i + for i in {1..32}; + do + _qsfp_port_i2c_var_set ${i} + + _qsfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/delete_device + fi + done + echo "DONE" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + echo -n "Main Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-32 ports EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN7_DEVICE}-0054 ]; then + echo "mb_eeprom 0x54" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN7_DEVICE}-0054 ]; then + echo "0x54" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}/delete_device + fi + echo "DONE" +} + +#PSU EEPROM init +function _i2c_psu_eeprom_init { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Init..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom + ## PUS(0) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN6_DEVICE}/new_device + + ## PUS(1) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}/new_device + + echo "done..." +} + +#get QSFP Status +function _i2c_qsfp_status_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) ^ 1)) ))/value` + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + _qsfp_eeprom_var_set ${QSFP_PORT} + + #Get QSFP EEPROM info + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom + ## PUS(0) EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN6_DEVICE}-0050/eeprom | hexdump -C + + ## PUS(1) EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN7_DEVICE}-0050/eeprom | hexdump -C + + echo "done..." +} + +#Get MotherBoard EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN7_DEVICE}-0054/eeprom | hexdump -C + echo "done..." +} + +#Set System Status LED +function _i2c_sys_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x80 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x80 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x40 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x40 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU2 LED +function _i2c_psu2_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x20 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x20 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x10 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x10 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + case ${FAN_TRAY} in + 1) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN7_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN7_DEVICE} $i2cAddr $ioPort 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN7_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN7_DEVICE} $i2cAddr $ioPort 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x08 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x08 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x04 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x04 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU1 LED +function _i2c_psu1_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x02 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x02 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x01 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x01 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Get Board Version and Type +function _i2c_board_type_get { + boardType=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_board_type` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BOARD_ID is 0x%02x, HW Rev %d, Build Rev %d\n" $boardId $boardHwRev $boardBuildRev + +} + +#Get CPLD Version +function _i2c_cpld_version { + cpldRev=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_version` + cpldRelease=$((($cpldRev) >> 6 & 0x01)) + cpldVersion=$((($cpldRev) & 0x3F)) + printf "CPLD is %s version(0:RD 1:Release), Revision is 0x%02x\n" $cpldRelease $cpldVersion + +} + +#Get PSU Status +function _i2c_psu_status { + psuPresent=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_pw_abs` + psu1Exist=$(($((($psuPresent) & 0x01))?0:1)) + psu2Exist=$(($((($psuPresent) & 0x02))?0:1)) + psuPwGood=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_pw_good` + psu1PwGood=$(($((($psuPwGood) >> 3 & 0x01))?1:0)) + psu2PwGood=$(($((($psuPwGood) >> 3 & 0x02))?1:0)) + printf "PSU1 Exist:%d PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Get Front Sensor Temperature +function _i2c_front_temp { + #Front MAC + sensors | grep 'Front MAC Temp' -A 1 +} + +#Get Rear Sensor Temperature +function _i2c_rear_temp { + #Rear MAC + sensors | grep 'Rear MAC Temp' -A 1 +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Main Function +function _main { + tart_time_str=`date` + start_time_sec=$(date +%s) + + _set_gpio_offset + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_fan_init" ]; then + _i2c_fan_init + elif [ "${EXEC_FUNC}" == "i2c_volmon_init" ]; then + _i2c_volmon_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_init" ]; then + _i2c_gpio_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_deinit" ]; then + _i2c_gpio_deinit + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_front_temp" ]; then + _i2c_front_temp + elif [ "${EXEC_FUNC}" == "i2c_rear_temp" ]; then + _i2c_rear_temp + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_temp_init + _i2c_fan_init + _i2c_io_exp_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_board_type_get + _i2c_cpld_version + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_monitor.sh new file mode 100755 index 000000000000..249f179216a6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_monitor.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, 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 . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..31}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_si_cfg.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_si_cfg.sh new file mode 100755 index 000000000000..f2bf35bc7715 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_si_cfg.sh @@ -0,0 +1,339 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, 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 . + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +TYPE=${1} +PORT=${2} + +#QSFP Optical +function _qsfp_optical_si_set { + case ${PORT} in + 0) + bcmcmd "phy ce0 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x39;phy ce0 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x37;phy ce0 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce0 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x39" + bcmcmd "phy ce0 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x37;phy ce0 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce0 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x35;phy ce0 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x37" + bcmcmd "phy ce0 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce0 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce0 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce0 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + ;; + 1) + bcmcmd "phy ce1 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x3E;phy ce1 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x32;phy ce1 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce1 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x38" + bcmcmd "phy ce1 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x38;phy ce1 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xE AMS_TX_DRIVERMODE=0x0;phy ce1 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x33;phy ce1 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3D" + bcmcmd "phy ce1 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce1 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x35;phy ce1 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x3B;phy ce1 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xE AMS_TX_DRIVERMODE=0x0" + ;; + 2) + bcmcmd "phy ce2 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x35;phy ce2 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x3B;phy ce2 AMS_TX_CTL2r AMS_TX_AMP_CTL=0xB AMS_TX_DRIVERMODE=0x0" + ;; + 3) + bcmcmd "phy ce3 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x3B;phy ce3 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x35;phy ce3 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce3 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x35" + bcmcmd "phy ce3 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x37;phy ce3 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0;phy ce3 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x35;phy ce3 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x37" + bcmcmd "phy ce3 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xB AMS_TX_DRIVERMODE=0x0;phy ce3 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x35;phy ce3 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x37;phy ce3 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xB AMS_TX_DRIVERMODE=0x0" + ;; + 4) + bcmcmd "phy ce4 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce4 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce4 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce4 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x33" + bcmcmd "phy ce4 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3D;phy ce4 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce4 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce4 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce4 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce4 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce4 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce4 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 5) + bcmcmd "phy ce5 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce5 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce5 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce5 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x35" + bcmcmd "phy ce5 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3B;phy ce5 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce5 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce5 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce5 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce5 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce5 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce5 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 6) + bcmcmd "phy ce6 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce6 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce6 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce6 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x36" + bcmcmd "phy ce6 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3A;phy ce6 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0;phy ce6 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce6 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce6 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce6 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce6 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce6 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 7) + bcmcmd "phy ce7 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce7 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce7 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce7 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30" + bcmcmd "phy ce7 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce7 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce7 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce7 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce7 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce7 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce7 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce7 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 8) + bcmcmd "phy ce8 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce8 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce8 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce8 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x2C" + bcmcmd "phy ce8 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x44;phy ce8 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce8 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x25;phy ce8 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x4B" + bcmcmd "phy ce8 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce8 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x25;phy ce8 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x4B;phy ce8 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 9) + bcmcmd "phy ce9 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce9 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce9 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce9 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x2B" + bcmcmd "phy ce9 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x45;phy ce9 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce9 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x25;phy ce9 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x4B" + bcmcmd "phy ce9 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce9 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x25;phy ce9 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x4B;phy ce9 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 10) + bcmcmd "phy ce10 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce10 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce10 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce10 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x2B" + bcmcmd "phy ce10 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x45;phy ce10 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0;phy ce10 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x25;phy ce10 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x4B" + bcmcmd "phy ce10 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce10 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x25;phy ce10 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x4B;phy ce10 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 11) + bcmcmd "phy ce11 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce11 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce11 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce11 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x2C" + bcmcmd "phy ce11 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x44;phy ce11 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce11 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x25;phy ce11 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x4B" + bcmcmd "phy ce11 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce11 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x25;phy ce11 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x4B;phy ce11 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 12) + bcmcmd "phy ce12 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce12 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce12 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce12 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x25" + bcmcmd "phy ce12 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x4B;phy ce12 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x5 AMS_TX_DRIVERMODE=0x0;phy ce12 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x25;phy ce12 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x4B" + bcmcmd "phy ce12 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce12 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x25;phy ce12 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x4B;phy ce12 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 13) + bcmcmd "phy ce13 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x25;phy ce13 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x4B;phy ce13 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 14) + bcmcmd "phy ce14 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x25;phy ce14 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x4B;phy ce14 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0" + ;; + 15) + bcmcmd "phy ce15 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce15 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce15 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0;phy ce15 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x25" + bcmcmd "phy ce15 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x4B;phy ce15 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x5 AMS_TX_DRIVERMODE=0x0;phy ce15 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x25;phy ce15 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x4B" + bcmcmd "phy ce15 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0;phy ce15 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x25;phy ce15 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x4B;phy ce15 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0" + ;; + 16) + bcmcmd "phy ce16 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x27;phy ce16 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x49;phy ce16 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0" + ;; + 17) + bcmcmd "phy ce17 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce17 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce17 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce17 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30" + bcmcmd "phy ce17 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce17 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce17 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce17 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce17 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce17 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce17 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40;phy ce17 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + ;; + 18) + bcmcmd "phy ce18 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x20;phy ce18 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x50;phy ce18 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x2 AMS_TX_DRIVERMODE=0x0" + ;; + 19) + bcmcmd "phy ce19 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x20;phy ce19 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x50;phy ce19 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x2 AMS_TX_DRIVERMODE=0x0" + ;; + 20) + bcmcmd "phy ce20 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x20;phy ce20 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x50;phy ce20 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x2 AMS_TX_DRIVERMODE=0x0" + ;; + 21) + bcmcmd "phy ce21 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x17;phy ce21 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x59;phy ce21 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0;phy ce21 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x17" + bcmcmd "phy ce21 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x59;phy ce21 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x2 AMS_TX_DRIVERMODE=0x0;phy ce21 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x20;phy ce21 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x50" + bcmcmd "phy ce21 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x2 AMS_TX_DRIVERMODE=0x0;phy ce21 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x20;phy ce21 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x50;phy ce21 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x2 AMS_TX_DRIVERMODE=0x0" + ;; + 22) + bcmcmd "phy ce22 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x25;phy ce22 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x4B;phy ce22 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0" + ;; + 23) + bcmcmd "phy ce23 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x25;phy ce23 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x4B;phy ce23 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0" + ;; + 24) + bcmcmd "phy ce24 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x23;phy ce24 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4D;phy ce24 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce24 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x29" + bcmcmd "phy ce24 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x47;phy ce24 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce24 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x29;phy ce24 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x47" + bcmcmd "phy ce24 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0;phy ce24 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x29;phy ce24 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x47;phy ce24 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0" + ;; + 25) + bcmcmd "phy ce25 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x29;phy ce25 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x47;phy ce25 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce25 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x29" + bcmcmd "phy ce25 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x47;phy ce25 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce25 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x29;phy ce25 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x47" + bcmcmd "phy ce25 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0;phy ce25 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x29;phy ce25 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x47;phy ce25 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0" + ;; + 26) + bcmcmd "phy ce26 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x30;phy ce26 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x40;phy ce26 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + ;; + 27) + bcmcmd "phy ce27 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce27 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce27 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce27 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30" + bcmcmd "phy ce27 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce27 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce27 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce27 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce27 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xB AMS_TX_DRIVERMODE=0x0;phy ce27 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce27 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce27 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + ;; + 28) + bcmcmd "phy ce28 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce28 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce28 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce28 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30" + bcmcmd "phy ce28 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce28 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce28 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce28 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce28 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce28 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce28 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce28 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + ;; + 29) + bcmcmd "phy ce29 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce29 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce29 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce29 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30" + bcmcmd "phy ce29 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce29 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce29 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce29 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce29 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce29 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce29 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce29 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + ;; + 30) + bcmcmd "phy ce30 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce30 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce30 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce30 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30" + bcmcmd "phy ce30 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce30 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce30 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce30 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce30 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce30 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce30 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce30 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 31) + bcmcmd "phy ce31 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x39;phy ce31 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x37;phy ce31 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0;phy ce31 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x39" + bcmcmd "phy ce31 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x37;phy ce31 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0;phy ce31 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce31 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce31 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce31 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce31 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce31 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + *) + echo "Unknown Port" + return + ;; + esac +} + +function _qsfp_dac_si_set { + case ${PORT} in + 0) + bcmcmd "phy ce0 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce0 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce0 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce0 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce0 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x1C;phy ce0 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x20;phy ce0 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x34;phy ce0 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce0 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce0 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce0 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce0 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce0 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x18;phy ce0 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x24;phy ce0 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x34;phy ce0 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + ;; + 1) + bcmcmd "phy ce1 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce1 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce1 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce1 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce1 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x1C;phy ce1 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x20;phy ce1 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x34;phy ce1 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce1 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce1 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce1 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce1 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce1 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x1C;phy ce1 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x20;phy ce1 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x34;phy ce1 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + ;; + 2) + bcmcmd "phy ce2 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce2 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce2 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce2 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce2 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x18;phy ce2 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x24;phy ce2 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x34;phy ce2 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xD AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce2 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce2 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce2 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce2 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce2 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x14;phy ce2 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x20;phy ce2 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x3C;phy ce2 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xD AMS_TX_DRIVERMODE=0x0" + ;; + 3) + bcmcmd "phy ce3 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce3 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce3 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce3 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce3 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x14;phy ce3 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x20;phy ce3 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3C;phy ce3 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xD AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce3 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce3 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce3 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce3 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce3 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x18;phy ce3 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x24;phy ce3 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x34;phy ce3 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xD AMS_TX_DRIVERMODE=0x0" + ;; + 4) + bcmcmd "phy ce4 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce4 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce4 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce4 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce4 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce4 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x33;phy ce4 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3D;phy ce4 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xB AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce4 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce4 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce4 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce4 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce4 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce4 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce4 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce4 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 5) + bcmcmd "phy ce5 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce5 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce5 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce5 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce5 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce5 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30;phy ce5 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce5 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xB AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce5 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce5 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce5 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce5 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce5 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce5 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce5 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce5 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 6) + bcmcmd "phy ce6 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce6 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce6 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce6 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce6 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce6 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x36;phy ce6 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3A;phy ce6 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce6 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce6 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce6 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce6 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce6 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce6 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce6 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce6 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 7) + bcmcmd "phy ce7 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce7 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce7 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce7 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce7 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce7 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30;phy ce7 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce7 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce7 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce7 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce7 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce7 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce7 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce7 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce7 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce7 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 8) + ;; + 9) + ;; + 10) + ;; + 11) + ;; + 12) + ;; + 13) + ;; + 14) + ;; + 15) + ;; + 16) + ;; + 17) + ;; + 18) + ;; + 19) + ;; + 20) + ;; + 21) + ;; + 22) + ;; + 23) + ;; + 24) + bcmcmd "phy ce24 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce24 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce24 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce24 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce24 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce24 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x29;phy ce24 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x47;phy ce24 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce24 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0X1F;phy ce24 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce24 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce24 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce24 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce24 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x29;phy ce24 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x47;phy ce24 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0" + ;; + 25) + bcmcmd "phy ce25 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce25 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce25 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce25 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce25 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce25 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x29;phy ce25 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x47;phy ce25 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce25 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce25 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce25 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce25 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce25 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce25 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x29;phy ce25 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x47;phy ce25 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0" + ;; + 26) + bcmcmd "phy ce26 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce26 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce26 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce26 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce26 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce26 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30;phy ce26 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce26 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce26 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce26 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce26 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce26 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce26 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce26 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce26 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce26 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + ;; + 27) + bcmcmd "phy ce27 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce27 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce27 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce27 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce27 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce27 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30;phy ce27 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce27 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce27 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce27 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce27 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce27 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce27 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce27 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce27 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce27 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + ;; + 28) + bcmcmd "phy ce28 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce28 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce28 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce28 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce28 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x10;phy ce28 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x18;phy ce28 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3C;phy ce28 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce28 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce28 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce28 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce28 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce28 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x10;phy ce28 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x1C;phy ce28 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x3C;phy ce28 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + ;; + 29) + bcmcmd "phy ce29 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce29 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce29 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce29 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce29 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x10;phy ce29 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x20;phy ce29 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3C;phy ce29 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce29 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce29 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce29 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce29 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce29 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x10;phy ce29 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x20;phy ce29 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x3C;phy ce29 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + ;; + 30) + bcmcmd "phy ce30 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce30 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce30 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce30 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce30 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x10;phy ce30 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x24;phy ce30 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3C;phy ce30 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce30 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce30 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce30 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce30 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce30 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x8;phy ce30 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x24;phy ce30 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x3C;phy ce30 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + ;; + 31) + bcmcmd "phy ce31 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce31 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce31 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce31 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce31 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x10;phy ce31 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x24;phy ce31 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3C;phy ce31 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce31 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce31 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce31 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce31 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce31 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x14;phy ce31 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x20;phy ce31 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x3C;phy ce31 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xE AMS_TX_DRIVERMODE=0x0" + ;; + *) + echo "Unknown Port" + return + ;; + esac +} + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} optical [0-31]" + echo " : ${0} dac [0-31]" + echo "----------------------------------------------------" +} + +#Main Function +function _main { + + if [ "${TYPE}" == "help" ]; then + _help + elif [ "${TYPE}" == "optical" ]; then + _qsfp_optical_si_set + elif [ "${TYPE}" == "dac" ]; then + _qsfp_dac_si_set + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/s9100_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/s9100_monitor.sh new file mode 100755 index 000000000000..974da6d5001f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/s9100_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, 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 . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/README.md b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/README.md new file mode 100644 index 000000000000..940d15f497c9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/README.md @@ -0,0 +1,184 @@ +# Ingrasys S9200-64X Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, 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 . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S9200-64X is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S9200-64X platform. + +### I2C i801 + +The I2C i801 on Ingrasys S9200-64X can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S9200-64X. + +### I2C iSMT + +The I2C iSMT module on S9200-64X can be found in +`/sys/bus/i2c/devices/i2c-1/` + +This is I2C bus for CPLD, HWM, power controller and I2C Switches. + +The i801 module must be loaded third on Ingrasys S9200-64X. + +### I2C PCA9548 +The PCA9548 module on S9200-64X can be found in +`/sys/bus/i2c/devices/i2c-2/` , `/sys/bus/i2c/devices/i2c-3/`, +`/sys/bus/i2c/devices/i2c-4/`, `/sys/bus/i2c/devices/i2c-5/`, +`/sys/bus/i2c/devices/i2c-6/`, `/sys/bus/i2c/devices/i2c-7/`, +`/sys/bus/i2c/devices/i2c-8/`, `/sys/bus/i2c/devices/i2c-9/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S9200-64X. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S9200-64X platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s9200-64x package is installed on the S9200-64X, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-9/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/9-0054/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon5/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm2` setting fan1/fan3/fan5/fan7. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon5/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-64] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-64] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/Makefile b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/Makefile new file mode 100755 index 000000000000..1a9e4e314e8e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m := eeprom_mb.o +obj-m += cpld.o +obj-m += ingrasys_s9200_64x_psu.o diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/cpld.c b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/cpld.c new file mode 100755 index 000000000000..7b16f5d3e321 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/cpld.c @@ -0,0 +1,498 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define S9200_MUX_BASE_NR 0 +#define CPLD_DEVICE_NUM 5 + +/* CPLD registers */ +#define CPLD_REG_REV 0x01 +#define CPLD_REG_ID 0x02 +#define CPLD_REG_10G_MUX 0x41 + +/* QSFP signal bit in register */ +#define BIT_RST 0 +#define BIT_LPM 2 +#define BIT_INT 0 +#define BIT_ABS 1 + +static void device_release(struct device *dev) +{ + return; +} + +/* + * S9200 CPLD register addresses + */ +static const int int_abs_reg[CPLD_DEVICE_NUM][2]= { + {0x20, 0x2B}, + {0x20, 0x2C}, + {0x20, 0x2C}, + {0x20, 0x2C}, + {0x20, 0x2C} +}; + +static const int rst_lp_reg[CPLD_DEVICE_NUM][2]= { + {0x30, 0x3B}, + {0x30, 0x3C}, + {0x30, 0x3C}, + {0x30, 0x3C}, + {0x30, 0x3C} +}; + +/* + * S9200 CPLD + */ + +enum cpld_type { + cpld_1, + cpld_2, + cpld_3, + cpld_4, + cpld_5, +}; + +enum qsfp_signal { + sig_int, + sig_abs, + sig_rst, + sig_lpm +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +static struct cpld_platform_data s9200_cpld_platform_data[] = { + [cpld_1] = { + .reg_addr = 0x33, + }, + + [cpld_2] = { + .reg_addr = 0x33, + }, + + [cpld_3] = { + .reg_addr = 0x33, + }, + + [cpld_4] = { + .reg_addr = 0x33, + }, + + [cpld_5] = { + .reg_addr = 0x33, + }, +}; + +static struct platform_device s9200_cpld = { + .name = "ingrasys-s9200-cpld", + .id = 0, + .dev = { + .platform_data = s9200_cpld_platform_data, + .release = device_release + }, +}; + +/* + * S9200 I2C DEVICES + */ + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; + +/* module_platform_driver */ +static ssize_t get_cpld_reg(struct device *dev, struct device_attribute *devattr, char *buf, int signal) +{ + int ret; + u64 data = 0; + u64 shift = 0; + int i = 0; + int j = 0; + int port = 0; + int bit = 0; + int bit_mask = 0; + int (*reg)[CPLD_DEVICE_NUM][2]; + struct cpld_platform_data *pdata = NULL; + + pdata = dev->platform_data; + + switch(signal) { + case sig_int: + bit = BIT_INT; + reg = (typeof(reg)) &int_abs_reg; + break; + case sig_abs: + bit = BIT_ABS; + reg = (typeof(reg)) &int_abs_reg; + break; + case sig_rst: + bit = BIT_RST; + reg = (typeof(reg)) &rst_lp_reg; + break; + case sig_lpm: + bit = BIT_LPM; + reg = (typeof(reg)) &rst_lp_reg; + break; + default: + return sprintf(buf, "na"); + } + bit_mask = 0x1 << bit; + + for (i=0; i> bit)) << port; + data |= shift; + port++; + } + } + + return sprintf(buf, "0x%016llx\n", data); +} + +static ssize_t set_cpld_reg(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count, int signal) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + u8 current_reg_val = 0; + u8 new_reg_val = 0; + int value; + int i = 0; + int j = 0; + int port = 0; + int ret = 0; + int bit = 0; + int (*reg)[CPLD_DEVICE_NUM][2]; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + switch(signal) { + case sig_int: + bit = BIT_INT; + reg = (typeof(reg)) &int_abs_reg; + break; + case sig_abs: + bit = BIT_ABS; + reg = (typeof(reg)) &int_abs_reg; + break; + case sig_rst: + bit = BIT_RST; + reg = (typeof(reg)) &rst_lp_reg; + break; + case sig_lpm: + bit = BIT_LPM; + reg = (typeof(reg)) &rst_lp_reg; + break; + default: + return sprintf(buf, "na"); + } + + for (i=0; i> port) & 0x1; + + //set value on bit N of new_reg_val + if (value > 0) { + new_reg_val = current_reg_val | (u8) (0x1 << bit); + } else { + new_reg_val = current_reg_val & (u8) ~(0x1 << bit); + } + //write reg value if changed + if (current_reg_val != new_reg_val) { + ret = i2c_smbus_write_byte_data(pdata[i].client, j, + (u8)(new_reg_val)); + if (ret < 0){ + return ret; + } + } + port++; + } + } + + return count; +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf) +{ + return get_cpld_reg(dev, devattr, buf, sig_lpm); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + return set_cpld_reg(dev, devattr, buf, count, sig_lpm); +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + return get_cpld_reg(dev, devattr, buf, sig_rst); +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + return set_cpld_reg(dev, devattr, buf, count, sig_rst); +} + +static ssize_t get_modprs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + return get_cpld_reg(dev, devattr, buf, sig_abs); +} + +static ssize_t get_int(struct device *dev, struct device_attribute *devattr, char *buf) +{ + return get_cpld_reg(dev, devattr, buf, sig_int); +} + +static ssize_t get_cpld_version(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int i = 0; + int cnt = 0; + u8 reg_val_rev[CPLD_DEVICE_NUM]; + u8 reg_val_id[CPLD_DEVICE_NUM]; + + struct cpld_platform_data *pdata = dev->platform_data; + + //get reg value + for (i=0; i> 6 & 0x1, + reg_val_id[i] & 0x7); + } + + return cnt; +} + +static ssize_t set_10g_mux(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + u8 data; + u8 current_reg_val = 0; + u8 new_reg_val = 0; + int cpld_dev_num=cpld_1; + int reg_offset=CPLD_REG_10G_MUX; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + int value; + int i = 0; + int port = 0; + int ret = 0; + int bit = 0; + + err = kstrtou8(buf, 16, &new_reg_val); + if (err) + return err; + + //read reg value + current_reg_val = i2c_smbus_read_byte_data(pdata[cpld_dev_num].client, reg_offset); + if (current_reg_val < 0) { + return current_reg_val; + } + + //write reg value if changed + if (current_reg_val != new_reg_val) { + ret = i2c_smbus_write_byte_data(pdata[cpld_dev_num].client, reg_offset, + (u8)(new_reg_val)); + if (ret < 0){ + return ret; + } + } + + return count; +} + +static ssize_t get_10g_mux(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int cpld_dev_num=cpld_1; + int reg_offset=CPLD_REG_10G_MUX; + u8 reg_val=0; + struct cpld_platform_data *pdata = dev->platform_data; + + //read 10G mux register + reg_val = i2c_smbus_read_byte_data(pdata[cpld_dev_num].client, reg_offset); + if (reg_val < 0) { + return sprintf(buf, "na"); + } + + return sprintf(buf, "0x%x\n", reg_val); +} + +static DEVICE_ATTR(qsfp_int, S_IRUGO, get_int, NULL); +static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL); +static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode); +static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset); +static DEVICE_ATTR(cpld_version, S_IRUGO, get_cpld_version, NULL); +static DEVICE_ATTR(cpld_10g_mux, S_IRUGO | S_IWUSR, get_10g_mux, set_10g_mux); + +static struct attribute *s9200_cpld_attrs[] = { + &dev_attr_qsfp_int.attr, + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_cpld_version.attr, + &dev_attr_cpld_10g_mux.attr, + NULL, +}; + +static struct attribute_group s9200_cpld_attr_grp = { + .attrs = s9200_cpld_attrs, +}; + +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent[CPLD_DEVICE_NUM]; + int i; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + parent[i] = i2c_get_adapter(S9200_MUX_BASE_NR + i + 1); + if (!parent[i]) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", + S9200_MUX_BASE_NR + i + 1); + return -ENODEV; + } + pdata[i].client = i2c_new_dummy(parent[i], pdata[i].reg_addr); + if (!pdata[i].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[i].reg_addr); + goto error; + } + } + + ret = sysfs_create_group(&pdev->dev.kobj, &s9200_cpld_attr_grp); + if (ret) + goto error; + + return 0; + +error: + i2c_put_adapter(parent[i]); + i--; + for (; i >= 0; i--) { + if (pdata[i].client) { + i2c_unregister_device(pdata[i].client); + i2c_put_adapter(parent[i]); + } + } + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + int i; + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + + sysfs_remove_group(&pdev->dev.kobj, &s9200_cpld_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } else { + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + if (pdata[i].client) { + parent = (pdata[i].client)->adapter; + i2c_unregister_device(pdata[i].client); + i2c_put_adapter(parent); + } + } + } + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "ingrasys-s9200-cpld", + }, +}; + +static int __init ingrasys_s9200_platform_init(void) +{ + int ret = 0; + + printk("ingrasysl_s9200_platform module initialization\n"); + + mdelay(10000); + + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpld driver\n"); + goto error_cpld_driver; + } + ret = platform_device_register(&s9200_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpld device\n"); + goto error_cpld; + } + + return 0; + +error_cpld: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +} + +static void __exit ingrasys_s9200_platform_exit(void) +{ + platform_device_unregister(&s9200_cpld); + platform_driver_unregister(&cpld_driver); +} + +module_init(ingrasys_s9200_platform_init); +module_exit(ingrasys_s9200_platform_exit); + +MODULE_DESCRIPTION("Ingrasys S9200 Platform Support"); +MODULE_AUTHOR("Jason Tsai "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/eeprom_mb.c b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/eeprom_mb.c new file mode 100755 index 000000000000..1cdb26658f5a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/eeprom_mb.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +/* enable dev_dbg print out */ +//#define DEBUG + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { /*0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57,*/ I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 512 + +#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 mb_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 mb_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++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static ssize_t mb_eeprom_write(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); + int ret; + int i; + u8 cmd; + u16 value16; + + dev_dbg(&client->dev, "mb_eeprom_write off=%d, count=%d\n", (int)off, (int)count); + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + mutex_lock(&data->update_lock); + + for(i=0; i < count; i++) { + /* write command */ + cmd = (off >> 8) & 0xff; + value16 = off & 0xff; + value16 |= buf[i] << 8; + ret = i2c_smbus_write_word_data(client, cmd, value16); + + if (ret < 0) { + dev_err(&client->dev, "write address failed at %d \n", (int)off); + goto exit; + } + + off++; + + /* need to wait for write complete */ + udelay(10000); + } +exit: + mutex_unlock(&data->update_lock); + /* force to update client when reading */ + for(i=0; i < SLICE_NUM; i++) { + data->last_updated[i] = 0; + } + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO | S_IWUSR, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, + .write = mb_eeprom_write, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x51 and 0x55. So decline + attaching to addresses >= 0x56 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x56) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_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, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys Mother Board EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/ingrasys_s9200_64x_platform.h b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/ingrasys_s9200_64x_platform.h new file mode 100644 index 000000000000..8a38965e7932 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/ingrasys_s9200_64x_platform.h @@ -0,0 +1,148 @@ +#ifndef _S9200_64X_PLATFORM_H +#define _S9200_64X_PLATFORM_H + +#include + +// remove debug before release +#define DEBUG + +enum bus_order { + I2C_BUS_MAIN, + MUX_9548_0_CH0, + MUX_9548_0_CH1, + MUX_9548_0_CH2, + MUX_9548_0_CH3, + MUX_9548_0_CH4, + MUX_9548_0_CH5, + MUX_9548_0_CH6, + MUX_9548_0_CH7, + MUX_9548_1_CH0, + MUX_9548_1_CH1, + MUX_9548_1_CH2, + MUX_9548_1_CH3, + MUX_9548_1_CH4, + MUX_9548_1_CH5, + MUX_9548_1_CH6, + MUX_9548_1_CH7, + MUX_9546_0_CH0, + MUX_9546_0_CH1, + MUX_9546_0_CH2, + MUX_9546_0_CH3, + MUX_9546_1_CH0, + MUX_9546_1_CH1, + MUX_9546_1_CH2, + MUX_9546_1_CH3, + MUX_9548_2_CH0, + MUX_9548_2_CH1, + MUX_9548_2_CH2, + MUX_9548_2_CH3, + MUX_9548_2_CH4, + MUX_9548_2_CH5, + MUX_9548_2_CH6, + MUX_9548_2_CH7, + MUX_9548_3_CH0, + MUX_9548_3_CH1, + MUX_9548_3_CH2, + MUX_9548_3_CH3, + MUX_9548_3_CH4, + MUX_9548_3_CH5, + MUX_9548_3_CH6, + MUX_9548_3_CH7, + MUX_9548_4_CH0, + MUX_9548_4_CH1, + MUX_9548_4_CH2, + MUX_9548_4_CH3, + MUX_9548_4_CH4, + MUX_9548_4_CH5, + MUX_9548_4_CH6, + MUX_9548_4_CH7, + MUX_9548_5_CH0, + MUX_9548_5_CH1, + MUX_9548_5_CH2, + MUX_9548_5_CH3, + MUX_9548_5_CH4, + MUX_9548_5_CH5, + MUX_9548_5_CH6, + MUX_9548_5_CH7, + MUX_9548_6_CH0, + MUX_9548_6_CH1, + MUX_9548_6_CH2, + MUX_9548_6_CH3, + MUX_9548_6_CH4, + MUX_9548_6_CH5, + MUX_9548_6_CH6, + MUX_9548_6_CH7, + MUX_9548_7_CH0, + MUX_9548_7_CH1, + MUX_9548_7_CH2, + MUX_9548_7_CH3, + MUX_9548_7_CH4, + MUX_9548_7_CH5, + MUX_9548_7_CH6, + MUX_9548_7_CH7, + MUX_9548_8_CH0, + MUX_9548_8_CH1, + MUX_9548_8_CH2, + MUX_9548_8_CH3, + MUX_9548_8_CH4, + MUX_9548_8_CH5, + MUX_9548_8_CH6, + MUX_9548_8_CH7, + MUX_9548_9_CH0, + MUX_9548_9_CH1, + MUX_9548_9_CH2, + MUX_9548_9_CH3, + MUX_9548_9_CH4, + MUX_9548_9_CH5, + MUX_9548_9_CH6, + MUX_9548_9_CH7, + MUX_9548_10_CH0, + MUX_9548_10_CH1, + MUX_9548_10_CH2, + MUX_9548_10_CH3, + MUX_9548_10_CH4, + MUX_9548_10_CH5, + MUX_9548_10_CH6, + MUX_9548_10_CH7, +}; + +#define I2C_ADDR_MUX_9555_0 (0x20) +#define I2C_ADDR_MUX_9555_1 (0x24) +#define I2C_ADDR_MUX_9555_2 (0x25) +#define I2C_ADDR_MUX_9555_3 (0x26) +#define I2C_ADDR_MUX_9539_0 (0x76) +#define I2C_ADDR_MUX_9539_1 (0x76) +#define I2C_BUS_FAN_STATUS (I2C_BUS_MAIN) +#define I2C_BUS_SYS_LED (MUX_9548_1_CH1) + +#define NUM_OF_I2C_MUX (11) +#define NUM_OF_CPLD (5) +#define NUM_OF_QSFP_PORT (64) +#define NUM_OF_SFP_PORT (2) +#define QSFP_EEPROM_I2C_ADDR (0x50) + +enum gpio_reg { + REG_PORT0_IN, + REG_PORT1_IN, + REG_PORT0_OUT, + REG_PORT1_OUT, + REG_PORT0_POL, + REG_PORT1_POL, + REG_PORT0_DIR, + REG_PORT1_DIR, +}; + +struct ing_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +struct i2c_init_data { + __u16 ch; + __u16 addr; + __u8 reg; + __u8 value; +}; + +#endif diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/ingrasys_s9200_64x_psu.c b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/ingrasys_s9200_64x_psu.c new file mode 100644 index 000000000000..46642f1271ca --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/ingrasys_s9200_64x_psu.c @@ -0,0 +1,389 @@ +/* + * S9200-64X PSU driver + * + * Copyright (C) 2017 Ingrasys, 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 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s9200_64x_platform.h" + +static ssize_t show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf); +static struct s9200_psu_data *s9200_psu_update_status(struct device *dev); +static struct s9200_psu_data *s9200_psu_update_eeprom(struct device *dev); +static int s9200_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len); + + +#define DRIVER_NAME "psu" + +// Addresses scanned +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* PSU EEPROM SIZE */ +#define EEPROM_SZ 256 +#define READ_EEPROM 1 +#define NREAD_EEPROM 0 + +static struct i2c_client pca9555_client; + +/* pca9555 gpio pin mapping */ +#define PSU2_PWROK 0 +#define PSU2_PRSNT_L 1 +#define PSU2_PWRON_L 2 +#define PSU1_PWROK 3 +#define PSU1_PRSNT_L 4 +#define PSU1_PWRON_L 5 +#define TMP_75_INT_L 6 + +/* Driver Private Data */ +struct s9200_psu_data { + struct mutex lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + s32 status; /* IO expander value */ + char eeprom[EEPROM_SZ]; /* psu eeprom data */ + char psuABS; /* PSU absent */ + char psuPG; /* PSU power good */ +}; + +enum psu_index +{ + s9200_psu1, + s9200_psu2 +}; + +/* + * display power good attribute + */ +static ssize_t +show_psu_pg(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9200_psu_data *data = s9200_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuPG; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + +/* + * display power absent attribute + */ +static ssize_t +show_psu_abs(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9200_psu_data *data = s9200_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuABS; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + + +/* + * sysfs attributes for psu + */ +static DEVICE_ATTR(psu_pg, S_IRUGO, show_psu_pg, NULL); +static DEVICE_ATTR(psu_abs, S_IRUGO, show_psu_abs, NULL); +static DEVICE_ATTR(psu_eeprom, S_IRUGO, show_psu_eeprom, NULL); + +static struct attribute *s9200_psu_attributes[] = { + &dev_attr_psu_pg.attr, + &dev_attr_psu_abs.attr, + &dev_attr_psu_eeprom.attr, + NULL +}; + +/* + * display psu eeprom content + */ +static ssize_t +show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct s9200_psu_data *data = s9200_psu_update_eeprom(dev); + + memcpy(buf, (char *)data->eeprom, EEPROM_SZ); + return EEPROM_SZ; +} + +static const struct attribute_group s9200_psu_group = { + .attrs = s9200_psu_attributes, +}; + +/* + * check gpio expander is accessible + */ +static int +pca9555_detect(struct i2c_client *client) +{ + if (i2c_smbus_read_byte_data(client, REG_PORT0_DIR) < 0) { + return -ENODEV; + } + + return 0; +} + +/* + * client address init + */ +static void +i2c_devices_client_address_init(struct i2c_client *client) +{ + pca9555_client = *client; + pca9555_client.addr = 0x25; +} + +static int +s9200_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct s9200_psu_data *data; + int status, err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct s9200_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct s9200_psu_data)); + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + i2c_devices_client_address_init(client); + + err = pca9555_detect(&pca9555_client); + if (err) { + dev_info(&client->dev, "pca9555_detect failed\n"); + return err; + } + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &s9200_psu_group); + if (status) { + goto exit_free; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &s9200_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int +s9200_psu_remove(struct i2c_client *client) +{ + struct s9200_psu_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &s9200_psu_group); + kfree(data); + + return 0; +} + + +/* + * psu eeprom read utility + */ +static int +s9200_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len) +{ + int i=0, ret=0; + int blk_max = 32; //max block read size + + /* read eeprom, 32 * 8 = 256 bytes */ + for (i=0; i < EEPROM_SZ/blk_max; i++) { + ret = i2c_smbus_read_i2c_block_data(client, (i*blk_max), blk_max, + data + (i*blk_max)); + if (ret < 0) { + return ret; + } + } + return ret; +} + +/* + * update eeprom content + */ +static struct s9200_psu_data +*s9200_psu_update_eeprom(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9200_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + if (time_after(jiffies, data->last_updated + 300 * HZ) + || !data->valid) { + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9200_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + /* Read eeprom */ + if (!data->psuABS) { + //clear local eeprom data + memset(data->eeprom, 0, EEPROM_SZ); + + //read eeprom + status = s9200_psu_read_block(client, 0, data->eeprom, + ARRAY_SIZE(data->eeprom)); + + if (status < 0) { + memset(data->eeprom, 0, EEPROM_SZ); + dev_err(&client->dev, "Read eeprom failed, status=(%d)\n", status); + } else { + data->valid = 1; + } + } else { + memset(data->eeprom, 0, EEPROM_SZ); + } + data->last_updated = jiffies; + } + + mutex_unlock(&data->lock); + + return data; +} + +/* + * update psu status + */ +static struct s9200_psu_data +*s9200_psu_update_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9200_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9200_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + mutex_unlock(&data->lock); + + return data; +} + +static const struct i2c_device_id s9200_psu_id[] = { + { "psu1", s9200_psu1 }, + { "psu2", s9200_psu2 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, s9200_psu_id); + +static struct i2c_driver s9200_psu_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = s9200_psu_probe, + .remove = s9200_psu_remove, + .id_table = s9200_psu_id, + .address_list = normal_i2c, +}; + +static int __init s9200_psu_init(void) +{ + return i2c_add_driver(&s9200_psu_driver); +} + +static void __exit s9200_psu_exit(void) +{ + i2c_del_driver(&s9200_psu_driver); +} + +module_init(s9200_psu_init); +module_exit(s9200_psu_exit); + +MODULE_AUTHOR("Jason Tsai "); +MODULE_DESCRIPTION("S9200-64X psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/service/qsfp-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/service/qsfp-monitor.service new file mode 100644 index 000000000000..bcb9beb6a999 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s9200-64x-monitor.service +After=s9200-64x-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/service/s9200-64x-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/service/s9200-64x-monitor.service new file mode 100644 index 000000000000..bd92628a6c3f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/service/s9200-64x-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s9200_64x_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/i2c_utils.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/i2c_utils.sh new file mode 100644 index 000000000000..dcb6b9167982 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/i2c_utils.sh @@ -0,0 +1,1951 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, 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 . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +QSFP_INIT_ACTION=${2} +MB_EEPROM_ACTION=${2} +TARGET_10G_MUX=${2} +QSFP_ACTION=${3} +QSFP_VALUE=${4} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +I2C_NUM=0 +NUM_I801_DEVICE=$((I2C_NUM++)) #0 + +#MUX PCA9548#0 CPLD (I2C_NUM 1~8) +NUM_MUX_9548_CPLD_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_CPLD_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548#1 UCD (I2C_NUM 9~16) +NUM_MUX_9548_UCD_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_UCD_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9545 PSU (I2C_NUM 17~20) +NUM_MUX_9545_PSU_CHAN=() +for (( i=0; i<4; ++i )) +do + NUM_MUX_9545_PSU_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP ROOT (I2C_NUM 21~28) +NUM_MUX_9548_QSFP_ROOT_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_ROOT_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 0~7 (I2C_NUM 29~36) +NUM_MUX_9548_QSFP_0_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_0_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 8~15 (I2C_NUM 37~44) +NUM_MUX_9548_QSFP_1_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_1_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 16~23 (I2C_NUM 45~52) +NUM_MUX_9548_QSFP_2_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_2_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 24~31 (I2C_NUM 53~60) +NUM_MUX_9548_QSFP_3_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_3_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 32~39 (I2C_NUM 61~68) +NUM_MUX_9548_QSFP_4_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_4_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 40~47 (I2C_NUM 69~76) +NUM_MUX_9548_QSFP_5_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_5_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 48~55 (I2C_NUM 77~84) +NUM_MUX_9548_QSFP_6_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_6_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 56~63 (I2C_NUM 85~92) +NUM_MUX_9548_QSFP_7_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_7_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9545 SFP (I2C_NUM 93~96) +NUM_MUX_9545_SFP_CHAN=() +for (( i=0; i<4; ++i )) +do + NUM_MUX_9545_SFP_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 CPLD SW Upgrade (I2C_NUM 97~104) +NUM_MUX_9548_CPLD_SW_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_CPLD_SW_CHAN[i]=$((I2C_NUM++)) +done + +#MUX Alias +I2C_BUS_PSU1_EEPROM=${NUM_MUX_9545_PSU_CHAN[1]} +I2C_BUS_PSU2_EEPROM=${NUM_MUX_9545_PSU_CHAN[0]} +I2C_BUS_LED_BOARD=${NUM_MUX_9548_UCD_CHAN[1]} +I2C_BUS_ID_GPIO=${NUM_MUX_9548_UCD_CHAN[2]} +I2C_BUS_10GMUX=${NUM_MUX_9548_UCD_CHAN[4]} +I2C_BUS_HWM=${NUM_MUX_9548_UCD_CHAN[7]} +I2C_BUS_FAN_BOARD=${NUM_I801_DEVICE} +I2C_BUS_MB_EEPROM=${NUM_I801_DEVICE} +I2C_BUS_TH_RESET=${NUM_I801_DEVICE} +I2C_BUS_BOARD_TYPE=${NUM_I801_DEVICE} +I2C_BUS_BMC_BOARD_TYPE=${NUM_I801_DEVICE} +I2C_BUS_LM75_MAC=${NUM_MUX_9548_CPLD_CHAN[5]} +I2C_BUS_LM75_FRONT=${NUM_MUX_9548_CPLD_CHAN[6]} +I2C_BUS_LM75_REAR=${NUM_MUX_9548_CPLD_CHAN[5]} +I2C_BUS_PSU_INT=${NUM_I801_DEVICE} +I2C_BUS_PSU_STATUS=${NUM_I801_DEVICE} +I2C_BUS_MUX_RST=${NUM_I801_DEVICE} +#CPU Board +I2C_BUS_CPU_EEPROM=${NUM_I801_DEVICE} +I2C_BUS_CPU_TMP75=${NUM_I801_DEVICE} +I2C_BUS_MUX_CPU_CPLD=${NUM_I801_DEVICE} + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_SYS_CPLD="/sys/devices/platform/ingrasys-s9200-cpld.0" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon5" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_LM75_MAC="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_LM75_MAC}" +PATH_LM75_FRONT="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_LM75_FRONT}" +PATH_LM75_REAR="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_LM75_REAR}" +PATH_CPU_TMP75="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_BMC_TMP75="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_HWM}" +PATH_PSU1_EERPOM=${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM} +PATH_PSU2_EEPROM=${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM} +PATH_10GMUX=${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_10GMUX} +#PATH for MUX PCA9548_QSFP_ROOT +PATH_MUX_9548_QSFP_ROOT="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_PSU_CHAN[2]}" +PATH_MUX_9548_QSFP_ROOT_CHAN=() +for (( i=0; i<8; ++i )) +do + PATH_MUX_9548_QSFP_ROOT_CHAN[i]="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_QSFP_ROOT_CHAN[i]}" +done +PATH_MUX_9545_SFP="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_PSU_CHAN[3]}" +PATH_MUX_9545_SFP_CHAN=() +for (( i=0; i<4; ++i )) +do + PATH_MUX_9545_SFP_CHAN[i]="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_SFP_CHAN[i]}" +done + +#i2cmap and gpiomap path +PATH_I2CMAP=/tmp/i2cmap + +#Mother Board +I2C_ADDR_MUX_9539_TH_RST=0x74 +I2C_ADDR_LED_BOARD=0x75 +I2C_ADDR_FAN_BOARD=0x20 +I2C_ADDR_ID_GPIO=0x27 +I2C_ADDR_MUX_9548_CPLD=0x70 +I2C_ADDR_MUX_9548_UCD=0x76 +I2C_ADDR_MUX_9545_PSU=0x72 +I2C_ADDR_MUX_9548_QSFP_ROOT=0x71 +I2C_ADDR_MUX_9548_QSFP=0x73 +I2C_ADDR_MUX_9545_SFP=0x73 +I2C_ADDR_CPLD=0x33 +I2C_ADDR_MB_EEPROM=0x55 +I2C_ADDR_QSFP_EEPROM=0x50 +I2C_ADDR_PSU_EEPROM=0x50 +I2C_ADDR_LM75_MAC=0x4E +I2C_ADDR_LM75_FRONT=0x4D +I2C_ADDR_LM75_REAR=0x4D +I2C_ADDR_10GMUX=0x67 +#Dummy BMC Board +I2C_ADDR_HWM=0x2F +I2C_ADDR_PSU_INT=0x24 #PSU Interrup on Dummy BMC Board +I2C_ADDR_BMC_BOARD_TYPE=0x24 #PSU Status on Dummy BMC Board +I2C_ADDR_PSU_STATUS=0x25 #PSU Status on Dummy BMC Board +I2C_ADDR_MUX_RST=0x26 #MUX RST on Dummy BMC Board +I2C_ADDR_TMP75_BB=0x4A +#CPU Board +I2C_ADDR_CPU_EEPROM=0x51 +I2C_ADDR_CPU_TMP75=0x4F +I2C_ADDR_MUX_CPU_CPLD=0x77 + +#sysfs +PATH_SYSFS_PSU1="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU1_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU_EEPROM)" +PATH_SYSFS_PSU2="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU2_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU_EEPROM)" + +#Active High/Low +ACTIVE_LOW=1 +ACTIVE_HIGH=0 +#GPIO Direction In/Out +DIR_IN=in +DIR_OUT=out + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +#W83795 Registers +REG_BANK_SEL=0x00 +REG_VOLT_CTRL1=0x02 +REG_VOLT_CTRL2=0x03 +REG_TEMP_CTRL1=0x04 +REG_TEMP_CTRL2=0x05 + +#PCA9535 Registers +REG_IN_0=0 +REG_IN_1=1 +REG_OUT_0=2 +REG_OUT_1=3 +REG_POLARITY_0=4 +REG_POLARITY_1=5 +REG_CFG_0=6 +REG_CFG_1=7 + +#LM75 Registers +LM75_REG_TEMP=0x00 +LM75_REG_CONF=0x01 +LM75_REG_HYST=0x02 +LM75_REG_TOS=0x03 + +#Bit Mask +BIT_MASK=(1 2 4 8 16 32 64 128) + +#MUX Type +PCA9545="pca9545" +PCA9548="pca9548" + +#PLATFORM Variables +PORT_NUM=64 + +#CPLD Variables +CPLD_QSFP_GROUP=(12 25 38 51 64) +CPLD_QSFP_STATUS_REG_BASE=0x20 +CPLD_QSFP_MODE_SELECT_REG_BASE=0x30 +CPLD_QSFP_ABS="abs" +CPLD_QSFP_INT="int" +CPLD_QSFP_RST="rst" +CPLD_QSFP_LP="lp" + + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_temp_init" + echo " : ${0} i2c_fan_init" + echo " : ${0} i2c_volmon_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_cpu_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [1-${PORT_NUM}]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_cpu_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [1-${PORT_NUM}]" + echo " : ${0} i2c_qsfp_type_get [1-${PORT_NUM}]" + echo " : ${0} i2c_qsfp_signal_get [1-${PORT_NUM}] [abs|int|rst|lp]" + echo " : ${0} i2c_qsfp_signal_set [1-${PORT_NUM}] [rst|lp] [0|1] (low_active)" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_bmc_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_led_fan_tray_test" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_sys_led green|amber" + echo " : ${0} i2c_fan_led green|amber" + echo " : ${0} i2c_psu1_led green|amber" + echo " : ${0} i2c_psu2_led green|amber" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo " : ${0} i2c_10g_mux cpu|fp" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +#logical(front panel) to physical (falcon core) port mapping +function _port_logic2phy { + + local logic_port=$1 + local phy_port=0 + + if (( $logic_port >=1 && $logic_port <= 32 )) ; then + phy_port=$(( (logic_port-1)/2*4 + (logic_port-1)%2 + 1)) + elif (( $logic_port >=33 && $logic_port <= 64 )) ; then + phy_port=$(( (((logic_port-1)%32))/2*4 + (logic_port-1)%2 + 3)) + fi + + echo $phy_port +} + +#set i2cmap +function _set_i2cmap { + local i2c_n=$1 + local alias=$2 + + #create i2cmap dir if not exist + mkdir -p $PATH_I2CMAP + + #check i2c_n exists in sysfs + if [ ! -L ${PATH_SYS_I2C_DEVICES}/i2c-${i2c_n} ]; then + echo "${PATH_SYS_I2C_DEVICES}/i2c-${i2c_n} does not exist." + return + fi + + #create or update link + ln -sf ${PATH_SYS_I2C_DEVICES}/i2c-${i2c_n} ${PATH_I2CMAP}/${alias} +} + +#clear i2cmap +function _clear_i2cmap { + #delete i2cmap dir + rm -rf ${PATH_I2CMAP}/ +} + +#remove kernel module if exists +function _util_rmmod { + local mod=$1 + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod +} + +function _create_i2c_mux_device { + local mux_type=$1 + local mux_addr=$2 + local mux_parent_chan=$3 + local mux_chan0=$4 + local mux_desc=$5 + + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${mux_chan0}" ]; then + _retry "echo '$mux_type ${mux_addr}' > ${mux_parent_chan}/new_device" + _set_i2cmap ${mux_chan0} "${mux_desc}" + else + echo "${mux_desc} ${mux_addr} already init." + fi +} + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + _util_rmmod i2c_i801 + modprobe i2c_i801 #disable_features=0x10 + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + #add MUX_9548_CPLD on I801 + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_CPLD ${PATH_I801_DEVICE} ${NUM_MUX_9548_CPLD_CHAN[0]} "PCA9548_CPLD" + + #add MUX_9548_UCD on I801 + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_UCD ${PATH_I801_DEVICE} ${NUM_MUX_9548_UCD_CHAN[0]} "PCA9548_UCD" + + #add MUX_9545_PSU on I801 + _create_i2c_mux_device $PCA9545 $I2C_ADDR_MUX_9545_PSU ${PATH_I801_DEVICE} ${NUM_MUX_9545_PSU_CHAN[0]} "PCA9545_PSU" + + #add MUX_9548_QSFP_ROOT on MUX_9545_PSU_CHAN[2] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP_ROOT ${PATH_MUX_9548_QSFP_ROOT} ${NUM_MUX_9548_QSFP_ROOT_CHAN[0]} "PCA9548_QSPF_ROOT" + + #add MUX_9548_QSFP_0 on MUX_9548_QSFP_ROOT_CHAN[0] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[0]} ${NUM_MUX_9548_QSFP_0_CHAN[0]} "PCA9548_QSPF_0" + + #add MUX_9548_QSFP_1 on MUX_9548_QSFP_ROOT_CHAN[1] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[1]} ${NUM_MUX_9548_QSFP_1_CHAN[0]} "PCA9548_QSPF_1" + + #add MUX_9548_QSFP_2 on MUX_9548_QSFP_ROOT_CHAN[2] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[2]} ${NUM_MUX_9548_QSFP_2_CHAN[0]} "PCA9548_QSPF_2" + + #add MUX_9548_QSFP_3 on MUX_9548_QSFP_ROOT_CHAN[3] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[3]} ${NUM_MUX_9548_QSFP_3_CHAN[0]} "PCA9548_QSPF_3" + + #add MUX_9548_QSFP_4 on MUX_9548_QSFP_ROOT_CHAN[4] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[4]} ${NUM_MUX_9548_QSFP_4_CHAN[0]} "PCA9548_QSPF_4" + + #add MUX_9548_QSFP_5 on MUX_9548_QSFP_ROOT_CHAN[5] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[5]} ${NUM_MUX_9548_QSFP_5_CHAN[0]} "PCA9548_QSPF_5" + + #add MUX_9548_QSFP_6 on MUX_9548_QSFP_ROOT_CHAN[6] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[6]} ${NUM_MUX_9548_QSFP_6_CHAN[0]} "PCA9548_QSPF_6" + + #add MUX_9548_QSFP_7 on MUX_9548_QSFP_ROOT_CHAN[7] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[7]} ${NUM_MUX_9548_QSFP_7_CHAN[0]} "PCA9548_QSPF_7" + + #add MUX_9545_SFP on QSFP_ROOT + _create_i2c_mux_device $PCA9545 $I2C_ADDR_MUX_9545_SFP ${PATH_MUX_9545_SFP} ${NUM_MUX_9545_SFP_CHAN[0]} "PCA9545_SPF" + + #Init CPLD LED_CLR Register (QSFP LED) + i2cset -y -m ${BIT_MASK[2]} ${NUM_I801_DEVICE} ${I2C_ADDR_MUX_9539_TH_RST} ${REG_OUT_0} 0xFF + + _util_rmmod coretemp + _util_rmmod jc42 + _util_rmmod w83795 + _util_rmmod lm75 + + _i2c_temp_init + _i2c_volmon_init + modprobe coretemp + modprobe lm75 + modprobe jc42 + modprobe eeprom_mb + _i2c_mb_eeprom_init "new" + _i2c_cpu_eeprom_init "new" + modprobe eeprom + modprobe gpio-pca953x + _i2c_sensors_init + _i2c_fan_init + _i2c_io_exp_init + _i2c_psu_init + _i2c_qsfp_eeprom_init "new" + _i2c_led_psu_status_set + _i2c_led_fan_status_set + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_sys_led + modprobe cpld + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + for mod in cpld coretemp jc42 w83795 lm75 eeprom eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_i801 ingrasys_s9200_64x_psu; + do + _util_rmmod $mod + done + _clear_i2cmap +} + +#Temperature sensor Init +function _i2c_temp_init { + local lm="lm75" + local tmp="tmp75" + local i2c_bus=${I2C_BUS_HWM} + local i2c_addr=${I2C_ADDR_HWM} + + echo "=========================================================" + echo "# Description: TEMP INIT" + echo "=========================================================" + + # select bank0 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_BANK_SEL} 0x80 + echo "enable VDSEN14, VDSEN15, VDSEN16, and TR4 temperature monitoring" + i2cset -y -r ${i2c_bus=} ${i2c_addr} ${REG_TEMP_CTRL2} 0x6A + + echo "export CPU sensor TMP75 to sysfs" + echo "${tmp} ${I2C_ADDR_CPU_TMP75}" > ${PATH_CPU_TMP75}/new_device + + echo "Add Dummy Board LM75 to sysfs" + echo "${lm} ${I2C_ADDR_LM75_MAC}" > ${PATH_LM75_MAC}/new_device + echo "${lm} ${I2C_ADDR_LM75_FRONT}" > ${PATH_LM75_FRONT}/new_device + echo "${lm} ${I2C_ADDR_LM75_REAR}" > ${PATH_LM75_REAR}/new_device + + echo "CLKIN clock frequency set as 48Mhz" + i2cset -y -r ${i2c_bus} ${i2c_addr} 0x01 0x1C + + # select bank 2 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_BANK_SEL} 0x82 + echo "set PWM mode in FOMC" + i2cset -y -r ${i2c_bus} ${i2c_addr} 0x0F 0x00 +} + +#FAN Init +function _i2c_fan_init { + local init_fan_speed=120 + + echo "=========================================================" + echo "# Description: FAN INIT" + echo "=========================================================" + + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo "Init Fan Speed to ${init_fan_speed} (MAX is 255)" + echo $init_fan_speed > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo $init_fan_speed > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + else + echo "FAIL, W83795 not found in path ${PATH_HWMON_W83795_DEVICE}" + fi +} + +#VOLMON Init +function _i2c_volmon_init { + echo -n "VOLMON INIT" + local i2c_bus=${I2C_BUS_HWM} + local i2c_addr=${I2C_ADDR_HWM} + + #select bank0 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_BANK_SEL} 0x80 + #enable voltage monitoring VSEN 1~8 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_VOLT_CTRL1} 0xFF + #enable voltage monitoring 3VDD and 3VBAT + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_VOLT_CTRL2} 0x50 + #eable voltage monitoring VSEN12 and VSEN13 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_TEMP_CTRL1} 0x0A + + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + local i2c_bus=0 + local i2c_addr=0 + + echo "=========================================================" + echo "# Description: I2C IO Expander Init" + echo "=========================================================" + + echo "Init PCA9539 TH RESET IO Expander" + #PCA9539 TH RESET + #0.0 TH_RST_L OUT 1 + #0.1 TH_PCIE_RST_L OUT 1 + #0.2 LED_CLR OUT 1 + #0.3 HOST_TO_BMC_I2C_GPIO OUT 0 + #0.4 USB_MUX_SEL OUT 0 + #0.5 UART_MUX_SEL OUT 0 + #0.6 FIN0 OUT 0 + #0.7 FIN7 OUT 0 + #1.0 TH_INT_L IN + #1.1 CPLD4_TO_CPU_INT_L IN + #1.2 CPLD3_TO_CPU_INT_L IN + #1.3 CPLD2_TO_CPU_INT_L IN + #1.4 CPLD1_TO_CPU_INT_L IN + #1.5 REF_SEL OUT 0 + #1.6 I210_PE_RST_L OUT 1 + #1.7 I210_RST_L OUT 1 + i2c_bus=${I2C_BUS_TH_RESET} + i2c_addr=${I2C_ADDR_MUX_9539_TH_RST} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_0} $((2#00000111)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_1} $((2#11000000)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} $((2#00011111)) + + #PCA9555 on BMC Dummy Board + #set SYSTEM_LED_RST_L before init PCA9539 LED BOARD IO Expander + echo "Init PCA9555 MUX RST IO Expander" + #PCA9555 MUX RST Expander + #0.0 FRU_I2C_MUX_RST_L OUT 1 + #0.1 MAIN_I2C_MUX_RST_L OUT 1 + #0.2 SYSTEM_LED_RST_L OUT 1 + #0.3 BMC_TO_UCD_RST_L OUT 1 + #0.4 BMC_TO_HOST_RST_L OUT 1 + #0.5 ETHX_RST_L OUT 1 + #0.6 GPIOF4 IN + #0.7 N/A + #1.0 CPU_to_FRU_I2C_EN OUT 1 + #1.1 CPU_to_MAIN_I2C_EN OUT 1 + #1.2 P3V3_FAN_EN OUT 1 + #1.3 P3V3_I2C_EN OUT 1 + #1.4 UCD9090_CNTRL OUT 1 + #1.5 UART_MUX_SEL OUT 0 + #1.6 USB_MUX_SEL OUT 0 + #1.7 ETHX_CPU_EEPROM_SEL OUT 0 + i2c_bus=${I2C_BUS_MUX_RST} + i2c_addr=${I2C_ADDR_MUX_RST} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_0} $((2#00111111)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_1} $((2#00011111)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} $((2#01000000)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} 0x00 + + echo "Init PCA9539 LED BOARD IO Expander" + #PCA9539 LED BOARD + #0.0 SYS_LED_G OUT 1 + #0.1 FAN_LED_EN OUT 1 + #0.2 FAN_LED_Y OUT 0 + #0.3 PSU1_LED_Y OUT 0 + #0.4 PSU0_LED_Y OUT 0 + #0.5~0.7 X + #1.0 PSU1_PWROK OUT 1 + #1.1 PSU0_PWROK OUT 1 + i2c_bus=${I2C_BUS_LED_BOARD} + i2c_addr=${I2C_ADDR_LED_BOARD} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_0} $((2#00000011)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_1} $((2#00000011)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} 0x00 + + echo "Init PCA9535 ID_GPIO IO Expander" + #PCA9535 ID_GPIO + #0.0 ~ 0.7 X + #1.0 Build_REV_0 IN + #1.1 Build_REV_1 IN + #1.2 HW_REV_0 IN + #1.3 HW_REV_1 IN + #1.4 Board_ID_0 IN + #1.5 Board_ID_1 IN + #1.6 Board_ID_2 IN + #1.7 Board_ID_3 IN + i2c_bus=${I2C_BUS_ID_GPIO} + i2c_addr=${I2C_ADDR_ID_GPIO} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} 0xFF + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} 0xFF + + #I2C_ADDR_FAN_BOARD + echo "Init PCA9535 FAN_BOARD IO Expander" + #PCA9535 FAN_BOARD + #0.0 EN_FAN1_LED_G_H OUT 1 + #0.1 EN_FAN1_LED_Y_H OUT 0 + #0.2 FAN1_ABS# IN 0 + #0.3 FAN1_DIR# IN 0 + #0.4 EN_FAN2_LED_G_H OUT 1 + #0.5 EN_FAN2_LED_Y_H OUT 0 + #0.6 FAN2_ABS# IN 0 + #0.7 FAN2_DIR# IN 0 + #1.0 EN_FAN3_LED_G_H OUT 1 + #1.1 EN_FAN3_LED_Y_H OUT 0 + #1.2 FAN3_ABS# IN 0 + #1.3 FAN3_DIR# IN 0 + #1.4 EN_FAN4_LED_G_H OUT 1 + #1.5 EN_FAN4_LED_Y_H OUT 0 + #1.6 FAN4_ABS# IN 0 + #1.7 FAN4_DIR# IN 0 + i2c_bus=${I2C_BUS_FAN_BOARD} + i2c_addr=${I2C_ADDR_FAN_BOARD} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_0} $((2#00010001)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_1} $((2#00010001)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} $((2#11001100)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} $((2#11001100)) + + #PCA9555 on BMC Dummy Board + echo "Init PCA9555 Interrupt IO Expander" + #PCA9555 Interrupt Expander + #0.0 HWM_INT_L IN + #0.1 UCD9090_INT_L IN + #0.2 ETHX_INT_L IN + #0.3 HOST_TO_BMC_INT_L IN + #0.4 THERMAL_ALT1# IN + #0.5 FAN_STATUS_INT_L IN + #0.6 PSU0_INT_L IN + #0.7 PSU1_INT_L IN + #1.0 Build_REV_0 IN + #1.1 Build_REV_1 IN + #1.2 HW_REV_0 IN + #1.3 HW_REV_1 IN + #1.4 Board_ID_0 IN + #1.5 Board_ID_1 IN + #1.6 Board_ID_2 IN + #1.7 Board_ID_3 IN + i2c_bus=${I2C_BUS_PSU_INT} + i2c_addr=${I2C_ADDR_PSU_INT} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} 0xFF + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} 0xFF + + #PCA9555 on BMC Dummy Board + echo "Init PCA9555 PSU0_PWROK IO Expander" + #PCA9555 PSU0_PWROK Expander + #0.0 PSU0_PWROK IN + #0.1 PSU0_PRSNT_L IN + #0.2 PSU0_PWRON_L OUT 0 + #0.3 PSU1_PWROK IN + #0.4 PSU1_PRSNT_L IN + #0.5 PSU1_PWRON_L OUT 0 + #0.6 TMP75_INT_L IN + #0.7 GPIOF7 IN + #1.0 ALL_PWR_GOOD IN + #1.1 CPU_PRSNT_L IN + #1.2 FP_BTN_UARTSEL_EN_L OUT 0 + #1.3 HOST_TO_BMC_I2C_GPIO OUT 0 + #1.4 HOST_CPU_PWRBTN_L OUT 1 + #1.5 N/A + #1.6 N/A + #1.7 N/A + i2c_bus=${I2C_BUS_PSU_STATUS} + i2c_addr=${I2C_ADDR_PSU_STATUS} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_1} $((2#00010000)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} $((2#11011011)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} $((2#11100011)) + + #PCA9539 on CPU Board + echo "Init PCA9539 CPLD IO Expander on CPU" + i2c_bus=${I2C_BUS_MUX_CPU_CPLD} + i2c_addr=${I2C_ADDR_MUX_CPU_CPLD} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} 0xFF + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} 0xFF +} + +function _i2c_sensors_init { + echo "SENSORS init" + local dev_path + + # add w83795 to sysfs + dev_path="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_HWM}-$(printf "%04x" ${I2C_ADDR_HWM})" + if ! [ -L ${dev_path} ]; then + echo "w83795adg ${I2C_ADDR_HWM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_HWM}/new_device + while [ ! -e "${PATH_HWMON_W83795_DEVICE}" ]; do + sleep 1 + done + else + echo "${dev_path} already exist (w83795)" + fi + + # BMC board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-$(printf "%04x" ${I2C_ADDR_TMP75_BB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_BB}" > ${PATH_BMC_TMP75}/new_device + else + echo "${dev_path} already exist" + fi + + echo "Done" +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "=========================================================" + echo "# Description: FAN Tray Status Setup" + echo "=========================================================" + + #check W83795 exists + if [ ! -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo "FAIL, W83795 not found in path ${PATH_HWMON_W83795_DEVICE}" + return + fi + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + + FAN_TRAY=1 + if [ "${FAN1_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + + echo "set [FAN TRAY 1] [Green]=on [Amber]=off" + else + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + + echo "set [FAN TRAY 1] [Green]=off [Amber]=on" + fi + + FAN_TRAY=2 + if [ "${FAN3_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + + echo "set [FAN TRAY 2] [Green]=on [Amber]=off" + else + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + + echo "set [FAN TRAY 2] [Green]=off [Amber]=on" + fi + + FAN_TRAY=3 + if [ "${FAN5_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + + echo "set [FAN TRAY 3] [Green]=on [Amber]=off" + else + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + + echo "set [FAN TRAY 3] [Green]=off [Amber]=on" + fi + + FAN_TRAY=4 + if [ "${FAN7_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + + echo "set [FAN TRAY 4] [Green]=on [Amber]=off" + else + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + + echo "set [FAN TRAY 4] [Green]=off [Amber]=on" + fi +} + +#Test FAN Tray LED +function _i2c_led_fan_tray_test { + echo "=========================================================" + echo "# Description: FAN Tray LED Test" + echo "=========================================================" + + for i in {1..4} + do + FAN_TRAY=$i + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + _pause "Check [Fan Tray ${i} LED] = Green and Press [Enter] key to continue..." + + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + _pause "Check [Fan Tray ${i} LED] = Amber and Press [Enter] key to continue..." + done +} +#Set FAN LED +function _i2c_led_fan_status_set { + echo "=========================================================" + echo "# Description: FAN Status Setup" + echo "=========================================================" + + #check W83795 exists in hwmon2 + if [ ! -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo "FAIL, W83795 not found in path ${PATH_HWMON_W83795_DEVICE}" + return + fi + + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + + if [ "${FAN1_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] ; then + COLOR_LED="green" + _i2c_fan_led + else + COLOR_LED="amber" + _i2c_fan_led + fi + echo "set [FAN LED] = ${COLOR_LED}" +} + +#Set PSU LED on LED Board +function _i2c_led_psu_status_set { + + echo "=========================================================" + echo "# Description: PSU LED Status Setup" + echo "=========================================================" + + #Get PSU Status + _i2c_psu_status + + #PSU1 Status + echo "------------------------------" + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + _i2c_psu1_led + else + COLOR_LED="amber" + _i2c_psu1_led + fi + else + COLOR_LED="amber" + _i2c_psu1_led + fi + echo "set [PSU1 LED] = ${COLOR_LED}" + + #PSU2 Status + echo "------------------------------" + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + _i2c_psu2_led + else + COLOR_LED="amber" + #ONOFF_LED="on" + _i2c_psu2_led + fi + else + COLOR_LED="amber" + _i2c_psu2_led + fi + echo "set [PSU2 LED] = ${COLOR_LED}" +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C LED TEST" + echo "=========================================================" + #sys led (green) + _i2c_reset_led + COLOR_LED="green" + _i2c_sys_led + _pause 'Check [SYS LED] = Green and Press [Enter] key to continue...' + #sys led (amber) + _i2c_reset_led + COLOR_LED="amber" + _i2c_sys_led + _pause 'Check [SYS LED] = Amber and Press [Enter] key to continue...' + + #FAN led (green) + _i2c_reset_led + COLOR_LED="green" + _i2c_fan_led + _pause 'Check [FAN LED] Green and Press [Enter] key to continue...' + #FAN led (amber) + _i2c_reset_led + COLOR_LED="amber" + _i2c_fan_led + _pause 'Check [FAN LED] = Amber and Press [Enter] key to continue...' + + #PSU1 led (green) + _i2c_reset_led + COLOR_LED="green" + _i2c_psu1_led + _pause 'Check [PSU1 LED] = Green and Press [Enter] key to continue...' + #PSU1 led (amber) + _i2c_reset_led + COLOR_LED="amber" + _i2c_psu1_led + _pause 'Check [PSU1 LED] = Amber and Press [Enter] key to continue...' + + #PSU2 led (green) + _i2c_reset_led + COLOR_LED="green" + _i2c_psu2_led + _pause 'Check [PSU2 LED] = Green and Press [Enter] key to continue...' + #PSU2 led (amber) + _i2c_reset_led + COLOR_LED="amber" + _i2c_psu2_led + _pause 'Check [PSU2 LED] = Amber and Press [Enter] key to continue...' + + #Turn OFF All LED + _i2c_reset_led + _pause 'Check turn off all LEDs and Press [Enter] key to continue...' +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + #global variables + cpld_group=0 + cpld_i2c_bus=0 + cpld_i2c_addr=$I2C_ADDR_CPLD + cpld_qsfp_status_reg_offset=0 + cpld_qsfp_mode_reg_offset=0 + + #local variables + local i=0 + local port=$1 + local port_group=$(( (port - 1)/8 )) + + case ${port_group} in + 0) + #the i2c expander base bus num to read qsfp eeprom + eeprombusbase=${NUM_MUX_9548_QSFP_0_CHAN[0]} + ;; + 1) + eeprombusbase=${NUM_MUX_9548_QSFP_1_CHAN[0]} + ;; + 2) + eeprombusbase=${NUM_MUX_9548_QSFP_2_CHAN[0]} + ;; + 3) + eeprombusbase=${NUM_MUX_9548_QSFP_3_CHAN[0]} + ;; + 4) + eeprombusbase=${NUM_MUX_9548_QSFP_4_CHAN[0]} + ;; + 5) + eeprombusbase=${NUM_MUX_9548_QSFP_5_CHAN[0]} + ;; + 6) + eeprombusbase=${NUM_MUX_9548_QSFP_6_CHAN[0]} + ;; + 7) + eeprombusbase=${NUM_MUX_9548_QSFP_7_CHAN[0]} + ;; + *) + echo "Please input 1~${PORT_NUM}" + exit + ;; + esac + + #set cpld_group and cpld_i2c_bus according to port + for ((i=0; i<5; ++i)) + do + if (("${port}" <= "${CPLD_QSFP_GROUP[i]}")); + then + local port_offset=0 + cpld_group=$i + cpld_i2c_bus=${NUM_MUX_9548_CPLD_CHAN[i]} + + if ((i>0)) + then + port_offset=$(( port - CPLD_QSFP_GROUP[i-1] )) + else + port_offset=$port + fi + cpld_qsfp_status_reg_offset=$((CPLD_QSFP_STATUS_REG_BASE + port_offset)) + cpld_qsfp_mode_reg_offset=$((CPLD_QSFP_MODE_SELECT_REG_BASE + port_offset)) + + break + fi + done +} + +function _i2c_get { + local i2c_bus=$1 + local i2c_addr=$2 + local reg=$3 + echo `i2cget -y ${i2c_bus} ${i2c_addr} ${reg}` +} + +function _i2c_set { + local i2c_bus=$1 + local i2c_addr=$2 + local reg=$3 + local mask=$4 + local value=$5 + + echo `i2cset -m $mask -y -r ${i2c_bus} ${i2c_addr} ${reg} ${value}` +} + +#Set QSFP Port variable +function _qsfp_eeprom_var_set { + #local variables + local port=$1 + + #global variables + eeprombusidx=$(( (port - 1)%8 )) + + case $eeprombusidx in + 0) + eeprombus=$(( $eeprombusbase + 0 )) + ;; + 1) + eeprombus=$(( $eeprombusbase + 1 )) + ;; + 2) + eeprombus=$(( $eeprombusbase + 2 )) + ;; + 3) + eeprombus=$(( $eeprombusbase + 3 )) + ;; + 4) + eeprombus=$(( $eeprombusbase + 4 )) + ;; + 5) + eeprombus=$(( $eeprombusbase + 5 )) + ;; + 6) + eeprombus=$(( $eeprombusbase + 6 )) + ;; + 7) + eeprombus=$(( $eeprombusbase + 7 )) + ;; + esac + eepromAddr=${I2C_ADDR_QSFP_EEPROM} +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + local value=0 + local status=0 + + echo "=========================================================" + echo "# Description: QSFP EEPROM GET" + echo "=========================================================" + + #status: 0 -> Down, 1 -> Up + _i2c_qsfp_signal_get ${QSFP_PORT} ${CPLD_QSFP_ABS} + + value=$qsfp_signal + status=$(( value?0:1 )) + + if [ $status = 0 ]; then + echo "[Fail] QSFP ${QSFP_PORT} is not present" + exit + fi + + echo "------------------------------" + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo "=========================================================" + echo "# Description: QSFP EEPROM INIT" + echo "=========================================================" + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init EEPROM + local i + for (( i=1; i<=${PORT_NUM}; i++ )) + do + _qsfp_port_i2c_var_set ${i} + + _qsfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/delete_device + fi + done +} + +#get qsfp singals (ABS, INT, RST, LP) from CPLD +function _i2c_qsfp_signal_get { + local port=$1 #port start from 1 + local signal=$2 + local attr_file="" + local phy_port=0 + local active="low_active" + + #global + qsfp_signal=0 + qsfp_signals=0 + + #verify port + if [ -z "${port}" ]; then + echo "No port, skip" + return + fi + + #verify port + if (( $port < 1 || $port > $PORT_NUM )) ; then + echo "invalid port, skip" + fi + + #get physical port + phy_port=$(_port_logic2phy $port) + + _qsfp_port_i2c_var_set ${phy_port} + _qsfp_eeprom_var_set ${phy_port} + + #verify signal + if [ -z "${signal}" ]; then + echo "No signal, skip" + return + elif [ "${signal}" == "${CPLD_QSFP_ABS}" ]; then + attr_file="qsfp_modprs" + elif [ "${signal}" == "${CPLD_QSFP_INT}" ]; then + attr_file="qsfp_int" + elif [ "${signal}" == "${CPLD_QSFP_RST}" ]; then + attr_file="qsfp_reset" + elif [ "${signal}" == "${CPLD_QSFP_LP}" ]; then + attr_file="qsfp_lpmode" + active="high_active" + else + echo "invalid signal ${signal}, skip" + return + fi + + mask=${BIT_MASK[bit_shift]} + + #signals of all ports + qsfp_signals=`cat ${PATH_SYS_CPLD}/${attr_file}` + #signal of single port + qsfp_signal=$(( (qsfp_signals >> (phy_port-1)) & 0x1)) + #print signals + printf "[port]=%d, [signal]=%s, [value]=%d (${active}), [qsfp_signals]=%016x\n" $port $signal $qsfp_signal $qsfp_signals +} + +#set qsfp singals (RST, LP) via CPLD +function _i2c_qsfp_signal_set { + local port=$1 #port start from 1 + local signal=$2 + local value=$3 + local values_ori=0 + local value_ori=0 + local values=0 + local attr_file="" + + #verify port + if [ -z "${port}" ]; then + echo "No port, skip" + return + fi + + #verify port + if (( $port < 1 || $port > $PORT_NUM )) ; then + echo "invalid port, skip" + fi + + #verify signal + if [ -z "${signal}" ]; then + echo "No signal, skip" + return + elif [ "${signal}" == "${CPLD_QSFP_RST}" ]; then + attr_file="qsfp_reset" + elif [ "${signal}" == "${CPLD_QSFP_LP}" ]; then + attr_file="qsfp_lpmode" + else + echo "invalid signal ${signal}, skip" + return + fi + + #get current signal values + _i2c_qsfp_signal_get $port $signal + value_ori=$qsfp_signal + values_ori=$qsfp_signals + + #if signal value is not changed, return + if [ "${value}" == "${value_ori}" ]; then + echo "value not changed, skip set operation" + return + fi + + #toggle the bit for update + values=$(( values_ori ^ (1 << (port-1)))) + + #set value to register + echo "$(printf "%016x" $values)" > ${PATH_SYS_CPLD}/${attr_file} + + #get updated signal values + _i2c_qsfp_signal_get $port $signal + values=$qsfp_signals + + #result + printf "Before: %016x\n" $values_ori + printf "After: %016x\n" $values +} + +#Init EEPROM +function _i2c_eeprom_init { + local i2c_bus=$1 + local i2c_addr=$2 + local action=$3 + local desc=$4 + local sys_i2c_dev=$PATH_SYS_I2C_DEVICES + + echo -n "${desc} EEPROM INIT" + + #Action check + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${sys_i2c_dev}/${i2c_bus}-$(printf "%04x" $i2c_addr) ]; then + echo "mb_eeprom ${i2c_addr}" > ${sys_i2c_dev}/i2c-${i2c_bus}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${sys_i2c_dev}/${i2c_bus}-$(printf "%04x" $i2c_addr) ]; then + echo "${i2c_addr}" > ${sys_i2c_dev}/i2c-${i2c_bus}/delete_device + fi + echo "DONE" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + local action=$1 + local i2c_bus=$I2C_BUS_MB_EEPROM + local i2c_addr=$I2C_ADDR_MB_EEPROM + local desc="Main Board" + + _i2c_eeprom_init $i2c_bus $i2c_addr $action $desc +} + +#Init CPU EEPROM +function _i2c_cpu_eeprom_init { + local action=$1 + local i2c_bus=$I2C_BUS_CPU_EEPROM + local i2c_addr=$I2C_ADDR_CPU_EEPROM + local desc="CPU Board" + + _i2c_eeprom_init $i2c_bus $i2c_addr $action $desc +} + +#get QSFP Status +function _i2c_qsfp_status_get { + local value=0 + local status=0 + + #status: 0 -> Down, 1 -> Up + _i2c_qsfp_signal_get ${QSFP_PORT} ${CPLD_QSFP_ABS} + value=$qsfp_signal + status=$(( value?0:1 )) + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + local phy_port=0 + local value=0 + local status=0 + + echo "=========================================================" + echo "# Description: QSFP TYPE Get" + echo "=========================================================" + + phy_port=$(_port_logic2phy ${QSFP_PORT}) + _qsfp_port_i2c_var_set ${phy_port} + _qsfp_eeprom_var_set ${phy_port} + + #get abs signal + _i2c_qsfp_signal_get ${QSFP_PORT} ${CPLD_QSFP_ABS} + value=$qsfp_signal + status=$(( value?0:1 )) + + #check qsfp is present + if [ $status = 0 ]; then + echo "[Fail] QSFP ${QSFP_PORT} is not present" + exit + fi + + #Get QSFP EEPROM info + if [ ! -e "${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf '%04x' $eepromAddr)/eeprom" ]; then + echo "FAIL, qsfp eeprom file does not exist. " + echo "qsfp eeprom file path: ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf '%04x' $eepromAddr)/eeprom" + return + fi + + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "------------------------------" + echo "identifier = $identifier" + echo "connector = $connector" + echo "transceiver = $transceiver" +} + +#Init PSU Kernel Module +function _i2c_psu_init { + echo "=========================================================" + echo "# Description: I2C PSU Init" + echo "=========================================================" + modprobe ingrasys_s9200_64x_psu + + echo "psu1 ${I2C_ADDR_PSU_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/new_device + echo "psu2 ${I2C_ADDR_PSU_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/new_device +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + local eeprom_psu1="" + local eeprom_psu2="" + + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + echo "PUS1 EEPROM" + eeprom_psu1="${PATH_SYSFS_PSU1}/psu_eeprom" + cat ${eeprom_psu1} | hexdump -C + + echo "------------------------------" + echo "PUS2 EEPROM" + eeprom_psu2="${PATH_SYSFS_PSU2}/psu_eeprom" + cat ${eeprom_psu2} | hexdump -C +} + +#Get MotherBoard EEPROM Information +function _i2c_mb_eeprom_get { + local path_i2c_dev=${PATH_SYS_I2C_DEVICES} + local i2c_bus=${I2C_BUS_MB_EEPROM} + local i2c_addr=${I2C_ADDR_MB_EEPROM} + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get" + echo "=========================================================" + + ## MB EEPROM + cat ${path_i2c_dev}/${i2c_bus}-$(printf "%04x" ${i2c_addr})/eeprom | hexdump -v -C +} + +#Get CPU EEPROM Information +function _i2c_cpu_eeprom_get { + local path_i2c_dev=${PATH_SYS_I2C_DEVICES} + local i2c_bus=${I2C_BUS_CPU_EEPROM} + local i2c_addr=${I2C_ADDR_CPU_EEPROM} + echo "=========================================================" + echo "# Description: I2C CPU EEPROM Get" + echo "=========================================================" + + ## CPU EEPROM + cat ${path_i2c_dev}/${i2c_bus}-$(printf "%04x" ${i2c_addr})/eeprom | hexdump -v -C +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + local value=0 + + echo "=========================================================" + echo "# Description: Set Fan Tray LED" + echo "=========================================================" + + case ${FAN_TRAY} in + 1) + ioPort=$REG_OUT_0 + if [ "${COLOR_LED}" == "green" ]; then + mask=${BIT_MASK[0]} + elif [ "${COLOR_LED}" == "amber" ]; then + mask=${BIT_MASK[1]} + fi + ;; + 2) + ioPort=$REG_OUT_0 + if [ "${COLOR_LED}" == "green" ]; then + mask=${BIT_MASK[4]} + elif [ "${COLOR_LED}" == "amber" ]; then + mask=${BIT_MASK[5]} + fi + ;; + 3) + ioPort=$REG_OUT_1 + if [ "${COLOR_LED}" == "green" ]; then + mask=${BIT_MASK[0]} + elif [ "${COLOR_LED}" == "amber" ]; then + mask=${BIT_MASK[1]} + fi + ;; + 4) + ioPort=$REG_OUT_1 + if [ "${COLOR_LED}" == "green" ]; then + mask=${BIT_MASK[4]} + elif [ "${COLOR_LED}" == "amber" ]; then + mask=${BIT_MASK[5]} + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + if [ "${ONOFF_LED}" == "on" ]; then + value=0xFF + elif [ "${ONOFF_LED}" == "off" ]; then + value=0x00 + else + echo "Invalid Parameters ${ONOFF_LED}, Exit!!!" + _help + exit ${FALSE} + fi + i2cset -m $mask -y -r ${I2C_BUS_FAN_BOARD} ${I2C_ADDR_FAN_BOARD} $ioPort $value + +} + +#Set System Status LED +function _i2c_sys_led { + local value=0 + local mask=${BIT_MASK[0]} + + if [ "${COLOR_LED}" == "green" ]; then + value=0xFF + elif [ "${COLOR_LED}" == "amber" ]; then + value=0x00 + else + echo "Invalid Parameters ${COLOR_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + _i2c_set_led $value $mask +} + +#Set FAN LED +function _i2c_fan_led { + local value=0 + local mask=${BIT_MASK[2]} + + if [ "${COLOR_LED}" == "green" ]; then + value=0x00 + elif [ "${COLOR_LED}" == "amber" ]; then + value=0xFF + else + echo "Invalid Parameters ${COLOR_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + _i2c_set_led $value $mask +} + +#Set PSU1 LED +function _i2c_psu1_led { + local value=0 + local mask=${BIT_MASK[3]} + + if [ "${COLOR_LED}" == "green" ]; then + value=0x00 + elif [ "${COLOR_LED}" == "amber" ]; then + value=0xFF + else + echo "Invalid Parameters ${COLOR_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + _i2c_set_led $value $mask +} + +#Set PSU2 LED +function _i2c_psu2_led { + local reg=${REG_OUT_0} + local value=0 + local mask=${BIT_MASK[4]} + + if [ "${COLOR_LED}" == "green" ]; then + value=0x00 + elif [ "${COLOR_LED}" == "amber" ]; then + value=0xFF + else + echo "Invalid Parameters ${COLOR_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + _i2c_set_led $value $mask +} + +#Set LEDs in LED Board +function _i2c_set_led { + local value=$1 + local mask=$2 + local reg=${REG_OUT_0} + local i2c_bus=$I2C_BUS_LED_BOARD + local i2c_addr=$I2C_ADDR_LED_BOARD + + _i2c_set $i2c_bus $i2c_addr $reg $mask $value +} + +#Reset all system leds +function _i2c_reset_led { + local mask=0xFF + local value=$((2#00000011)) + local reg=${REG_OUT_0} + local i2c_bus=$I2C_BUS_LED_BOARD + local i2c_addr=$I2C_ADDR_LED_BOARD + + _i2c_set $i2c_bus $i2c_addr $reg $mask $value +} + +#Get Mother Board Version and Type +function _i2c_board_type_get { + echo "=========================================================" + echo "# Description: I2C MB Board Type Get" + echo "=========================================================" + local i2c_bus=${I2C_BUS_ID_GPIO} + local i2c_addr=${I2C_ADDR_ID_GPIO} + local reg=${REG_IN_1} + local value=0 + + value=$(_i2c_get $i2c_bus $i2c_addr $reg) + + #Bit 0-1 + boardBuildRev=$((value & 0x03)) + #Bit 2-3 + boardHwRev=$((value >> 2 & 0x03)) + #Bit 4-7 + boardId=$((value>>4)) + printf "[MB BOARD_ID] = 0x%02x, [HW Rev] = %d, [Build Rev] = %d\n" $boardId $boardHwRev $boardBuildRev +} + +#Get Board Version and Type from Dummy BMC Board +function _i2c_bmc_board_type_get { + echo "=========================================================" + echo "# Description: I2C BMC Board Type Get" + echo "=========================================================" + + local i2c_bus=${I2C_BUS_BMC_BOARD_TYPE} + local i2c_addr=${I2C_ADDR_BMC_BOARD_TYPE} + local reg=${REG_IN_1} + local value=0 + + value=$(_i2c_get $i2c_bus $i2c_addr $reg) + + #Bit 0-1 + boardBuildRev=$((($value) & 0x03)) + #Bit 2-3 + boardHwRev=$((($value) >> 2 & 0x03)) + #Bit 4-7 + boardId=$((($value) >> 4)) + printf "[BMC BOARD_ID] = 0x%02x, [HW Rev] = %d, [Build Rev] = %d\n" $boardId $boardHwRev $boardBuildRev +} + +#Get CPLD Version +function _i2c_cpld_version { + echo "=========================================================" + echo "# Description: CPLD Version" + echo "=========================================================" + cat ${PATH_SYS_CPLD}/cpld_version +} + +#Get PSU Status +function _i2c_psu_status { + local psu_abs="" + + psu1PwGood=`cat ${PATH_SYSFS_PSU1}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU1}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu1Exist=1 + else + psu1Exist=0 + fi + + psu2PwGood=`cat ${PATH_SYSFS_PSU2}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU2}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu2Exist=1 + else + psu2Exist=0 + fi + + printf "PSU1 Exist:%x PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Set 10G Mux to CPU or Front Panel +function _i2c_10g_mux { + + echo "=========================================================" + echo "# Description: 10G Mux" + echo "=========================================================" + + local target=${TARGET_10G_MUX} + local i2c_bus=${I2C_BUS_10GMUX} + local i2c_addr=${I2C_ADDR_10GMUX} + local reg=0 + local mask=0xff + local value=0 + local file_10g_mux="${PATH_SYS_CPLD}/cpld_10g_mux" + + #get current 10g mux register value on CPLD + value=`cat ${file_10g_mux}` + + if [ "${target}" == "cpu" ]; then + #Set XE0: slave address access + _i2c_set $i2c_bus $i2c_addr 0x06 $mask 0x18 + #Set XE0: CH4 D_IN0-S_OUTA0 EQ + _i2c_set $i2c_bus $i2c_addr 0x2c $mask 0x00 + #Set XE0: CH5 NC-S_OUTB0 DEM + _i2c_set $i2c_bus $i2c_addr 0x35 $mask 0x80 + #Set XE0: CH5 NC-S_OUTB0 VOD + _i2c_set $i2c_bus $i2c_addr 0x34 $mask 0xab + #Set XE0: CH1 D_OUT0-S_INB0 EQ + _i2c_set $i2c_bus $i2c_addr 0x16 $mask 0x01 + #Set XE0: CH1 D_OUT0-S_INB0 DEM + _i2c_set $i2c_bus $i2c_addr 0x18 $mask 0x80 + #Set XE0: CH1 D_OUT0-S_INB0 VOD + _i2c_set $i2c_bus $i2c_addr 0x17 $mask 0xab + #Set XE1: CH6 D_IN1-S_OUTA1 EQ + _i2c_set $i2c_bus $i2c_addr 0x3a $mask 0x00 + #Set XE1: CH7 NC-S_OUTB1 EQ + _i2c_set $i2c_bus $i2c_addr 0x41 $mask 0x00 + #Set XE1: CH7 NC-S_OUTB1 DEM + _i2c_set $i2c_bus $i2c_addr 0x43 $mask 0x80 + #Set XE1: CH7 NC-S_OUTB1 VOD + _i2c_set $i2c_bus $i2c_addr 0x42 $mask 0xab + #Set XE1: CH3 D_OUT1-S_INB1 EQ + _i2c_set $i2c_bus $i2c_addr 0x24 $mask 0x01 + #Set XE1: CH3 D_OUT1-S_INB1 DEM + _i2c_set $i2c_bus $i2c_addr 0x26 $mask 0x80 + #Set XE1: CH3 D_OUT1-S_INB1 VOD + _i2c_set $i2c_bus $i2c_addr 0x25 $mask 0xab + #Enable auto negotiation of XE ports + eval "bcmcmd 'port xe0,xe1 an=1 if=kr en=1'" + #delay 1 sec + sleep 1 + + #switch 10G MUX to cpu on CPLD + value=$(( value & 0xf3 )) + echo "$(printf "%x" ${value})" > ${file_10g_mux} + + echo "Switch 10G Mux to [CPU]" + + elif [ "${COLOR_LED}" == "fp" ]; then + #Set XE0: slave address access + _i2c_set $i2c_bus $i2c_addr 0x06 $mask 0x18 + #Set XE0: CH4 D_IN0-S_OUTA0 EQ + _i2c_set $i2c_bus $i2c_addr 0x2c $mask 0x00 + #Set XE0: CH4 D_IN0-S_OUTA0 DEM + _i2c_set $i2c_bus $i2c_addr 0x2e $mask 0x80 + #Set XE0: CH4 D_IN0-S_OUTA0 VOD + _i2c_set $i2c_bus $i2c_addr 0x2d $mask 0xab + #Set XE0: CH0 NC-S_INA0 EQ + _i2c_set $i2c_bus $i2c_addr 0x0f $mask 0x00 + #Set XE0: CH1 D_OUT0-S_INB0 DEM + _i2c_set $i2c_bus $i2c_addr 0x18 $mask 0x80 + #Set XE0: CH1 D_OUT0-S_INB0 VOD + _i2c_set $i2c_bus $i2c_addr 0x17 $mask 0xab + #Set XE1: CH6 D_IN1-S_OUTA1 EQ + _i2c_set $i2c_bus $i2c_addr 0x3a $mask 0x00 + #Set XE1: CH6 D_IN1-S_OUTA1 DEM + _i2c_set $i2c_bus $i2c_addr 0x3c $mask 0x80 + #Set XE1: CH6 D_IN1-S_OUTA1 VOD + _i2c_set $i2c_bus $i2c_addr 0x3b $mask 0xab + #Set XE1: CH2 NC-S_INA1 EQ + _i2c_set $i2c_bus $i2c_addr 0x1d $mask 0x00 + #Set XE1: CH3 D_OUT1-S_INB1 DEM + _i2c_set $i2c_bus $i2c_addr 0x26 $mask 0x80 + #Set XE1: CH3 D_OUT1-S_INB1 VOD + _i2c_set $i2c_bus $i2c_addr 0x25 $mask 0xab + #Enable auto negotiation of XE ports + eval "bcmcmd 'port xe0,xe1 an=0 if=kr en=1'" + #delay 1 sec + sleep 1 + + #switch 10G MUX to front panel on CPLD + value=$(( value | 0x0c )) + echo "$(printf "%x" ${value})" > ${file_10g_mux} + + echo "Switch 10G Mux to [Front Panel]" + else + echo "invalid target, please set target to cpu/fp" + fi +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Main Function +function _main { + start_time_str=`date` + start_time_sec=$(date +%s) + + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_fan_init" ]; then + _i2c_fan_init + elif [ "${EXEC_FUNC}" == "i2c_volmon_init" ]; then + _i2c_volmon_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_cpu_eeprom_get" ]; then + _i2c_cpu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_INIT_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_cpu_eeprom_init" ]; then + _i2c_cpu_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_signal_get" ]; then + _i2c_qsfp_signal_get ${QSFP_PORT} ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_signal_set" ]; then + _i2c_qsfp_signal_set ${QSFP_PORT} ${QSFP_ACTION} ${QSFP_VALUE} + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_test" ]; then + _i2c_led_fan_tray_test + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_bmc_board_type_get" ]; then + _i2c_bmc_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_deinit + _i2c_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_cpu_eeprom_get + _i2c_board_type_get + _i2c_bmc_board_type_get + _i2c_cpld_version + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_10g_mux" ]; then + _i2c_10g_mux + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_monitor.sh new file mode 100755 index 000000000000..51c49c1152f5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_monitor.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, 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 . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..63}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1) ` + local identifier=`echo "$qsfp_type" | egrep -o 'identifier = .*$' | sed -e 's/identifier = //g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | egrep -o 'connector = .*$' | sed -e 's/connector = //g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_si_cfg.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_si_cfg.sh new file mode 100755 index 000000000000..ba59c50ca7bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_si_cfg.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, 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 . + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +TYPE=${1} +PORT=${2} + +#FIXME update SI values +#QSFP Optical +function _qsfp_optical_si_set { + local idx=0 + #FIXME + local si=(11 68 13 15 68 15 11 68 9 11 68 13 + 11 68 17 11 68 13 13 68 11 11 68 15 + 11 68 13 11 68 17 11 68 17 13 68 13 + 11 68 15 11 68 9 11 68 9 11 68 7 + 9 68 13 13 68 7 11 68 7 11 68 11 + 11 68 13 11 68 13 9 68 7 11 68 11 + 11 68 9 11 68 15 11 68 9 11 68 9 + 11 68 9 11 68 7 11 68 9 11 68 9 + 13 68 9 13 68 13 13 68 7 13 68 11 + 13 68 5 13 68 11 13 68 5 13 68 11 + + 11 68 3 11 68 9 11 68 5 11 68 13 + 11 68 9 11 68 9 11 68 11 13 68 5 + 13 68 3 11 68 7 11 68 5 11 68 9 + 11 68 9 13 68 9 13 68 1 11 68 11 + 5 68 1 11 68 7 11 68 1 13 68 3 + 11 68 5 11 68 3 11 68 7 11 68 3 + 11 68 3 13 68 11 13 68 1 13 68 3 + 11 68 1 13 68 1 13 68 1 11 68 7 + 11 68 1 11 68 5 11 68 1 9 68 5 + 5 68 1 13 68 1 11 68 5 11 68 3 + + 11 68 1 11 68 11 11 68 1 13 68 7 + 13 68 1 15 68 1 11 68 1 13 68 7 + 13 68 1 11 68 5 11 68 1 11 68 1 + 11 68 5 13 68 3 11 68 5 9 68 1 + 11 68 5 13 68 5 13 68 1 11 68 9 + 13 68 1 11 68 13 13 68 1 11 68 7 + 11 68 1 11 68 1 9 68 1 11 68 1 + 11 68 1 11 68 1 11 68 5 11 68 1 + 13 68 1 11 68 11 11 68 1 11 68 1 + 11 68 1 11 68 15 11 68 1 13 68 5 + + 11 68 1 11 68 1 9 68 1 13 68 1 + 11 68 1 11 68 1 9 68 1 11 68 1 + 11 68 1 13 68 3 11 68 1 13 68 1 + 11 68 1 13 68 1 11 68 1 11 68 13 + 11 68 1 11 68 1 11 68 1 11 68 1 + 11 68 11 11 68 1 13 68 1 11 68 1 + 11 68 1 11 68 9 11 68 1 11 68 7 + 11 68 1 13 68 1 13 68 1 11 68 1 + 11 68 1 11 68 5 11 68 1 13 68 3 + 11 68 3 9 68 1 11 68 3 11 68 1 + + 11 68 7 11 68 9 11 68 1 11 68 9 + 11 68 3 11 68 15 11 68 3 9 68 9 + 9 68 1 11 68 3 11 68 1 11 68 5 + 11 68 5 5 68 5 11 68 5 11 68 1 + 13 68 5 13 68 5 11 68 1 11 68 9 + 11 68 1 11 68 1 11 68 1 13 68 7 + 11 68 1 11 68 5 11 68 1 11 68 3 + 11 68 5 11 68 1 11 68 5 11 68 1 + 11 68 3 11 68 7 11 68 3 11 68 9 + 11 68 1 13 68 7 11 68 1 9 68 9 + + 13 68 1 11 68 5 11 68 3 13 68 5 + 11 68 7 11 68 11 13 68 5 9 68 5 + 11 68 5 11 68 13 13 68 7 11 68 13 + 11 68 7 11 68 11 11 68 5 11 68 11 + 11 68 11 11 68 11 11 68 7 11 68 11 + 11 68 13 11 68 11 11 68 9 15 68 9 + 11 68 11 11 68 5 11 68 7 13 68 11 + 11 68 9 13 68 17 11 68 7 11 68 13 + 11 68 11 11 68 17 11 68 13 11 68 15 + 13 68 9 13 68 11 11 68 11 13 68 7 + + 11 68 13 13 68 9 11 68 9 11 68 9 + 11 68 19 11 68 15 11 68 9 11 68 11 + 13 68 13 13 68 17 13 68 11 11 68 11 + 13 68 9 13 68 13 11 68 11 11 68 9) + + idx=$(( PORT * 12 )) + #FIXEME + #for j in {0..3} + #do + # bcmcmd "phy ce${PORT} CL93N72_UT_CTL2r.${j} CL93N72_TXFIR_POST=${si[idx++]}; phy ce${PORT} CL93N72_UT_CTL3r.${j} CL93N72_TXFIR_MAIN=${si[idx++]}; phy ce${PORT} CL93N72_UT_CTL2r.${j} CL93N72_TXFIR_PRE=${si[idx++]};" + #done +} + +function _qsfp_dac_si_set { + local idx=0 + # each port has 4 lanes, each lane has 3 SI values (post,main,pre), total 4*3=12 + local port_si=12 + + #si[0]: txfir_post for port0 lane0 + #si[1]: txfir_main for port0 lane0 + #si[2]: txfir_pre for port0 lane0 + + #si[3]: txfir_post for port0 lane1 + #si[4]: txfir_main for port0 lane1 + #si[5]: txfir_pre for port0 lane1 + + local si=(11 68 13 15 68 15 11 68 9 11 68 13 + 11 68 17 11 68 13 13 68 11 11 68 15 + 11 68 13 11 68 17 11 68 17 13 68 13 + 11 68 15 11 68 9 11 68 9 11 68 7 + 9 68 13 13 68 7 11 68 7 11 68 11 + 11 68 13 11 68 13 9 68 7 11 68 11 + 11 68 9 11 68 15 11 68 9 11 68 9 + 11 68 9 11 68 7 11 68 9 11 68 9 + 13 68 9 13 68 13 13 68 7 13 68 11 + 13 68 5 13 68 11 13 68 5 13 68 11 + + 11 68 3 11 68 9 11 68 5 11 68 13 + 11 68 9 11 68 9 11 68 11 13 68 5 + 13 68 3 11 68 7 11 68 5 11 68 9 + 11 68 9 13 68 9 13 68 1 11 68 11 + 5 68 1 11 68 7 11 68 1 13 68 3 + 11 68 5 11 68 3 11 68 7 11 68 3 + 11 68 3 13 68 11 13 68 1 13 68 3 + 11 68 1 13 68 1 13 68 1 11 68 7 + 11 68 1 11 68 5 11 68 1 9 68 5 + 5 68 1 13 68 1 11 68 5 11 68 3 + + 11 68 1 11 68 11 11 68 1 13 68 7 + 13 68 1 15 68 1 11 68 1 13 68 7 + 13 68 1 11 68 5 11 68 1 11 68 1 + 11 68 5 13 68 3 11 68 5 9 68 1 + 11 68 5 13 68 5 13 68 1 11 68 9 + 13 68 1 11 68 13 13 68 1 11 68 7 + 11 68 1 11 68 1 9 68 1 11 68 1 + 11 68 1 11 68 1 11 68 5 11 68 1 + 13 68 1 11 68 11 11 68 1 11 68 1 + 11 68 1 11 68 15 11 68 1 13 68 5 + + 11 68 1 11 68 1 9 68 1 13 68 1 + 11 68 1 11 68 1 9 68 1 11 68 1 + 11 68 1 13 68 3 11 68 1 13 68 1 + 11 68 1 13 68 1 11 68 1 11 68 13 + 11 68 1 11 68 1 11 68 1 11 68 1 + 11 68 11 11 68 1 13 68 1 11 68 1 + 11 68 1 11 68 9 11 68 1 11 68 7 + 11 68 1 13 68 1 13 68 1 11 68 1 + 11 68 1 11 68 5 11 68 1 13 68 3 + 11 68 3 9 68 1 11 68 3 11 68 1 + + 11 68 7 11 68 9 11 68 1 11 68 9 + 11 68 3 11 68 15 11 68 3 9 68 9 + 9 68 1 11 68 3 11 68 1 11 68 5 + 11 68 5 5 68 5 11 68 5 11 68 1 + 13 68 5 13 68 5 11 68 1 11 68 9 + 11 68 1 11 68 1 11 68 1 13 68 7 + 11 68 1 11 68 5 11 68 1 11 68 3 + 11 68 5 11 68 1 11 68 5 11 68 1 + 11 68 3 11 68 7 11 68 3 11 68 9 + 11 68 1 13 68 7 11 68 1 9 68 9 + + 13 68 1 11 68 5 11 68 3 13 68 5 + 11 68 7 11 68 11 13 68 5 9 68 5 + 11 68 5 11 68 13 13 68 7 11 68 13 + 11 68 7 11 68 11 11 68 5 11 68 11 + 11 68 11 11 68 11 11 68 7 11 68 11 + 11 68 13 11 68 11 11 68 9 15 68 9 + 11 68 11 11 68 5 11 68 7 13 68 11 + 11 68 9 13 68 17 11 68 7 11 68 13 + 11 68 11 11 68 17 11 68 13 11 68 15 + 13 68 9 13 68 11 11 68 11 13 68 7 + + 11 68 13 13 68 9 11 68 9 11 68 9 + 11 68 19 11 68 15 11 68 9 11 68 11 + 13 68 13 13 68 17 13 68 11 11 68 11 + 13 68 9 13 68 13 11 68 11 11 68 9) + + # get first si index for this port + idx=$(( PORT * port_si )) + + # loop for 4 lanes + for j in {0..3} + do + bcmcmd "phy ce${PORT} CL93N72_UT_CTL2r.${j} CL93N72_TXFIR_POST=${si[idx++]}; phy ce${PORT} CL93N72_UT_CTL3r.${j} CL93N72_TXFIR_MAIN=${si[idx++]}; phy ce${PORT} CL93N72_UT_CTL2r.${j} CL93N72_TXFIR_PRE=${si[idx++]};" + done +} + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} optical [0-63]" + echo " : ${0} dac [0-63]" + echo "----------------------------------------------------" +} + +#Main Function +function _main { + + if [ "${TYPE}" == "help" ]; then + _help + elif [ "${TYPE}" == "optical" ]; then + _qsfp_optical_si_set + elif [ "${TYPE}" == "dac" ]; then + _qsfp_dac_si_set + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/s9200_64x_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/s9200_64x_monitor.sh new file mode 100755 index 000000000000..974da6d5001f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/s9200_64x_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, 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 . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-inventec/.gitignore b/platform/broadcom/sonic-platform-modules-inventec/.gitignore new file mode 100644 index 000000000000..2490baa9d1e2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/.gitignore @@ -0,0 +1,59 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-inventec/LICENSE b/platform/broadcom/sonic-platform-modules-inventec/LICENSE new file mode 100644 index 000000000000..9cecc1d4669e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/platform/broadcom/sonic-platform-modules-inventec/common/utils/asic_monitor.py b/platform/broadcom/sonic-platform-modules-inventec/common/utils/asic_monitor.py new file mode 100755 index 000000000000..bcb05b9cb845 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/common/utils/asic_monitor.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Inventec, Inc. +# +# Editor: James Huang ( Huang.James@inventec.com ) +# +""" +Usage: %(scriptName)s [options] command object + +Auto detecting the Chipset temperature and update + +options: + -h | --help : this help message + -d | --debug : run with debug mode + +""" + +try: + import os + import commands + import sys, getopt + import logging + import re + import time + import syslog + from sonic_sfp.bcmshell import bcmshell + +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +args = [] +INV_REDWOOD_PLATFORM = "SONiC-Inventec-d7032-100" +INV_CYPRESS_PLATFORM = "SONiC-Inventec-d7054" +INV_SEQUOIA_PLATFORM = "SONiC-Inventec-d7264" +INV_MAPLE_PLATFORM = "SONiC-Inventec-d6556" +INV_MAGNOLIA_PLATFORM = "SONiC-Inventec-d6254qs" + +PSOC_NAME = "name" +HWMON_PATH = "/sys/class/hwmon/" +SWITCH_TEMP_FILE_NAME = "switch_tmp" + +def log_message( level, string ): + syslog.openlog("asic_monitor", syslog.LOG_PID, facility=syslog.LOG_DAEMON) + syslog.syslog( level, string ) + +def initialLoop(): + + global bcm_obj + initialNotOK = True + + while initialNotOK : + try: + bcm_obj = BCMUtil() + bcm_obj.execute_command("echo") + initialNotOK = False + print bcm_obj + log_message( syslog.LOG_INFO, "BCMUtil Object initialed successfully" ) + except Exception, e: + print "Exception. The warning is {0}".format(str(e)) + time.sleep(10) + +class BCMUtil(bcmshell): + + asic_temperature = 0 + platform = None + + def get_platform(self): + if self.platform is None: + self.platform = os.popen("uname -n").read().strip() + return self.platform + + def get_asic_temperature( self ): + return self.asic_temperature + + def set_asic_temperature( self, temp ): + self.asic_temperature = temp + + def parsing_asic_temp(self): + content = self.run("show temp") + for line in content.split("\n"): + TempObject = re.search(r"(average current temperature is)\s+(?P\d+)\.(?P\d+)",line) + if TempObject is not None: + self.set_asic_temperature( int( TempObject.group("temperature_high") ) ) + + def execute_command(self, cmd): + return self.run(cmd) + + +def main(): + + global bcm_obj + initialLoop() + log_message( syslog.LOG_INFO, "Object initialed successfully" ) + + while 1 : + try: + bcm_obj.parsing_asic_temp() + for index in os.listdir(HWMON_PATH): + file_list = os.listdir("{0}/{1}/device/".format(HWMON_PATH,index)) + if PSOC_NAME in file_list : + with open( "{0}/{1}/device/{2}".format(HWMON_PATH, index, PSOC_NAME), 'rb') as readPtr: + content = readPtr.read().strip() + if bcm_obj.get_platform() == INV_SEQUOIA_PLATFORM : + if content == "inv_bmc" and SWITCH_TEMP_FILE_NAME in file_list : + os.system("echo {0} > {1}/{2}/device/{3}".format( ( bcm_obj.get_asic_temperature() * 1000 ), HWMON_PATH, index, SWITCH_TEMP_FILE_NAME )) + break + else : + if content == "inv_psoc" and SWITCH_TEMP_FILE_NAME in file_list : + print "echo {0} > {1}/{2}/device/{3}".format( ( bcm_obj.get_asic_temperature() * 1000 ), HWMON_PATH, index, SWITCH_TEMP_FILE_NAME ) + os.system("echo {0} > {1}/{2}/device/{3}".format( ( bcm_obj.get_asic_temperature() * 1000 ), HWMON_PATH, index, SWITCH_TEMP_FILE_NAME )) + break + except Exception, e: + log_message( syslog.LOG_WARNING, "Exception. The warning is {0}".format(str(e)) ) + initialLoop() + time.sleep(5) + + syslog.closelog() + del bcm_obj + +if __name__ == "__main__": + main() + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/common/utils/led_proc.py b/platform/broadcom/sonic-platform-modules-inventec/common/utils/led_proc.py new file mode 100755 index 000000000000..bab0e2dafe76 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/common/utils/led_proc.py @@ -0,0 +1,372 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 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 . + +import os +import time +import syslog +import re +from sonic_sfp.bcmshell import bcmshell + + +# ===================================================================== +# global variable init +# ===================================================================== +# port object +PORT_LIST = [] +# object is to execute bcm shell command +BCM_SHELL = None +SHELL_READY = False +# port status that is auto update by chip in data ram +STATUS_RX = 1<<0 +STATUS_TX = 1<<1 +# define data ram address +PORT_DATA_OFFSET_ADDR = 0xA0 +# define board type +INV_MAGNOLIA = "SONiC-Inventec-d6254qs" +INV_REDWOOD = "SONiC-Inventec-d7032-100" +INV_CYPRESS = "SONiC-Inventec-d7054" +INV_MAPLE = "SONiC-Inventec-d6556" +INV_SEQUOIA = "" +BOARD_TPYE = "" +EAGLE_CORE = [] +# define port data for bit streaming +BIT_LINK = None +BIT_FAULT = None +BIT_TX = None +BIT_RX = None +BIT_SPEED0 = None +BIT_SPEED1 = None +# define port speed +SPEED_100G = 100 +SPEED_40G = 40 +SPEED_25G = 25 +SPEED_10G = 10 + + +# ===================================================================== +# class object +# ===================================================================== +class Port(): + + port_num = None + name = None + bcm_id = None + led_up = None + s_addr = None + write2_up = None + led_index = None + link_status = None + speed = None + + def write_data_ram(self, data): + BCM_SHELL.cmd("setreg CMIC_LEDUP{0}_DATA_RAM({1}) {2}".format(self.write2_up, self.led_index, data)) + + def read_data_ram(self): + r_string = BCM_SHELL.run("getreg CMIC_LEDUP{0}_DATA_RAM({1})".format(self.led_up, self.s_addr)) + for line in r_string.split("\n"): + re_obj = re.search(r"\.+)\>", line) + if re_obj is not None: + #syslog.syslog(syslog.LOG_DEBUG, "Read Led({0}) data_ram({1}): {2}".format(self.up, addr, re_obj.group("data"))) + return int(re_obj.group("data"), 16) + + + +# ===================================================================== +# Function +# ===================================================================== +def _remap_registers(fp): + + content = fp.readlines() + fp.close() + err = False + + for line in content: + try: + BCM_SHELL.cmd(line.rstrip()) + except Exception, e: + err = True + syslog.syslog(syslog.LOG_ERR, "remap register abnormal: {0}".format(str(e))) + + if not err: + syslog.syslog(syslog.LOG_INFO, "remap Led registers successfully") + + + +def _board_init(): + + global BOARD_TPYE + global BIT_LINK + global BIT_FAULT + global BIT_TX + global BIT_RX + global BIT_SPEED0 + global BIT_SPEED1 + global EAGLE_CORE + global TOTAL_SCAN_BITS + global SYNC_S + global SYNC_P + + cmd = "uname -n" + platform = os.popen(cmd).read() + + if platform.rstrip() == INV_MAGNOLIA: + BOARD_TPYE = "inventec_d6254qs" + BIT_RX = 1<<0 #0x01 + BIT_TX = 1<<1 #0x02 + BIT_SPEED1 = 1<<4 #0x10 + BIT_LINK = 1<<7 #0x80 + fp = open('/usr/share/sonic/device/x86_64-inventec_d6254qs-r0/led_proc_init.soc', "r") + _remap_registers(fp) + + elif platform.rstrip() == INV_REDWOOD: + BOARD_TPYE = "inventec_d7032q28b" + BIT_RX = 1<<0 #0x01 + BIT_TX = 1<<1 #0x02 + BIT_SPEED0 = 1<<3 #0x08 + BIT_SPEED1 = 1<<4 #0x10 + BIT_FAULT = 1<<6 #0x40 + BIT_LINK = 1<<7 #0x80 + EAGLE_CORE = [66, 100] + fp = open('/usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/led_proc_init.soc', "r") + _remap_registers(fp) + + elif platform.rstrip() == INV_CYPRESS: + BOARD_TPYE = "inventec_d7054q28b" + BIT_LINK = 1<<0 #0x01 + BIT_FAULT = 1<<1 #0x02 + BIT_SPEED0 = 1<<2 #0x04 + EAGLE_CORE = [66, 100] + + elif platform.rstrip() == INV_SEQUOIA: + BOARD_TPYE = "inventec_d7264q28b" + + elif platform.rstrip() == INV_MAPLE: + BOARD_TPYE = "inventec_d6556" + fp = open('/usr/share/sonic/device/x86_64-inventec_d6556-r0/led_proc_init.soc', "r") + _remap_registers(fp) + #led process: m0 led process that is controlled by linkscan_led_fw.bin and custom_led.bin + syslog.syslog(syslog.LOG_INFO, "Found device: {0}".format(BOARD_TPYE)) + exit(0) + + else: + BOARD_TPYE = "not found" + syslog.syslog(syslog.LOG_ERR, "Found device: {0}".format(BOARD_TPYE)) + exit(0) + + syslog.syslog(syslog.LOG_INFO, "Found device: {0}".format(BOARD_TPYE)) + + + +def _lookup_led_index(p): + + index = 0 + if BOARD_TPYE == "inventec_d6254qs": + if 0 <= p.port_num <= 47: + index = p.port_num + (p.port_num / 4) + p.write2_up = 0 + elif 48 <= p.port_num <= 71: + index = p.port_num - 48 + p.write2_up = 1 + if p.led_up == 0: + p.s_addr = p.port_num * 2 + elif p.led_up == 1: + p.s_addr = (p.port_num - 36) * 2 + + elif BOARD_TPYE == "inventec_d7032q28b": + p.write2_up = 0 + index = p.port_num + if 0 <= p.port_num <= 7: + p.s_addr = p.port_num * 8 + elif 8 <= p.port_num <= 23: + p.s_addr = (p.port_num - 8) * 8 + elif 24 <= p.port_num <= 31: + p.s_addr = (p.port_num - 16) * 8 + + else: + p.write2_up = p.led_up + for port in PORT_LIST: + if p.bcm_id == port.bcm_id: + break + if p.led_up == port.led_up: + index += 1 + + return PORT_DATA_OFFSET_ADDR + index + + +def _update_port_list(only_update): + + global PORT_LIST + number = 0 + count = 0 + + content = BCM_SHELL.run("ps") + for line in content.split("\n"): + re_obj = re.search(r"(?P(xe|ce)\d+)\(\s*(?P\d+)\)\s+(?P(up|down|!ena)).+\s+(?P\d+)G", line) + if re_obj is not None: + if int(re_obj.group("bcm_id")) not in EAGLE_CORE: + if only_update: + PORT_LIST[number].link_status = re_obj.group("link") + else: + # create port object while first time + port_obj = Port() + port_obj.port_num = number + port_obj.name = re_obj.group("port_name") + port_obj.bcm_id = int(re_obj.group("bcm_id")) + port_obj.link_status = re_obj.group("link") + port_obj.speed = int(re_obj.group("speed")) + PORT_LIST.append(port_obj) + number += 1 + + if not only_update: + content = BCM_SHELL.run("led status") + for line in content.split("\n"): + re_obj = re.search(r"(?P\d+).+(?P\d)\:", line) + if re_obj is not None: + if int(re_obj.group("bcm_id")) not in EAGLE_CORE: + PORT_LIST[count].led_up = int(re_obj.group("led_up")) + PORT_LIST[count].led_index = _lookup_led_index(PORT_LIST[count]) + count += 1 + + if number is not count: + PORT_LIST = [] + syslog.syslog(syslog.LOG_ERR, "The amount of port is not match") + + + +def sync_bcmsh_socket(): + + global BCM_SHELL + global SHELL_READY + waitSyncd = True + retryCount = 0 + + while waitSyncd: + time.sleep(10) + try: + BCM_SHELL = bcmshell() + BCM_SHELL.run("Echo") + waitSyncd = False + except Exception, e: + print "{0}, Retry times({1})".format(str(e),retryCount) + #syslog.syslog(syslog.LOG_DEBUG, "{0}, Retry times({1})".format(str(e),retryCount)) + retryCount += 1 + + syslog.syslog(syslog.LOG_INFO, "bcmshell socket create successfully") + + if SHELL_READY is False: + SHELL_READY = True + return + elif SHELL_READY is True: + update_led_status() + + + +def update_led_status(): + + led_thread = True # True/False (gate to turn on/off) + reset_sec = 2 + count_down = 0 + queue_active = [] + port_data = None + s_byte = None + + + # thread for keeping update port status in data ram + while led_thread: + try: + if count_down == 0: + queue_active = [] + _update_port_list(1) + for port in PORT_LIST: + if port.link_status == "up": + queue_active.append(port) + else: + port_data = 0 + port.write_data_ram(port_data) + count_down = reset_sec + else: + for port in queue_active: + port_data = 0 + + if BOARD_TPYE == "inventec_d6254qs": + s_byte = port.read_data_ram() + if s_byte&STATUS_RX: + port_data |= BIT_RX + if s_byte&STATUS_TX: + port_data |= BIT_TX + port_data |= BIT_LINK + + elif BOARD_TPYE == "inventec_d7032q28b": + s_byte = port.read_data_ram() + if s_byte&STATUS_RX: + port_data |= BIT_RX + if s_byte&STATUS_TX: + port_data |= BIT_TX + if port.speed == SPEED_100G: + port_data |= BIT_SPEED0 + port_data |= BIT_SPEED1 + elif port.speed == SPEED_40G: + port_data |= BIT_SPEED1 + elif port.speed == SPEED_25G: + port_data |= BIT_SPEED0 + else: + pass + port_data |= BIT_LINK + + elif BOARD_TPYE == "inventec_d7054q28b": + if port.speed != SPEED_100G and port.speed != SPEED_25G: + port_data |= BIT_SPEED0 + + # write data to update data ram for specific port + port.write_data_ram(port_data) + + time.sleep(0.5) + count_down -= 1 + + except Exception, e: + syslog.syslog(syslog.LOG_WARNING, "{0}".format(str(e))) + sync_bcmsh_socket() + + + +def debug_print(): + + for port in PORT_LIST: + output = "" + output += "name:{0} | ".format(port.name) + output += "port_num:{0} | ".format(port.port_num) + output += "bcm_id:{0} | ".format(port.bcm_id) + output += "link_status:{0} | ".format(port.link_status) + output += "speed:{0} | ".format(port.speed) + output += "led_up:{0} | ".format(port.led_up) + output += "s_addr:{0} | ".format(port.s_addr) + output += "write2_up:{0} | ".format(port.write2_up) + output += "led_index:{0} | ".format(port.led_index) + print output + + +if __name__ == "__main__": + + syslog.openlog("led_proc", syslog.LOG_PID, facility=syslog.LOG_DAEMON) + + sync_bcmsh_socket() + _board_init() + _update_port_list(0) + #debug_print() + update_led_status() + + syslog.closelog() diff --git a/platform/broadcom/sonic-platform-modules-inventec/common/utils/platform_status.py b/platform/broadcom/sonic-platform-modules-inventec/common/utils/platform_status.py new file mode 100755 index 000000000000..f1e7f7fece77 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/common/utils/platform_status.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +import os +import socket +from collections import OrderedDict + +# Purpose: Shutdown DUT upon receiving thermaltrip event from kernel (inv_pthread) + +NETLINK_KOBJECT_UEVENT = 15 + +class KernelEventMonitor(object): + + def __init__(self): + self.received_events = OrderedDict() + self.socket = socket.socket(socket.AF_NETLINK, socket.SOCK_DGRAM, NETLINK_KOBJECT_UEVENT) + + def start(self): + self.socket.bind((os.getpid(), -1)) + + def stop(self): + self.socket.close() + + def __enter__(self): + self.start() + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.stop() + + def __iter__(self): + while True: + for item in monitor.next_events(): + yield item + + def next_events(self): + data = self.socket.recv(16384) + event = {} + for item in data.split(b'\x00'): + if not item: + #check if we have an event and if we already received it + if event and event['SEQNUM'] not in self.received_events: + self.received_events[event['SEQNUM']] = None + if (len(self.received_events) > 100): + self.received_events.popitem(last=False) + yield event + event = {} + else: + try: + k, v = item.split(b'=', 1) + event[k.decode('ascii')] = v.decode('ascii') + except ValueError: + pass + +if __name__ == '__main__': + with KernelEventMonitor() as monitor: + for event in monitor: + if event['SUBSYSTEM'] == 'platform_status': + print('subsystem is platform_status') + + # Receive thermaltrip event + if event['ACTION'] == 'remove' and event['DEVPATH'] == '/kernel/platform_status/fan': + os.system("shutdown -h now") + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/common/utils/transceiver_monitor.py b/platform/broadcom/sonic-platform-modules-inventec/common/utils/transceiver_monitor.py new file mode 100755 index 000000000000..9e4a44c167fe --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/common/utils/transceiver_monitor.py @@ -0,0 +1,378 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Inventec, Inc. +# +# Editor: James Huang ( Huang.James@inventec.com ) +# +# + +""" +Usage: %(scriptName)s [options] command object + +Auto detecting the transceiver and set the correct if_type value + +options: + -h | --help : this help message + -d | --debug : run with debug mode + +""" + +try: + import os + import commands + import sys, getopt + import logging + import re + import time + import datetime + import syslog + from sfputil import SfpUtil + from sonic_sfp.bcmshell import bcmshell + +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +DEBUG = False +args = [] +INV_REDWOOD_PLATFORM = "SONiC-Inventec-d7032-100" +INV_CYPRESS_PLATFORM = "SONiC-Inventec-d7054" +INV_SEQUOIA_PLATFORM = "SONiC-Inventec-d7264" +INV_MAPLE_PLATFORM = "SONiC-Inventec-d6556" +INV_MAGNOLIA_PLATFORM = "SONiC-Inventec-d6254qs" + +transceiver_type_dict = { + "FCBG110SD1C03": "SR", + "FCBG110SD1C05": "SR", + "FTLX8571D3BCL": "SR", + "FTLX8574D3BCL": "SR", + "AFBR-709DMZ": "SR", + "AFBR-709SMZ": "SR", + "FTLX8571D3BCV": "SR", + "FTLX1471D3BCL": "SR", + "FTLX1871M3BCL": "SR", + "FTLF8536P4BCL": "SR", + "FCBG125SD1C05": "SR", + "FCBG125SD1C30": "SR", + "FCBG125SD1C03": "SR", + "FCBG410QB1C03-1E": "SR4", + "FCBG4100QB1C030-1E": "SR4", + "885350163": "SR4", + "88535017": "SR4", + "FTL410QE2C": "SR4", + "FTL410QD3C": "SR4", + "FTL410QD2C": "SR4", + "AFBR-79E3PZ": "SR4", + "AFBR-79Q4Z": "SR4", + "FTL4C1QE1C": "SR4", + "FTLC9551REPM": "SR4", + "FTLC1151RDPL": "SR4", + "DAC-010SS-X50" : "KR", + "DAC-010QQ-X50": "KR4", + "DAC-040QS-007": "KR4", + "DAC-040QQ-007": "KR4", + "DAC-040QQ-005": "KR4", + "DAC-040QS-005": "KR4", + "NDAAFF-0001": "KR4", + "L0HQF001-SD-R": "KR4", + "DAC-Q28/Q28-28-01": "KR4", + "NDAAFF-0003": "KR4", + "NDAQGF0001": "KR4", + "L0HQF003-SD-R": "KR4", + "NDAQGJ-0003": "KR4", + "L0HQF004-SD-R": "KR4", + "L0HSF006-SD-R": "KR", + "L0HSF007-SD-R": "KR", + "L0HSF008-SD-R": "KR", + "L0HQF009-SD-R": "KR4", + "FSPP-H7-M85-X3D": "SR", + "PT0-M3-4D33K-C2": "SR", + "RTXM228-551": "SR", + "RTXM330-003": "SR", + "RTXM330-030": "SR", + "MFA2P10-A005": "SR", + "QAB-OA03MC": "SR4", + "QAB-OA05MC": "SR4", + "RTXM320-571": "SR4", + "AFBR-89CDDZ": "SR4", + "RTXM420-550": "SR4", + "MMA1B00-C100D": "SR4", + "RTXM420-551": "SR4", + "E04025QTXA000": "SR4", + "LQ210PR-Oxxx": "SR4", + "TR-FC13L-N00": "SR4", + "SPQ-CE-LR-CDFL": "SR4", + "FIM37700/170": "SR4", + "FCBN425QE1C03": "SR4", + "TQS-Q14H8-XCAXX": "SR4", + "FPD-203R008-10/3": "SR4", + "LTA8531-PC+": "SR4" + } + +initial_command = [] + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def log_message( string ): + syslog.openlog("transceiver_monitor", syslog.LOG_PID, facility=syslog.LOG_DAEMON) + syslog.syslog(syslog.LOG_NOTICE, string) + +class BCMUtil(bcmshell): + + port_to_bcm_mapping = dict() + sal_config_list = dict() + eagle_list = [] + platform = None + + def get_platform(self): + if self.platform is None: + self.platform = os.popen("uname -n").read().strip() + return self.platform + + def get_port_to_bcm_mapping(self): + if self.port_to_bcm_mapping is None: + return dict() + else: + return self.port_to_bcm_mapping + + def show_port_to_bcm_mapping(self): + for key,value in self.port_to_bcm_mapping.iteritems(): + print "{0}---{1}".format(key, value) + + def get_eagle_port(self): + return self.eagle_list + + def parsing_eagle_port(self): + name = self.get_platform() + if name is not None: + if name == INV_REDWOOD_PLATFORM: + self.eagle_list = [66,100] + elif name == INV_CYPRESS_PLATFORM: + self.eagle_list = [66,100] + elif name == INV_SEQUOIA_PLATFORM: + self.eagle_list = [66,100] + elif name == INV_MAPLE_PLATFORM: + self.eagle_list = [66,130] + else: + self.eagle_list = [] + + def get_sal_config_list(self): + return self.sal_config_list + + def show_sal_config_list(self): + for key,value in self.sal_config_list.iteritems(): + print "{0}---{1}".format(key, value) + + def initial_sal_config_list( self ): + content = self.run("config") + for line in content.split("\n"): + ConfigObject = re.search(r"portmap\_(?P\d+)\=(?P\d+)\:\d+",line) + if ConfigObject is not None: + if int(ConfigObject.group("bcm_id")) not in self.get_eagle_port(): + self.get_sal_config_list()[int(ConfigObject.group("bcm_id"))]={"lane": int(ConfigObject.group("lane_id")), "speed": None, "portname": None} + + def parsing_port_list(self): + content = self.run("ps") + count = 0 + for line in content.split("\n"): + PSObject = re.search(r"(?P(xe|ce)\d+)\(\s*(?P\d+)\).+\s+(?P\d+)G",line) + if PSObject is not None: + if int(PSObject.group("bcm_id")) not in self.get_eagle_port(): + if self.get_sal_config_list().has_key(int(PSObject.group("bcm_id"))): + self.get_sal_config_list()[int(PSObject.group("bcm_id"))]["portname"] = PSObject.group("port_name") + self.get_sal_config_list()[int(PSObject.group("bcm_id"))]["speed"] = int(PSObject.group("speed"))*1000 + self.port_to_bcm_mapping[count] = int(PSObject.group("bcm_id")) + count = count +1 + + + def execute_command(self, cmd): + self.cmd(cmd) + +class TransceiverUtil(SfpUtil): + + transceiver_port_mapping = dict() + + def get_transceiver_port_mapping(self): + return self.transceiver_port_mapping + + def show_transceiver_port_mapping(self): + for key,value in self.transceiver_port_mapping.iteritems(): + print "{0}---{1}".format(key, value) + + def get_bcm_port_name(self, index): + if self.transceiver_port_mapping.has_key(index) and bcm_obj.get_sal_config_list().has_key(self.transceiver_port_mapping[index]["bcm"]): + return bcm_obj.get_sal_config_list()[self.transceiver_port_mapping[index]["bcm"]]["portname"] + else: + return "" + + def get_port_to_i2c_mapping(self): + if self.port_to_i2c_mapping is None: + return dict() + else: + return self.port_to_i2c_mapping + + def show_port_to_i2c_mapping(self): + for key,value in self.port_to_i2c_mapping.iteritems(): + print "{0}---{1}".format(key, value) + + def get_eeprom_partNum(self, portNum): + tempdict = dict() + tempdict = self.get_eeprom_dict(portNum) + self.get_eeprom_partNum_from_parser_eeprom_dict(tempdict) + + def get_eeprom_dict_info(self, portNum): + return self.get_eeprom_dict(portNum) + + def get_eeprom_partNum_from_parser_eeprom_dict(self, tempdict ): + if tempdict is not None: + if tempdict["interface"]["data"].has_key("VendorPN"): + return tempdict["interface"]["data"]["VendorPN"] + elif tempdict["interface"]["data"].has_key("Vendor PN"): + return tempdict["interface"]["data"]["Vendor PN"] + else: + return None + else: + return None + + def get_transceiver_type(self, pn ): + if pn is not None: + if transceiver_type_dict.has_key(pn.upper()): + return transceiver_type_dict[pn.upper()] + else: + return None + + def set_transceiver_type( self, portNum, pn ): + type = self.get_transceiver_type( pn ) + if type is not None: + if bcm_obj.get_platform() == INV_SEQUOIA_PLATFORM or bcm_obj.get_platform() == INV_MAPLE_PLATFORM : + speed = bcm_obj.get_sal_config_list()[self.transceiver_port_mapping[portNum]["bcm"]]["speed"] + bcm_obj.execute_command( "port %s if=%s speed=%d" % ( self.get_bcm_port_name(portNum), type, speed ) ) + else: + bcm_obj.execute_command( "port %s if=%s" % ( self.get_bcm_port_name(portNum), type ) ) + print "Detecting port {0}({1}) need to change interface type {2} ({3})".format( self.get_bcm_port_name(portNum), portNum, type, self.get_transceiver_port_mapping()[portNum]["pn"]) + log_message("Detecting port {0} need to change interface type {1} ({2})".format(self.get_bcm_port_name(portNum), type, self.get_transceiver_port_mapping()[portNum]["pn"]) ) + + def initial_transceiver_port_mapping(self): + for index in self.get_port_to_i2c_mapping().keys(): + if self.transceiver_port_mapping.has_key(index) is False : + i2cValue = self.get_port_to_i2c_mapping()[index] + bcmValue = bcm_obj.get_port_to_bcm_mapping()[index] + self.transceiver_port_mapping[index]={"i2c": i2cValue, "bcm": bcmValue , "pn": None} + + def set_power_mode_for_QSFP(self): + for index in self.get_port_to_i2c_mapping().keys(): + if index >= self.qsfp_port_start and index <= self.qsfp_port_end : + self.set_low_power_mode(index, False) + else: + # To set tx_disable + self.set_tx_disable(index) + + def set_tx_disable(self, port_num): + if port_num >= self.qsfp_port_start and port_num <= self.qsfp_port_end : + pass + else: + try: + tx_file = open("/sys/class/swps/port"+str(port_num)+"/tx_disable", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = int(tx_file.readline().rstrip()) + + # always set 0 to tx_disable field + if reg_value == 1 : + reg_value = 0 + tx_file.write(hex(reg_value)) + tx_file.close() + + +def main(): + + global DEBUG + global transceiver_obj + global bcm_obj + + initalNotOK = True + retestCount = 0 + while initalNotOK : + try: + transceiver_obj = TransceiverUtil() + bcm_obj = BCMUtil() + initalNotOK = False + except Exception, e: + log_message("Exception. The warning is {0}, Retry again ({1})".format(str(e),retestCount) ) + retestCount = retestCount + 1 + time.sleep(5) + + log_message( "Object initialed successfully" ) + options, args = getopt.getopt(sys.argv[1:], 'hd', ['help', + 'debug' + ]) + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + else: + logging.info("no option") + + initalNotOK = True + while initalNotOK : + try : + # Before loop, You could execute specific command to initial chip + for cmd_index in initial_command : + bcm_obj.execute_command(cmd_index) + + # Initial the sal config list + bcm_obj.parsing_eagle_port() + bcm_obj.initial_sal_config_list() + # bcm_obj.show_sal_config_list() + bcm_obj.parsing_port_list() + #bcm_obj.show_port_to_bcm_mapping() + #bcm_obj.show_sal_config_list() + # transceiver_obj.show_port_to_i2c_mapping() + + # Initial the transceiver_obj + transceiver_obj.initial_transceiver_port_mapping() + # transceiver_obj.show_transceiver_port_mapping() + + initalNotOK = False + except Exception, e: + log_message("Exception. The warning is {0}".format(str(e)) ) + time.sleep(5) + + # Improve the power mode for QSFP ports + transceiver_obj.set_power_mode_for_QSFP() + + while 1 : + try: + if bcm_obj.get_platform() == INV_SEQUOIA_PLATFORM: + bcm_obj.parsing_port_list() + for index in transceiver_obj.get_port_to_i2c_mapping().keys(): + info = transceiver_obj.get_eeprom_dict_info(index) + value = transceiver_obj.get_eeprom_partNum_from_parser_eeprom_dict(info) + if transceiver_obj.get_transceiver_port_mapping().has_key(index) is not False and transceiver_obj.get_transceiver_port_mapping()[index]["pn"] <> value: + transceiver_obj.get_transceiver_port_mapping()[index]["pn"] = value + transceiver_obj.set_transceiver_type(index,value) + transceiver_obj.set_tx_disable(index) + #transceiver_obj.show_transceiver_port_mapping() + # transceiver_obj.show_transceiver_port_mapping() + except Exception, e: + log_message("Exception. The warning is {0}".format(str(e)) ) + time.sleep(1) + + syslog.closelog() + del transceiver_obj + del bcm_obj + +if __name__ == "__main__": + main() + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/Makefile new file mode 100644 index 000000000000..13fc34c230c5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/Makefile @@ -0,0 +1,7 @@ +obj-m += inv_cpld.o inv_psoc.o +obj-m += inv_platform.o +obj-m += inv_eeprom.o +obj-m += swps.o +obj-m += inv_pthread.o +swps-objs := inv_swps.o io_expander.o transceiver.o + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_cpld.c new file mode 100644 index 000000000000..683ffa0ff3ce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/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/d6254qs/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_eeprom.c new file mode 100644 index 000000000000..3d13f3b04719 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/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/d6254qs/modules/inv_mux.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.c new file mode 100644 index 000000000000..a8a9a3c3df79 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.c @@ -0,0 +1,280 @@ +/* + * 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 "io_expander.h" +#include "inv_mux.h" + +static struct mux_obj_s *mux_head_p = NULL; + + +/* ========== MUX object functions ========== + */ +int +_common_force_pull_gpio(int mem_addr, + int input, + int bit_offset){ + + unsigned int val = 0; + unsigned int targ = 0; + + /* Get current value */ + val = inl(mem_addr); + if (val == 0) { + SWPS_ERR("%s: inl:%d fail!\n", __func__, val); + return -1; + } + /* Count target value */ + switch (input) { + case 0: /* Pull Low */ + targ = (val & (~(1 << bit_offset))); + break; + case 1: /* Pull high */ + targ = (val | (1 << bit_offset)); + break; + default: + SWPS_ERR("%s: input state:%d incorrect!\n", + __func__, input); + return -1; + } + /* Setup gpio */ + outl(targ, mem_addr); + if (targ != inl(mem_addr)){ + SWPS_ERR("%s: outl:%d fail!\n", __func__, targ); + return -1; + } + SWPS_DEBUG("%s: done.\n", __func__); + return 0; +} + + +int +rangeley_force_pull_high(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +rangeley_force_pull_low(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +hedera_force_pull_high(struct mux_obj_s *self){ + return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 1, 5); +} + + +int +hedera_force_pull_low(struct mux_obj_s *self){ + return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 0, 5); +} + + +int +normal_gpio_pull_high(struct mux_obj_s *self){ + return gpio_direction_output(self->gpio_num, 1); +} + + +int +normal_gpio_pull_low(struct mux_obj_s *self){ + return gpio_direction_output(self->gpio_num, 0); +} + + +int +pca9548_reset_mux_all(struct mux_obj_s *self){ + /* [Note] Power-on reset (PCA9548A-NXP) + * When power is applied to VDD, an internal Power-On Reset (POR) + * holds the PCA9548A in a reset condition until VDD has reached + * VPOR. At this point, the reset condition is released and the + * PCA9548A register and I2C-bus state machine are initialized to + * their default states (all zeroes) causing all the channels to + * be deselected. Thereafter, VDD must be lowered below 0.2 V for + * at least 5 us in order to reset the device. + */ + if (self->_pull_low(self) < 0) { + SWPS_ERR("%s: _pull_low fail!\n", __func__); + return -1; + } + mdelay(MUX_RST_WAIT_MS); + if (self->_pull_high(self) < 0) { + SWPS_ERR("%s: _pull_high fail!\n", __func__); + return -1; + } + mdelay(MUX_RST_WAIT_MS); + return 0; +} + + +int +common_reset_mux_all(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +init_gpio_4_force(struct mux_obj_s *self){ + return 0; +} + + +int +init_gpio_4_normal(struct mux_obj_s *self){ + + int err = 0; + + if (!gpio_is_valid(self->gpio_num)) { + SWPS_ERR("%s: GIPO:%d isn't valid\n", __func__, self->gpio_num); + return -1; + } + err = gpio_request(self->gpio_num, MUX_GPIO_LABEL); + if (err < 0) { + SWPS_ERR("%s: gpio_request fail :%d :%d\n", + __func__, err, self->gpio_num); + return -1; + } + SWPS_DEBUG("%s: gpio_request:%d ok.\n", __func__, self->gpio_num); + return 0; +} + + +static int +_setup_muxctl_cb(struct mux_obj_s *self, + unsigned gpio){ + + char mod_dsc[32] = "ERR"; + + switch (gpio) { + case MUX_RST_GPIO_FORCE_RANGELEY: + self->gpio_num = gpio; + self->_pull_low = rangeley_force_pull_low; + self->_pull_high = rangeley_force_pull_high; + self->_init = init_gpio_4_force; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Rangeley force mode"); + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_FORCE_HEDERA: + self->gpio_num = gpio; + self->_pull_low = hedera_force_pull_low; + self->_pull_high = hedera_force_pull_high; + self->_init = init_gpio_4_force; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Hedera force mode"); + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_48_PAC9548: + case MUX_RST_GPIO_69_PAC9548: + case MUX_RST_GPIO_249_PCA9548: + case MUX_RST_GPIO_505_PCA9548: + self->gpio_num = gpio; + self->_pull_low = normal_gpio_pull_low; + self->_pull_high = normal_gpio_pull_high; + self->_init = init_gpio_4_normal; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Normal mode :%d", (int)gpio); + goto ok_setup_muxctl_cb; + + default: + break; + } + SWPS_ERR("%s: Unexpected GPIO:%d\n", __func__, gpio); + return -1; + +ok_setup_muxctl_cb: + SWPS_INFO("muxctl: %s.\n", mod_dsc); + return 0; +} + + +/* ========== MUX public functions ========== + */ +void +clean_mux_gpio(void){ + + if (!mux_head_p) { + SWPS_DEBUG("%s: mux_head_p is NULL\n", __func__); + return; + } + if (gpio_is_valid(mux_head_p->gpio_num)) { + gpio_free(mux_head_p->gpio_num); + } + kfree(mux_head_p); + mux_head_p = NULL; + SWPS_DEBUG("%s: done.\n", __func__); +} + + +int +reset_mux_gpio(void){ + + if (!mux_head_p) { + SWPS_ERR("%s: MUX ctl object doesn't exist!\n", __func__); + return -1; + } + if (mux_head_p->reset(mux_head_p) < 0){ + SWPS_ERR("%s: reset fail!\n", __func__); + return -1; + } + return 0; +} + + +int +init_mux_gpio(unsigned gpio){ + + /* Create MUX control object */ + if (mux_head_p) { + SWPS_DEBUG("%s: mux_head_p is not NULL!\n", __func__); + clean_mux_gpio(); + } + /* Currently, it is using single muxctl architecture. + * In the future, it may use the multi-muxctl if HW add new features. + * (Ex: Port power-status control) + */ + mux_head_p = kzalloc(sizeof(struct mux_obj_s), GFP_KERNEL); + if (!mux_head_p) { + SWPS_ERR("%s: kzalloc fail!\n", __func__); + return -1; + } + /* Initial MUX controller */ + if (_setup_muxctl_cb(mux_head_p, gpio) < 0){ + SWPS_ERR("%s: _setup_muxctl_cb fail!\n", __func__); + return -1; + } + if (mux_head_p->_init(mux_head_p) < 0) { + SWPS_ERR("%s: init() fail\n", __func__); + goto err_init_mux_gpio; + } + /* Setup default value */ + if (mux_head_p->_pull_high(mux_head_p) < 0) { + SWPS_ERR("%s: setup default fail!\n", __func__); + goto err_init_mux_gpio; + } + return 0; + +err_init_mux_gpio: + clean_mux_gpio(); + return -1; +} + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.h b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.h new file mode 100644 index 000000000000..687a11b4e5be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.h @@ -0,0 +1,45 @@ +/* + * 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. + */ +#ifndef INV_MUX_H +#define INV_MUX_H + + +/* MUX basic information */ +#define MUX_GPIO_LABEL "SWPS_RST_MUX" + +/* MUX reset GPIO define */ +#define MUX_RST_GPIO_FORCE (30100) +#define MUX_RST_GPIO_FORCE_RANGELEY (30101) +#define MUX_RST_GPIO_FORCE_HEDERA (30102) +#define MUX_RST_GPIO_48_PAC9548 (48) +#define MUX_RST_GPIO_69_PAC9548 (69) +#define MUX_RST_GPIO_249_PCA9548 (249) +#define MUX_RST_GPIO_505_PCA9548 (505) + +/* MUX relate value define */ +#define MUX_RST_WAIT_MS (1) +#define MUX_RST_MEM_ADDR_RANGELEY (0) // TBD +#define MUX_RST_MEM_ADDR_HEDERA (0x548) + +struct mux_obj_s { + unsigned gpio_num; + int (*_pull_high)(struct mux_obj_s *self); + int (*_pull_low)(struct mux_obj_s *self); + int (*_init)(struct mux_obj_s *self); + int (*reset)(struct mux_obj_s *self); +}; + + +void clean_mux_gpio(void); +int reset_mux_gpio(void); +int init_mux_gpio(unsigned gpio); + + +#endif /* INV_MUX_H */ + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_platform.c new file mode 100644 index 000000000000..e69b526f4555 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_platform.c @@ -0,0 +1,243 @@ +/* + * 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 + +struct inv_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +///////////////////////////////////////////////////////////////////////////////////////// +static struct pca954x_platform_mode mux_modes_0[] = { + {.adap_id = 2,}, {.adap_id = 3,}, + {.adap_id = 4,}, {.adap_id = 5,}, + {.adap_id = 6,}, {.adap_id = 7,}, + {.adap_id = 8,}, {.adap_id = 9,}, +}; +static struct pca954x_platform_mode mux_modes_0_0[] = { + {.adap_id = 10,}, {.adap_id = 11,}, + {.adap_id = 12,}, {.adap_id = 13,}, + {.adap_id = 14,}, {.adap_id = 15,}, + {.adap_id = 16,}, {.adap_id = 17,}, +}; + +static struct pca954x_platform_mode mux_modes_0_1[] = { + {.adap_id = 18,}, {.adap_id = 19,}, + {.adap_id = 20,}, {.adap_id = 21,}, + {.adap_id = 22,}, {.adap_id = 23,}, + {.adap_id = 24,}, {.adap_id = 25,}, +}; + +static struct pca954x_platform_mode mux_modes_0_2[] = { + {.adap_id = 26,}, {.adap_id = 27,}, + {.adap_id = 28,}, {.adap_id = 29,}, + {.adap_id = 30,}, {.adap_id = 31,}, + {.adap_id = 32,}, {.adap_id = 33,}, +}; + +static struct pca954x_platform_mode mux_modes_0_3[] = { + {.adap_id = 34,}, {.adap_id = 35,}, + {.adap_id = 36,}, {.adap_id = 37,}, + {.adap_id = 38,}, {.adap_id = 39,}, + {.adap_id = 40,}, {.adap_id = 41,}, +}; + +static struct pca954x_platform_mode mux_modes_0_4[] = { + {.adap_id = 42,}, {.adap_id = 43,}, + {.adap_id = 44,}, {.adap_id = 45,}, + {.adap_id = 46,}, {.adap_id = 47,}, + {.adap_id = 48,}, {.adap_id = 49,}, +}; + +static struct pca954x_platform_mode mux_modes_0_5[] = { + {.adap_id = 50,}, {.adap_id = 51,}, + {.adap_id = 52,}, {.adap_id = 53,}, + {.adap_id = 54,}, {.adap_id = 55,}, + {.adap_id = 56,}, {.adap_id = 57,}, +}; + +static struct pca954x_platform_mode mux_modes_0_6[] = { + {.adap_id = 58,}, {.adap_id = 59,}, + {.adap_id = 60,}, {.adap_id = 61,}, + {.adap_id = 62,}, {.adap_id = 63,}, + {.adap_id = 64,}, {.adap_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 xlp_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 xlp_i2c_device_info1[] __initdata = { + {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc + {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld +}; + +static struct i2c_board_info xlp_i2c_device_info2[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0}, +}; + +static struct i2c_board_info xlp_i2c_device_info3[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0}, +}; + +static struct i2c_board_info xlp_i2c_device_info4[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0}, +}; + +static struct i2c_board_info xlp_i2c_device_info5[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0}, +}; +static struct i2c_board_info xlp_i2c_device_info6[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_4, 0, 0}, +}; +static struct i2c_board_info xlp_i2c_device_info7[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_5, 0, 0}, +}; +static struct i2c_board_info xlp_i2c_device_info8[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_6, 0, 0}, +}; + + +static struct inv_i2c_board_info i2cdev_list[] = { + {0, ARRAY_SIZE(xlp_i2c_device_info0), xlp_i2c_device_info0 }, //smbus 0 + + {2, ARRAY_SIZE(xlp_i2c_device_info2), xlp_i2c_device_info2 }, //mux 0 + {3, ARRAY_SIZE(xlp_i2c_device_info3), xlp_i2c_device_info3 }, //mux 1 + {4, ARRAY_SIZE(xlp_i2c_device_info4), xlp_i2c_device_info4 }, //mux 2 + {5, ARRAY_SIZE(xlp_i2c_device_info5), xlp_i2c_device_info5 }, //mux 3 + {6, ARRAY_SIZE(xlp_i2c_device_info6), xlp_i2c_device_info6 }, //mux 4 + {7, ARRAY_SIZE(xlp_i2c_device_info7), xlp_i2c_device_info7 }, //mux 5 + {8, ARRAY_SIZE(xlp_i2c_device_info8), xlp_i2c_device_info8 }, //mux 6 +}; + +///////////////////////////////////////////////////////////////////////////////////////// +static struct i2c_gpio_platform_data i2c_gpio_platdata = { + .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 platform_device magnolia_device_i2c_gpio = { + .name = "i2c-gpio", + .id = 0, // adapter number + .dev.platform_data = &i2c_gpio_platdata, +}; + +#define PLAT_MAX_I2C_CLIENTS 32 +static struct i2c_client *plat_i2c_client[PLAT_MAX_I2C_CLIENTS]; +static int num_i2c_clients = 0; +static int plat_i2c_client_add(struct i2c_client *e) +{ + if (num_i2c_clients >= PLAT_MAX_I2C_CLIENTS) + return -1; + + plat_i2c_client[num_i2c_clients] = e; + num_i2c_clients++; + return num_i2c_clients; +} + +static void plat_i2c_client_remove_all(void) +{ + int i; + for (i = num_i2c_clients-1; i >= 0; i--) + i2c_unregister_device(plat_i2c_client[i]); +} + +static int __init plat_magnolia_init(void) +{ + struct i2c_adapter *adap = NULL; + struct i2c_client *e = NULL; + int ret = 0; + int i,j; + + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "I2CHostCommunication.h" + +#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; + + u8 psu1_vendor[16]; + u8 psu2_vendor[16]; + u8 psu1_model[20]; + u8 psu2_model[20]; + u8 psu1_version[8]; + u8 psu2_version[8]; + u8 psu1_date[6]; + u8 psu2_date[6]; + u8 psu1_sn[20]; + u8 psu2_sn[20]; +}; + +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; +}; + +/*-----------------------------------------------------------------------*/ + +static ssize_t psoc_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 psoc_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 +} + +#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) + +#define PMBUS_MFR_ID (0x99) +#define PMBUS_MFR_MODEL (0x9A) +#define PMBUS_MFR_REVISION (0x9B) +#define PMBUS_MFR_DATE (0x9D) +#define PMBUS_MFR_SERIAL (0x9E) + +static int psoc_i2c_bridge_read(struct i2c_client *client, + unsigned char bus, + unsigned char chip, + char *addr, int alen, + unsigned char *data, int len ) +{ + unsigned char txdata[28], rxdata[28]; + int index, timeout; + + txdata[PSOC_I2C_STATUS] = 0; /* the status */ + txdata[PSOC_I2C_CNTRL] = ((alen & 3) << 5) | (len & 0x1f); /* the sizes */ + txdata[PSOC_I2C_ADDR] = (chip << 1) | PSOC_I2C_READ; /* read address */ + for(index = 0; index < alen; index++) + txdata[PSOC_I2C_DATA + index] = addr[index]; /* the chip address */ + for(; index < alen+len; index++) + txdata[PSOC_I2C_DATA + index] = 0; /* clear the chip data */ + + psoc_i2c_write(client, &txdata[PSOC_I2C_CNTRL], PSOC_I2C_CNTRL, 2 + alen + len); + + //delay a while ??? + //--------------------------------------------------------------------- + //start write + txdata[PSOC_I2C_STATUS] = PSOC_I2C_START | PSOC_PMB_SEL; /* the start bit for the PM bus */ + psoc_i2c_write(client, &txdata[PSOC_I2C_STATUS], PSOC_I2C_STATUS, 1); + + //delay a while + timeout = 40; //40*20==>800 ms + do { + psoc_i2c_read(client, &rxdata[PSOC_I2C_STATUS], PSOC_I2C_STATUS, 1); + + //check rxdata[5] error bit(1) and complete bit(0) ,TBD + if((rxdata[PSOC_I2C_STATUS] & 0x2) == 0x2) { + //printk("i2c bridge fail!!!\n"); + timeout = 0; + break; + } + if((rxdata[PSOC_I2C_STATUS] & PSOC_I2C_START) == 0) { + /* comand complete */ + psoc_i2c_read(client, &rxdata[PSOC_I2C_DATA+alen], PSOC_I2C_DATA+alen, len); + break; + } + + //delay + msleep(20); + } while(timeout--); + + if(timeout <= 0) { + return -1; + } + + //--------------------------------------------------------------------- + + for(index=0; index < len; index++) { + data[index] = rxdata[PSOC_I2C_DATA + alen + index]; + } + + return 0; +} + + +/* +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 */ + +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(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 reg = attr->index & 0xFF; + u8 len = ((attr->index & 0xFF00) >> 8); + u8 chip = (attr->index >> 16)? 0x59:0x58; + u8 bus = 1; + unsigned char value[2] = {0,0};; + + if (len == 2) + { + mutex_lock(&data->update_lock); + psoc_i2c_bridge_read(client, bus, chip, ®, 1, value, 2); + mutex_unlock(&data->update_lock); + + status = value[1]<<8 | value[0]; + //status1 = value[1]<<8 | value[0]; + + return sprintf(buf, "%ld\n", pmbus_reg2data_linear(status, (reg==PMBUS_READ_VOUT)?1:0) ); + } + else + { //len is not defined. + u8 tmpbuf[32]; + mutex_lock(&data->update_lock); + //length of block read + psoc_i2c_bridge_read(client, bus, chip, ®, 1, &len, 1); + //data included length + psoc_i2c_bridge_read(client, bus, chip, ®, 1, tmpbuf, len+1); + mutex_unlock(&data->update_lock); + + memcpy(buf, tmpbuf+1, len); + buf[len]='\n'; + + return len+1; + } +} + +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 & 0xFF) + PSU_INFO_OFFSET; + u8 len = (attr->index >> 8)& 0xFF; + u8 rxbuf[21] = {0}; + if (len == 2) + { + 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 )); + } + else + { + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client,rxbuf,offset,len); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s \n",rxbuf); + } +} + +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(temp6_input, 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(psu1_vin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_VIN); +static SENSOR_DEVICE_ATTR(psu1_vout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_VOUT); +static SENSOR_DEVICE_ATTR(psu1_iin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_IIN); +static SENSOR_DEVICE_ATTR(psu1_iout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_IOUT); +static SENSOR_DEVICE_ATTR(psu1_pin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_PIN); +static SENSOR_DEVICE_ATTR(psu1_pout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_POUT); + +static SENSOR_DEVICE_ATTR(psu1_vendor, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_ID); +static SENSOR_DEVICE_ATTR(psu1_model, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu1_version, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu1_date, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_DATE); +static SENSOR_DEVICE_ATTR(psu1_sn, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_SERIAL); + +static SENSOR_DEVICE_ATTR(psu2_vin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_VIN); +static SENSOR_DEVICE_ATTR(psu2_vout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_VOUT); +static SENSOR_DEVICE_ATTR(psu2_iin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_IIN); +static SENSOR_DEVICE_ATTR(psu2_iout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_IOUT); +static SENSOR_DEVICE_ATTR(psu2_pin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_PIN); +static SENSOR_DEVICE_ATTR(psu2_pout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_POUT); + +static SENSOR_DEVICE_ATTR(psu2_vendor, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_ID); +static SENSOR_DEVICE_ATTR(psu2_model, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu2_version, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu2_date, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_DATE); +static SENSOR_DEVICE_ATTR(psu2_sn, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_SERIAL); + +static SENSOR_DEVICE_ATTR(psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_pout)); + + +static SENSOR_DEVICE_ATTR(psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_pout)); + +static SENSOR_DEVICE_ATTR(psoc_psu1_vendor, S_IRUGO, show_psu_psoc, 0, (0x10<<8)|PSOC_PSU_OFF(psu1_vendor)); +static SENSOR_DEVICE_ATTR(psoc_psu1_model, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu1_model)); +static SENSOR_DEVICE_ATTR(psoc_psu1_version, S_IRUGO, show_psu_psoc, 0, (0x08<<8)|PSOC_PSU_OFF(psu1_version)); +static SENSOR_DEVICE_ATTR(psoc_psu1_date, S_IRUGO, show_psu_psoc, 0, (0x06<<8)|PSOC_PSU_OFF(psu1_date)); +static SENSOR_DEVICE_ATTR(psoc_psu1_sn, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu1_sn)); +static SENSOR_DEVICE_ATTR(psoc_psu2_vendor, S_IRUGO, show_psu_psoc, 0, (0x10<<8)|PSOC_PSU_OFF(psu2_vendor)); +static SENSOR_DEVICE_ATTR(psoc_psu2_model, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu2_model)); +static SENSOR_DEVICE_ATTR(psoc_psu2_version, S_IRUGO, show_psu_psoc, 0, (0x08<<8)|PSOC_PSU_OFF(psu2_version)); +static SENSOR_DEVICE_ATTR(psoc_psu2_date, S_IRUGO, show_psu_psoc, 0, (0x06<<8)|PSOC_PSU_OFF(psu2_date)); +static SENSOR_DEVICE_ATTR(psoc_psu2_sn, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu2_sn)); + +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, + &sensor_dev_attr_temp6_input.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, + + //psu + &sensor_dev_attr_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psu2_pout.dev_attr.attr, + + &sensor_dev_attr_psu1_vendor.dev_attr.attr, + &sensor_dev_attr_psu1_model.dev_attr.attr, + &sensor_dev_attr_psu1_version.dev_attr.attr, + &sensor_dev_attr_psu1_date.dev_attr.attr, + &sensor_dev_attr_psu1_sn.dev_attr.attr, + &sensor_dev_attr_psu2_vendor.dev_attr.attr, + &sensor_dev_attr_psu2_model.dev_attr.attr, + &sensor_dev_attr_psu2_version.dev_attr.attr, + &sensor_dev_attr_psu2_date.dev_attr.attr, + &sensor_dev_attr_psu2_sn.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, + + //add info + &sensor_dev_attr_psoc_psu1_vendor.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_model.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_version.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_date.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_sn.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vendor.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_model.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_version.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_date.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_sn.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; + + 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; + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.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/d6254qs/modules/inv_pthread.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_pthread.c new file mode 100644 index 000000000000..7d3287a591c6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_pthread.c @@ -0,0 +1,1312 @@ +/* + * 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. + */ + +/***************************** + Magnolia platform +******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SHOW_ATTR_WARNING ("N/A") +#define SHOW_ATTR_NOTPRINT ("Not Available") +#define SHOW_ATTR_NOTSUPPORT ("Not Support") + +#define INV_HWMID_MAX (10) +#define INV_HWMID_INIT (-1) + +/*access userspace data to kernel space*/ +#define ACC_R (0) +#define ACC_W (1) + +#define TINY_BUF_SIZE (8) +#define MAX_PATH_SIZE (64) +#define MIN_ACC_SIZE (32) +#define MAX_ACC_SIZE (256) + +/* + * LED definitions + */ +#define STATUS_LED_MODE_AUTO 0 +#define STATUS_LED_MODE_DIAG 1 +#define STATUS_LED_MODE_MANU 2 + +#define STATUS_LED_GRN0 10 // 0 - 000: off +#define STATUS_LED_GRN1 11 // 1 - 001: 0.5hz +#define STATUS_LED_GRN2 12 // 2 - 010: 1 hz +#define STATUS_LED_GRN3 13 // 3 - 011: 2 hz +#define STATUS_LED_GRN7 17 // 7 - 111: on +#define STATUS_LED_RED0 20 // 0 - 000: off +#define STATUS_LED_RED1 21 // 1 - 001: 0.5hz +#define STATUS_LED_RED2 22 // 2 - 010: 1 hz +#define STATUS_LED_RED3 23 // 3 - 011: 2 hz +#define STATUS_LED_RED7 27 // 7 - 111: on +#define STATUS_LED_INVALID 0 // Invalid + +ssize_t status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2); +ssize_t status_led_grn(const char *freq); +ssize_t status_led_red(const char *freq); +ssize_t status_led_diag_mode_enable(void); +ssize_t status_led_diag_mode_disable(void); +int status_led_check_color(void); +int status_led_check_diag_mode(void); + +#if 1 +/* For timestamps in SYSFS_LOG */ +#define SYSFS_LOG printk +#else +//#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[SYSFS] %s/%d: " fmt, __func__, __LINE__, ##args) +#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[p_thread] " fmt, ##args) +#endif + +#define INV_PTHREAD_KERNEL_MODULE (1) +#define SWITCH_HEALTH_LED_CHANGE_VIA_GPIO (1) + +/* inventec_class *********************************/ +static struct kobject *status_kobj; +static struct kset *status_kset; + + +static struct mutex rw_lock; + +static int hwm_psoc = INV_HWMID_INIT; +static int hwm_cpld = INV_HWMID_INIT; + +int get_hwm_psoc(void) +{ + return hwm_psoc; +} + +int get_hwm_cpld(void) +{ + return hwm_cpld; +} + +static ssize_t access_user_space(const char *name, int mode, char *buf, size_t len, loff_t offset) +{ + struct file *fp; + mm_segment_t fs; + loff_t pos = offset; + char *mark = NULL; + ssize_t vfs_ret = 0; + + if (mode == ACC_R) { + fp = filp_open(name, O_RDONLY, S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_read(fp, buf, len, &pos); + + mark = strpbrk(buf, "\n"); + if (mark) + *mark = '\0'; + + filp_close(fp, NULL); + set_fs(fs); + } else if (mode == ACC_W) { + fp = filp_open(name, O_WRONLY, S_IWUSR | S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_write(fp, buf, len, &pos); + filp_close(fp, NULL); + set_fs(fs); + } + + return vfs_ret; +} + +int inventec_strtol(const char *sbufp, char **endp, unsigned int base) +{ + char *endptr; + int value = simple_strtol(sbufp, &endptr, base); + if (value == 0 && sbufp == endptr) { + *endp = NULL; + return value; + } + *endp = (char*)1; + return value; +} + +int inventec_singlechar_to_int(const char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } + else + if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } + else + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } + return -1; +} + +int inventec_store_input(char *inputp, int count) +{ + int i = 0; + while(inputp[i] != '\n' && inputp[i] != '\0' && i < count) { + i++; + } + inputp[i] = '\0'; + return strlen(inputp); +} + +#if 0 +/* + * Time stamps for kernel log on yocto + */ +#include + +void SYSFS_LOG(char *fmt, ...) +{ + char buf[80], ts[32]; + va_list args; + int hlen; + + inventec_tmstmp(&ts[0]); + hlen = sprintf(buf, "[SYSFS] %s ", ts); // Do not edit this line + + va_start(args, fmt); + vsprintf(&buf[hlen-1], fmt, args); + va_end(args); + printk(KERN_WARNING "[p_thread] %s\n", buf); +} +#endif + +ssize_t +inventec_show_attr(char *buf_p, const char *invdevp) +{ + int inv_len = MAX_ACC_SIZE; /* INV driver return max length */ + char tmp_buf[MAX_ACC_SIZE]; + char *str_negative = "-", *mark = NULL; + + /* [Step2] Get data by uaccess */ + memset(tmp_buf, 0, sizeof(tmp_buf)); + mutex_lock(&rw_lock); + if (access_user_space(invdevp, ACC_R, tmp_buf, inv_len, 0) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + mutex_unlock(&rw_lock); + + /* [Step3] Check return value + * - Ex: When transceiver not plugged + * => SWPS return error code "-202" + * => Pic8 need return "NA" (assume) + */ + if (strcspn(tmp_buf, str_negative) == 0) { + /* error case: "-202" */ + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + + /* OK case:*/ + mark = strpbrk(tmp_buf, "\n"); + if (mark) { *mark = '\0'; } + + return sprintf(buf_p, "%s\n", tmp_buf); +} + +ssize_t +inventec_store_attr(const char *buf_p, size_t count, const char *invdevp) +{ + ssize_t ret = 0; + + /* [Step2] Get data by uaccess */ + mutex_lock(&rw_lock); + if ((ret = access_user_space(invdevp, ACC_W, (char*)buf_p, count, 0)) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return -EINVAL; + } + mutex_unlock(&rw_lock); + + /* OK case:*/ + return ret; +} + +int sysfs_detect_hwmon_index(void) +{ + char hwmon_buf[MAX_ACC_SIZE]; + char hwmon_path[MAX_PATH_SIZE]; + int hwid = 0; + + for (hwid = 0; + hwid < INV_HWMID_MAX && (hwm_psoc == INV_HWMID_INIT || hwm_cpld == INV_HWMID_INIT); + hwid++) { + memset(hwmon_buf, 0, sizeof(hwmon_buf)); + sprintf(hwmon_path, "/sys/class/hwmon/hwmon%d/device/name", hwid); + + inventec_show_attr(hwmon_buf, hwmon_path); + if (strncmp(hwmon_buf, "inv_psoc", 8) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_bmc", 7) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_cpld", 8) == 0) { + hwm_cpld = hwid; + } + } + if (hwid >= INV_HWMID_MAX) { + printk(KERN_ERR "[p_thread] detect hwmon index failed, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return -1; + } + printk(KERN_INFO "[p_thread] detect hwmon index success, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return 0; +} + +static int __init +inventec_class_init(void) +{ + mutex_init(&rw_lock); + +#ifdef INV_PTHREAD_KERNEL_MODULE + if (sysfs_detect_hwmon_index() < 0) { + return -1; + } +#endif + + printk(KERN_INFO "[p_thread] [%s/%d] Module initial success.\n",__func__,__LINE__); + + return 0; +} + +static void __exit +inventec_class_exit(void) +{ + printk(KERN_INFO "[p_thread] [%s/%d] Remove module.\n",__func__,__LINE__); +} + +/* fan device *************************************/ +#define FAN_DEV_PATH_STATE "/sys/class/hwmon/hwmon%d/device/fan_gpi" +#define FAN_DEV_PATH_FAN1_INPUT "/sys/class/hwmon/hwmon%d/device/fan1_input" +#define FAN_DEV_PATH_FAN2_INPUT "/sys/class/hwmon/hwmon%d/device/fan2_input" +#define FAN_DEV_PATH_FAN3_INPUT "/sys/class/hwmon/hwmon%d/device/fan3_input" +#define FAN_DEV_PATH_FAN4_INPUT "/sys/class/hwmon/hwmon%d/device/fan4_input" +#define FAN_DEV_PATH_FAN5_INPUT "/sys/class/hwmon/hwmon%d/device/fan5_input" +#define FAN_DEV_PATH_FAN6_INPUT "/sys/class/hwmon/hwmon%d/device/fan6_input" +#define FAN_DEV_PATH_FAN7_INPUT "/sys/class/hwmon/hwmon%d/device/fan7_input" +#define FAN_DEV_PATH_FAN8_INPUT "/sys/class/hwmon/hwmon%d/device/fan8_input" + +static char fan_dev_path_state[MAX_PATH_SIZE]; +static char fan_dev_path_fan1_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan2_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan3_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan4_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan5_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan6_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan7_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan8_input[MAX_PATH_SIZE]; + +void sysfs_fan_path_init(void) +{ + sprintf(&fan_dev_path_state[0], FAN_DEV_PATH_STATE, get_hwm_psoc()); + sprintf(&fan_dev_path_fan1_input[0],FAN_DEV_PATH_FAN1_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan2_input[0],FAN_DEV_PATH_FAN2_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan3_input[0],FAN_DEV_PATH_FAN3_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan4_input[0],FAN_DEV_PATH_FAN4_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan5_input[0],FAN_DEV_PATH_FAN5_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan6_input[0],FAN_DEV_PATH_FAN6_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan7_input[0],FAN_DEV_PATH_FAN7_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan8_input[0],FAN_DEV_PATH_FAN8_INPUT, get_hwm_psoc()); +} + +#define FAN_STATE_NORMAL "normal" +#define FAN_STATE_FAULTY "faulty" +#define FAN_STATE_UNINSTALLED "uninstalled" +#define FAN_STATE_UNKNOW "unknown state" +#define FAN_STATE_INVALID "Invalid state value" +#define FAN_STATE_READ_ERROR "state read error" + +#define FAN_LOG_UNINSTALLED "removed" +#define FAN_LOG_NORMAL "inserted" + +//#define FAN_STATE_BIT_NORMAL 0 +#define FAN_STATE_BIT_FAULTY 0 +#define FAN_STATE_BIT_UNINSTALLED 1 +#define FAN_STATE_BIT_UNKNOW 2 +#define FAN_STATE_BIT_INVALID 3 +#define FAN_STATE_BIT_READ_ERROR 4 + +static struct fans_tbl_s { + char *fan_name; + char *fan_front; + char *fan_rear; + unsigned int fan_state; +} fans_tbl[] = { + {"fan1", fan_dev_path_fan1_input, + fan_dev_path_fan2_input, 0}, + {"fan2", fan_dev_path_fan3_input, + fan_dev_path_fan4_input, 0}, + {"fan3", fan_dev_path_fan5_input, + fan_dev_path_fan6_input, 0}, + {"fan4", fan_dev_path_fan7_input, + fan_dev_path_fan8_input, 0}, +}; +#define FAN_TBL_TOTAL ( sizeof(fans_tbl)/ sizeof(const struct fans_tbl_s) ) + +#define FAN_STATE_CHECK(i,b) (fans_tbl[i].fan_state & (1< 0) + { + printk(KERN_ERR "[p_thread] All fans failed.\n"); + printk(KERN_ERR "[p_thread] System shutdown immediately in %d seconds.\n", cd_shutdown); + } + cd_shutdown -= 1; + } + return ret; +} + +/* End of faninfo_device */ + +static int __init +fan_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_fan_path_init(); +#endif + return 0; +} + + +static void __exit +fan_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove fan module.\n"); +} + +/* psu device *************************************/ +static unsigned int psu_voltin = 0; +#define PSU_VOLTIN_ACDC (70000) + +/* + * normal/unpower/uninstall/fault are PSU states output from driver level + * checkpsu/error are defined by sysfs + */ +#define PSU_STATE_VAL_NORMAL (0) +#define PSU_STATE_VAL_UNPOWER (2) +#define PSU_STATE_VAL_FAULT (4) +#define PSU_STATE_VAL_UNINSTALL (7) +#define PSU_STATE_VAL_CHECKPSU (8) +#define PSU_STATE_VAL_ERROR (9) + +#define PSU_STATE_NORMAL ("0 : normal") +#define PSU_STATE_UNPOWER ("2 : unpowered") +#define PSU_STATE_FAULT ("4 : fault") +#define PSU_STATE_UNINSTALL ("7 : not installed") +#define PSU_STATE_CHECKPSU ("8 : check psu") +#define PSU_STATE_ERROR ("9 : state error") + +#define PSU_STATE_LEN_NORMAL (strlen(PSU_STATE_NORMAL)) +#define PSU_STATE_LEN_UNPOWER (strlen(PSU_STATE_UNPOWER)) +#define PSU_STATE_LEN_FAULT (strlen(PSU_STATE_FAULT)) +#define PSU_STATE_LEN_UNINSTALL (strlen(PSU_STATE_UNINSTALL)) +#define PSU_STATE_LEN_CHECKPSU (strlen(PSU_STATE_CHECKPSU)) + +typedef struct { + char *inv_dev_attrp; + char *inv_dev_pathp; +} psu_dev_t; + +typedef struct { + const char *psu_name; + int psu_major; + dev_t psu_devt; + struct device *psu_dev_p; + psu_dev_t *psu_dev_namep; + int psu_dev_total; + char *psu_inv_pathp; + void *psu_tracking; + char *psu_currentin; + char *psu_currentout; + char *psu_powerin; + char *psu_powerout; + char *psu_voltin; + char *psu_voltout; +} psu_dev_group_t; + +#define PSU_DEV_PATH_TEMPLATE "/sys/class/hwmon/hwmon%d/device/%s" + +static char psu_dev_path_state[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltin[MAX_PATH_SIZE]; +#if 0 +static char psu_dev_path_vendor[MAX_PATH_SIZE]; +static char psu_dev_path_version[MAX_PATH_SIZE]; +static char psu_dev_path_sn[MAX_PATH_SIZE]; +static char psu_dev_path_temperature[MAX_PATH_SIZE]; +static char psu_dev_path_fan_speed[MAX_PATH_SIZE]; +static char psu_dev_path_fan_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_fan_faulty[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_psu_rpm[MAX_PATH_SIZE]; +#endif + +void sysfs_psu_path_init(void) +{ + sprintf(&psu_dev_path_state[0], PSU_DEV_PATH_TEMPLATE, get_hwm_cpld(), "\%s" ); + sprintf(&psu_dev_path_psu_voltin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#if 0 + sprintf(&psu_dev_path_vendor[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_version[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_sn[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_temperature[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_speed[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_faulty[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_voltout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_rpm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#endif +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +#if 0 + { "vendor", psu_dev_path_vendor }, + { "version", psu_dev_path_version }, + { "sn", psu_dev_path_sn }, + { "temperature", psu_dev_path_temperature }, + { "fan_speed", psu_dev_path_fan_speed }, + { "fan_pwm", psu_dev_path_fan_pwm }, + { "fan_faulty", psu_dev_path_fan_faulty }, + { "psu_currentin", psu_dev_path_psu_currentin }, + { "psu_currentout", psu_dev_path_psu_currentout }, + { "psu_powerin", psu_dev_path_psu_powerin }, + { "psu_powerout", psu_dev_path_psu_powerout }, + { "psu_voltout", psu_dev_path_psu_voltout }, + { "psu_pwm", psu_dev_path_psu_pwm }, + { "psu_rpm", psu_dev_path_psu_rpm }, +#endif +}; +#define PSU_DEV_NAME_TOTAL ( sizeof(psu_dev_name) / sizeof(const psu_dev_t) ) + +static psu_dev_group_t psu_dev_group[] = { + { + .psu_name = "psu1", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, + { + .psu_name = "psu2", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, +}; +#define PSU_DEV_GROUP_TOTAL ( sizeof(psu_dev_group)/ sizeof(const psu_dev_group_t) ) + +static char psu_state[4][MIN_ACC_SIZE]; + +static struct psu_wire_tbl_s { + char *psu_attr; + char *psu_name; + char *psu_wire; + char *psu_state; +} psu_wire_tbl[] = { + { "state", "psu1", "psu0", psu_state[0] }, // Using cpld + { "state", "psu2", "psu1", psu_state[1] }, + { "psu_voltin", "psu1", "psoc_psu1_vin", psu_state[2] }, + { "psu_voltin", "psu2", "psoc_psu2_vin", psu_state[3] }, +}; +#define PSU_WIRE_TBL_TOTAL ( sizeof(psu_wire_tbl)/ sizeof(const struct psu_wire_tbl_s) ) + +static char * +psu_attr_get_wirep(const char *psu_attrp, const char *psu_namep, char **psu_statepp) +{ + int i; + + for (i = 0; i < PSU_WIRE_TBL_TOTAL; i++) { + if (strncmp(psu_wire_tbl[i].psu_attr, psu_attrp, strlen(psu_attrp)) == 0 && + strncmp(psu_wire_tbl[i].psu_name, psu_namep, strlen(psu_namep)) == 0) { + if (psu_statepp) { + *psu_statepp = psu_wire_tbl[i].psu_state; + } + return psu_wire_tbl[i].psu_wire; + } + } + return NULL; +} + +int psu_check_state_normal(char *statep) +{ + if (strstr(statep, "normal")) { + return 1; + } + return 0; +} + +#define PSU_ATTR_VOLTIN ("psu_voltin") +#define PSU_ATTR_VOLTIN_LEN (10) + +/* Get PSU voltin for determon AC(110v) or DC(48v) */ +void psu_get_voltin(void) +{ + char acc_path[MAX_PATH_SIZE], volt[MIN_ACC_SIZE]; + psu_dev_t *devnamep; + unsigned int voltin; + char *invwirep; + int i, j; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + //psu_dev_group[i].psu_name; + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_VOLTIN, PSU_ATTR_VOLTIN_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_VOLTIN, psu_dev_group[i].psu_name, NULL); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_DEBUG "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(volt, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + continue; + } + else { + voltin = simple_strtol(&volt[0], NULL, 10); + printk(KERN_DEBUG "[p_thread] Read %s %s = %u\n",acc_path,volt,voltin); + if (voltin > psu_voltin) { + psu_voltin = voltin; + } + } + } + } + } + + SYSFS_LOG("[p_thread] PSU voltin = %u\n", psu_voltin); +} + +#define PSU_ATTR_STATE ("state") +#define PSU_ATTR_STATE_LEN (5) + +/* psus_control() by inv_thread */ +int psus_control(int log_only) +{ + char acc_path[MAX_PATH_SIZE], state[MIN_ACC_SIZE]; + psu_dev_t *devnamep = NULL; + char *invwirep = NULL; + char *psu_statep = NULL; + int i, j, flag = 0; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_STATE, PSU_ATTR_STATE_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_STATE, psu_dev_group[i].psu_name, &psu_statep); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_INFO "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(state, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + if (strncmp(psu_statep, PSU_STATE_ERROR, strlen(PSU_STATE_ERROR)) != 0) { + strcpy(psu_statep, PSU_STATE_ERROR); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_ERROR); + } + flag = 1; + } + else + if (strstr(state, "normal")) { + //printk(KERN_INFO "[p_thread] %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + } + else + if (psu_voltin > PSU_VOLTIN_ACDC) { /* AC PSUS */ + //printk(KERN_INFO "[p_thread] RYU: %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + flag = 1; + } + else { /* DC PSUS */ + if (strncmp(psu_statep, PSU_STATE_CHECKPSU, PSU_STATE_LEN_CHECKPSU) != 0) { + strcpy(psu_statep, PSU_STATE_CHECKPSU); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_CHECKPSU); + } + flag = 1; + } + } + } + } + + if (log_only) { + return 0; + } + + //SYSFS_LOG("[p_thread] RYU: %s: flag = %d\n",psu_wire_tbl[i].psu_name,flag); + if (flag == 1) { + status_led_grn("3"); + return 1; + } + return 0; +} + +/* End of psuinfo_device */ + +static int __init +psu_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_psu_path_init(); +#endif + return 0; +} + + +static void __exit +psu_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove psu module.\n"); +} + +/* led device *************************************/ +#define STATUS_LED_GRN_PATH "/sys/class/hwmon/hwmon%d/device/grn_led" +#define STATUS_LED_RED_PATH "/sys/class/hwmon/hwmon%d/device/red_led" + +#define FAN_LED_GRN1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn1" +#define FAN_LED_GRN2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn2" +#define FAN_LED_GRN3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn3" +#define FAN_LED_GRN4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn4" +#define FAN_LED_RED1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red1" +#define FAN_LED_RED2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red2" +#define FAN_LED_RED3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red3" +#define FAN_LED_RED4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red4" + +#define HWMON_DEVICE_DIAG_PATH "/sys/class/hwmon/hwmon%d/device/diag" +#define HWMON_DEVICE_CTRL_PATH "/sys/class/hwmon/hwmon%d/device/ctl" + +static char status_led_grn_path[MAX_PATH_SIZE]; +static char status_led_red_path[MAX_PATH_SIZE]; +static char fan_led_grn1_path[MAX_PATH_SIZE]; +static char fan_led_grn2_path[MAX_PATH_SIZE]; +static char fan_led_grn3_path[MAX_PATH_SIZE]; +static char fan_led_grn4_path[MAX_PATH_SIZE]; +static char fan_led_red1_path[MAX_PATH_SIZE]; +static char fan_led_red2_path[MAX_PATH_SIZE]; +static char fan_led_red3_path[MAX_PATH_SIZE]; +static char fan_led_red4_path[MAX_PATH_SIZE]; +static char hwmon_device_diag_path[MAX_PATH_SIZE]; +static char hwmon_device_ctrl_path[MAX_PATH_SIZE]; + +void sysfs_led_path_init(void) +{ + sprintf(&status_led_grn_path[0], STATUS_LED_GRN_PATH, get_hwm_cpld()); + sprintf(&status_led_red_path[0], STATUS_LED_RED_PATH, get_hwm_cpld()); + sprintf(&fan_led_grn1_path[0], FAN_LED_GRN1_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn2_path[0], FAN_LED_GRN2_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn3_path[0], FAN_LED_GRN3_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn4_path[0], FAN_LED_GRN4_PATH, get_hwm_psoc()); + sprintf(&fan_led_red1_path[0], FAN_LED_RED1_PATH, get_hwm_psoc()); + sprintf(&fan_led_red2_path[0], FAN_LED_RED2_PATH, get_hwm_psoc()); + sprintf(&fan_led_red3_path[0], FAN_LED_RED3_PATH, get_hwm_psoc()); + sprintf(&fan_led_red4_path[0], FAN_LED_RED4_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_diag_path[0], HWMON_DEVICE_DIAG_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_ctrl_path[0], HWMON_DEVICE_CTRL_PATH, get_hwm_cpld()); +} + +/* return 0/off 1/green 2/red */ +int +status_led_check_color(void) +{ + char tmpbuf[MIN_ACC_SIZE]; + int ret = STATUS_LED_INVALID; + + if (inventec_show_attr(&tmpbuf[0], status_led_grn_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_GRN0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_GRN1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_GRN2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_GRN3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_GRN7; + } + return ret; + } + + if (inventec_show_attr(&tmpbuf[0], status_led_red_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_RED0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_RED1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_RED2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_RED3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_RED7; + } + return ret; + } + return ret; +} + +/* + * Store attr Section + */ +static DEFINE_MUTEX(diag_mutex); + +ssize_t status_led_diag_mode_enable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '0') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("1", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + mutex_unlock(&diag_mutex); + } + + return ret; +} + +ssize_t status_led_diag_mode_disable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '1') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("0", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + mutex_unlock(&diag_mutex); + } + return 1; +} + +ssize_t +status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2) +{ + ssize_t ret; + + ret = inventec_store_attr(tmp1, strlen(tmp1), path1); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(tmp2, strlen(tmp2), path2); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_red(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_grn_path[0]); + + if (ret < 0) { + return ret; + } + + ret = inventec_store_attr(freq, strlen(freq), &status_led_red_path[0]); + + if (ret < 0) { + return ret; + } + + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_grn(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +static int status_led_diag_mode = STATUS_LED_MODE_AUTO; + +int status_led_check_diag_mode(void) +{ + return status_led_diag_mode; +} + +/* End of ledinfo_device */ + +static int __init +led_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); +#endif + return 0; +} + + +static void __exit +led_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove led module.\n"); +} + +/* sensor device **********************************/ +#define SENSOR_DEV_PATH_SWITCH_TEMP "/sys/class/hwmon/hwmon%d/device/switch_tmp" + +static char sensor_dev_path_switch_temp[MAX_PATH_SIZE]; + +void sysfs_sensor_path_init(void) +{ + sprintf(&sensor_dev_path_switch_temp[0], SENSOR_DEV_PATH_SWITCH_TEMP, get_hwm_psoc()); +} + +void switch_temp_update(void) +{ + char buf[MIN_ACC_SIZE]; + ssize_t count = inventec_show_attr(&buf[0], "proc/switch/temp"); + if (count > 0) { + //printk(KERN_ERR "[p_thread] [STEMP] Switch temperature is out of range: %d\n", stemp); + inventec_store_attr(&buf[0], count, sensor_dev_path_switch_temp); + } +} + +/**************************************************/ +/* From system_device */ +static int inv_pthread_control = 1; + +int thread_control(void) +{ + return inv_pthread_control; +} + +void thread_control_set(int val) +{ + inv_pthread_control = val; +} +/* End system_device */ + +#define THREAD_SLEEP_MINS (3) +#define THREAD_DELAY_MINS (THREAD_SLEEP_MINS + THREAD_SLEEP_MINS + 1) + +extern void psu_get_voltin(void); + +static struct task_struct *thread_st; +static int thread_data; + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO +void led_set_gpio_to_change_status_led(void) +{ + ssize_t ret = inventec_store_attr("253", 3, "/sys/class/gpio/export"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 253 to /sys/class/gpio/export failed\n"); + return; + } + + printk("[p_thread] Write 253 to /sys/class/gpio/export\n"); + + ret = inventec_store_attr("out", 3, "/sys/class/gpio/gpio253/direction"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write low to /sys/class/gpio/gpio253/direction failed\n"); + return; + } + + //pull high and then low + ret = inventec_store_attr("1", 1, "sys/class/gpio/gpio253/value"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 1 to sys/class/gpio/gpio253/value failed\n"); + } + + //pull low + ret = inventec_store_attr("0", 1, "sys/class/gpio/gpio253/value"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 0 to sys/class/gpio/gpio253/value failed\n"); + } + + SYSFS_LOG("[p_thread] Set gpio to support status led change successfully\n"); +} +#endif + +// Function executed by kernel thread +static int thread_fn(void *unused) +{ + /* Delay for guarantee HW ready */ + ssleep(THREAD_DELAY_MINS); + +#ifndef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); + sysfs_fan_path_init(); + sysfs_psu_path_init(); +#endif + //sysfs_sensor_path_init(); + + /* Default status init */ + status_led_grn("7"); + + psu_get_voltin(); + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO + led_set_gpio_to_change_status_led(); +#endif + + while (1) + { + ssleep(THREAD_SLEEP_MINS); + + if (thread_control() == 0) { + printk(KERN_INFO "[p_thread] %s/%d: Thread Stop by inv_pthread control\n",__func__,__LINE__); + break; + } + + if (status_led_check_diag_mode() == STATUS_LED_MODE_MANU) { + /* status led in change color/freq mode, higher priority. Ignore fans sttaus */ + continue; + } + + //switch_temp_update(); + + if (fans_control() > 0) { + psus_control(1); + continue; + } + else + if (psus_control(0) > 0) { + continue; + } + + if (status_led_check_color() != STATUS_LED_GRN7) { /* status led red, change it to green */ + status_led_grn("7"); + } + } + +#ifndef INV_PTHREAD_KERNEL_MODULE +err_inv_pthread_fn_1: +#endif + do_exit(0); + printk(KERN_INFO "[p_thread] %s/%d: Thread Stopped\n",__func__,__LINE__); + return 0; +} + + +static ssize_t s_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + int fan_absence; + size_t count; + + fan_absence = fans_control(); + count += sprintf(&buf[count], "%d\n", fan_absence); + return count; +} + +static ssize_t s_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) +{ + return count; +} + +static struct attribute status_att = { + .name = "fan_absence", + .mode = 0777, +}; + +static const struct sysfs_ops status_ops = { + .show = s_show, + .store = s_store, +}; + +static struct kobj_type status_ktype = { + .sysfs_ops = &status_ops, +}; + + +static int __init inv_pthread_init(void) +{ + int retval; + + status_kobj = kzalloc(sizeof(*status_kobj), GFP_KERNEL); + if(!status_kobj) + return PTR_ERR(status_kobj); + + status_kset = kset_create_and_add("platform_status", NULL, kernel_kobj); + if(!status_kset) + return -1; + + status_kobj->kset = status_kset; + + retval = kobject_init_and_add(status_kobj, &status_ktype, NULL, "fan"); + if(retval) + return retval; + + retval = sysfs_create_file(status_kobj, &status_att); + + + inventec_class_init(); + fan_device_init(); + psu_device_init(); + led_device_init(); + + thread_control_set(1); + + printk(KERN_INFO "[p_thread] %s/%d: Creating Thread\n",__func__,__LINE__); + //Create the kernel thread with name 'inv_pthread' + thread_st = kthread_run(thread_fn, (void*)&thread_data, "inv_pthread"); + if (thread_st) + printk(KERN_INFO "[p_thread] inv_pthread Created successfully\n"); + else + printk(KERN_ERR "[p_thread] inv_pthread creation failed\n"); + + return retval; +} + +static void __exit inv_pthread_exit(void) +{ + thread_control_set(0); + /* Delay for guarantee thread exit */ + ssleep(THREAD_DELAY_MINS); + + fan_device_exit(); + psu_device_exit(); + led_device_exit(); + inventec_class_exit(); + + sysfs_remove_file(status_kobj, &status_att); + kset_unregister(status_kset); + kobject_del(status_kobj); + + printk(KERN_INFO "[p_thread] inv_pthread cleaning Up\n"); +} + +module_init(inv_pthread_init); +module_exit(inv_pthread_exit); + +MODULE_AUTHOR("Robert "); +MODULE_DESCRIPTION("Inventec Platform Management Thread"); +MODULE_VERSION("version 1.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.c new file mode 100644 index 000000000000..eff030df0a8a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.c @@ -0,0 +1,3027 @@ +/* + * 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 +#include +#include "inv_swps.h" + +static int ctl_major; +static int port_major; +static int ioexp_total; +static int port_total; +static int auto_config; +static int flag_i2c_reset; +static int flag_mod_state; +static unsigned gpio_rest_mux; +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 void swp_polling_worker(struct work_struct *work); +static DECLARE_DELAYED_WORK(swp_polling, swp_polling_worker); + +static int reset_i2c_topology(void); + + +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, + __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; +} + + +static int +_get_polling_period(void) { + + int retval = 0; + + if (SWP_POLLING_PERIOD == 0) { + return 0; + } + retval = ((SWP_POLLING_PERIOD * HZ) / 1000); + if (retval == 0) { + return 1; + } + return retval; +} + + +static struct transvr_obj_s * +_get_transvr_obj(char *dev_name) { + + struct device *dev_p = NULL; + struct transvr_obj_s *transvr_obj_p = NULL; + + dev_p = get_swpdev_by_name(dev_name); + if (!dev_p){ + return NULL; + } + transvr_obj_p = dev_get_drvdata(dev_p); + if (!transvr_obj_p){ + return NULL; + } + return transvr_obj_p; +} + + +static void +unlock_tobj_all(void) { + + struct transvr_obj_s *tobj_p; + char port_name[32]; + int port_id = 0; + int minor_curr = 0; + + for (minor_curr=0; minor_currauto_config = auto_config; + unlock_transvr_obj(tobj_p); + SWPS_DEBUG("%s: Set %s auto_config=%d\n", + __func__, tobj_p->swp_name, auto_config); + } + return retval; +} + + +/* ========== R/W Functions module control attribute ========== + */ +static ssize_t +show_attr_platform(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 32, "%s\n", platform_p->name); +} + + +static ssize_t +show_attr_version(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%s\n", SWP_VERSION); +} + + +static ssize_t +show_attr_status(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", flag_mod_state); +} + + +static ssize_t +show_attr_auto_config(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", auto_config); +} + + +static int +_check_reset_pwd(const char *buf_p, + size_t count) { + + int in_max = 64; + int in_len = (int)count; + char in_val[64] = "ERR"; + char *emsg = "ERR"; + + if (in_len >= in_max) { + emsg = "input too much"; + goto err_check_reset_pwd; + } + if (!sscanf(buf_p,"%s",in_val)) { + emsg = "format incorrect"; + goto err_check_reset_pwd; + } + if (strcmp(in_val, SWP_RESET_PWD) != 0) { + emsg = "password incorrect"; + goto err_check_reset_pwd; + } + return 0; + +err_check_reset_pwd: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} + + +static ssize_t +store_attr_reset_i2c(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + if (_check_reset_pwd(buf_p, count) < 0) { + return -EBFONT; + } + /* Polling mode */ + if (SWP_POLLING_ENABLE) { + SWPS_INFO("%s: reset I2C :polling\n", __func__); + flag_i2c_reset = 1; + return count; + } + /* Direct mode */ + SWPS_INFO("%s: reset I2C go. :direct\n", __func__); + if (reset_i2c_topology() < 0) { + SWPS_ERR("%s: reset fail!\n", __func__); + return -EIO; + } + SWPS_INFO("%s: reset I2C ok. :direct\n", __func__); + return count; +} + + +static ssize_t +store_attr_reset_swps(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p; + char port_name[32] = "ERR"; + int port_id = 0; + int minor_curr = 0; + + if (_check_reset_pwd(buf_p, count) < 0) { + return -EBFONT; + } + for (minor_curr=0; minor_currstate = STATE_TRANSVR_DISCONNECTED; + unlock_transvr_obj(tobj_p); + SWPS_INFO("%s: reset:%s\n", __func__, tobj_p->swp_name); + } + return count; +} + + +static ssize_t +store_attr_auto_config(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + int input_val = sscanf_2_int(buf_p); + + if (input_val < 0){ + return -EBFONT; + } + if ((input_val != 0) && (input_val != 1)) { + return -EBFONT; + } + auto_config = input_val; + _update_auto_config_2_trnasvr(); + return count; +} + + +/* ========== Show functions: For transceiver attribute ========== + */ +static ssize_t +_show_transvr_hex_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p), + char *buf_p) { + size_t len; + int result; + + lock_transvr_obj(tobj_p); + result = get_func(tobj_p); + unlock_transvr_obj(tobj_p); + if (result < 0){ + len = snprintf(buf_p, 8, "%d\n", result); + } else { + len = snprintf(buf_p, 8, "0x%02x\n", result); + } + return len; +} + + +static ssize_t +_show_transvr_int_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p), + char *buf_p) { + size_t len; + + lock_transvr_obj(tobj_p); + len = snprintf(buf_p, 16, "%d\n", get_func(tobj_p)); + unlock_transvr_obj(tobj_p); + return len; +} + + +static ssize_t +_show_transvr_str_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p, char* buf), + char *buf_p) { + size_t len; + + lock_transvr_obj(tobj_p); + len = get_func(tobj_p, buf_p); + unlock_transvr_obj(tobj_p); + return len; +} + + +static ssize_t +show_attr_id(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_transvr_hex_attr(tobj_p, + tobj_p->get_id, + buf_p); +} + + +static ssize_t +show_attr_ext_id(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_transvr_hex_attr(tobj_p, + tobj_p->get_ext_id, + buf_p); +} + + +static ssize_t +show_attr_connector(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_transvr_hex_attr(tobj_p, + tobj_p->get_connector, + buf_p); +} + + +static ssize_t +show_attr_vendor_name(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_transvr_str_attr(tobj_p, + tobj_p->get_vendor_name, + buf_p); +} + + +static ssize_t +show_attr_vendor_pn(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_transvr_str_attr(tobj_p, + tobj_p->get_vendor_pn, + buf_p); +} + + +static ssize_t +show_attr_vendor_rev(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_transvr_str_attr(tobj_p, + tobj_p->get_vendor_rev, + buf_p); +} + + +static ssize_t +show_attr_vendor_sn(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_transvr_str_attr(tobj_p, + tobj_p->get_vendor_sn, + buf_p); +} + + +static ssize_t +show_attr_power_cls(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + size_t len; + int result; + struct transvr_obj_s *tobj_p; + + tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + lock_transvr_obj(tobj_p); + result = tobj_p->get_power_cls(tobj_p); + unlock_transvr_obj(tobj_p); + if (result < 0){ + len = snprintf(buf_p, 16, "%d\n", result); + } else { + len = snprintf(buf_p, 16, "Power Class %d\n", result); + } + return len; +} + + +static ssize_t +show_attr_br(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_transvr_hex_attr(tobj_p, + tobj_p->get_br, + buf_p); +} + + +static ssize_t +show_attr_len_sm(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_transvr_int_attr(tobj_p, + tobj_p->get_len_sm, + buf_p); +} + + +static ssize_t +show_attr_len_smf(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_transvr_int_attr(tobj_p, + tobj_p->get_len_smf, + buf_p); +} + + +static ssize_t +show_attr_len_om1(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_transvr_int_attr(tobj_p, + tobj_p->get_len_om1, + buf_p); +} + + +static ssize_t +show_attr_len_om2(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_transvr_int_attr(tobj_p, + tobj_p->get_len_om2, + buf_p); +} + + +static ssize_t +show_attr_len_om3(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_transvr_int_attr(tobj_p, + tobj_p->get_len_om3, + buf_p); +} + + +static ssize_t +show_attr_len_om4(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_transvr_int_attr(tobj_p, + tobj_p->get_len_om4, + buf_p); +} + + +static ssize_t +show_attr_comp_rev(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_transvr_hex_attr(tobj_p, + tobj_p->get_comp_rev, + buf_p); +} + + +static ssize_t +show_attr_comp_eth(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_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_1, + buf_p); +} + + +static ssize_t +show_attr_comp_eth_10(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_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_10, + buf_p); +} + + +static ssize_t +show_attr_comp_eth_10_40(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_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_10_40, + buf_p); +} + + +static ssize_t +show_attr_comp_extend(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_transvr_hex_attr(tobj_p, + tobj_p->get_comp_extend, + buf_p); +} + + +static ssize_t +show_attr_rate_id(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_transvr_hex_attr(tobj_p, + tobj_p->get_rate_id, + buf_p); +} + + +static ssize_t +show_attr_temperature(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_transvr_str_attr(tobj_p, + tobj_p->get_curr_temp, + buf_p); +} + + +static ssize_t +show_attr_voltage(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_transvr_str_attr(tobj_p, + tobj_p->get_curr_vol, + buf_p); +} + + +static ssize_t +show_attr_tx_bias(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_transvr_str_attr(tobj_p, + tobj_p->get_tx_bias, + buf_p); +} + + +static ssize_t +show_attr_tx_power(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_transvr_str_attr(tobj_p, + tobj_p->get_tx_power, + buf_p); +} + + +static ssize_t +show_attr_tx_eq(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_transvr_str_attr(tobj_p, + tobj_p->get_tx_eq, + buf_p); +} + + +static ssize_t +show_attr_rx_power(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_transvr_str_attr(tobj_p, + tobj_p->get_rx_power, + buf_p); +} + + +static ssize_t +show_attr_rx_am(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_transvr_str_attr(tobj_p, + tobj_p->get_rx_am, + buf_p); +} + + +static ssize_t +show_attr_rx_em(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_transvr_str_attr(tobj_p, + tobj_p->get_rx_em, + buf_p); +} + + +static ssize_t +show_attr_wavelength(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_transvr_str_attr(tobj_p, + tobj_p->get_wavelength, + buf_p); +} + + +static ssize_t +show_attr_extphy_offset(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_transvr_str_attr(tobj_p, + tobj_p->get_extphy_offset, + buf_p); +} + + +static ssize_t +show_attr_extphy_reg(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_transvr_str_attr(tobj_p, + tobj_p->get_extphy_reg, + buf_p); +} + + +static ssize_t +show_attr_info(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_transvr_int_attr(tobj_p, + tobj_p->get_info, + buf_p); +} + + +static ssize_t +show_attr_if_type(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_transvr_str_attr(tobj_p, + tobj_p->get_if_type, + buf_p); +} + + +static ssize_t +show_attr_if_speed(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_transvr_str_attr(tobj_p, + tobj_p->get_if_speed, + buf_p); +} + + +static ssize_t +show_attr_if_lane(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_transvr_str_attr(tobj_p, + tobj_p->get_if_lane, + buf_p); +} + + +static ssize_t +show_attr_cdr(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_transvr_hex_attr(tobj_p, + tobj_p->get_cdr, + buf_p); +} + + +static ssize_t +show_attr_soft_rs0(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_transvr_int_attr(tobj_p, + tobj_p->get_soft_rs0, + buf_p); +} + + +static ssize_t +show_attr_soft_rs1(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_transvr_int_attr(tobj_p, + tobj_p->get_soft_rs1, + buf_p); +} + + +static ssize_t +show_attr_soft_rx_los(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_transvr_str_attr(tobj_p, + tobj_p->get_soft_rx_los, + buf_p); +} + + +static ssize_t +show_attr_soft_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_transvr_str_attr(tobj_p, + tobj_p->get_soft_tx_disable, + buf_p); +} + + +static ssize_t +show_attr_soft_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_transvr_str_attr(tobj_p, + tobj_p->get_soft_tx_fault, + buf_p); +} + + +static ssize_t +show_attr_auto_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_transvr_str_attr(tobj_p, + tobj_p->get_auto_tx_disable, + buf_p); +} + + +/* ========== Store functions: transceiver (R/W) attribute ========== + */ +static ssize_t +_store_transvr_int_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_int(buf_p); + if (input < 0){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +_store_transvr_byte_hex_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_int(buf_p); + if ((input < 0) || (input > 0xff)){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +_store_transvr_binary_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_binary(buf_p); + if (input < 0){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +store_attr_cdr(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_transvr_byte_hex_attr(tobj_p, + tobj_p->set_cdr, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_rs0(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_transvr_binary_attr(tobj_p, + tobj_p->set_soft_rs0, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_rs1(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_transvr_binary_attr(tobj_p, + tobj_p->set_soft_rs1, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count) { + + int check = sscanf_2_int(buf_p); + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + if ((check < 0) || (check > 0xf)){ + return -EBFONT; + } + return _store_transvr_byte_hex_attr(tobj_p, + tobj_p->set_soft_tx_disable, + buf_p, + count); +} + + +static ssize_t +store_attr_auto_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count) { + + int err = -EPERM; + int input = sscanf_2_int(buf_p); + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + if ((input < 0) || (input > 0xf)){ + if (input != VAL_TRANSVR_FUNCTION_DISABLE) { + return -EBFONT; + } + } + lock_transvr_obj(tobj_p); + err = tobj_p->set_auto_tx_disable(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +store_attr_tx_eq(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_transvr_int_attr(tobj_p, + tobj_p->set_tx_eq, + buf_p, + count); +} + + +static ssize_t +store_attr_rx_am(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_transvr_int_attr(tobj_p, + tobj_p->set_rx_am, + buf_p, + count); +} + + +static ssize_t +store_attr_rx_em(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_transvr_int_attr(tobj_p, + tobj_p->set_rx_em, + buf_p, + count); +} + + +static ssize_t +store_attr_extphy_offset(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_transvr_int_attr(tobj_p, + tobj_p->set_extphy_offset, + buf_p, + count); +} + + +static ssize_t +store_attr_extphy_reg(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_transvr_int_attr(tobj_p, + tobj_p->set_extphy_reg, + buf_p, + count); +} + +/* ========== 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); +} + + +static ssize_t +show_attr_hard_rs0(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_hard_rs0, + buf_p); +} + + +static ssize_t +show_attr_hard_rs1(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_hard_rs1, + 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); +} + + +static ssize_t +store_attr_hard_rs0(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_hard_rs0, + buf_p, + count); +} + + +static ssize_t +store_attr_hard_rs1(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_hard_rs1, + buf_p, + count); +} + + +/* ========== SWPS attribute: For module control ========== + */ +static DEVICE_ATTR(platform, S_IRUGO, show_attr_platform, NULL); +static DEVICE_ATTR(version, S_IRUGO, show_attr_version, NULL); +static DEVICE_ATTR(status, S_IRUGO, show_attr_status, NULL); +static DEVICE_ATTR(reset_i2c, S_IWUSR, NULL, store_attr_reset_i2c); +static DEVICE_ATTR(reset_swps, S_IWUSR, NULL, store_attr_reset_swps); +static DEVICE_ATTR(auto_config, S_IRUGO|S_IWUSR, show_attr_auto_config, store_attr_auto_config); + +/* ========== Transceiver attribute: from eeprom ========== + */ +static DEVICE_ATTR(id, S_IRUGO, show_attr_id, NULL); +static DEVICE_ATTR(ext_id, S_IRUGO, show_attr_ext_id, NULL); +static DEVICE_ATTR(connector, S_IRUGO, show_attr_connector, NULL); +static DEVICE_ATTR(vendor_name, S_IRUGO, show_attr_vendor_name, NULL); +static DEVICE_ATTR(vendor_pn, S_IRUGO, show_attr_vendor_pn, NULL); +static DEVICE_ATTR(vendor_rev, S_IRUGO, show_attr_vendor_rev, NULL); +static DEVICE_ATTR(vendor_sn, S_IRUGO, show_attr_vendor_sn, NULL); +static DEVICE_ATTR(power_cls, S_IRUGO, show_attr_power_cls, NULL); +static DEVICE_ATTR(br, S_IRUGO, show_attr_br, NULL); +static DEVICE_ATTR(len_sm, S_IRUGO, show_attr_len_sm, NULL); +static DEVICE_ATTR(len_smf, S_IRUGO, show_attr_len_smf, NULL); +static DEVICE_ATTR(len_om1, S_IRUGO, show_attr_len_om1, NULL); +static DEVICE_ATTR(len_om2, S_IRUGO, show_attr_len_om2, NULL); +static DEVICE_ATTR(len_om3, S_IRUGO, show_attr_len_om3, NULL); +static DEVICE_ATTR(len_om4, S_IRUGO, show_attr_len_om4, NULL); +static DEVICE_ATTR(comp_rev, S_IRUGO, show_attr_comp_rev, NULL); +static DEVICE_ATTR(comp_eth, S_IRUGO, show_attr_comp_eth, NULL); +static DEVICE_ATTR(comp_eth_10, S_IRUGO, show_attr_comp_eth_10, NULL); +static DEVICE_ATTR(comp_eth_10_40, S_IRUGO, show_attr_comp_eth_10_40, NULL); +static DEVICE_ATTR(comp_extend, S_IRUGO, show_attr_comp_extend, NULL); +static DEVICE_ATTR(rate_id, S_IRUGO, show_attr_rate_id, NULL); +static DEVICE_ATTR(temperature, S_IRUGO, show_attr_temperature, NULL); +static DEVICE_ATTR(voltage, S_IRUGO, show_attr_voltage, NULL); +static DEVICE_ATTR(tx_bias, S_IRUGO, show_attr_tx_bias, NULL); +static DEVICE_ATTR(tx_power, S_IRUGO, show_attr_tx_power, NULL); +static DEVICE_ATTR(rx_power, S_IRUGO, show_attr_rx_power, NULL); +static DEVICE_ATTR(info, S_IRUGO, show_attr_info, NULL); +static DEVICE_ATTR(if_type, S_IRUGO, show_attr_if_type, NULL); +static DEVICE_ATTR(if_speed, S_IRUGO, show_attr_if_speed, NULL); +static DEVICE_ATTR(if_lane, S_IRUGO, show_attr_if_lane, NULL); +static DEVICE_ATTR(soft_rx_los, S_IRUGO, show_attr_soft_rx_los, NULL); +static DEVICE_ATTR(soft_tx_fault, S_IRUGO, show_attr_soft_tx_fault, NULL); +static DEVICE_ATTR(wavelength, S_IRUGO, show_attr_wavelength, NULL); +static DEVICE_ATTR(tx_eq, S_IRUGO|S_IWUSR, show_attr_tx_eq, store_attr_tx_eq); +static DEVICE_ATTR(rx_am, S_IRUGO|S_IWUSR, show_attr_rx_am, store_attr_rx_am); +static DEVICE_ATTR(rx_em, S_IRUGO|S_IWUSR, show_attr_rx_em, store_attr_rx_em); +static DEVICE_ATTR(cdr, S_IRUGO|S_IWUSR, show_attr_cdr, store_attr_cdr); +static DEVICE_ATTR(soft_rs0, S_IRUGO|S_IWUSR, show_attr_soft_rs0, store_attr_soft_rs0); +static DEVICE_ATTR(soft_rs1, S_IRUGO|S_IWUSR, show_attr_soft_rs1, store_attr_soft_rs1); +static DEVICE_ATTR(soft_tx_disable, S_IRUGO|S_IWUSR, show_attr_soft_tx_disable, store_attr_soft_tx_disable); +static DEVICE_ATTR(auto_tx_disable, S_IRUGO|S_IWUSR, show_attr_auto_tx_disable, store_attr_auto_tx_disable); +static DEVICE_ATTR(extphy_offset, S_IRUGO|S_IWUSR, show_attr_extphy_offset, store_attr_extphy_offset); +static DEVICE_ATTR(extphy_reg, S_IRUGO|S_IWUSR, show_attr_extphy_reg, store_attr_extphy_reg); + +/* ========== 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); +static DEVICE_ATTR(hard_rs0, S_IRUGO|S_IWUSR, show_attr_hard_rs0, store_attr_hard_rs0); +static DEVICE_ATTR(hard_rs1, S_IRUGO|S_IWUSR, show_attr_hard_rs1, store_attr_hard_rs1); + +/* ========== 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->vendor_name); + kfree(transvr_obj_p->vendor_pn); + kfree(transvr_obj_p->vendor_rev); + kfree(transvr_obj_p->vendor_sn); + kfree(transvr_obj_p->worker_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 void +clean_swps_common(void){ + + dev_t dev_num; + struct device *device_p; + + device_p = get_swpdev_by_name(SWP_DEV_MODCTL); + if (device_p){ + dev_num = MKDEV(ctl_major, 1); + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); + } + cancel_delayed_work_sync(&swp_polling); + SWPS_DEBUG("%s: done.\n", __func__); +} + + +static int +get_platform_type(void){ + + int i; + int pf_total = ARRAY_SIZE(platform_map); + 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; + } + memset(platform_p->name, 0, sizeof(platform_p->name)); + + switch (PLATFORM_SETTINGS) { + case PLATFORM_TYPE_AUTO: + snprintf(platform_p->name, (sizeof(platform_p->name) - 1), + "%s", dmi_get_system_info(DMI_BOARD_NAME)); + for (i=0; iname, platform_map[i].name) == 0) { + platform_p->id = platform_map[i].id; + snprintf(log_msg, sizeof(log_msg), + "Auto detect platform: %d (%s)", + platform_p->id, platform_p->name); + goto ok_get_platform_type_1; + } + } + snprintf(log_msg, sizeof(log_msg), + "Auto detect fail! detect platform: %s", + platform_p->name); + goto err_get_platform_type_2; + + case PLATFORM_TYPE_MAGNOLIA: + case PLATFORM_TYPE_MAGNOLIA_FNC: + case PLATFORM_TYPE_REDWOOD: + case PLATFORM_TYPE_REDWOOD_FSL: + case PLATFORM_TYPE_HUDSON32I_GA: + case PLATFORM_TYPE_SPRUCE: + case PLATFORM_TYPE_CYPRESS_GA1: + case PLATFORM_TYPE_CYPRESS_GA2: + case PLATFORM_TYPE_CYPRESS_BAI: + case PLATFORM_TYPE_TAHOE: + case PLATFORM_TYPE_SEQUOIA_GA: + case PLATFORM_TYPE_LAVENDER_GA: + case PLATFORM_TYPE_LAVENDER_ONL: + platform_p->id = PLATFORM_SETTINGS; + for (i=0; iname, (sizeof(platform_p->name) - 1), + "%s", platform_map[i].name); + snprintf(log_msg, sizeof(log_msg), + "User setup platform: %d (%s)", + platform_p->id, platform_p->name); + goto ok_get_platform_type_1; + } + } + snprintf(log_msg, sizeof(log_msg), + "Internal error, can not map id:%d", + PLATFORM_SETTINGS); + goto err_get_platform_type_2; + + default: + break; + } + snprintf(log_msg, sizeof(log_msg), + "PLATFORM_SETTINGS:%d undefined", PLATFORM_SETTINGS); + goto err_get_platform_type_2; + +ok_get_platform_type_1: + SWPS_DEBUG("%s: %s, :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return 0; + +err_get_platform_type_2: + kfree(platform_p); +err_get_platform_type_1: + SWPS_ERR("%s: %s :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return -1; +} + + +static int +get_layout_info(void){ + + switch (platform_p->id) { +#ifdef SWPS_MAGNOLIA + case PLATFORM_TYPE_MAGNOLIA: + case PLATFORM_TYPE_MAGNOLIA_FNC: + gpio_rest_mux = magnolia_gpio_rest_mux; + ioexp_layout = magnolia_ioexp_layout; + port_layout = magnolia_port_layout; + ioexp_total = ARRAY_SIZE(magnolia_ioexp_layout); + port_total = ARRAY_SIZE(magnolia_port_layout); + break; +#endif +#ifdef SWPS_REDWOOD + case PLATFORM_TYPE_REDWOOD: + gpio_rest_mux = redwood_gpio_rest_mux; + ioexp_layout = redwood_ioexp_layout; + port_layout = redwood_port_layout; + ioexp_total = ARRAY_SIZE(redwood_ioexp_layout); + port_total = ARRAY_SIZE(redwood_port_layout); + break; +#endif +#ifdef SWPS_HUDSON32I_GA + case PLATFORM_TYPE_HUDSON32I_GA: + gpio_rest_mux = hudsin32iga_gpio_rest_mux; + ioexp_layout = hudson32iga_ioexp_layout; + port_layout = hudson32iga_port_layout; + ioexp_total = ARRAY_SIZE(hudson32iga_ioexp_layout); + port_total = ARRAY_SIZE(hudson32iga_port_layout); + break; +#endif +#ifdef SWPS_SPRUCE + case PLATFORM_TYPE_SPRUCE: + gpio_rest_mux = spruce_gpio_rest_mux; + ioexp_layout = spruce_ioexp_layout; + port_layout = spruce_port_layout; + ioexp_total = ARRAY_SIZE(spruce_ioexp_layout); + port_total = ARRAY_SIZE(spruce_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_GA1 + case PLATFORM_TYPE_CYPRESS_GA1: + gpio_rest_mux = cypress_ga1_gpio_rest_mux; + ioexp_layout = cypress_ga1_ioexp_layout; + port_layout = cypress_ga1_port_layout; + ioexp_total = ARRAY_SIZE(cypress_ga1_ioexp_layout); + port_total = ARRAY_SIZE(cypress_ga1_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_GA2 + case PLATFORM_TYPE_CYPRESS_GA2: + gpio_rest_mux = cypress_ga2_gpio_rest_mux; + 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); + break; +#endif +#ifdef SWPS_CYPRESS_BAI + case PLATFORM_TYPE_CYPRESS_BAI: + gpio_rest_mux = cypress_b_gpio_rest_mux; + ioexp_layout = cypress_b_ioexp_layout; + port_layout = cypress_b_port_layout; + ioexp_total = ARRAY_SIZE(cypress_b_ioexp_layout); + port_total = ARRAY_SIZE(cypress_b_port_layout); + break; +#endif +#ifdef SWPS_REDWOOD_FSL + case PLATFORM_TYPE_REDWOOD_FSL: + gpio_rest_mux = redwood_fsl_gpio_rest_mux; + ioexp_layout = redwood_fsl_ioexp_layout; + port_layout = redwood_fsl_port_layout; + ioexp_total = ARRAY_SIZE(redwood_fsl_ioexp_layout); + port_total = ARRAY_SIZE(redwood_fsl_port_layout); + break; +#endif +#ifdef SWPS_TAHOE + case PLATFORM_TYPE_TAHOE: + gpio_rest_mux = tahoe_gpio_rest_mux; + ioexp_layout = tahoe_ioexp_layout; + port_layout = tahoe_port_layout; + ioexp_total = ARRAY_SIZE(tahoe_ioexp_layout); + port_total = ARRAY_SIZE(tahoe_port_layout); + break; +#endif +#ifdef SWPS_SEQUOIA + case PLATFORM_TYPE_SEQUOIA_GA: + gpio_rest_mux = sequoia_gpio_rest_mux; + ioexp_layout = sequoia_ioexp_layout; + port_layout = sequoia_port_layout; + ioexp_total = ARRAY_SIZE(sequoia_ioexp_layout); + port_total = ARRAY_SIZE(sequoia_port_layout); + break; +#endif +#ifdef SWPS_LAVENDER + case PLATFORM_TYPE_LAVENDER_GA: + case PLATFORM_TYPE_LAVENDER_ONL: + gpio_rest_mux = lavender_gpio_rest_mux; + ioexp_layout = lavender_ioexp_layout; + port_layout = lavender_port_layout; + ioexp_total = ARRAY_SIZE(lavender_ioexp_layout); + port_total = ARRAY_SIZE(lavender_port_layout); + break; +#endif + default: + SWPS_ERR(" Invalid platform: %d (%s)\n", + platform_p->id, platform_p->name); + return -1; + } + SWPS_INFO("Start to initial platform: %d (%s)\n", + platform_p->id, platform_p->name); + return 0; +} + + +/* ========== Functions for objects operations ========== + */ +static int +__detect_issues_port(int minor_num) { + + struct transvr_obj_s *tobj_p; + int port_id = port_layout[minor_num].port_id; + char port_name[32] = "ERR"; + char *i2c_emsg = "detected bad transceiver/cable"; + + memset(port_name, 0, sizeof(port_name)); + snprintf(port_name, sizeof(port_name), "%s%d", SWP_DEV_PORT, port_id); + tobj_p = _get_transvr_obj(port_name); + if (!tobj_p) { + SWPS_INFO("%s: tobj_p is NULL :%d\n", __func__, minor_num); + return -1; + } + if (resync_channel_tier_2(tobj_p) < 0) { + if (check_channel_tier_1() < 0) { + alarm_msg_2_user(tobj_p, i2c_emsg); + return -2;; + } + } + return 0; +} + + +static int +_detect_issues_port(void) { + /* OK : retrun -1; + * Fail: return fail at which minor number (0~N) + */ + char *emsg = "ERR"; + int minor = 0; + int minor_2st = 1; + + /* Force moving the initial channel pointer + * Filter out case of fail at minor-0 port + */ + while (minor_2st < port_total) { + minor = minor_2st; + if (__detect_issues_port(minor_2st) < 0) { + emsg = "detect minor_2st fail"; + goto err_p_detect_issues_port; + } + minor_2st += 8; + } + /* Scan all port */ + for (minor=0; minor:%d\n", __func__, emsg, minor_err); + return -1; +} + + +static int +check_transvr_obj_one(char *dev_name){ + /* [Return] + * 0 : Doesn't need to take care + * -1 : Single error + * -2 : Critical error (I2C topology die) + * -9 : Internal error + */ + struct transvr_obj_s *tobj_p = NULL; + int retval = -9; + + tobj_p = _get_transvr_obj(dev_name); + if (!tobj_p) { + SWPS_ERR("%s: %s _get_transvr_obj fail\n", + __func__, dev_name); + return -9; + } + /* Check transceiver current status */ + lock_transvr_obj(tobj_p); + retval = tobj_p->check(tobj_p); + unlock_transvr_obj(tobj_p); + switch (retval) { + case 0: + case ERR_TRANSVR_UNPLUGGED: + case ERR_TRNASVR_BE_ISOLATED: + case ERR_TRANSVR_TASK_BUSY: + return 0; + + case ERR_TRANSVR_I2C_CRASH: + default: + break; + } + /* Identify abnormal case */ + if (check_channel_tier_1() < 0) { + SWPS_DEBUG("%s: %s critical error :%d\n", + __func__, dev_name, retval); + return -2; + } + SWPS_DEBUG("%s: %s single error :%d\n", + __func__, dev_name, retval); + return -1; +} + + +static int +check_transvr_objs(void){ + + char dev_name[32]; + int port_id, err_code; + int minor_curr = 0; + + for (minor_curr=0; minor_curr:%d\n", + __func__, dev_name, err_code); + break; + } + } + return 0; + +err_check_transvr_objs: + SWPS_ERR("%s: %s reset_i2c_topology fail.\n", + __func__, dev_name); + return -1; +} + + +static void +swp_polling_worker(struct work_struct *work){ + + /* Reset I2C */ + if (flag_i2c_reset) { + goto polling_reset_i2c; + } + /* Check IOEXP */ + if (check_ioexp_objs() < 0) { + goto polling_reset_i2c; + } + /* Check transceiver */ + if (check_transvr_objs() < 0) { + SWPS_DEBUG("%s: check_transvr_objs fail.\n", __func__); + flag_i2c_reset = 1; + } + goto polling_schedule_round; + +polling_reset_i2c: + SWPS_DEBUG("%s: reset_i2c_topology start.\n", __func__); + if (reset_i2c_topology() < 0) { + SWPS_ERR("%s: reset i2c fail!\n", __func__); + flag_i2c_reset = 1; + } else { + SWPS_DEBUG("%s: reset_i2c_topology OK.\n", __func__); + flag_i2c_reset = 0; + } +polling_schedule_round: + schedule_delayed_work(&swp_polling, _get_polling_period()); +} + + +/* ========== Functions for register something ========== + */ +static int +register_transvr_common_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_id) < 0) { + err_attr = "dev_attr_id"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_ext_id) < 0) { + err_attr = "dev_attr_ext_id"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_connector) < 0) { + err_attr = "dev_attr_connector"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_name) < 0) { + err_attr = "dev_attr_vendor_name"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_pn) < 0) { + err_attr = "dev_attr_vendor_pn"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_rev) < 0) { + err_attr = "dev_attr_vendor_rev"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_sn) < 0) { + err_attr = "dev_attr_vendor_sn"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_br) < 0) { + err_attr = "dev_attr_br"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_smf) < 0) { + err_attr = "dev_attr_len_smf"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om1) < 0) { + err_attr = "dev_attr_len_om1"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om2) < 0) { + err_attr = "dev_attr_len_om2"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om3) < 0) { + err_attr = "dev_attr_len_om3"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om4) < 0) { + err_attr = "dev_attr_len_om4"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_extend) < 0) { + err_attr = "dev_attr_comp_extend"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth) < 0) { + err_attr = "dev_attr_comp_eth"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_rev) < 0) { + err_attr = "dev_attr_comp_rev"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_info) < 0) { + err_attr = "dev_attr_info"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_type) < 0) { + err_attr = "dev_attr_if_type"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_speed) < 0) { + err_attr = "dev_attr_if_speed"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_lane) < 0) { + err_attr = "dev_attr_if_lane"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_temperature) < 0) { + err_attr = "dev_attr_temperature"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_voltage) < 0) { + err_attr = "dev_attr_voltage"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_bias) < 0) { + err_attr = "dev_attr_tx_bias"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_power) < 0) { + err_attr = "dev_attr_tx_power"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_rx_power) < 0) { + err_attr = "dev_attr_rx_power"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_eq) < 0) { + err_attr = "dev_attr_tx_eq"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_rx_em) < 0) { + err_attr = "dev_attr_rx_em"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_wavelength) < 0) { + err_attr = "dev_attr_wavelength"; + goto err_transvr_comm_attr; + } + return 0; + +err_transvr_comm_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + +static int +register_transvr_sfp_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_common_attr(device_p) < 0) { + err_attr = "register_transvr_common_attr"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth_10) < 0) { + err_attr = "dev_attr_comp_eth_10"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_len_sm) < 0) { + err_attr = "dev_attr_len_sm"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_rate_id) < 0) { + err_attr = "dev_attr_rate_id"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rs0) < 0) { + err_attr = "dev_attr_soft_rs0"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rs1) < 0) { + err_attr = "dev_attr_soft_rs1"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_extphy_offset) < 0) { + err_attr = "dev_attr_extphy_offset"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_extphy_reg) < 0) { + err_attr = "dev_attr_extphy_reg"; + goto err_transvr_sfp_attr; + } + return 0; + +err_transvr_sfp_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_qsfp_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_common_attr(device_p) < 0) { + err_attr = "register_transvr_common_attr"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth_10_40) < 0) { + err_attr = "dev_attr_comp_eth_10_40"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_power_cls) < 0) { + err_attr = "dev_attr_power_cls"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rx_los) < 0) { + err_attr = "soft_rx_los"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_tx_disable) < 0) { + err_attr = "soft_tx_disable"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_auto_tx_disable) < 0) { + err_attr = "auto_tx_disable"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_tx_fault) < 0) { + err_attr = "soft_tx_fault"; + goto err_transvr_qsfp_attr; + } + return 0; + +err_transvr_qsfp_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_qsfp28_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_qsfp_attr(device_p) < 0){ + err_attr = "register_transvr_qsfp_attr"; + goto err_transvr_qsfp28_attr; + } + if (device_create_file(device_p, &dev_attr_cdr) < 0) { + err_attr = "dev_attr_cdr"; + goto err_transvr_qsfp28_attr; + } + if (device_create_file(device_p, &dev_attr_rx_am) < 0) { + err_attr = "dev_attr_rx_am"; + goto err_transvr_qsfp28_attr; + } + return 0; + +err_transvr_qsfp28_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_attr(struct device *device_p, + struct transvr_obj_s *transvr_obj){ + + switch (transvr_obj->layout){ + case TRANSVR_TYPE_SFP: + if (register_transvr_sfp_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + if (register_transvr_qsfp_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + case TRANSVR_TYPE_QSFP_28: + if (register_transvr_qsfp28_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + default: + goto err_reg_tvr_attr; + } + return 0; + +err_reg_tvr_attr: + SWPS_ERR("%s: fail! type=%d \n", __func__, transvr_obj->type); + return -1; +} + + +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; + } + if (device_create_file(device_p, &dev_attr_hard_rs0) < 0) { + err_attr = "dev_attr_hard_rs0"; + goto err_ioexp_sfp2_attr; + } + if (device_create_file(device_p, &dev_attr_hard_rs1) < 0) { + err_attr = "dev_attr_hard_rs1"; + 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_modctl_attr(struct device *device_p){ + + char *err_msg = NULL; + + if (device_create_file(device_p, &dev_attr_platform) < 0) { + err_msg = "dev_attr_platform"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_version) < 0) { + err_msg = "dev_attr_version"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_status) < 0) { + err_msg = "dev_attr_status"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_reset_i2c) < 0) { + err_msg = "dev_attr_reset_i2c"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_reset_swps) < 0) { + err_msg = "dev_attr_reset_swps"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_auto_config) < 0) { + err_msg = "dev_attr_auto_config"; + goto err_reg_modctl_attr; + } + return 0; + +err_reg_modctl_attr: + SWPS_ERR("%s: %s\n", __func__, err_msg); + 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_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + if (register_ioexp_attr_sfp_1(device_p) < 0){ + err_msg = "register_ioexp_attr_sfp_1 fail"; + goto err_reg_ioexp_attr; + } + break; + 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_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + 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_modctl_device(void) { + + struct device *device_p = NULL; + int minor_comm = 0; /* Default minor number for common device */ + dev_t dev_num = MKDEV(ctl_major, minor_comm); + char *err_msg = "ERROR"; + + device_p = device_create(swp_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + NULL, /* void *private_data */ + SWP_DEV_MODCTL); /* const char *fmt */ + if (IS_ERR(device_p)){ + err_msg = "device_create fail"; + goto err_register_modctl_device_1; + } + if (register_modctl_attr(device_p) < 0) { + err_msg = "register_modctl_attr fail"; + goto err_register_modctl_device_2; + } + return 0; + +err_register_modctl_device_2: + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); +err_register_modctl_device_1: + SWPS_ERR("%s: %s\n", __func__, err_msg); + 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_transvr_attr(device_p, transvr_obj) < 0){ + goto err_regswp_reg_attr; + } + 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 ctl_devt = 0; + dev_t port_devt = 0; + int dev_total = port_total + 1; /* char_dev for module control */ + + /* Register device number */ + if (alloc_chrdev_region(&ctl_devt, 0, 1, SWP_DEV_MODCTL) < 0){ + SWPS_WARN("Allocate CTL MAJOR failure! \n"); + goto err_register_swp_module_1; + } + 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_2; + } + ctl_major = MAJOR(ctl_devt); + 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); +err_register_swp_module_2: + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); +err_register_swp_module_1: + 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; + if (SWP_POLLING_ENABLE){ + run_mod = IOEXP_MODE_POLLING; + } + /* 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_dev_topology(void){ + + int err; + char *emsg = "ERR"; + flag_mod_state = SWP_STATE_NORMAL; + + err = init_ioexp_objs(); + switch(err){ + case 0: /* Normal */ + SWPS_DEBUG("%s: normal case\n", __func__); + break; + + case -1: /* topology error */ + SWPS_DEBUG("%s: detect tier-1 topology initial failure :%d\n", + __func__, err); + /* Reset and isolate */ + err = reset_i2c_topology(); + if (err < 0) { + emsg = "reset i2c topology fail"; + goto err_init_dev_topology; + } + /* Re-initial again */ + err = init_ioexp_objs(); + if (err < 0) { + emsg = "re-init ioexp objects fail"; + goto err_init_dev_topology; + } + break; + + case -2: /* Internal error */ + SWPS_DEBUG("%s: internal error case\n", __func__); + err = -2; + emsg = "internal error"; + goto err_init_dev_topology; + + default: + SWPS_DEBUG("%s: undefined error case\n", __func__); + emsg = "undefined error case"; + goto err_init_dev_topology; + } + SWPS_DEBUG("%s: initial I2C topology success\n", __func__); + return 0; + +err_init_dev_topology: + SWPS_ERR("%s: %s :%d\n", __func__, emsg, err); + return -1; +} + + +static int +init_polling_task(void){ + + if (SWP_POLLING_ENABLE){ + schedule_delayed_work(&swp_polling, _get_polling_period()); + } + return 0; +} + + +static int +init_swps_common(void){ + + char *err_msg = "ERR"; + + auto_config = 0; + if ((SWP_AUTOCONFIG_ENABLE) && (SWP_POLLING_ENABLE)){ + auto_config = 1; + } + if (register_modctl_device() < 0) { + err_msg = "register_modctl_device fail"; + goto err_init_swps_common_1; + } + if (_update_auto_config_2_trnasvr() < 0) { + err_msg = "_update_auto_config_2_trnasvr fail"; + goto err_init_swps_common_1; + } + if (init_polling_task() < 0){ + err_msg = "init_polling_task fail"; + goto err_init_swps_common_1; + } + return 0; + +err_init_swps_common_1: + clean_swps_common(); + SWPS_ERR("%s: %s\n", __func__, err_msg); + 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_mux_gpio(gpio_rest_mux) < 0){ + goto err_init_mux; + } + if (init_dev_topology() < 0){ + goto err_init_topology; + } + if (init_swps_common() < 0){ + goto err_init_topology; + } + SWPS_INFO("Inventec switch-port module V.%s initial success.\n", SWP_VERSION); + return 0; + + +err_init_topology: + clean_mux_gpio(); +err_init_mux: + clean_port_obj(); +err_init_portobj: + clean_ioexp_objs(); +err_init_ioexp: + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); + 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_swps_common(); + clean_port_obj(); + clean_ioexp_objs(); + clean_mux_gpio(); + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); + 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/d6254qs/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.h new file mode 100644 index 000000000000..8e1451d6149a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.h @@ -0,0 +1,1033 @@ +/* + * 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. + */ + +#ifndef INV_SWPS_H +#define INV_SWPS_H + +#include "transceiver.h" +#include "io_expander.h" +#include "inv_mux.h" + +/* Module settings */ +#define SWP_CLS_NAME "swps" +#define SWP_DEV_PORT "port" +#define SWP_DEV_MODCTL "module" +#define SWP_RESET_PWD "inventec" +#define SWP_POLLING_PERIOD (300) /* msec */ +#define SWP_POLLING_ENABLE (1) +#define SWP_AUTOCONFIG_ENABLE (1) + +/* Module information */ +#define SWP_AUTHOR "Neil " +#define SWP_DESC "Inventec port and transceiver driver" +#define SWP_VERSION "4.2.7" +#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_AUTO (100) +#define PLATFORM_TYPE_MAGNOLIA (111) +#define PLATFORM_TYPE_MAGNOLIA_FNC (112) +#define PLATFORM_TYPE_REDWOOD (121) +#define PLATFORM_TYPE_REDWOOD_FSL (122) +#define PLATFORM_TYPE_HUDSON32I_GA (131) +#define PLATFORM_TYPE_SPRUCE (141) +#define PLATFORM_TYPE_CYPRESS_GA1 (151) /* Up -> Down */ +#define PLATFORM_TYPE_CYPRESS_GA2 (152) /* Down -> Up */ +#define PLATFORM_TYPE_CYPRESS_BAI (153) /* Down -> Up */ +#define PLATFORM_TYPE_TAHOE (161) +#define PLATFORM_TYPE_SEQUOIA_GA (171) +#define PLATFORM_TYPE_LAVENDER_GA (181) +#define PLATFORM_TYPE_LAVENDER_ONL (182) +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_MAGNOLIA + +/* Define platform flag and kernel version */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA) + #define SWPS_MAGNOLIA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA_FNC) + #define SWPS_MAGNOLIA (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD) + #define SWPS_REDWOOD (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD_FSL) + #define SWPS_REDWOOD_FSL (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_HUDSON32I_GA) + #define SWPS_HUDSON32I_GA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SPRUCE) + #define SWPS_SPRUCE (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA1) + #define SWPS_CYPRESS_GA1 (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA2) + #define SWPS_CYPRESS_GA2 (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_BAI) + #define SWPS_CYPRESS_BAI (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_TAHOE) + #define SWPS_TAHOE (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SEQUOIA_GA) + #define SWPS_SEQUOIA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA) + #define SWPS_LAVENDER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL) + #define SWPS_LAVENDER (1) + #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_AUTO, "Auto-Detect" }, + {PLATFORM_TYPE_MAGNOLIA, "Magnolia" }, + {PLATFORM_TYPE_MAGNOLIA_FNC, "Magnolia_FNC" }, + {PLATFORM_TYPE_REDWOOD, "Redwood" }, + {PLATFORM_TYPE_REDWOOD_FSL, "Redwood_FSL" }, + {PLATFORM_TYPE_HUDSON32I_GA, "Hudson32i" }, + {PLATFORM_TYPE_SPRUCE, "Spruce" }, + {PLATFORM_TYPE_CYPRESS_GA1, "Cypress_GA1" }, + {PLATFORM_TYPE_CYPRESS_GA2, "Cypress_GA2" }, + {PLATFORM_TYPE_CYPRESS_BAI, "Cypress_BAI" }, + {PLATFORM_TYPE_TAHOE, "Tahoe" }, + {PLATFORM_TYPE_SEQUOIA_GA, "Sequoia_GA" }, + {PLATFORM_TYPE_LAVENDER_GA, "Lavender_GA" }, + {PLATFORM_TYPE_LAVENDER_ONL, "Lavender_ONL" }, +}; + + +/* ========================================== + * Magnolia Layout configuration + * ========================================== + */ +#ifdef SWPS_MAGNOLIA +unsigned magnolia_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s magnolia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAGINOLIA_NAB, { {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 */ + }, + {1, IOEXP_TYPE_MAGINOLIA_NAB, { {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 */ + }, + {2, IOEXP_TYPE_MAGINOLIA_NAB, { {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 */ + }, + {3, IOEXP_TYPE_MAGINOLIA_4AB, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander 4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf0, 0xff}, {0xf0, 0xff}, }, }, /* addr[1] = I/O Expander 4 B */ + }, + {4, IOEXP_TYPE_MAGINOLIA_NAB, { {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 */ + }, + {5, IOEXP_TYPE_MAGINOLIA_NAB, { {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 */ + }, + {6, IOEXP_TYPE_MAGINOLIA_7AB, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[1] = I/O Expander 7 B */ + }, +}; + +struct inv_port_layout_s magnolia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 16} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 15} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 14} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 13} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 24} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 23} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 22} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 21} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 28} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 27} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 26} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 25} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 32} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 31} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 30} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 29} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 48} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 47} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 46} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 45} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 52} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 51} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 50} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 49} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 56} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 55} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 54} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 53} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 60} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 59} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 58} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 57} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 64} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 63} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 62} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 61} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 68} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 67} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 66} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 65} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 72} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 71} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 70} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 69} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 76} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 75} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 74} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 73} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Redwood Layout configuration + * ========================================== + */ +#ifdef SWPS_REDWOOD +unsigned redwood_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +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 + + +/* ========================================== + * Hudson32i Layout configuration + * ========================================== + */ +#ifdef SWPS_HUDSON32I_GA +unsigned hudsin32iga_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s hudson32iga_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_HUDSON32IGA_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */ + }, + {1, IOEXP_TYPE_HUDSON32IGA_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */ + }, + {2, IOEXP_TYPE_HUDSON32IGA_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */ + }, + {3, IOEXP_TYPE_HUDSON32IGA_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */ + }, +}; + +struct inv_port_layout_s hudson32iga_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 1, 2, 3, 4} }, + { 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 5, 6, 7, 8} }, + { 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 9, 10, 11, 12} }, + { 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 13, 14, 15, 16} }, + { 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 17, 18, 19, 20} }, + { 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 21, 22, 23, 24} }, + { 6, 12, 0, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 25, 26, 27, 28} }, + { 7, 13, 0, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 29, 30, 31, 32} }, + { 8, 14, 1, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 33, 34, 35, 36} }, + { 9, 15, 1, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 37, 38, 39, 40} }, + {10, 16, 1, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 41, 42, 43, 44} }, + {11, 17, 1, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 45, 46, 47, 48} }, + {12, 18, 1, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 49, 50, 51, 52} }, + {13, 19, 1, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 53, 54, 55, 56} }, + {14, 20, 1, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 57, 58, 59, 60} }, + {15, 21, 1, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 61, 62, 63, 64} }, + {16, 22, 2, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 65, 66, 67, 68} }, + {17, 23, 2, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 69, 70, 71, 72} }, + {18, 24, 2, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 73, 74, 75, 76} }, + {19, 25, 2, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + {20, 26, 2, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + {21, 27, 2, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 85, 86, 87, 88} }, + {22, 28, 2, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 89, 90, 91, 92} }, + {23, 29, 2, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 93, 94, 95, 96} }, + {24, 30, 3, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + {25, 31, 3, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + {26, 32, 3, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + {27, 33, 3, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, + {28, 34, 3, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {113,114,115,116} }, + {29, 35, 3, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {117,118,119,120} }, + {30, 36, 3, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {121,122,123,124} }, + {31, 37, 3, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Spruce Layout configuration + * ========================================== + */ +#ifdef SWPS_SPRUCE +unsigned spruce_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s spruce_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SPRUCE_7AB, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[2] = I/O Expander 7B */ + }, +}; + +struct inv_port_layout_s spruce_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + { 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + { 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + { 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + { 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + { 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (Inventec version [Up->Down]) + * ========================================== + */ +#ifdef SWPS_CYPRESS_GA1 +unsigned cypress_ga1_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; + +struct inv_ioexp_layout_s cypress_ga1_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_ga1_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (Inventec version [Down->Up]) + * ========================================== + */ +#ifdef SWPS_CYPRESS_GA2 +unsigned cypress_ga2_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; + +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 + + +/* ========================================== + * Cypress Layout configuration (BaiDu version) + * ========================================== + */ +#ifdef SWPS_CYPRESS_BAI +unsigned cypress_b_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; + +struct inv_ioexp_layout_s cypress_b_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_b_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 2, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 4, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 6, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 8, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + {10, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {12, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {14, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {16, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {18, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {20, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {22, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {24, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {26, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {28, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {30, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {32, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {34, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {36, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {38, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {40, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {42, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {44, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {46, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {48, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {50, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {52, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {54, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Redwood_fsl Layout configuration + * ========================================== + */ +#ifdef SWPS_REDWOOD_FSL +unsigned redwood_fsl_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s redwood_fsl_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_fsl_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 + + +/* ========================================== + * Tahoe Layout configuration + * ========================================== + */ +#ifdef SWPS_TAHOE +unsigned tahoe_gpio_rest_mux = MUX_RST_GPIO_249_PCA9548; + +struct inv_ioexp_layout_s tahoe_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_TAHOE_6ABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[0] = I/O Expander 6 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[1] = I/O Expander 6 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {1, IOEXP_TYPE_TAHOE_5A, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[0] = I/O Expander 5 A */ + }, +}; + + +struct inv_port_layout_s tahoe_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 12, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + { 1, 11, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + { 2, 22, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + { 3, 21, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + { 4, 24, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} }, + { 5, 23, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + { 6, 18, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} }, + { 7, 17, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} }, + { 8, 20, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} }, + { 9, 19, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} }, +}; +#endif + + +/* ========================================== + * Sequoia Layout configuration + * ========================================== + */ +#ifdef SWPS_SEQUOIA +unsigned sequoia_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; + +struct inv_ioexp_layout_s sequoia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { {1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + {1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + +struct inv_port_layout_s sequoia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 9, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 1, 10, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 2, 11, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 3, 12, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 4, 13, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + { 5, 14, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 6, 15, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + { 7, 16, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + { 8, 17, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + { 9, 18, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {10, 19, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {11, 20, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {12, 21, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} }, + {13, 22, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} }, + {14, 23, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121, 122, 123, 124} }, + {15, 24, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} }, + {16, 25, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {137, 138, 139, 140} }, + {17, 26, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {129, 130, 131, 132} }, + {18, 27, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {153, 154, 155, 156} }, + {19, 28, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {145, 146, 147, 148} }, + {20, 29, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {169, 170, 171, 172} }, + {21, 30, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {161, 162, 163, 164} }, + {22, 31, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {185, 186, 187, 188} }, + {23, 32, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {177, 178, 179, 180} }, + {24, 33, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {201, 202, 203, 204} }, + {25, 34, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {193, 194, 195, 196} }, + {26, 35, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {217, 218, 219, 220} }, + {27, 36, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {209, 210, 211, 212} }, + {28, 37, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {233, 234, 235, 236} }, + {29, 38, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {225, 226, 227, 228} }, + {30, 39, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {249, 250, 251, 252} }, + {31, 40, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {241, 242, 243, 244} }, + {32, 44, 4, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + {33, 43, 4, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + {34, 42, 4, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + {35, 41, 4, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + {36, 48, 4, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {37, 47, 4, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {38, 46, 4, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {39, 45, 4, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {40, 52, 5, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {41, 51, 5, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {42, 50, 5, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {43, 49, 5, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {44, 56, 5, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} }, + {45, 55, 5, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} }, + {46, 54, 5, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125, 126, 127, 128} }, + {47, 53, 5, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117, 118, 119, 120} }, + {48, 60, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {141, 142, 143, 144} }, + {49, 59, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {133, 134, 135, 136} }, + {50, 58, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {157, 158, 159, 160} }, + {51, 57, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {149, 150, 151, 152} }, + {52, 64, 6, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {173, 174, 175, 176} }, + {53, 63, 6, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {165, 166, 167, 168} }, + {54, 62, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {189, 190, 191, 192} }, + {55, 61, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {181, 182, 183, 184} }, + {56, 68, 7, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {205, 206, 207, 208} }, + {57, 67, 7, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {197, 198, 199, 200} }, + {58, 66, 7, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {221, 222, 223, 224} }, + {59, 65, 7, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {213, 214, 215, 216} }, + {60, 72, 7, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {237, 238, 239, 240} }, + {61, 71, 7, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {229, 230, 231, 232} }, + {62, 70, 7, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {253, 254, 255, 256} }, + {63, 69, 7, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {245, 246, 247, 248} }, +}; +#endif + + +/* ========================================== + * Lavender Layout configuration + * ========================================== + */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA) +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL) +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; +#endif + +#ifdef SWPS_LAVENDER +struct inv_ioexp_layout_s lavender_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { { 1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + { 1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { { 2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + { 2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + { 2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { { 3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + { 3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + { 3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { { 4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + { 4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + { 4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { { 9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + { 9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + { 9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {11, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {11, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {11, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {12, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {12, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {12, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, + {8, IOEXP_TYPE_LAVENDER_P65, { { 5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xF6, 0xff}, {0xF8, 0xff}, }, }, /* addr[0] = I/O Expander CPU */ + }, +}; + + +struct inv_port_layout_s lavender_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 17, 0, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {188, 189, 190, 191} }, + { 1, 18, 0, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {184, 185, 186, 187} }, + { 2, 19, 0, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {180, 181, 182, 183} }, + { 3, 20, 0, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {176, 177, 178, 179} }, + { 4, 21, 0, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {172, 173, 174, 175} }, + { 5, 22, 0, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {168, 169, 170, 171} }, + { 6, 23, 0, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {164, 165, 166, 167} }, + { 7, 24, 0, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {160, 161, 162, 163} }, + { 8, 25, 1, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {156, 157, 158, 159} }, + { 9, 26, 1, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {152, 153, 154, 155} }, + {10, 27, 1, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {148, 149, 150, 151} }, + {11, 28, 1, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {144, 145, 146, 147} }, + {12, 29, 1, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {140, 141, 142, 143} }, + {13, 30, 1, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {136, 137, 138, 139} }, + {14, 31, 1, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {132, 133, 134, 135} }, + {15, 32, 1, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {128, 129, 130, 131} }, + {16, 33, 2, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 0, 1, 2, 3} }, + {17, 34, 2, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 4, 5, 6, 7} }, + {18, 35, 2, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 8, 9, 10, 11} }, + {19, 36, 2, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 12, 13, 14, 15} }, + {20, 37, 2, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 16, 17, 18, 19} }, + {21, 38, 2, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 20, 21, 22, 23} }, + {22, 39, 2, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 24, 25, 26, 27} }, + {23, 40, 2, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 28, 29, 30, 31} }, + {24, 41, 3, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 32, 33, 34, 35} }, + {25, 42, 3, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 36, 37, 38, 39} }, + {26, 43, 3, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 40, 41, 42, 43} }, + {27, 44, 3, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 44, 45, 46, 47} }, + {28, 45, 3, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 48, 49, 50, 51} }, + {29, 46, 3, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 52, 53, 54, 55} }, + {30, 47, 3, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 56, 57, 58, 59} }, + {31, 48, 3, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 60, 61, 62, 63} }, + {32, 49, 4, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {256, 257, 258, 259} }, + {33, 50, 4, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {260, 261, 262, 263} }, + {34, 51, 4, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {264, 265, 266, 267} }, + {35, 52, 4, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {268, 269, 270, 271} }, + {36, 53, 4, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {272, 273, 274, 275} }, + {37, 54, 4, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {276, 277, 278, 279} }, + {38, 55, 4, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {280, 281, 282, 283} }, + {39, 56, 4, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {284, 285, 286, 287} }, + {40, 57, 5, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {288, 289, 290, 291} }, + {41, 58, 5, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {292, 293, 294, 295} }, + {42, 59, 5, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {296, 297, 298, 299} }, + {43, 60, 5, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {300, 301, 302, 303} }, + {44, 61, 5, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {304, 305, 306, 307} }, + {45, 62, 5, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {308, 309, 310, 311} }, + {46, 63, 5, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {312, 313, 314, 315} }, + {47, 64, 5, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {316, 317, 318, 319} }, + {48, 65, 6, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {444, 445, 446, 447} }, + {49, 66, 6, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {440, 441, 442, 443} }, + {50, 67, 6, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {436, 437, 438, 439} }, + {51, 68, 6, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {432, 433, 434, 435} }, + {52, 69, 6, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {428, 429, 430, 431} }, + {53, 70, 6, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {424, 425, 426, 427} }, + {54, 71, 6, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {420, 421, 422, 423} }, + {55, 72, 6, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {416, 417, 418, 419} }, + {56, 73, 7, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {412, 413, 414, 415} }, + {57, 74, 7, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {408, 409, 410, 411} }, + {58, 75, 7, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {404, 405, 406, 407} }, + {59, 76, 7, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {400, 401, 402, 403} }, + {60, 77, 7, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {396, 397, 398, 399} }, + {61, 78, 7, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {392, 393, 394, 395} }, + {62, 79, 7, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {388, 389, 390, 391} }, + {63, 80, 7, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {384, 385, 386, 387} }, + {64, 5, 8, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 64, 65, 66, 67} }, +}; +#endif + + +#endif /* INV_SWPS_H */ + + + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.c new file mode 100644 index 000000000000..9f1bbd0e4f2f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.c @@ -0,0 +1,1885 @@ +/* + * 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 "io_expander.h" + +static struct ioexp_obj_s *ioexp_head_p = NULL; +static struct ioexp_obj_s *ioexp_tail_p = NULL; + + +/* ========== Register IOEXP layout ========== + */ +struct ioexp_map_s ioexp_map_magnolia_nab = { + + .chip_amount = 2, + .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_magnolia_4ab = { + + .chip_amount = 2, + .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, 0, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 0, 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, 1, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 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_magnolia_7ab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {1, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {1, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {1, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 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) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 2}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 3}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 1, 7}, /* 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) */ + }, +}; + + +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) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 0, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 0, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 0, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 0, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 0, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 0, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 0, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 1, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 1, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 1, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 1, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 1, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 1, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 1, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +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) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(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) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_5a = { + + .chip_amount = 1, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_6abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 0}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 3}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 0}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + {2, 1, 5}, /* map_present[8] = MOD_ABS_PORT(X+8) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {1, 0, 1}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 6}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 1, 3}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {2, 0, 1}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {2, 0, 6}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + {2, 1, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 2}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 7}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 1, 4}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {2, 0, 2}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {2, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + {2, 1, 4}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+8) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {1, 0, 0}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 0, 5}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 2}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {2, 0, 0}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {2, 0, 5}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + {2, 1, 2}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_sequoia_nabc = { + + .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, 1, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {0, 1, 6}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {0, 1, 7}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 3}, /* 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, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_lavender_p65 = { + + .chip_amount = 1, + .data_width = 1, + + .map_present = { {0, 0, 4}, }, /* map_present[0] = MOD_ABS_PORT(X) */ + .map_reset = { {0, 0, 1}, }, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + .map_lpmod = { {0, 0, 2}, }, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + .map_modsel = { {0, 0, 0}, }, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ +}; + + +/* ========== 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_check_by_mode(struct ioexp_obj_s *self){ + + switch (self->mode){ + case IOEXP_MODE_DIRECT: + return self->fsm_4_direct(self); + + case IOEXP_MODE_POLLING: + if (self->state >= 0){ + return 0; + } + switch (self->state){ + case STATE_IOEXP_INIT: + return ERR_IOEXP_UNINIT; + case STATE_IOEXP_ABNORMAL: + return ERR_IOEXP_ABNORMAL; + default: + return ERR_IOEXP_NOSTATE; + } + break; + + default: + break; + } + SWPS_ERR("%s: Exception occurs. :%d \n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +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; + + /* Check and get address */ + err_code = _common_check_by_mode(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; + + /* Check and get address */ + err_code = _common_check_by_mode(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){ + /* [Transmit Fault (Tx_Fault)] + * A catastrophic laser fault will activate the transmitter signal, + * TX_FAULT, and disable the laser. This signal is an open collector + * output (pull-up required on the host board). A low signal indicates + * normal laser operation and a high signal indicates a fault. The + * TX_FAULT will be latched high when a laser fault occurs and is + * cleared by toggling the TX_DISABLE input or power cycling the + * transceiver. The transmitter fault condition can also be monitored + * via the two-wire serial interface. + * (address A2, byte 110, bit 2). + * + * 0: Normal + * 1: Abnormal + */ + 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_get_hard_rs0(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + "common_get_hard_rs0"); +} + + +int +common_get_hard_rs1(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + "common_get_hard_rs1"); +} + + +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 +common_set_hard_rs0(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + input_val, + "common_set_hard_rs0"); +} + + +int +common_set_hard_rs1(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + input_val, + "common_set_hard_rs1"); +} + + +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; +} + + +int +fake_ioexp_init(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_ioexp_update(struct ioexp_obj_s *self){ + return 1; +} + + +int +fake_update_func(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_get_func(struct ioexp_obj_s *self, + int virt_offset){ + SWPS_WARN("Someone called fake_get_func\n"); + return -1; +} + +int +fake_set_func(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + SWPS_WARN("Someone called fake_set_func\n"); + return -1; +} + + +/* ========== 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) { + 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; + + case IOEXP_MODE_POLLING: + /* Check system and channel is ready */ + if (self->state == STATE_IOEXP_INIT){ + if (!_is_channel_ready(self)){ + self->state = STATE_IOEXP_INIT; + SWPS_WARN("%s: IOEXP:%d channel not ready.\n", + __func__, self->ioexp_id); + return 0; + } + } + /* Execute initial callback */ + 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; +} + + +int +common_ioexp_fsm_4_polling(struct ioexp_obj_s *self){ + + int result_val, i, show_e; + int fail_retry = 3; + char *func_name = "common_ioexp_fsm_4_polling"; + +#ifdef DEBUG_SWPS + show_e = 1; +#else + show_e = 0; +#endif + + 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; + } + /* Case: System (Channel) not ready */ + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, wait and retry */ + return 0; + } + /* Case: Initial done */ + SWPS_INFO("IOEXP-%d: initial done. :%d\n", + self->ioexp_id, self->ioexp_type); + return result_val; + + case STATE_IOEXP_NORMAL: + /* Retry mechanism for case of i2c topology not stable */ + for (i=0; iupdate_all(self, show_e, func_name); + if (result_val >= 0) { + self->state = STATE_IOEXP_NORMAL; + return 0; + } + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: detect I2C crash :%d\n", + __func__, self->ioexp_id); + break; + } + SWPS_DEBUG("IOEXP-%d: unstable :%d\n", + self->ioexp_id, result_val); + } + SWPS_INFO("IOEXP-%d: NORMAL -> ABNORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_e, func_name); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_INFO("IOEXP-%d: ABNORMAL -> NORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("IOEXP-%d: Exception occurs :%d\n", + self->ioexp_id, self->state); + return ERR_IOEXP_UNEXCPT; +} + + +/* ========== Object private functions for check & update ========== + */ +int +common_ioexp_check(struct ioexp_obj_s *self){ + + int result; + + if (self->mode != IOEXP_MODE_POLLING){ + SWPS_ERR("%s: not polling mode :%d\n", + __func__, self->mode); + return ERR_IOEXP_NOTSUPPORT; + } + mutex_lock(&self->lock); + result = self->fsm_4_polling(self); + mutex_unlock(&self->lock); + return result; +} + + +/* ========== Functions for Factory pattern ========== + */ +static struct ioexp_map_s * +get_ioexp_map(int ioexp_type){ + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + return &ioexp_map_magnolia_nab; + case IOEXP_TYPE_MAGINOLIA_4AB: + return &ioexp_map_magnolia_4ab; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + return &ioexp_map_magnolia_7ab; + case IOEXP_TYPE_REDWOOD_P01P08: + return &ioexp_map_redwood_p01p08_p17p24; + case IOEXP_TYPE_REDWOOD_P09P16: + return &ioexp_map_redwood_p09p16_p25p32; + case IOEXP_TYPE_HUDSON32IGA_P01P08: + return &ioexp_map_hudson32iga_p01p08_p17p24; + case IOEXP_TYPE_HUDSON32IGA_P09P16: + return &ioexp_map_hudson32iga_p09p16_p25p32; + case IOEXP_TYPE_CYPRESS_NABC: + return &ioexp_map_cypress_nabc; + case IOEXP_TYPE_CYPRESS_7ABC: + return &ioexp_map_cypress_7abc; + case IOEXP_TYPE_TAHOE_5A: + return &ioexp_map_tahoe_5a; + case IOEXP_TYPE_TAHOE_6ABC: + return &ioexp_map_tahoe_6abc; + case IOEXP_TYPE_SEQUOIA_NABC: + return &ioexp_map_sequoia_nabc; + case IOEXP_TYPE_LAVENDER_P65: + return &ioexp_map_lavender_p65; + 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_POLLING: /* Direct access device mode */ + case IOEXP_MODE_DIRECT: /* Polling mode, read from cache */ + 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; + } + /* Setup mapping structure */ + self->ioexp_map_p = kzalloc(sizeof(*ioexp_map_p), GFP_KERNEL); + if (!(self->ioexp_map_p)) { + SWPS_ERR("%s: kzalloc ioexp_map_p fail\n", __func__); + return -1; + } + memcpy(self->ioexp_map_p, ioexp_map_p, sizeof(*ioexp_map_p)); + /* Setup attributes */ + self->ioexp_id = ioexp_id; + self->ioexp_type = ioexp_type; + 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, + int chip_amount){ + struct ioexp_addr_s *tmp_p; + if (!addr_map_p){ + SWPS_ERR("%s: map is null\n", __func__); + return -1; + } + tmp_p = kzalloc((sizeof(*addr_map_p) * chip_amount), GFP_KERNEL); + if (!tmp_p){ + SWPS_ERR("%s: kzalloc fail.\n", __func__); + return -1; + } + memcpy(tmp_p, addr_map_p, (sizeof(*addr_map_p) * chip_amount)); + self->ioexp_map_p->map_addr = tmp_p; + + return 0; +} + + +static int +setup_ioexp_public_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + 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->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = 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; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + return 0; + 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->get_hard_rs0 = common_get_hard_rs0; + self->get_hard_rs1 = common_get_hard_rs1; + 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; + self->set_hard_rs0 = common_set_hard_rs0; + self->set_hard_rs1 = common_set_hard_rs1; + return 0; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + 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->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = ioexp_get_not_support; + 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; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + 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_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_NABC: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + self->init = common_ioexp_init; + self->check = common_ioexp_check; + self->update_all = common_ioexp_update_all; + self->fsm_4_direct = common_ioexp_fsm_4_direct; + self->fsm_4_polling = common_ioexp_fsm_4_polling; + 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, ioexp_map_p->chip_amount) < 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; + if (ioexp_curr_p->ioexp_map_p) { + if (ioexp_curr_p->ioexp_map_p->map_addr) { + kfree(ioexp_curr_p->ioexp_map_p->map_addr); + } + kfree(ioexp_curr_p->ioexp_map_p); + } + + 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__); +} + + +int +check_ioexp_objs(void){ + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while (ioexp_curr_p){ + if ( (ioexp_curr_p->check(ioexp_curr_p)) < 0){ + SWPS_INFO("check IOEXP-%d fail! :%d\n", + ioexp_curr_p->ioexp_id, ioexp_curr_p->ioexp_type); + return -1; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} + + +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; +} + + +void +unlock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_unlock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } +} + + +int +lock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_lock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} + + +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} + + +static int +_scan_channel_tier_1(int force, + int show_err) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + int ready = 0; + + if (!ioexp_curr_p) { + goto err_scan_tier_1_channel; + } + while(ioexp_curr_p) { + ready = _is_channel_ready(ioexp_curr_p); + if ((!ready) && (!force)) { + goto err_scan_tier_1_channel; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; + +err_scan_tier_1_channel: + if (show_err) { + if (ioexp_curr_p) { + SWPS_INFO("%s: IOEXP-%d fail\n", __func__, ioexp_curr_p->ioexp_id); + } else { + SWPS_INFO("%s: IOEXP is null.\n", __func__); + } + } + return -1; +} + + +static int +_scan_channel_tier_1_single(void) { + + int ret = 0; + int chan_id = 0; + int fake_cid = 0; + int fake_offs = 0; + int fake_addr = 0; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + + if (ioexp_head_p->ioexp_id != ioexp_tail_p->ioexp_id) { + return 0; + } + /* Setup i2c_client */ + chan_id = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chan_id; + fake_addr = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chip_addr; + adap = i2c_get_adapter((chan_id + 1)); + if(!adap){ + SWPS_INFO("%s: Can not get adap!\n", __func__); + return 0; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + SWPS_INFO("%s: Can not kzalloc client!\n", __func__); + return 0; + } + client->adapter = adap; + client->addr = fake_addr; + /* Fouce move ioexp ptr to next */ + ret = i2c_smbus_read_byte_data(client, fake_offs); + SWPS_DEBUG("%s: move ioexp_ptr done. :%d\n", __func__, ret); + kfree(client); + return 1; +} + + +int +resync_channel_tier_1(void) { + + char *emsg = "ERR"; + + if (!ioexp_head_p) { + emsg = "ioexp_head_p is NULL"; + goto err_resync_ioexp_status_1; + } + /* Run all */ + if (ioexp_head_p->ioexp_id == ioexp_tail_p->ioexp_id) { + _scan_channel_tier_1_single(); + } else { + _scan_channel_tier_1(1, 0); + } + /* Check all */ + if (_scan_channel_tier_1(0, 1) < 0) { + emsg = "resync tier-1 channel fail"; + goto err_resync_ioexp_status_1; + } + return 0; + +err_resync_ioexp_status_1: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.h new file mode 100644 index 000000000000..82fef3f7febc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.h @@ -0,0 +1,183 @@ +/* + * 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. + */ + +#ifndef IO_EXPANDER_H +#define IO_EXPANDER_H + +#include + + +/* IOEXP type define (SFP series) */ +#define IOEXP_TYPE_MAGINOLIA_NAB (10101) +#define IOEXP_TYPE_MAGINOLIA_4AB (10102) +#define IOEXP_TYPE_CYPRESS_NABC (10103) + +/* IOEXP type define (QSFP series) */ +#define IOEXP_TYPE_MAGINOLIA_7AB (10201) +#define IOEXP_TYPE_REDWOOD_P01P08 (10202) +#define IOEXP_TYPE_REDWOOD_P09P16 (10203) +#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204) +#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205) +#define IOEXP_TYPE_SPRUCE_7AB (10206) +#define IOEXP_TYPE_CYPRESS_7ABC (10207) +#define IOEXP_TYPE_TAHOE_5A (10208) +#define IOEXP_TYPE_TAHOE_6ABC (10209) +#define IOEXP_TYPE_SEQUOIA_NABC (10210) +#define IOEXP_TYPE_LAVENDER_P65 (10211) + +/* IOEXP mode define */ +#define IOEXP_MODE_POLLING (19000) +#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_ABNORMAL (-103) +#define ERR_IOEXP_NOSTATE (-104) +#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[10]; /* IOEXP for SFP / QSFP */ + struct ioexp_bitmap_s map_tx_disable[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_tx_fault[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_rxlos[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_reset[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_lpmod[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_modsel[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs0[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs1[10]; /* 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 (*get_hard_rs0)(struct ioexp_obj_s *self, int virt_offset); + int (*get_hard_rs1)(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); + int (*set_hard_rs0)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_hard_rs1)(struct ioexp_obj_s *self, int virt_offset, int input_val); + + /* =========================================== + * Object private functions + * =========================================== + */ + int (*init)(struct ioexp_obj_s *self); + int (*check)(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); + int (*fsm_4_polling)(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); +int check_ioexp_objs(void); +void clean_ioexp_objs(void); + +void unlock_ioexp_all(void); +int lock_ioexp_all(void); + +int check_channel_tier_1(void); +int resync_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/d6254qs/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/transceiver.c new file mode 100644 index 000000000000..e7f3cf70fa68 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/transceiver.c @@ -0,0 +1,8388 @@ +/* + * 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 "io_expander.h" +#include "transceiver.h" + + +/* ========== Register EEPROM address mapping ========== + */ +struct eeprom_map_s eeprom_map_sfp = { + .addr_br =0x50, .page_br =-1, .offset_br =12, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =94, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =-1, .offset_connector =2, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =-1, .offset_diag_type =92 , .length_diag_type =1, + .addr_extbr =-1, .page_extbr =-1, .offset_extbr =-1, .length_extbr =-1, + .addr_ext_id =0x50, .page_ext_id =-1, .offset_ext_id =1, .length_ext_id =1, + .addr_id =0x50, .page_id =-1, .offset_id =0, .length_id =1, + .addr_len_sm =0x50, .page_len_sm =-1, .offset_len_sm =15, .length_len_sm =1, + .addr_len_smf =0x50, .page_len_smf =-1, .offset_len_smf =14, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =-1, .offset_len_om1 =17, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =-1, .offset_len_om2 =16, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =-1, .offset_len_om3 =19, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =-1, .offset_len_om4 =18, .length_len_om4 =1, + .addr_option =0x50, .page_option =-1, .offset_option =64, .length_option =2, + .addr_rate_id =0x50, .page_rate_id =-1, .offset_rate_id =13, .length_rate_id =1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =0x51, .page_rx_em =-1, .offset_rx_em =115, .length_rx_em =1, + .addr_rx_los =-1, .page_rx_los =-1, .offset_rx_los =-1, .length_rx_los =-1, + .addr_rx_power =0x51, .page_rx_power =-1, .offset_rx_power =104, .length_rx_power =2, + .addr_soft_rs0 =0x51, .page_soft_rs0 =-1, .offset_soft_rs0 =110, .length_soft_rs0 =1, + .addr_soft_rs1 =0x51, .page_soft_rs1 =-1, .offset_soft_rs1 =118, .length_soft_rs0 =1, + .addr_temp =0x51, .page_temp =-1, .offset_temp =96, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =-1, .offset_trancomp =3, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =-1, .offset_trancomp_ext =36, .length_trancomp_ext =1, + .addr_tx_bias =0x51, .page_tx_bias =-1, .offset_tx_bias =100, .length_tx_bias =2, + .addr_tx_disable =-1, .page_tx_disable =-1, .offset_tx_disable =-1, .length_tx_disable =-1, + .addr_tx_eq =0x51, .page_tx_eq =-1, .offset_tx_eq =114, .length_tx_eq =1, + .addr_tx_fault =-1, .page_tx_fault =-1, .offset_tx_fault =-1, .length_tx_fault =-1, + .addr_tx_power =0x51, .page_tx_power =-1, .offset_tx_power =102, .length_tx_power =2, + .addr_vendor_name =0x50, .page_vendor_name =-1, .offset_vendor_name =20, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =-1, .offset_vendor_pn =40, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =-1, .offset_vendor_rev =56, .length_vendor_rev =4, + .addr_vendor_sn =0x50, .page_vendor_sn =-1, .offset_vendor_sn =68, .length_vendor_sn =16, + .addr_voltage =0x51, .page_voltage =-1, .offset_voltage =98, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =-1, .offset_wavelength =60, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =-1, .page_rx_em =-1, .offset_rx_em =-1, .length_rx_em =-1, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =-1, .page_tx_eq =-1, .offset_tx_eq =-1, .length_tx_eq =-1, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp28 = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =0x50, .page_cdr =-1, .offset_cdr =98, .length_cdr =1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =0x50, .page_rx_am =3, .offset_rx_am =238, .length_rx_am =2, + .addr_rx_em =0x50, .page_rx_em =3, .offset_rx_em =236, .length_rx_em =2, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =0x50, .page_tx_eq =3, .offset_tx_eq =234, .length_tx_eq =2, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + + +/* ========== Utility Functions ========== + */ +static int +get_bit(uint8_t origin_byte, int bit_shift) { + return (int)((origin_byte >> bit_shift) & 0x1); +} + +static int +transform_word_to_int(uint8_t hight_byte, + uint8_t low_byte) { + return ((((int)hight_byte) << 8) + (int)low_byte); +} + + +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 +_is_transvr_support_ctle(struct transvr_obj_s *self); + +static int +_transvr_init_handler(struct transvr_obj_s *self); + +int +_transvr_clean_handler(struct transvr_obj_s *self); + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self); + + +void +lock_transvr_obj(struct transvr_obj_s *self) { + + mutex_lock(&self->lock); + self->curr_page = VAL_TRANSVR_PAGE_FREE; +} + + +void +unlock_transvr_obj(struct transvr_obj_s *self) { + + self->curr_page = VAL_TRANSVR_PAGE_FREE; + mutex_unlock(&self->lock); +} + + +static int +_check_by_mode(struct transvr_obj_s *self, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + char *caller_name){ + + int return_val = ERR_TRANSVR_UNEXCPT; + + switch (self->mode){ + case TRANSVR_MODE_POLLING: + switch (self->state){ + case STATE_TRANSVR_CONNECTED: + goto ok_check_by_mode_1; + case STATE_TRANSVR_NEW: + case STATE_TRANSVR_INIT: + return ERR_TRANSVR_UNINIT; + case STATE_TRANSVR_DISCONNECTED: + return ERR_TRANSVR_UNPLUGGED; + case STATE_TRANSVR_UNEXCEPTED: + return ERR_TRANSVR_ABNORMAL; + case STATE_TRANSVR_ISOLATED: + return ERR_TRNASVR_BE_ISOLATED; + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + + case TRANSVR_MODE_DIRECT: + return_val = self->fsm_4_direct(self, caller_name); + if (return_val < 0){ + return return_val; + } + goto ok_check_by_mode_1; + + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + +ok_check_by_mode_1: + return attr_update_func(self, 0); + +err_check_by_mode_1: + SWPS_INFO("_check_by_mode: mode:%d state:%d\n", self->mode, self->state); + return ERR_TRANSVR_UNEXCPT; +} + + +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; +} + +/* +static int +_common_setup_password(struct transvr_obj_s *self, + int addr, + int page, + int offs, + uint8_t pwd[4], + int show_e) { + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, 4, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_setup_password; + } + for (i=0; i<4; i++) { + err = i2c_smbus_write_byte_data(self->i2c_client_p, + (offs + i), + pwd[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_setup_password; + } + } + return 0; + +err_common_setup_password: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} +*/ + +static int +_common_update_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + uint8_t *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_uint8_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_uint8_attr; + } + buf[i] = err; + } + return 0; + +err_common_update_uint8_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_int_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_int_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_int_attr; + } + buf[i] = (int)err; + } + return 0; + +err_common_update_int_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_INT_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_string_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + char buf[], + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_string_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_string_attr; + } + buf[i] = (char)err; + } + return 0; + +err_common_update_string_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = 'e'; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + uint8_t update, + uint8_t *buf, + char *caller, + int show_e){ + int len = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + if ((*buf) == update){ + return 0; + } + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + err = i2c_smbus_write_byte_data(self->i2c_client_p, + offset, + update); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + (*buf) = update; + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_array(struct transvr_obj_s *self, + int addr, + int page, + int offs, + int len, + uint8_t update[], + uint8_t buf[], + char *caller, + int show_e){ + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + for (i=0; ii2c_client_p, + (offs + i), + update[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + buf[i] = update[i]; + } + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, emsg, caller, err, i); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_attr_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_id, + self->eeprom_map_p->page_id, + self->eeprom_map_p->offset_id, + self->eeprom_map_p->length_id, + &(self->id), + "_common_update_attr_id", + show_err); +} + + +static int +_common_update_attr_extended_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_ext_id, + self->eeprom_map_p->page_ext_id, + self->eeprom_map_p->offset_ext_id, + self->eeprom_map_p->length_ext_id, + &(self->ext_id), + "_common_update_attr_extended_id", + show_err); +} + + +static int +_common_update_attr_connector(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_connector, + self->eeprom_map_p->page_connector, + self->eeprom_map_p->offset_connector, + self->eeprom_map_p->length_connector, + &(self->connector), + "_common_update_attr_connector", + show_err); +} + + +static int +_common_update_attr_transvr_comp(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp, + self->eeprom_map_p->page_trancomp, + self->eeprom_map_p->offset_trancomp, + self->eeprom_map_p->length_trancomp, + self->transvr_comp, + "_common_update_attr_transvr_comp", + show_err); +} + + +static int +_common_update_attr_transvr_comp_ext(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp_ext, + self->eeprom_map_p->page_trancomp_ext, + self->eeprom_map_p->offset_trancomp_ext, + self->eeprom_map_p->length_trancomp_ext, + &(self->transvr_comp_ext), + "_common_update_attr_transvr_comp_ext", + show_err); +} + + +static int +_common_update_attr_vendor_name(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_name, + self->eeprom_map_p->page_vendor_name, + self->eeprom_map_p->offset_vendor_name, + self->eeprom_map_p->length_vendor_name, + self->vendor_name, + "_common_update_attr_vendor_name", + show_err); +} + + +static int +_common_update_attr_vendor_pn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_pn, + self->eeprom_map_p->page_vendor_pn, + self->eeprom_map_p->offset_vendor_pn, + self->eeprom_map_p->length_vendor_pn, + self->vendor_pn, + "_common_update_attr_vendor_pn", + show_err); +} + + +static int +_common_update_attr_vendor_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_rev, + self->eeprom_map_p->page_vendor_rev, + self->eeprom_map_p->offset_vendor_rev, + self->eeprom_map_p->length_vendor_rev, + self->vendor_rev, + "_common_update_attr_vendor_rev", + show_err); +} + + +static int +_common_update_attr_vendor_sn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_sn, + self->eeprom_map_p->page_vendor_sn, + self->eeprom_map_p->offset_vendor_sn, + self->eeprom_map_p->length_vendor_sn, + self->vendor_sn, + "_common_update_attr_vendor_sn", + show_err); +} + + +static int +_common_update_attr_br(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_br, + self->eeprom_map_p->page_br, + self->eeprom_map_p->offset_br, + self->eeprom_map_p->length_br, + &(self->br), + "_common_update_attr_br", + show_err); +} + + +static int +_common_update_attr_len_smf(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_smf, + self->eeprom_map_p->page_len_smf, + self->eeprom_map_p->offset_len_smf, + self->eeprom_map_p->length_len_smf, + &(self->len_smf), + "_common_update_attr_len_smf", + show_err); +} + + +static int +_common_update_attr_len_om1(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om1, + self->eeprom_map_p->page_len_om1, + self->eeprom_map_p->offset_len_om1, + self->eeprom_map_p->length_len_om1, + &(self->len_om1), + "_common_update_attr_len_om1", + show_err); +} + +static int +_common_update_attr_len_om2(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om2, + self->eeprom_map_p->page_len_om2, + self->eeprom_map_p->offset_len_om2, + self->eeprom_map_p->length_len_om2, + &(self->len_om2), + "_common_update_attr_len_om2", + show_err); +} + +static int +_common_update_attr_len_om3(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om3, + self->eeprom_map_p->page_len_om3, + self->eeprom_map_p->offset_len_om3, + self->eeprom_map_p->length_len_om3, + &(self->len_om3), + "_common_update_attr_len_om3", + show_err); +} + + +static int +_common_update_attr_len_om4(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om4, + self->eeprom_map_p->page_len_om4, + self->eeprom_map_p->offset_len_om4, + self->eeprom_map_p->length_len_om4, + &(self->len_om4), + "_common_update_attr_len_om4", + show_err); +} + + +static int +_common_update_attr_option(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_option, + self->eeprom_map_p->page_option, + self->eeprom_map_p->offset_option, + self->eeprom_map_p->length_option, + self->option, + "_common_update_attr_option", + show_err); +} + + +static int +_common_update_attr_comp_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_comp_rev, + self->eeprom_map_p->page_comp_rev, + self->eeprom_map_p->offset_comp_rev, + self->eeprom_map_p->length_comp_rev, + &(self->comp_rev), + "_common_update_attr_comp_rev", + show_err); +} + + +static int +_common_update_attr_diag_type(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_diag_type, + self->eeprom_map_p->page_diag_type, + self->eeprom_map_p->offset_diag_type, + self->eeprom_map_p->length_diag_type, + &(self->diag_type), + "_common_update_attr_diag_type", + show_err); +} + + +static int +_common_update_attr_wavelength(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_wavelength, + self->eeprom_map_p->page_wavelength, + self->eeprom_map_p->offset_wavelength, + self->eeprom_map_p->length_wavelength, + self->wavelength, + "_common_update_attr_wavelength", + show_err); +} + + +int +_common_get_option_value(struct transvr_obj_s *self, + int offset, + int bit_shift) { + /* SFP: + * - option[0] = A0h / 64 + * - option[1] = A0h / 65 + * QSFP: + * - option[0] = 00h / 193 + * - option[1] = 00h / 194 + * - option[2] = 00h / 195 + */ + return (self->option[offset] & (1 << bit_shift)); +} + + +static int +_sfp_update_attr_len_sm(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_sm, + self->eeprom_map_p->page_len_sm, + self->eeprom_map_p->offset_len_sm, + self->eeprom_map_p->length_len_sm, + &(self->len_sm), + "_common_update_attr_len_sm", + show_err); +} + + +static int +_sfp_update_attr_rate_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_rate_id, + self->eeprom_map_p->page_rate_id, + self->eeprom_map_p->offset_rate_id, + self->eeprom_map_p->length_rate_id, + &(self->rate_id), + "_sfp_update_attr_rate_id", + show_err); +} + + +static int +_sfp_update_attr_soft_rs0(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + self->eeprom_map_p->length_soft_rs0, + &(self->soft_rs0), + "_sfp_update_attr_soft_rs0", + show_err); +} + + +static int +_sfp_update_attr_soft_rs1(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + self->eeprom_map_p->length_soft_rs1, + &(self->soft_rs1), + "_sfp_update_attr_soft_rs1", + show_err); +} + + +int +_sfp_is_diag_support(struct transvr_obj_s *self){ + + uint8_t bit_mask = 0xC0; /* 1100 0000 */ + uint8_t en_val = 0x40; /* 0100 0000 */ + uint8_t checkval = (self->diag_type & bit_mask); + + if (checkval == en_val) { + return 1; + } + return 0; +} + + +static int +_sfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_sfp_update_attr_curr_temp", + show_err); +} + + +static int +_sfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_sfp_update_attr_curr_voltage", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_sfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_sfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_sfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_sfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_sfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_sfp_update_attr_rx_em", + show_err); +} + + +static int +_sfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_sfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_cdr(struct transvr_obj_s *self, + int show_err){ + if (self->type != TRANSVR_TYPE_QSFP_28){ + self->cdr = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + self->eeprom_map_p->length_cdr, + &(self->cdr), + "_common_update_attr_cdr", + show_err); +} + + +static int +_qsfg_update_attr_extbr(struct transvr_obj_s *self, + int show_err) { + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_extbr, + self->eeprom_map_p->page_extbr, + self->eeprom_map_p->offset_extbr, + self->eeprom_map_p->length_extbr, + &(self->extbr), + "_common_update_attr_extbr", + show_err); +} + + +static int +_qsfp_is_diag_support(struct transvr_obj_s *self, + int diag_type) { + /* Input Parm: diag_type + * => 1 : temperature + * => 2 : voltage + * => 3 : tx relate + * => 4 : rx relate + */ + uint8_t mask_b2 = 0x04; /* 0000 0100 */ + uint8_t mask_b3 = 0x08; /* 0000 1000 */ + + switch (diag_type) { + case 1: /* temperature */ + case 2: /* voltage */ + /* Direct access target, because of spec not defined */ + return 1; + case 3: + case 4: + /* [Note] + * Due to lot of transceiver vendor defined it not rigorously and + * consider of general support, we seem it as supported if there + * are bit-2 OR bit-3 defined by transceiver vendor. + */ + if ( ((self->diag_type & mask_b2) == mask_b2 ) || + ((self->diag_type & mask_b3) == mask_b3 ) ){ + return 1; + } + return 0; + default: + SWPS_INFO("%s: undefined diag_type:%d\n", + __func__, diag_type); + break; + } + return 0; +} + + +int +_qsfp_is_implement_tx_disable(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-4 + */ + int byte = 2; + int bit = 4; + return _common_get_option_value(self, byte, bit); +} + + +int +_qsfp_is_implement_tx_fault(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-3 + */ + int byte = 2; + int bit = 3; + return _common_get_option_value(self, byte, bit); +} + + +static int +_qsfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + int diag_type = 1; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_qsfp_update_attr_curr_temp", + show_err); +} + + +static int +_qsfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + int diag_type = 2; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_qsfp_update_attr_curr_voltage", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_qsfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_qsfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_qsfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 4; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_qsfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_qsfp_update_attr_soft_rx_los(struct transvr_obj_s *self, + int show_err){ + + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_los, + self->eeprom_map_p->page_rx_los, + self->eeprom_map_p->offset_rx_los, + self->eeprom_map_p->length_rx_los, + &(self->rx_los), + "_qsfp_update_attr_soft_rx_los", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_disable(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_disable(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_update_attr_soft_tx_disable", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_fault(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_fault(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_fault, + self->eeprom_map_p->page_tx_fault, + self->eeprom_map_p->offset_tx_fault, + self->eeprom_map_p->length_tx_fault, + &(self->tx_fault), + "_qsfp_update_attr_soft_tx_fault", + show_err); +} + + +static int +_qsfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_qsfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_rx_am(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + self->rx_am, + "_qsfp_update_attr_rx_am", + show_err); +} + + +static int +_qsfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_qsfp_update_attr_rx_em", + show_err); +} + + +int +_common_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = "err"; + + if (_common_update_attr_id(self, show_err) < 0) { + err_str = "_common_update_attr_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_extended_id(self, show_err) < 0) { + err_str = "_common_update_attr_extended_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_connector(self, show_err) < 0) { + err_str = "_common_update_attr_connector"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp_ext(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp_ext"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_name(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_name"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_pn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_pn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_rev(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_sn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_sn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_br(self, show_err) < 0) { + err_str = "_common_update_attr_br"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_smf(self, show_err) < 0) { + err_str = "_common_update_attr_len_smf"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om1(self, show_err) < 0) { + err_str = "_common_update_attr_len_om1"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om2(self, show_err) < 0) { + err_str = "_common_update_attr_len_om2"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om3(self, show_err) < 0) { + err_str = "_common_update_attr_len_om3"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om4(self, show_err) < 0) { + err_str = "_common_update_attr_len_om4"; + goto err_common_update_attr_all; + } + if (_common_update_attr_option(self, show_err) < 0) { + err_str = "_common_update_attr_option"; + goto err_common_update_attr_all; + } + if (_common_update_attr_comp_rev(self, show_err) < 0) { + err_str = "_common_update_attr_comp_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_diag_type(self, show_err) < 0) { + err_str = "_common_update_attr_diag_type"; + goto err_common_update_attr_all; + } + if (_common_update_attr_wavelength(self, show_err) < 0) { + err_str = "_common_update_attr_wavelength"; + goto err_common_update_attr_all; + } + return 0; + +err_common_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_sfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_len_sm(self, show_err) < 0) { + err_str = "_sfp_update_attr_len_sm"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_rate_id(self, show_err) < 0) { + err_str = "_sfp_update_attr_rate_id"; + goto err_sfp_update_attr_all; + } + if ((self->rate_id) > 0) { + if (_sfp_update_attr_soft_rs0(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs0"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_soft_rs1(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs1"; + goto err_sfp_update_attr_all; + } + } + return 0; + +err_sfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_qsfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_qsfp_update_attr_all; + } + if (_qsfg_update_attr_extbr(self, show_err) < 0) { + err_str = "_qsfg_update_attr_extbr"; + goto err_qsfp_update_attr_all; + } + if (self->type == TRANSVR_TYPE_QSFP_28) { + if (_qsfp_update_attr_cdr(self, 1) < 0) { + err_str = "_qsfp_update_attr_cdr"; + goto err_qsfp_update_attr_all; + } + } + return 0; + +err_qsfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +/* ========== Object functions for common type ========== + */ +int +_common_count_temp(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + int sign = 0; + int high = 0; + int low = 0; + int lmax = 8; + + /* Count high */ + sign = get_bit(high_byte,7); + SWP_BIT_CLEAR(high_byte, 7); + high = (int)high_byte; + if (sign == 1) { + high = 0 - high; + } + /* Count low */ + low = (get_bit(low_byte, 7) * 500); + low += (get_bit(low_byte, 6) * 250); + low += (get_bit(low_byte, 5) * 125); + low += (get_bit(low_byte, 4) * 62); + low = (low / 100); + /* Integrate High and Low */ + return snprintf(buf_p, lmax, "%d.%d\n", high, low); +} + + +int +_common_count_voltage(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note]: + * Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts. Practical + * considerations to be defined by transceiver manufacturer will + * tend to limit the actual bounds of the supply voltage measurement. + * Accuracy is vendor specific but must be better than 3% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. Note that in some transceivers, transmitter supply + * voltage and receiver supply voltage are isolated. In that case, + * only one supply is monitored. Refer to the device specification + * for more detail. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 100 uV (1mV=1000uV) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 Volt */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_tx_bias(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 2 uA (1mA=1000uA) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total*2) / 1000); + val_f = (((total*2) - (val_i*1000)) / 100); + /* Return Unit: 1 mA */ + return snprintf(buf_p, lmax, "%d.%01d\n", val_i, val_f); +} + + +int +_common_count_tx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_rx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_wavelength(struct transvr_obj_s *self, + uint8_t high_byte, + uint8_t low_byte) { + /* [Note] + * SFP : uint 1 um. + * QSFP: unit 0.05 um. + */ + int total = 0; + + total = transform_word_to_int(high_byte, low_byte); + switch (self->type) { + case TRANSVR_TYPE_SFP: + return total; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + return (total/20); + + default: + break; + } + return ERR_TRANSVR_UNDEFINED; +} + + +int +common_get_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_id, + "common_get_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->id; +} + + +int +common_get_ext_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "common_get_ext_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->ext_id; +} + + +int +common_get_connector(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_connector, + "common_get_connector"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->connector; +} + + +int +common_get_vendor_name(struct transvr_obj_s *self, char *buf){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_name, + "common_get_vendor_name"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); +} + + +int +common_get_vendor_pn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_pn, + "common_get_vendor_pn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); +} + + +int +common_get_vendor_rev(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_rev, + "common_get_vendor_rev"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); +} + + +int +common_get_vendor_sn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_sn, + "common_get_vendor_sn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); +} + + +int +common_get_br(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return (int)self->br; + } + err = _check_by_mode(self, + &_common_update_attr_br, + "common_get_br"); + if (err < 0){ + return err; + } + /* Transform to INT to show error case */ + return (int)self->br; +} + + +int +common_get_len_smf(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_smf; + } + err = _check_by_mode(self, + &_common_update_attr_len_smf, + "common_get_len_smf"); + if (err < 0){ + return err; + } + return self->len_smf; +} + + +int +common_get_len_om1(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om1; + } + err = _check_by_mode(self, + &_common_update_attr_len_om1, + "common_get_len_om1"); + if (err < 0){ + return err; + } + return self->len_om1; +} + + +int +common_get_len_om2(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om2; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om2, + "common_get_len_om2"); + if (err < 0){ + return err; + } + return self->len_om2; +} + + +int +common_get_len_om3(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om3; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om3, + "common_get_len_om3"); + if (err < 0){ + return err; + } + return self->len_om3; +} + + +int +common_get_len_om4(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om4; + } + err = _check_by_mode(self, + &_common_update_attr_len_om4, + "common_get_len_om4"); + if (err < 0){ + return err; + } + return self->len_om4; +} + + +int +common_get_comp_extended(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp_ext, + "common_get_comp_extended"); + if (err_code < 0){ + return err_code; + } + return self->transvr_comp_ext; +} + + +int +common_get_comp_rev(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_comp_rev, + "common_get_comp_rev"); + if (err_code < 0){ + return err_code; + } + return self->comp_rev; +} + + +int +common_get_info(struct transvr_obj_s *self){ + + if (self->state != STATE_TRANSVR_CONNECTED) { + return self->state; + } + return self->info; +} + + +int +_common_get_if_lane(struct transvr_obj_s *self, + char *result){ + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_M_STR); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + memset(tmp_str, 0, LEN_TRANSVR_M_STR); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_M_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_M_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_M_STR); + } + if (i == 0) { + return EVENT_TRANSVR_TASK_FAIL; + } + return 0; +} + + +int +common_get_if_lane(struct transvr_obj_s *self, + char *buf_p){ + + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + if (self->ioexp_obj_p->state != STATE_IOEXP_NORMAL) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n", ERR_TRANSVR_ABNORMAL); + } + if (_common_get_if_lane(self, tmp_str) < 0) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n" ,ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%s\n" ,tmp_str); +} + + +int +sfp_get_len_sm(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_len_sm, + "sfp_get_len_sm"); + if (err_code < 0){ + return err_code; + } + return self->len_sm; +} + + +int +sfp_get_rate_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_rate_id, + "sfp_get_rate_id"); + if (err_code < 0){ + return err_code; + } + return self->rate_id; +} + + +int +sfp_get_soft_rs0(struct transvr_obj_s *self){ + /* Note: + * SFP Soft Rate_Select Select [aka. "RS(0)"] address + * A2h, offset: 110, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs0, + "sfp_get_soft_rs0"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs0 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_soft_rs1(struct transvr_obj_s *self){ + /* Note: + * SFP Soft RS(1) Select address + * A2h, offset: 118, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs1, + "sfp_get_soft_rs1"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs1 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_temp, + "sfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +sfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_voltage, + "sfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +sfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_bias, + "sfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _common_count_tx_bias(self->curr_tx_bias[0], + self->curr_tx_bias[1], + buf_p); +} + + +int +sfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_power, + "sfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_tx_power(self->curr_tx_power[0], + self->curr_tx_power[1], + buf_p); +} + + +int +sfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_rx_power, + "sfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_rx_power(self->curr_rx_power[0], + self->curr_rx_power[0], + buf_p); +} + + +int +sfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->rx_em[0]); +} + + +int +sfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->tx_eq[0]); +} + + +int +_sfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: A0h / 36 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +__sfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* SFP Specification Compliance: A0h / 3-10 + * transvr_comp[0-7] = 3 - 10 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_get_comp_10g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[0] = address A0h / 3 + * + * 3 7: 10G Base-ER + * 3 6: 10GBASE-LRM + * 3 5: 10GBASE-LR + * 3 4: 10GBASE-SR + */ + int bitmask = 0xf0; /* 11110000 */ + return (__sfp_get_comp_attr(self, 0) & bitmask); +} + + +int +_sfp_get_comp_1g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[3] = address A0h / 6 + * + * 6 7: BASE-PX *3 + * 6 6: BASE-BX10 *3 + * 6 5: 100BASE-FX + * 6 4: 100BASE-LX/LX10 + * 6 3: 1000BASE-T + * 6 2: 1000BASE-CX + * 6 1: 1000BASE-LX *3 + * 6 0: 1000BASE-SX + */ + return __sfp_get_comp_attr(self, 3); +} + + +int +_sfp_get_cable_tech(struct transvr_obj_s *self) { + /* transvr_comp[5] = address A0h / 8 + * + * 8 3: Active Cable *8 + * 8 2: Passive Cable *8 + */ + int bitmask = 0x0c; /* 00001100 */ + return (__sfp_get_comp_attr(self, 5) & bitmask); +} + + +int +sfp_get_comp_eth_1(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_1"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_1g_eth_comp(self); +} + + +int +sfp_get_comp_eth_10(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_10"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_10g_eth_comp(self); +} + + +int +_sfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: A0h / 2 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Note] Optical and Cable Variants Specification Compliance (SFF-8472) + * [Addr] A0h, Bytes 60-61 + * [Note] For optical variants, as defined by having zero's in A0h Byte 8 + * bits 2 and 3, Bytes 60 and 61 denote nominal transmitter output + * wavelength at room temperature. 16 bit value with byte 60 as high + * order byte and byte 61 as low order byte. The laser wavelength is + * equal to the 16 bit integer value in nm. This field allows the user + * to read the laser wavelength directly, so it is not necessary to + * infer it from the Transceiver Codes A0h Bytes 3 to 10 (see Table + * 5-3). This also allows specification of wavelengths not covered + * in the Transceiver Codes, such as those used in coarse WDM systems. + * + * For passive and active cable variants, a value of 00h for both A0h + * Byte 60 and Byte 61 denotes laser wavelength or cable specification + * compliance is unspecified. + */ + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +int +sfp_get_1g_rj45_extphy_offset(struct transvr_obj_s *self, char *buf) { + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + return snprintf(buf, LEN_TRANSVR_S_STR, "0x%02x\n", self->extphy_offset); +} + + +int +sfp_get_1g_rj45_extphy_reg(struct transvr_obj_s *self, char *buf) { + + int i = 0; + int ret = 0; + int retry = 3; + int delay = 200; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56, + -1, self->extphy_offset, 1, 0) < 0) { + return -EIO; + } + for (i=0; ii2c_client_p, self->extphy_offset); + if (ret >=0) { + goto ok_sfp_get_1g_rj45_extphy_reg; + } + msleep(delay); + } + SWPS_INFO("%s: retry:%d fail :%s :0x%02x\n", + __func__, retry, self->swp_name, self->extphy_offset); + return -EIO; + +ok_sfp_get_1g_rj45_extphy_reg: + ret = ((ret & 0x00ff) << 8) | ((ret & 0xff00) >> 8); + return snprintf(buf, LEN_TRANSVR_S_STR, "0x%04x\n", ret); +} + + +int +__qsfp_get_power_cls(struct transvr_obj_s *self, + int direct_access){ + + int err_code; + uint8_t detect_val; + + /* Detect and Update power class attribute */ + if (direct_access){ + err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_power_cls"); + } else { + err_code = self->ext_id; + } + if (err_code <0){ + return err_code; + } + if (err_code == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data */ + detect_val = self->ext_id; + SWP_BIT_CLEAR(detect_val, 2); /* Bit2: CDR RX present */ + SWP_BIT_CLEAR(detect_val, 3); /* Bit3: CDR TX present */ + SWP_BIT_CLEAR(detect_val, 4); /* Bit4: CLEI present */ + SWP_BIT_CLEAR(detect_val, 5); /* Bit5: reserved */ + /* Identify power class */ + switch (detect_val) { + case 0: /* Class_1: 00000000 */ + return 1; + case 64: /* Class_2: 01000000 */ + return 2; + case 128: /* Class_3: 10000000 */ + return 3; + case 192: /* Class_4: 11000000 */ + return 4; + case 1: /* Class_5: 00000001 */ + case 193: /* Class_5: 11000001 */ + return 5; + case 2: /* Class_6: 00000010 */ + case 194: /* Class_6: 11000010 */ + return 6; + case 3: /* Class_7: 00000011 */ + case 195: /* Class_7: 11000011 */ + return 7; + default: + break; + } + SWPS_INFO("%s: Detect undefined power class:%d\n", __func__, detect_val); + return ERR_TRANSVR_UNDEFINED; +} + + +int +qsfp_get_power_cls(struct transvr_obj_s *self) { + return __qsfp_get_power_cls(self, 1); +} + + +int +__qsfp_get_cdr_present(struct transvr_obj_s *self, + int direct_access){ + + int retval; + int BIT_SHIFT = 2; + int BIT_MASK = 0x3; + + /* Detect and Update power class attribute */ + if (direct_access) { + retval = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_cdr_present"); + if (retval < 0){ + return retval; + } + } + retval = self->ext_id; + if (retval == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data and return */ + return (int)(retval >> BIT_SHIFT & BIT_MASK); +} + + +int +qsfp_get_cdr_present(struct transvr_obj_s *self) { + return __qsfp_get_cdr_present(self, 1); +} + + +int +qsfp_get_cdr(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + "qsfp_get_cdr"); + if (err_code <0){ + return err_code; + } + + return self->cdr; +} + + +int +__qsfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* QSFP Specification Compliance: 00h / 131-138 + * transvr_comp[0-7] = 131 - 138 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_get_comp_10_40_100_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[0] = address 00h / 131 + * + * 131 7: Extended: See section 6.3.23. The Extended Specification Compliance + * Codes are maintained in the Transceiver Management section of SFF- + * 8024. + * 131 6: 10GBASE-LRM + * 131 5: 10GBASE-LR + * 131 4: 10GBASE-SR + * 131 3: 40GBASE-CR4 + * 131 2: 40GBASE-SR4 + * 131 1: 40GBASE-LR4 + * 131 0: 40G Active Cable (XLPPI) + */ + return __qsfp_get_comp_attr(self, 0); +} + + +int +_qsfp_get_comp_sonet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 132 7-3: Reserved + * 132 2: OC 48, long reach + * 132 1: OC 48, intermediate reach + * 132 0: OC 48 short reach + */ + return __qsfp_get_comp_attr(self, 1); +} + + +int +_qsfp_get_comp_sas_sata(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 133 7: SAS 24.0 Gb/s + * 133 6: SAS 12.0 Gb/s + * 133 5: SAS 6.0 Gb/s + * 133 4: SAS 3.0 Gb/s + * 133 3-0: Reserved + */ + return __qsfp_get_comp_attr(self, 2); +} + + +int +_qsfp_get_comp_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 134 7-4: Reserved + * 134 3: 1000BASE-T + * 134 2: 1000BASE-CX + * 134 1: 1000BASE-LX + * 134 0: 1000BASE-SX + */ + return __qsfp_get_comp_attr(self, 3); +} + + +int +_qsfp_get_comp_fc_link_length(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 7: Very long distance (V) + * 135 6: Short distance (S) + * 135 5: Intermediate distance (I) + * 135 4: Long distance (L) + * 135 3: Medium (M) + */ + int mask = 0xFC; /* 11111100 */ + return (__qsfp_get_comp_attr(self, 4) & mask); +} + + +int +_qsfp_get_comp_fc_trans_tech(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 2: Reserved + * 135 1: Longwave laser (LC) + * 135 0: Electrical inter-enclosure (EL) + * + * 136 7: Electrical intra-enclosure + * 136 6: Shortwave laser w/o OFC (SN) + * 136 5: Shortwave laser w OFC (SL) + * 136 4: Longwave Laser (LL) + * 136 3-0: Reserved + * + * return value = [bit 8-15:addr 135][bit 0-7:addr 136] + */ + int mask_135 = 7; /* 00000111 */ + int val_135 = (__qsfp_get_comp_attr(self, 4) & mask_135); + int val_136 = __qsfp_get_comp_attr(self, 5); + return ((val_135 << 7) + val_136); +} + + +int +_qsfp_get_comp_fc_trans_media(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 137 7: Twin Axial Pair (TW) + * 137 6: Shielded Twisted Pair (TP) + * 137 5: Miniature Coax (MI) + * 137 4: Video Coax (TV) + * 137 3: Multi-mode 62.5 m (M6) + * 137 2: Multi-mode 50 m (M5) + * 137 1: Multi-mode 50 um (OM3) + * 137 0: Single Mode (SM) + */ + return __qsfp_get_comp_attr(self, 6); +} + + +int +_qsfp_get_comp_fc_speed(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 138 7: 1200 MBps (per channel) + * 138 6: 800 MBps + * 138 5: 1600 MBps (per channel) + * 138 4: 400 MBps + * 138 3: 3200 MBps (per channel) + * 138 2: 200 MBps + * 138 1: Extended: See section 6.3.23. The Extended Specification + * Compliance Codes are maintained in the Transceiver Management + * section of SFF-8024. + * 138 0: 100 MBps + */ + return __qsfp_get_comp_attr(self, 7); +} + + +int +_qsfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: 00h / 192 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_comp_eth(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_eth"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_ethernet(self); +} + + +int +qsfp_get_comp_10_40(struct transvr_obj_s *self) { + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_10_40"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_10_40_100_ethernet(self); +} + + +int +_qsfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: 00h / 130 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_temp, + "qsfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +qsfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_voltage, + "qsfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +qsfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->tx_eq[0], self->tx_eq[1]); +} + + +int +qsfp_get_transvr_rx_am(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_get_transvr_rx_am"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_am[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_am[0], self->rx_am[1]); +} + + +int +qsfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_em[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_em[0], self->rx_em[1]); +} + + +int +_qsfp_get_channel_diag(uint8_t *data_array, + int (*count_func)(uint8_t high_byte, uint8_t low_byte, char *buf_p), + char *ch_name, + char *result_p) { + int i, high, low; + int len_max = 128; + char ch_buf[4][16] = { DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL }; + + for (i=0; i<4; i++) { + high = (i*2); + low = ((i*2) + 1); + count_func(data_array[high], data_array[low], ch_buf[i]); + } + return snprintf(result_p, len_max, + "%s-%d:%s%s-%d:%s%s-%d:%s%s-%d:%s", + ch_name, 1, ch_buf[0], + ch_name, 2, ch_buf[1], + ch_name, 3, ch_buf[2], + ch_name, 4, ch_buf[3]); +} + + +int +qsfp_get_soft_rx_los(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_rx_los, + "qsfp_get_soft_rx_los"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->rx_los & mask)); +} + + +int +qsfp_get_soft_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_get_soft_tx_disable"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_disable & mask)); +} + + +int +qsfp_get_soft_tx_fault(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_fault, + "qsfp_get_soft_tx_fault"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_fault & mask)); +} + + +int +qsfp_get_auto_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + if (self->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "%d\n", ERR_TRANSVR_FUNC_DISABLE); + } + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "0x%02x\n", self->auto_tx_disable); +} + + +int +qsfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_bias, + "qsfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _qsfp_get_channel_diag(self->curr_tx_bias, + _common_count_tx_bias, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_power, + "qsfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_tx_power, + _common_count_tx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "RX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_rx_power, + "qsfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_rx_power, + _common_count_rx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Desc] Wavelength or Copper Cable Attenuation (SFF-8636) + * [Addr] 00h 186-187 + * [Note] + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is + * a 16-bit hex value with Byte 186 as high order byte and Byte 187 as + * low order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. + * If the free side device is identified as copper cable these registers will + * be used to define the cable attenuation. An indication of 0 dB attenuation + * refers to the case where the attenuation is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +/* Public Function for Setup Features + */ +static int +__sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + uint8_t update_val = (*attr_p); + + switch (input_val) { + case 0: + SWP_BIT_CLEAR(update_val, bit_shift); + break; + case 1: + SWP_BIT_SET(update_val, bit_shift); + break; + default: + retval = ERR_TRANSVR_UNEXCPT; + err_code = ERR_TRANSVR_UNEXCPT; + err_msg = "Exception occurs"; + goto err_private_sfp_set_soft_rs_1; + } + err_code = _common_set_uint8_attr(self, + address, + page, + offset, + update_val, + attr_p, + caller, + show_err); + if (err_code < 0) { + retval = err_code; + err_msg = "Write data via i2c fail!"; + goto err_private_sfp_set_soft_rs_1; + } + (*attr_p) = update_val; + return 0; + +err_private_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +static int +_sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + /* Check input value */ + if ((input_val != 0) && (input_val != 1)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + switch (err_code) { + case 0: + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "Not support this feature"; + break; + case ERR_TRANSVR_UNINIT: + retval = ERR_TRANSVR_UNINIT; + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + retval = ERR_TRANSVR_UNPLUGGED; + err_msg = "Transceiver unplugged!"; + break; + default: + retval = err_code; + err_msg = "Check Rate_ID fail!"; + break; + } + goto err_common_sfp_set_soft_rs_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + attr_update_func, + caller); + if ( (err_code < 0) || + ((*attr_p) == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Generate and update value */ + return __sfp_set_soft_rs(self, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + +err_common_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +sfp_set_soft_rs0(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(0)"] address + * A2h, offset: 110, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + bit_shift, + &_sfp_update_attr_soft_rs0, + &(self->soft_rs0), + "sfp_set_soft_rs0", + show_err); +} + + +int +sfp_set_soft_rs1(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(1)"] address + * A2h, offset: 118, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + bit_shift, + &_sfp_update_attr_soft_rs1, + &(self->soft_rs1), + "sfp_set_soft_rs1", + show_err); +} + + +int +__sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_tx_eq; + } + setv = (uint8_t)input; + if (self->tx_eq[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + setv, + &(self->tx_eq[0]), + "_sfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_tx_eq; + } + return 0; + +err_sfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; itx_eq[0]; + if (_sfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if (self->tx_eq[0] == tmp){ + return 0; + } + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +sfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_tx_eq(self, input, 1); +} + + +int +__sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_rx_em; + } + setv = (uint8_t)input; + if (self->rx_em[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + setv, + &(self->rx_em[0]), + "_sfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_rx_em; + } + return 0; + +err_sfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; irx_em[0]; + if (_sfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if (self->rx_em[0] == tmp){ + return 0; + } + } + return -1; +} + + +int +sfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_rx_em(self, input, 1); +} + + +int +sfp_set_1g_rj45_extphy_offset(struct transvr_obj_s *self, + int input) { + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if ((input < 0) || (input > 0xff)) { + return ERR_TRANSVR_BADINPUT; + } + self->extphy_offset = (uint8_t)input; + return 0; +} + + +int +sfp_set_1g_rj45_extphy_reg(struct transvr_obj_s *self, + int input) { + + int i = 0; + int retry = 3; + int delay = 200; + uint16_t tmp = 0; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if ((input < 0) || (input > 0xffff)) { + return ERR_TRANSVR_BADINPUT; + } + tmp = ((input & 0x00ff) << 8) | ((input & 0xff00) >> 8); + if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56, + -1, self->extphy_offset, 1, 0) < 0) { + return -EIO; + } + for (i=0; i<=retry; i++) { + if (i2c_smbus_write_word_data(self->i2c_client_p, + self->extphy_offset, + tmp) >= 0) { + return 0; + } + msleep(delay); + } + SWPS_INFO("%s: retry:%d fail :%s :0x%02x\n", + __func__, retry, self->swp_name, self->extphy_offset); + return -EIO; +} + + +static int +__qsfp_set_cdr(struct transvr_obj_s *self, + int input_val, + int show_err) { + + uint8_t update_val; + int CDR_FEATURE_SUPPORTED = 0x3; + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_name = "__qsfp_set_cdr"; + + /* Check input value */ + if ((input_val < 0) || (input_val > 0xff)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_qsfp_set_cdr_1; + } + update_val = (uint8_t)input_val; + /* Check CDR supported by transceiver */ + err_code = qsfp_get_cdr_present(self); + if (err_code < 0) { + retval = err_code; + switch (err_code) { + case ERR_TRANSVR_UNINIT: + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + err_msg = "Transceiver unplugged!"; + break; + default: + err_msg = "Check CDR present fail!"; + break; + } + goto err_qsfp_set_cdr_1; + } + if (err_code != CDR_FEATURE_SUPPORTED) { + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "This transceiver not support CDR!"; + goto err_qsfp_set_cdr_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + func_name); + if ( (err_code < 0) || + (self->cdr == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_qsfp_set_cdr_1; + } + /* Write input value to transceiver */ + return _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + update_val, + &(self->cdr), + func_name, + show_err); + +err_qsfp_set_cdr_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +qsfp_set_cdr(struct transvr_obj_s *self, + int input_val) { + return __qsfp_set_cdr(self, input_val, 1); +} + + +int +qsfp_set_soft_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int show_err = 1; + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + int update_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_soft_tx_disable"); + if (retval < 0) { + snprintf(err_msg, 63, "Not ready. err:%d", retval); + goto err_qsfp_set_soft_tx_disable; + } + if ((input_val > in_max) || + (input_val < in_min) ){ + retval = ERR_TRANSVR_BADINPUT; + snprintf(err_msg, 63, "Input value:%d incorrect!", input_val); + goto err_qsfp_set_soft_tx_disable; + } + if ((self->tx_disable & 0x0f) == input_val) { + return 0; + } + update_val = ((self->tx_disable & 0xf0) & input_val); + retval = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + input_val, + &(self->tx_disable), + "qsfp_set_tx_disable", + show_err); + if (retval < 0) { + snprintf(err_msg, 63, "_common_set_uint8_attr:%d fail!", retval); + goto err_qsfp_set_soft_tx_disable; + } + return 0; + +err_qsfp_set_soft_tx_disable: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return retval; +} + + +int +_qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + uint8_t update) { + + uint8_t tx_enable = 0x0; + int show_e = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Handle timing issues */ + if (update != tx_enable) { + /* Note: + * Because there are some txvr has timing issues, + * therefore we need to execute reset cycle first. + * (enable -> other settings) + */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + tx_enable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set reset value fail"; + goto err_qsfp_set_auto_tx_disable; + } + mdelay(10); + } + /* Setup target value */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->auto_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set target value fail"; + goto err_qsfp_set_auto_tx_disable; + } + /* Check and update */ + err = _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C get value fail"; + goto err_qsfp_set_auto_tx_disable; + } + if (self->tx_disable != update) { + emsg = "data not become effective"; + goto err_qsfp_set_auto_tx_disable; + } + return 0; + +err_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s\n", + __func__, emsg, self->swp_name); + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Update settings*/ + if (input_val == VAL_TRANSVR_FUNCTION_DISABLE) { + emsg = "User disable auto tx_disable"; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + goto out_qsfp_set_auto_tx_disable; + } + if ((input_val > in_max) || (input_val < in_min) ){ + SWPS_INFO("%s: Input value:%d incorrect! :%s\n", + __func__, input_val, self->swp_name); + return ERR_TRANSVR_BADINPUT; + } + self->auto_tx_disable = input_val; + /* Check current soft tx_disable */ + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_auto_tx_disable"); + switch (retval) { + case 0: + break; + case ERR_TRANSVR_UNPLUGGED: + emsg = "Doesn't need to update"; + goto out_qsfp_set_auto_tx_disable; + default: + SWPS_INFO("%s: setup fail :%d :%s\n", + __func__, retval, self->swp_name); + return retval; + } + return _qsfp_set_auto_tx_disable(self, input_val); + +out_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s :%d\n :%d", + __func__, emsg, self->swp_name, input_val, retval); + return 0; +} + + +int +__qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_tx_eq; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->tx_eq[0] == setv[0]) && + (self->tx_eq[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + setv, + self->tx_eq, + "_qsfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_tx_eq; + } + return 0; + +err_qsfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; itx_eq[0]; + tmp[1] = self->tx_eq[1]; + if (_qsfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if ((self->tx_eq[0] == tmp[0]) && + (self->tx_eq[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_tx_eq(self, input, 1); +} + + +int +__qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_am; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_am[0] == setv[0]) && + (self->rx_am[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + setv, + self->rx_am, + "_qsfp_set_rx_am", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_am; + } + return 0; + +err_qsfp_set_rx_am: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_am[0]; + tmp[1] = self->rx_am[1]; + if (_qsfp_update_attr_rx_am(self, show_e) < 0){ + continue; + } + if ((self->rx_am[0] == tmp[0]) && + (self->rx_am[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_am(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_set_rx_am"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_am(self, input, 1); +} + + +int +__qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_em; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_em[0] == setv[0]) && + (self->rx_em[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + setv, + self->rx_em, + "_qsfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_em; + } + return 0; + +err_qsfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_em[0]; + tmp[1] = self->rx_em[1]; + if (_qsfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if ((self->rx_em[0] == tmp[0]) && + (self->rx_em[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_em(self, input, 1); +} + + +int +common_transvr_dump(struct transvr_obj_s* self){ + + char *type_name = "Undefined"; + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + switch (self->type) { + case TRANSVR_TYPE_SFP: + type_name = STR_TRANSVR_SFP; + break; + case TRANSVR_TYPE_QSFP: + type_name = STR_TRANSVR_QSFP; + break; + case TRANSVR_TYPE_QSFP_PLUS: + type_name = STR_TRANSVR_QSFP_PLUS; + break; + case TRANSVR_TYPE_QSFP_28: + type_name = STR_TRANSVR_QSFP28; + break; + case TRANSVR_TYPE_FAKE: + type_name = "FAKE"; + goto ok_common_transvr_dump; + case TRANSVR_TYPE_UNPLUGGED: + type_name = "UNPLUGGED"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_INCONSISTENT: + type_name = "INCONSISTENT"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_ERROR: + type_name = "ERROR"; + goto err_common_transvr_dump; + + default: + type_name = "UNEXPECTED"; + goto err_common_transvr_dump; + } + printk(KERN_INFO "[SWPS] Dump %s information:\n", self->swp_name); + printk(KERN_INFO " |- :%s\n", type_name); + printk(KERN_INFO " |- :%s\n", self->vendor_name); + printk(KERN_INFO " |- :%s\n", self->vendor_pn); + printk(KERN_INFO " |- :%s\n", self->vendor_rev); + printk(KERN_INFO " |- :%s\n", self->vendor_sn); + printk(KERN_INFO " |- :0x%02x\n", self->br); + printk(KERN_INFO " |- :0x%02x\n", self->comp_rev); + printk(KERN_INFO " |- :%d\n", self->len_om1); + printk(KERN_INFO " |- :%d\n", self->len_om2); + printk(KERN_INFO " |- :%d\n", self->len_om3); + printk(KERN_INFO " |- :%d\n", self->len_om4); + return 0; + +ok_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return 0; + +err_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return -1; +} + + +int +sfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_sm); + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :0x%02x\n", self->rate_id); + return 0; +} + + +int +qsfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :Class_%d\n", __qsfp_get_power_cls(self, 0)); + return 0; +} + + +int +fake_transvr_dump(struct transvr_obj_s* self) { + + printk(KERN_INFO "[SWPS] Dump transceiver information: %s\n", self->swp_name); + printk(KERN_INFO " |- :FAKE\n"); + printk(KERN_INFO " |- :FAKE_VENDER_NAME\n"); + printk(KERN_INFO " |- :FAKE_VENDER_PN\n"); + printk(KERN_INFO " |- :FAKE_VENDER_REV\n"); + printk(KERN_INFO " |- :FAKE_VENDER_SN\n"); + printk(KERN_INFO " |- :0x99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " '- :0x99\n"); + return 0; +} + + +/* ========== Object functions for fake type ========== + */ +int +fake_transvr_update(struct transvr_obj_s *self, + int show_err){ + self->state = STATE_TRANSVR_CONNECTED; + return 0; +} + + +int +fake_get_binary(struct transvr_obj_s *self){ + return 1; +} + +int +fake_get_int(struct transvr_obj_s *self){ + return 99; +} + + +int +fake_get_hex(struct transvr_obj_s *self){ + return 0x0f; +} + + +int +fake_get_str(struct transvr_obj_s *self, char *buf) { + return snprintf(buf, 16, "fake_get_str\n"); +} + + +int +fake_set_int(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: %d\n", __func__, input); + return 0; +} + + +int +fake_set_hex(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: 0x%02x\n", __func__, input); + return 0; +} + + +/* ========== Object functions for unsupported ========== + */ +int +unsupported_get_func(struct transvr_obj_s *self){ + return ERR_TRANSVR_NOTSUPPORT; +} + + +int +unsupported_get_func2(struct transvr_obj_s *self, + char *buf_p) { + int len = snprintf(buf_p, 8, "%d\n", ERR_TRANSVR_NOTSUPPORT); + return len; +} + + +int +unsupported_set_func(struct transvr_obj_s *self, + int input_val){ + return ERR_TRANSVR_NOTSUPPORT; +} + + + +/* ========== Object functions for long term task ========== + * + * [Note] + * SWPS transceiver worker is likely the green-thread (coroutine). + * Due to resource and performance considerations. SWPS run all + * features in one kthread at the same time, and handle by it self. + */ + +/* For Transceiver Task Handling + */ +static struct transvr_worker_s * +transvr_task_get(struct transvr_obj_s *self, + char *func_name) { + + struct transvr_worker_s *curr_p = self->worker_p; + + while(curr_p != NULL){ + if (strcmp((curr_p->func_name), func_name) == 0 ) { + return curr_p; + } + curr_p = curr_p->next_p; + } + return NULL; +} + + +static struct transvr_worker_s* +transvr_task_creat(struct transvr_obj_s *self, + int (*main_task)(struct transvr_worker_s *task), + int (*post_task)(struct transvr_worker_s *task), + char *caller) { + + struct transvr_worker_s *task_p = NULL; + struct transvr_worker_s *curr_p = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check task not exist */ + task_p = transvr_task_get(self, caller); + if (task_p) { + snprintf(err_msg, sizeof(err_msg), "Task already created!"); + goto err_transvr_task_creat; + } + /* Create task worker */ + task_p = kzalloc(sizeof(struct transvr_worker_s), GFP_KERNEL); + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_transvr_task_creat; + } + /* Setup task data */ + task_p->transvr_p = self; + task_p->next_p = NULL; + task_p->trigger_time = 0; + task_p->retry = 1; + task_p->state = STATE_T_TASK_INIT; + task_p->main_task = main_task; + task_p->post_task = post_task; + task_p->p_data = NULL; + snprintf(task_p->func_name, sizeof(task_p->func_name), "%s", caller); + /* Setup Link List */ + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p->next_p != NULL) { + curr_p = curr_p->next_p; + } + curr_p->next_p = task_p; + task_p->pre_p = curr_p; + } else { + self->worker_p = task_p; + task_p->pre_p = NULL; + } + return task_p; + +err_transvr_task_creat: + SWPS_ERR("%s: %s :%s :%s\n", + __func__, err_msg, caller, self->swp_name); + return NULL; +} + + +static void +transvr_task_free_one(struct transvr_worker_s *task_p){ + + struct transvr_worker_s *pre_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (task_p) { + pre_p = task_p->pre_p; + next_p = task_p->next_p; + + if ((pre_p) && (next_p)) { + pre_p->next_p = next_p; + next_p->pre_p = pre_p; + + } else if ((!pre_p) && (next_p)) { + next_p->pre_p = NULL; + + } else if ((pre_p) && (!next_p)) { + pre_p->next_p = NULL; + + } else if ((!pre_p) && (!next_p)) { + task_p->transvr_p->worker_p = NULL; + } else { + SWPS_ERR("%s: Unexcept case!\n :%s", + __func__, task_p->transvr_p->swp_name); + } + kfree(task_p->p_data); + kfree(task_p); + } +} + + +static void +transvr_task_free_all(struct transvr_obj_s *self) { + + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p) { + next_p = curr_p->next_p; + transvr_task_free_one(curr_p); + curr_p = next_p; + } + self->worker_p = NULL; + } +} + + +static void +transvr_cache_free_all(struct transvr_obj_s *self) { + + memset(self->vendor_name, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_rev, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_pn, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_sn, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + self->extphy_offset = 0; +} + +static int +_transvr_task_run_main(struct transvr_worker_s *task_p) { + + int retval = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "main_task is NULL!"); + goto main_transvr_task_err; + } + if ((task_p->trigger_time) == 0){ + goto main_transvr_task_run; + } + if (time_before(jiffies, task_p->trigger_time)){ + goto main_transvr_task_wait; + } + goto main_transvr_task_run; + +main_transvr_task_run: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + task_p->retry -= 1; + } + retval = task_p->main_task(task_p); + if (retval < 0) { + if (task_p->retry > 0) { + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + } + goto main_transvr_task_identify; + +main_transvr_task_identify: + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + + case EVENT_TRANSVR_TASK_DONE: + task_p->state = STATE_T_TASK_DONE; + return EVENT_TRANSVR_TASK_DONE; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + +main_transvr_task_wait: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + +main_transvr_task_err: + task_p->state = STATE_T_TASK_FAIL; + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, retval, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +_transvr_task_run_post(struct transvr_worker_s *task_p) { + + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if ((task_p->post_task) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + switch (task_p->state) { + case STATE_T_TASK_WAIT: + case STATE_T_TASK_INIT: + goto post_transvr_task_wait; + + case STATE_T_TASK_DONE: + case STATE_T_TASK_FAIL: + goto post_transvr_task_run; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Unexcept task state"); + goto post_transvr_task_err; + +post_transvr_task_run: + task_p->post_task(task_p); + return EVENT_TRANSVR_TASK_DONE; + +post_transvr_task_wait: + return EVENT_TRANSVR_TASK_WAIT; + +post_transvr_task_err: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, task_p->state, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_one(struct transvr_worker_s *task_p) { + + int retval_main = DEBUG_TRANSVR_INT_VAL; + int retval_post = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval_main = _transvr_task_run_main(task_p); + if (retval_main < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute main_task fail!"); + goto err_transvr_task_run_one; + } + retval_post = _transvr_task_run_post(task_p); + if (retval_post < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute post_task fail!"); + goto err_transvr_task_run_one; + } + return retval_main; + +err_transvr_task_run_one: + SWPS_INFO("%s: %s
:%d :%d :%s :%s\n", + __func__, err_msg, retval_main, retval_post, + task_p->func_name, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_all(struct transvr_obj_s *self) { + + int haserr = 0; + int retval = DEBUG_TRANSVR_INT_VAL; + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if ((self->worker_p) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + curr_p = self->worker_p; + while (curr_p != NULL) { + next_p = curr_p->next_p; + retval = transvr_task_run_one(curr_p); + if (curr_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + curr_p = next_p; + continue; + } + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + break; + case EVENT_TRANSVR_TASK_DONE: + transvr_task_free_one(curr_p); + break; + case EVENT_TRANSVR_TASK_FAIL: + + default: + haserr = 1; + transvr_task_free_one(curr_p); + break; + } + curr_p = next_p; + } + if (haserr) { + return EVENT_TRANSVR_TASK_FAIL; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +static void +transvr_task_set_delay(struct transvr_worker_s *task_p, + unsigned long delay_msec) { + + task_p->trigger_time = (jiffies + (delay_msec * (HZ/1000))); +} + + +static void +transvr_task_set_retry(struct transvr_worker_s *task_p, + unsigned long retry_times) { + + task_p->retry = retry_times; +} + + +/* For Transceiver Post Task + */ +int +taskfunc_post_do_nothing(struct transvr_worker_s *task_p) { + + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_post_handle_task_state(struct transvr_worker_s *task_p) { + + struct transvr_obj_s* tp = task_p->transvr_p; + + switch (task_p->state) { + case STATE_T_TASK_INIT: + case STATE_T_TASK_WAIT: + return EVENT_TRANSVR_TASK_WAIT; + + case STATE_T_TASK_DONE: + tp->state = STATE_TRANSVR_CONNECTED; + tp->send_uevent(tp, KOBJ_ADD); + return EVENT_TRANSVR_TASK_DONE; + + case STATE_T_TASK_FAIL: + tp->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_TASK_FAIL; + + default: + break; + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +/* For Transceiver Main Task + */ +int +_taskfunc_sfp_setup_soft_rs(struct transvr_worker_s *task_p, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller) { + + int show_err = 0; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_soft_rs"; + + err_code = _sfp_update_attr_soft_rs0(task_p->transvr_p, 0); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + err_code = __sfp_set_soft_rs(task_p->transvr_p, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_setup_soft_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_code); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +__taskfunc_sfp_setup_hard_rs(struct transvr_worker_s *task_p, + int input_val, + int (*get_func)(struct ioexp_obj_s *self, int virt_offset), + int (*set_func)(struct ioexp_obj_s *self, int virt_offset, int input_val)) { + + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + + err_val = get_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset); + + if (err_val < 0) { + if (err_val == ERR_IOEXP_NOTSUPPORT) { + return EVENT_TRANSVR_TASK_DONE; + } + err_str = "Get current hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + if (err_val == input_val) { + return EVENT_TRANSVR_TASK_DONE; + } + err_val = set_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_p_taskfunc_sfp_setup_hard_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_hard_rs0(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs0, + task_p->transvr_p->ioexp_obj_p->set_hard_rs0); +} + + +int +_taskfunc_sfp_setup_hard_rs1(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs1, + task_p->transvr_p->ioexp_obj_p->set_hard_rs1); +} + + +int +_taskfunc_sfp_setup_rs0(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs0"; + + err_val = _taskfunc_sfp_setup_hard_rs0(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs0, + task_p->transvr_p->eeprom_map_p->page_soft_rs0, + task_p->transvr_p->eeprom_map_p->offset_soft_rs0, + bit_shift, + &(task_p->transvr_p->soft_rs0), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs0_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs0(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_rs1(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs1"; + + err_val = _taskfunc_sfp_setup_hard_rs1(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs1, + task_p->transvr_p->eeprom_map_p->page_soft_rs1, + task_p->transvr_p->eeprom_map_p->offset_soft_rs1, + bit_shift, + &(task_p->transvr_p->soft_rs1), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs1_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs1(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_sfp_setup_SFF8431_case1(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs0(task_p, update_val); +} + + + +int +taskfunc_sfp_setup_SFF8431_case2(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs1(task_p, update_val); +} + + +int +taskfunc_sfp_setup_SFF8431_case3(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + int update_rs0 = 1; + int update_rs1 = 1; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _taskfunc_sfp_setup_rs0(task_p, update_rs0); + if (err_code < 0) { + return err_code; + } + return _taskfunc_sfp_setup_rs1(task_p, update_rs1); +} + + +int +taskfunc_sfp_handle_1g_rj45(struct transvr_worker_s *task_p) { + + /* Not all of platform support 0x56 for transceiver + * external PHY, Support list as below: + * => 1. Magnolia-PVT (PS: EVT & DVT not ready) + */ + int ext_phy_addr = 0x56; + int ext_phy_page = -1; + int ext_phy_offs = 0x11; + int ext_phy_len = 1; + int lstate_mask = 0x04; /* 00000100 */ + int show_err = 0; + int fail_retry = 5; + int fail_delay = 1000; /* msec */ + int err_code = DEBUG_TRANSVR_INT_VAL; + uint8_t detect_val = DEBUG_TRANSVR_HEX_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + int *tmp_p = NULL; + char *func_name = "taskfunc_sfp_handle_1g_rj45"; + + if (task_p->transvr_p->state != STATE_TRANSVR_CONNECTED) { + return EVENT_TRANSVR_TASK_DONE; + } + if ( (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000) && + (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000_up) ) { + goto err_taskfunc_sfp_handle_1g_rj45_1; + } + err_code = _common_update_uint8_attr(task_p->transvr_p, + ext_phy_addr, + ext_phy_page, + ext_phy_offs, + ext_phy_len, + &detect_val, + func_name, + show_err); + if ( (err_code < 0) || + (detect_val == DEBUG_TRANSVR_HEX_VAL) ) { + snprintf(err_str, sizeof(err_str), "Detect external link status fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + if ((detect_val & lstate_mask) == lstate_mask) { + goto ok_taskfunc_sfp_handle_1g_rj45_link_up; + } + goto ok_taskfunc_sfp_handle_1g_rj45_link_down; + +ok_taskfunc_sfp_handle_1g_rj45_link_up: + /* Filter out noise */ + if (!(task_p->p_data)) { + tmp_p = kzalloc(sizeof(int), GFP_KERNEL); + if (!tmp_p) { + snprintf(err_str, sizeof(err_str), "kzalloc p_data fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + *tmp_p = TRANSVR_CLASS_BASE_T_1000_up; + task_p->p_data = tmp_p; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + } + if ((*(int *)(task_p->p_data)) != TRANSVR_CLASS_BASE_T_1000_up) { + kfree(task_p->p_data); + task_p->p_data = NULL; + snprintf(err_str, sizeof(err_str), "Internal error"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + kfree(task_p->p_data); + task_p->p_data = NULL; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_link_down: + if (task_p->p_data) { + kfree(task_p->p_data); + task_p->p_data = NULL; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_done: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_1: + snprintf(err_str, sizeof(err_str), "Detect transceiver:%d not Base-T, remove task.", + task_p->transvr_p->info); + SWPS_INFO("%s: %s :%s\n", __func__, err_str, task_p->transvr_p->swp_name); + transvr_task_set_retry(task_p, 0); + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_2: + if (task_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, fail_retry); + } + if ((task_p->retry) == 0) { + /* Error case: + * => In this case, SWPS will stop external Link state monitor features + * and keeps transvr_p->info on TRANSVR_CLASS_BASE_T_1000_up. + * Upper layer will see it always Linkup that because of these type of + * transceiver has external phy, BCM chip see it as Loopback transceiver. + */ + SWPS_WARN("%s can not access external PHY of Base-T SFP transceiver\n", + task_p->transvr_p->swp_name); + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + return EVENT_TRANSVR_TASK_DONE; + } else { + transvr_task_set_delay(task_p, fail_delay); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_qsfp_setup_power_mod(struct transvr_obj_s *self, + int setup_val) { + + int curr_val = DEBUG_TRANSVR_INT_VAL; + int err_val = DEBUG_TRANSVR_INT_VAL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + curr_val = self->ioexp_obj_p->get_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset); + if (curr_val < 0){ + err_msg = "Get current value fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + if (curr_val == setup_val){ + return EVENT_TRANSVR_TASK_DONE; + } + err_val = self->ioexp_obj_p->set_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset, + setup_val); + if (err_val < 0){ + err_msg = "Setup power mode fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_qsfp_setup_power_mod_1: + SWPS_INFO("%s: %s :%d :%d :%d\n", + __func__, err_msg, err_val, curr_val, setup_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_qsfp_handle_tx_disable(struct transvr_worker_s *task_p) { + + int i = 0; + int retry = 5; + int delay_ms = 100; + + if (task_p->transvr_p->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return EVENT_TRANSVR_TASK_DONE; + } + if (!_qsfp_is_implement_tx_disable(task_p->transvr_p)) { + return EVENT_TRANSVR_TASK_DONE; + } + for (i=0; itransvr_p, + task_p->transvr_p->auto_tx_disable) + == EVENT_TRANSVR_TASK_DONE) { + goto ok_taskfunc_qsfp_handle_tx_disable; + } + mdelay(delay_ms); + } + SWPS_INFO("%s auto setup tx_disable:0x%02x fail.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_INIT_FAIL; + +ok_taskfunc_qsfp_handle_tx_disable: + SWPS_INFO("%s auto setup tx_disable:0x%02x ok.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_qsfp_set_hpmod(struct transvr_worker_s *task_p) { + + int err = DEBUG_TRANSVR_INT_VAL; + int HIGH_POWER_MODE = 0; + + /* Handle power mode */ + err = _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + HIGH_POWER_MODE); + if (err < 0) { + SWPS_INFO("%s: setup hpmod fail :%d :%s\n", + __func__, err, task_p->transvr_p->swp_name); + return err; + } + /* Handle auto tx_disable + * [Note] + * => Because there are some transceiver have timing issues or + * setup sequence issues, therefore we handle auto tx_disable + * after handle power mode. + */ + mdelay(100); + return taskfunc_qsfp_handle_tx_disable(task_p); +} + + +int +taskfunc_qsfp_set_lpmod(struct transvr_worker_s *task_p) { + + int LOW_POWER_MODE = 1; + return _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + LOW_POWER_MODE); +} + + +static int +initfunc_sfp_handle_multi_rate_mode(struct transvr_obj_s *self) { + + int task_retry = 3; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "sfp_handle_multi_rate_mode"; + struct transvr_worker_s *task_p = NULL; + + switch (self->rate_id) { + case 0x00: /* Unspecified */ + case 0x03: /* Unspecified */ + case 0x05: /* Unspecified */ + case 0x07: /* Unspecified */ + case 0x09: /* Unspecified */ + case 0x0B: /* Unspecified */ + case 0x0D: /* Unspecified */ + case 0x0F: /* Unspecified */ + goto sfp_handle_multi_rate_mode_4_unspecified; + + case 0x02: /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case1, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x04: /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case2, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x06: /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case3, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x01: /* SFF-8079 (4/2/1G Rate_Select & AS0/AS1) */ + err_str = "SFF-8079 (4/2/1G Rate_Select & AS0/AS1)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x08: /* FC-PI-5 (16/8/4G Rx Rate_select only) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Rx Rate_select only)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0A: /* FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0C: /* FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + */ + err_str = "FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0E: /* 10/8G Rx and Tx Rate_Select controlling the operation or + * locking modes of the internal signal conditioner, retimer + * or CDR, according to the logic table defined in Table 10-2, + * High Bit Rate (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = + * 8.5 Gb/s. In this mode, the default value of bit 110.3 (Soft + * Rate Select RS(0), Table 9-11) and of bit 118.3 (Soft Rate + * Select RS(1), Table 10-1) is 1. + */ + err_str = "cable type: 0x0E"; + goto sfp_handle_multi_rate_mode_4_not_support; + + default: + err_str = "cable type: UNKNOW"; + goto sfp_handle_multi_rate_mode_4_not_support; + } + +sfp_handle_multi_rate_mode_4_sff8431: + if (!task_p) { + err_str = "Create task fail!"; + goto sfp_handle_multi_rate_mode_4_fail_1; + } + transvr_task_set_retry(task_p, task_retry); + return EVENT_TRANSVR_TASK_WAIT; + +sfp_handle_multi_rate_mode_4_unspecified: + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_not_support: + SWPS_INFO("%s: Does not support %s :%s :0x%02x\n", + func_str, err_str, self->swp_name, self->rate_id); + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_fail_1: + SWPS_INFO("%s: %s :%s :0x%02x, :%d\n", + func_str, err_str, self->swp_name, self->rate_id, err_code); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +initfunc_sfp_handle_1g_rj45(struct transvr_obj_s *self) { + + struct transvr_worker_s *task_p = NULL; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_sfp_handle_1g_rj45"; + + + if (self->info == TRANSVR_CLASS_BASE_T_1000) { + task_p = transvr_task_creat(self, + taskfunc_sfp_handle_1g_rj45, + taskfunc_post_do_nothing, + func_str); + if (!task_p) { + snprintf(err_str, sizeof(err_str), "Create task fail"); + goto err_initfunc_sfp_handle_1g_rj45; + } + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_initfunc_sfp_handle_1g_rj45: + SWPS_INFO("%s: %s :%s :%d\n", + __func__, err_str, self->swp_name, detect_cls); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +initfunc_qsfp_handle_power_mode(struct transvr_obj_s *self) { + + int err_code = EVENT_TRANSVR_EXCEP_INIT; + int power_class = DEBUG_TRANSVR_INT_VAL; + int hpmod_retry = 3; + int lpower_config = 1; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + unsigned long hpmod_delay = 500; /* msec */ + struct transvr_worker_s *task_p = NULL; + + /* Handle power mode for IOEXP */ + power_class = __qsfp_get_power_cls(self, 0); + switch (power_class) { + case 1: /* Case: Low power mode (Class = 1) */ + err_code = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (err_code < 0){ + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + return EVENT_TRANSVR_TASK_DONE; + + case 2: /* Case: High power mode (Class > 1) */ + case 3: + case 4: + case 5: + case 6: + case 7: + task_p = transvr_task_creat(self, + taskfunc_qsfp_set_hpmod, + taskfunc_post_handle_task_state, + "transvr_init_qsfp"); + if (!task_p) { + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + transvr_task_set_retry(task_p, hpmod_retry); + transvr_task_set_delay(task_p, hpmod_delay); + return EVENT_TRANSVR_TASK_WAIT; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Exception case"); + goto err_initfunc_qsfp_handle_power_mode; + +err_initfunc_qsfp_handle_power_mode: + SWPS_INFO("%s: %s :%s \n", __func__, err_msg, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +initfunc_qsfp28_handle_cdr(struct transvr_obj_s *self) { + + uint8_t DEFAULT_VAL_CDR = 0xff; + int CDR_FUNC_EXISTED = 0x3; + int show_err = 1; + int err_val = EVENT_TRANSVR_TASK_FAIL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_qsfp28_handle_cdr"; + + err_val = __qsfp_get_cdr_present(self, 0); + if ( (err_val < 0) || + (err_val == DEBUG_TRANSVR_HEX_VAL) ) { + err_msg = "detect cdr_present fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + if (err_val == CDR_FUNC_EXISTED) { + err_val = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->offset_cdr, + DEFAULT_VAL_CDR, + &(self->cdr), + func_str, + show_err); + if (err_val < 0) { + err_msg = "set CDR fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_qsfp_handle_cdr_1: + SWPS_INFO("%s: %s :%d :%s\n", + func_str, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + +/* ========== 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 +_sfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = _sfp_get_comp_extended(self); + + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_25G_AOC; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_25G_SR; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_25G_LR; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_25G_ER; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x0c: /* 25GBASE-CR CA-S */ + case 0x0d: /* 25GBASE-CR CA-N */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L1_25G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_10_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _sfp_get_comp_10g_eth_comp(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 10G Optical (x1) */ + if ((detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + } + if ((detect_val & 0x80) == 0x80) { /* 10000000 : 10GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_1g = 0x0b; + int upper_bound_1g = 0x1A; + int lower_bound_10g = 0x60; + int upper_bound_10g = 0x75; + int lower_bound_25g = 0xf0; + int upper_bound_25g = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 25G */ + if ((notmal_br >= lower_bound_25g) && + (notmal_br <= upper_bound_25g) ) { + return TRANSVR_CLASS_25G; + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + /* Check 1G */ + if ((notmal_br >= lower_bound_1g) && + (notmal_br <= upper_bound_1g) ) { + return TRANSVR_CLASS_1G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + int speed_br = DEBUG_TRANSVR_INT_VAL; + int speed_tmp = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + + speed_br = _sfp_detect_if_sp_by_br(self); + detect_val = _sfp_get_comp_1g_eth_comp(self); + + if (detect_val < 0) { + snprintf(err_str, sizeof(err_str), "Detect abnormal value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + } + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 1G (x1) */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 1000BASE-SX */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_SX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x02) == 0x02) { /* 00000010 : 1000BASE-LX *3 */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_LX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 1000BASE-CX */ + speed_tmp = TRANSVR_CLASS_COPPER_L1_1G; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + /* Case: 1000 Base-T (x1) */ + if ((detect_val & 0x08) == 0x08) { /* 00001000 : 1000BASE-T */ + return TRANSVR_CLASS_BASE_T_1000; + } + /* Case: 100 Base */ + if ( ((detect_val & 0x10) == 0x10) || /* 00010000 : 100BASE-LX/LX10 */ + ((detect_val & 0x20) == 0x20) || /* 00100000 : 100BASE-FX */ + ((detect_val & 0x40) == 0x40) || /* 01000000 : BASE-BX10 *3 */ + ((detect_val & 0x80) == 0x80) ){ /* 10000000 : BASE-PX *3 */ + return TRANSVR_CLASS_OPTICAL_100; + } + /* Case: ERROR */ + snprintf(err_str, sizeof(err_str), "Case:ERROR, value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + +ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g: + switch (speed_br) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_1G: + return speed_tmp; + case TRANSVR_CLASS_10G: + goto ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G; + } + +ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G: + switch (speed_tmp) { + case TRANSVR_CLASS_OPTICAL_1G_SX: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case TRANSVR_CLASS_OPTICAL_1G_LX: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case TRANSVR_CLASS_COPPER_L1_1G: + return TRANSVR_CLASS_COPPER_L1_10G; + default: + break; + } + snprintf(err_str, sizeof(err_str), "transfer_1to10 fail, speed:%d", speed_tmp); + goto err_p_sfp_detect_class_by_1g_ethernet; + +err_p_sfp_detect_class_by_1g_ethernet: + SWPS_INFO("%s: %s :%s", __func__, err_str, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int is_active = 0; + int conn_val = DEBUG_TRANSVR_INT_VAL; + int check_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _sfp_detect_if_sp_by_br(self); + conn_val = _sfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 */ + case 0x0d: /* MPO 2x16 */ + /* + * ToDo: Need verify Optical Pigtail + */ + goto ok_sfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + /* + * ToDo: Need check ACC use case + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x23: /* No separable connector */ + /* + * ToDo: Standard not clear, not all transceiver vendor + * have the same defined + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_check_active_passive: + check_val = _sfp_get_cable_tech(self); + switch(check_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_unknow; + case 0x04: /* Passive */ + goto ok_sfp_detect_class_by_feature_4_copper; + case 0x08: /* Active */ + is_active = 1; + goto ok_sfp_detect_class_by_feature_4_aoc; + default: + snprintf(err_msg, sizeof(err_msg), + "_sfp_get_cable_tech return Non define value:%d", + check_val); + break; + } + goto err_sfp_detect_class_by_feature_1; + +ok_sfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_25G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_25G_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_25G_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_25G_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_25G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + case TRANSVR_CLASS_1G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_1G_SX; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_1G_LX; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_1G_EX; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_1G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_sfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_OPTICAL_25G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_S_AOC; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_OPTICAL_1G_AOC; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_COPPER_L1_25G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L1_10G; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_COPPER_L1_1G; + default: + return TRANSVR_CLASS_COPPER; + } + +ok_sfp_detect_class_by_feature_4_unknow: + return TRANSVR_CLASS_UNSPECIFIED; + +err_sfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +sft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _sfp_detect_class_by_extend_comp(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 10G Compliance */ + detect_val = _sfp_detect_class_by_10_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 1G Compliance */ + detect_val = _sfp_detect_class_by_1g_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_BASE_T_1000: + case TRANSVR_CLASS_OPTICAL_100: + /* + * ToDo: Need Check 0.1G + */ + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_COPPER_L1_10G: + /* Transfer speed case + * => Example: Raycom 10G DAC + */ + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 1G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check by connector, br, wavelength */ + detect_val = _sfp_detect_class_by_feature(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_OPTICAL_1G: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_COPPER: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_COPPER_L1_10G: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined get_connector:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sft_detect_transceiver_class_1; + +err_sft_detect_transceiver_class_1: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_trident2_if_type_1; + +err_sfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SR); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_KR); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_tomahawk_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_tomahawk_if_type_1; + +err_sfp_set_tomahawk_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_bf_tofino_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to BF looks like doesn't have interface type. + * We bypass it currently. + */ + int lmax = 8; + return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); +} + + +int +_sfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = sft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _sfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TOMAHAWK: + return _sfp_set_tomahawk_if_type(self, detect_cls, result); + + case BF_CHIP_TYPE_TOFINO: + return _sfp_set_bf_tofino_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_sfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = sft_detect_transvr_class(self); + switch(detect_val) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_SP_100); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + detect_val); + goto err_sfp_detect_if_speed_1; + } + /* Check by BR */ + detect_val = _sfp_detect_if_sp_by_br(self); + switch (detect_val) { + case TRANSVR_CLASS_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + default: + break; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_detect_if_speed_1; + +err_sfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_extended(self); + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_100G_AOC; + + case 0x06: /* 100G CWDM4 */ + case 0x09: /* Obsolete (assigned before 100G CWDM4 MSA required FEC) */ + case 0x17: /* 100G CLR4 */ + case 0x1A: /* 100GE-DWDM2 */ + return TRANSVR_CLASS_OPTICAL_100G; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_100G_SR4; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_100G_LR4; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_100G_ER4; + + case 0x07: /* 100G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_100G_PSM4; + + case 0x12: /* 40G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_40G; + + case 0x11: /* 4 x 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + + case 0x10: /* 40GBASE-ER4 */ + return TRANSVR_CLASS_OPTICAL_40G_ER4; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L4_100G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_class_by_10_40_100_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_10_40_100_ethernet(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 40G Optical */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 40G Active Cable (XLPPI) */ + return TRANSVR_CLASS_OPTICAL_40G_AOC; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 40GBASE-SR4 */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + } + if ( (detect_val & 0x02) == 0x02) { /* 00000010 : 40GBASE-LR4 */ + return TRANSVR_CLASS_OPTICAL_40G_LR4; + } + if ( (detect_val & 0x08) == 0x08) { /* 00001000 : 40GBASE-CR4 */ + return TRANSVR_CLASS_COPPER_L4_40G; + } + /* Case: 10G Optical */ + if ( (detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + } + /* Case: Extend Compliance */ + if ( ((detect_val & 0x80) == 0x80) ){ /* 10000000 : Use Extend Compliance */ + return TRANSVR_CLASS_EXTEND_COMP; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_10g = 0x10; + int upper_bound_10g = 0x25; + int lower_bound_40g = 0x60; + int upper_bound_40g = 0x75; + int lower_bound_100g = 0x60; + int upper_bound_100g = 0x75; + int used_extend_br = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + int extend_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 40G */ + if ((notmal_br >= lower_bound_40g) && + (notmal_br <= upper_bound_40g) ) { + return TRANSVR_CLASS_40G; + } + /* Check 100G */ + if (notmal_br == used_extend_br) { + extend_br = (int)(self->extbr); /* updated by update_all() */ + if ((extend_br >= lower_bound_100g) && + (extend_br <= upper_bound_100g) ) { + return TRANSVR_CLASS_100G; + } + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_qsfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int conn_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _qsfp_detect_if_sp_by_br(self); + conn_val = _qsfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 (Multifiber Parallel Optic) */ + case 0x0d: /* MPO 2x16 */ + goto ok_qsfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + goto ok_qsfp_detect_class_by_feature_4_copper; + case 0x23: /* No separable connector */ + if ((_qsfp_get_comp_fc_link_length(self) > 0) || + (_qsfp_get_comp_fc_trans_tech(self) > 0) || + (_qsfp_get_comp_fc_trans_media(self) > 0) || + (_qsfp_get_comp_fc_speed(self) > 0) ) { + goto ok_qsfp_detect_class_by_feature_4_aoc; + } + goto ok_qsfp_detect_class_by_feature_4_copper; + default: + snprintf(err_msg, sizeof(err_msg), + "_qsfp_get_connector_type return Non define value:%d", + conn_val); + goto err_qsfp_detect_class_by_feature_1; + } + return TRANSVR_CLASS_UNSPECIFIED; + +ok_qsfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_100G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_100G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_100G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_100G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_100G; + + case TRANSVR_CLASS_40G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_40G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_40G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_40G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_40G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_Q_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_OPTICAL_100G_AOC; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_OPTICAL_40G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_Q_AOC; + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_COPPER_L4_100G; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_COPPER_L4_40G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L4_10G; + default: + return TRANSVR_CLASS_COPPER; + } + +err_qsfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", + __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +qsft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _qsfp_detect_class_by_extend_comp(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_COPPER_L4_100G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check 10/40G/100G Ethernet Compliance */ + detect_val = _qsfp_detect_class_by_10_40_100_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_COPPER_L4_40G: + return detect_val; + case TRANSVR_CLASS_EXTEND_COMP: + /* Format incorrect case (We already checked the Extend + * Compliance is 0 + */ + snprintf(err_msg, sizeof(err_msg), + "Transceiver format incorrect"); + goto err_qsft_detect_transvr_class_1; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10/40/100:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check by Connector type, BR and wavelength */ + detect_val = _qsfp_detect_class_by_feature(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_COPPER_L4_100G: + case TRANSVR_CLASS_COPPER_L4_40G: + case TRANSVR_CLASS_COPPER_L4_10G: + case TRANSVR_CLASS_COPPER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined connector:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), + "Can not identify!"); + goto err_qsft_detect_transvr_class_1; + +err_qsft_detect_transvr_class_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: LR4 or LR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: /* Need Check: ER4 or ER */ + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_KR4); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_bf_tofino_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to BF looks like doesn't have interface type. + * We bypass it currently. + */ + int lmax = 8; + return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); +} + + +int +_qsfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = qsft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _qsfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TOMAHAWK: + return _qsfp_set_tomahawk_if_type(self, detect_cls, result); + + case BF_CHIP_TYPE_TOFINO: + return _qsfp_set_bf_tofino_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 8; + char tmp_result[8] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = qsft_detect_transvr_class(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G Copper */ + case TRANSVR_CLASS_COPPER_L4_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + break; + /* Copper */ + case TRANSVR_CLASS_COPPER: + break; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined class case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Check br and extbr */ + detect_val = _qsfp_detect_if_sp_by_br(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + case TRANSVR_CLASS_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined BR case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_detect_if_speed_1; + +err_qsfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_common_set_lane_map_str(struct transvr_obj_s* self, + char *result) { + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + char err_msg[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_L_STR); + snprintf(result, LEN_TRANSVR_L_STR, "%s=", TRANSVR_UEVENT_KEY_LANE); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + if (tmp_val > 256) { + snprintf(err_msg, sizeof(err_msg), + "detect abnormal value:%d", tmp_val); + goto err_common_set_lane_map_str_1; + } + memset(tmp_str, 0, sizeof(tmp_str)); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_L_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_L_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_L_STR); + } + if (i == 0) { + goto err_common_set_lane_map_str_2; + } + return 0; + +err_common_set_lane_map_str_1: + SWPS_INFO("%s: %s", __func__, err_msg); +err_common_set_lane_map_str_2: + snprintf(result, LEN_TRANSVR_L_STR, "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_common_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action, + int (*detect_if_type)(struct transvr_obj_s *self, char *result), + int (*detect_if_speed)(struct transvr_obj_s *self, char *result), + int send_anyway) { + + char *uevent_envp[4]; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + char tmp_str[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_1[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_2[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_3[64] = DEBUG_TRANSVR_STR_VAL; + + if (TRANSVR_UEVENT_ENABLE != 1) { + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_get_if_lane(self, tmp_str) < 0) { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + } else { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, tmp_str); + } + switch (u_action) { + case KOBJ_ADD: + /* Detect type */ + if (detect_if_type(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface type fail!"); + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, tmp_str); + uevent_envp[0] = tmp_str_1; + /* Detect speed */ + if (detect_if_speed(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface speed fail!"); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, tmp_str); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + case KOBJ_REMOVE: + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + default: + snprintf(err_msg, sizeof(err_msg), "kobject_action:%d not support", u_action); + goto private_common_send_uevent_4_fail; + } + snprintf(err_msg, sizeof(err_msg), "%s", "Exception case"); + goto private_common_send_uevent_4_fail; + +private_common_send_uevent_4_fail: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + if (send_anyway) { + goto private_common_send_uevent_4_send; + } + return ERR_TRANSVR_UEVENT_FAIL; + +private_common_send_uevent_4_send: + return kobject_uevent_env(&(self->transvr_dev_p->kobj), + u_action, + uevent_envp); +} + +int +sfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_sfp_detect_if_type, + &_sfp_detect_if_speed, + send_anyway); +} + + +int +qsfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_qsfp_detect_if_type, + &_qsfp_detect_if_speed, + send_anyway); +} + + +int +fake_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + return EVENT_TRANSVR_TASK_DONE; +} + + +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; +} + + +static int +_is_except_happened_4_pmode(struct transvr_obj_s* self, + int new_state) { + + int event_chk = 0; + + if (self->temp == 0){ + return 0; + } + switch (new_state) { + case STATE_TRANSVR_INIT: + event_chk = EVENT_TRANSVR_EXCEP_INIT; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_CONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_UP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_DISCONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_DOWN; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_SWAPPED: + event_chk = EVENT_TRANSVR_EXCEP_SWAP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_UNEXCEPTED: + event_chk = EVENT_TRANSVR_EXCEP_EXCEP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_ISOLATED: + event_chk = EVENT_TRANSVR_EXCEP_ISOLATED; + goto check_event_happened_4_pmode; + + default: + SWPS_INFO("%s: unexcepted case:%d\n", __func__, new_state); + break; + } + return 0; + +check_event_happened_4_pmode: + if (self->temp == event_chk){ + return 1; + } + return 0; +} + + +int +common_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + /* [Return Value]: + * ERR_TRANSVR_UNINIT : (1) Initial not ready + * ERR_TRANSVR_UNPLUGGED : (1) Any -> Down + * ERR_TRANSVR_TASK_BUSY : (1) Wait Initial task + * ERR_TRANSVR_UNEXCPT : (1) Initial fail + * (2) Task fail + * (3) Reload fail + * ERR_TRNASVR_BE_ISOLATED : (1) Already be isolated + * OK Case (return 0) : (1) action_4_connected + * (2) action_4_nothing (initial retry) + */ + int curr_state[2]; + int old_state = self->state; + int old_type = self->type; + int new_state = STATE_TRANSVR_UNEXCEPTED; + int new_type = TRANSVR_TYPE_ERROR; + int return_val = ERR_TRANSVR_UNEXCPT; + + /* Never initial */ + if (self->state == STATE_TRANSVR_NEW) { + goto comfsm_action_4_reinit_obj; + } + /* Detect current state */ + switch (detect_transvr_state(self, curr_state)) { + case 0: + new_state = curr_state[0]; + new_type = curr_state[1]; + break; + + case ERR_TRNASVR_BE_ISOLATED: + new_state = STATE_TRANSVR_ISOLATED; + new_type = old_type; + break; + + case ERR_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case ERR_TRANSVR_UNEXCPT: + default: + new_state = STATE_TRANSVR_UNEXCEPTED; + new_type = old_type; + } + /* State handling */ + switch (old_state) { + case STATE_TRANSVR_INIT: /* INIT -> */ + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 1-1: UP -> INIT */ + SWPS_INFO("Detect %s is present. :1-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 1-2: UP -> UP */ + return_val = 0; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 1-3: UP -> DOWN */ + SWPS_INFO("Detect %s is removed. :1-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 1-4: UP -> SWAP */ + SWPS_INFO("Detect %s is swapped. :1-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 1-5: UP -> UNEXPET */ + SWPS_INFO("Detect %s has error. :1-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 1-6: UP -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :1-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_DISCONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 2-1: DOWN -> INIT */ + SWPS_INFO("Detect %s is present. :2-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 2-2: DOWN -> UP */ + SWPS_INFO("Detect %s is present. :2-2\n",self->swp_name); + goto comfsm_action_4_reinit_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 2-3: DOWN -> DOWN */ + return_val = ERR_TRANSVR_UNPLUGGED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_SWAPPED: /* Case 2-4: DOWN -> SWAP */ + SWPS_INFO("Detect %s is swapped. :2-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 2-5: DOWN -> UNEXPET */ + SWPS_INFO("Detect %s has error. :2-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 2-6: DOWN -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :2-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_UNEXCEPTED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 3-1: UNEXPET -> INIT */ + SWPS_INFO("Detect %s is present. :3-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 3-2: UNEXPET -> UP */ + SWPS_INFO("Detect %s is present. :3-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 3-3: UNEXPET -> DOWN */ + SWPS_INFO("Detect %s is removed. :3-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 3-4: UNEXPET -> SWAP */ + SWPS_INFO("Detect %s is swapped. :3-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 3-5: UNEXPET -> UNEXPET */ + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRANSVR_UNEXCPT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 3-6: UNEXPET -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :3-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 4-1: ISOLATE -> INIT */ + SWPS_INFO("Detect %s internal error. :4-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 4-2: ISOLATE -> UP */ + SWPS_INFO("Detect %s internal error. :4-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 4-3: ISOLATE -> DOWN */ + SWPS_INFO("Detect %s is removed. :4-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 4-4: ISOLATE -> SWAP */ + SWPS_INFO("Detect %s internal error. :4-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 4-5: ISOLATE -> UNEXPET */ + SWPS_INFO("Detect %s internal error. :4-5\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 4-6: ISOLATE -> ISOLATE */ + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + default: + break; + } + goto comfsm_action_4_unexpected; + + default: + break; + } + goto comfsm_action_4_unexpected; + + +comfsm_action_4_keep_state: + return return_val; + +comfsm_action_4_reinit_obj: + SWPS_DEBUG("FSM action: %s re-initial.\n", self->swp_name); + return_val = _transvr_init_handler(self); + goto comfsm_action_4_identify_event; + +comfsm_action_4_reload_obj: + SWPS_DEBUG("FSM action: %s reload.\n", self->swp_name); + self->type = new_type; + return_val = reload_transvr_obj(self, new_type); + goto comfsm_action_4_identify_event; + +comfsm_action_4_identify_event: + switch (return_val) { + case EVENT_TRANSVR_INIT_UP: + case EVENT_TRANSVR_TASK_DONE: + goto comfsm_action_4_connected; + + case EVENT_TRANSVR_INIT_DOWN: + goto comfsm_action_4_disconnected; + + case EVENT_TRANSVR_INIT_REINIT: + goto comfsm_action_4_nothing; + + case EVENT_TRANSVR_TASK_WAIT: + self->state = STATE_TRANSVR_INIT; + return ERR_TRANSVR_TASK_BUSY; + + case EVENT_TRANSVR_TASK_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_TASK_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_INIT_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_INIT_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_RELOAD_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_RELOAD_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case EVENT_TRANSVR_EXCEP_ISOLATED: + goto comfsm_action_4_isolate_obj; + + default: + SWPS_INFO("%s detect undefined event:%d.\n", self->swp_name, return_val); + goto comfsm_action_4_unexpected; + } + +comfsm_action_4_nothing: + SWPS_DEBUG("FSM action: %s do nothing.\n", self->swp_name); + return 0; + +comfsm_action_4_connected: + SWPS_DEBUG("FSM action: %s Connected.\n", self->swp_name); + self->state = STATE_TRANSVR_CONNECTED; + self->type = new_type; + self->send_uevent(self, KOBJ_ADD); + _transvr_clean_retry(self); + return 0; + +comfsm_action_4_disconnected: + SWPS_DEBUG("FSM action: %s Disconnected. \n", self->swp_name); + self->state = STATE_TRANSVR_DISCONNECTED; + self->temp = EVENT_TRANSVR_TASK_DONE; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_retry(self); + _transvr_clean_handler(self); + return ERR_TRANSVR_UNPLUGGED; + +comfsm_action_4_report_i2c_crash: + SWPS_DEBUG("FSM action: %s report I2C crash.\n", self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_I2C_CRASH; + +comfsm_action_4_isolate_obj: + SWPS_DEBUG("FSM action: %s isolate.\n", self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return ERR_TRNASVR_BE_ISOLATED; + +comfsm_action_4_unexpected: + SWPS_INFO("FSM action: %s unexpected.\n", self->swp_name); + SWPS_INFO("Dump: :%d :0x%02x :%d :0x%02x\n", + old_state, old_type, new_state, new_type); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_handler(self); + 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; +} + + +int +fake_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + + +/* ========== Object functions for Initial procedure ========== + */ +int +transvr_init_common(struct transvr_obj_s *self){ + /* Nothing to update */ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_fake(struct transvr_obj_s *self){ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_sfp(struct transvr_obj_s *self){ + + int tmp_val = DEBUG_TRANSVR_INT_VAL; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_msg = "ERR"; + + self->info = sft_detect_transvr_class(self); + /* Disable auto_config */ + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + /* Handle multi-rate */ + err_code = initfunc_sfp_handle_multi_rate_mode(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_multi_rate_mode fail!"; + goto err_transvr_init_sfp_1; + } + /* Handle 1G- RJ45 */ + tmp_val = err_code; + err_code = initfunc_sfp_handle_1g_rj45(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_1g_rj45 fail!"; + goto err_transvr_init_sfp_1; + } + tmp_val = (tmp_val > err_code ? tmp_val : err_code); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_sfp_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_code, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp(struct transvr_obj_s *self){ + + int err = EVENT_TRANSVR_EXCEP_EXCEP; + char *emsg = "ERR"; + + self->info = qsft_detect_transvr_class(self); + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + err = initfunc_qsfp_handle_power_mode(self); + if (err < 0){ + emsg = "initfunc_qsfp_handle_tx_disable fail!"; + goto err_transvr_init_qsfp; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, emsg, err, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp28(struct transvr_obj_s *self){ + + int tmp_val = EVENT_TRANSVR_EXCEP_EXCEP; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_msg = "ERR"; + + /* Handle QSFP common */ + err_val = transvr_init_qsfp(self); + if (err_val < 0){ + err_msg = "transvr_init_qsfp fail!"; + goto err_transvr_init_qsfp28_1; + } + /* Disable auto_config */ + if (!self->auto_config) { + return err_val; + } + /* Handle CDR */ + tmp_val = err_val; + err_val = initfunc_qsfp28_handle_cdr(self); + if (err_val < 0){ + err_msg = "Handle CDR fail!"; + goto err_transvr_init_qsfp28_1; + } + tmp_val = (tmp_val > err_val ? tmp_val : err_val); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp28_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +/* ========== 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 +_is_transvr_support_ctle(struct transvr_obj_s *self) { + + switch (self->info) { + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return 1; + default: + break; + } + return 0; +} + + +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; + } + if (self->clean == NULL) { + snprintf(emsg, elimit, "clean() is null"); + goto initer_err_case_unexcept_0; + } + self->clean(self); + + /* 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_1; + } + + /* 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_1; + } + } + + /* 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_1; + } + + /* 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_1; + } + goto initer_ok_case_up; + + +initer_ok_case_wait: + self->dump_all(self); + return EVENT_TRANSVR_TASK_WAIT; + +initer_ok_case_up: + self->state = STATE_TRANSVR_CONNECTED; + self->temp = 0; + self->dump_all(self); + 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_1: + self->clean(self); +initer_err_case_unexcept_0: + self->state = STATE_TRANSVR_UNEXCEPTED; + if (_is_except_happened_4_pmode(self, d_state) && + (self->mode == TRANSVR_MODE_POLLING) ){ + SWPS_INFO("%s: %s :%s\n", __func__, emsg, self->swp_name); + SWPS_INFO("Dump: :%d :%d :%d :%d\n", + self->state, self->type, d_state, d_type); + } + 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; +} + + +/* ========== Object functions for Clean procedure ========== + */ +int +_transvr_clean_handler(struct transvr_obj_s *self){ + + int retval = DEBUG_TRANSVR_INT_VAL; + + if (!self->clean) { + SWPS_ERR("%s: %s clean() is NULL.\n", + __func__, self->swp_name); + return EVENT_TRANSVR_TASK_FAIL; + } + retval = self->clean(self); + if (retval != EVENT_TRANSVR_TASK_DONE){ + SWPS_ERR("%s: %s clean() fail. [ERR]:%d\n", + __func__, self->swp_name, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +common_transvr_clean(struct transvr_obj_s *self){ + + transvr_task_free_all(self); + transvr_cache_free_all(self); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +qsfp_transvr_clean(struct transvr_obj_s *self){ + + int retval; + int lpower_config = 1; + + retval = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (retval < 0){ + SWPS_ERR("%s: Set lpmod fail! :%d\n", + __func__, retval); + return retval; + } + retval = common_transvr_clean(self); + if (retval < 0){ + SWPS_ERR("%s: common_transvr_clean fail! :%d\n", + __func__, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +fake_transvr_clean(struct transvr_obj_s *self){ + + return EVENT_TRANSVR_TASK_DONE; +} + + +/* ========== Object functions for check and update ========== + */ +int +common_transvr_check(struct transvr_obj_s *self){ + + char fun_str[32] = "common_transvr_check"; + + if (self->mode != TRANSVR_MODE_POLLING) { + SWPS_ERR("%s: mode:%d is not TRANSVR_MODE_POLLING\n", + fun_str, self->mode); + return ERR_TRANSVR_UNEXCPT; + } + /* Trigger delay task */ + transvr_task_run_all(self); + /* Trigger state machine to check and update */ + return self->fsm_4_polling(self, fun_str); +} + + +int +fake_transvr_check(struct transvr_obj_s *self){ + return 0; +} + + +/* ========== Functions for Factory pattern ========== + */ +static int +setup_transvr_public_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = unsupported_get_func; + self->get_br = common_get_br; + self->get_len_sm = sfp_get_len_sm; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = sfp_get_comp_eth_1; + self->get_comp_eth_10 = sfp_get_comp_eth_10; + self->get_comp_eth_10_40 = unsupported_get_func; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = sfp_get_rate_id; + self->get_soft_rs0 = sfp_get_soft_rs0; + self->get_soft_rs1 = sfp_get_soft_rs1; + self->get_info = common_get_info; + self->get_if_type = sfp_get_if_type; + self->get_if_speed = sfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = sfp_get_transvr_temp; + self->get_curr_vol = sfp_get_transvr_voltage; + self->get_soft_rx_los = unsupported_get_func2; + self->get_soft_tx_disable = unsupported_get_func2; + self->get_soft_tx_fault = unsupported_get_func2; + self->get_auto_tx_disable = unsupported_get_func2; + self->get_tx_bias = sfp_get_transvr_tx_bias; + self->get_tx_power = sfp_get_transvr_tx_power; + self->get_rx_power = sfp_get_transvr_rx_power; + self->get_tx_eq = sfp_get_transvr_tx_eq; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = sfp_get_transvr_rx_em; + self->get_wavelength = sfp_get_wavelength; + self->get_extphy_offset = sfp_get_1g_rj45_extphy_offset; + self->get_extphy_reg = sfp_get_1g_rj45_extphy_reg; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = sfp_set_soft_rs0; + self->set_soft_rs1 = sfp_set_soft_rs1; + self->set_soft_tx_disable = unsupported_set_func; + self->set_auto_tx_disable = unsupported_set_func; + self->set_tx_eq = sfp_set_tx_eq; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = sfp_set_rx_em; + self->set_extphy_offset = sfp_set_1g_rj45_extphy_offset; + self->set_extphy_reg = sfp_set_1g_rj45_extphy_reg; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = unsupported_get_func2; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = unsupported_get_func2; + self->get_wavelength = qsfp_get_wavelength; + self->get_extphy_offset = unsupported_get_func2; + self->get_extphy_reg = unsupported_get_func2; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = unsupported_set_func; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = unsupported_set_func; + self->set_extphy_offset = unsupported_set_func; + self->set_extphy_reg = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = qsfp_get_cdr; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = qsfp_get_transvr_tx_eq; + self->get_rx_am = qsfp_get_transvr_rx_am; + self->get_rx_em = qsfp_get_transvr_rx_em; + self->get_wavelength = qsfp_get_wavelength; + self->get_extphy_offset = unsupported_get_func2; + self->get_extphy_reg = unsupported_get_func2; + self->set_cdr = qsfp_set_cdr; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = qsfp_set_tx_eq; + self->set_rx_am = qsfp_set_rx_am; + self->set_rx_em = qsfp_set_rx_em; + self->set_extphy_offset = unsupported_set_func; + self->set_extphy_reg = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_FAKE: + self->get_id = fake_get_hex; + self->get_ext_id = fake_get_hex; + self->get_connector = fake_get_hex; + self->get_vendor_name = fake_get_str; + self->get_vendor_pn = fake_get_str; + self->get_vendor_rev = fake_get_str; + self->get_vendor_sn = fake_get_str; + self->get_power_cls = fake_get_int; + self->get_br = fake_get_hex; + self->get_len_sm = fake_get_int; + self->get_len_smf = fake_get_int; + self->get_len_om1 = fake_get_int; + self->get_len_om2 = fake_get_int; + self->get_len_om3 = fake_get_int; + self->get_len_om4 = fake_get_int; + self->get_comp_rev = fake_get_hex; + self->get_comp_eth_1 = fake_get_hex; + self->get_comp_eth_10 = fake_get_hex; + self->get_comp_eth_10_40 = fake_get_hex; + self->get_comp_extend = fake_get_hex; + self->get_cdr = fake_get_hex; + self->get_rate_id = fake_get_hex; + self->get_soft_rs0 = fake_get_binary; + self->get_soft_rs1 = fake_get_binary; + self->get_info = fake_get_int; + self->get_if_type = fake_get_str; + self->get_if_speed = fake_get_str; + self->get_if_lane = fake_get_str; + self->get_curr_temp = fake_get_str; + self->get_curr_vol = fake_get_str; + self->get_soft_rx_los = fake_get_str; + self->get_soft_tx_disable = fake_get_str; + self->get_soft_tx_fault = fake_get_str; + self->get_auto_tx_disable = fake_get_str; + self->get_tx_bias = fake_get_str; + self->get_tx_power = fake_get_str; + self->get_rx_power = fake_get_str; + self->get_tx_eq = fake_get_str; + self->get_rx_am = fake_get_str; + self->get_rx_em = fake_get_str; + self->get_wavelength = fake_get_str; + self->get_extphy_offset = fake_get_str; + self->get_extphy_reg = fake_get_str; + self->set_cdr = fake_set_hex; + self->set_soft_rs0 = fake_set_int; + self->set_soft_rs1 = fake_set_int; + self->set_soft_tx_disable = fake_set_int; + self->set_auto_tx_disable = fake_set_int; + self->set_tx_eq = fake_set_int; + self->set_rx_am = fake_set_int; + self->set_rx_em = fake_set_int; + self->set_extphy_offset = fake_set_hex; + self->set_extphy_reg = fake_set_hex; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static int +setup_transvr_private_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->init = transvr_init_sfp; + self->clean = common_transvr_clean; + self->check = common_transvr_check; + self->update_all = _sfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = sfp_send_uevent; + self->dump_all = sfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->init = transvr_init_qsfp; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->init = transvr_init_qsfp28; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_FAKE: + self->init = transvr_init_fake; + self->clean = fake_transvr_clean; + self->check = fake_transvr_check; + self->update_all = fake_transvr_update; + self->fsm_4_direct = fake_fsm_4_direct_mode; + self->fsm_4_polling = fake_fsm_4_polling_mode; + self->send_uevent = fake_send_uevent; + self->dump_all = fake_transvr_dump; + 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_SFP: + return &eeprom_map_sfp; + 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 */ + case TRANSVR_MODE_POLLING: /* Polling mode, read from cache */ + 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_transvr_dsize_attr(struct transvr_obj_s *self){ + + char *emsg = DEBUG_TRANSVR_STR_VAL; + + self->vendor_name = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_name){ + emsg = "vendor_name"; + goto err_setup_d_attr; + } + self->vendor_pn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_pn){ + emsg = "vendor_pn"; + goto err_setup_d_attr; + } + self->vendor_rev = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_rev){ + emsg = "vendor_rev"; + goto err_setup_d_attr; + } + self->vendor_sn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_sn){ + emsg = "vendor_sn"; + goto err_setup_d_attr; + } + self->worker_p = NULL; + return 0; + +err_setup_d_attr: + SWPS_ERR("%s: %s kzalloc fail!", __func__, emsg); + return ERR_TRANSVR_UNEXCPT; +} + + +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 dynamic size attributes */ + if (setup_transvr_dsize_attr(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_public_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_private_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare i2c client object */ + if (setup_i2c_client(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + return result_p; + +err_create_transvr_dattr_fail: + kfree(result_p->vendor_sn); + kfree(result_p->vendor_rev); + kfree(result_p->vendor_pn); + kfree(result_p->vendor_name); +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; + } + /* Replace call back functions */ + if (setup_transvr_public_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + 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; +} + + +int +isolate_transvr_obj(struct transvr_obj_s *self) { + + self->state = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s be isolated\n", __func__, self->swp_name); + return 0; +} + + +int +resync_channel_tier_2(struct transvr_obj_s *self) { + + int val = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_ISOLATED) { + return 0; + } + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + val = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (val < 0) { + return -1; + } + return 0; +} + + +/* ----------------------------------------- + * ToDo List + * ----------------------------------------- + * 1. _sfp_detect_class_by_feature() + * => Need check ACC use case. + * 2. _sfp_detect_class_by_1g_ethernet() + * => Need check 0.1G use case. + * 3. Loopback transceiver use case. + * => Less much data + * 4. _qsfp_detect_class_by_extend_comp() + * => Verify 100G CWDM4 + * => Verify Obsolete (assigned before 100G CWDM4 MSA required FEC) + * => Verify 100G CLR4 + * => Verify 100GE-DWDM2 + * => Verify 40G PSM4 Parallel SMF + * => Verify 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. + * => Verify 100G ACC or 25GAUI C2M ACC. + * => Verify 25GBASE-LR + * => Verify 40G Active Cable (XLPPI) + */ + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/transceiver.h new file mode 100644 index 000000000000..42e1938670fb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/transceiver.h @@ -0,0 +1,814 @@ +/* + * 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. + */ + +#ifndef TRANSCEIVER_H +#define TRANSCEIVER_H + +#include + +/* advanced features control */ +#define TRANSVR_INFO_DUMP_ENABLE (1) +#define TRANSVR_INFO_CACHE_ENABLE (1) +#define TRANSVR_UEVENT_ENABLE (1) + +/* 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 class for base info */ +#define TRANSVR_CLASS_UNSPECIFIED (0) +#define TRANSVR_CLASS_ERROR (-26001) +#define TRANSVR_CLASS_1G (26001) +#define TRANSVR_CLASS_10G (26011) +#define TRANSVR_CLASS_25G (26021) +#define TRANSVR_CLASS_40G (26041) +#define TRANSVR_CLASS_100G (26101) +#define TRANSVR_CLASS_NO_SPERARABLE (26901) +#define TRANSVR_CLASS_EXTEND_COMP (26902) +/* Transceiver class for Optical 1G */ +#define TRANSVR_CLASS_OPTICAL (27000) +#define TRANSVR_CLASS_OPTICAL_100 (27001) +#define TRANSVR_CLASS_OPTICAL_1G (27002) +#define TRANSVR_CLASS_OPTICAL_1G_AOC (27003) +#define TRANSVR_CLASS_OPTICAL_1G_SX (27004) +#define TRANSVR_CLASS_OPTICAL_1G_LX (27005) +#define TRANSVR_CLASS_OPTICAL_1G_EX (27006) +/* Transceiver class for Optical 10G */ +#define TRANSVR_CLASS_OPTICAL_10G (27010) +#define TRANSVR_CLASS_OPTICAL_10G_S_AOC (27011) +#define TRANSVR_CLASS_OPTICAL_10G_S_SR (27012) +#define TRANSVR_CLASS_OPTICAL_10G_S_LR (27013) +#define TRANSVR_CLASS_OPTICAL_10G_S_ER (27014) +#define TRANSVR_CLASS_OPTICAL_10G_Q_AOC (27015) +#define TRANSVR_CLASS_OPTICAL_10G_Q_SR (27016) +#define TRANSVR_CLASS_OPTICAL_10G_Q_LR (27017) +#define TRANSVR_CLASS_OPTICAL_10G_Q_ER (27018) +/* Transceiver class for Optical 25G */ +#define TRANSVR_CLASS_OPTICAL_25G (27020) +#define TRANSVR_CLASS_OPTICAL_25G_AOC (27021) +#define TRANSVR_CLASS_OPTICAL_25G_SR (27022) +#define TRANSVR_CLASS_OPTICAL_25G_LR (27023) +#define TRANSVR_CLASS_OPTICAL_25G_ER (27024) +/* Transceiver class for Optical 40G */ +#define TRANSVR_CLASS_OPTICAL_40G (27040) +#define TRANSVR_CLASS_OPTICAL_40G_AOC (27041) +#define TRANSVR_CLASS_OPTICAL_40G_SR4 (27042) +#define TRANSVR_CLASS_OPTICAL_40G_LR4 (27043) +#define TRANSVR_CLASS_OPTICAL_40G_ER4 (27044) +/* Transceiver class for Optical 100G */ +#define TRANSVR_CLASS_OPTICAL_100G (27100) +#define TRANSVR_CLASS_OPTICAL_100G_AOC (27101) +#define TRANSVR_CLASS_OPTICAL_100G_SR4 (27102) +#define TRANSVR_CLASS_OPTICAL_100G_LR4 (27103) +#define TRANSVR_CLASS_OPTICAL_100G_ER4 (27104) +#define TRANSVR_CLASS_OPTICAL_100G_PSM4 (27105) +/* Transceiver class for Copper */ +#define TRANSVR_CLASS_COPPER (28000) +#define TRANSVR_CLASS_COPPER_L1_1G (28001) +#define TRANSVR_CLASS_COPPER_L1_10G (28011) +#define TRANSVR_CLASS_COPPER_L4_10G (28012) +#define TRANSVR_CLASS_COPPER_L1_25G (28021) +#define TRANSVR_CLASS_COPPER_L4_40G (28041) +#define TRANSVR_CLASS_COPPER_L4_100G (28101) +/* Transceiver class for Base-T */ +#define TRANSVR_CLASS_BASE_T_1000 (29001) +#define TRANSVR_CLASS_BASE_T_1000_up (29002) +/* For uevent message */ +#define TRANSVR_UEVENT_KEY_IF "IF_TYPE" +#define TRANSVR_UEVENT_KEY_SP "IF_SPEED" +#define TRANSVR_UEVENT_KEY_LANE "IF_LANE" +#define TRANSVR_UEVENT_UNKNOW "UNKNOW" +#define TRANSVR_IF_KR "KR" +#define TRANSVR_IF_KR4 "KR4" +#define TRANSVR_IF_SR "SR" +#define TRANSVR_IF_SR4 "SR4" +#define TRANSVR_IF_SFI "SFI" +#define TRANSVR_IF_IF_GMII "GMII" +#define TRANSVR_IF_IF_XGMII "XGMII" +#define TRANSVR_IF_SP_100 "100" +#define TRANSVR_IF_SP_1G "1000" +#define TRANSVR_IF_SP_10G "10000" +#define TRANSVR_IF_SP_25G "25000" +#define TRANSVR_IF_SP_40G "40000" +#define TRANSVR_IF_SP_100G "100000" + +/* Transceiver mode define */ +#define TRANSVR_MODE_DIRECT (21000) +#define TRANSVR_MODE_POLLING (21001) + +/* 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. */ + +/* Task state define */ +#define STATE_T_TASK_WAIT (110) +#define STATE_T_TASK_DONE (0) +#define STATE_T_TASK_INIT (-110) +#define STATE_T_TASK_FAIL (-410) + + +/* 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_UEVENT_FAIL (-213) +#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_EXTPHY_ADDR_56 (0x56) +#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_SFP "SFP" +#define STR_TRANSVR_QSFP "QSFP" +#define STR_TRANSVR_QSFP_PLUS "QSFP+" +#define STR_TRANSVR_QSFP28 "QSFP28" + +/* For transvr buf len */ +#define LEN_TRANSVR_S_STR (16) +#define LEN_TRANSVR_M_STR (32) +#define LEN_TRANSVR_L_STR (64) + +/* Optical wavelength */ +#define VAL_OPTICAL_WAVELENGTH_SR (850) +#define VAL_OPTICAL_WAVELENGTH_LR (1310) +#define VAL_OPTICAL_WAVELENGTH_ER (1550) + +/* BCM chip type define */ +#define BCM_CHIP_TYPE_TRIDENT_2 (31001) /* Magnolia, Hudson32i, Spruce */ +#define BCM_CHIP_TYPE_TOMAHAWK (31002) /* Redwood, Cypress, Sequoia */ + +#define BF_CHIP_TYPE_TOFINO (31011) /* Lavender */ + +/* Info from transceiver EEPROM */ +struct eeprom_map_s { + int addr_br; int page_br; int offset_br; int length_br; + int addr_cdr; int page_cdr; int offset_cdr; int length_cdr; + int addr_comp_rev; int page_comp_rev; int offset_comp_rev; int length_comp_rev; + int addr_connector; int page_connector; int offset_connector; int length_connector; + int addr_diag_type; int page_diag_type; int offset_diag_type; int length_diag_type; + int addr_extbr; int page_extbr; int offset_extbr; int length_extbr; + int addr_ext_id; int page_ext_id; int offset_ext_id; int length_ext_id; + int addr_id; int page_id; int offset_id; int length_id; + int addr_len_sm; int page_len_sm; int offset_len_sm; int length_len_sm; + int addr_len_smf; int page_len_smf; int offset_len_smf; int length_len_smf; + int addr_len_om1; int page_len_om1; int offset_len_om1; int length_len_om1; + int addr_len_om2; int page_len_om2; int offset_len_om2; int length_len_om2; + int addr_len_om3; int page_len_om3; int offset_len_om3; int length_len_om3; + int addr_len_om4; int page_len_om4; int offset_len_om4; int length_len_om4; + int addr_option; int page_option; int offset_option; int length_option; + int addr_rate_id; int page_rate_id; int offset_rate_id; int length_rate_id; + int addr_rx_am; int page_rx_am; int offset_rx_am; int length_rx_am; + int addr_rx_em; int page_rx_em; int offset_rx_em; int length_rx_em; + int addr_rx_los; int page_rx_los; int offset_rx_los; int length_rx_los; + int addr_rx_power; int page_rx_power; int offset_rx_power; int length_rx_power; + int addr_soft_rs0; int page_soft_rs0; int offset_soft_rs0; int length_soft_rs0; + int addr_soft_rs1; int page_soft_rs1; int offset_soft_rs1; int length_soft_rs1; + int addr_temp; int page_temp; int offset_temp; int length_temp; + int addr_trancomp; int page_trancomp; int offset_trancomp; int length_trancomp; + int addr_trancomp_ext; int page_trancomp_ext; int offset_trancomp_ext; int length_trancomp_ext; + int addr_tx_bias; int page_tx_bias; int offset_tx_bias; int length_tx_bias; + int addr_tx_disable; int page_tx_disable; int offset_tx_disable; int length_tx_disable; + int addr_tx_eq; int page_tx_eq; int offset_tx_eq; int length_tx_eq; + int addr_tx_fault; int page_tx_fault; int offset_tx_fault; int length_tx_fault; + int addr_tx_power; int page_tx_power; int offset_tx_power; int length_tx_power; + int addr_vendor_name; int page_vendor_name; int offset_vendor_name; int length_vendor_name; + int addr_vendor_pn; int page_vendor_pn; int offset_vendor_pn; int length_vendor_pn; + int addr_vendor_rev; int page_vendor_rev; int offset_vendor_rev; int length_vendor_rev; + int addr_vendor_sn; int page_vendor_sn; int offset_vendor_sn; int length_vendor_sn; + int addr_voltage; int page_voltage; int offset_voltage; int length_voltage; + int addr_wavelength; int page_wavelength; int offset_wavelength; int length_wavelength; +}; + + +struct transvr_worker_s; + +/* Class of transceiver object */ +struct transvr_obj_s { + + /* ========== Object private property ========== + * [Prop]: id + * [Desc]: Type of serial transceiver. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh /QSFP28:11h + */ + uint8_t id; + + /* [Prop]: connector + * [Desc]: Connector type. + * [Note]: SFP : A0h / 2 + * QSFP: 00h / 130 + */ + uint8_t connector; + + /* [Prop]: transvr_comp + * [Desc]: Transceiver compliance code. + * [Note]: SFP: SFF-8472 + * - Normal : A0h / offset 3-10 + * - Extended: A0h / offset 36 + * QSFP: SFF-8436 & SFF-8636 + * - Normal : 00h / offset 131-138 + * - Extended: 00h / offset 192 + */ + uint8_t transvr_comp[8]; + uint8_t transvr_comp_ext; + + /* [Prop]: vendor_name + * [Desc]: SFP vendor name (ASCII 16 byte char). + * [Note]: ex:FINISAR CORP. + */ + char *vendor_name; + + /* [Prop]: vendor_pn + * [Desc]: Part number provided by SFP vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_pn; + + /* [Prop]: vendor_rev + * [Desc]: Revision level for part number provided by vendor (ASCII 4 byte char). + * [Note]: + */ + char *vendor_rev; + + /* [Prop]: vendor_sn + * [Desc]: Serial number provided by vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_sn; + + /* [Prop]: Extended identifier + * [Desc]: SFP: + * => None + * + * QSFP: + * => This byte contained two information: + * (1) Power consumption class + * (2) CDR function present + * [Note]: Bit description as below: + * [SFP] + * None + * + * [QSFP] + * (1) Power consumption class: + * Class 1: 1.5W (Bit6-7 = 00:) + * Class 2: 2.0W (Bit6-7 = 01:) + * Class 3: 2.5W (Bit6-7 = 10:) + * Class 4: 3.5W (Bit6-7 = 11:) + * Class 5: 4.0W (Bit0-1 = 01:) + * Class 6: 4.5W (Bit0-1 = 10:) + * Class 7: 5.0W (Bit0-1 = 11:) + * (2) CDR function present: + * Bit2: 0 = No CDR in RX + * 1 = CDR present in RX + * Bit3: 0 = No CDR in TX + * 1 = CDR present in TX + */ + uint8_t ext_id; + + /* [Prop]: br + * [Desc]: Nominal bit rate, units of 100 MBits/sec. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh + * has val: 0x67 + * no val : + */ + uint8_t br; + + /* [Prop]: extbr + * [Desc]: Extended br (00h/222) + * [Desc]: Nominal bit rate per channel, units of 250 Mbps. + * Complements. Byte 140. See Table 32A. + */ + uint8_t extbr; + + /* [Prop]: len_sm + * [Desc]: Length (single mode)-(100's)m + * [Note]: This value specifies the link length that is supported by the transceiver + * while operating in compliance with the applicable standards using single mode + * fiber. The value is in units of 100 meters. A value of 255 means that the + * transceiver supports a link length greater than 25.4 km. A value of zero means + * that the transceiver does not support single mode fiber or that the length + * information must be determined from the transceiver technology. + */ + int len_sm; + + /* [Prop]: len_smf + * [Desc]: Length (single mode)-km + * [Note]: Addition to EEPROM data from original GBIC definition. This value specifies + * the link length that is supported by the transceiver while operating in + * compliance with the applicable standards using single mode fiber. The value + * is in units of kilometers. A value of 255 means that the transceiver supports + * a link length greater than 254 km. A value of zero means that the transceiver + * does not support single mode fiber or that the length information must be + * determined from the transceiver technology. + */ + int len_smf; + + /* [Prop]: len_om1 + * [Desc]: Link length supported for 62.5 um OM1 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om1; + + /* [Prop]: len_om2 + * [Desc]: Link length supported for 50 um OM2 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om2; + + /* [Prop]: len_om3 + * [Desc]: Length (50um, OM3) + * [Note]: This value specifies link length that is supported by the transceiver while + * operating in compliance with applicable standards using 50 micron multimode + * OM3 [2000 MHz*km] fiber. The value is in units of 10 meters. A value of 255 + * means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber + * or that the length information must be determined from the transceiver technology. + */ + int len_om3; + + /* [Prop]: len_om4 + * [Desc]: Length (50um, OM4) and Length (Active Cable or Copper) + * [Note]: For optical links, this value specifies link length that is supported by the + * transceiver while operating in compliance with applicable standards using 50 micron + * multimode OM4 [4700 MHz*km] fiber. The value is in units of 10 meters. A value of + * 255 means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber or that + * the length information must be determined from the transceiver codes specified in Table 5-3. + * + * For copper links, this value specifies minimum link length supported by the transceiver + * while operating in compliance with applicable standards using copper cable. For active + * cable, this value represents actual length. The value is in units of 1 meter. A value of 255 + * means the transceiver supports a link length greater than 254 meters. A value of zero means + * the transceiver does not support copper or active cables or the length information must be + * determined from transceiver technology. Further information about cable design, equalization, + * and connectors is usually required to guarantee meeting a particular length requirement. + */ + int len_om4; + + /* [Prop]: comp_rev + * [Desc]: SFF spec revision compliance + * [Note]: Indicates which revision of SFF SFF-8472 (SFP) / SFF-8636 (QSFP) the transceiver + * complies with. (unsigned integer) + */ + uint8_t comp_rev; + + /* [Prop]: CDR + * [Desc]: For transceivers with CDR capability, setting the CDR to ON engages the internal + * retiming function. Setting the CDR to OFF enables an internal bypassing mode ,which + * directs traffic around the internal CDR. (Reference: SFF-8636) + * [Note]: value=0xff: ON. + * value=0x00: OFF. + */ + uint8_t cdr; + + /* [Prop]: rate_id + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Addr: A0h / Offset: 13 + * 2. Value description: + * 00h Unspecified + * 01h SFF-8079 (4/2/1G Rate_Select & AS0/AS1) + * 02h SFF-8431 (8/4/2G Rx Rate_Select only) + * 03h Unspecified * + * 04h SFF-8431 (8/4/2G Tx Rate_Select only) + * 05h Unspecified * + * 06h SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) + * 07h Unspecified * + * 08h FC-PI-5 (16/8/4G Rx Rate_select only) High=16G only, Low=8G/4G + * 09h Unspecified * + * 0Ah FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) High=16G only, + * Low=8G/4G + * 0Bh Unspecified * + * 0Ch FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + * 0Dh Unspecified * + * 0Eh 10/8G Rx and Tx Rate_Select controlling the operation or locking + * modes of the internal signal conditioner, retimer or CDR, according + * to the logic table defined in Table 10-2, High Bit Rate + * (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = 8.5 Gb/s. In this mode, + * the default value of bit 110.3 (Soft Rate Select RS(0), Table 9-11) + * and of bit 118.3 (Soft Rate Select RS(1), Table 10-1) is 1. + * 0Fh Unspecified * + * 10h-FFh Unallocated + */ + int rate_id; + + /* [Prop]: soft_rs0 + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Writing '1' selects full bandwidth operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(0) or RS(0) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 110 / Bit: 3 + */ + uint8_t soft_rs0; + + /* [Prop]: soft_rs1 + * [Desc]: Soft Rate Select 1(TX). + * [Note]: 1. Writing '1' selects full bandwidth TX operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(1) or RS(1) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 118 / Bit: 3 + */ + uint8_t soft_rs1; + + /* [Prop]: diag_type + * [Desc]: DIAGNOSTIC MONITORING TYPE (A0h/92) + * [Note]: Description in SFF-8472 as below: + * Bit7: Reserved for legacy diagnostic implementations. Must be '0' for compliance + * with this document. + * Bit6: Digital diagnostic monitoring implemented (described in this document). + * Must be '1' for compliance with this document. + * Bit5 Internally calibrated + * Bit4 Externally calibrated + * Bit3 Received power measurement type.0 = OMA, 1 = average power + * Bit2 Address change required see section above, "addressing modes" + * Bit1-0 Unallocated + */ + uint8_t diag_type; + + /* [Prop]: curr_temp + * [Desc]: Transceiver Current Temperature (A2h/96-97) + * [Note]: 1. Dependent on diag_type. + * 2. 96: High byte + * 3. 97: Low byte + * 4. This feature only for SFP + */ + uint8_t curr_temp[2]; + + /* [Prop]: curr_vol + * [Desc]: Transceiver Current Voltage (SFP:A2h/108-109; QSFP:00h/22-23) + * [Note]: 1. Dependent on diag_type. + * 2. 98: High byte + * 3. 99: Low byte + * 4. This feature only for SFP + * 5. Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts + */ + uint8_t curr_voltage[2]; + + /* [Prop]: curr_tx_bias + * [Desc]: Transceiver TX Bias Current (SFP:A2h/100-101; QSFP:00h/26-27) + * [Note]: 1. Dependent on diag_type. + * 2. 100: High byte + * 3. 101: Low byte + * 4. This feature only for SFP + * 5. Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + uint8_t curr_tx_bias[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + uint8_t curr_tx_power[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + uint8_t curr_rx_power[8]; + + /* [Prop]: wavelength + * [Desc]: Wavelength or Copper Cable Attenuation + * [Note]: (Following is info from SFF-8636) + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is a + * 16-bit hex value with Byte 186 as high order byte and Byte 187 as low + * order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. If the free side device is identified as + * copper cable these registers will be used to define the cable attenuation. + * An indication of 0 dB attenuation refers to the case where the attenuation + * is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + uint8_t wavelength[2]; + + /* [Prop]: Amplitude control + * [Desc]: Amplitude control + * [Note]: QSFP28 => SFF-8636 03H Byte-238/239 + */ + uint8_t rx_am[2]; + + /* [Prop]: Emphasis control + * [Desc]: Emphasis control + * [Note]: SFP+/28 => SFF-8472 A2H Byte-115 + * QSFP28 => SFF-8636 03H Byte-236/237 + */ + uint8_t rx_em[2]; + + /* [Prop]: Soft Rx LOS + * [Desc]: Soft Rx LOS which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 3: + * - Bit 0: L-Rx1 LOS + * - Bit 1: L-Rx2 LOS + * - Bit 2: L-Rx3 LOS + * - Bit 3: L-Rx4 LOS + */ + uint8_t rx_los; + + /* [Prop]: Soft Tx Disable + * [Desc]: Soft Tx Disable which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Disable + * - Bit 1: Tx2 Disable + * - Bit 2: Tx3 Disable + * - Bit 3: Tx4 Disable + */ + uint8_t tx_disable; + + /* [Prop]: Soft Tx Fault + * [Desc]: Soft Tx Fault which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Fault + * - Bit 1: Tx2 Fault + * - Bit 2: Tx3 Fault + * - Bit 3: Tx4 Fault + */ + uint8_t tx_fault; + + /* [Prop]: Transceiver EQUALIZATION + * [Desc]: Transceiver EQUALIZATION + * [Note]: SFP+/28 => SFF-8472 A2H Byte-114 + * QSFP28 => SFF-8636 03H Byte-234/235 + */ + uint8_t tx_eq[2]; + + /* [Prop]: OPTION VALUES + * [Desc]: The bits in the option field shall specify the options implemented in the transceiver. + * [Note]: SFP+/28 => SFF-8472 A0H Byte-64/65 + * QSFP+/28 => SFF-8636 00H Byte-193/195 + */ + uint8_t option[3]; + + /* [Prop]: External PHY offset + * [Desc]: It needs to be setup first if you want to access transceiver external phy. + * [Note]: This feature dependent on transceiver. + * Currently, only 1G-RJ45 transceiver supported it. + */ + uint8_t extphy_offset; + + /* ========== 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 transvr_worker_s *worker_p; + struct mutex lock; + char swp_name[32]; + int auto_config; + 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 public functions ========== + */ + int (*get_id)(struct transvr_obj_s *self); + int (*get_ext_id)(struct transvr_obj_s *self); + int (*get_connector)(struct transvr_obj_s *self); + int (*get_vendor_name)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_pn)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_rev)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_sn)(struct transvr_obj_s *self, char *buf_p); + int (*get_power_cls)(struct transvr_obj_s *self); + int (*get_br)(struct transvr_obj_s *self); + int (*get_len_sm)(struct transvr_obj_s *self); + int (*get_len_smf)(struct transvr_obj_s *self); + int (*get_len_om1)(struct transvr_obj_s *self); + int (*get_len_om2)(struct transvr_obj_s *self); + int (*get_len_om3)(struct transvr_obj_s *self); + int (*get_len_om4)(struct transvr_obj_s *self); + int (*get_comp_rev)(struct transvr_obj_s *self); + int (*get_comp_eth_1)(struct transvr_obj_s *self); + int (*get_comp_eth_10)(struct transvr_obj_s *self); + int (*get_comp_eth_10_40)(struct transvr_obj_s *self); + int (*get_comp_extend)(struct transvr_obj_s *self); + int (*get_cdr)(struct transvr_obj_s *self); + int (*get_rate_id)(struct transvr_obj_s *self); + int (*get_soft_rs0)(struct transvr_obj_s *self); + int (*get_soft_rs1)(struct transvr_obj_s *self); + int (*get_info)(struct transvr_obj_s *self); + int (*get_if_type)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_speed)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_lane)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_temp)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_vol)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_rx_los)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_fault)(struct transvr_obj_s *self, char *buf_p); + int (*get_auto_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_bias)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_eq)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_am)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_em)(struct transvr_obj_s *self, char *buf_p); + int (*get_wavelength)(struct transvr_obj_s *self, char *buf_p); + int (*get_extphy_offset)(struct transvr_obj_s *self, char *buf_p); + int (*get_extphy_reg)(struct transvr_obj_s *self, char *buf_p); + int (*set_cdr)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs0)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs1)(struct transvr_obj_s *self, int input_val); + int (*set_soft_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_auto_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_tx_eq)(struct transvr_obj_s *self, int input_val); + int (*set_rx_am)(struct transvr_obj_s *self, int input_val); + int (*set_rx_em)(struct transvr_obj_s *self, int input_val); + int (*set_extphy_offset)(struct transvr_obj_s *self, int input_val); + int (*set_extphy_reg)(struct transvr_obj_s *self, int input_val); + + /* ========== Object private functions ========== + */ + int (*init)(struct transvr_obj_s *self); + int (*clean)(struct transvr_obj_s *self); + int (*check)(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); + int (*fsm_4_polling)(struct transvr_obj_s* self, char *caller_name); + int (*send_uevent)(struct transvr_obj_s* self, enum kobject_action u_action); + int (*dump_all)(struct transvr_obj_s* self); +}; + + +/* For AVL Mapping */ +struct transvr_avl_s { + char vendor_name[32]; + char vendor_pn[32]; + int (*init)(struct transvr_obj_s *self); +}; + + +/* Worker for long term task of transceiver */ +struct transvr_worker_s { + /* Task Parameter */ + struct transvr_obj_s *transvr_p; + struct transvr_worker_s *next_p; + struct transvr_worker_s *pre_p; + unsigned long trigger_time; + char func_name[64]; + int retry; + int state; + + /* Task private data */ + void *p_data; + + /* Call back function */ + int (*main_task)(struct transvr_worker_s *task); + int (*post_task)(struct transvr_worker_s *task); +}; + + +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 lock_transvr_obj(struct transvr_obj_s *self); +void unlock_transvr_obj(struct transvr_obj_s *self); +int isolate_transvr_obj(struct transvr_obj_s *self); + +int resync_channel_tier_2(struct transvr_obj_s *self); + +void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg); + +#endif /* TRANSCEIVER_H */ + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/utils/inventec_d6254_util.py b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/utils/inventec_d6254_util.py new file mode 100644 index 000000000000..31cf736dafb4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/utils/inventec_d6254_util.py @@ -0,0 +1,239 @@ +#!/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 "[D6254]"+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 pca9548 0x71> /sys/bus/i2c/devices/i2c-0/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-2/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-3/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-4/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-5/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-6/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-7/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-8/new_device', +'echo inv_eeprom 0x53 > /sys/bus/i2c/devices/i2c-0/new_device'] +#'echo inv_psoc 0x66> /sys/bus/i2c/devices/i2c-0/new_device', +#'echo inv_cpld 0x55> /sys/bus/i2c/devices/i2c-0/new_device'] + +drivers =[ +'gpio_ich', +'lpc_ich', +'i2c-i801', +'i2c-mux', +'i2c-mux-pca954x', +'i2c-dev', +'inv_eeprom', +'inv_platform', +'inv_psoc', +'inv_cpld', +'swps', +'inv_pthread'] + + + +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(10,18): + 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(18,26): + 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 + for i in range(26,34): + 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(34,42): + 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(42,50): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-6/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(50,58): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-7/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(58,64): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-8/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 " D6254 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/d6556/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/Makefile new file mode 100644 index 000000000000..c13abd37e129 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/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 +obj-m += inv_pthread.o +swps-objs := inv_swps.o inv_mux.o io_expander.o transceiver.o diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_cpld.c new file mode 100644 index 000000000000..5ee4b26cdab9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_cpld.c @@ -0,0 +1,526 @@ +/* + * 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 +#define CPLD_BIOSCS_OFFSET 0x04 +#define CPLD_PSUFANLED_OFFSET 0x75 + +/* 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 ssize_t show_bios_cs(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_BIOSCS_OFFSET, 1); + + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld BIOS_CS fail\n"); + + + status = sprintf (buf, "0x%X\n", b[0] & 0x01); + + return strlen(buf); +} + +static ssize_t set_bios_cs(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_BIOSCS_OFFSET, 1); + if(temp) byte |= 0x01; + else byte &= ~(0x01); + cpld_i2c_write(client, &byte, CPLD_BIOSCS_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 + "4 Hz", //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; + + 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 char* status_psufan_str[] = { + "OFF", //00 + "ON", //01 + "1 Hz", //10 + "2 Hz", //11 +}; + +static ssize_t show_psufan_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 red_status, grn_status, byte; + int shift = (attr->index == 0)?0:2; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_PSUFANLED_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte>>shift) & 0x33; + grn_status = byte >> 4; + red_status = byte & 0x03; + + return sprintf (buf, "0x%02x: Green %s , Red %s\n", byte, status_psufan_str[grn_status],status_psufan_str[red_status]); +} + +static ssize_t set_psufan_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int shift = (attr->index == 0)?0:2; + int mask = (attr->index == 0)?0xcc:0x33; + u8 temp = simple_strtol(buf, NULL, 16) & 0x33; + u8 byte = 0; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_PSUFANLED_OFFSET, 1); + byte &= mask; + byte |= (temp<update_lock); + + return count; +} + + +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 SENSOR_DEVICE_ATTR(fan_led, S_IWUSR|S_IRUGO, show_psufan_led, set_psufan_led, 0); +static SENSOR_DEVICE_ATTR(psu_led, S_IWUSR|S_IRUGO, show_psufan_led, set_psufan_led, 1); + +static SENSOR_DEVICE_ATTR(bios_cs, S_IWUSR|S_IRUGO, show_bios_cs, set_bios_cs, 0); + +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, + + &sensor_dev_attr_fan_led.dev_attr.attr, + &sensor_dev_attr_psu_led.dev_attr.attr, + + &sensor_dev_attr_bios_cs.dev_attr.attr, + + NULL +}; + +static const struct attribute_group cpld_group = { + .attrs = cpld_attributes, +}; + +static struct attribute *cpld2_attributes[] = { + //info + &sensor_dev_attr_info.dev_attr.attr, + + NULL +}; + +static const struct attribute_group cpld2_group = { + .attrs = cpld2_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 */ + if(id->driver_data==1) // CPLD2 + status = sysfs_create_group(&client->dev.kobj, &cpld2_group); + else // default CPLD1 + 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, }, + { "inv_cpld2", 1, }, + { /* 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/d6556/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_eeprom.c new file mode 100644 index 000000000000..7bb167d2e74e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/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 D6556 Mother Board EEPROM driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_mux.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_mux.c new file mode 100644 index 000000000000..a303527bec46 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_mux.c @@ -0,0 +1,281 @@ +/* + * 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 "io_expander.h" +#include "inv_mux.h" + +static struct mux_obj_s *mux_head_p = NULL; + + +/* ========== MUX object functions ========== + */ +int +_common_force_pull_gpio(int mem_addr, + int input, + int bit_offset){ + + unsigned int val = 0; + unsigned int targ = 0; + + /* Get current value */ + val = inl(mem_addr); + if (val == 0) { + SWPS_ERR("%s: inl:%d fail!\n", __func__, val); + return -1; + } + /* Count target value */ + switch (input) { + case 0: /* Pull Low */ + targ = (val & (~(1 << bit_offset))); + break; + case 1: /* Pull high */ + targ = (val | (1 << bit_offset)); + break; + default: + SWPS_ERR("%s: input state:%d incorrect!\n", + __func__, input); + return -1; + } + /* Setup gpio */ + outl(targ, mem_addr); + if (targ != inl(mem_addr)){ + SWPS_ERR("%s: outl:%d fail!\n", __func__, targ); + return -1; + } + SWPS_DEBUG("%s: done.\n", __func__); + return 0; +} + + +int +rangeley_force_pull_high(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +rangeley_force_pull_low(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +hedera_force_pull_high(struct mux_obj_s *self){ + return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 1, 5); +} + + +int +hedera_force_pull_low(struct mux_obj_s *self){ + return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 0, 5); +} + + +int +normal_gpio_pull_high(struct mux_obj_s *self){ + return gpio_direction_output(self->gpio_num, 1); +} + + +int +normal_gpio_pull_low(struct mux_obj_s *self){ + return gpio_direction_output(self->gpio_num, 0); +} + + +int +pca9548_reset_mux_all(struct mux_obj_s *self){ + /* [Note] Power-on reset (PCA9548A-NXP) + * When power is applied to VDD, an internal Power-On Reset (POR) + * holds the PCA9548A in a reset condition until VDD has reached + * VPOR. At this point, the reset condition is released and the + * PCA9548A register and I2C-bus state machine are initialized to + * their default states (all zeroes) causing all the channels to + * be deselected. Thereafter, VDD must be lowered below 0.2 V for + * at least 5 us in order to reset the device. + */ + if (self->_pull_low(self) < 0) { + SWPS_ERR("%s: _pull_low fail!\n", __func__); + return -1; + } + mdelay(MUX_RST_WAIT_MS); + if (self->_pull_high(self) < 0) { + SWPS_ERR("%s: _pull_high fail!\n", __func__); + return -1; + } + mdelay(MUX_RST_WAIT_MS); + return 0; +} + + +int +common_reset_mux_all(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +init_gpio_4_force(struct mux_obj_s *self){ + return 0; +} + + +int +init_gpio_4_normal(struct mux_obj_s *self){ + + int err = 0; + + if (!gpio_is_valid(self->gpio_num)) { + SWPS_ERR("%s: GIPO:%d isn't valid\n", __func__, self->gpio_num); + return -1; + } + err = gpio_request(self->gpio_num, MUX_GPIO_LABEL); + if (err < 0) { + SWPS_ERR("%s: gpio_request fail :%d :%d\n", + __func__, err, self->gpio_num); + return -1; + } + SWPS_DEBUG("%s: gpio_request:%d ok.\n", __func__, self->gpio_num); + return 0; +} + + +static int +_setup_muxctl_cb(struct mux_obj_s *self, + unsigned gpio){ + + char mod_dsc[32] = "ERR"; + + switch (gpio) { + case MUX_RST_GPIO_FORCE_RANGELEY: + self->gpio_num = gpio; + self->_pull_low = rangeley_force_pull_low; + self->_pull_high = rangeley_force_pull_high; + self->_init = init_gpio_4_force; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Rangeley force mode"); + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_FORCE_HEDERA: + self->gpio_num = gpio; + self->_pull_low = hedera_force_pull_low; + self->_pull_high = hedera_force_pull_high; + self->_init = init_gpio_4_force; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Hedera force mode"); + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_48_PAC9548: + case MUX_RST_GPIO_69_PAC9548: + case MUX_RST_GPIO_249_PCA9548: + case MUX_RST_GPIO_500_PAC9548: + case MUX_RST_GPIO_505_PCA9548: + self->gpio_num = gpio; + self->_pull_low = normal_gpio_pull_low; + self->_pull_high = normal_gpio_pull_high; + self->_init = init_gpio_4_normal; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Normal mode :%d", (int)gpio); + goto ok_setup_muxctl_cb; + + default: + break; + } + SWPS_ERR("%s: Unexpected GPIO:%d\n", __func__, gpio); + return -1; + +ok_setup_muxctl_cb: + SWPS_INFO("muxctl: %s.\n", mod_dsc); + return 0; +} + + +/* ========== MUX public functions ========== + */ +void +clean_mux_gpio(void){ + + if (!mux_head_p) { + SWPS_DEBUG("%s: mux_head_p is NULL\n", __func__); + return; + } + if (gpio_is_valid(mux_head_p->gpio_num)) { + gpio_free(mux_head_p->gpio_num); + } + kfree(mux_head_p); + mux_head_p = NULL; + SWPS_DEBUG("%s: done.\n", __func__); +} + + +int +reset_mux_gpio(void){ + + if (!mux_head_p) { + SWPS_ERR("%s: MUX ctl object doesn't exist!\n", __func__); + return -1; + } + if (mux_head_p->reset(mux_head_p) < 0){ + SWPS_ERR("%s: reset fail!\n", __func__); + return -1; + } + return 0; +} + + +int +init_mux_gpio(unsigned gpio){ + + /* Create MUX control object */ + if (mux_head_p) { + SWPS_DEBUG("%s: mux_head_p is not NULL!\n", __func__); + clean_mux_gpio(); + } + /* Currently, it is using single muxctl architecture. + * In the future, it may use the multi-muxctl if HW add new features. + * (Ex: Port power-status control) + */ + mux_head_p = kzalloc(sizeof(struct mux_obj_s), GFP_KERNEL); + if (!mux_head_p) { + SWPS_ERR("%s: kzalloc fail!\n", __func__); + return -1; + } + /* Initial MUX controller */ + if (_setup_muxctl_cb(mux_head_p, gpio) < 0){ + SWPS_ERR("%s: _setup_muxctl_cb fail!\n", __func__); + return -1; + } + if (mux_head_p->_init(mux_head_p) < 0) { + SWPS_ERR("%s: init() fail\n", __func__); + goto err_init_mux_gpio; + } + /* Setup default value */ + if (mux_head_p->_pull_high(mux_head_p) < 0) { + SWPS_ERR("%s: setup default fail!\n", __func__); + goto err_init_mux_gpio; + } + return 0; + +err_init_mux_gpio: + clean_mux_gpio(); + return -1; +} + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_mux.h b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_mux.h new file mode 100644 index 000000000000..f981a304644a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_mux.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#ifndef INV_MUX_H +#define INV_MUX_H + + +/* MUX basic information */ +#define MUX_GPIO_LABEL "SWPS_RST_MUX" + +/* MUX reset GPIO define */ +#define MUX_RST_GPIO_FORCE (30100) +#define MUX_RST_GPIO_FORCE_RANGELEY (30101) +#define MUX_RST_GPIO_FORCE_HEDERA (30102) +#define MUX_RST_GPIO_48_PAC9548 (48) +#define MUX_RST_GPIO_69_PAC9548 (69) +#define MUX_RST_GPIO_249_PCA9548 (249) +#define MUX_RST_GPIO_500_PAC9548 (500) +#define MUX_RST_GPIO_505_PCA9548 (505) + +/* MUX relate value define */ +#define MUX_RST_WAIT_MS (1) +#define MUX_RST_MEM_ADDR_RANGELEY (0) // TBD +#define MUX_RST_MEM_ADDR_HEDERA (0x548) + +struct mux_obj_s { + unsigned gpio_num; + int (*_pull_high)(struct mux_obj_s *self); + int (*_pull_low)(struct mux_obj_s *self); + int (*_init)(struct mux_obj_s *self); + int (*reset)(struct mux_obj_s *self); +}; + + +void clean_mux_gpio(void); +int reset_mux_gpio(void); +int init_mux_gpio(unsigned gpio); + + +#endif /* INV_MUX_H */ + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_platform.c new file mode 100644 index 000000000000..26bd47300dab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_platform.c @@ -0,0 +1,215 @@ +/* + * 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 + +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 = { + {"pca9548", 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 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[] = { + {bus_id(1), ARRAY_SIZE(i2c_device_info0), i2c_device_info0 }, //mux root + + {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 +}; + +///////////////////////////////////////////////////////////////////////////////////////// +static struct i2c_gpio_platform_data i2c_gpio_platdata0 = { + .scl_pin = 238, + .sda_pin = 255, + + .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 = 1, // adapter number + .dev.platform_data = &i2c_gpio_platdata0, +}; + +static int __init inv_platform_init(void) +{ + struct i2c_adapter *adap = NULL; + struct i2c_client *e = NULL; + int ret = 0; + int i,j,k; + + //use i2c-gpio + //register i2c gpio + //config gpio58,75 to gpio function 58=32+3*8+2 75=32*2+8*1+3 gpio69=32*2+8*0+5 + outl( inl(0x533) | (1<<2), 0x533); + outl( inl(0x541) | (1<<3), 0x541); + outl( inl(0x540) | (1<<5), 0x540); //RST_I2C_MUX_N (GPIO69) + outl( inl(0x500) | (1<<7), 0x500); //SYS_RDY_N (GPIO7) + outl( inl(0x501) | (1<<7), 0x501); //BMC_HEART_BEAT (GPIO15) + outl( inl(0x503) | (1<<2)|(1<<3), 0x503); //PSOC_HEART_BEAT(26),CPLD_HEART_BEAT(27) + + + ret = platform_device_register(&device_i2c_gpio0); + if (ret) { + printk(KERN_ERR "i2c-gpio: device_i2c_gpio0 register fail %d\n", ret); + } + mdelay(500); //wait for device_i2c_gpio register successfully + + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define SWITCH_TEMPERATURE_SOCK "/proc/switch/temp" +#define PSOC_POLLING_PERIOD 1000 + +#include +#include +#include +#include + +#define IPMI_MAX_INTF (4) +#define NETFN_OEM 0x30 +#define CMD_GETDATA 0x31 +#define CMD_SETDATA 0x32 +#define FAN_NUM 4 +#define PSU_NUM 2 + +#define FAN_CLEI_SUPPORT 1 +#define PSU_CLEI_SUPPORT 0 + +#define PSU1 0x5800 +#define PSU2 0x5900 +#define BMC_PMBusNumber 3 +#define PMBus_Vendor 0x99 +#define PMBus_Serial 0x9E +#define PMBus_Temp2 0x8E +#define PMBus_Version 0x9B +#define MaxLeng_Result 0x40 + +#define BMC_FanCLEIBusNumber 9 +#define DEVICE_CLEI_ADDR 0x52,0x53,0x54,0x55,0x56,0x50,0x51 + +#define MAX_IPMI_RECV_LENGTH 0xff +static char CLEI_ADDR[]={DEVICE_CLEI_ADDR}; +struct task_struct *kthread_auto_update; +static long pmbus_reg2data_linear(int data, int linear16); +struct ipmi_result{ + char result[MAX_IPMI_RECV_LENGTH]; + int result_length; +}; + +DEFINE_MUTEX(ipmi_mutex); +DEFINE_MUTEX(ipmi2_mutex); +static struct ipmi_result ipmiresult; +static struct device *hwmon_dev; +static struct kobject *device_kobj; +static ipmi_user_t ipmi_mh_user = NULL; +static void msg_handler(struct ipmi_recv_msg *msg,void* handler_data); +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 +}; + +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__)) clei { + u8 issue_number[3]; + u8 abbreviation_number[9]; + u8 fc_number[10]; + u8 clei_code[10]; + u8 product_year_and_month[5]; + u8 label_location_code[2]; + u8 serial_number[5]; + u8 pcb_revision[5]; + u8 vendor_name[10]; + u8 reserved[5]; +}; + +struct __attribute__ ((__packed__)) psoc_layout { + u8 ctl; //offset: 0 + u16 switch_temp; //offset: 1 + + // BYTE[03:20] - voltage + u16 voltage[15]; //offset: 0x03-0x20 + + // BYTE[21:27] - ExtFan + u8 led_ctl2; //offset: 21 + u8 ext_pwm; //offset: 22 + u16 ext_rpm[2]; //offset: 23 + u8 gpi_fan2; //offset: 27 + + //gpo + u8 led_ctl; //offset: 28 + + u8 gpio; //offset: 29 + + //pwm duty + u8 pwm[4]; //offset: 2a + u8 pwm_psu[2]; //offset: 2e + + //fan rpm + u16 fan[4*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[2]; //offset: 50 + + //version + u8 version[2]; //offset: 54 + + u8 reserve2[4]; //offset: 56 + struct psoc_psu_layout psu_info; //offset: 5a +}; + +/* 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) + +#define PWM2_OFFSET PSOC_OFF(ext_pwm) +#define RPM2_OFFSET PSOC_OFF(ext_rpm) +#define FAN_LED2_OFFSET PSOC_OFF(led_ctl2) +#define FAN_GPI2_OFFSET PSOC_OFF(gpi_fan2) + +#define CLEI_OFF(m) offsetof(struct clei, m) +#define FAN1_CLEI_INDEX 0 +#define FAN2_CLEI_INDEX 1 +#define FAN3_CLEI_INDEX 2 +#define FAN4_CLEI_INDEX 3 +#define FAN5_CLEI_INDEX 4 +#define PSU1_CLEI_INDEX 5 +#define PSU2_CLEI_INDEX 6 + +static void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data) +{ + struct ipmi_result *msg_result = recv_msg->user_msg_data; + + if(recv_msg->msg.data[0]==0 && recv_msg->msg.data_len>0) { + msg_result->result_length=recv_msg->msg.data_len-1; + memcpy(msg_result->result, &recv_msg->msg.data[1], recv_msg->msg.data_len-1); + } + ipmi_free_recv_msg(recv_msg); + mutex_unlock(&ipmi_mutex); + + return; +} + +int start_ipmi_command(char NetFn, char cmd,char *data,int data_length, char* result, int* result_length) +{ + int rv=0,i; + int timeout; + + //wait previous command finish at least 50msec + timeout=50; + while((mutex_is_locked(&ipmi_mutex) == 1 || (mutex_is_locked(&ipmi2_mutex) == 1)) && (--timeout)>0) { usleep_range(1000,1010); } + if(timeout==0) { return -1; } + mutex_lock(&ipmi_mutex); + mutex_lock(&ipmi2_mutex); + + if(ipmi_mh_user == NULL) { + for (i=0,rv=1; i0) { usleep_range(1000,1100);} + if(timeout==0) { + mutex_unlock(&ipmi2_mutex); + return -1; + } + else { + *result_length=ipmiresult.result_length; + memcpy(result,ipmiresult.result,*result_length); + mutex_unlock(&ipmi2_mutex); + return 0; + } + } + return 0; +} +EXPORT_SYMBOL(start_ipmi_command); + +static ssize_t psoc_ipmi_read(u8 *buf, u8 offset, size_t count) +{ + uint8_t data[2]; + int result_len=0; + int rv; + + data[0] = offset; + data[1] = count; + + rv=start_ipmi_command(NETFN_OEM, CMD_GETDATA,data,2, buf, &result_len); + + return result_len; +} + +static ssize_t psoc_ipmi_write(char *buf, unsigned offset, size_t count) +{ + uint8_t data[count+1],result[1]; + int result_len; + + data[0] = offset; + memcpy(&data[1],buf,count); + + start_ipmi_command(NETFN_OEM, CMD_SETDATA,data,count+1, result, &result_len); + return count; +} + + +static u16 psoc_read16(u8 offset) +{ + u16 value = 0; + u8 buf[]={0,0}; + + if(psoc_ipmi_read(buf, offset, 2) == 2) + value = (buf[0]<<8 | buf[1]<<0); + + return value; +} + +static u8 psoc_read8(u8 offset) +{ + u8 value = 0; + u8 buf = 0; + + if(psoc_ipmi_read(&buf, offset, 1) == 1) + value = buf; + + return value; +} + +/* +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=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 byte=0; + int shift = (attr->index == 0)?3:0; + + status = psoc_ipmi_read(&byte, PSOC_PSU_OFFSET, 1); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + +static ssize_t show_ipmi_pmbus(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=0; + + data[0] = BMC_PMBusNumber; + 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(start_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_clei(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 device_index = attr->index & 0xFF; + + uint8_t data[5],result[MaxLeng_Result]; + int result_len=0; + + data[0] = (device_index<=FAN5_CLEI_INDEX) ? BMC_FanCLEIBusNumber:BMC_PMBusNumber; + data[1] = CLEI_ADDR[device_index]<<1; + data[2] = sizeof(struct clei); + data[3] = (device_index<=FAN5_CLEI_INDEX) ? 0x00 : 0x01; //PSU CLEI will start from 0x0100 + data[4] = 0; + + if(start_ipmi_command(0x06, 0x52,data,5, result, &result_len)==0) + { + if(result_len < sizeof(struct clei)) memset(result, 0, sizeof(struct clei)); + sprintf (buf, "Issue Number: %.3s\n", &result[CLEI_OFF(issue_number)]); + sprintf (buf, "%sAbbreviation Number: %.9s\n", buf, &result[CLEI_OFF(abbreviation_number)]); + sprintf (buf, "%sFC Number: %.10s\n", buf, &result[CLEI_OFF(fc_number)]); + sprintf (buf, "%sCLEI Code: %.10s\n", buf, &result[CLEI_OFF(clei_code)]); + sprintf (buf, "%sProduct Year and Month: %.5s\n", buf, &result[CLEI_OFF(product_year_and_month)]); + sprintf (buf, "%s2D Label Location Code: %.2s\n", buf, &result[CLEI_OFF(label_location_code)]); + sprintf (buf, "%sSerial Number: %.5s\n", buf, &result[CLEI_OFF(serial_number)]); + sprintf (buf, "%sPCB Revision: %.5s\n", buf, &result[CLEI_OFF(pcb_revision)]); + sprintf (buf, "%sVendor Name: %.10s\n", buf, &result[CLEI_OFF(vendor_name)]); + return strlen(buf); + } + else + { + return sprintf(buf, "NONE\n"); + } +} + +static ssize_t show_thermal(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index * 2 + THERMAL_OFFSET; + + status = psoc_read16(offset); + + 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=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index; + + status = psoc_read8(offset); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t set_pwm(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index; + u8 pwm = simple_strtol(buf, NULL, 10); + if(pwm > 255) pwm = 255; + psoc_ipmi_write(&pwm, offset, 1); + + return count; +} + + +static ssize_t show_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index; + status = psoc_read16(offset); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t show_switch_tmp(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + u16 temp = 0; + + status = psoc_ipmi_read((u8*)&temp, SWITCH_TMP_OFFSET, 2); + + 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) +{ + long temp = simple_strtol(buf, NULL, 10); + u16 temp2 = ( (temp/1000) <<8 ) & 0xFF00 ; + + psoc_ipmi_write((u8*)&temp2, SWITCH_TMP_OFFSET, 2); + + + return count; +} + +static ssize_t show_diag(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + u8 diag_flag = 0; + + status = psoc_ipmi_read((u8*)&diag_flag, DIAG_FLAG_OFFSET, 1); + + status = sprintf (buf, "%d\n", ((diag_flag & 0x80)?1:0)); + + return strlen(buf); +} + +static ssize_t set_diag(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + u8 value = 0; + u8 diag = simple_strtol(buf, NULL, 10); + + diag = diag?1:0; + + psoc_ipmi_read((u8*)&value, DIAG_FLAG_OFFSET, 1); + if(diag) value |= (1<<7); + else value &= ~(1<<7); + psoc_ipmi_write((u8*)&value, DIAG_FLAG_OFFSET, 1); + + return count; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + + status = psoc_read16(VERSION_OFFSET); + + 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=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 bit = attr->index; + + if(bit < 8) { status = psoc_read8(FAN_LED_OFFSET); } +#if FAN_NUM>4 + if(bit >= 8) { status = psoc_read8(FAN_LED2_OFFSET); bit-=8; } +#endif + + return sprintf(buf, "%d\n", + (status & (1<index; + u8 led_state = 0; + + u8 v = simple_strtol(buf, NULL, 10); + + if(attr->index < 8) { led_state = psoc_read8(FAN_LED_OFFSET ); } +#if FAN_NUM>4 + if(attr->index >= 8) { led_state = psoc_read8(FAN_LED2_OFFSET); bit-=8; } +#endif + if(v) led_state |= (1<index < 8) { psoc_ipmi_write(&led_state, FAN_LED_OFFSET, 1);} +#if FAN_NUM>4 + if(attr->index >= 8) { psoc_ipmi_write(&led_state, FAN_LED2_OFFSET,1);} +#endif + return count; +} + +static ssize_t show_value8(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index; + + status = psoc_read8(offset); + + 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=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index + PSU_INFO_OFFSET; + + status = psoc_read16(offset); + + if((strstr(attr->dev_attr.attr.name, "vout")!=NULL)|(strstr(attr->dev_attr.attr.name, "in3")!=NULL)|(strstr(attr->dev_attr.attr.name, "in4")!=NULL)) { + offset=1; + } + else { + offset=0; + } + + return sprintf(buf, "%ld \n", pmbus_reg2data_linear(status, offset )); +} + +static ssize_t show_name(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return sprintf(buf, "inv_psoc\n"); +} + +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); +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(temp7_input, S_IRUGO, show_thermal, 0, 5); +static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_thermal, 0, 6); + +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0 + PWM_OFFSET); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 1 + PWM_OFFSET); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 2 + PWM_OFFSET); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 3 + PWM_OFFSET); +#if FAN_NUM > 4 +static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0 + PWM2_OFFSET); +#endif +static SENSOR_DEVICE_ATTR(pwm_psu1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4 + PWM_OFFSET); +static SENSOR_DEVICE_ATTR(pwm_psu2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5 + PWM_OFFSET); +static SENSOR_DEVICE_ATTR(pwm6, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4 + PWM_OFFSET); +static SENSOR_DEVICE_ATTR(pwm7, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5 + PWM_OFFSET); + +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu_st, 0, 0); +static SENSOR_DEVICE_ATTR(psu2, S_IRUGO, show_psu_st, 0, 1); + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, 0, 0*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(rpm_psu1, S_IRUGO, show_rpm, 0, 8*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(rpm_psu2, S_IRUGO, show_rpm, 0, 9*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, show_rpm, 0, 8*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan12_input, S_IRUGO, show_rpm, 0, 9*2 + RPM_OFFSET); + +#if FAN_NUM > 4 +static SENSOR_DEVICE_ATTR(fan9_input , S_IRUGO, show_rpm, 0,0*2 + RPM2_OFFSET); +static SENSOR_DEVICE_ATTR(fan10_input, S_IRUGO, show_rpm, 0,1*2 + RPM2_OFFSET); +#endif + +static SENSOR_DEVICE_ATTR(switch_tmp, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0); +static SENSOR_DEVICE_ATTR(temp6_input, 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); + +#if FAN_NUM>4 +static SENSOR_DEVICE_ATTR(fan_led_grn5, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 8); +static SENSOR_DEVICE_ATTR(fan_led_red5, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 12); +static SENSOR_DEVICE_ATTR(fan_gpi2, S_IRUGO, show_value8, 0, FAN_GPI2_OFFSET); +#endif + +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(in1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vout)); +static SENSOR_DEVICE_ATTR(curr3_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iout)); +static SENSOR_DEVICE_ATTR(power3_input, 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)); + +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin)); +static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vout)); +static SENSOR_DEVICE_ATTR(curr4_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iout)); +static SENSOR_DEVICE_ATTR(power4_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pout)); + +//IPMI +static SENSOR_DEVICE_ATTR(thermal2_psu1, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Temp2); +static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Temp2); + +static SENSOR_DEVICE_ATTR(psoc_psu1_vendor, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Vendor); +static SENSOR_DEVICE_ATTR(psoc_psu1_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Serial); +static SENSOR_DEVICE_ATTR(psoc_psu1_version, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Version); + +static SENSOR_DEVICE_ATTR(thermal2_psu2, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Temp2); +static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Temp2); +static SENSOR_DEVICE_ATTR(psoc_psu2_vendor, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Vendor); +static SENSOR_DEVICE_ATTR(psoc_psu2_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Serial); +static SENSOR_DEVICE_ATTR(psoc_psu2_version, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Version); + +//CLEI +#if FAN_CLEI_SUPPORT +static SENSOR_DEVICE_ATTR(fan1_clei, S_IRUGO, show_clei, 0, FAN1_CLEI_INDEX ); +static SENSOR_DEVICE_ATTR(fan2_clei, S_IRUGO, show_clei, 0, FAN2_CLEI_INDEX ); +static SENSOR_DEVICE_ATTR(fan3_clei, S_IRUGO, show_clei, 0, FAN3_CLEI_INDEX ); +static SENSOR_DEVICE_ATTR(fan4_clei, S_IRUGO, show_clei, 0, FAN4_CLEI_INDEX ); +#if FAN_NUM > 4 +static SENSOR_DEVICE_ATTR(fan5_clei, S_IRUGO, show_clei, 0, FAN5_CLEI_INDEX ); +#endif +#endif + +#if PSU_CLEI_SUPPORT +static SENSOR_DEVICE_ATTR(psu1_clei, S_IRUGO, show_clei, 0, PSU1_CLEI_INDEX ); +static SENSOR_DEVICE_ATTR(psu2_clei, S_IRUGO, show_clei, 0, PSU2_CLEI_INDEX ); +#endif + +static struct attribute *psoc_attributes[] = { + //name + &dev_attr_name.attr, + //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, + + &sensor_dev_attr_temp7_input.dev_attr.attr, + &sensor_dev_attr_temp8_input.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, +#if FAN_NUM > 4 + &sensor_dev_attr_pwm5.dev_attr.attr, +#endif + &sensor_dev_attr_pwm_psu1.dev_attr.attr, + &sensor_dev_attr_pwm_psu2.dev_attr.attr, + &sensor_dev_attr_pwm6.dev_attr.attr, + &sensor_dev_attr_pwm7.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, +#if FAN_NUM > 4 + &sensor_dev_attr_fan9_input.dev_attr.attr, + &sensor_dev_attr_fan10_input.dev_attr.attr, +#endif + &sensor_dev_attr_rpm_psu1.dev_attr.attr, + &sensor_dev_attr_rpm_psu2.dev_attr.attr, + &sensor_dev_attr_fan11_input.dev_attr.attr, + &sensor_dev_attr_fan12_input.dev_attr.attr, + //switch temperature + &sensor_dev_attr_switch_tmp.dev_attr.attr, + &sensor_dev_attr_temp6_input.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, +#if FAN_NUM >4 + &sensor_dev_attr_fan_led_grn5.dev_attr.attr, + &sensor_dev_attr_fan_led_red5.dev_attr.attr, + &sensor_dev_attr_fan_gpi2.dev_attr.attr, +#endif + //fan GPI + &sensor_dev_attr_fan_gpi.dev_attr.attr, + &sensor_dev_attr_psu1.dev_attr.attr, + &sensor_dev_attr_psu2.dev_attr.attr, + + + //psu_psoc + &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, + + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_curr3_input.dev_attr.attr, + &sensor_dev_attr_power3_input.dev_attr.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_curr4_input.dev_attr.attr, + &sensor_dev_attr_power4_input.dev_attr.attr, + + //ipmi_i2c_command + &sensor_dev_attr_thermal2_psu1.dev_attr.attr, + &sensor_dev_attr_temp9_input.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_vendor.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_temp10_input.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vendor.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_serial.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_version.dev_attr.attr, + + //clei +#if FAN_CLEI_SUPPORT + &sensor_dev_attr_fan1_clei.dev_attr.attr, + &sensor_dev_attr_fan2_clei.dev_attr.attr, + &sensor_dev_attr_fan3_clei.dev_attr.attr, + &sensor_dev_attr_fan4_clei.dev_attr.attr, +#if FAN_NUM > 4 + &sensor_dev_attr_fan5_clei.dev_attr.attr, +#endif +#endif + +#if PSU_CLEI_SUPPORT + &sensor_dev_attr_psu1_clei.dev_attr.attr, + &sensor_dev_attr_psu2_clei.dev_attr.attr, +#endif + NULL +}; + +static const struct attribute_group psoc_group = { + .attrs = psoc_attributes, +}; + +//================================= +static void check_switch_temp(void) +{ + static struct file *f; + mm_segment_t old_fs; + + set_fs(get_ds()); + f = filp_open(SWITCH_TEMPERATURE_SOCK,O_RDONLY,0644); + if(IS_ERR(f)) { + return; + } + else { + char temp_str[]={0,0,0,0,0,0,0}; + loff_t pos = 0; + u16 temp2 = 0; + old_fs = get_fs(); + set_fs(KERNEL_DS); + vfs_read(f, temp_str,6,&pos); + temp2 = ((simple_strtoul(temp_str,NULL,10)/1000) <<8 ) & 0xFF00 ; + psoc_ipmi_write((u8*)&temp2, SWITCH_TMP_OFFSET, 2); + } + filp_close(f,NULL); + set_fs(old_fs); +} + +static int psoc_polling_thread(void *p) +{ + while (!kthread_should_stop()) + { + check_switch_temp(); + set_current_state(TASK_INTERRUPTIBLE); + if(kthread_should_stop()) + break; + + schedule_timeout(msecs_to_jiffies(PSOC_POLLING_PERIOD)); + } + return 0; +} + +static int __init inv_psoc_init(void) +{ + int ret; + + hwmon_dev = hwmon_device_register(NULL); + if (IS_ERR(hwmon_dev)) { + goto fail_hwmon_device_register; + } + + device_kobj = kobject_create_and_add("device", &hwmon_dev->kobj); + if(!device_kobj) { + goto fail_hwmon_device_register; + } + + ret = sysfs_create_group(device_kobj, &psoc_group); + if (ret) { + goto fail_create_group_hwmon; + } + + ret = sysfs_create_group(&hwmon_dev->kobj, &psoc_group); + if (ret) { + goto fail_create_group_hwmon; + } + + kthread_auto_update = kthread_run(psoc_polling_thread,NULL,"BMC_DRIVER"); + if (IS_ERR(kthread_auto_update)) { + goto fail_create_group_hwmon; + } + return ret; + +fail_create_group_hwmon: + hwmon_device_unregister(hwmon_dev); +fail_hwmon_device_register: + return -ENOMEM; +} + +static void __exit inv_psoc_exit(void) +{ + kthread_stop(kthread_auto_update); + if(ipmi_mh_user!=NULL) {ipmi_destroy_user(ipmi_mh_user);} + if(hwmon_dev != NULL) hwmon_device_unregister(hwmon_dev); + sysfs_remove_group(device_kobj, &psoc_group); +} + +MODULE_AUTHOR("Ting.Jack "); +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/d6556/modules/inv_pthread.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_pthread.c new file mode 100644 index 000000000000..e3b180cd5eab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_pthread.c @@ -0,0 +1,1459 @@ +/* + * 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. + */ + +/***************************** + Maple platform +******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SHOW_ATTR_WARNING ("N/A") +#define SHOW_ATTR_NOTPRINT ("Not Available") +#define SHOW_ATTR_NOTSUPPORT ("Not Support") + +#define INV_HWMID_MAX (10) +#define INV_HWMID_INIT (-1) + +/*access userspace data to kernel space*/ +#define ACC_R (0) +#define ACC_W (1) + +#define TINY_BUF_SIZE (8) +#define MAX_PATH_SIZE (64) +#define MIN_ACC_SIZE (32) +#define MAX_ACC_SIZE (256) + +/* + * LED definitions + */ +#define STATUS_LED_MODE_AUTO 0 +#define STATUS_LED_MODE_DIAG 1 +#define STATUS_LED_MODE_MANU 2 + +#define STATUS_LED_GRN0 10 // 0 - 000: off +#define STATUS_LED_GRN1 11 // 1 - 001: 0.5hz +#define STATUS_LED_GRN2 12 // 2 - 010: 1 hz +#define STATUS_LED_GRN3 13 // 3 - 011: 2 hz +#define STATUS_LED_GRN7 17 // 7 - 111: on +#define STATUS_LED_RED0 20 // 0 - 000: off +#define STATUS_LED_RED1 21 // 1 - 001: 0.5hz +#define STATUS_LED_RED2 22 // 2 - 010: 1 hz +#define STATUS_LED_RED3 23 // 3 - 011: 2 hz +#define STATUS_LED_RED7 27 // 7 - 111: on +#define STATUS_LED_INVALID 0 // Invalid + +ssize_t status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2); +ssize_t status_led_grn(const char *freq); +ssize_t status_led_red(const char *freq); +ssize_t status_led_diag_mode_enable(void); +ssize_t status_led_diag_mode_disable(void); +int status_led_check_color(void); +int status_led_check_diag_mode(void); + +int status_led_psu_control(void); +ssize_t status_fan_led(const char *freq); +ssize_t status_psu_led(const char *freq); + +#if 1 +/* For timestamps in SYSFS_LOG */ +#define SYSFS_LOG printk +#else +//#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[SYSFS] %s/%d: " fmt, __func__, __LINE__, ##args) +#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[p_thread] " fmt, ##args) +#endif + +#define INV_PTHREAD_KERNEL_MODULE (1) + +/* inventec_class *********************************/ +static struct kobject *status_kobj; +static struct kset *status_kset; + + +static struct mutex rw_lock; + +static int hwm_psoc = INV_HWMID_INIT; +static int hwm_cpld = INV_HWMID_INIT; + +int get_hwm_psoc(void) +{ + return hwm_psoc; +} + +int get_hwm_cpld(void) +{ + return hwm_cpld; +} + +static ssize_t access_user_space(const char *name, int mode, char *buf, size_t len, loff_t offset) +{ + struct file *fp; + mm_segment_t fs; + loff_t pos = offset; + char *mark = NULL; + ssize_t vfs_ret = 0; + + if (mode == ACC_R) { + fp = filp_open(name, O_RDONLY, S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_read(fp, buf, len, &pos); + + mark = strpbrk(buf, "\n"); + if (mark) + *mark = '\0'; + + filp_close(fp, NULL); + set_fs(fs); + } else if (mode == ACC_W) { + fp = filp_open(name, O_WRONLY, S_IWUSR | S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_write(fp, buf, len, &pos); + filp_close(fp, NULL); + set_fs(fs); + } + + return vfs_ret; +} + +int inventec_strtol(const char *sbufp, char **endp, unsigned int base) +{ + char *endptr; + int value = simple_strtol(sbufp, &endptr, base); + if (value == 0 && sbufp == endptr) { + *endp = NULL; + return value; + } + *endp = (char*)1; + return value; +} + +int inventec_singlechar_to_int(const char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } + else + if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } + else + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } + return -1; +} + +int inventec_store_input(char *inputp, int count) +{ + int i = 0; + while(inputp[i] != '\n' && inputp[i] != '\0' && i < count) { + i++; + } + inputp[i] = '\0'; + return strlen(inputp); +} + +#if 0 +/* + * Time stamps for kernel log on yocto + */ +#include + +void SYSFS_LOG(char *fmt, ...) +{ + char buf[80], ts[32]; + va_list args; + int hlen; + + inventec_tmstmp(&ts[0]); + hlen = sprintf(buf, "[SYSFS] %s ", ts); // Do not edit this line + + va_start(args, fmt); + vsprintf(&buf[hlen-1], fmt, args); + va_end(args); + printk(KERN_WARNING "[p_thread] %s\n", buf); +} +#endif + +ssize_t +inventec_show_attr(char *buf_p, const char *invdevp) +{ + int inv_len = MAX_ACC_SIZE; /* INV driver return max length */ + char tmp_buf[MAX_ACC_SIZE]; + char *str_negative = "-", *mark = NULL; + + /* [Step2] Get data by uaccess */ + memset(tmp_buf, 0, sizeof(tmp_buf)); + mutex_lock(&rw_lock); + if (access_user_space(invdevp, ACC_R, tmp_buf, inv_len, 0) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + mutex_unlock(&rw_lock); + + /* [Step3] Check return value + * - Ex: When transceiver not plugged + * => SWPS return error code "-202" + * => Pic8 need return "NA" (assume) + */ + if (strcspn(tmp_buf, str_negative) == 0) { + /* error case: "-202" */ + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + + /* OK case:*/ + mark = strpbrk(tmp_buf, "\n"); + if (mark) { *mark = '\0'; } + + return sprintf(buf_p, "%s\n", tmp_buf); +} + +ssize_t +inventec_store_attr(const char *buf_p, size_t count, const char *invdevp) +{ + ssize_t ret = 0; + + /* [Step2] Get data by uaccess */ + mutex_lock(&rw_lock); + if ((ret = access_user_space(invdevp, ACC_W, (char*)buf_p, count, 0)) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return -EINVAL; + } + mutex_unlock(&rw_lock); + + /* OK case:*/ + return ret; +} + +int sysfs_detect_hwmon_index(void) +{ + char hwmon_buf[MAX_ACC_SIZE]; + char hwmon_path[MAX_PATH_SIZE]; + char hwmon_dev_path[MAX_PATH_SIZE]; + int hwid = 0; + + for (hwid = 0; + hwid < INV_HWMID_MAX && (hwm_psoc == INV_HWMID_INIT || hwm_cpld == INV_HWMID_INIT); + hwid++) { + memset(hwmon_buf, 0, sizeof(hwmon_buf)); + sprintf(hwmon_path, "/sys/class/hwmon/hwmon%d/name", hwid); + + inventec_show_attr(hwmon_buf, hwmon_path); + if (strncmp(hwmon_buf, "inv_psoc", 8) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_bmc", 7) == 0) { + hwm_psoc = hwid; + } + + sprintf(hwmon_dev_path, "/sys/class/hwmon/hwmon%d/device/name", hwid); + inventec_show_attr(hwmon_buf, hwmon_dev_path); + if (strncmp(hwmon_buf, "inv_cpld", 8) == 0) { + hwm_cpld = hwid; + } + } + if (hwid >= INV_HWMID_MAX) { + printk(KERN_ERR "[p_thread] detect hwmon index failed, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return -1; + } + printk(KERN_INFO "[p_thread] detect hwmon index success, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return 0; +} + +static int __init +inventec_class_init(void) +{ + mutex_init(&rw_lock); + +#ifdef INV_PTHREAD_KERNEL_MODULE + if (sysfs_detect_hwmon_index() < 0) { + return -1; + } +#endif + + printk(KERN_INFO "[p_thread] [%s/%d] Module initial success.\n",__func__,__LINE__); + + return 0; +} + +static void __exit +inventec_class_exit(void) +{ + printk(KERN_INFO "[p_thread] [%s/%d] Remove module.\n",__func__,__LINE__); +} + +/* fan device *************************************/ +#define FAN_DEV_PATH_STATE "/sys/class/hwmon/hwmon%d/device/fan_gpi" +#define FAN_DEV_PATH_FAN1_INPUT "/sys/class/hwmon/hwmon%d/device/fan1_input" +#define FAN_DEV_PATH_FAN2_INPUT "/sys/class/hwmon/hwmon%d/device/fan2_input" +#define FAN_DEV_PATH_FAN3_INPUT "/sys/class/hwmon/hwmon%d/device/fan3_input" +#define FAN_DEV_PATH_FAN4_INPUT "/sys/class/hwmon/hwmon%d/device/fan4_input" +#define FAN_DEV_PATH_FAN5_INPUT "/sys/class/hwmon/hwmon%d/device/fan5_input" +#define FAN_DEV_PATH_FAN6_INPUT "/sys/class/hwmon/hwmon%d/device/fan6_input" +#define FAN_DEV_PATH_FAN7_INPUT "/sys/class/hwmon/hwmon%d/device/fan7_input" +#define FAN_DEV_PATH_FAN8_INPUT "/sys/class/hwmon/hwmon%d/device/fan8_input" + +static char fan_dev_path_state[MAX_PATH_SIZE]; +static char fan_dev_path_fan1_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan2_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan3_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan4_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan5_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan6_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan7_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan8_input[MAX_PATH_SIZE]; + +void sysfs_fan_path_init(void) +{ + sprintf(&fan_dev_path_state[0], FAN_DEV_PATH_STATE, get_hwm_psoc()); + sprintf(&fan_dev_path_fan1_input[0],FAN_DEV_PATH_FAN1_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan2_input[0],FAN_DEV_PATH_FAN2_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan3_input[0],FAN_DEV_PATH_FAN3_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan4_input[0],FAN_DEV_PATH_FAN4_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan5_input[0],FAN_DEV_PATH_FAN5_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan6_input[0],FAN_DEV_PATH_FAN6_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan7_input[0],FAN_DEV_PATH_FAN7_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan8_input[0],FAN_DEV_PATH_FAN8_INPUT, get_hwm_psoc()); +} + +#define FAN_STATE_NORMAL "normal" +#define FAN_STATE_FAULTY "faulty" +#define FAN_STATE_UNINSTALLED "uninstalled" +#define FAN_STATE_UNKNOW "unknown state" +#define FAN_STATE_INVALID "Invalid state value" +#define FAN_STATE_READ_ERROR "state read error" + +#define FAN_LOG_UNINSTALLED "removed" +#define FAN_LOG_NORMAL "inserted" + +//#define FAN_STATE_BIT_NORMAL 0 +#define FAN_STATE_BIT_FAULTY 0 +#define FAN_STATE_BIT_UNINSTALLED 1 +#define FAN_STATE_BIT_UNKNOW 2 +#define FAN_STATE_BIT_INVALID 3 +#define FAN_STATE_BIT_READ_ERROR 4 + +static struct fans_tbl_s { + char *fan_name; + char *fan_front; + char *fan_rear; + unsigned int fan_state; +} fans_tbl[] = { + {"fan1", fan_dev_path_fan1_input, + fan_dev_path_fan2_input, 0}, + {"fan2", fan_dev_path_fan3_input, + fan_dev_path_fan4_input, 0}, + {"fan3", fan_dev_path_fan5_input, + fan_dev_path_fan6_input, 0}, + {"fan4", fan_dev_path_fan7_input, + fan_dev_path_fan8_input, 0}, +}; +#define FAN_TBL_TOTAL ( sizeof(fans_tbl)/ sizeof(const struct fans_tbl_s) ) + +#define FAN_STATE_CHECK(i,b) (fans_tbl[i].fan_state & (1< 0) + { + printk(KERN_ERR "[p_thread] All fans failed.\n"); + printk(KERN_ERR "[p_thread] System shutdown immediately in %d seconds.\n", cd_shutdown); + } + cd_shutdown -= 1; + } + return ret; +} + +/* End of faninfo_device */ + +static int __init +fan_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_fan_path_init(); +#endif + return 0; +} + + +static void __exit +fan_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove fan module.\n"); +} + +/* psu device *************************************/ +static unsigned int psu_voltin = 0; +#define PSU_VOLTIN_ACDC (70000) + +/* + * normal/unpower/uninstall/fault are PSU states output from driver level + * checkpsu/error are defined by sysfs + */ +#define PSU_STATE_VAL_NORMAL (0) +#define PSU_STATE_VAL_UNPOWER (2) +#define PSU_STATE_VAL_FAULT (4) +#define PSU_STATE_VAL_UNINSTALL (7) +#define PSU_STATE_VAL_CHECKPSU (8) +#define PSU_STATE_VAL_ERROR (9) + +#define PSU_STATE_NORMAL ("0 : normal") +#define PSU_STATE_UNPOWER ("2 : unnormal") +#define PSU_STATE_FAULT ("4 : fault") +#define PSU_STATE_UNINSTALL ("7 : not installed") +#define PSU_STATE_CHECKPSU ("8 : check psu") +#define PSU_STATE_ERROR ("9 : state error") + +#define PSU_STATE_LEN_NORMAL (strlen(PSU_STATE_NORMAL)) +#define PSU_STATE_LEN_UNPOWER (strlen(PSU_STATE_UNPOWER)) +#define PSU_STATE_LEN_FAULT (strlen(PSU_STATE_FAULT)) +#define PSU_STATE_LEN_UNINSTALL (strlen(PSU_STATE_UNINSTALL)) +#define PSU_STATE_LEN_CHECKPSU (strlen(PSU_STATE_CHECKPSU)) + +typedef struct { + char *inv_dev_attrp; + char *inv_dev_pathp; +} psu_dev_t; + +typedef struct { + const char *psu_name; + int psu_major; + dev_t psu_devt; + struct device *psu_dev_p; + psu_dev_t *psu_dev_namep; + int psu_dev_total; + char *psu_inv_pathp; + void *psu_tracking; + char *psu_currentin; + char *psu_currentout; + char *psu_powerin; + char *psu_powerout; + char *psu_voltin; + char *psu_voltout; +} psu_dev_group_t; + +#define PSU_DEV_PATH_TEMPLATE "/sys/class/hwmon/hwmon%d/device/%s" + +static char psu_dev_path_state[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltin[MAX_PATH_SIZE]; + +static char psu_0_dev_path_state[MAX_PATH_SIZE]; +static char psu_1_dev_path_state[MAX_PATH_SIZE]; + +#if 0 +static char psu_dev_path_vendor[MAX_PATH_SIZE]; +static char psu_dev_path_version[MAX_PATH_SIZE]; +static char psu_dev_path_sn[MAX_PATH_SIZE]; +static char psu_dev_path_temperature[MAX_PATH_SIZE]; +static char psu_dev_path_fan_speed[MAX_PATH_SIZE]; +static char psu_dev_path_fan_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_fan_faulty[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_psu_rpm[MAX_PATH_SIZE]; +#endif + +void sysfs_psu_path_init(void) +{ + sprintf(&psu_dev_path_state[0], PSU_DEV_PATH_TEMPLATE, get_hwm_cpld(), "\%s" ); + sprintf(&psu_dev_path_psu_voltin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + + sprintf(&psu_0_dev_path_state[0], PSU_DEV_PATH_TEMPLATE, get_hwm_cpld(), "psu0" ); + sprintf(&psu_1_dev_path_state[0], PSU_DEV_PATH_TEMPLATE, get_hwm_cpld(), "psu1" ); + +#if 0 + sprintf(&psu_dev_path_vendor[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_version[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_sn[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_temperature[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_speed[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_faulty[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_voltout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_rpm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#endif +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +#if 0 + { "vendor", psu_dev_path_vendor }, + { "version", psu_dev_path_version }, + { "sn", psu_dev_path_sn }, + { "temperature", psu_dev_path_temperature }, + { "fan_speed", psu_dev_path_fan_speed }, + { "fan_pwm", psu_dev_path_fan_pwm }, + { "fan_faulty", psu_dev_path_fan_faulty }, + { "psu_currentin", psu_dev_path_psu_currentin }, + { "psu_currentout", psu_dev_path_psu_currentout }, + { "psu_powerin", psu_dev_path_psu_powerin }, + { "psu_powerout", psu_dev_path_psu_powerout }, + { "psu_voltout", psu_dev_path_psu_voltout }, + { "psu_pwm", psu_dev_path_psu_pwm }, + { "psu_rpm", psu_dev_path_psu_rpm }, +#endif +}; +#define PSU_DEV_NAME_TOTAL ( sizeof(psu_dev_name) / sizeof(const psu_dev_t) ) + +static psu_dev_group_t psu_dev_group[] = { + { + .psu_name = "psu1", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, + { + .psu_name = "psu2", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, +}; +#define PSU_DEV_GROUP_TOTAL ( sizeof(psu_dev_group)/ sizeof(const psu_dev_group_t) ) + +static char psu_state[4][MIN_ACC_SIZE]; + +static struct psu_wire_tbl_s { + char *psu_attr; + char *psu_name; + char *psu_wire; + char *psu_state; +} psu_wire_tbl[] = { + { "state", "psu1", "psu0", psu_state[0] }, // Using cpld + { "state", "psu2", "psu1", psu_state[1] }, + { "psu_voltin", "psu1", "psoc_psu1_vin", psu_state[2] }, + { "psu_voltin", "psu2", "psoc_psu2_vin", psu_state[3] }, +}; +#define PSU_WIRE_TBL_TOTAL ( sizeof(psu_wire_tbl)/ sizeof(const struct psu_wire_tbl_s) ) + +static char * +psu_attr_get_wirep(const char *psu_attrp, const char *psu_namep, char **psu_statepp) +{ + int i; + + for (i = 0; i < PSU_WIRE_TBL_TOTAL; i++) { + if (strncmp(psu_wire_tbl[i].psu_attr, psu_attrp, strlen(psu_attrp)) == 0 && + strncmp(psu_wire_tbl[i].psu_name, psu_namep, strlen(psu_namep)) == 0) { + if (psu_statepp) { + *psu_statepp = psu_wire_tbl[i].psu_state; + } + return psu_wire_tbl[i].psu_wire; + } + } + return NULL; +} + +int psu_check_state_normal(char *statep) +{ + if (strstr(statep, "normal")) { + return 1; + } + return 0; +} + +#define PSU_ATTR_VOLTIN ("psu_voltin") +#define PSU_ATTR_VOLTIN_LEN (10) + +/* Get PSU voltin for determon AC(110v) or DC(48v) */ +void psu_get_voltin(void) +{ + char acc_path[MAX_PATH_SIZE], volt[MIN_ACC_SIZE]; + psu_dev_t *devnamep; + unsigned int voltin; + char *invwirep; + int i, j; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + //psu_dev_group[i].psu_name; + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_VOLTIN, PSU_ATTR_VOLTIN_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_VOLTIN, psu_dev_group[i].psu_name, NULL); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_DEBUG "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(volt, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + continue; + } + else { + voltin = simple_strtol(&volt[0], NULL, 10); + printk(KERN_DEBUG "[p_thread] Read %s %s = %u\n",acc_path,volt,voltin); + if (voltin > psu_voltin) { + psu_voltin = voltin; + } + } + } + } + } + + SYSFS_LOG("[p_thread] PSU voltin = %u\n", psu_voltin); +} + +#define PSU_ATTR_STATE ("state") +#define PSU_ATTR_STATE_LEN (5) + +/* psus_control() by inv_thread */ +int psus_control(int log_only) +{ + char acc_path[MAX_PATH_SIZE], state[MIN_ACC_SIZE]; + psu_dev_t *devnamep = NULL; + char *invwirep = NULL; + char *psu_statep = NULL; + int i, j, flag = 0; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_STATE, PSU_ATTR_STATE_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_STATE, psu_dev_group[i].psu_name, &psu_statep); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_INFO "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(state, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + if (strncmp(psu_statep, PSU_STATE_ERROR, strlen(PSU_STATE_ERROR)) != 0) { + strcpy(psu_statep, PSU_STATE_ERROR); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_ERROR); + } + flag = 1; + } + else + if (strstr(state, "normal")) { + //printk(KERN_INFO "[p_thread] %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + } + else + if (psu_voltin > PSU_VOLTIN_ACDC) { /* AC PSUS */ + //printk(KERN_INFO "[p_thread] RYU: %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + flag = 1; + } + else { /* DC PSUS */ + if (strncmp(psu_statep, PSU_STATE_CHECKPSU, PSU_STATE_LEN_CHECKPSU) != 0) { + strcpy(psu_statep, PSU_STATE_CHECKPSU); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_CHECKPSU); + } + flag = 1; + } + } + } + } + + if (log_only) { + return 0; + } + + //SYSFS_LOG("[p_thread] RYU: %s: flag = %d\n",psu_wire_tbl[i].psu_name,flag); + if (flag == 1) { + status_psu_led("0x20"); + return 1; + } + return 0; +} + +int status_led_psu_control(void) +{ + int retVal = 0; //no issue + + char buf[MAX_ACC_SIZE]; + + int normal_psu_cnt = 0; //normal + + int fault_psu_cnt = 0; + + //read fan status one by one + //read psu 0 status + if (inventec_show_attr(&buf[0], psu_0_dev_path_state) > 0) + { + if(buf[0] == '0') //normal + { + normal_psu_cnt = normal_psu_cnt + 1; + } + else if (buf[0] == '4') // psu fault + { + fault_psu_cnt = fault_psu_cnt + 1; + } + + //Check 2nd psu + if(inventec_show_attr(&buf[0], psu_1_dev_path_state) > 0) + { + if(buf[0] == '0') //normal + { + normal_psu_cnt = normal_psu_cnt + 1; + } + else if (buf[0] == '4') // psu fault + { + fault_psu_cnt = fault_psu_cnt + 1; + } + } + } + + if (normal_psu_cnt == 0) + { + status_psu_led("0"); + retVal = 1; + } + else + { + if( fault_psu_cnt > 0) + { + status_psu_led("0x01"); //Red lit + retVal = 1; + } + else if (normal_psu_cnt == 1) + { + status_psu_led("0x20"); // Green blink + retVal = 1; + } + else if (normal_psu_cnt == 2) + { + status_psu_led("0x10"); // Green Lit + retVal = 0; + } + } + + return retVal; +} + + +/* End of psuinfo_device */ + +static int __init +psu_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_psu_path_init(); +#endif + return 0; +} + + +static void __exit +psu_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove psu module.\n"); +} + +/* led device *************************************/ +#define STATUS_LED_GRN_PATH "/sys/class/hwmon/hwmon%d/device/grn_led" +#define STATUS_LED_RED_PATH "/sys/class/hwmon/hwmon%d/device/red_led" + +#define STATUS_LED_FAN_PATH "/sys/class/hwmon/hwmon%d/device/fan_led" +#define STATUS_LED_PSU_PATH "/sys/class/hwmon/hwmon%d/device/psu_led" + +#define FAN_LED_GRN1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn1" +#define FAN_LED_GRN2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn2" +#define FAN_LED_GRN3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn3" +#define FAN_LED_GRN4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn4" +#define FAN_LED_RED1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red1" +#define FAN_LED_RED2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red2" +#define FAN_LED_RED3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red3" +#define FAN_LED_RED4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red4" + +#define HWMON_DEVICE_DIAG_PATH "/sys/class/hwmon/hwmon%d/device/diag" +#define HWMON_DEVICE_CTRL_PATH "/sys/class/hwmon/hwmon%d/device/ctl" + +static char status_led_grn_path[MAX_PATH_SIZE]; +static char status_led_red_path[MAX_PATH_SIZE]; +static char status_led_fan_path[MAX_PATH_SIZE]; +static char status_led_psu_path[MAX_PATH_SIZE]; + +static char fan_led_grn1_path[MAX_PATH_SIZE]; +static char fan_led_grn2_path[MAX_PATH_SIZE]; +static char fan_led_grn3_path[MAX_PATH_SIZE]; +static char fan_led_grn4_path[MAX_PATH_SIZE]; +static char fan_led_red1_path[MAX_PATH_SIZE]; +static char fan_led_red2_path[MAX_PATH_SIZE]; +static char fan_led_red3_path[MAX_PATH_SIZE]; +static char fan_led_red4_path[MAX_PATH_SIZE]; +static char hwmon_device_diag_path[MAX_PATH_SIZE]; +static char hwmon_device_ctrl_path[MAX_PATH_SIZE]; + +void sysfs_led_path_init(void) +{ + sprintf(&status_led_grn_path[0], STATUS_LED_GRN_PATH, get_hwm_cpld()); + sprintf(&status_led_red_path[0], STATUS_LED_RED_PATH, get_hwm_cpld()); + sprintf(&status_led_fan_path[0], STATUS_LED_FAN_PATH, get_hwm_cpld()); + sprintf(&status_led_psu_path[0], STATUS_LED_PSU_PATH, get_hwm_cpld()); + + sprintf(&fan_led_grn1_path[0], FAN_LED_GRN1_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn2_path[0], FAN_LED_GRN2_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn3_path[0], FAN_LED_GRN3_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn4_path[0], FAN_LED_GRN4_PATH, get_hwm_psoc()); + sprintf(&fan_led_red1_path[0], FAN_LED_RED1_PATH, get_hwm_psoc()); + sprintf(&fan_led_red2_path[0], FAN_LED_RED2_PATH, get_hwm_psoc()); + sprintf(&fan_led_red3_path[0], FAN_LED_RED3_PATH, get_hwm_psoc()); + sprintf(&fan_led_red4_path[0], FAN_LED_RED4_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_diag_path[0], HWMON_DEVICE_DIAG_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_ctrl_path[0], HWMON_DEVICE_CTRL_PATH, get_hwm_cpld()); +} + +/* return 0/off 1/green 2/red */ +int +status_led_check_color(void) +{ + char tmpbuf[MIN_ACC_SIZE]; + int ret = STATUS_LED_INVALID; + + if (inventec_show_attr(&tmpbuf[0], status_led_grn_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_GRN0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_GRN1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_GRN2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_GRN3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_GRN7; + } + return ret; + } + + if (inventec_show_attr(&tmpbuf[0], status_led_red_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_RED0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_RED1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_RED2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_RED3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_RED7; + } + return ret; + } + return ret; +} + +/* + * Store attr Section + */ +static DEFINE_MUTEX(diag_mutex); + +ssize_t status_led_diag_mode_enable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '0') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("1", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + mutex_unlock(&diag_mutex); + } + + return ret; +} + +ssize_t status_led_diag_mode_disable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '1') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("0", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + mutex_unlock(&diag_mutex); + } + return 1; +} + +ssize_t +status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2) +{ + ssize_t ret; + + ret = inventec_store_attr(tmp1, strlen(tmp1), path1); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(tmp2, strlen(tmp2), path2); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_red(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_grn_path[0]); + + if (ret < 0) { + return ret; + } + + ret = inventec_store_attr(freq, strlen(freq), &status_led_red_path[0]); + + if (ret < 0) { + return ret; + } + + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_grn(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +static int status_led_diag_mode = STATUS_LED_MODE_AUTO; + +int status_led_check_diag_mode(void) +{ + return status_led_diag_mode; +} + +//status led: FAN & PSU +ssize_t +status_fan_led(const char *freq) +{ + ssize_t ret; + ret = inventec_store_attr(freq, strlen(freq), &status_led_fan_path[0]); + if (ret < 0) { + return ret; + } + + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_psu_led(const char *freq) +{ + ssize_t ret; + ret = inventec_store_attr(freq, strlen(freq), &status_led_psu_path[0]); + if (ret < 0) { + return ret; + } + + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +/* End of ledinfo_device */ + +static int __init +led_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); +#endif + return 0; +} + + +static void __exit +led_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove led module.\n"); +} + +/* sensor device **********************************/ +#define SENSOR_DEV_PATH_SWITCH_TEMP "/sys/class/hwmon/hwmon%d/device/switch_tmp" + +static char sensor_dev_path_switch_temp[MAX_PATH_SIZE]; + +void sysfs_sensor_path_init(void) +{ + sprintf(&sensor_dev_path_switch_temp[0], SENSOR_DEV_PATH_SWITCH_TEMP, get_hwm_psoc()); +} + +void switch_temp_update(void) +{ + char buf[MIN_ACC_SIZE]; + ssize_t count = inventec_show_attr(&buf[0], "proc/switch/temp"); + if (count > 0) { + //printk(KERN_ERR "[p_thread] [STEMP] Switch temperature is out of range: %d\n", stemp); + inventec_store_attr(&buf[0], count, sensor_dev_path_switch_temp); + } +} + +/**************************************************/ +/* From system_device */ +static int inv_pthread_control = 1; + +int thread_control(void) +{ + return inv_pthread_control; +} + +void thread_control_set(int val) +{ + inv_pthread_control = val; +} +/* End system_device */ + +#define THREAD_SLEEP_MINS (3) +#define THREAD_DELAY_MINS (THREAD_SLEEP_MINS + THREAD_SLEEP_MINS + 1) + +extern void psu_get_voltin(void); + +static struct task_struct *thread_st; +static int thread_data; + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO +void led_set_gpio_to_change_status_led(void) +{ + ssize_t ret = inventec_store_attr("253", 2, "/sys/class/gpio/export"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 253 to /sys/class/gpio/export failed\n"); + return; + } + + printk("[p_thread] Write 253 to /sys/class/gpio/export\n"); + + ret = inventec_store_attr("out", 3, "/sys/class/gpio/gpio253/direction"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write low to /sys/class/gpio/gpio253/direction failed\n"); + return; + } + + //pull high and then low + ret = inventec_store_attr("1", 1, "sys/class/gpio/gpio253/value"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 1 to sys/class/gpio/gpio253/value failed\n"); + } + + //pull low + ret = inventec_store_attr("0", 1, "sys/class/gpio/gpio253/value"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 0 to sys/class/gpio/gpio253/value failed\n"); + } + + SYSFS_LOG("[p_thread] Set gpio to support status led change successfully\n"); +} +#endif + +// Function executed by kernel thread +static int thread_fn(void *unused) +{ + bool fan_issue = false; + bool psu_issue = false; + bool psu_number_issue = false; + + /* Delay for guarantee HW ready */ + ssleep(THREAD_DELAY_MINS); + +#ifndef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); + sysfs_fan_path_init(); + sysfs_psu_path_init(); +#endif + //sysfs_sensor_path_init(); + + /* Default status init */ + status_led_grn("7"); + + psu_get_voltin(); + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO + led_set_gpio_to_change_status_led(); +#endif + + while (1) + { + ssleep(THREAD_SLEEP_MINS); + + if (thread_control() == 0) { + printk(KERN_INFO "[p_thread] %s/%d: Thread Stop by inv_pthread control\n",__func__,__LINE__); + break; + } + + if (status_led_check_diag_mode() == STATUS_LED_MODE_MANU) { + /* status led in change color/freq mode, higher priority. Ignore fans sttaus */ + continue; + } + + //switch_temp_update(); + + if (fans_control() > 0) //has at least one failed fan + { + psus_control(0); //now we have separate led for FAN and PSU + fan_issue = true; + } + + if (psus_control(1) > 0) + { + psu_issue = true; + } + + if (status_led_psu_control() > 0) + { + psu_number_issue = true; + } + + if(fan_issue || psu_issue || psu_number_issue) + { + continue; + } + + if (status_led_check_color() != STATUS_LED_GRN7) { /* status led red, change it to green */ + status_led_grn("7"); + } + } + +#ifndef INV_PTHREAD_KERNEL_MODULE +err_inv_pthread_fn_1: +#endif + do_exit(0); + printk(KERN_INFO "[p_thread] %s/%d: Thread Stopped\n",__func__,__LINE__); + return 0; +} + + +static ssize_t s_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + int fan_absence; + size_t count; + + fan_absence = fans_control(); + count += sprintf(&buf[count], "%d\n", fan_absence); + return count; +} + +static ssize_t s_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) +{ + return count; +} + +static struct attribute status_att = { + .name = "fan_absence", + .mode = 0777, +}; + +static const struct sysfs_ops status_ops = { + .show = s_show, + .store = s_store, +}; + +static struct kobj_type status_ktype = { + .sysfs_ops = &status_ops, +}; + + +static int __init inv_pthread_init(void) +{ + int retval; + + status_kobj = kzalloc(sizeof(*status_kobj), GFP_KERNEL); + if(!status_kobj) + return PTR_ERR(status_kobj); + + status_kset = kset_create_and_add("platform_status", NULL, kernel_kobj); + if(!status_kset) + return -1; + + status_kobj->kset = status_kset; + + retval = kobject_init_and_add(status_kobj, &status_ktype, NULL, "fan"); + if(retval) + return retval; + + retval = sysfs_create_file(status_kobj, &status_att); + + + inventec_class_init(); + fan_device_init(); + psu_device_init(); + led_device_init(); + + thread_control_set(1); + + printk(KERN_INFO "[p_thread] %s/%d: Creating Thread\n",__func__,__LINE__); + //Create the kernel thread with name 'inv_pthread' + thread_st = kthread_run(thread_fn, (void*)&thread_data, "inv_pthread"); + if (thread_st) + printk(KERN_INFO "[p_thread] inv_pthread Created successfully\n"); + else + printk(KERN_ERR "[p_thread] inv_pthread creation failed\n"); + + return retval; +} + +static void __exit inv_pthread_exit(void) +{ + thread_control_set(0); + /* Delay for guarantee thread exit */ + ssleep(THREAD_DELAY_MINS); + + fan_device_exit(); + psu_device_exit(); + led_device_exit(); + inventec_class_exit(); + + sysfs_remove_file(status_kobj, &status_att); + kset_unregister(status_kset); + kobject_del(status_kobj); + + printk(KERN_INFO "[p_thread] inv_pthread cleaning Up\n"); +} + +module_init(inv_pthread_init); +module_exit(inv_pthread_exit); + +MODULE_AUTHOR("Robert "); +MODULE_DESCRIPTION("Inventec Platform Management Thread"); +MODULE_VERSION("version 1.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_swps.c new file mode 100644 index 000000000000..cbb22fba2979 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_swps.c @@ -0,0 +1,3049 @@ +/* + * 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 +#include +#include "inv_swps.h" + +static int ctl_major; +static int port_major; +static int ioexp_total; +static int port_total; +static int auto_config; +static int flag_i2c_reset; +static int flag_mod_state; +static unsigned gpio_rest_mux; +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 void swp_polling_worker(struct work_struct *work); +static DECLARE_DELAYED_WORK(swp_polling, swp_polling_worker); + +static int reset_i2c_topology(void); + + +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, + __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; +} + + +static int +_get_polling_period(void) { + + int retval = 0; + + if (SWP_POLLING_PERIOD == 0) { + return 0; + } + retval = ((SWP_POLLING_PERIOD * HZ) / 1000); + if (retval == 0) { + return 1; + } + return retval; +} + + +static struct transvr_obj_s * +_get_transvr_obj(char *dev_name) { + + struct device *dev_p = NULL; + struct transvr_obj_s *transvr_obj_p = NULL; + + dev_p = get_swpdev_by_name(dev_name); + if (!dev_p){ + return NULL; + } + transvr_obj_p = dev_get_drvdata(dev_p); + if (!transvr_obj_p){ + return NULL; + } + return transvr_obj_p; +} + + +static void +unlock_tobj_all(void) { + + struct transvr_obj_s *tobj_p; + char port_name[32]; + int port_id = 0; + int minor_curr = 0; + + for (minor_curr=0; minor_currauto_config = auto_config; + unlock_transvr_obj(tobj_p); + SWPS_DEBUG("%s: Set %s auto_config=%d\n", + __func__, tobj_p->swp_name, auto_config); + } + return retval; +} + + +/* ========== R/W Functions module control attribute ========== + */ +static ssize_t +show_attr_platform(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 32, "%s\n", platform_p->name); +} + + +static ssize_t +show_attr_version(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%s\n", SWP_VERSION); +} + + +static ssize_t +show_attr_status(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", flag_mod_state); +} + + +static ssize_t +show_attr_auto_config(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", auto_config); +} + + +static int +_check_reset_pwd(const char *buf_p, + size_t count) { + + int in_max = 64; + int in_len = (int)count; + char in_val[64] = "ERR"; + char *emsg = "ERR"; + + if (in_len >= in_max) { + emsg = "input too much"; + goto err_check_reset_pwd; + } + if (!sscanf(buf_p,"%s",in_val)) { + emsg = "format incorrect"; + goto err_check_reset_pwd; + } + if (strcmp(in_val, SWP_RESET_PWD) != 0) { + emsg = "password incorrect"; + goto err_check_reset_pwd; + } + return 0; + +err_check_reset_pwd: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} + + +static ssize_t +store_attr_reset_i2c(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + if (_check_reset_pwd(buf_p, count) < 0) { + return -EBFONT; + } + /* Polling mode */ + if (SWP_POLLING_ENABLE) { + SWPS_INFO("%s: reset I2C :polling\n", __func__); + flag_i2c_reset = 1; + return count; + } + /* Direct mode */ + SWPS_INFO("%s: reset I2C go. :direct\n", __func__); + if (reset_i2c_topology() < 0) { + SWPS_ERR("%s: reset fail!\n", __func__); + return -EIO; + } + SWPS_INFO("%s: reset I2C ok. :direct\n", __func__); + return count; +} + + +static ssize_t +store_attr_reset_swps(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p; + char port_name[32] = "ERR"; + int port_id = 0; + int minor_curr = 0; + + if (_check_reset_pwd(buf_p, count) < 0) { + return -EBFONT; + } + for (minor_curr=0; minor_currstate = STATE_TRANSVR_DISCONNECTED; + unlock_transvr_obj(tobj_p); + SWPS_INFO("%s: reset:%s\n", __func__, tobj_p->swp_name); + } + return count; +} + + +static ssize_t +store_attr_auto_config(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + int input_val = sscanf_2_int(buf_p); + + if (input_val < 0){ + return -EBFONT; + } + if ((input_val != 0) && (input_val != 1)) { + return -EBFONT; + } + auto_config = input_val; + _update_auto_config_2_trnasvr(); + return count; +} + + +/* ========== Show functions: For transceiver attribute ========== + */ +static ssize_t +_show_transvr_hex_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p), + char *buf_p) { + size_t len; + int result; + + lock_transvr_obj(tobj_p); + result = get_func(tobj_p); + unlock_transvr_obj(tobj_p); + if (result < 0){ + len = snprintf(buf_p, 8, "%d\n", result); + } else { + len = snprintf(buf_p, 8, "0x%02x\n", result); + } + return len; +} + + +static ssize_t +_show_transvr_int_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p), + char *buf_p) { + size_t len; + + lock_transvr_obj(tobj_p); + len = snprintf(buf_p, 16, "%d\n", get_func(tobj_p)); + unlock_transvr_obj(tobj_p); + return len; +} + + +static ssize_t +_show_transvr_str_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p, char* buf), + char *buf_p) { + size_t len; + + lock_transvr_obj(tobj_p); + len = get_func(tobj_p, buf_p); + unlock_transvr_obj(tobj_p); + return len; +} + + +static ssize_t +show_attr_id(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_transvr_hex_attr(tobj_p, + tobj_p->get_id, + buf_p); +} + + +static ssize_t +show_attr_ext_id(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_transvr_hex_attr(tobj_p, + tobj_p->get_ext_id, + buf_p); +} + + +static ssize_t +show_attr_connector(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_transvr_hex_attr(tobj_p, + tobj_p->get_connector, + buf_p); +} + + +static ssize_t +show_attr_vendor_name(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_transvr_str_attr(tobj_p, + tobj_p->get_vendor_name, + buf_p); +} + + +static ssize_t +show_attr_vendor_pn(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_transvr_str_attr(tobj_p, + tobj_p->get_vendor_pn, + buf_p); +} + + +static ssize_t +show_attr_vendor_rev(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_transvr_str_attr(tobj_p, + tobj_p->get_vendor_rev, + buf_p); +} + + +static ssize_t +show_attr_vendor_sn(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_transvr_str_attr(tobj_p, + tobj_p->get_vendor_sn, + buf_p); +} + + +static ssize_t +show_attr_power_cls(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + size_t len; + int result; + struct transvr_obj_s *tobj_p; + + tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + lock_transvr_obj(tobj_p); + result = tobj_p->get_power_cls(tobj_p); + unlock_transvr_obj(tobj_p); + if (result < 0){ + len = snprintf(buf_p, 16, "%d\n", result); + } else { + len = snprintf(buf_p, 16, "Power Class %d\n", result); + } + return len; +} + + +static ssize_t +show_attr_br(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_transvr_hex_attr(tobj_p, + tobj_p->get_br, + buf_p); +} + + +static ssize_t +show_attr_len_sm(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_transvr_int_attr(tobj_p, + tobj_p->get_len_sm, + buf_p); +} + + +static ssize_t +show_attr_len_smf(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_transvr_int_attr(tobj_p, + tobj_p->get_len_smf, + buf_p); +} + + +static ssize_t +show_attr_len_om1(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_transvr_int_attr(tobj_p, + tobj_p->get_len_om1, + buf_p); +} + + +static ssize_t +show_attr_len_om2(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_transvr_int_attr(tobj_p, + tobj_p->get_len_om2, + buf_p); +} + + +static ssize_t +show_attr_len_om3(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_transvr_int_attr(tobj_p, + tobj_p->get_len_om3, + buf_p); +} + + +static ssize_t +show_attr_len_om4(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_transvr_int_attr(tobj_p, + tobj_p->get_len_om4, + buf_p); +} + + +static ssize_t +show_attr_comp_rev(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_transvr_hex_attr(tobj_p, + tobj_p->get_comp_rev, + buf_p); +} + + +static ssize_t +show_attr_comp_eth(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_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_1, + buf_p); +} + + +static ssize_t +show_attr_comp_eth_10(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_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_10, + buf_p); +} + + +static ssize_t +show_attr_comp_eth_10_40(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_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_10_40, + buf_p); +} + + +static ssize_t +show_attr_comp_extend(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_transvr_hex_attr(tobj_p, + tobj_p->get_comp_extend, + buf_p); +} + + +static ssize_t +show_attr_rate_id(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_transvr_hex_attr(tobj_p, + tobj_p->get_rate_id, + buf_p); +} + + +static ssize_t +show_attr_temperature(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_transvr_str_attr(tobj_p, + tobj_p->get_curr_temp, + buf_p); +} + + +static ssize_t +show_attr_voltage(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_transvr_str_attr(tobj_p, + tobj_p->get_curr_vol, + buf_p); +} + + +static ssize_t +show_attr_tx_bias(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_transvr_str_attr(tobj_p, + tobj_p->get_tx_bias, + buf_p); +} + + +static ssize_t +show_attr_tx_power(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_transvr_str_attr(tobj_p, + tobj_p->get_tx_power, + buf_p); +} + + +static ssize_t +show_attr_tx_eq(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_transvr_str_attr(tobj_p, + tobj_p->get_tx_eq, + buf_p); +} + + +static ssize_t +show_attr_rx_power(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_transvr_str_attr(tobj_p, + tobj_p->get_rx_power, + buf_p); +} + + +static ssize_t +show_attr_rx_am(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_transvr_str_attr(tobj_p, + tobj_p->get_rx_am, + buf_p); +} + + +static ssize_t +show_attr_rx_em(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_transvr_str_attr(tobj_p, + tobj_p->get_rx_em, + buf_p); +} + + +static ssize_t +show_attr_wavelength(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_transvr_str_attr(tobj_p, + tobj_p->get_wavelength, + buf_p); +} + + +static ssize_t +show_attr_extphy_offset(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_transvr_str_attr(tobj_p, + tobj_p->get_extphy_offset, + buf_p); +} + + +static ssize_t +show_attr_extphy_reg(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_transvr_str_attr(tobj_p, + tobj_p->get_extphy_reg, + buf_p); +} + + +static ssize_t +show_attr_info(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_transvr_int_attr(tobj_p, + tobj_p->get_info, + buf_p); +} + + +static ssize_t +show_attr_if_type(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_transvr_str_attr(tobj_p, + tobj_p->get_if_type, + buf_p); +} + + +static ssize_t +show_attr_if_speed(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_transvr_str_attr(tobj_p, + tobj_p->get_if_speed, + buf_p); +} + + +static ssize_t +show_attr_if_lane(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_transvr_str_attr(tobj_p, + tobj_p->get_if_lane, + buf_p); +} + + +static ssize_t +show_attr_cdr(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_transvr_hex_attr(tobj_p, + tobj_p->get_cdr, + buf_p); +} + + +static ssize_t +show_attr_soft_rs0(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_transvr_int_attr(tobj_p, + tobj_p->get_soft_rs0, + buf_p); +} + + +static ssize_t +show_attr_soft_rs1(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_transvr_int_attr(tobj_p, + tobj_p->get_soft_rs1, + buf_p); +} + + +static ssize_t +show_attr_soft_rx_los(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_transvr_str_attr(tobj_p, + tobj_p->get_soft_rx_los, + buf_p); +} + + +static ssize_t +show_attr_soft_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_transvr_str_attr(tobj_p, + tobj_p->get_soft_tx_disable, + buf_p); +} + + +static ssize_t +show_attr_soft_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_transvr_str_attr(tobj_p, + tobj_p->get_soft_tx_fault, + buf_p); +} + + +static ssize_t +show_attr_auto_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_transvr_str_attr(tobj_p, + tobj_p->get_auto_tx_disable, + buf_p); +} + + +/* ========== Store functions: transceiver (R/W) attribute ========== + */ +static ssize_t +_store_transvr_int_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_int(buf_p); + if (input < 0){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +_store_transvr_byte_hex_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_int(buf_p); + if ((input < 0) || (input > 0xff)){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +_store_transvr_binary_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_binary(buf_p); + if (input < 0){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +store_attr_cdr(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_transvr_byte_hex_attr(tobj_p, + tobj_p->set_cdr, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_rs0(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_transvr_binary_attr(tobj_p, + tobj_p->set_soft_rs0, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_rs1(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_transvr_binary_attr(tobj_p, + tobj_p->set_soft_rs1, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count) { + + int check = sscanf_2_int(buf_p); + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + if ((check < 0) || (check > 0xf)){ + return -EBFONT; + } + return _store_transvr_byte_hex_attr(tobj_p, + tobj_p->set_soft_tx_disable, + buf_p, + count); +} + + +static ssize_t +store_attr_auto_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count) { + + int err = -EPERM; + int input = sscanf_2_int(buf_p); + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + if ((input < 0) || (input > 0xf)){ + if (input != VAL_TRANSVR_FUNCTION_DISABLE) { + return -EBFONT; + } + } + lock_transvr_obj(tobj_p); + err = tobj_p->set_auto_tx_disable(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +store_attr_tx_eq(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_transvr_int_attr(tobj_p, + tobj_p->set_tx_eq, + buf_p, + count); +} + + +static ssize_t +store_attr_rx_am(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_transvr_int_attr(tobj_p, + tobj_p->set_rx_am, + buf_p, + count); +} + + +static ssize_t +store_attr_rx_em(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_transvr_int_attr(tobj_p, + tobj_p->set_rx_em, + buf_p, + count); +} + + +static ssize_t +store_attr_extphy_offset(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_transvr_int_attr(tobj_p, + tobj_p->set_extphy_offset, + buf_p, + count); +} + + +static ssize_t +store_attr_extphy_reg(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_transvr_int_attr(tobj_p, + tobj_p->set_extphy_reg, + buf_p, + count); +} + +/* ========== 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); +} + + +static ssize_t +show_attr_hard_rs0(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_hard_rs0, + buf_p); +} + + +static ssize_t +show_attr_hard_rs1(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_hard_rs1, + 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); +} + + +static ssize_t +store_attr_hard_rs0(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_hard_rs0, + buf_p, + count); +} + + +static ssize_t +store_attr_hard_rs1(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_hard_rs1, + buf_p, + count); +} + + +/* ========== SWPS attribute: For module control ========== + */ +static DEVICE_ATTR(platform, S_IRUGO, show_attr_platform, NULL); +static DEVICE_ATTR(version, S_IRUGO, show_attr_version, NULL); +static DEVICE_ATTR(status, S_IRUGO, show_attr_status, NULL); +static DEVICE_ATTR(reset_i2c, S_IWUSR, NULL, store_attr_reset_i2c); +static DEVICE_ATTR(reset_swps, S_IWUSR, NULL, store_attr_reset_swps); +static DEVICE_ATTR(auto_config, S_IRUGO|S_IWUSR, show_attr_auto_config, store_attr_auto_config); + +/* ========== Transceiver attribute: from eeprom ========== + */ +static DEVICE_ATTR(id, S_IRUGO, show_attr_id, NULL); +static DEVICE_ATTR(ext_id, S_IRUGO, show_attr_ext_id, NULL); +static DEVICE_ATTR(connector, S_IRUGO, show_attr_connector, NULL); +static DEVICE_ATTR(vendor_name, S_IRUGO, show_attr_vendor_name, NULL); +static DEVICE_ATTR(vendor_pn, S_IRUGO, show_attr_vendor_pn, NULL); +static DEVICE_ATTR(vendor_rev, S_IRUGO, show_attr_vendor_rev, NULL); +static DEVICE_ATTR(vendor_sn, S_IRUGO, show_attr_vendor_sn, NULL); +static DEVICE_ATTR(power_cls, S_IRUGO, show_attr_power_cls, NULL); +static DEVICE_ATTR(br, S_IRUGO, show_attr_br, NULL); +static DEVICE_ATTR(len_sm, S_IRUGO, show_attr_len_sm, NULL); +static DEVICE_ATTR(len_smf, S_IRUGO, show_attr_len_smf, NULL); +static DEVICE_ATTR(len_om1, S_IRUGO, show_attr_len_om1, NULL); +static DEVICE_ATTR(len_om2, S_IRUGO, show_attr_len_om2, NULL); +static DEVICE_ATTR(len_om3, S_IRUGO, show_attr_len_om3, NULL); +static DEVICE_ATTR(len_om4, S_IRUGO, show_attr_len_om4, NULL); +static DEVICE_ATTR(comp_rev, S_IRUGO, show_attr_comp_rev, NULL); +static DEVICE_ATTR(comp_eth, S_IRUGO, show_attr_comp_eth, NULL); +static DEVICE_ATTR(comp_eth_10, S_IRUGO, show_attr_comp_eth_10, NULL); +static DEVICE_ATTR(comp_eth_10_40, S_IRUGO, show_attr_comp_eth_10_40, NULL); +static DEVICE_ATTR(comp_extend, S_IRUGO, show_attr_comp_extend, NULL); +static DEVICE_ATTR(rate_id, S_IRUGO, show_attr_rate_id, NULL); +static DEVICE_ATTR(temperature, S_IRUGO, show_attr_temperature, NULL); +static DEVICE_ATTR(voltage, S_IRUGO, show_attr_voltage, NULL); +static DEVICE_ATTR(tx_bias, S_IRUGO, show_attr_tx_bias, NULL); +static DEVICE_ATTR(tx_power, S_IRUGO, show_attr_tx_power, NULL); +static DEVICE_ATTR(rx_power, S_IRUGO, show_attr_rx_power, NULL); +static DEVICE_ATTR(info, S_IRUGO, show_attr_info, NULL); +static DEVICE_ATTR(if_type, S_IRUGO, show_attr_if_type, NULL); +static DEVICE_ATTR(if_speed, S_IRUGO, show_attr_if_speed, NULL); +static DEVICE_ATTR(if_lane, S_IRUGO, show_attr_if_lane, NULL); +static DEVICE_ATTR(soft_rx_los, S_IRUGO, show_attr_soft_rx_los, NULL); +static DEVICE_ATTR(soft_tx_fault, S_IRUGO, show_attr_soft_tx_fault, NULL); +static DEVICE_ATTR(wavelength, S_IRUGO, show_attr_wavelength, NULL); +static DEVICE_ATTR(tx_eq, S_IRUGO|S_IWUSR, show_attr_tx_eq, store_attr_tx_eq); +static DEVICE_ATTR(rx_am, S_IRUGO|S_IWUSR, show_attr_rx_am, store_attr_rx_am); +static DEVICE_ATTR(rx_em, S_IRUGO|S_IWUSR, show_attr_rx_em, store_attr_rx_em); +static DEVICE_ATTR(cdr, S_IRUGO|S_IWUSR, show_attr_cdr, store_attr_cdr); +static DEVICE_ATTR(soft_rs0, S_IRUGO|S_IWUSR, show_attr_soft_rs0, store_attr_soft_rs0); +static DEVICE_ATTR(soft_rs1, S_IRUGO|S_IWUSR, show_attr_soft_rs1, store_attr_soft_rs1); +static DEVICE_ATTR(soft_tx_disable, S_IRUGO|S_IWUSR, show_attr_soft_tx_disable, store_attr_soft_tx_disable); +static DEVICE_ATTR(auto_tx_disable, S_IRUGO|S_IWUSR, show_attr_auto_tx_disable, store_attr_auto_tx_disable); +static DEVICE_ATTR(extphy_offset, S_IRUGO|S_IWUSR, show_attr_extphy_offset, store_attr_extphy_offset); +static DEVICE_ATTR(extphy_reg, S_IRUGO|S_IWUSR, show_attr_extphy_reg, store_attr_extphy_reg); + +/* ========== 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); +static DEVICE_ATTR(hard_rs0, S_IRUGO|S_IWUSR, show_attr_hard_rs0, store_attr_hard_rs0); +static DEVICE_ATTR(hard_rs1, S_IRUGO|S_IWUSR, show_attr_hard_rs1, store_attr_hard_rs1); + +/* ========== 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->vendor_name); + kfree(transvr_obj_p->vendor_pn); + kfree(transvr_obj_p->vendor_rev); + kfree(transvr_obj_p->vendor_sn); + kfree(transvr_obj_p->worker_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 void +clean_swps_common(void){ + + dev_t dev_num; + struct device *device_p; + + device_p = get_swpdev_by_name(SWP_DEV_MODCTL); + if (device_p){ + dev_num = MKDEV(ctl_major, 1); + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); + } + cancel_delayed_work_sync(&swp_polling); + SWPS_DEBUG("%s: done.\n", __func__); +} + + +static int +get_platform_type(void){ + + int i; + int pf_total = ARRAY_SIZE(platform_map); + 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; + } + memset(platform_p->name, 0, sizeof(platform_p->name)); + + switch (PLATFORM_SETTINGS) { + case PLATFORM_TYPE_AUTO: + snprintf(platform_p->name, (sizeof(platform_p->name) - 1), + "%s", dmi_get_system_info(DMI_BOARD_NAME)); + for (i=0; iname, platform_map[i].name) == 0) { + platform_p->id = platform_map[i].id; + snprintf(log_msg, sizeof(log_msg), + "Auto detect platform: %d (%s)", + platform_p->id, platform_p->name); + goto ok_get_platform_type_1; + } + } + snprintf(log_msg, sizeof(log_msg), + "Auto detect fail! detect platform: %s", + platform_p->name); + goto err_get_platform_type_2; + + case PLATFORM_TYPE_MAGNOLIA: + case PLATFORM_TYPE_MAGNOLIA_FNC: + case PLATFORM_TYPE_REDWOOD: + case PLATFORM_TYPE_REDWOOD_FSL: + case PLATFORM_TYPE_HUDSON32I_GA: + case PLATFORM_TYPE_SPRUCE: + case PLATFORM_TYPE_CYPRESS_GA1: + case PLATFORM_TYPE_CYPRESS_GA2: + case PLATFORM_TYPE_CYPRESS_BAI: + case PLATFORM_TYPE_TAHOE: + case PLATFORM_TYPE_SEQUOIA_GA: + case PLATFORM_TYPE_LAVENDER_GA: + case PLATFORM_TYPE_LAVENDER_ONL: + case PLATFORM_TYPE_COTTONWOOD_RANGELEY: + case PLATFORM_TYPE_MAPLE: + platform_p->id = PLATFORM_SETTINGS; + for (i=0; iname, (sizeof(platform_p->name) - 1), + "%s", platform_map[i].name); + snprintf(log_msg, sizeof(log_msg), + "User setup platform: %d (%s)", + platform_p->id, platform_p->name); + goto ok_get_platform_type_1; + } + } + snprintf(log_msg, sizeof(log_msg), + "Internal error, can not map id:%d", + PLATFORM_SETTINGS); + goto err_get_platform_type_2; + + default: + break; + } + snprintf(log_msg, sizeof(log_msg), + "PLATFORM_SETTINGS:%d undefined", PLATFORM_SETTINGS); + goto err_get_platform_type_2; + +ok_get_platform_type_1: + SWPS_DEBUG("%s: %s, :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return 0; + +err_get_platform_type_2: + kfree(platform_p); +err_get_platform_type_1: + SWPS_ERR("%s: %s :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return -1; +} + + +static int +get_layout_info(void){ + + switch (platform_p->id) { +#ifdef SWPS_MAGNOLIA + case PLATFORM_TYPE_MAGNOLIA: + case PLATFORM_TYPE_MAGNOLIA_FNC: + gpio_rest_mux = magnolia_gpio_rest_mux; + ioexp_layout = magnolia_ioexp_layout; + port_layout = magnolia_port_layout; + ioexp_total = ARRAY_SIZE(magnolia_ioexp_layout); + port_total = ARRAY_SIZE(magnolia_port_layout); + break; +#endif +#ifdef SWPS_REDWOOD + case PLATFORM_TYPE_REDWOOD: + gpio_rest_mux = redwood_gpio_rest_mux; + ioexp_layout = redwood_ioexp_layout; + port_layout = redwood_port_layout; + ioexp_total = ARRAY_SIZE(redwood_ioexp_layout); + port_total = ARRAY_SIZE(redwood_port_layout); + break; +#endif +#ifdef SWPS_HUDSON32I_GA + case PLATFORM_TYPE_HUDSON32I_GA: + gpio_rest_mux = hudsin32iga_gpio_rest_mux; + ioexp_layout = hudson32iga_ioexp_layout; + port_layout = hudson32iga_port_layout; + ioexp_total = ARRAY_SIZE(hudson32iga_ioexp_layout); + port_total = ARRAY_SIZE(hudson32iga_port_layout); + break; +#endif +#ifdef SWPS_SPRUCE + case PLATFORM_TYPE_SPRUCE: + gpio_rest_mux = spruce_gpio_rest_mux; + ioexp_layout = spruce_ioexp_layout; + port_layout = spruce_port_layout; + ioexp_total = ARRAY_SIZE(spruce_ioexp_layout); + port_total = ARRAY_SIZE(spruce_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_GA1 + case PLATFORM_TYPE_CYPRESS_GA1: + gpio_rest_mux = cypress_ga1_gpio_rest_mux; + ioexp_layout = cypress_ga1_ioexp_layout; + port_layout = cypress_ga1_port_layout; + ioexp_total = ARRAY_SIZE(cypress_ga1_ioexp_layout); + port_total = ARRAY_SIZE(cypress_ga1_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_GA2 + case PLATFORM_TYPE_CYPRESS_GA2: + gpio_rest_mux = cypress_ga2_gpio_rest_mux; + 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); + break; +#endif +#ifdef SWPS_CYPRESS_BAI + case PLATFORM_TYPE_CYPRESS_BAI: + gpio_rest_mux = cypress_b_gpio_rest_mux; + ioexp_layout = cypress_b_ioexp_layout; + port_layout = cypress_b_port_layout; + ioexp_total = ARRAY_SIZE(cypress_b_ioexp_layout); + port_total = ARRAY_SIZE(cypress_b_port_layout); + break; +#endif +#ifdef SWPS_REDWOOD_FSL + case PLATFORM_TYPE_REDWOOD_FSL: + gpio_rest_mux = redwood_fsl_gpio_rest_mux; + ioexp_layout = redwood_fsl_ioexp_layout; + port_layout = redwood_fsl_port_layout; + ioexp_total = ARRAY_SIZE(redwood_fsl_ioexp_layout); + port_total = ARRAY_SIZE(redwood_fsl_port_layout); + break; +#endif +#ifdef SWPS_TAHOE + case PLATFORM_TYPE_TAHOE: + gpio_rest_mux = tahoe_gpio_rest_mux; + ioexp_layout = tahoe_ioexp_layout; + port_layout = tahoe_port_layout; + ioexp_total = ARRAY_SIZE(tahoe_ioexp_layout); + port_total = ARRAY_SIZE(tahoe_port_layout); + break; +#endif +#ifdef SWPS_SEQUOIA + case PLATFORM_TYPE_SEQUOIA_GA: + gpio_rest_mux = sequoia_gpio_rest_mux; + ioexp_layout = sequoia_ioexp_layout; + port_layout = sequoia_port_layout; + ioexp_total = ARRAY_SIZE(sequoia_ioexp_layout); + port_total = ARRAY_SIZE(sequoia_port_layout); + break; +#endif +#ifdef SWPS_LAVENDER + case PLATFORM_TYPE_LAVENDER_GA: + case PLATFORM_TYPE_LAVENDER_ONL: + gpio_rest_mux = lavender_gpio_rest_mux; + ioexp_layout = lavender_ioexp_layout; + port_layout = lavender_port_layout; + ioexp_total = ARRAY_SIZE(lavender_ioexp_layout); + port_total = ARRAY_SIZE(lavender_port_layout); + break; +#endif +#ifdef SWPS_COTTONWOOD_RANGELEY + case PLATFORM_TYPE_COTTONWOOD_RANGELEY: + gpio_rest_mux = cottonwood_rangeley_gpio_rest_mux; + ioexp_layout = cottonwood_rangeley_ioexp_layout; + port_layout = cottonwood_rangeley_port_layout; + ioexp_total = ARRAY_SIZE(cottonwood_rangeley_ioexp_layout); + port_total = ARRAY_SIZE(cottonwood_rangeley_port_layout); + break; +#endif +#ifdef SWPS_MAPLE + case PLATFORM_TYPE_MAPLE: + gpio_rest_mux = maple_gpio_rest_mux; + ioexp_layout = maple_ioexp_layout; + port_layout = maple_port_layout; + ioexp_total = ARRAY_SIZE(maple_ioexp_layout); + port_total = ARRAY_SIZE(maple_port_layout); + break; +#endif + default: + SWPS_ERR(" Invalid platform: %d (%s)\n", + platform_p->id, platform_p->name); + return -1; + } + SWPS_INFO("Start to initial platform: %d (%s)\n", + platform_p->id, platform_p->name); + return 0; +} + + +/* ========== Functions for objects operations ========== + */ +static int +__detect_issues_port(int minor_num) { + + struct transvr_obj_s *tobj_p; + int port_id = port_layout[minor_num].port_id; + char port_name[32] = "ERR"; + char *i2c_emsg = "detected bad transceiver/cable"; + + memset(port_name, 0, sizeof(port_name)); + snprintf(port_name, sizeof(port_name), "%s%d", SWP_DEV_PORT, port_id); + tobj_p = _get_transvr_obj(port_name); + if (!tobj_p) { + SWPS_INFO("%s: tobj_p is NULL :%d\n", __func__, minor_num); + return -1; + } + if (resync_channel_tier_2(tobj_p) < 0) { + if (check_channel_tier_1() < 0) { + alarm_msg_2_user(tobj_p, i2c_emsg); + return -2;; + } + } + return 0; +} + + +static int +_detect_issues_port(void) { + /* OK : retrun -1; + * Fail: return fail at which minor number (0~N) + */ + char *emsg = "ERR"; + int minor = 0; + int minor_2st = 1; + + /* Force moving the initial channel pointer + * Filter out case of fail at minor-0 port + */ + while (minor_2st < port_total) { + minor = minor_2st; + if (__detect_issues_port(minor_2st) < 0) { + emsg = "detect minor_2st fail"; + goto err_p_detect_issues_port; + } + minor_2st += 8; + } + /* Scan all port */ + for (minor=0; minor:%d\n", __func__, emsg, minor_err); + return -1; +} + + +static int +check_transvr_obj_one(char *dev_name){ + /* [Return] + * 0 : Doesn't need to take care + * -1 : Single error + * -2 : Critical error (I2C topology die) + * -9 : Internal error + */ + struct transvr_obj_s *tobj_p = NULL; + int retval = -9; + + tobj_p = _get_transvr_obj(dev_name); + if (!tobj_p) { + SWPS_ERR("%s: %s _get_transvr_obj fail\n", + __func__, dev_name); + return -9; + } + /* Check transceiver current status */ + lock_transvr_obj(tobj_p); + retval = tobj_p->check(tobj_p); + unlock_transvr_obj(tobj_p); + switch (retval) { + case 0: + case ERR_TRANSVR_UNPLUGGED: + case ERR_TRNASVR_BE_ISOLATED: + case ERR_TRANSVR_TASK_BUSY: + return 0; + + case ERR_TRANSVR_I2C_CRASH: + default: + break; + } + /* Identify abnormal case */ + if (check_channel_tier_1() < 0) { + SWPS_DEBUG("%s: %s critical error :%d\n", + __func__, dev_name, retval); + return -2; + } + SWPS_DEBUG("%s: %s single error :%d\n", + __func__, dev_name, retval); + return -1; +} + + +static int +check_transvr_objs(void){ + + char dev_name[32]; + int port_id, err_code; + int minor_curr = 0; + + for (minor_curr=0; minor_curr:%d\n", + __func__, dev_name, err_code); + break; + } + } + return 0; + +err_check_transvr_objs: + SWPS_ERR("%s: %s reset_i2c_topology fail.\n", + __func__, dev_name); + return -1; +} + + +static void +swp_polling_worker(struct work_struct *work){ + + /* Reset I2C */ + if (flag_i2c_reset) { + goto polling_reset_i2c; + } + /* Check IOEXP */ + if (check_ioexp_objs() < 0) { + goto polling_reset_i2c; + } + /* Check transceiver */ + if (check_transvr_objs() < 0) { + SWPS_DEBUG("%s: check_transvr_objs fail.\n", __func__); + flag_i2c_reset = 1; + } + goto polling_schedule_round; + +polling_reset_i2c: + SWPS_DEBUG("%s: reset_i2c_topology start.\n", __func__); + if (reset_i2c_topology() < 0) { + SWPS_ERR("%s: reset i2c fail!\n", __func__); + flag_i2c_reset = 1; + } else { + SWPS_DEBUG("%s: reset_i2c_topology OK.\n", __func__); + flag_i2c_reset = 0; + } +polling_schedule_round: + schedule_delayed_work(&swp_polling, _get_polling_period()); +} + + +/* ========== Functions for register something ========== + */ +static int +register_transvr_common_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_id) < 0) { + err_attr = "dev_attr_id"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_ext_id) < 0) { + err_attr = "dev_attr_ext_id"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_connector) < 0) { + err_attr = "dev_attr_connector"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_name) < 0) { + err_attr = "dev_attr_vendor_name"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_pn) < 0) { + err_attr = "dev_attr_vendor_pn"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_rev) < 0) { + err_attr = "dev_attr_vendor_rev"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_sn) < 0) { + err_attr = "dev_attr_vendor_sn"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_br) < 0) { + err_attr = "dev_attr_br"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_smf) < 0) { + err_attr = "dev_attr_len_smf"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om1) < 0) { + err_attr = "dev_attr_len_om1"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om2) < 0) { + err_attr = "dev_attr_len_om2"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om3) < 0) { + err_attr = "dev_attr_len_om3"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om4) < 0) { + err_attr = "dev_attr_len_om4"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_extend) < 0) { + err_attr = "dev_attr_comp_extend"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth) < 0) { + err_attr = "dev_attr_comp_eth"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_rev) < 0) { + err_attr = "dev_attr_comp_rev"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_info) < 0) { + err_attr = "dev_attr_info"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_type) < 0) { + err_attr = "dev_attr_if_type"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_speed) < 0) { + err_attr = "dev_attr_if_speed"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_lane) < 0) { + err_attr = "dev_attr_if_lane"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_temperature) < 0) { + err_attr = "dev_attr_temperature"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_voltage) < 0) { + err_attr = "dev_attr_voltage"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_bias) < 0) { + err_attr = "dev_attr_tx_bias"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_power) < 0) { + err_attr = "dev_attr_tx_power"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_rx_power) < 0) { + err_attr = "dev_attr_rx_power"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_eq) < 0) { + err_attr = "dev_attr_tx_eq"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_rx_em) < 0) { + err_attr = "dev_attr_rx_em"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_wavelength) < 0) { + err_attr = "dev_attr_wavelength"; + goto err_transvr_comm_attr; + } + return 0; + +err_transvr_comm_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + +static int +register_transvr_sfp_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_common_attr(device_p) < 0) { + err_attr = "register_transvr_common_attr"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth_10) < 0) { + err_attr = "dev_attr_comp_eth_10"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_len_sm) < 0) { + err_attr = "dev_attr_len_sm"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_rate_id) < 0) { + err_attr = "dev_attr_rate_id"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rs0) < 0) { + err_attr = "dev_attr_soft_rs0"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rs1) < 0) { + err_attr = "dev_attr_soft_rs1"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_extphy_offset) < 0) { + err_attr = "dev_attr_extphy_offset"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_extphy_reg) < 0) { + err_attr = "dev_attr_extphy_reg"; + goto err_transvr_sfp_attr; + } + return 0; + +err_transvr_sfp_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_qsfp_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_common_attr(device_p) < 0) { + err_attr = "register_transvr_common_attr"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth_10_40) < 0) { + err_attr = "dev_attr_comp_eth_10_40"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_power_cls) < 0) { + err_attr = "dev_attr_power_cls"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rx_los) < 0) { + err_attr = "soft_rx_los"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_tx_disable) < 0) { + err_attr = "soft_tx_disable"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_auto_tx_disable) < 0) { + err_attr = "auto_tx_disable"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_tx_fault) < 0) { + err_attr = "soft_tx_fault"; + goto err_transvr_qsfp_attr; + } + return 0; + +err_transvr_qsfp_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_qsfp28_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_qsfp_attr(device_p) < 0){ + err_attr = "register_transvr_qsfp_attr"; + goto err_transvr_qsfp28_attr; + } + if (device_create_file(device_p, &dev_attr_cdr) < 0) { + err_attr = "dev_attr_cdr"; + goto err_transvr_qsfp28_attr; + } + if (device_create_file(device_p, &dev_attr_rx_am) < 0) { + err_attr = "dev_attr_rx_am"; + goto err_transvr_qsfp28_attr; + } + return 0; + +err_transvr_qsfp28_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_attr(struct device *device_p, + struct transvr_obj_s *transvr_obj){ + + switch (transvr_obj->layout){ + case TRANSVR_TYPE_SFP: + if (register_transvr_sfp_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + if (register_transvr_qsfp_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + case TRANSVR_TYPE_QSFP_28: + if (register_transvr_qsfp28_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + default: + goto err_reg_tvr_attr; + } + return 0; + +err_reg_tvr_attr: + SWPS_ERR("%s: fail! type=%d \n", __func__, transvr_obj->type); + return -1; +} + + +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; + } + if (device_create_file(device_p, &dev_attr_hard_rs0) < 0) { + err_attr = "dev_attr_hard_rs0"; + goto err_ioexp_sfp2_attr; + } + if (device_create_file(device_p, &dev_attr_hard_rs1) < 0) { + err_attr = "dev_attr_hard_rs1"; + 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_modctl_attr(struct device *device_p){ + + char *err_msg = NULL; + + if (device_create_file(device_p, &dev_attr_platform) < 0) { + err_msg = "dev_attr_platform"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_version) < 0) { + err_msg = "dev_attr_version"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_status) < 0) { + err_msg = "dev_attr_status"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_reset_i2c) < 0) { + err_msg = "dev_attr_reset_i2c"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_reset_swps) < 0) { + err_msg = "dev_attr_reset_swps"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_auto_config) < 0) { + err_msg = "dev_attr_auto_config"; + goto err_reg_modctl_attr; + } + return 0; + +err_reg_modctl_attr: + SWPS_ERR("%s: %s\n", __func__, err_msg); + 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_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case CPLD_TYPE_COTTONWOOD: + if (register_ioexp_attr_sfp_1(device_p) < 0){ + err_msg = "register_ioexp_attr_sfp_1 fail"; + goto err_reg_ioexp_attr; + } + break; + case IOEXP_TYPE_CYPRESS_NABC: + case IOEXP_TYPE_MAPLE_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_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + case IOEXP_TYPE_MAPLE_0ABC: + 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_modctl_device(void) { + + struct device *device_p = NULL; + int minor_comm = 0; /* Default minor number for common device */ + dev_t dev_num = MKDEV(ctl_major, minor_comm); + char *err_msg = "ERROR"; + + device_p = device_create(swp_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + NULL, /* void *private_data */ + SWP_DEV_MODCTL); /* const char *fmt */ + if (IS_ERR(device_p)){ + err_msg = "device_create fail"; + goto err_register_modctl_device_1; + } + if (register_modctl_attr(device_p) < 0) { + err_msg = "register_modctl_attr fail"; + goto err_register_modctl_device_2; + } + return 0; + +err_register_modctl_device_2: + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); +err_register_modctl_device_1: + SWPS_ERR("%s: %s\n", __func__, err_msg); + 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_transvr_attr(device_p, transvr_obj) < 0){ + goto err_regswp_reg_attr; + } + 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 ctl_devt = 0; + dev_t port_devt = 0; + int dev_total = port_total + 1; /* char_dev for module control */ + + /* Register device number */ + if (alloc_chrdev_region(&ctl_devt, 0, 1, SWP_DEV_MODCTL) < 0){ + SWPS_WARN("Allocate CTL MAJOR failure! \n"); + goto err_register_swp_module_1; + } + 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_2; + } + ctl_major = MAJOR(ctl_devt); + 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); +err_register_swp_module_2: + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); +err_register_swp_module_1: + 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; + if (SWP_POLLING_ENABLE){ + run_mod = IOEXP_MODE_POLLING; + } + /* 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_dev_topology(void){ + + int err; + char *emsg = "ERR"; + flag_mod_state = SWP_STATE_NORMAL; + + err = init_ioexp_objs(); + switch(err){ + case 0: /* Normal */ + SWPS_DEBUG("%s: normal case\n", __func__); + break; + + case -1: /* topology error */ + SWPS_DEBUG("%s: detect tier-1 topology initial failure :%d\n", + __func__, err); + /* Reset and isolate */ + err = reset_i2c_topology(); + if (err < 0) { + emsg = "reset i2c topology fail"; + goto err_init_dev_topology; + } + /* Re-initial again */ + err = init_ioexp_objs(); + if (err < 0) { + emsg = "re-init ioexp objects fail"; + goto err_init_dev_topology; + } + break; + + case -2: /* Internal error */ + SWPS_DEBUG("%s: internal error case\n", __func__); + err = -2; + emsg = "internal error"; + goto err_init_dev_topology; + + default: + SWPS_DEBUG("%s: undefined error case\n", __func__); + emsg = "undefined error case"; + goto err_init_dev_topology; + } + SWPS_DEBUG("%s: initial I2C topology success\n", __func__); + return 0; + +err_init_dev_topology: + SWPS_ERR("%s: %s :%d\n", __func__, emsg, err); + return -1; +} + + +static int +init_polling_task(void){ + + if (SWP_POLLING_ENABLE){ + schedule_delayed_work(&swp_polling, _get_polling_period()); + } + return 0; +} + + +static int +init_swps_common(void){ + + char *err_msg = "ERR"; + + auto_config = 0; + if ((SWP_AUTOCONFIG_ENABLE) && (SWP_POLLING_ENABLE)){ + auto_config = 1; + } + if (register_modctl_device() < 0) { + err_msg = "register_modctl_device fail"; + goto err_init_swps_common_1; + } + if (_update_auto_config_2_trnasvr() < 0) { + err_msg = "_update_auto_config_2_trnasvr fail"; + goto err_init_swps_common_1; + } + if (init_polling_task() < 0){ + err_msg = "init_polling_task fail"; + goto err_init_swps_common_1; + } + return 0; + +err_init_swps_common_1: + clean_swps_common(); + SWPS_ERR("%s: %s\n", __func__, err_msg); + 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_mux_gpio(gpio_rest_mux) < 0){ + goto err_init_mux; + } + if (init_dev_topology() < 0){ + goto err_init_topology; + } + if (init_swps_common() < 0){ + goto err_init_topology; + } + SWPS_INFO("Inventec switch-port module V.%s initial success.\n", SWP_VERSION); + return 0; + + +err_init_topology: + clean_mux_gpio(); +err_init_mux: + clean_port_obj(); +err_init_portobj: + clean_ioexp_objs(); +err_init_ioexp: + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); + 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_swps_common(); + clean_port_obj(); + clean_ioexp_objs(); + clean_mux_gpio(); + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); + 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/d6556/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_swps.h new file mode 100644 index 000000000000..d28a0a3c968e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_swps.h @@ -0,0 +1,1164 @@ +/* + * 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. + */ + +#ifndef INV_SWPS_H +#define INV_SWPS_H + +#include "transceiver.h" +#include "io_expander.h" +#include "inv_mux.h" + +/* Module settings */ +#define SWP_CLS_NAME "swps" +#define SWP_DEV_PORT "port" +#define SWP_DEV_MODCTL "module" +#define SWP_RESET_PWD "inventec" +#define SWP_POLLING_PERIOD (300) /* msec */ +#define SWP_POLLING_ENABLE (1) +#define SWP_AUTOCONFIG_ENABLE (1) + +/* Module information */ +#define SWP_AUTHOR "Neil " +#define SWP_DESC "Inventec port and transceiver driver" +#define SWP_VERSION "4.2.9" +#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_AUTO (100) +#define PLATFORM_TYPE_MAGNOLIA (111) +#define PLATFORM_TYPE_MAGNOLIA_FNC (112) +#define PLATFORM_TYPE_REDWOOD (121) +#define PLATFORM_TYPE_REDWOOD_FSL (122) +#define PLATFORM_TYPE_HUDSON32I_GA (131) +#define PLATFORM_TYPE_SPRUCE (141) +#define PLATFORM_TYPE_CYPRESS_GA1 (151) /* Up -> Down */ +#define PLATFORM_TYPE_CYPRESS_GA2 (152) /* Down -> Up */ +#define PLATFORM_TYPE_CYPRESS_BAI (153) /* Down -> Up */ +#define PLATFORM_TYPE_TAHOE (161) +#define PLATFORM_TYPE_SEQUOIA_GA (171) +#define PLATFORM_TYPE_LAVENDER_GA (181) +#define PLATFORM_TYPE_LAVENDER_ONL (182) +#define PLATFORM_TYPE_COTTONWOOD_RANGELEY (191) +#define PLATFORM_TYPE_MAPLE (201) +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_MAPLE + +/* Define platform flag and kernel version */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA) + #define SWPS_MAGNOLIA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA_FNC) + #define SWPS_MAGNOLIA (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD) + #define SWPS_REDWOOD (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD_FSL) + #define SWPS_REDWOOD_FSL (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_HUDSON32I_GA) + #define SWPS_HUDSON32I_GA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SPRUCE) + #define SWPS_SPRUCE (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA1) + #define SWPS_CYPRESS_GA1 (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA2) + #define SWPS_CYPRESS_GA2 (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_BAI) + #define SWPS_CYPRESS_BAI (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_TAHOE) + #define SWPS_TAHOE (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SEQUOIA_GA) + #define SWPS_SEQUOIA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA) + #define SWPS_LAVENDER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL) + #define SWPS_LAVENDER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_COTTONWOOD_RANGELEY) + #define SWPS_COTTONWOOD_RANGELEY (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAPLE) + #define SWPS_MAPLE (1) + #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_AUTO, "Auto-Detect" }, + {PLATFORM_TYPE_MAGNOLIA, "Magnolia" }, + {PLATFORM_TYPE_MAGNOLIA_FNC, "Magnolia_FNC" }, + {PLATFORM_TYPE_REDWOOD, "Redwood" }, + {PLATFORM_TYPE_REDWOOD_FSL, "Redwood_FSL" }, + {PLATFORM_TYPE_HUDSON32I_GA, "Hudson32i" }, + {PLATFORM_TYPE_SPRUCE, "Spruce" }, + {PLATFORM_TYPE_CYPRESS_GA1, "Cypress_GA1" }, + {PLATFORM_TYPE_CYPRESS_GA2, "Cypress_GA2" }, + {PLATFORM_TYPE_CYPRESS_BAI, "Cypress_BAI" }, + {PLATFORM_TYPE_TAHOE, "Tahoe" }, + {PLATFORM_TYPE_SEQUOIA_GA, "Sequoia_GA" }, + {PLATFORM_TYPE_LAVENDER_GA, "Lavender_GA" }, + {PLATFORM_TYPE_LAVENDER_ONL, "Lavender_ONL" }, + {PLATFORM_TYPE_COTTONWOOD_RANGELEY, "Cottonwood_RANGELEY" }, + {PLATFORM_TYPE_MAPLE, "Maple" }, +}; + + +/* ========================================== + * Magnolia Layout configuration + * ========================================== + */ +#ifdef SWPS_MAGNOLIA +unsigned magnolia_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s magnolia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAGINOLIA_NAB, { {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 */ + }, + {1, IOEXP_TYPE_MAGINOLIA_NAB, { {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 */ + }, + {2, IOEXP_TYPE_MAGINOLIA_NAB, { {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 */ + }, + {3, IOEXP_TYPE_MAGINOLIA_4AB, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander 4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf0, 0xff}, {0xf0, 0xff}, }, }, /* addr[1] = I/O Expander 4 B */ + }, + {4, IOEXP_TYPE_MAGINOLIA_NAB, { {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 */ + }, + {5, IOEXP_TYPE_MAGINOLIA_NAB, { {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 */ + }, + {6, IOEXP_TYPE_MAGINOLIA_7AB, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[1] = I/O Expander 7 B */ + }, +}; + +struct inv_port_layout_s magnolia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 16} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 15} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 14} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 13} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 24} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 23} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 22} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 21} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 28} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 27} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 26} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 25} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 32} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 31} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 30} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 29} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 48} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 47} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 46} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 45} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 52} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 51} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 50} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 49} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 56} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 55} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 54} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 53} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 60} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 59} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 58} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 57} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 64} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 63} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 62} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 61} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 68} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 67} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 66} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 65} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 72} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 71} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 70} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 69} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 76} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 75} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 74} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 73} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Redwood Layout configuration + * ========================================== + */ +#ifdef SWPS_REDWOOD +unsigned redwood_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +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 + + +/* ========================================== + * Hudson32i Layout configuration + * ========================================== + */ +#ifdef SWPS_HUDSON32I_GA +unsigned hudsin32iga_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s hudson32iga_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_HUDSON32IGA_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */ + }, + {1, IOEXP_TYPE_HUDSON32IGA_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */ + }, + {2, IOEXP_TYPE_HUDSON32IGA_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */ + }, + {3, IOEXP_TYPE_HUDSON32IGA_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */ + }, +}; + +struct inv_port_layout_s hudson32iga_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 1, 2, 3, 4} }, + { 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 5, 6, 7, 8} }, + { 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 9, 10, 11, 12} }, + { 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 13, 14, 15, 16} }, + { 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 17, 18, 19, 20} }, + { 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 21, 22, 23, 24} }, + { 6, 12, 0, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 25, 26, 27, 28} }, + { 7, 13, 0, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 29, 30, 31, 32} }, + { 8, 14, 1, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 33, 34, 35, 36} }, + { 9, 15, 1, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 37, 38, 39, 40} }, + {10, 16, 1, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 41, 42, 43, 44} }, + {11, 17, 1, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 45, 46, 47, 48} }, + {12, 18, 1, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 49, 50, 51, 52} }, + {13, 19, 1, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 53, 54, 55, 56} }, + {14, 20, 1, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 57, 58, 59, 60} }, + {15, 21, 1, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 61, 62, 63, 64} }, + {16, 22, 2, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 65, 66, 67, 68} }, + {17, 23, 2, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 69, 70, 71, 72} }, + {18, 24, 2, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 73, 74, 75, 76} }, + {19, 25, 2, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + {20, 26, 2, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + {21, 27, 2, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 85, 86, 87, 88} }, + {22, 28, 2, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 89, 90, 91, 92} }, + {23, 29, 2, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 93, 94, 95, 96} }, + {24, 30, 3, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + {25, 31, 3, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + {26, 32, 3, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + {27, 33, 3, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, + {28, 34, 3, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {113,114,115,116} }, + {29, 35, 3, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {117,118,119,120} }, + {30, 36, 3, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {121,122,123,124} }, + {31, 37, 3, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Spruce Layout configuration + * ========================================== + */ +#ifdef SWPS_SPRUCE +unsigned spruce_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s spruce_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SPRUCE_7AB, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[2] = I/O Expander 7B */ + }, +}; + +struct inv_port_layout_s spruce_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + { 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + { 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + { 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + { 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + { 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (Inventec version [Up->Down]) + * ========================================== + */ +#ifdef SWPS_CYPRESS_GA1 +unsigned cypress_ga1_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; + +struct inv_ioexp_layout_s cypress_ga1_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_ga1_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (Inventec version [Down->Up]) + * ========================================== + */ +#ifdef SWPS_CYPRESS_GA2 +unsigned cypress_ga2_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; + +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 + + +/* ========================================== + * Cypress Layout configuration (BaiDu version) + * ========================================== + */ +#ifdef SWPS_CYPRESS_BAI +unsigned cypress_b_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; + +struct inv_ioexp_layout_s cypress_b_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_b_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 2, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 4, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 6, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 8, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + {10, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {12, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {14, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {16, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {18, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {20, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {22, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {24, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {26, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {28, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {30, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {32, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {34, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {36, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {38, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {40, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {42, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {44, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {46, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {48, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {50, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {52, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {54, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Redwood_fsl Layout configuration + * ========================================== + */ +#ifdef SWPS_REDWOOD_FSL +unsigned redwood_fsl_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s redwood_fsl_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_fsl_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 + + +/* ========================================== + * Tahoe Layout configuration + * ========================================== + */ +#ifdef SWPS_TAHOE +unsigned tahoe_gpio_rest_mux = MUX_RST_GPIO_249_PCA9548; + +struct inv_ioexp_layout_s tahoe_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_TAHOE_6ABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[0] = I/O Expander 6 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[1] = I/O Expander 6 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {1, IOEXP_TYPE_TAHOE_5A, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[0] = I/O Expander 5 A */ + }, +}; + + +struct inv_port_layout_s tahoe_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 12, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + { 1, 11, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + { 2, 22, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + { 3, 21, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + { 4, 24, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} }, + { 5, 23, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + { 6, 18, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} }, + { 7, 17, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} }, + { 8, 20, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} }, + { 9, 19, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} }, +}; +#endif + + +/* ========================================== + * Sequoia Layout configuration + * ========================================== + */ +#ifdef SWPS_SEQUOIA +unsigned sequoia_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; + +struct inv_ioexp_layout_s sequoia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { {1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + {1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + +struct inv_port_layout_s sequoia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 9, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 1, 10, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 2, 11, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 3, 12, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 4, 13, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + { 5, 14, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 6, 15, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + { 7, 16, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + { 8, 17, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + { 9, 18, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {10, 19, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {11, 20, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {12, 21, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} }, + {13, 22, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} }, + {14, 23, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121, 122, 123, 124} }, + {15, 24, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} }, + {16, 25, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {137, 138, 139, 140} }, + {17, 26, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {129, 130, 131, 132} }, + {18, 27, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {153, 154, 155, 156} }, + {19, 28, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {145, 146, 147, 148} }, + {20, 29, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {169, 170, 171, 172} }, + {21, 30, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {161, 162, 163, 164} }, + {22, 31, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {185, 186, 187, 188} }, + {23, 32, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {177, 178, 179, 180} }, + {24, 33, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {201, 202, 203, 204} }, + {25, 34, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {193, 194, 195, 196} }, + {26, 35, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {217, 218, 219, 220} }, + {27, 36, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {209, 210, 211, 212} }, + {28, 37, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {233, 234, 235, 236} }, + {29, 38, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {225, 226, 227, 228} }, + {30, 39, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {249, 250, 251, 252} }, + {31, 40, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {241, 242, 243, 244} }, + {32, 44, 4, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + {33, 43, 4, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + {34, 42, 4, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + {35, 41, 4, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + {36, 48, 4, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {37, 47, 4, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {38, 46, 4, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {39, 45, 4, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {40, 52, 5, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {41, 51, 5, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {42, 50, 5, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {43, 49, 5, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {44, 56, 5, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} }, + {45, 55, 5, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} }, + {46, 54, 5, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125, 126, 127, 128} }, + {47, 53, 5, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117, 118, 119, 120} }, + {48, 60, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {141, 142, 143, 144} }, + {49, 59, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {133, 134, 135, 136} }, + {50, 58, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {157, 158, 159, 160} }, + {51, 57, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {149, 150, 151, 152} }, + {52, 64, 6, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {173, 174, 175, 176} }, + {53, 63, 6, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {165, 166, 167, 168} }, + {54, 62, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {189, 190, 191, 192} }, + {55, 61, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {181, 182, 183, 184} }, + {56, 68, 7, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {205, 206, 207, 208} }, + {57, 67, 7, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {197, 198, 199, 200} }, + {58, 66, 7, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {221, 222, 223, 224} }, + {59, 65, 7, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {213, 214, 215, 216} }, + {60, 72, 7, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {237, 238, 239, 240} }, + {61, 71, 7, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {229, 230, 231, 232} }, + {62, 70, 7, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {253, 254, 255, 256} }, + {63, 69, 7, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {245, 246, 247, 248} }, +}; +#endif + + +/* ========================================== + * Lavender Layout configuration + * ========================================== + */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA) +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL) +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; +#endif + +#ifdef SWPS_LAVENDER +struct inv_ioexp_layout_s lavender_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { { 1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + { 1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { { 2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + { 2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + { 2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { { 3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + { 3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + { 3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { { 4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + { 4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + { 4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { { 9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + { 9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + { 9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {11, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {11, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {11, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {12, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {12, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {12, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, + {8, IOEXP_TYPE_LAVENDER_P65, { { 5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xF6, 0xff}, {0xF8, 0xff}, }, }, /* addr[0] = I/O Expander CPU */ + }, +}; + + +struct inv_port_layout_s lavender_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 17, 0, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {188, 189, 190, 191} }, + { 1, 18, 0, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {184, 185, 186, 187} }, + { 2, 19, 0, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {180, 181, 182, 183} }, + { 3, 20, 0, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {176, 177, 178, 179} }, + { 4, 21, 0, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {172, 173, 174, 175} }, + { 5, 22, 0, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {168, 169, 170, 171} }, + { 6, 23, 0, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {164, 165, 166, 167} }, + { 7, 24, 0, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {160, 161, 162, 163} }, + { 8, 25, 1, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {156, 157, 158, 159} }, + { 9, 26, 1, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {152, 153, 154, 155} }, + {10, 27, 1, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {148, 149, 150, 151} }, + {11, 28, 1, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {144, 145, 146, 147} }, + {12, 29, 1, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {140, 141, 142, 143} }, + {13, 30, 1, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {136, 137, 138, 139} }, + {14, 31, 1, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {132, 133, 134, 135} }, + {15, 32, 1, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {128, 129, 130, 131} }, + {16, 33, 2, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 0, 1, 2, 3} }, + {17, 34, 2, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 4, 5, 6, 7} }, + {18, 35, 2, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 8, 9, 10, 11} }, + {19, 36, 2, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 12, 13, 14, 15} }, + {20, 37, 2, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 16, 17, 18, 19} }, + {21, 38, 2, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 20, 21, 22, 23} }, + {22, 39, 2, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 24, 25, 26, 27} }, + {23, 40, 2, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 28, 29, 30, 31} }, + {24, 41, 3, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 32, 33, 34, 35} }, + {25, 42, 3, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 36, 37, 38, 39} }, + {26, 43, 3, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 40, 41, 42, 43} }, + {27, 44, 3, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 44, 45, 46, 47} }, + {28, 45, 3, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 48, 49, 50, 51} }, + {29, 46, 3, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 52, 53, 54, 55} }, + {30, 47, 3, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 56, 57, 58, 59} }, + {31, 48, 3, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 60, 61, 62, 63} }, + {32, 49, 4, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {256, 257, 258, 259} }, + {33, 50, 4, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {260, 261, 262, 263} }, + {34, 51, 4, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {264, 265, 266, 267} }, + {35, 52, 4, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {268, 269, 270, 271} }, + {36, 53, 4, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {272, 273, 274, 275} }, + {37, 54, 4, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {276, 277, 278, 279} }, + {38, 55, 4, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {280, 281, 282, 283} }, + {39, 56, 4, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {284, 285, 286, 287} }, + {40, 57, 5, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {288, 289, 290, 291} }, + {41, 58, 5, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {292, 293, 294, 295} }, + {42, 59, 5, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {296, 297, 298, 299} }, + {43, 60, 5, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {300, 301, 302, 303} }, + {44, 61, 5, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {304, 305, 306, 307} }, + {45, 62, 5, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {308, 309, 310, 311} }, + {46, 63, 5, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {312, 313, 314, 315} }, + {47, 64, 5, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {316, 317, 318, 319} }, + {48, 65, 6, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {444, 445, 446, 447} }, + {49, 66, 6, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {440, 441, 442, 443} }, + {50, 67, 6, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {436, 437, 438, 439} }, + {51, 68, 6, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {432, 433, 434, 435} }, + {52, 69, 6, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {428, 429, 430, 431} }, + {53, 70, 6, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {424, 425, 426, 427} }, + {54, 71, 6, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {420, 421, 422, 423} }, + {55, 72, 6, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {416, 417, 418, 419} }, + {56, 73, 7, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {412, 413, 414, 415} }, + {57, 74, 7, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {408, 409, 410, 411} }, + {58, 75, 7, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {404, 405, 406, 407} }, + {59, 76, 7, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {400, 401, 402, 403} }, + {60, 77, 7, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {396, 397, 398, 399} }, + {61, 78, 7, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {392, 393, 394, 395} }, + {62, 79, 7, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {388, 389, 390, 391} }, + {63, 80, 7, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {384, 385, 386, 387} }, + {64, 5, 8, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 64, 65, 66, 67} }, +}; +#endif + +/* =========================================================== + * Cottonwood Layout configuration Rangeley (Rangeley CPU board) + * =========================================================== + */ +#ifdef SWPS_COTTONWOOD_RANGELEY +unsigned cottonwood_rangeley_gpio_rest_mux = MUX_RST_GPIO_500_PAC9548; + +struct inv_ioexp_layout_s cottonwood_rangeley_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, CPLD_TYPE_COTTONWOOD,{ {1, 0x55, {22, 23, 24, 25}, {22, 23, 24, 25}, {-1, -1, -1, -1}, {0xee, 0xee, 0x99, 0x99}, {0x00, 0x00, 0x00, 0x00}, }, + }, + }, +}; + + +struct inv_port_layout_s cottonwood_rangeley_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHI_TYPE / LANE_ID */ + { 0, 2, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 75} }, + { 1, 3, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 77} }, + { 2, 4, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 79} }, + { 3, 5, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, +}; +#endif + +/* =========================================================== + * Maple Layout configuration + * =========================================================== + */ +#ifdef SWPS_MAPLE +unsigned maple_gpio_rest_mux = 249; + +struct inv_ioexp_layout_s maple_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAPLE_0ABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_MAPLE_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_MAPLE_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_MAPLE_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_MAPLE_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_MAPLE_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_MAPLE_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, +}; + +struct inv_port_layout_s maple_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 1} }, + { 1, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 2} }, + { 2, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 3} }, + { 3, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 4} }, + { 4, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 5} }, + { 5, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 6} }, + { 6, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 7} }, + { 7, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 8} }, + { 8, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 13} }, + { 9, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 14} }, + {10, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 15} }, + {11, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 16} }, + {12, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 21} }, + {13, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 22} }, + {14, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 23} }, + {15, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 24} }, + {16, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 29} }, + {17, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 30} }, + {18, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 31} }, + {19, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 32} }, + {20, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 33} }, + {21, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 34} }, + {22, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 35} }, + {23, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 36} }, + {24, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 41} }, + {25, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 42} }, + {26, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 43} }, + {27, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 44} }, + {28, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 49} }, + {29, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 50} }, + {30, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 51} }, + {31, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 52} }, + {32, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 57} }, + {33, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 58} }, + {34, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 59} }, + {35, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 60} }, + {36, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 61} }, + {37, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 62} }, + {38, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 63} }, + {39, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 64} }, + {40, 58, 6, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 65} }, + {41, 59, 6, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 66} }, + {42, 60, 6, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 67} }, + {43, 61, 6, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 68} }, + {44, 62, 6, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 69} }, + {45, 63, 6, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 70} }, + {46, 64, 6, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 71} }, + {47, 65, 6, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 72} }, + {48, 10, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 77, 78, 79, 80} }, + {49, 11, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 85, 86, 87, 88} }, + {50, 12, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 93, 94, 95, 96} }, + {51, 13, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 97, 98, 99,100} }, + {52, 14, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {105,106,107,108} }, + {53, 15, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {113,114,115,116} }, + {54, 16, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {121,122,123,124} }, + {55, 17, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {125,126,127,128} }, +}; +#endif + +#endif /* INV_SWPS_H */ + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/io_expander.c new file mode 100644 index 000000000000..4564b5855fd8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/io_expander.c @@ -0,0 +1,2046 @@ +#include +#include +#include "io_expander.h" + +static struct ioexp_obj_s *ioexp_head_p = NULL; +static struct ioexp_obj_s *ioexp_tail_p = NULL; + + +/* ========== Register IOEXP layout ========== + */ +struct ioexp_map_s ioexp_map_magnolia_nab = { + + .chip_amount = 2, + .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_magnolia_4ab = { + + .chip_amount = 2, + .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, 0, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 0, 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, 1, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 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_magnolia_7ab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {1, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {1, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {1, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 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) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 2}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 3}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 1, 7}, /* 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) */ + }, +}; + + +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) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 0, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 0, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 0, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 0, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 0, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 0, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 0, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 1, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 1, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 1, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 1, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 1, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 1, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 1, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +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) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(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) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_5a = { + + .chip_amount = 1, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_6abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 0}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 3}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 0}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + {2, 1, 5}, /* map_present[8] = MOD_ABS_PORT(X+8) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {1, 0, 1}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 6}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 1, 3}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {2, 0, 1}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {2, 0, 6}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + {2, 1, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 2}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 7}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 1, 4}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {2, 0, 2}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {2, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + {2, 1, 4}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+8) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {1, 0, 0}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 0, 5}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 2}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {2, 0, 0}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {2, 0, 5}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + {2, 1, 2}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_sequoia_nabc = { + + .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, 1, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {0, 1, 6}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {0, 1, 7}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 3}, /* 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, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_lavender_p65 = { + + .chip_amount = 1, + .data_width = 1, + + .map_present = { {0, 0, 4}, }, /* map_present[0] = MOD_ABS_PORT(X) */ + .map_reset = { {0, 0, 1}, }, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + .map_lpmod = { {0, 0, 2}, }, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + .map_modsel = { {0, 0, 0}, }, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ +}; + + +struct ioexp_map_s cpld_map_cottonwood = { + + .chip_amount = 1, + .data_width = 4, + + .map_present = { {0, 2, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 2, 4}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 3, 0}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 3, 4}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + }, + .map_tx_disable = { {0, 0, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 4}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 4}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + }, + .map_tx_fault = { {0, 2, 2}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 2, 6}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 3, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 3, 6}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + }, + .map_rxlos = { {0, 2, 1}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 2, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 3, 1}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 3, 5}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + }, + .map_hard_rs0 = { {0, 0, 2}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {0, 0, 6}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {0, 1, 2}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {0, 1, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + }, + .map_hard_rs1 = { {0, 0, 2}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {0, 0, 6}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {0, 1, 2}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {0, 1, 6}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + }, +}; + +struct ioexp_map_s ioexp_map_maple_0abc = { + + .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, 1, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + {0, 1, 6}, /* map_reset[6] = QRESET_QSFP_N_P(X+6) */ + {0, 1, 7}, /* map_reset[7] = QRESET_QSFP_N_P(X+7) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP_P(X+7) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP_N_P(X+6) */ + {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP_N_P(X+7) */ + }, +}; + +struct ioexp_map_s ioexp_map_maple_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) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_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_check_by_mode(struct ioexp_obj_s *self){ + + switch (self->mode){ + case IOEXP_MODE_DIRECT: + return self->fsm_4_direct(self); + + case IOEXP_MODE_POLLING: + if (self->state >= 0){ + return 0; + } + switch (self->state){ + case STATE_IOEXP_INIT: + return ERR_IOEXP_UNINIT; + case STATE_IOEXP_ABNORMAL: + return ERR_IOEXP_ABNORMAL; + default: + return ERR_IOEXP_NOSTATE; + } + break; + + default: + break; + } + SWPS_ERR("%s: Exception occurs. :%d \n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +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; + + /* Check and get address */ + err_code = _common_check_by_mode(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; + + /* Check and get address */ + err_code = _common_check_by_mode(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){ + /* [Transmit Fault (Tx_Fault)] + * A catastrophic laser fault will activate the transmitter signal, + * TX_FAULT, and disable the laser. This signal is an open collector + * output (pull-up required on the host board). A low signal indicates + * normal laser operation and a high signal indicates a fault. The + * TX_FAULT will be latched high when a laser fault occurs and is + * cleared by toggling the TX_DISABLE input or power cycling the + * transceiver. The transmitter fault condition can also be monitored + * via the two-wire serial interface. + * (address A2, byte 110, bit 2). + * + * 0: Normal + * 1: Abnormal + */ + 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_get_hard_rs0(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + "common_get_hard_rs0"); +} + + +int +common_get_hard_rs1(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + "common_get_hard_rs1"); +} + + +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 +common_set_hard_rs0(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + input_val, + "common_set_hard_rs0"); +} + + +int +common_set_hard_rs1(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + input_val, + "common_set_hard_rs1"); +} + + +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; +} + + +int +fake_ioexp_init(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_ioexp_update(struct ioexp_obj_s *self){ + return 1; +} + + +int +fake_update_func(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_get_func(struct ioexp_obj_s *self, + int virt_offset){ + SWPS_WARN("Someone called fake_get_func\n"); + return -1; +} + +int +fake_set_func(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + SWPS_WARN("Someone called fake_set_func\n"); + return -1; +} + + +/* ========== 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) { + 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++){ + + /* [Desc] Skip the setup default value behavior + [Note] Setup default value = -1 if you don't want to write the value to IOEXP or CPLD + */ + if(addr_p->write_offset[offset] < 0){ + SWPS_DEBUG("skip a write_offset <%d>\n", addr_p->conf_offset[offset]); + continue; + } + 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; + + case IOEXP_MODE_POLLING: + /* Check system and channel is ready */ + if (self->state == STATE_IOEXP_INIT){ + if (!_is_channel_ready(self)){ + self->state = STATE_IOEXP_INIT; + SWPS_WARN("%s: IOEXP:%d channel not ready.\n", + __func__, self->ioexp_id); + return 0; + } + } + /* Execute initial callback */ + 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; +} + + +int +common_ioexp_fsm_4_polling(struct ioexp_obj_s *self){ + + int result_val, i, show_e; + int fail_retry = 3; + char *func_name = "common_ioexp_fsm_4_polling"; + +#ifdef DEBUG_SWPS + show_e = 1; +#else + show_e = 0; +#endif + + 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; + } + /* Case: System (Channel) not ready */ + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, wait and retry */ + return 0; + } + /* Case: Initial done */ + SWPS_INFO("IOEXP-%d: initial done. :%d\n", + self->ioexp_id, self->ioexp_type); + return result_val; + + case STATE_IOEXP_NORMAL: + /* Retry mechanism for case of i2c topology not stable */ + for (i=0; iupdate_all(self, show_e, func_name); + if (result_val >= 0) { + self->state = STATE_IOEXP_NORMAL; + return 0; + } + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: detect I2C crash :%d\n", + __func__, self->ioexp_id); + break; + } + SWPS_DEBUG("IOEXP-%d: unstable :%d\n", + self->ioexp_id, result_val); + } + SWPS_INFO("IOEXP-%d: NORMAL -> ABNORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_e, func_name); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_INFO("IOEXP-%d: ABNORMAL -> NORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("IOEXP-%d: Exception occurs :%d\n", + self->ioexp_id, self->state); + return ERR_IOEXP_UNEXCPT; +} + + +/* ========== Object private functions for check & update ========== + */ +int +common_ioexp_check(struct ioexp_obj_s *self){ + + int result; + + if (self->mode != IOEXP_MODE_POLLING){ + SWPS_ERR("%s: not polling mode :%d\n", + __func__, self->mode); + return ERR_IOEXP_NOTSUPPORT; + } + mutex_lock(&self->lock); + result = self->fsm_4_polling(self); + mutex_unlock(&self->lock); + return result; +} + + +/* ========== Functions for Factory pattern ========== + */ +static struct ioexp_map_s * +get_ioexp_map(int ioexp_type){ + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + return &ioexp_map_magnolia_nab; + case IOEXP_TYPE_MAGINOLIA_4AB: + return &ioexp_map_magnolia_4ab; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + return &ioexp_map_magnolia_7ab; + case IOEXP_TYPE_REDWOOD_P01P08: + return &ioexp_map_redwood_p01p08_p17p24; + case IOEXP_TYPE_REDWOOD_P09P16: + return &ioexp_map_redwood_p09p16_p25p32; + case IOEXP_TYPE_HUDSON32IGA_P01P08: + return &ioexp_map_hudson32iga_p01p08_p17p24; + case IOEXP_TYPE_HUDSON32IGA_P09P16: + return &ioexp_map_hudson32iga_p09p16_p25p32; + case IOEXP_TYPE_CYPRESS_NABC: + return &ioexp_map_cypress_nabc; + case IOEXP_TYPE_CYPRESS_7ABC: + return &ioexp_map_cypress_7abc; + case IOEXP_TYPE_TAHOE_5A: + return &ioexp_map_tahoe_5a; + case IOEXP_TYPE_TAHOE_6ABC: + return &ioexp_map_tahoe_6abc; + case IOEXP_TYPE_SEQUOIA_NABC: + return &ioexp_map_sequoia_nabc; + case IOEXP_TYPE_LAVENDER_P65: + return &ioexp_map_lavender_p65; + case CPLD_TYPE_COTTONWOOD: + return &cpld_map_cottonwood; + case IOEXP_TYPE_MAPLE_0ABC: + return &ioexp_map_maple_0abc; + case IOEXP_TYPE_MAPLE_NABC: + return &ioexp_map_maple_nabc; + 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_POLLING: /* Direct access device mode */ + case IOEXP_MODE_DIRECT: /* Polling mode, read from cache */ + 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; + } + /* Setup mapping structure */ + self->ioexp_map_p = kzalloc(sizeof(*ioexp_map_p), GFP_KERNEL); + if (!(self->ioexp_map_p)) { + SWPS_ERR("%s: kzalloc ioexp_map_p fail\n", __func__); + return -1; + } + memcpy(self->ioexp_map_p, ioexp_map_p, sizeof(*ioexp_map_p)); + /* Setup attributes */ + self->ioexp_id = ioexp_id; + self->ioexp_type = ioexp_type; + 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, + int chip_amount){ + struct ioexp_addr_s *tmp_p; + if (!addr_map_p){ + SWPS_ERR("%s: map is null\n", __func__); + return -1; + } + tmp_p = kzalloc((sizeof(*addr_map_p) * chip_amount), GFP_KERNEL); + if (!tmp_p){ + SWPS_ERR("%s: kzalloc fail.\n", __func__); + return -1; + } + memcpy(tmp_p, addr_map_p, (sizeof(*addr_map_p) * chip_amount)); + self->ioexp_map_p->map_addr = tmp_p; + + return 0; +} + + +static int +setup_ioexp_public_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case CPLD_TYPE_COTTONWOOD: + 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->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = 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; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + return 0; + case IOEXP_TYPE_CYPRESS_NABC: + case IOEXP_TYPE_MAPLE_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->get_hard_rs0 = common_get_hard_rs0; + self->get_hard_rs1 = common_get_hard_rs1; + 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; + self->set_hard_rs0 = common_set_hard_rs0; + self->set_hard_rs1 = common_set_hard_rs1; + return 0; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + case IOEXP_TYPE_MAPLE_0ABC: + 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->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = ioexp_get_not_support; + 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; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + 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_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_NABC: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + case CPLD_TYPE_COTTONWOOD: + case IOEXP_TYPE_MAPLE_NABC: + case IOEXP_TYPE_MAPLE_0ABC: + self->init = common_ioexp_init; + self->check = common_ioexp_check; + self->update_all = common_ioexp_update_all; + self->fsm_4_direct = common_ioexp_fsm_4_direct; + self->fsm_4_polling = common_ioexp_fsm_4_polling; + 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++){ + + /* [Desc] Skip the setup config value behavior + [Note] Setup config value = -1 if you don't want to write the value to IOEXP or CPLD + */ + if(addr_p->conf_offset[offset] < 0){ + SWPS_DEBUG("skip a config_offset <%d>\n", addr_p->conf_offset[offset]); + continue; + } + 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, ioexp_map_p->chip_amount) < 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; + if (ioexp_curr_p->ioexp_map_p) { + if (ioexp_curr_p->ioexp_map_p->map_addr) { + kfree(ioexp_curr_p->ioexp_map_p->map_addr); + } + kfree(ioexp_curr_p->ioexp_map_p); + } + + 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__); +} + + +int +check_ioexp_objs(void){ + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while (ioexp_curr_p){ + if ( (ioexp_curr_p->check(ioexp_curr_p)) < 0){ + SWPS_INFO("check IOEXP-%d fail! :%d\n", + ioexp_curr_p->ioexp_id, ioexp_curr_p->ioexp_type); + return -1; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} + + +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; +} + + +void +unlock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_unlock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } +} + + +int +lock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_lock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} + + +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} + + +static int +_scan_channel_tier_1(int force, + int show_err) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + int ready = 0; + + if (!ioexp_curr_p) { + goto err_scan_tier_1_channel; + } + while(ioexp_curr_p) { + ready = _is_channel_ready(ioexp_curr_p); + if ((!ready) && (!force)) { + goto err_scan_tier_1_channel; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; + +err_scan_tier_1_channel: + if (show_err) { + if (ioexp_curr_p) { + SWPS_INFO("%s: IOEXP-%d fail\n", __func__, ioexp_curr_p->ioexp_id); + } else { + SWPS_INFO("%s: IOEXP is null.\n", __func__); + } + } + return -1; +} + + +static int +_scan_channel_tier_1_single(void) { + + int ret = 0; + int chan_id = 0; + int fake_cid = 0; + int fake_offs = 0; + int fake_addr = 0; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + + if (ioexp_head_p->ioexp_id != ioexp_tail_p->ioexp_id) { + return 0; + } + /* Setup i2c_client */ + chan_id = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chan_id; + fake_addr = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chip_addr; + adap = i2c_get_adapter((chan_id + 1)); + if(!adap){ + SWPS_INFO("%s: Can not get adap!\n", __func__); + return 0; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + SWPS_INFO("%s: Can not kzalloc client!\n", __func__); + return 0; + } + client->adapter = adap; + client->addr = fake_addr; + /* Fouce move ioexp ptr to next */ + ret = i2c_smbus_read_byte_data(client, fake_offs); + SWPS_DEBUG("%s: move ioexp_ptr done. :%d\n", __func__, ret); + kfree(client); + return 1; +} + + +int +resync_channel_tier_1(void) { + + char *emsg = "ERR"; + + if (!ioexp_head_p) { + emsg = "ioexp_head_p is NULL"; + goto err_resync_ioexp_status_1; + } + /* Run all */ + if (ioexp_head_p->ioexp_id == ioexp_tail_p->ioexp_id) { + _scan_channel_tier_1_single(); + } else { + _scan_channel_tier_1(1, 0); + } + /* Check all */ + if (_scan_channel_tier_1(0, 1) < 0) { + emsg = "resync tier-1 channel fail"; + goto err_resync_ioexp_status_1; + } + return 0; + +err_resync_ioexp_status_1: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/io_expander.h new file mode 100644 index 000000000000..1af909e2466a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/io_expander.h @@ -0,0 +1,187 @@ +/* + * 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. + */ + +#ifndef IO_EXPANDER_H +#define IO_EXPANDER_H + +#include + + +/* IOEXP type define (SFP series) */ +#define IOEXP_TYPE_MAGINOLIA_NAB (10101) +#define IOEXP_TYPE_MAGINOLIA_4AB (10102) +#define IOEXP_TYPE_CYPRESS_NABC (10103) +#define IOEXP_TYPE_MAPLE_NABC (10104) + +/* IOEXP type define (QSFP series) */ +#define IOEXP_TYPE_MAGINOLIA_7AB (10201) +#define IOEXP_TYPE_REDWOOD_P01P08 (10202) +#define IOEXP_TYPE_REDWOOD_P09P16 (10203) +#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204) +#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205) +#define IOEXP_TYPE_SPRUCE_7AB (10206) +#define IOEXP_TYPE_CYPRESS_7ABC (10207) +#define IOEXP_TYPE_TAHOE_5A (10208) +#define IOEXP_TYPE_TAHOE_6ABC (10209) +#define IOEXP_TYPE_SEQUOIA_NABC (10210) +#define IOEXP_TYPE_LAVENDER_P65 (10211) +#define IOEXP_TYPE_MAPLE_0ABC (10212) + +/* CPLD type define */ +#define CPLD_TYPE_COTTONWOOD (10301) + +/* IOEXP mode define */ +#define IOEXP_MODE_POLLING (19000) +#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_ABNORMAL (-103) +#define ERR_IOEXP_NOSTATE (-104) +#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[10]; /* IOEXP for SFP / QSFP */ + struct ioexp_bitmap_s map_tx_disable[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_tx_fault[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_rxlos[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_reset[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_lpmod[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_modsel[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs0[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs1[10]; /* 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 (*get_hard_rs0)(struct ioexp_obj_s *self, int virt_offset); + int (*get_hard_rs1)(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); + int (*set_hard_rs0)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_hard_rs1)(struct ioexp_obj_s *self, int virt_offset, int input_val); + + /* =========================================== + * Object private functions + * =========================================== + */ + int (*init)(struct ioexp_obj_s *self); + int (*check)(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); + int (*fsm_4_polling)(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); +int check_ioexp_objs(void); +void clean_ioexp_objs(void); + +void unlock_ioexp_all(void); +int lock_ioexp_all(void); + +int check_channel_tier_1(void); +int resync_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/d6556/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/transceiver.c new file mode 100644 index 000000000000..6fe8f599fb48 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/transceiver.c @@ -0,0 +1,8389 @@ +/* + * 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 "io_expander.h" +#include "transceiver.h" + + +/* ========== Register EEPROM address mapping ========== + */ +struct eeprom_map_s eeprom_map_sfp = { + .addr_br =0x50, .page_br =-1, .offset_br =12, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =94, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =-1, .offset_connector =2, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =-1, .offset_diag_type =92 , .length_diag_type =1, + .addr_extbr =-1, .page_extbr =-1, .offset_extbr =-1, .length_extbr =-1, + .addr_ext_id =0x50, .page_ext_id =-1, .offset_ext_id =1, .length_ext_id =1, + .addr_id =0x50, .page_id =-1, .offset_id =0, .length_id =1, + .addr_len_sm =0x50, .page_len_sm =-1, .offset_len_sm =15, .length_len_sm =1, + .addr_len_smf =0x50, .page_len_smf =-1, .offset_len_smf =14, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =-1, .offset_len_om1 =17, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =-1, .offset_len_om2 =16, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =-1, .offset_len_om3 =19, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =-1, .offset_len_om4 =18, .length_len_om4 =1, + .addr_option =0x50, .page_option =-1, .offset_option =64, .length_option =2, + .addr_rate_id =0x50, .page_rate_id =-1, .offset_rate_id =13, .length_rate_id =1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =0x51, .page_rx_em =-1, .offset_rx_em =115, .length_rx_em =1, + .addr_rx_los =-1, .page_rx_los =-1, .offset_rx_los =-1, .length_rx_los =-1, + .addr_rx_power =0x51, .page_rx_power =-1, .offset_rx_power =104, .length_rx_power =2, + .addr_soft_rs0 =0x51, .page_soft_rs0 =-1, .offset_soft_rs0 =110, .length_soft_rs0 =1, + .addr_soft_rs1 =0x51, .page_soft_rs1 =-1, .offset_soft_rs1 =118, .length_soft_rs0 =1, + .addr_temp =0x51, .page_temp =-1, .offset_temp =96, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =-1, .offset_trancomp =3, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =-1, .offset_trancomp_ext =36, .length_trancomp_ext =1, + .addr_tx_bias =0x51, .page_tx_bias =-1, .offset_tx_bias =100, .length_tx_bias =2, + .addr_tx_disable =-1, .page_tx_disable =-1, .offset_tx_disable =-1, .length_tx_disable =-1, + .addr_tx_eq =0x51, .page_tx_eq =-1, .offset_tx_eq =114, .length_tx_eq =1, + .addr_tx_fault =-1, .page_tx_fault =-1, .offset_tx_fault =-1, .length_tx_fault =-1, + .addr_tx_power =0x51, .page_tx_power =-1, .offset_tx_power =102, .length_tx_power =2, + .addr_vendor_name =0x50, .page_vendor_name =-1, .offset_vendor_name =20, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =-1, .offset_vendor_pn =40, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =-1, .offset_vendor_rev =56, .length_vendor_rev =4, + .addr_vendor_sn =0x50, .page_vendor_sn =-1, .offset_vendor_sn =68, .length_vendor_sn =16, + .addr_voltage =0x51, .page_voltage =-1, .offset_voltage =98, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =-1, .offset_wavelength =60, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =-1, .page_rx_em =-1, .offset_rx_em =-1, .length_rx_em =-1, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =-1, .page_tx_eq =-1, .offset_tx_eq =-1, .length_tx_eq =-1, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp28 = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =0x50, .page_cdr =-1, .offset_cdr =98, .length_cdr =1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =0x50, .page_rx_am =3, .offset_rx_am =238, .length_rx_am =2, + .addr_rx_em =0x50, .page_rx_em =3, .offset_rx_em =236, .length_rx_em =2, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =0x50, .page_tx_eq =3, .offset_tx_eq =234, .length_tx_eq =2, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + + +/* ========== Utility Functions ========== + */ +static int +get_bit(uint8_t origin_byte, int bit_shift) { + return (int)((origin_byte >> bit_shift) & 0x1); +} + +static int +transform_word_to_int(uint8_t hight_byte, + uint8_t low_byte) { + return ((((int)hight_byte) << 8) + (int)low_byte); +} + +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 +_is_transvr_support_ctle(struct transvr_obj_s *self); + +static int +_transvr_init_handler(struct transvr_obj_s *self); + +int +_transvr_clean_handler(struct transvr_obj_s *self); + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self); + + +void +lock_transvr_obj(struct transvr_obj_s *self) { + + mutex_lock(&self->lock); + self->curr_page = VAL_TRANSVR_PAGE_FREE; +} + + +void +unlock_transvr_obj(struct transvr_obj_s *self) { + + self->curr_page = VAL_TRANSVR_PAGE_FREE; + mutex_unlock(&self->lock); +} + + +static int +_check_by_mode(struct transvr_obj_s *self, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + char *caller_name){ + + int return_val = ERR_TRANSVR_UNEXCPT; + + switch (self->mode){ + case TRANSVR_MODE_POLLING: + switch (self->state){ + case STATE_TRANSVR_CONNECTED: + goto ok_check_by_mode_1; + case STATE_TRANSVR_NEW: + case STATE_TRANSVR_INIT: + return ERR_TRANSVR_UNINIT; + case STATE_TRANSVR_DISCONNECTED: + return ERR_TRANSVR_UNPLUGGED; + case STATE_TRANSVR_UNEXCEPTED: + return ERR_TRANSVR_ABNORMAL; + case STATE_TRANSVR_ISOLATED: + return ERR_TRNASVR_BE_ISOLATED; + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + + case TRANSVR_MODE_DIRECT: + return_val = self->fsm_4_direct(self, caller_name); + if (return_val < 0){ + return return_val; + } + goto ok_check_by_mode_1; + + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + +ok_check_by_mode_1: + return attr_update_func(self, 0); + +err_check_by_mode_1: + SWPS_INFO("_check_by_mode: mode:%d state:%d\n", self->mode, self->state); + return ERR_TRANSVR_UNEXCPT; +} + + +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; +} + +/* +static int +_common_setup_password(struct transvr_obj_s *self, + int addr, + int page, + int offs, + uint8_t pwd[4], + int show_e) { + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, 4, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_setup_password; + } + for (i=0; i<4; i++) { + err = i2c_smbus_write_byte_data(self->i2c_client_p, + (offs + i), + pwd[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_setup_password; + } + } + return 0; + +err_common_setup_password: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} +*/ + +static int +_common_update_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + uint8_t *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_uint8_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_uint8_attr; + } + buf[i] = err; + } + return 0; + +err_common_update_uint8_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_int_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_int_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_int_attr; + } + buf[i] = (int)err; + } + return 0; + +err_common_update_int_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_INT_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_string_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + char buf[], + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_string_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_string_attr; + } + buf[i] = (char)err; + } + return 0; + +err_common_update_string_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = 'e'; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + uint8_t update, + uint8_t *buf, + char *caller, + int show_e){ + int len = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + if ((*buf) == update){ + return 0; + } + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + err = i2c_smbus_write_byte_data(self->i2c_client_p, + offset, + update); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + (*buf) = update; + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_array(struct transvr_obj_s *self, + int addr, + int page, + int offs, + int len, + uint8_t update[], + uint8_t buf[], + char *caller, + int show_e){ + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + for (i=0; ii2c_client_p, + (offs + i), + update[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + buf[i] = update[i]; + } + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, emsg, caller, err, i); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_attr_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_id, + self->eeprom_map_p->page_id, + self->eeprom_map_p->offset_id, + self->eeprom_map_p->length_id, + &(self->id), + "_common_update_attr_id", + show_err); +} + + +static int +_common_update_attr_extended_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_ext_id, + self->eeprom_map_p->page_ext_id, + self->eeprom_map_p->offset_ext_id, + self->eeprom_map_p->length_ext_id, + &(self->ext_id), + "_common_update_attr_extended_id", + show_err); +} + + +static int +_common_update_attr_connector(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_connector, + self->eeprom_map_p->page_connector, + self->eeprom_map_p->offset_connector, + self->eeprom_map_p->length_connector, + &(self->connector), + "_common_update_attr_connector", + show_err); +} + + +static int +_common_update_attr_transvr_comp(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp, + self->eeprom_map_p->page_trancomp, + self->eeprom_map_p->offset_trancomp, + self->eeprom_map_p->length_trancomp, + self->transvr_comp, + "_common_update_attr_transvr_comp", + show_err); +} + + +static int +_common_update_attr_transvr_comp_ext(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp_ext, + self->eeprom_map_p->page_trancomp_ext, + self->eeprom_map_p->offset_trancomp_ext, + self->eeprom_map_p->length_trancomp_ext, + &(self->transvr_comp_ext), + "_common_update_attr_transvr_comp_ext", + show_err); +} + + +static int +_common_update_attr_vendor_name(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_name, + self->eeprom_map_p->page_vendor_name, + self->eeprom_map_p->offset_vendor_name, + self->eeprom_map_p->length_vendor_name, + self->vendor_name, + "_common_update_attr_vendor_name", + show_err); +} + + +static int +_common_update_attr_vendor_pn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_pn, + self->eeprom_map_p->page_vendor_pn, + self->eeprom_map_p->offset_vendor_pn, + self->eeprom_map_p->length_vendor_pn, + self->vendor_pn, + "_common_update_attr_vendor_pn", + show_err); +} + + +static int +_common_update_attr_vendor_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_rev, + self->eeprom_map_p->page_vendor_rev, + self->eeprom_map_p->offset_vendor_rev, + self->eeprom_map_p->length_vendor_rev, + self->vendor_rev, + "_common_update_attr_vendor_rev", + show_err); +} + + +static int +_common_update_attr_vendor_sn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_sn, + self->eeprom_map_p->page_vendor_sn, + self->eeprom_map_p->offset_vendor_sn, + self->eeprom_map_p->length_vendor_sn, + self->vendor_sn, + "_common_update_attr_vendor_sn", + show_err); +} + + +static int +_common_update_attr_br(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_br, + self->eeprom_map_p->page_br, + self->eeprom_map_p->offset_br, + self->eeprom_map_p->length_br, + &(self->br), + "_common_update_attr_br", + show_err); +} + + +static int +_common_update_attr_len_smf(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_smf, + self->eeprom_map_p->page_len_smf, + self->eeprom_map_p->offset_len_smf, + self->eeprom_map_p->length_len_smf, + &(self->len_smf), + "_common_update_attr_len_smf", + show_err); +} + + +static int +_common_update_attr_len_om1(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om1, + self->eeprom_map_p->page_len_om1, + self->eeprom_map_p->offset_len_om1, + self->eeprom_map_p->length_len_om1, + &(self->len_om1), + "_common_update_attr_len_om1", + show_err); +} + +static int +_common_update_attr_len_om2(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om2, + self->eeprom_map_p->page_len_om2, + self->eeprom_map_p->offset_len_om2, + self->eeprom_map_p->length_len_om2, + &(self->len_om2), + "_common_update_attr_len_om2", + show_err); +} + +static int +_common_update_attr_len_om3(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om3, + self->eeprom_map_p->page_len_om3, + self->eeprom_map_p->offset_len_om3, + self->eeprom_map_p->length_len_om3, + &(self->len_om3), + "_common_update_attr_len_om3", + show_err); +} + + +static int +_common_update_attr_len_om4(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om4, + self->eeprom_map_p->page_len_om4, + self->eeprom_map_p->offset_len_om4, + self->eeprom_map_p->length_len_om4, + &(self->len_om4), + "_common_update_attr_len_om4", + show_err); +} + + +static int +_common_update_attr_option(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_option, + self->eeprom_map_p->page_option, + self->eeprom_map_p->offset_option, + self->eeprom_map_p->length_option, + self->option, + "_common_update_attr_option", + show_err); +} + + +static int +_common_update_attr_comp_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_comp_rev, + self->eeprom_map_p->page_comp_rev, + self->eeprom_map_p->offset_comp_rev, + self->eeprom_map_p->length_comp_rev, + &(self->comp_rev), + "_common_update_attr_comp_rev", + show_err); +} + + +static int +_common_update_attr_diag_type(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_diag_type, + self->eeprom_map_p->page_diag_type, + self->eeprom_map_p->offset_diag_type, + self->eeprom_map_p->length_diag_type, + &(self->diag_type), + "_common_update_attr_diag_type", + show_err); +} + + +static int +_common_update_attr_wavelength(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_wavelength, + self->eeprom_map_p->page_wavelength, + self->eeprom_map_p->offset_wavelength, + self->eeprom_map_p->length_wavelength, + self->wavelength, + "_common_update_attr_wavelength", + show_err); +} + + +int +_common_get_option_value(struct transvr_obj_s *self, + int offset, + int bit_shift) { + /* SFP: + * - option[0] = A0h / 64 + * - option[1] = A0h / 65 + * QSFP: + * - option[0] = 00h / 193 + * - option[1] = 00h / 194 + * - option[2] = 00h / 195 + */ + return (self->option[offset] & (1 << bit_shift)); +} + + +static int +_sfp_update_attr_len_sm(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_sm, + self->eeprom_map_p->page_len_sm, + self->eeprom_map_p->offset_len_sm, + self->eeprom_map_p->length_len_sm, + &(self->len_sm), + "_common_update_attr_len_sm", + show_err); +} + + +static int +_sfp_update_attr_rate_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_rate_id, + self->eeprom_map_p->page_rate_id, + self->eeprom_map_p->offset_rate_id, + self->eeprom_map_p->length_rate_id, + &(self->rate_id), + "_sfp_update_attr_rate_id", + show_err); +} + + +static int +_sfp_update_attr_soft_rs0(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + self->eeprom_map_p->length_soft_rs0, + &(self->soft_rs0), + "_sfp_update_attr_soft_rs0", + show_err); +} + + +static int +_sfp_update_attr_soft_rs1(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + self->eeprom_map_p->length_soft_rs1, + &(self->soft_rs1), + "_sfp_update_attr_soft_rs1", + show_err); +} + + +int +_sfp_is_diag_support(struct transvr_obj_s *self){ + + uint8_t bit_mask = 0xC0; /* 1100 0000 */ + uint8_t en_val = 0x40; /* 0100 0000 */ + uint8_t checkval = (self->diag_type & bit_mask); + + if (checkval == en_val) { + return 1; + } + return 0; +} + + +static int +_sfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_sfp_update_attr_curr_temp", + show_err); +} + + +static int +_sfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_sfp_update_attr_curr_voltage", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_sfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_sfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_sfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_sfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_sfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_sfp_update_attr_rx_em", + show_err); +} + + +static int +_sfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_sfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_cdr(struct transvr_obj_s *self, + int show_err){ + if (self->type != TRANSVR_TYPE_QSFP_28){ + self->cdr = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + self->eeprom_map_p->length_cdr, + &(self->cdr), + "_common_update_attr_cdr", + show_err); +} + + +static int +_qsfg_update_attr_extbr(struct transvr_obj_s *self, + int show_err) { + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_extbr, + self->eeprom_map_p->page_extbr, + self->eeprom_map_p->offset_extbr, + self->eeprom_map_p->length_extbr, + &(self->extbr), + "_common_update_attr_extbr", + show_err); +} + + +static int +_qsfp_is_diag_support(struct transvr_obj_s *self, + int diag_type) { + /* Input Parm: diag_type + * => 1 : temperature + * => 2 : voltage + * => 3 : tx relate + * => 4 : rx relate + */ + uint8_t mask_b2 = 0x04; /* 0000 0100 */ + uint8_t mask_b3 = 0x08; /* 0000 1000 */ + + switch (diag_type) { + case 1: /* temperature */ + case 2: /* voltage */ + /* Direct access target, because of spec not defined */ + return 1; + case 3: + case 4: + /* [Note] + * Due to lot of transceiver vendor defined it not rigorously and + * consider of general support, we seem it as supported if there + * are bit-2 OR bit-3 defined by transceiver vendor. + */ + if ( ((self->diag_type & mask_b2) == mask_b2 ) || + ((self->diag_type & mask_b3) == mask_b3 ) ){ + return 1; + } + return 0; + default: + SWPS_INFO("%s: undefined diag_type:%d\n", + __func__, diag_type); + break; + } + return 0; +} + + +int +_qsfp_is_implement_tx_disable(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-4 + */ + int byte = 2; + int bit = 4; + return _common_get_option_value(self, byte, bit); +} + + +int +_qsfp_is_implement_tx_fault(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-3 + */ + int byte = 2; + int bit = 3; + return _common_get_option_value(self, byte, bit); +} + + +static int +_qsfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + int diag_type = 1; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_qsfp_update_attr_curr_temp", + show_err); +} + + +static int +_qsfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + int diag_type = 2; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_qsfp_update_attr_curr_voltage", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_qsfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_qsfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_qsfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 4; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_qsfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_qsfp_update_attr_soft_rx_los(struct transvr_obj_s *self, + int show_err){ + + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_los, + self->eeprom_map_p->page_rx_los, + self->eeprom_map_p->offset_rx_los, + self->eeprom_map_p->length_rx_los, + &(self->rx_los), + "_qsfp_update_attr_soft_rx_los", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_disable(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_disable(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_update_attr_soft_tx_disable", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_fault(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_fault(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_fault, + self->eeprom_map_p->page_tx_fault, + self->eeprom_map_p->offset_tx_fault, + self->eeprom_map_p->length_tx_fault, + &(self->tx_fault), + "_qsfp_update_attr_soft_tx_fault", + show_err); +} + + +static int +_qsfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_qsfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_rx_am(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + self->rx_am, + "_qsfp_update_attr_rx_am", + show_err); +} + + +static int +_qsfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_qsfp_update_attr_rx_em", + show_err); +} + + +int +_common_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = "err"; + + if (_common_update_attr_id(self, show_err) < 0) { + err_str = "_common_update_attr_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_extended_id(self, show_err) < 0) { + err_str = "_common_update_attr_extended_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_connector(self, show_err) < 0) { + err_str = "_common_update_attr_connector"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp_ext(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp_ext"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_name(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_name"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_pn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_pn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_rev(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_sn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_sn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_br(self, show_err) < 0) { + err_str = "_common_update_attr_br"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_smf(self, show_err) < 0) { + err_str = "_common_update_attr_len_smf"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om1(self, show_err) < 0) { + err_str = "_common_update_attr_len_om1"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om2(self, show_err) < 0) { + err_str = "_common_update_attr_len_om2"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om3(self, show_err) < 0) { + err_str = "_common_update_attr_len_om3"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om4(self, show_err) < 0) { + err_str = "_common_update_attr_len_om4"; + goto err_common_update_attr_all; + } + if (_common_update_attr_option(self, show_err) < 0) { + err_str = "_common_update_attr_option"; + goto err_common_update_attr_all; + } + if (_common_update_attr_comp_rev(self, show_err) < 0) { + err_str = "_common_update_attr_comp_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_diag_type(self, show_err) < 0) { + err_str = "_common_update_attr_diag_type"; + goto err_common_update_attr_all; + } + if (_common_update_attr_wavelength(self, show_err) < 0) { + err_str = "_common_update_attr_wavelength"; + goto err_common_update_attr_all; + } + return 0; + +err_common_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_sfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_len_sm(self, show_err) < 0) { + err_str = "_sfp_update_attr_len_sm"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_rate_id(self, show_err) < 0) { + err_str = "_sfp_update_attr_rate_id"; + goto err_sfp_update_attr_all; + } + if ((self->rate_id) > 0) { + if (_sfp_update_attr_soft_rs0(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs0"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_soft_rs1(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs1"; + goto err_sfp_update_attr_all; + } + } + return 0; + +err_sfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_qsfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_qsfp_update_attr_all; + } + if (_qsfg_update_attr_extbr(self, show_err) < 0) { + err_str = "_qsfg_update_attr_extbr"; + goto err_qsfp_update_attr_all; + } + if (self->type == TRANSVR_TYPE_QSFP_28) { + if (_qsfp_update_attr_cdr(self, 1) < 0) { + err_str = "_qsfp_update_attr_cdr"; + goto err_qsfp_update_attr_all; + } + } + return 0; + +err_qsfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +/* ========== Object functions for common type ========== + */ +int +_common_count_temp(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + int sign = 0; + int high = 0; + int low = 0; + int lmax = 8; + + /* Count high */ + sign = get_bit(high_byte,7); + SWP_BIT_CLEAR(high_byte, 7); + high = (int)high_byte; + if (sign == 1) { + high = 0 - high; + } + /* Count low */ + low = (get_bit(low_byte, 7) * 500); + low += (get_bit(low_byte, 6) * 250); + low += (get_bit(low_byte, 5) * 125); + low += (get_bit(low_byte, 4) * 62); + low = (low / 100); + /* Integrate High and Low */ + return snprintf(buf_p, lmax, "%d.%d\n", high, low); +} + + +int +_common_count_voltage(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note]: + * Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts. Practical + * considerations to be defined by transceiver manufacturer will + * tend to limit the actual bounds of the supply voltage measurement. + * Accuracy is vendor specific but must be better than 3% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. Note that in some transceivers, transmitter supply + * voltage and receiver supply voltage are isolated. In that case, + * only one supply is monitored. Refer to the device specification + * for more detail. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 100 uV (1mV=1000uV) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 Volt */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_tx_bias(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 2 uA (1mA=1000uA) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total*2) / 1000); + val_f = (((total*2) - (val_i*1000)) / 100); + /* Return Unit: 1 mA */ + return snprintf(buf_p, lmax, "%d.%01d\n", val_i, val_f); +} + + +int +_common_count_tx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_rx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_wavelength(struct transvr_obj_s *self, + uint8_t high_byte, + uint8_t low_byte) { + /* [Note] + * SFP : uint 1 um. + * QSFP: unit 0.05 um. + */ + int total = 0; + + total = transform_word_to_int(high_byte, low_byte); + switch (self->type) { + case TRANSVR_TYPE_SFP: + return total; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + return (total/20); + + default: + break; + } + return ERR_TRANSVR_UNDEFINED; +} + + +int +common_get_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_id, + "common_get_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->id; +} + + +int +common_get_ext_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "common_get_ext_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->ext_id; +} + + +int +common_get_connector(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_connector, + "common_get_connector"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->connector; +} + + +int +common_get_vendor_name(struct transvr_obj_s *self, char *buf){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_name, + "common_get_vendor_name"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); +} + + +int +common_get_vendor_pn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_pn, + "common_get_vendor_pn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); +} + + +int +common_get_vendor_rev(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_rev, + "common_get_vendor_rev"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); +} + + +int +common_get_vendor_sn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_sn, + "common_get_vendor_sn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); +} + + +int +common_get_br(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return (int)self->br; + } + err = _check_by_mode(self, + &_common_update_attr_br, + "common_get_br"); + if (err < 0){ + return err; + } + /* Transform to INT to show error case */ + return (int)self->br; +} + + +int +common_get_len_smf(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_smf; + } + err = _check_by_mode(self, + &_common_update_attr_len_smf, + "common_get_len_smf"); + if (err < 0){ + return err; + } + return self->len_smf; +} + + +int +common_get_len_om1(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om1; + } + err = _check_by_mode(self, + &_common_update_attr_len_om1, + "common_get_len_om1"); + if (err < 0){ + return err; + } + return self->len_om1; +} + + +int +common_get_len_om2(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om2; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om2, + "common_get_len_om2"); + if (err < 0){ + return err; + } + return self->len_om2; +} + + +int +common_get_len_om3(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om3; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om3, + "common_get_len_om3"); + if (err < 0){ + return err; + } + return self->len_om3; +} + + +int +common_get_len_om4(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om4; + } + err = _check_by_mode(self, + &_common_update_attr_len_om4, + "common_get_len_om4"); + if (err < 0){ + return err; + } + return self->len_om4; +} + + +int +common_get_comp_extended(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp_ext, + "common_get_comp_extended"); + if (err_code < 0){ + return err_code; + } + return self->transvr_comp_ext; +} + + +int +common_get_comp_rev(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_comp_rev, + "common_get_comp_rev"); + if (err_code < 0){ + return err_code; + } + return self->comp_rev; +} + + +int +common_get_info(struct transvr_obj_s *self){ + + if (self->state != STATE_TRANSVR_CONNECTED) { + return self->state; + } + return self->info; +} + + +int +_common_get_if_lane(struct transvr_obj_s *self, + char *result){ + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_M_STR); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + memset(tmp_str, 0, LEN_TRANSVR_M_STR); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_M_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_M_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_M_STR); + } + if (i == 0) { + return EVENT_TRANSVR_TASK_FAIL; + } + return 0; +} + + +int +common_get_if_lane(struct transvr_obj_s *self, + char *buf_p){ + + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + if (self->ioexp_obj_p->state != STATE_IOEXP_NORMAL) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n", ERR_TRANSVR_ABNORMAL); + } + if (_common_get_if_lane(self, tmp_str) < 0) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n" ,ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%s\n" ,tmp_str); +} + + +int +sfp_get_len_sm(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_len_sm, + "sfp_get_len_sm"); + if (err_code < 0){ + return err_code; + } + return self->len_sm; +} + + +int +sfp_get_rate_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_rate_id, + "sfp_get_rate_id"); + if (err_code < 0){ + return err_code; + } + return self->rate_id; +} + + +int +sfp_get_soft_rs0(struct transvr_obj_s *self){ + /* Note: + * SFP Soft Rate_Select Select [aka. "RS(0)"] address + * A2h, offset: 110, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs0, + "sfp_get_soft_rs0"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs0 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_soft_rs1(struct transvr_obj_s *self){ + /* Note: + * SFP Soft RS(1) Select address + * A2h, offset: 118, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs1, + "sfp_get_soft_rs1"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs1 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_temp, + "sfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +sfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_voltage, + "sfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +sfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_bias, + "sfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _common_count_tx_bias(self->curr_tx_bias[0], + self->curr_tx_bias[1], + buf_p); +} + + +int +sfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_power, + "sfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_tx_power(self->curr_tx_power[0], + self->curr_tx_power[1], + buf_p); +} + + +int +sfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_rx_power, + "sfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_rx_power(self->curr_rx_power[0], + self->curr_rx_power[0], + buf_p); +} + + +int +sfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->rx_em[0]); +} + + +int +sfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->tx_eq[0]); +} + + +int +_sfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: A0h / 36 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +__sfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* SFP Specification Compliance: A0h / 3-10 + * transvr_comp[0-7] = 3 - 10 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_get_comp_10g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[0] = address A0h / 3 + * + * 3 7: 10G Base-ER + * 3 6: 10GBASE-LRM + * 3 5: 10GBASE-LR + * 3 4: 10GBASE-SR + */ + int bitmask = 0xf0; /* 11110000 */ + return (__sfp_get_comp_attr(self, 0) & bitmask); +} + + +int +_sfp_get_comp_1g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[3] = address A0h / 6 + * + * 6 7: BASE-PX *3 + * 6 6: BASE-BX10 *3 + * 6 5: 100BASE-FX + * 6 4: 100BASE-LX/LX10 + * 6 3: 1000BASE-T + * 6 2: 1000BASE-CX + * 6 1: 1000BASE-LX *3 + * 6 0: 1000BASE-SX + */ + return __sfp_get_comp_attr(self, 3); +} + + +int +_sfp_get_cable_tech(struct transvr_obj_s *self) { + /* transvr_comp[5] = address A0h / 8 + * + * 8 3: Active Cable *8 + * 8 2: Passive Cable *8 + */ + int bitmask = 0x0c; /* 00001100 */ + return (__sfp_get_comp_attr(self, 5) & bitmask); +} + + +int +sfp_get_comp_eth_1(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_1"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_1g_eth_comp(self); +} + + +int +sfp_get_comp_eth_10(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_10"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_10g_eth_comp(self); +} + + +int +_sfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: A0h / 2 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Note] Optical and Cable Variants Specification Compliance (SFF-8472) + * [Addr] A0h, Bytes 60-61 + * [Note] For optical variants, as defined by having zero's in A0h Byte 8 + * bits 2 and 3, Bytes 60 and 61 denote nominal transmitter output + * wavelength at room temperature. 16 bit value with byte 60 as high + * order byte and byte 61 as low order byte. The laser wavelength is + * equal to the 16 bit integer value in nm. This field allows the user + * to read the laser wavelength directly, so it is not necessary to + * infer it from the Transceiver Codes A0h Bytes 3 to 10 (see Table + * 5-3). This also allows specification of wavelengths not covered + * in the Transceiver Codes, such as those used in coarse WDM systems. + * + * For passive and active cable variants, a value of 00h for both A0h + * Byte 60 and Byte 61 denotes laser wavelength or cable specification + * compliance is unspecified. + */ + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +int +sfp_get_1g_rj45_extphy_offset(struct transvr_obj_s *self, char *buf) { + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + return snprintf(buf, LEN_TRANSVR_S_STR, "0x%02x\n", self->extphy_offset); +} + + +int +sfp_get_1g_rj45_extphy_reg(struct transvr_obj_s *self, char *buf) { + + int i = 0; + int ret = 0; + int retry = 3; + int delay = 200; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56, + -1, self->extphy_offset, 1, 0) < 0) { + return -EIO; + } + for (i=0; ii2c_client_p, self->extphy_offset); + if (ret >=0) { + goto ok_sfp_get_1g_rj45_extphy_reg; + } + msleep(delay); + } + SWPS_INFO("%s: retry:%d fail :%s :0x%02x\n", + __func__, retry, self->swp_name, self->extphy_offset); + return -EIO; + +ok_sfp_get_1g_rj45_extphy_reg: + ret = ((ret & 0x00ff) << 8) | ((ret & 0xff00) >> 8); + return snprintf(buf, LEN_TRANSVR_S_STR, "0x%04x\n", ret); +} + + +int +__qsfp_get_power_cls(struct transvr_obj_s *self, + int direct_access){ + + int err_code; + uint8_t detect_val; + + /* Detect and Update power class attribute */ + if (direct_access){ + err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_power_cls"); + } else { + err_code = self->ext_id; + } + if (err_code <0){ + return err_code; + } + if (err_code == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data */ + detect_val = self->ext_id; + SWP_BIT_CLEAR(detect_val, 2); /* Bit2: CDR RX present */ + SWP_BIT_CLEAR(detect_val, 3); /* Bit3: CDR TX present */ + SWP_BIT_CLEAR(detect_val, 4); /* Bit4: CLEI present */ + SWP_BIT_CLEAR(detect_val, 5); /* Bit5: reserved */ + /* Identify power class */ + switch (detect_val) { + case 0: /* Class_1: 00000000 */ + return 1; + case 64: /* Class_2: 01000000 */ + return 2; + case 128: /* Class_3: 10000000 */ + return 3; + case 192: /* Class_4: 11000000 */ + return 4; + case 1: /* Class_5: 00000001 */ + case 193: /* Class_5: 11000001 */ + return 5; + case 2: /* Class_6: 00000010 */ + case 194: /* Class_6: 11000010 */ + return 6; + case 3: /* Class_7: 00000011 */ + case 195: /* Class_7: 11000011 */ + return 7; + default: + break; + } + SWPS_INFO("%s: Detect undefined power class:%d\n", __func__, detect_val); + return ERR_TRANSVR_UNDEFINED; +} + + +int +qsfp_get_power_cls(struct transvr_obj_s *self) { + return __qsfp_get_power_cls(self, 1); +} + + +int +__qsfp_get_cdr_present(struct transvr_obj_s *self, + int direct_access){ + + int retval; + int BIT_SHIFT = 2; + int BIT_MASK = 0x3; + + /* Detect and Update power class attribute */ + if (direct_access) { + retval = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_cdr_present"); + if (retval < 0){ + return retval; + } + } + retval = self->ext_id; + if (retval == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data and return */ + return (int)(retval >> BIT_SHIFT & BIT_MASK); +} + + +int +qsfp_get_cdr_present(struct transvr_obj_s *self) { + return __qsfp_get_cdr_present(self, 1); +} + + +int +qsfp_get_cdr(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + "qsfp_get_cdr"); + if (err_code <0){ + return err_code; + } + + return self->cdr; +} + + +int +__qsfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* QSFP Specification Compliance: 00h / 131-138 + * transvr_comp[0-7] = 131 - 138 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_get_comp_10_40_100_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[0] = address 00h / 131 + * + * 131 7: Extended: See section 6.3.23. The Extended Specification Compliance + * Codes are maintained in the Transceiver Management section of SFF- + * 8024. + * 131 6: 10GBASE-LRM + * 131 5: 10GBASE-LR + * 131 4: 10GBASE-SR + * 131 3: 40GBASE-CR4 + * 131 2: 40GBASE-SR4 + * 131 1: 40GBASE-LR4 + * 131 0: 40G Active Cable (XLPPI) + */ + return __qsfp_get_comp_attr(self, 0); +} + + +int +_qsfp_get_comp_sonet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 132 7-3: Reserved + * 132 2: OC 48, long reach + * 132 1: OC 48, intermediate reach + * 132 0: OC 48 short reach + */ + return __qsfp_get_comp_attr(self, 1); +} + + +int +_qsfp_get_comp_sas_sata(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 133 7: SAS 24.0 Gb/s + * 133 6: SAS 12.0 Gb/s + * 133 5: SAS 6.0 Gb/s + * 133 4: SAS 3.0 Gb/s + * 133 3-0: Reserved + */ + return __qsfp_get_comp_attr(self, 2); +} + + +int +_qsfp_get_comp_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 134 7-4: Reserved + * 134 3: 1000BASE-T + * 134 2: 1000BASE-CX + * 134 1: 1000BASE-LX + * 134 0: 1000BASE-SX + */ + return __qsfp_get_comp_attr(self, 3); +} + + +int +_qsfp_get_comp_fc_link_length(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 7: Very long distance (V) + * 135 6: Short distance (S) + * 135 5: Intermediate distance (I) + * 135 4: Long distance (L) + * 135 3: Medium (M) + */ + int mask = 0xFC; /* 11111100 */ + return (__qsfp_get_comp_attr(self, 4) & mask); +} + + +int +_qsfp_get_comp_fc_trans_tech(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 2: Reserved + * 135 1: Longwave laser (LC) + * 135 0: Electrical inter-enclosure (EL) + * + * 136 7: Electrical intra-enclosure + * 136 6: Shortwave laser w/o OFC (SN) + * 136 5: Shortwave laser w OFC (SL) + * 136 4: Longwave Laser (LL) + * 136 3-0: Reserved + * + * return value = [bit 8-15:addr 135][bit 0-7:addr 136] + */ + int mask_135 = 7; /* 00000111 */ + int val_135 = (__qsfp_get_comp_attr(self, 4) & mask_135); + int val_136 = __qsfp_get_comp_attr(self, 5); + return ((val_135 << 7) + val_136); +} + + +int +_qsfp_get_comp_fc_trans_media(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 137 7: Twin Axial Pair (TW) + * 137 6: Shielded Twisted Pair (TP) + * 137 5: Miniature Coax (MI) + * 137 4: Video Coax (TV) + * 137 3: Multi-mode 62.5 m (M6) + * 137 2: Multi-mode 50 m (M5) + * 137 1: Multi-mode 50 um (OM3) + * 137 0: Single Mode (SM) + */ + return __qsfp_get_comp_attr(self, 6); +} + + +int +_qsfp_get_comp_fc_speed(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 138 7: 1200 MBps (per channel) + * 138 6: 800 MBps + * 138 5: 1600 MBps (per channel) + * 138 4: 400 MBps + * 138 3: 3200 MBps (per channel) + * 138 2: 200 MBps + * 138 1: Extended: See section 6.3.23. The Extended Specification + * Compliance Codes are maintained in the Transceiver Management + * section of SFF-8024. + * 138 0: 100 MBps + */ + return __qsfp_get_comp_attr(self, 7); +} + + +int +_qsfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: 00h / 192 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_comp_eth(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_eth"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_ethernet(self); +} + + +int +qsfp_get_comp_10_40(struct transvr_obj_s *self) { + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_10_40"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_10_40_100_ethernet(self); +} + + +int +_qsfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: 00h / 130 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_temp, + "qsfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +qsfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_voltage, + "qsfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +qsfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->tx_eq[0], self->tx_eq[1]); +} + + +int +qsfp_get_transvr_rx_am(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_get_transvr_rx_am"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_am[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_am[0], self->rx_am[1]); +} + + +int +qsfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_em[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_em[0], self->rx_em[1]); +} + + +int +_qsfp_get_channel_diag(uint8_t *data_array, + int (*count_func)(uint8_t high_byte, uint8_t low_byte, char *buf_p), + char *ch_name, + char *result_p) { + int i, high, low; + int len_max = 128; + char ch_buf[4][16] = { DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL }; + + for (i=0; i<4; i++) { + high = (i*2); + low = ((i*2) + 1); + count_func(data_array[high], data_array[low], ch_buf[i]); + } + return snprintf(result_p, len_max, + "%s-%d:%s%s-%d:%s%s-%d:%s%s-%d:%s", + ch_name, 1, ch_buf[0], + ch_name, 2, ch_buf[1], + ch_name, 3, ch_buf[2], + ch_name, 4, ch_buf[3]); +} + + +int +qsfp_get_soft_rx_los(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_rx_los, + "qsfp_get_soft_rx_los"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->rx_los & mask)); +} + + +int +qsfp_get_soft_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_get_soft_tx_disable"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_disable & mask)); +} + + +int +qsfp_get_soft_tx_fault(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_fault, + "qsfp_get_soft_tx_fault"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_fault & mask)); +} + + +int +qsfp_get_auto_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + if (self->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "%d\n", ERR_TRANSVR_FUNC_DISABLE); + } + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "0x%02x\n", self->auto_tx_disable); +} + + +int +qsfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_bias, + "qsfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _qsfp_get_channel_diag(self->curr_tx_bias, + _common_count_tx_bias, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_power, + "qsfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_tx_power, + _common_count_tx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "RX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_rx_power, + "qsfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_rx_power, + _common_count_rx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Desc] Wavelength or Copper Cable Attenuation (SFF-8636) + * [Addr] 00h 186-187 + * [Note] + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is + * a 16-bit hex value with Byte 186 as high order byte and Byte 187 as + * low order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. + * If the free side device is identified as copper cable these registers will + * be used to define the cable attenuation. An indication of 0 dB attenuation + * refers to the case where the attenuation is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +/* Public Function for Setup Features + */ +static int +__sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + uint8_t update_val = (*attr_p); + + switch (input_val) { + case 0: + SWP_BIT_CLEAR(update_val, bit_shift); + break; + case 1: + SWP_BIT_SET(update_val, bit_shift); + break; + default: + retval = ERR_TRANSVR_UNEXCPT; + err_code = ERR_TRANSVR_UNEXCPT; + err_msg = "Exception occurs"; + goto err_private_sfp_set_soft_rs_1; + } + err_code = _common_set_uint8_attr(self, + address, + page, + offset, + update_val, + attr_p, + caller, + show_err); + if (err_code < 0) { + retval = err_code; + err_msg = "Write data via i2c fail!"; + goto err_private_sfp_set_soft_rs_1; + } + (*attr_p) = update_val; + return 0; + +err_private_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +static int +_sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + /* Check input value */ + if ((input_val != 0) && (input_val != 1)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + switch (err_code) { + case 0: + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "Not support this feature"; + break; + case ERR_TRANSVR_UNINIT: + retval = ERR_TRANSVR_UNINIT; + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + retval = ERR_TRANSVR_UNPLUGGED; + err_msg = "Transceiver unplugged!"; + break; + default: + retval = err_code; + err_msg = "Check Rate_ID fail!"; + break; + } + goto err_common_sfp_set_soft_rs_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + attr_update_func, + caller); + if ( (err_code < 0) || + ((*attr_p) == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Generate and update value */ + return __sfp_set_soft_rs(self, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + +err_common_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +sfp_set_soft_rs0(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(0)"] address + * A2h, offset: 110, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + bit_shift, + &_sfp_update_attr_soft_rs0, + &(self->soft_rs0), + "sfp_set_soft_rs0", + show_err); +} + + +int +sfp_set_soft_rs1(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(1)"] address + * A2h, offset: 118, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + bit_shift, + &_sfp_update_attr_soft_rs1, + &(self->soft_rs1), + "sfp_set_soft_rs1", + show_err); +} + + +int +__sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_tx_eq; + } + setv = (uint8_t)input; + if (self->tx_eq[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + setv, + &(self->tx_eq[0]), + "_sfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_tx_eq; + } + return 0; + +err_sfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; itx_eq[0]; + if (_sfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if (self->tx_eq[0] == tmp){ + return 0; + } + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +sfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_tx_eq(self, input, 1); +} + + +int +__sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_rx_em; + } + setv = (uint8_t)input; + if (self->rx_em[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + setv, + &(self->rx_em[0]), + "_sfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_rx_em; + } + return 0; + +err_sfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; irx_em[0]; + if (_sfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if (self->rx_em[0] == tmp){ + return 0; + } + } + return -1; +} + + +int +sfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_rx_em(self, input, 1); +} + + +int +sfp_set_1g_rj45_extphy_offset(struct transvr_obj_s *self, + int input) { + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if ((input < 0) || (input > 0xff)) { + return ERR_TRANSVR_BADINPUT; + } + self->extphy_offset = (uint8_t)input; + return 0; +} + + +int +sfp_set_1g_rj45_extphy_reg(struct transvr_obj_s *self, + int input) { + + int i = 0; + int retry = 3; + int delay = 200; + uint16_t tmp = 0; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if ((input < 0) || (input > 0xffff)) { + return ERR_TRANSVR_BADINPUT; + } + tmp = ((input & 0x00ff) << 8) | ((input & 0xff00) >> 8); + if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56, + -1, self->extphy_offset, 1, 0) < 0) { + return -EIO; + } + for (i=0; i<=retry; i++) { + if (i2c_smbus_write_word_data(self->i2c_client_p, + self->extphy_offset, + tmp) >= 0) { + return 0; + } + msleep(delay); + } + SWPS_INFO("%s: retry:%d fail :%s :0x%02x\n", + __func__, retry, self->swp_name, self->extphy_offset); + return -EIO; +} + + +static int +__qsfp_set_cdr(struct transvr_obj_s *self, + int input_val, + int show_err) { + + uint8_t update_val; + int CDR_FEATURE_SUPPORTED = 0x3; + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_name = "__qsfp_set_cdr"; + + /* Check input value */ + if ((input_val < 0) || (input_val > 0xff)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_qsfp_set_cdr_1; + } + update_val = (uint8_t)input_val; + /* Check CDR supported by transceiver */ + err_code = qsfp_get_cdr_present(self); + if (err_code < 0) { + retval = err_code; + switch (err_code) { + case ERR_TRANSVR_UNINIT: + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + err_msg = "Transceiver unplugged!"; + break; + default: + err_msg = "Check CDR present fail!"; + break; + } + goto err_qsfp_set_cdr_1; + } + if (err_code != CDR_FEATURE_SUPPORTED) { + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "This transceiver not support CDR!"; + goto err_qsfp_set_cdr_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + func_name); + if ( (err_code < 0) || + (self->cdr == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_qsfp_set_cdr_1; + } + /* Write input value to transceiver */ + return _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + update_val, + &(self->cdr), + func_name, + show_err); + +err_qsfp_set_cdr_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +qsfp_set_cdr(struct transvr_obj_s *self, + int input_val) { + return __qsfp_set_cdr(self, input_val, 1); +} + + +int +qsfp_set_soft_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int show_err = 1; + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + int update_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_soft_tx_disable"); + if (retval < 0) { + snprintf(err_msg, 63, "Not ready. err:%d", retval); + goto err_qsfp_set_soft_tx_disable; + } + if ((input_val > in_max) || + (input_val < in_min) ){ + retval = ERR_TRANSVR_BADINPUT; + snprintf(err_msg, 63, "Input value:%d incorrect!", input_val); + goto err_qsfp_set_soft_tx_disable; + } + if ((self->tx_disable & 0x0f) == input_val) { + return 0; + } + update_val = ((self->tx_disable & 0xf0) & input_val); + retval = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + input_val, + &(self->tx_disable), + "qsfp_set_tx_disable", + show_err); + if (retval < 0) { + snprintf(err_msg, 63, "_common_set_uint8_attr:%d fail!", retval); + goto err_qsfp_set_soft_tx_disable; + } + return 0; + +err_qsfp_set_soft_tx_disable: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return retval; +} + + +int +_qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + uint8_t update) { + + uint8_t tx_enable = 0x0; + int show_e = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Handle timing issues */ + if (update != tx_enable) { + /* Note: + * Because there are some txvr has timing issues, + * therefore we need to execute reset cycle first. + * (enable -> other settings) + */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + tx_enable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set reset value fail"; + goto err_qsfp_set_auto_tx_disable; + } + mdelay(10); + } + /* Setup target value */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->auto_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set target value fail"; + goto err_qsfp_set_auto_tx_disable; + } + /* Check and update */ + err = _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C get value fail"; + goto err_qsfp_set_auto_tx_disable; + } + if (self->tx_disable != update) { + emsg = "data not become effective"; + goto err_qsfp_set_auto_tx_disable; + } + return 0; + +err_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s\n", + __func__, emsg, self->swp_name); + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Update settings*/ + if (input_val == VAL_TRANSVR_FUNCTION_DISABLE) { + emsg = "User disable auto tx_disable"; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + goto out_qsfp_set_auto_tx_disable; + } + if ((input_val > in_max) || (input_val < in_min) ){ + SWPS_INFO("%s: Input value:%d incorrect! :%s\n", + __func__, input_val, self->swp_name); + return ERR_TRANSVR_BADINPUT; + } + self->auto_tx_disable = input_val; + /* Check current soft tx_disable */ + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_auto_tx_disable"); + switch (retval) { + case 0: + break; + case ERR_TRANSVR_UNPLUGGED: + emsg = "Doesn't need to update"; + goto out_qsfp_set_auto_tx_disable; + default: + SWPS_INFO("%s: setup fail :%d :%s\n", + __func__, retval, self->swp_name); + return retval; + } + return _qsfp_set_auto_tx_disable(self, input_val); + +out_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s :%d\n :%d", + __func__, emsg, self->swp_name, input_val, retval); + return 0; +} + + +int +__qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_tx_eq; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->tx_eq[0] == setv[0]) && + (self->tx_eq[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + setv, + self->tx_eq, + "_qsfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_tx_eq; + } + return 0; + +err_qsfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; itx_eq[0]; + tmp[1] = self->tx_eq[1]; + if (_qsfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if ((self->tx_eq[0] == tmp[0]) && + (self->tx_eq[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_tx_eq(self, input, 1); +} + + +int +__qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_am; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_am[0] == setv[0]) && + (self->rx_am[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + setv, + self->rx_am, + "_qsfp_set_rx_am", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_am; + } + return 0; + +err_qsfp_set_rx_am: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_am[0]; + tmp[1] = self->rx_am[1]; + if (_qsfp_update_attr_rx_am(self, show_e) < 0){ + continue; + } + if ((self->rx_am[0] == tmp[0]) && + (self->rx_am[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_am(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_set_rx_am"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_am(self, input, 1); +} + + +int +__qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_em; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_em[0] == setv[0]) && + (self->rx_em[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + setv, + self->rx_em, + "_qsfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_em; + } + return 0; + +err_qsfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_em[0]; + tmp[1] = self->rx_em[1]; + if (_qsfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if ((self->rx_em[0] == tmp[0]) && + (self->rx_em[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_em(self, input, 1); +} + + +int +common_transvr_dump(struct transvr_obj_s* self){ + + char *type_name = "Undefined"; + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + switch (self->type) { + case TRANSVR_TYPE_SFP: + type_name = STR_TRANSVR_SFP; + break; + case TRANSVR_TYPE_QSFP: + type_name = STR_TRANSVR_QSFP; + break; + case TRANSVR_TYPE_QSFP_PLUS: + type_name = STR_TRANSVR_QSFP_PLUS; + break; + case TRANSVR_TYPE_QSFP_28: + type_name = STR_TRANSVR_QSFP28; + break; + case TRANSVR_TYPE_FAKE: + type_name = "FAKE"; + goto ok_common_transvr_dump; + case TRANSVR_TYPE_UNPLUGGED: + type_name = "UNPLUGGED"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_INCONSISTENT: + type_name = "INCONSISTENT"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_ERROR: + type_name = "ERROR"; + goto err_common_transvr_dump; + + default: + type_name = "UNEXPECTED"; + goto err_common_transvr_dump; + } + printk(KERN_INFO "[SWPS] Dump %s information:\n", self->swp_name); + printk(KERN_INFO " |- :%s\n", type_name); + printk(KERN_INFO " |- :%s\n", self->vendor_name); + printk(KERN_INFO " |- :%s\n", self->vendor_pn); + printk(KERN_INFO " |- :%s\n", self->vendor_rev); + printk(KERN_INFO " |- :%s\n", self->vendor_sn); + printk(KERN_INFO " |- :0x%02x\n", self->br); + printk(KERN_INFO " |- :0x%02x\n", self->comp_rev); + printk(KERN_INFO " |- :%d\n", self->len_om1); + printk(KERN_INFO " |- :%d\n", self->len_om2); + printk(KERN_INFO " |- :%d\n", self->len_om3); + printk(KERN_INFO " |- :%d\n", self->len_om4); + return 0; + +ok_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return 0; + +err_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return -1; +} + + +int +sfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_sm); + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :0x%02x\n", self->rate_id); + return 0; +} + + +int +qsfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :Class_%d\n", __qsfp_get_power_cls(self, 0)); + return 0; +} + + +int +fake_transvr_dump(struct transvr_obj_s* self) { + + printk(KERN_INFO "[SWPS] Dump transceiver information: %s\n", self->swp_name); + printk(KERN_INFO " |- :FAKE\n"); + printk(KERN_INFO " |- :FAKE_VENDER_NAME\n"); + printk(KERN_INFO " |- :FAKE_VENDER_PN\n"); + printk(KERN_INFO " |- :FAKE_VENDER_REV\n"); + printk(KERN_INFO " |- :FAKE_VENDER_SN\n"); + printk(KERN_INFO " |- :0x99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " '- :0x99\n"); + return 0; +} + + +/* ========== Object functions for fake type ========== + */ +int +fake_transvr_update(struct transvr_obj_s *self, + int show_err){ + self->state = STATE_TRANSVR_CONNECTED; + return 0; +} + + +int +fake_get_binary(struct transvr_obj_s *self){ + return 1; +} + +int +fake_get_int(struct transvr_obj_s *self){ + return 99; +} + + +int +fake_get_hex(struct transvr_obj_s *self){ + return 0x0f; +} + + +int +fake_get_str(struct transvr_obj_s *self, char *buf) { + return snprintf(buf, 16, "fake_get_str\n"); +} + + +int +fake_set_int(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: %d\n", __func__, input); + return 0; +} + + +int +fake_set_hex(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: 0x%02x\n", __func__, input); + return 0; +} + + +/* ========== Object functions for unsupported ========== + */ +int +unsupported_get_func(struct transvr_obj_s *self){ + return ERR_TRANSVR_NOTSUPPORT; +} + + +int +unsupported_get_func2(struct transvr_obj_s *self, + char *buf_p) { + int len = snprintf(buf_p, 8, "%d\n", ERR_TRANSVR_NOTSUPPORT); + return len; +} + + +int +unsupported_set_func(struct transvr_obj_s *self, + int input_val){ + return ERR_TRANSVR_NOTSUPPORT; +} + + + +/* ========== Object functions for long term task ========== + * + * [Note] + * SWPS transceiver worker is likely the green-thread (coroutine). + * Due to resource and performance considerations. SWPS run all + * features in one kthread at the same time, and handle by it self. + */ + +/* For Transceiver Task Handling + */ +static struct transvr_worker_s * +transvr_task_get(struct transvr_obj_s *self, + char *func_name) { + + struct transvr_worker_s *curr_p = self->worker_p; + + while(curr_p != NULL){ + if (strcmp((curr_p->func_name), func_name) == 0 ) { + return curr_p; + } + curr_p = curr_p->next_p; + } + return NULL; +} + + +static struct transvr_worker_s* +transvr_task_creat(struct transvr_obj_s *self, + int (*main_task)(struct transvr_worker_s *task), + int (*post_task)(struct transvr_worker_s *task), + char *caller) { + + struct transvr_worker_s *task_p = NULL; + struct transvr_worker_s *curr_p = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check task not exist */ + task_p = transvr_task_get(self, caller); + if (task_p) { + snprintf(err_msg, sizeof(err_msg), "Task already created!"); + goto err_transvr_task_creat; + } + /* Create task worker */ + task_p = kzalloc(sizeof(struct transvr_worker_s), GFP_KERNEL); + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_transvr_task_creat; + } + /* Setup task data */ + task_p->transvr_p = self; + task_p->next_p = NULL; + task_p->trigger_time = 0; + task_p->retry = 1; + task_p->state = STATE_T_TASK_INIT; + task_p->main_task = main_task; + task_p->post_task = post_task; + task_p->p_data = NULL; + snprintf(task_p->func_name, sizeof(task_p->func_name), "%s", caller); + /* Setup Link List */ + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p->next_p != NULL) { + curr_p = curr_p->next_p; + } + curr_p->next_p = task_p; + task_p->pre_p = curr_p; + } else { + self->worker_p = task_p; + task_p->pre_p = NULL; + } + return task_p; + +err_transvr_task_creat: + SWPS_ERR("%s: %s :%s :%s\n", + __func__, err_msg, caller, self->swp_name); + return NULL; +} + + +static void +transvr_task_free_one(struct transvr_worker_s *task_p){ + + struct transvr_worker_s *pre_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (task_p) { + pre_p = task_p->pre_p; + next_p = task_p->next_p; + + if ((pre_p) && (next_p)) { + pre_p->next_p = next_p; + next_p->pre_p = pre_p; + + } else if ((!pre_p) && (next_p)) { + next_p->pre_p = NULL; + + } else if ((pre_p) && (!next_p)) { + pre_p->next_p = NULL; + + } else if ((!pre_p) && (!next_p)) { + task_p->transvr_p->worker_p = NULL; + } else { + SWPS_ERR("%s: Unexcept case!\n :%s", + __func__, task_p->transvr_p->swp_name); + } + kfree(task_p->p_data); + kfree(task_p); + } +} + + +static void +transvr_task_free_all(struct transvr_obj_s *self) { + + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p) { + next_p = curr_p->next_p; + transvr_task_free_one(curr_p); + curr_p = next_p; + } + self->worker_p = NULL; + } +} + + +static void +transvr_cache_free_all(struct transvr_obj_s *self) { + + memset(self->vendor_name, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_rev, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_pn, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_sn, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + self->extphy_offset = 0; +} + +static int +_transvr_task_run_main(struct transvr_worker_s *task_p) { + + int retval = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "main_task is NULL!"); + goto main_transvr_task_err; + } + if ((task_p->trigger_time) == 0){ + goto main_transvr_task_run; + } + if (time_before(jiffies, task_p->trigger_time)){ + goto main_transvr_task_wait; + } + goto main_transvr_task_run; + +main_transvr_task_run: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + task_p->retry -= 1; + } + retval = task_p->main_task(task_p); + if (retval < 0) { + if (task_p->retry > 0) { + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + } + goto main_transvr_task_identify; + +main_transvr_task_identify: + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + + case EVENT_TRANSVR_TASK_DONE: + task_p->state = STATE_T_TASK_DONE; + return EVENT_TRANSVR_TASK_DONE; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + +main_transvr_task_wait: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + +main_transvr_task_err: + task_p->state = STATE_T_TASK_FAIL; + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, retval, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +_transvr_task_run_post(struct transvr_worker_s *task_p) { + + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if ((task_p->post_task) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + switch (task_p->state) { + case STATE_T_TASK_WAIT: + case STATE_T_TASK_INIT: + goto post_transvr_task_wait; + + case STATE_T_TASK_DONE: + case STATE_T_TASK_FAIL: + goto post_transvr_task_run; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Unexcept task state"); + goto post_transvr_task_err; + +post_transvr_task_run: + task_p->post_task(task_p); + return EVENT_TRANSVR_TASK_DONE; + +post_transvr_task_wait: + return EVENT_TRANSVR_TASK_WAIT; + +post_transvr_task_err: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, task_p->state, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_one(struct transvr_worker_s *task_p) { + + int retval_main = DEBUG_TRANSVR_INT_VAL; + int retval_post = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval_main = _transvr_task_run_main(task_p); + if (retval_main < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute main_task fail!"); + goto err_transvr_task_run_one; + } + retval_post = _transvr_task_run_post(task_p); + if (retval_post < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute post_task fail!"); + goto err_transvr_task_run_one; + } + return retval_main; + +err_transvr_task_run_one: + SWPS_INFO("%s: %s
:%d :%d :%s :%s\n", + __func__, err_msg, retval_main, retval_post, + task_p->func_name, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_all(struct transvr_obj_s *self) { + + int haserr = 0; + int retval = DEBUG_TRANSVR_INT_VAL; + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if ((self->worker_p) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + curr_p = self->worker_p; + while (curr_p != NULL) { + next_p = curr_p->next_p; + retval = transvr_task_run_one(curr_p); + if (curr_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + curr_p = next_p; + continue; + } + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + break; + case EVENT_TRANSVR_TASK_DONE: + transvr_task_free_one(curr_p); + break; + case EVENT_TRANSVR_TASK_FAIL: + + default: + haserr = 1; + transvr_task_free_one(curr_p); + break; + } + curr_p = next_p; + } + if (haserr) { + return EVENT_TRANSVR_TASK_FAIL; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +static void +transvr_task_set_delay(struct transvr_worker_s *task_p, + unsigned long delay_msec) { + + task_p->trigger_time = (jiffies + (delay_msec * (HZ/1000))); +} + + +static void +transvr_task_set_retry(struct transvr_worker_s *task_p, + unsigned long retry_times) { + + task_p->retry = retry_times; +} + + +/* For Transceiver Post Task + */ +int +taskfunc_post_do_nothing(struct transvr_worker_s *task_p) { + + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_post_handle_task_state(struct transvr_worker_s *task_p) { + + struct transvr_obj_s* tp = task_p->transvr_p; + + switch (task_p->state) { + case STATE_T_TASK_INIT: + case STATE_T_TASK_WAIT: + return EVENT_TRANSVR_TASK_WAIT; + + case STATE_T_TASK_DONE: + tp->state = STATE_TRANSVR_CONNECTED; + tp->send_uevent(tp, KOBJ_ADD); + return EVENT_TRANSVR_TASK_DONE; + + case STATE_T_TASK_FAIL: + tp->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_TASK_FAIL; + + default: + break; + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +/* For Transceiver Main Task + */ +int +_taskfunc_sfp_setup_soft_rs(struct transvr_worker_s *task_p, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller) { + + int show_err = 0; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_soft_rs"; + + err_code = _sfp_update_attr_soft_rs0(task_p->transvr_p, 0); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + err_code = __sfp_set_soft_rs(task_p->transvr_p, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_setup_soft_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_code); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +__taskfunc_sfp_setup_hard_rs(struct transvr_worker_s *task_p, + int input_val, + int (*get_func)(struct ioexp_obj_s *self, int virt_offset), + int (*set_func)(struct ioexp_obj_s *self, int virt_offset, int input_val)) { + + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + + err_val = get_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset); + + if (err_val < 0) { + if (err_val == ERR_IOEXP_NOTSUPPORT) { + return EVENT_TRANSVR_TASK_DONE; + } + err_str = "Get current hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + if (err_val == input_val) { + return EVENT_TRANSVR_TASK_DONE; + } + err_val = set_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_p_taskfunc_sfp_setup_hard_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_hard_rs0(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs0, + task_p->transvr_p->ioexp_obj_p->set_hard_rs0); +} + + +int +_taskfunc_sfp_setup_hard_rs1(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs1, + task_p->transvr_p->ioexp_obj_p->set_hard_rs1); +} + + +int +_taskfunc_sfp_setup_rs0(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs0"; + + err_val = _taskfunc_sfp_setup_hard_rs0(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs0, + task_p->transvr_p->eeprom_map_p->page_soft_rs0, + task_p->transvr_p->eeprom_map_p->offset_soft_rs0, + bit_shift, + &(task_p->transvr_p->soft_rs0), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs0_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs0(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_rs1(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs1"; + + err_val = _taskfunc_sfp_setup_hard_rs1(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs1, + task_p->transvr_p->eeprom_map_p->page_soft_rs1, + task_p->transvr_p->eeprom_map_p->offset_soft_rs1, + bit_shift, + &(task_p->transvr_p->soft_rs1), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs1_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs1(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_sfp_setup_SFF8431_case1(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs0(task_p, update_val); +} + + + +int +taskfunc_sfp_setup_SFF8431_case2(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs1(task_p, update_val); +} + + +int +taskfunc_sfp_setup_SFF8431_case3(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + int update_rs0 = 1; + int update_rs1 = 1; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _taskfunc_sfp_setup_rs0(task_p, update_rs0); + if (err_code < 0) { + return err_code; + } + return _taskfunc_sfp_setup_rs1(task_p, update_rs1); +} + + +int +taskfunc_sfp_handle_1g_rj45(struct transvr_worker_s *task_p) { + + /* Not all of platform support 0x56 for transceiver + * external PHY, Support list as below: + * => 1. Magnolia-PVT (PS: EVT & DVT not ready) + */ + int ext_phy_addr = 0x56; + int ext_phy_page = -1; + int ext_phy_offs = 0x11; + int ext_phy_len = 1; + int lstate_mask = 0x04; /* 00000100 */ + int show_err = 0; + int fail_retry = 5; + int fail_delay = 1000; /* msec */ + int err_code = DEBUG_TRANSVR_INT_VAL; + uint8_t detect_val = DEBUG_TRANSVR_HEX_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + int *tmp_p = NULL; + char *func_name = "taskfunc_sfp_handle_1g_rj45"; + + if (task_p->transvr_p->state != STATE_TRANSVR_CONNECTED) { + return EVENT_TRANSVR_TASK_DONE; + } + if ( (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000) && + (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000_up) ) { + goto err_taskfunc_sfp_handle_1g_rj45_1; + } + err_code = _common_update_uint8_attr(task_p->transvr_p, + ext_phy_addr, + ext_phy_page, + ext_phy_offs, + ext_phy_len, + &detect_val, + func_name, + show_err); + if ( (err_code < 0) || + (detect_val == DEBUG_TRANSVR_HEX_VAL) ) { + snprintf(err_str, sizeof(err_str), "Detect external link status fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + if ((detect_val & lstate_mask) == lstate_mask) { + goto ok_taskfunc_sfp_handle_1g_rj45_link_up; + } + goto ok_taskfunc_sfp_handle_1g_rj45_link_down; + +ok_taskfunc_sfp_handle_1g_rj45_link_up: + /* Filter out noise */ + if (!(task_p->p_data)) { + tmp_p = kzalloc(sizeof(int), GFP_KERNEL); + if (!tmp_p) { + snprintf(err_str, sizeof(err_str), "kzalloc p_data fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + *tmp_p = TRANSVR_CLASS_BASE_T_1000_up; + task_p->p_data = tmp_p; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + } + if ((*(int *)(task_p->p_data)) != TRANSVR_CLASS_BASE_T_1000_up) { + kfree(task_p->p_data); + task_p->p_data = NULL; + snprintf(err_str, sizeof(err_str), "Internal error"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + kfree(task_p->p_data); + task_p->p_data = NULL; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_link_down: + if (task_p->p_data) { + kfree(task_p->p_data); + task_p->p_data = NULL; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_done: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_1: + snprintf(err_str, sizeof(err_str), "Detect transceiver:%d not Base-T, remove task.", + task_p->transvr_p->info); + SWPS_INFO("%s: %s :%s\n", __func__, err_str, task_p->transvr_p->swp_name); + transvr_task_set_retry(task_p, 0); + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_2: + if (task_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, fail_retry); + } + if ((task_p->retry) == 0) { + /* Error case: + * => In this case, SWPS will stop external Link state monitor features + * and keeps transvr_p->info on TRANSVR_CLASS_BASE_T_1000_up. + * Upper layer will see it always Linkup that because of these type of + * transceiver has external phy, BCM chip see it as Loopback transceiver. + */ + SWPS_WARN("%s can not access external PHY of Base-T SFP transceiver\n", + task_p->transvr_p->swp_name); + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + return EVENT_TRANSVR_TASK_DONE; + } else { + transvr_task_set_delay(task_p, fail_delay); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_qsfp_setup_power_mod(struct transvr_obj_s *self, + int setup_val) { + + int curr_val = DEBUG_TRANSVR_INT_VAL; + int err_val = DEBUG_TRANSVR_INT_VAL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + curr_val = self->ioexp_obj_p->get_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset); + if (curr_val < 0){ + err_msg = "Get current value fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + if (curr_val == setup_val){ + return EVENT_TRANSVR_TASK_DONE; + } + err_val = self->ioexp_obj_p->set_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset, + setup_val); + if (err_val < 0){ + err_msg = "Setup power mode fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_qsfp_setup_power_mod_1: + SWPS_INFO("%s: %s :%d :%d :%d\n", + __func__, err_msg, err_val, curr_val, setup_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_qsfp_handle_tx_disable(struct transvr_worker_s *task_p) { + + int i = 0; + int retry = 5; + int delay_ms = 100; + + if (task_p->transvr_p->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return EVENT_TRANSVR_TASK_DONE; + } + if (!_qsfp_is_implement_tx_disable(task_p->transvr_p)) { + return EVENT_TRANSVR_TASK_DONE; + } + for (i=0; itransvr_p, + task_p->transvr_p->auto_tx_disable) + == EVENT_TRANSVR_TASK_DONE) { + goto ok_taskfunc_qsfp_handle_tx_disable; + } + mdelay(delay_ms); + } + SWPS_INFO("%s auto setup tx_disable:0x%02x fail.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_INIT_FAIL; + +ok_taskfunc_qsfp_handle_tx_disable: + SWPS_INFO("%s auto setup tx_disable:0x%02x ok.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_qsfp_set_hpmod(struct transvr_worker_s *task_p) { + + int err = DEBUG_TRANSVR_INT_VAL; + int HIGH_POWER_MODE = 0; + + /* Handle power mode */ + err = _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + HIGH_POWER_MODE); + if (err < 0) { + SWPS_INFO("%s: setup hpmod fail :%d :%s\n", + __func__, err, task_p->transvr_p->swp_name); + return err; + } + /* Handle auto tx_disable + * [Note] + * => Because there are some transceiver have timing issues or + * setup sequence issues, therefore we handle auto tx_disable + * after handle power mode. + */ + mdelay(100); + return taskfunc_qsfp_handle_tx_disable(task_p); +} + + +int +taskfunc_qsfp_set_lpmod(struct transvr_worker_s *task_p) { + + int LOW_POWER_MODE = 1; + return _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + LOW_POWER_MODE); +} + + +static int +initfunc_sfp_handle_multi_rate_mode(struct transvr_obj_s *self) { + + int task_retry = 3; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "sfp_handle_multi_rate_mode"; + struct transvr_worker_s *task_p = NULL; + + switch (self->rate_id) { + case 0x00: /* Unspecified */ + case 0x03: /* Unspecified */ + case 0x05: /* Unspecified */ + case 0x07: /* Unspecified */ + case 0x09: /* Unspecified */ + case 0x0B: /* Unspecified */ + case 0x0D: /* Unspecified */ + case 0x0F: /* Unspecified */ + goto sfp_handle_multi_rate_mode_4_unspecified; + + case 0x02: /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case1, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x04: /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case2, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x06: /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case3, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x01: /* SFF-8079 (4/2/1G Rate_Select & AS0/AS1) */ + err_str = "SFF-8079 (4/2/1G Rate_Select & AS0/AS1)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x08: /* FC-PI-5 (16/8/4G Rx Rate_select only) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Rx Rate_select only)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0A: /* FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0C: /* FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + */ + err_str = "FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0E: /* 10/8G Rx and Tx Rate_Select controlling the operation or + * locking modes of the internal signal conditioner, retimer + * or CDR, according to the logic table defined in Table 10-2, + * High Bit Rate (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = + * 8.5 Gb/s. In this mode, the default value of bit 110.3 (Soft + * Rate Select RS(0), Table 9-11) and of bit 118.3 (Soft Rate + * Select RS(1), Table 10-1) is 1. + */ + err_str = "cable type: 0x0E"; + goto sfp_handle_multi_rate_mode_4_not_support; + + default: + err_str = "cable type: UNKNOW"; + goto sfp_handle_multi_rate_mode_4_not_support; + } + +sfp_handle_multi_rate_mode_4_sff8431: + if (!task_p) { + err_str = "Create task fail!"; + goto sfp_handle_multi_rate_mode_4_fail_1; + } + transvr_task_set_retry(task_p, task_retry); + return EVENT_TRANSVR_TASK_WAIT; + +sfp_handle_multi_rate_mode_4_unspecified: + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_not_support: + SWPS_INFO("%s: Does not support %s :%s :0x%02x\n", + func_str, err_str, self->swp_name, self->rate_id); + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_fail_1: + SWPS_INFO("%s: %s :%s :0x%02x, :%d\n", + func_str, err_str, self->swp_name, self->rate_id, err_code); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +initfunc_sfp_handle_1g_rj45(struct transvr_obj_s *self) { + + struct transvr_worker_s *task_p = NULL; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_sfp_handle_1g_rj45"; + + + if (self->info == TRANSVR_CLASS_BASE_T_1000) { + task_p = transvr_task_creat(self, + taskfunc_sfp_handle_1g_rj45, + taskfunc_post_do_nothing, + func_str); + if (!task_p) { + snprintf(err_str, sizeof(err_str), "Create task fail"); + goto err_initfunc_sfp_handle_1g_rj45; + } + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_initfunc_sfp_handle_1g_rj45: + SWPS_INFO("%s: %s :%s :%d\n", + __func__, err_str, self->swp_name, detect_cls); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +initfunc_qsfp_handle_power_mode(struct transvr_obj_s *self) { + + int err_code = EVENT_TRANSVR_EXCEP_INIT; + int power_class = DEBUG_TRANSVR_INT_VAL; + int hpmod_retry = 3; + int lpower_config = 1; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + unsigned long hpmod_delay = 500; /* msec */ + struct transvr_worker_s *task_p = NULL; + + /* Handle power mode for IOEXP */ + power_class = __qsfp_get_power_cls(self, 0); + switch (power_class) { + case 1: /* Case: Low power mode (Class = 1) */ + err_code = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (err_code < 0){ + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + return EVENT_TRANSVR_TASK_DONE; + + case 2: /* Case: High power mode (Class > 1) */ + case 3: + case 4: + case 5: + case 6: + case 7: + task_p = transvr_task_creat(self, + taskfunc_qsfp_set_hpmod, + taskfunc_post_handle_task_state, + "transvr_init_qsfp"); + if (!task_p) { + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + transvr_task_set_retry(task_p, hpmod_retry); + transvr_task_set_delay(task_p, hpmod_delay); + return EVENT_TRANSVR_TASK_WAIT; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Exception case"); + goto err_initfunc_qsfp_handle_power_mode; + +err_initfunc_qsfp_handle_power_mode: + SWPS_INFO("%s: %s :%s \n", __func__, err_msg, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +initfunc_qsfp28_handle_cdr(struct transvr_obj_s *self) { + + uint8_t DEFAULT_VAL_CDR = 0xff; + int CDR_FUNC_EXISTED = 0x3; + int show_err = 1; + int err_val = EVENT_TRANSVR_TASK_FAIL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_qsfp28_handle_cdr"; + + err_val = __qsfp_get_cdr_present(self, 0); + if ( (err_val < 0) || + (err_val == DEBUG_TRANSVR_HEX_VAL) ) { + err_msg = "detect cdr_present fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + if (err_val == CDR_FUNC_EXISTED) { + err_val = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->offset_cdr, + DEFAULT_VAL_CDR, + &(self->cdr), + func_str, + show_err); + if (err_val < 0) { + err_msg = "set CDR fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_qsfp_handle_cdr_1: + SWPS_INFO("%s: %s :%d :%s\n", + func_str, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + +/* ========== 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 +_sfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = _sfp_get_comp_extended(self); + + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_25G_AOC; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_25G_SR; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_25G_LR; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_25G_ER; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x0c: /* 25GBASE-CR CA-S */ + case 0x0d: /* 25GBASE-CR CA-N */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L1_25G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_10_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _sfp_get_comp_10g_eth_comp(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 10G Optical (x1) */ + if ((detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + } + if ((detect_val & 0x80) == 0x80) { /* 10000000 : 10GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_1g = 0x0b; + int upper_bound_1g = 0x1A; + int lower_bound_10g = 0x60; + int upper_bound_10g = 0x75; + int lower_bound_25g = 0xf0; + int upper_bound_25g = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 25G */ + if ((notmal_br >= lower_bound_25g) && + (notmal_br <= upper_bound_25g) ) { + return TRANSVR_CLASS_25G; + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + /* Check 1G */ + if ((notmal_br >= lower_bound_1g) && + (notmal_br <= upper_bound_1g) ) { + return TRANSVR_CLASS_1G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + int speed_br = DEBUG_TRANSVR_INT_VAL; + int speed_tmp = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + + speed_br = _sfp_detect_if_sp_by_br(self); + detect_val = _sfp_get_comp_1g_eth_comp(self); + + if (detect_val < 0) { + snprintf(err_str, sizeof(err_str), "Detect abnormal value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + } + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 1G (x1) */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 1000BASE-SX */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_SX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x02) == 0x02) { /* 00000010 : 1000BASE-LX *3 */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_LX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 1000BASE-CX */ + speed_tmp = TRANSVR_CLASS_COPPER_L1_1G; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + /* Case: 1000 Base-T (x1) */ + if ((detect_val & 0x08) == 0x08) { /* 00001000 : 1000BASE-T */ + return TRANSVR_CLASS_BASE_T_1000; + } + /* Case: 100 Base */ + if ( ((detect_val & 0x10) == 0x10) || /* 00010000 : 100BASE-LX/LX10 */ + ((detect_val & 0x20) == 0x20) || /* 00100000 : 100BASE-FX */ + ((detect_val & 0x40) == 0x40) || /* 01000000 : BASE-BX10 *3 */ + ((detect_val & 0x80) == 0x80) ){ /* 10000000 : BASE-PX *3 */ + return TRANSVR_CLASS_OPTICAL_100; + } + /* Case: ERROR */ + snprintf(err_str, sizeof(err_str), "Case:ERROR, value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + +ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g: + switch (speed_br) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_1G: + return speed_tmp; + case TRANSVR_CLASS_10G: + goto ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G; + } + +ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G: + switch (speed_tmp) { + case TRANSVR_CLASS_OPTICAL_1G_SX: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case TRANSVR_CLASS_OPTICAL_1G_LX: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case TRANSVR_CLASS_COPPER_L1_1G: + return TRANSVR_CLASS_COPPER_L1_10G; + default: + break; + } + snprintf(err_str, sizeof(err_str), "transfer_1to10 fail, speed:%d", speed_tmp); + goto err_p_sfp_detect_class_by_1g_ethernet; + +err_p_sfp_detect_class_by_1g_ethernet: + SWPS_INFO("%s: %s :%s", __func__, err_str, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int is_active = 0; + int conn_val = DEBUG_TRANSVR_INT_VAL; + int check_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _sfp_detect_if_sp_by_br(self); + conn_val = _sfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 */ + case 0x0d: /* MPO 2x16 */ + /* + * ToDo: Need verify Optical Pigtail + */ + goto ok_sfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + /* + * ToDo: Need check ACC use case + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x23: /* No separable connector */ + /* + * ToDo: Standard not clear, not all transceiver vendor + * have the same defined + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_check_active_passive: + check_val = _sfp_get_cable_tech(self); + switch(check_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_unknow; + case 0x04: /* Passive */ + goto ok_sfp_detect_class_by_feature_4_copper; + case 0x08: /* Active */ + is_active = 1; + goto ok_sfp_detect_class_by_feature_4_aoc; + default: + snprintf(err_msg, sizeof(err_msg), + "_sfp_get_cable_tech return Non define value:%d", + check_val); + break; + } + goto err_sfp_detect_class_by_feature_1; + +ok_sfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_25G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_25G_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_25G_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_25G_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_25G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + case TRANSVR_CLASS_1G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_1G_SX; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_1G_LX; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_1G_EX; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_1G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_sfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_OPTICAL_25G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_S_AOC; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_OPTICAL_1G_AOC; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_COPPER_L1_25G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L1_10G; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_COPPER_L1_1G; + default: + return TRANSVR_CLASS_COPPER; + } + +ok_sfp_detect_class_by_feature_4_unknow: + return TRANSVR_CLASS_UNSPECIFIED; + +err_sfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +sft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _sfp_detect_class_by_extend_comp(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 10G Compliance */ + detect_val = _sfp_detect_class_by_10_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 1G Compliance */ + detect_val = _sfp_detect_class_by_1g_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_BASE_T_1000: + case TRANSVR_CLASS_OPTICAL_100: + /* + * ToDo: Need Check 0.1G + */ + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_COPPER_L1_10G: + /* Transfer speed case + * => Example: Raycom 10G DAC + */ + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 1G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check by connector, br, wavelength */ + detect_val = _sfp_detect_class_by_feature(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_OPTICAL_1G: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_COPPER: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_COPPER_L1_10G: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined get_connector:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sft_detect_transceiver_class_1; + +err_sft_detect_transceiver_class_1: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_trident2_if_type_1; + +err_sfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SR); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_KR); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_tomahawk_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_tomahawk_if_type_1; + +err_sfp_set_tomahawk_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_bf_tofino_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to BF looks like doesn't have interface type. + * We bypass it currently. + */ + int lmax = 8; + return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); +} + + +int +_sfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = sft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _sfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TRIDENT_3: + case BCM_CHIP_TYPE_TOMAHAWK: + return _sfp_set_tomahawk_if_type(self, detect_cls, result); + + case BF_CHIP_TYPE_TOFINO: + return _sfp_set_bf_tofino_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_sfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = sft_detect_transvr_class(self); + switch(detect_val) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_SP_100); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + detect_val); + goto err_sfp_detect_if_speed_1; + } + /* Check by BR */ + detect_val = _sfp_detect_if_sp_by_br(self); + switch (detect_val) { + case TRANSVR_CLASS_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + default: + break; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_detect_if_speed_1; + +err_sfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_extended(self); + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_100G_AOC; + + case 0x06: /* 100G CWDM4 */ + case 0x09: /* Obsolete (assigned before 100G CWDM4 MSA required FEC) */ + case 0x17: /* 100G CLR4 */ + case 0x1A: /* 100GE-DWDM2 */ + return TRANSVR_CLASS_OPTICAL_100G; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_100G_SR4; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_100G_LR4; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_100G_ER4; + + case 0x07: /* 100G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_100G_PSM4; + + case 0x12: /* 40G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_40G; + + case 0x11: /* 4 x 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + + case 0x10: /* 40GBASE-ER4 */ + return TRANSVR_CLASS_OPTICAL_40G_ER4; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L4_100G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_class_by_10_40_100_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_10_40_100_ethernet(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 40G Optical */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 40G Active Cable (XLPPI) */ + return TRANSVR_CLASS_OPTICAL_40G_AOC; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 40GBASE-SR4 */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + } + if ( (detect_val & 0x02) == 0x02) { /* 00000010 : 40GBASE-LR4 */ + return TRANSVR_CLASS_OPTICAL_40G_LR4; + } + if ( (detect_val & 0x08) == 0x08) { /* 00001000 : 40GBASE-CR4 */ + return TRANSVR_CLASS_COPPER_L4_40G; + } + /* Case: 10G Optical */ + if ( (detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + } + /* Case: Extend Compliance */ + if ( ((detect_val & 0x80) == 0x80) ){ /* 10000000 : Use Extend Compliance */ + return TRANSVR_CLASS_EXTEND_COMP; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_10g = 0x10; + int upper_bound_10g = 0x25; + int lower_bound_40g = 0x60; + int upper_bound_40g = 0x75; + int lower_bound_100g = 0x60; + int upper_bound_100g = 0x75; + int used_extend_br = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + int extend_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 40G */ + if ((notmal_br >= lower_bound_40g) && + (notmal_br <= upper_bound_40g) ) { + return TRANSVR_CLASS_40G; + } + /* Check 100G */ + if (notmal_br == used_extend_br) { + extend_br = (int)(self->extbr); /* updated by update_all() */ + if ((extend_br >= lower_bound_100g) && + (extend_br <= upper_bound_100g) ) { + return TRANSVR_CLASS_100G; + } + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_qsfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int conn_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _qsfp_detect_if_sp_by_br(self); + conn_val = _qsfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 (Multifiber Parallel Optic) */ + case 0x0d: /* MPO 2x16 */ + goto ok_qsfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + goto ok_qsfp_detect_class_by_feature_4_copper; + case 0x23: /* No separable connector */ + if ((_qsfp_get_comp_fc_link_length(self) > 0) || + (_qsfp_get_comp_fc_trans_tech(self) > 0) || + (_qsfp_get_comp_fc_trans_media(self) > 0) || + (_qsfp_get_comp_fc_speed(self) > 0) ) { + goto ok_qsfp_detect_class_by_feature_4_aoc; + } + goto ok_qsfp_detect_class_by_feature_4_copper; + default: + snprintf(err_msg, sizeof(err_msg), + "_qsfp_get_connector_type return Non define value:%d", + conn_val); + goto err_qsfp_detect_class_by_feature_1; + } + return TRANSVR_CLASS_UNSPECIFIED; + +ok_qsfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_100G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_100G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_100G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_100G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_100G; + + case TRANSVR_CLASS_40G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_40G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_40G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_40G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_40G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_Q_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_OPTICAL_100G_AOC; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_OPTICAL_40G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_Q_AOC; + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_COPPER_L4_100G; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_COPPER_L4_40G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L4_10G; + default: + return TRANSVR_CLASS_COPPER; + } + +err_qsfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", + __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +qsft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _qsfp_detect_class_by_extend_comp(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_COPPER_L4_100G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check 10/40G/100G Ethernet Compliance */ + detect_val = _qsfp_detect_class_by_10_40_100_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_COPPER_L4_40G: + return detect_val; + case TRANSVR_CLASS_EXTEND_COMP: + /* Format incorrect case (We already checked the Extend + * Compliance is 0 + */ + snprintf(err_msg, sizeof(err_msg), + "Transceiver format incorrect"); + goto err_qsft_detect_transvr_class_1; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10/40/100:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check by Connector type, BR and wavelength */ + detect_val = _qsfp_detect_class_by_feature(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_COPPER_L4_100G: + case TRANSVR_CLASS_COPPER_L4_40G: + case TRANSVR_CLASS_COPPER_L4_10G: + case TRANSVR_CLASS_COPPER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined connector:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), + "Can not identify!"); + goto err_qsft_detect_transvr_class_1; + +err_qsft_detect_transvr_class_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: LR4 or LR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: /* Need Check: ER4 or ER */ + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_KR4); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_bf_tofino_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to BF looks like doesn't have interface type. + * We bypass it currently. + */ + int lmax = 8; + return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); +} + + +int +_qsfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = qsft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _qsfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TRIDENT_3: + case BCM_CHIP_TYPE_TOMAHAWK: + return _qsfp_set_tomahawk_if_type(self, detect_cls, result); + + case BF_CHIP_TYPE_TOFINO: + return _qsfp_set_bf_tofino_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 8; + char tmp_result[8] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = qsft_detect_transvr_class(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G Copper */ + case TRANSVR_CLASS_COPPER_L4_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + break; + /* Copper */ + case TRANSVR_CLASS_COPPER: + break; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined class case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Check br and extbr */ + detect_val = _qsfp_detect_if_sp_by_br(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + case TRANSVR_CLASS_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined BR case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_detect_if_speed_1; + +err_qsfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_common_set_lane_map_str(struct transvr_obj_s* self, + char *result) { + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + char err_msg[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_L_STR); + snprintf(result, LEN_TRANSVR_L_STR, "%s=", TRANSVR_UEVENT_KEY_LANE); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + if (tmp_val > 256) { + snprintf(err_msg, sizeof(err_msg), + "detect abnormal value:%d", tmp_val); + goto err_common_set_lane_map_str_1; + } + memset(tmp_str, 0, sizeof(tmp_str)); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_L_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_L_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_L_STR); + } + if (i == 0) { + goto err_common_set_lane_map_str_2; + } + return 0; + +err_common_set_lane_map_str_1: + SWPS_INFO("%s: %s", __func__, err_msg); +err_common_set_lane_map_str_2: + snprintf(result, LEN_TRANSVR_L_STR, "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_common_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action, + int (*detect_if_type)(struct transvr_obj_s *self, char *result), + int (*detect_if_speed)(struct transvr_obj_s *self, char *result), + int send_anyway) { + + char *uevent_envp[4]; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + char tmp_str[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_1[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_2[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_3[64] = DEBUG_TRANSVR_STR_VAL; + + if (TRANSVR_UEVENT_ENABLE != 1) { + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_get_if_lane(self, tmp_str) < 0) { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + } else { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, tmp_str); + } + switch (u_action) { + case KOBJ_ADD: + /* Detect type */ + if (detect_if_type(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface type fail!"); + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, tmp_str); + uevent_envp[0] = tmp_str_1; + /* Detect speed */ + if (detect_if_speed(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface speed fail!"); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, tmp_str); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + case KOBJ_REMOVE: + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + default: + snprintf(err_msg, sizeof(err_msg), "kobject_action:%d not support", u_action); + goto private_common_send_uevent_4_fail; + } + snprintf(err_msg, sizeof(err_msg), "%s", "Exception case"); + goto private_common_send_uevent_4_fail; + +private_common_send_uevent_4_fail: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + if (send_anyway) { + goto private_common_send_uevent_4_send; + } + return ERR_TRANSVR_UEVENT_FAIL; + +private_common_send_uevent_4_send: + return kobject_uevent_env(&(self->transvr_dev_p->kobj), + u_action, + uevent_envp); +} + +int +sfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_sfp_detect_if_type, + &_sfp_detect_if_speed, + send_anyway); +} + + +int +qsfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_qsfp_detect_if_type, + &_qsfp_detect_if_speed, + send_anyway); +} + + +int +fake_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + return EVENT_TRANSVR_TASK_DONE; +} + + +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; +} + + +static int +_is_except_happened_4_pmode(struct transvr_obj_s* self, + int new_state) { + + int event_chk = 0; + + if (self->temp == 0){ + return 0; + } + switch (new_state) { + case STATE_TRANSVR_INIT: + event_chk = EVENT_TRANSVR_EXCEP_INIT; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_CONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_UP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_DISCONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_DOWN; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_SWAPPED: + event_chk = EVENT_TRANSVR_EXCEP_SWAP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_UNEXCEPTED: + event_chk = EVENT_TRANSVR_EXCEP_EXCEP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_ISOLATED: + event_chk = EVENT_TRANSVR_EXCEP_ISOLATED; + goto check_event_happened_4_pmode; + + default: + SWPS_INFO("%s: unexcepted case:%d\n", __func__, new_state); + break; + } + return 0; + +check_event_happened_4_pmode: + if (self->temp == event_chk){ + return 1; + } + return 0; +} + + +int +common_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + /* [Return Value]: + * ERR_TRANSVR_UNINIT : (1) Initial not ready + * ERR_TRANSVR_UNPLUGGED : (1) Any -> Down + * ERR_TRANSVR_TASK_BUSY : (1) Wait Initial task + * ERR_TRANSVR_UNEXCPT : (1) Initial fail + * (2) Task fail + * (3) Reload fail + * ERR_TRNASVR_BE_ISOLATED : (1) Already be isolated + * OK Case (return 0) : (1) action_4_connected + * (2) action_4_nothing (initial retry) + */ + int curr_state[2]; + int old_state = self->state; + int old_type = self->type; + int new_state = STATE_TRANSVR_UNEXCEPTED; + int new_type = TRANSVR_TYPE_ERROR; + int return_val = ERR_TRANSVR_UNEXCPT; + + /* Never initial */ + if (self->state == STATE_TRANSVR_NEW) { + goto comfsm_action_4_reinit_obj; + } + /* Detect current state */ + switch (detect_transvr_state(self, curr_state)) { + case 0: + new_state = curr_state[0]; + new_type = curr_state[1]; + break; + + case ERR_TRNASVR_BE_ISOLATED: + new_state = STATE_TRANSVR_ISOLATED; + new_type = old_type; + break; + + case ERR_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case ERR_TRANSVR_UNEXCPT: + default: + new_state = STATE_TRANSVR_UNEXCEPTED; + new_type = old_type; + } + /* State handling */ + switch (old_state) { + case STATE_TRANSVR_INIT: /* INIT -> */ + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 1-1: UP -> INIT */ + SWPS_INFO("Detect %s is present. :1-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 1-2: UP -> UP */ + return_val = 0; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 1-3: UP -> DOWN */ + SWPS_INFO("Detect %s is removed. :1-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 1-4: UP -> SWAP */ + SWPS_INFO("Detect %s is swapped. :1-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 1-5: UP -> UNEXPET */ + SWPS_INFO("Detect %s has error. :1-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 1-6: UP -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :1-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_DISCONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 2-1: DOWN -> INIT */ + SWPS_INFO("Detect %s is present. :2-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 2-2: DOWN -> UP */ + SWPS_INFO("Detect %s is present. :2-2\n",self->swp_name); + goto comfsm_action_4_reinit_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 2-3: DOWN -> DOWN */ + return_val = ERR_TRANSVR_UNPLUGGED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_SWAPPED: /* Case 2-4: DOWN -> SWAP */ + SWPS_INFO("Detect %s is swapped. :2-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 2-5: DOWN -> UNEXPET */ + SWPS_INFO("Detect %s has error. :2-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 2-6: DOWN -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :2-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_UNEXCEPTED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 3-1: UNEXPET -> INIT */ + SWPS_INFO("Detect %s is present. :3-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 3-2: UNEXPET -> UP */ + SWPS_INFO("Detect %s is present. :3-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 3-3: UNEXPET -> DOWN */ + SWPS_INFO("Detect %s is removed. :3-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 3-4: UNEXPET -> SWAP */ + SWPS_INFO("Detect %s is swapped. :3-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 3-5: UNEXPET -> UNEXPET */ + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRANSVR_UNEXCPT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 3-6: UNEXPET -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :3-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 4-1: ISOLATE -> INIT */ + SWPS_INFO("Detect %s internal error. :4-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 4-2: ISOLATE -> UP */ + SWPS_INFO("Detect %s internal error. :4-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 4-3: ISOLATE -> DOWN */ + SWPS_INFO("Detect %s is removed. :4-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 4-4: ISOLATE -> SWAP */ + SWPS_INFO("Detect %s internal error. :4-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 4-5: ISOLATE -> UNEXPET */ + SWPS_INFO("Detect %s internal error. :4-5\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 4-6: ISOLATE -> ISOLATE */ + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + default: + break; + } + goto comfsm_action_4_unexpected; + + default: + break; + } + goto comfsm_action_4_unexpected; + + +comfsm_action_4_keep_state: + return return_val; + +comfsm_action_4_reinit_obj: + SWPS_DEBUG("FSM action: %s re-initial.\n", self->swp_name); + return_val = _transvr_init_handler(self); + goto comfsm_action_4_identify_event; + +comfsm_action_4_reload_obj: + SWPS_DEBUG("FSM action: %s reload.\n", self->swp_name); + self->type = new_type; + return_val = reload_transvr_obj(self, new_type); + goto comfsm_action_4_identify_event; + +comfsm_action_4_identify_event: + switch (return_val) { + case EVENT_TRANSVR_INIT_UP: + case EVENT_TRANSVR_TASK_DONE: + goto comfsm_action_4_connected; + + case EVENT_TRANSVR_INIT_DOWN: + goto comfsm_action_4_disconnected; + + case EVENT_TRANSVR_INIT_REINIT: + goto comfsm_action_4_nothing; + + case EVENT_TRANSVR_TASK_WAIT: + self->state = STATE_TRANSVR_INIT; + return ERR_TRANSVR_TASK_BUSY; + + case EVENT_TRANSVR_TASK_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_TASK_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_INIT_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_INIT_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_RELOAD_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_RELOAD_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case EVENT_TRANSVR_EXCEP_ISOLATED: + goto comfsm_action_4_isolate_obj; + + default: + SWPS_INFO("%s detect undefined event:%d.\n", self->swp_name, return_val); + goto comfsm_action_4_unexpected; + } + +comfsm_action_4_nothing: + SWPS_DEBUG("FSM action: %s do nothing.\n", self->swp_name); + return 0; + +comfsm_action_4_connected: + SWPS_DEBUG("FSM action: %s Connected.\n", self->swp_name); + self->state = STATE_TRANSVR_CONNECTED; + self->type = new_type; + self->send_uevent(self, KOBJ_ADD); + _transvr_clean_retry(self); + return 0; + +comfsm_action_4_disconnected: + SWPS_DEBUG("FSM action: %s Disconnected. \n", self->swp_name); + self->state = STATE_TRANSVR_DISCONNECTED; + self->temp = EVENT_TRANSVR_TASK_DONE; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_retry(self); + _transvr_clean_handler(self); + return ERR_TRANSVR_UNPLUGGED; + +comfsm_action_4_report_i2c_crash: + SWPS_DEBUG("FSM action: %s report I2C crash.\n", self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_I2C_CRASH; + +comfsm_action_4_isolate_obj: + SWPS_DEBUG("FSM action: %s isolate.\n", self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return ERR_TRNASVR_BE_ISOLATED; + +comfsm_action_4_unexpected: + SWPS_INFO("FSM action: %s unexpected.\n", self->swp_name); + SWPS_INFO("Dump: :%d :0x%02x :%d :0x%02x\n", + old_state, old_type, new_state, new_type); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_handler(self); + 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; +} + + +int +fake_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + + +/* ========== Object functions for Initial procedure ========== + */ +int +transvr_init_common(struct transvr_obj_s *self){ + /* Nothing to update */ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_fake(struct transvr_obj_s *self){ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_sfp(struct transvr_obj_s *self){ + + int tmp_val = DEBUG_TRANSVR_INT_VAL; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_msg = "ERR"; + + self->info = sft_detect_transvr_class(self); + /* Disable auto_config */ + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + /* Handle multi-rate */ + err_code = initfunc_sfp_handle_multi_rate_mode(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_multi_rate_mode fail!"; + goto err_transvr_init_sfp_1; + } + /* Handle 1G- RJ45 */ + tmp_val = err_code; + err_code = initfunc_sfp_handle_1g_rj45(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_1g_rj45 fail!"; + goto err_transvr_init_sfp_1; + } + tmp_val = (tmp_val > err_code ? tmp_val : err_code); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_sfp_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_code, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp(struct transvr_obj_s *self){ + + int err = EVENT_TRANSVR_EXCEP_EXCEP; + char *emsg = "ERR"; + + self->info = qsft_detect_transvr_class(self); + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + err = initfunc_qsfp_handle_power_mode(self); + if (err < 0){ + emsg = "initfunc_qsfp_handle_tx_disable fail!"; + goto err_transvr_init_qsfp; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, emsg, err, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp28(struct transvr_obj_s *self){ + + int tmp_val = EVENT_TRANSVR_EXCEP_EXCEP; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_msg = "ERR"; + + /* Handle QSFP common */ + err_val = transvr_init_qsfp(self); + if (err_val < 0){ + err_msg = "transvr_init_qsfp fail!"; + goto err_transvr_init_qsfp28_1; + } + /* Disable auto_config */ + if (!self->auto_config) { + return err_val; + } + /* Handle CDR */ + tmp_val = err_val; + err_val = initfunc_qsfp28_handle_cdr(self); + if (err_val < 0){ + err_msg = "Handle CDR fail!"; + goto err_transvr_init_qsfp28_1; + } + tmp_val = (tmp_val > err_val ? tmp_val : err_val); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp28_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +/* ========== 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 +_is_transvr_support_ctle(struct transvr_obj_s *self) { + + switch (self->info) { + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return 1; + default: + break; + } + return 0; +} + + +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; + } + if (self->clean == NULL) { + snprintf(emsg, elimit, "clean() is null"); + goto initer_err_case_unexcept_0; + } + self->clean(self); + + /* 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_1; + } + + /* 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_1; + } + } + + /* 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_1; + } + + /* 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_1; + } + goto initer_ok_case_up; + + +initer_ok_case_wait: + self->dump_all(self); + return EVENT_TRANSVR_TASK_WAIT; + +initer_ok_case_up: + self->state = STATE_TRANSVR_CONNECTED; + self->temp = 0; + self->dump_all(self); + 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_1: + self->clean(self); +initer_err_case_unexcept_0: + self->state = STATE_TRANSVR_UNEXCEPTED; + if (_is_except_happened_4_pmode(self, d_state) && + (self->mode == TRANSVR_MODE_POLLING) ){ + SWPS_INFO("%s: %s :%s\n", __func__, emsg, self->swp_name); + SWPS_INFO("Dump: :%d :%d :%d :%d\n", + self->state, self->type, d_state, d_type); + } + 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; +} + + +/* ========== Object functions for Clean procedure ========== + */ +int +_transvr_clean_handler(struct transvr_obj_s *self){ + + int retval = DEBUG_TRANSVR_INT_VAL; + + if (!self->clean) { + SWPS_ERR("%s: %s clean() is NULL.\n", + __func__, self->swp_name); + return EVENT_TRANSVR_TASK_FAIL; + } + retval = self->clean(self); + if (retval != EVENT_TRANSVR_TASK_DONE){ + SWPS_ERR("%s: %s clean() fail. [ERR]:%d\n", + __func__, self->swp_name, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +common_transvr_clean(struct transvr_obj_s *self){ + + transvr_task_free_all(self); + transvr_cache_free_all(self); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +qsfp_transvr_clean(struct transvr_obj_s *self){ + + int retval; + int lpower_config = 1; + + retval = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (retval < 0){ + SWPS_ERR("%s: Set lpmod fail! :%d\n", + __func__, retval); + return retval; + } + retval = common_transvr_clean(self); + if (retval < 0){ + SWPS_ERR("%s: common_transvr_clean fail! :%d\n", + __func__, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +fake_transvr_clean(struct transvr_obj_s *self){ + + return EVENT_TRANSVR_TASK_DONE; +} + + +/* ========== Object functions for check and update ========== + */ +int +common_transvr_check(struct transvr_obj_s *self){ + + char fun_str[32] = "common_transvr_check"; + + if (self->mode != TRANSVR_MODE_POLLING) { + SWPS_ERR("%s: mode:%d is not TRANSVR_MODE_POLLING\n", + fun_str, self->mode); + return ERR_TRANSVR_UNEXCPT; + } + /* Trigger delay task */ + transvr_task_run_all(self); + /* Trigger state machine to check and update */ + return self->fsm_4_polling(self, fun_str); +} + + +int +fake_transvr_check(struct transvr_obj_s *self){ + return 0; +} + + +/* ========== Functions for Factory pattern ========== + */ +static int +setup_transvr_public_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = unsupported_get_func; + self->get_br = common_get_br; + self->get_len_sm = sfp_get_len_sm; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = sfp_get_comp_eth_1; + self->get_comp_eth_10 = sfp_get_comp_eth_10; + self->get_comp_eth_10_40 = unsupported_get_func; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = sfp_get_rate_id; + self->get_soft_rs0 = sfp_get_soft_rs0; + self->get_soft_rs1 = sfp_get_soft_rs1; + self->get_info = common_get_info; + self->get_if_type = sfp_get_if_type; + self->get_if_speed = sfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = sfp_get_transvr_temp; + self->get_curr_vol = sfp_get_transvr_voltage; + self->get_soft_rx_los = unsupported_get_func2; + self->get_soft_tx_disable = unsupported_get_func2; + self->get_soft_tx_fault = unsupported_get_func2; + self->get_auto_tx_disable = unsupported_get_func2; + self->get_tx_bias = sfp_get_transvr_tx_bias; + self->get_tx_power = sfp_get_transvr_tx_power; + self->get_rx_power = sfp_get_transvr_rx_power; + self->get_tx_eq = sfp_get_transvr_tx_eq; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = sfp_get_transvr_rx_em; + self->get_wavelength = sfp_get_wavelength; + self->get_extphy_offset = sfp_get_1g_rj45_extphy_offset; + self->get_extphy_reg = sfp_get_1g_rj45_extphy_reg; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = sfp_set_soft_rs0; + self->set_soft_rs1 = sfp_set_soft_rs1; + self->set_soft_tx_disable = unsupported_set_func; + self->set_auto_tx_disable = unsupported_set_func; + self->set_tx_eq = sfp_set_tx_eq; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = sfp_set_rx_em; + self->set_extphy_offset = sfp_set_1g_rj45_extphy_offset; + self->set_extphy_reg = sfp_set_1g_rj45_extphy_reg; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = unsupported_get_func2; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = unsupported_get_func2; + self->get_wavelength = qsfp_get_wavelength; + self->get_extphy_offset = unsupported_get_func2; + self->get_extphy_reg = unsupported_get_func2; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = unsupported_set_func; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = unsupported_set_func; + self->set_extphy_offset = unsupported_set_func; + self->set_extphy_reg = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = qsfp_get_cdr; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = qsfp_get_transvr_tx_eq; + self->get_rx_am = qsfp_get_transvr_rx_am; + self->get_rx_em = qsfp_get_transvr_rx_em; + self->get_wavelength = qsfp_get_wavelength; + self->get_extphy_offset = unsupported_get_func2; + self->get_extphy_reg = unsupported_get_func2; + self->set_cdr = qsfp_set_cdr; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = qsfp_set_tx_eq; + self->set_rx_am = qsfp_set_rx_am; + self->set_rx_em = qsfp_set_rx_em; + self->set_extphy_offset = unsupported_set_func; + self->set_extphy_reg = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_FAKE: + self->get_id = fake_get_hex; + self->get_ext_id = fake_get_hex; + self->get_connector = fake_get_hex; + self->get_vendor_name = fake_get_str; + self->get_vendor_pn = fake_get_str; + self->get_vendor_rev = fake_get_str; + self->get_vendor_sn = fake_get_str; + self->get_power_cls = fake_get_int; + self->get_br = fake_get_hex; + self->get_len_sm = fake_get_int; + self->get_len_smf = fake_get_int; + self->get_len_om1 = fake_get_int; + self->get_len_om2 = fake_get_int; + self->get_len_om3 = fake_get_int; + self->get_len_om4 = fake_get_int; + self->get_comp_rev = fake_get_hex; + self->get_comp_eth_1 = fake_get_hex; + self->get_comp_eth_10 = fake_get_hex; + self->get_comp_eth_10_40 = fake_get_hex; + self->get_comp_extend = fake_get_hex; + self->get_cdr = fake_get_hex; + self->get_rate_id = fake_get_hex; + self->get_soft_rs0 = fake_get_binary; + self->get_soft_rs1 = fake_get_binary; + self->get_info = fake_get_int; + self->get_if_type = fake_get_str; + self->get_if_speed = fake_get_str; + self->get_if_lane = fake_get_str; + self->get_curr_temp = fake_get_str; + self->get_curr_vol = fake_get_str; + self->get_soft_rx_los = fake_get_str; + self->get_soft_tx_disable = fake_get_str; + self->get_soft_tx_fault = fake_get_str; + self->get_auto_tx_disable = fake_get_str; + self->get_tx_bias = fake_get_str; + self->get_tx_power = fake_get_str; + self->get_rx_power = fake_get_str; + self->get_tx_eq = fake_get_str; + self->get_rx_am = fake_get_str; + self->get_rx_em = fake_get_str; + self->get_wavelength = fake_get_str; + self->get_extphy_offset = fake_get_str; + self->get_extphy_reg = fake_get_str; + self->set_cdr = fake_set_hex; + self->set_soft_rs0 = fake_set_int; + self->set_soft_rs1 = fake_set_int; + self->set_soft_tx_disable = fake_set_int; + self->set_auto_tx_disable = fake_set_int; + self->set_tx_eq = fake_set_int; + self->set_rx_am = fake_set_int; + self->set_rx_em = fake_set_int; + self->set_extphy_offset = fake_set_hex; + self->set_extphy_reg = fake_set_hex; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static int +setup_transvr_private_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->init = transvr_init_sfp; + self->clean = common_transvr_clean; + self->check = common_transvr_check; + self->update_all = _sfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = sfp_send_uevent; + self->dump_all = sfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->init = transvr_init_qsfp; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->init = transvr_init_qsfp28; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_FAKE: + self->init = transvr_init_fake; + self->clean = fake_transvr_clean; + self->check = fake_transvr_check; + self->update_all = fake_transvr_update; + self->fsm_4_direct = fake_fsm_4_direct_mode; + self->fsm_4_polling = fake_fsm_4_polling_mode; + self->send_uevent = fake_send_uevent; + self->dump_all = fake_transvr_dump; + 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_SFP: + return &eeprom_map_sfp; + 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 */ + case TRANSVR_MODE_POLLING: /* Polling mode, read from cache */ + 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_transvr_dsize_attr(struct transvr_obj_s *self){ + + char *emsg = DEBUG_TRANSVR_STR_VAL; + + self->vendor_name = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_name){ + emsg = "vendor_name"; + goto err_setup_d_attr; + } + self->vendor_pn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_pn){ + emsg = "vendor_pn"; + goto err_setup_d_attr; + } + self->vendor_rev = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_rev){ + emsg = "vendor_rev"; + goto err_setup_d_attr; + } + self->vendor_sn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_sn){ + emsg = "vendor_sn"; + goto err_setup_d_attr; + } + self->worker_p = NULL; + return 0; + +err_setup_d_attr: + SWPS_ERR("%s: %s kzalloc fail!", __func__, emsg); + return ERR_TRANSVR_UNEXCPT; +} + + +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 dynamic size attributes */ + if (setup_transvr_dsize_attr(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_public_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_private_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare i2c client object */ + if (setup_i2c_client(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + return result_p; + +err_create_transvr_dattr_fail: + kfree(result_p->vendor_sn); + kfree(result_p->vendor_rev); + kfree(result_p->vendor_pn); + kfree(result_p->vendor_name); +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; + } + /* Replace call back functions */ + if (setup_transvr_public_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + 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; +} + + +int +isolate_transvr_obj(struct transvr_obj_s *self) { + + self->state = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s be isolated\n", __func__, self->swp_name); + return 0; +} + + +int +resync_channel_tier_2(struct transvr_obj_s *self) { + + int val = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_ISOLATED) { + return 0; + } + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + val = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (val < 0) { + return -1; + } + return 0; +} + + +/* ----------------------------------------- + * ToDo List + * ----------------------------------------- + * 1. _sfp_detect_class_by_feature() + * => Need check ACC use case. + * 2. _sfp_detect_class_by_1g_ethernet() + * => Need check 0.1G use case. + * 3. Loopback transceiver use case. + * => Less much data + * 4. _qsfp_detect_class_by_extend_comp() + * => Verify 100G CWDM4 + * => Verify Obsolete (assigned before 100G CWDM4 MSA required FEC) + * => Verify 100G CLR4 + * => Verify 100GE-DWDM2 + * => Verify 40G PSM4 Parallel SMF + * => Verify 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. + * => Verify 100G ACC or 25GAUI C2M ACC. + * => Verify 25GBASE-LR + * => Verify 40G Active Cable (XLPPI) + */ + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/transceiver.h new file mode 100644 index 000000000000..f17b7fde71b1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/transceiver.h @@ -0,0 +1,815 @@ +/* + * 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. + */ + +#ifndef TRANSCEIVER_H +#define TRANSCEIVER_H + +#include + +/* advanced features control */ +#define TRANSVR_INFO_DUMP_ENABLE (1) +#define TRANSVR_INFO_CACHE_ENABLE (1) +#define TRANSVR_UEVENT_ENABLE (1) + +/* 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 class for base info */ +#define TRANSVR_CLASS_UNSPECIFIED (0) +#define TRANSVR_CLASS_ERROR (-26001) +#define TRANSVR_CLASS_1G (26001) +#define TRANSVR_CLASS_10G (26011) +#define TRANSVR_CLASS_25G (26021) +#define TRANSVR_CLASS_40G (26041) +#define TRANSVR_CLASS_100G (26101) +#define TRANSVR_CLASS_NO_SPERARABLE (26901) +#define TRANSVR_CLASS_EXTEND_COMP (26902) +/* Transceiver class for Optical 1G */ +#define TRANSVR_CLASS_OPTICAL (27000) +#define TRANSVR_CLASS_OPTICAL_100 (27001) +#define TRANSVR_CLASS_OPTICAL_1G (27002) +#define TRANSVR_CLASS_OPTICAL_1G_AOC (27003) +#define TRANSVR_CLASS_OPTICAL_1G_SX (27004) +#define TRANSVR_CLASS_OPTICAL_1G_LX (27005) +#define TRANSVR_CLASS_OPTICAL_1G_EX (27006) +/* Transceiver class for Optical 10G */ +#define TRANSVR_CLASS_OPTICAL_10G (27010) +#define TRANSVR_CLASS_OPTICAL_10G_S_AOC (27011) +#define TRANSVR_CLASS_OPTICAL_10G_S_SR (27012) +#define TRANSVR_CLASS_OPTICAL_10G_S_LR (27013) +#define TRANSVR_CLASS_OPTICAL_10G_S_ER (27014) +#define TRANSVR_CLASS_OPTICAL_10G_Q_AOC (27015) +#define TRANSVR_CLASS_OPTICAL_10G_Q_SR (27016) +#define TRANSVR_CLASS_OPTICAL_10G_Q_LR (27017) +#define TRANSVR_CLASS_OPTICAL_10G_Q_ER (27018) +/* Transceiver class for Optical 25G */ +#define TRANSVR_CLASS_OPTICAL_25G (27020) +#define TRANSVR_CLASS_OPTICAL_25G_AOC (27021) +#define TRANSVR_CLASS_OPTICAL_25G_SR (27022) +#define TRANSVR_CLASS_OPTICAL_25G_LR (27023) +#define TRANSVR_CLASS_OPTICAL_25G_ER (27024) +/* Transceiver class for Optical 40G */ +#define TRANSVR_CLASS_OPTICAL_40G (27040) +#define TRANSVR_CLASS_OPTICAL_40G_AOC (27041) +#define TRANSVR_CLASS_OPTICAL_40G_SR4 (27042) +#define TRANSVR_CLASS_OPTICAL_40G_LR4 (27043) +#define TRANSVR_CLASS_OPTICAL_40G_ER4 (27044) +/* Transceiver class for Optical 100G */ +#define TRANSVR_CLASS_OPTICAL_100G (27100) +#define TRANSVR_CLASS_OPTICAL_100G_AOC (27101) +#define TRANSVR_CLASS_OPTICAL_100G_SR4 (27102) +#define TRANSVR_CLASS_OPTICAL_100G_LR4 (27103) +#define TRANSVR_CLASS_OPTICAL_100G_ER4 (27104) +#define TRANSVR_CLASS_OPTICAL_100G_PSM4 (27105) +/* Transceiver class for Copper */ +#define TRANSVR_CLASS_COPPER (28000) +#define TRANSVR_CLASS_COPPER_L1_1G (28001) +#define TRANSVR_CLASS_COPPER_L1_10G (28011) +#define TRANSVR_CLASS_COPPER_L4_10G (28012) +#define TRANSVR_CLASS_COPPER_L1_25G (28021) +#define TRANSVR_CLASS_COPPER_L4_40G (28041) +#define TRANSVR_CLASS_COPPER_L4_100G (28101) +/* Transceiver class for Base-T */ +#define TRANSVR_CLASS_BASE_T_1000 (29001) +#define TRANSVR_CLASS_BASE_T_1000_up (29002) +/* For uevent message */ +#define TRANSVR_UEVENT_KEY_IF "IF_TYPE" +#define TRANSVR_UEVENT_KEY_SP "IF_SPEED" +#define TRANSVR_UEVENT_KEY_LANE "IF_LANE" +#define TRANSVR_UEVENT_UNKNOW "UNKNOW" +#define TRANSVR_IF_KR "KR" +#define TRANSVR_IF_KR4 "KR4" +#define TRANSVR_IF_SR "SR" +#define TRANSVR_IF_SR4 "SR4" +#define TRANSVR_IF_SFI "SFI" +#define TRANSVR_IF_IF_GMII "GMII" +#define TRANSVR_IF_IF_XGMII "XGMII" +#define TRANSVR_IF_SP_100 "100" +#define TRANSVR_IF_SP_1G "1000" +#define TRANSVR_IF_SP_10G "10000" +#define TRANSVR_IF_SP_25G "25000" +#define TRANSVR_IF_SP_40G "40000" +#define TRANSVR_IF_SP_100G "100000" + +/* Transceiver mode define */ +#define TRANSVR_MODE_DIRECT (21000) +#define TRANSVR_MODE_POLLING (21001) + +/* 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. */ + +/* Task state define */ +#define STATE_T_TASK_WAIT (110) +#define STATE_T_TASK_DONE (0) +#define STATE_T_TASK_INIT (-110) +#define STATE_T_TASK_FAIL (-410) + + +/* 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_UEVENT_FAIL (-213) +#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_EXTPHY_ADDR_56 (0x56) +#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_SFP "SFP" +#define STR_TRANSVR_QSFP "QSFP" +#define STR_TRANSVR_QSFP_PLUS "QSFP+" +#define STR_TRANSVR_QSFP28 "QSFP28" + +/* For transvr buf len */ +#define LEN_TRANSVR_S_STR (16) +#define LEN_TRANSVR_M_STR (32) +#define LEN_TRANSVR_L_STR (64) + +/* Optical wavelength */ +#define VAL_OPTICAL_WAVELENGTH_SR (850) +#define VAL_OPTICAL_WAVELENGTH_LR (1310) +#define VAL_OPTICAL_WAVELENGTH_ER (1550) + +/* BCM chip type define */ +#define BCM_CHIP_TYPE_TRIDENT_2 (31001) /* Magnolia, Hudson32i, Spruce */ +#define BCM_CHIP_TYPE_TOMAHAWK (31002) /* Redwood, Cypress, Sequoia */ +#define BCM_CHIP_TYPE_TRIDENT_3 (31003) /* Maple */ + +#define BF_CHIP_TYPE_TOFINO (31011) /* Lavender */ + +/* Info from transceiver EEPROM */ +struct eeprom_map_s { + int addr_br; int page_br; int offset_br; int length_br; + int addr_cdr; int page_cdr; int offset_cdr; int length_cdr; + int addr_comp_rev; int page_comp_rev; int offset_comp_rev; int length_comp_rev; + int addr_connector; int page_connector; int offset_connector; int length_connector; + int addr_diag_type; int page_diag_type; int offset_diag_type; int length_diag_type; + int addr_extbr; int page_extbr; int offset_extbr; int length_extbr; + int addr_ext_id; int page_ext_id; int offset_ext_id; int length_ext_id; + int addr_id; int page_id; int offset_id; int length_id; + int addr_len_sm; int page_len_sm; int offset_len_sm; int length_len_sm; + int addr_len_smf; int page_len_smf; int offset_len_smf; int length_len_smf; + int addr_len_om1; int page_len_om1; int offset_len_om1; int length_len_om1; + int addr_len_om2; int page_len_om2; int offset_len_om2; int length_len_om2; + int addr_len_om3; int page_len_om3; int offset_len_om3; int length_len_om3; + int addr_len_om4; int page_len_om4; int offset_len_om4; int length_len_om4; + int addr_option; int page_option; int offset_option; int length_option; + int addr_rate_id; int page_rate_id; int offset_rate_id; int length_rate_id; + int addr_rx_am; int page_rx_am; int offset_rx_am; int length_rx_am; + int addr_rx_em; int page_rx_em; int offset_rx_em; int length_rx_em; + int addr_rx_los; int page_rx_los; int offset_rx_los; int length_rx_los; + int addr_rx_power; int page_rx_power; int offset_rx_power; int length_rx_power; + int addr_soft_rs0; int page_soft_rs0; int offset_soft_rs0; int length_soft_rs0; + int addr_soft_rs1; int page_soft_rs1; int offset_soft_rs1; int length_soft_rs1; + int addr_temp; int page_temp; int offset_temp; int length_temp; + int addr_trancomp; int page_trancomp; int offset_trancomp; int length_trancomp; + int addr_trancomp_ext; int page_trancomp_ext; int offset_trancomp_ext; int length_trancomp_ext; + int addr_tx_bias; int page_tx_bias; int offset_tx_bias; int length_tx_bias; + int addr_tx_disable; int page_tx_disable; int offset_tx_disable; int length_tx_disable; + int addr_tx_eq; int page_tx_eq; int offset_tx_eq; int length_tx_eq; + int addr_tx_fault; int page_tx_fault; int offset_tx_fault; int length_tx_fault; + int addr_tx_power; int page_tx_power; int offset_tx_power; int length_tx_power; + int addr_vendor_name; int page_vendor_name; int offset_vendor_name; int length_vendor_name; + int addr_vendor_pn; int page_vendor_pn; int offset_vendor_pn; int length_vendor_pn; + int addr_vendor_rev; int page_vendor_rev; int offset_vendor_rev; int length_vendor_rev; + int addr_vendor_sn; int page_vendor_sn; int offset_vendor_sn; int length_vendor_sn; + int addr_voltage; int page_voltage; int offset_voltage; int length_voltage; + int addr_wavelength; int page_wavelength; int offset_wavelength; int length_wavelength; +}; + + +struct transvr_worker_s; + +/* Class of transceiver object */ +struct transvr_obj_s { + + /* ========== Object private property ========== + * [Prop]: id + * [Desc]: Type of serial transceiver. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh /QSFP28:11h + */ + uint8_t id; + + /* [Prop]: connector + * [Desc]: Connector type. + * [Note]: SFP : A0h / 2 + * QSFP: 00h / 130 + */ + uint8_t connector; + + /* [Prop]: transvr_comp + * [Desc]: Transceiver compliance code. + * [Note]: SFP: SFF-8472 + * - Normal : A0h / offset 3-10 + * - Extended: A0h / offset 36 + * QSFP: SFF-8436 & SFF-8636 + * - Normal : 00h / offset 131-138 + * - Extended: 00h / offset 192 + */ + uint8_t transvr_comp[8]; + uint8_t transvr_comp_ext; + + /* [Prop]: vendor_name + * [Desc]: SFP vendor name (ASCII 16 byte char). + * [Note]: ex:FINISAR CORP. + */ + char *vendor_name; + + /* [Prop]: vendor_pn + * [Desc]: Part number provided by SFP vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_pn; + + /* [Prop]: vendor_rev + * [Desc]: Revision level for part number provided by vendor (ASCII 4 byte char). + * [Note]: + */ + char *vendor_rev; + + /* [Prop]: vendor_sn + * [Desc]: Serial number provided by vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_sn; + + /* [Prop]: Extended identifier + * [Desc]: SFP: + * => None + * + * QSFP: + * => This byte contained two information: + * (1) Power consumption class + * (2) CDR function present + * [Note]: Bit description as below: + * [SFP] + * None + * + * [QSFP] + * (1) Power consumption class: + * Class 1: 1.5W (Bit6-7 = 00:) + * Class 2: 2.0W (Bit6-7 = 01:) + * Class 3: 2.5W (Bit6-7 = 10:) + * Class 4: 3.5W (Bit6-7 = 11:) + * Class 5: 4.0W (Bit0-1 = 01:) + * Class 6: 4.5W (Bit0-1 = 10:) + * Class 7: 5.0W (Bit0-1 = 11:) + * (2) CDR function present: + * Bit2: 0 = No CDR in RX + * 1 = CDR present in RX + * Bit3: 0 = No CDR in TX + * 1 = CDR present in TX + */ + uint8_t ext_id; + + /* [Prop]: br + * [Desc]: Nominal bit rate, units of 100 MBits/sec. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh + * has val: 0x67 + * no val : + */ + uint8_t br; + + /* [Prop]: extbr + * [Desc]: Extended br (00h/222) + * [Desc]: Nominal bit rate per channel, units of 250 Mbps. + * Complements. Byte 140. See Table 32A. + */ + uint8_t extbr; + + /* [Prop]: len_sm + * [Desc]: Length (single mode)-(100's)m + * [Note]: This value specifies the link length that is supported by the transceiver + * while operating in compliance with the applicable standards using single mode + * fiber. The value is in units of 100 meters. A value of 255 means that the + * transceiver supports a link length greater than 25.4 km. A value of zero means + * that the transceiver does not support single mode fiber or that the length + * information must be determined from the transceiver technology. + */ + int len_sm; + + /* [Prop]: len_smf + * [Desc]: Length (single mode)-km + * [Note]: Addition to EEPROM data from original GBIC definition. This value specifies + * the link length that is supported by the transceiver while operating in + * compliance with the applicable standards using single mode fiber. The value + * is in units of kilometers. A value of 255 means that the transceiver supports + * a link length greater than 254 km. A value of zero means that the transceiver + * does not support single mode fiber or that the length information must be + * determined from the transceiver technology. + */ + int len_smf; + + /* [Prop]: len_om1 + * [Desc]: Link length supported for 62.5 um OM1 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om1; + + /* [Prop]: len_om2 + * [Desc]: Link length supported for 50 um OM2 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om2; + + /* [Prop]: len_om3 + * [Desc]: Length (50um, OM3) + * [Note]: This value specifies link length that is supported by the transceiver while + * operating in compliance with applicable standards using 50 micron multimode + * OM3 [2000 MHz*km] fiber. The value is in units of 10 meters. A value of 255 + * means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber + * or that the length information must be determined from the transceiver technology. + */ + int len_om3; + + /* [Prop]: len_om4 + * [Desc]: Length (50um, OM4) and Length (Active Cable or Copper) + * [Note]: For optical links, this value specifies link length that is supported by the + * transceiver while operating in compliance with applicable standards using 50 micron + * multimode OM4 [4700 MHz*km] fiber. The value is in units of 10 meters. A value of + * 255 means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber or that + * the length information must be determined from the transceiver codes specified in Table 5-3. + * + * For copper links, this value specifies minimum link length supported by the transceiver + * while operating in compliance with applicable standards using copper cable. For active + * cable, this value represents actual length. The value is in units of 1 meter. A value of 255 + * means the transceiver supports a link length greater than 254 meters. A value of zero means + * the transceiver does not support copper or active cables or the length information must be + * determined from transceiver technology. Further information about cable design, equalization, + * and connectors is usually required to guarantee meeting a particular length requirement. + */ + int len_om4; + + /* [Prop]: comp_rev + * [Desc]: SFF spec revision compliance + * [Note]: Indicates which revision of SFF SFF-8472 (SFP) / SFF-8636 (QSFP) the transceiver + * complies with. (unsigned integer) + */ + uint8_t comp_rev; + + /* [Prop]: CDR + * [Desc]: For transceivers with CDR capability, setting the CDR to ON engages the internal + * retiming function. Setting the CDR to OFF enables an internal bypassing mode ,which + * directs traffic around the internal CDR. (Reference: SFF-8636) + * [Note]: value=0xff: ON. + * value=0x00: OFF. + */ + uint8_t cdr; + + /* [Prop]: rate_id + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Addr: A0h / Offset: 13 + * 2. Value description: + * 00h Unspecified + * 01h SFF-8079 (4/2/1G Rate_Select & AS0/AS1) + * 02h SFF-8431 (8/4/2G Rx Rate_Select only) + * 03h Unspecified * + * 04h SFF-8431 (8/4/2G Tx Rate_Select only) + * 05h Unspecified * + * 06h SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) + * 07h Unspecified * + * 08h FC-PI-5 (16/8/4G Rx Rate_select only) High=16G only, Low=8G/4G + * 09h Unspecified * + * 0Ah FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) High=16G only, + * Low=8G/4G + * 0Bh Unspecified * + * 0Ch FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + * 0Dh Unspecified * + * 0Eh 10/8G Rx and Tx Rate_Select controlling the operation or locking + * modes of the internal signal conditioner, retimer or CDR, according + * to the logic table defined in Table 10-2, High Bit Rate + * (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = 8.5 Gb/s. In this mode, + * the default value of bit 110.3 (Soft Rate Select RS(0), Table 9-11) + * and of bit 118.3 (Soft Rate Select RS(1), Table 10-1) is 1. + * 0Fh Unspecified * + * 10h-FFh Unallocated + */ + int rate_id; + + /* [Prop]: soft_rs0 + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Writing '1' selects full bandwidth operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(0) or RS(0) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 110 / Bit: 3 + */ + uint8_t soft_rs0; + + /* [Prop]: soft_rs1 + * [Desc]: Soft Rate Select 1(TX). + * [Note]: 1. Writing '1' selects full bandwidth TX operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(1) or RS(1) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 118 / Bit: 3 + */ + uint8_t soft_rs1; + + /* [Prop]: diag_type + * [Desc]: DIAGNOSTIC MONITORING TYPE (A0h/92) + * [Note]: Description in SFF-8472 as below: + * Bit7: Reserved for legacy diagnostic implementations. Must be '0' for compliance + * with this document. + * Bit6: Digital diagnostic monitoring implemented (described in this document). + * Must be '1' for compliance with this document. + * Bit5 Internally calibrated + * Bit4 Externally calibrated + * Bit3 Received power measurement type.0 = OMA, 1 = average power + * Bit2 Address change required see section above, "addressing modes" + * Bit1-0 Unallocated + */ + uint8_t diag_type; + + /* [Prop]: curr_temp + * [Desc]: Transceiver Current Temperature (A2h/96-97) + * [Note]: 1. Dependent on diag_type. + * 2. 96: High byte + * 3. 97: Low byte + * 4. This feature only for SFP + */ + uint8_t curr_temp[2]; + + /* [Prop]: curr_vol + * [Desc]: Transceiver Current Voltage (SFP:A2h/108-109; QSFP:00h/22-23) + * [Note]: 1. Dependent on diag_type. + * 2. 98: High byte + * 3. 99: Low byte + * 4. This feature only for SFP + * 5. Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts + */ + uint8_t curr_voltage[2]; + + /* [Prop]: curr_tx_bias + * [Desc]: Transceiver TX Bias Current (SFP:A2h/100-101; QSFP:00h/26-27) + * [Note]: 1. Dependent on diag_type. + * 2. 100: High byte + * 3. 101: Low byte + * 4. This feature only for SFP + * 5. Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + uint8_t curr_tx_bias[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + uint8_t curr_tx_power[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + uint8_t curr_rx_power[8]; + + /* [Prop]: wavelength + * [Desc]: Wavelength or Copper Cable Attenuation + * [Note]: (Following is info from SFF-8636) + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is a + * 16-bit hex value with Byte 186 as high order byte and Byte 187 as low + * order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. If the free side device is identified as + * copper cable these registers will be used to define the cable attenuation. + * An indication of 0 dB attenuation refers to the case where the attenuation + * is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + uint8_t wavelength[2]; + + /* [Prop]: Amplitude control + * [Desc]: Amplitude control + * [Note]: QSFP28 => SFF-8636 03H Byte-238/239 + */ + uint8_t rx_am[2]; + + /* [Prop]: Emphasis control + * [Desc]: Emphasis control + * [Note]: SFP+/28 => SFF-8472 A2H Byte-115 + * QSFP28 => SFF-8636 03H Byte-236/237 + */ + uint8_t rx_em[2]; + + /* [Prop]: Soft Rx LOS + * [Desc]: Soft Rx LOS which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 3: + * - Bit 0: L-Rx1 LOS + * - Bit 1: L-Rx2 LOS + * - Bit 2: L-Rx3 LOS + * - Bit 3: L-Rx4 LOS + */ + uint8_t rx_los; + + /* [Prop]: Soft Tx Disable + * [Desc]: Soft Tx Disable which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Disable + * - Bit 1: Tx2 Disable + * - Bit 2: Tx3 Disable + * - Bit 3: Tx4 Disable + */ + uint8_t tx_disable; + + /* [Prop]: Soft Tx Fault + * [Desc]: Soft Tx Fault which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Fault + * - Bit 1: Tx2 Fault + * - Bit 2: Tx3 Fault + * - Bit 3: Tx4 Fault + */ + uint8_t tx_fault; + + /* [Prop]: Transceiver EQUALIZATION + * [Desc]: Transceiver EQUALIZATION + * [Note]: SFP+/28 => SFF-8472 A2H Byte-114 + * QSFP28 => SFF-8636 03H Byte-234/235 + */ + uint8_t tx_eq[2]; + + /* [Prop]: OPTION VALUES + * [Desc]: The bits in the option field shall specify the options implemented in the transceiver. + * [Note]: SFP+/28 => SFF-8472 A0H Byte-64/65 + * QSFP+/28 => SFF-8636 00H Byte-193/195 + */ + uint8_t option[3]; + + /* [Prop]: External PHY offset + * [Desc]: It needs to be setup first if you want to access transceiver external phy. + * [Note]: This feature dependent on transceiver. + * Currently, only 1G-RJ45 transceiver supported it. + */ + uint8_t extphy_offset; + + /* ========== 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 transvr_worker_s *worker_p; + struct mutex lock; + char swp_name[32]; + int auto_config; + 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 public functions ========== + */ + int (*get_id)(struct transvr_obj_s *self); + int (*get_ext_id)(struct transvr_obj_s *self); + int (*get_connector)(struct transvr_obj_s *self); + int (*get_vendor_name)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_pn)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_rev)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_sn)(struct transvr_obj_s *self, char *buf_p); + int (*get_power_cls)(struct transvr_obj_s *self); + int (*get_br)(struct transvr_obj_s *self); + int (*get_len_sm)(struct transvr_obj_s *self); + int (*get_len_smf)(struct transvr_obj_s *self); + int (*get_len_om1)(struct transvr_obj_s *self); + int (*get_len_om2)(struct transvr_obj_s *self); + int (*get_len_om3)(struct transvr_obj_s *self); + int (*get_len_om4)(struct transvr_obj_s *self); + int (*get_comp_rev)(struct transvr_obj_s *self); + int (*get_comp_eth_1)(struct transvr_obj_s *self); + int (*get_comp_eth_10)(struct transvr_obj_s *self); + int (*get_comp_eth_10_40)(struct transvr_obj_s *self); + int (*get_comp_extend)(struct transvr_obj_s *self); + int (*get_cdr)(struct transvr_obj_s *self); + int (*get_rate_id)(struct transvr_obj_s *self); + int (*get_soft_rs0)(struct transvr_obj_s *self); + int (*get_soft_rs1)(struct transvr_obj_s *self); + int (*get_info)(struct transvr_obj_s *self); + int (*get_if_type)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_speed)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_lane)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_temp)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_vol)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_rx_los)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_fault)(struct transvr_obj_s *self, char *buf_p); + int (*get_auto_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_bias)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_eq)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_am)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_em)(struct transvr_obj_s *self, char *buf_p); + int (*get_wavelength)(struct transvr_obj_s *self, char *buf_p); + int (*get_extphy_offset)(struct transvr_obj_s *self, char *buf_p); + int (*get_extphy_reg)(struct transvr_obj_s *self, char *buf_p); + int (*set_cdr)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs0)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs1)(struct transvr_obj_s *self, int input_val); + int (*set_soft_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_auto_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_tx_eq)(struct transvr_obj_s *self, int input_val); + int (*set_rx_am)(struct transvr_obj_s *self, int input_val); + int (*set_rx_em)(struct transvr_obj_s *self, int input_val); + int (*set_extphy_offset)(struct transvr_obj_s *self, int input_val); + int (*set_extphy_reg)(struct transvr_obj_s *self, int input_val); + + /* ========== Object private functions ========== + */ + int (*init)(struct transvr_obj_s *self); + int (*clean)(struct transvr_obj_s *self); + int (*check)(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); + int (*fsm_4_polling)(struct transvr_obj_s* self, char *caller_name); + int (*send_uevent)(struct transvr_obj_s* self, enum kobject_action u_action); + int (*dump_all)(struct transvr_obj_s* self); +}; + + +/* For AVL Mapping */ +struct transvr_avl_s { + char vendor_name[32]; + char vendor_pn[32]; + int (*init)(struct transvr_obj_s *self); +}; + + +/* Worker for long term task of transceiver */ +struct transvr_worker_s { + /* Task Parameter */ + struct transvr_obj_s *transvr_p; + struct transvr_worker_s *next_p; + struct transvr_worker_s *pre_p; + unsigned long trigger_time; + char func_name[64]; + int retry; + int state; + + /* Task private data */ + void *p_data; + + /* Call back function */ + int (*main_task)(struct transvr_worker_s *task); + int (*post_task)(struct transvr_worker_s *task); +}; + + +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 lock_transvr_obj(struct transvr_obj_s *self); +void unlock_transvr_obj(struct transvr_obj_s *self); +int isolate_transvr_obj(struct transvr_obj_s *self); + +int resync_channel_tier_2(struct transvr_obj_s *self); + +void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg); + +#endif /* TRANSCEIVER_H */ + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/utils/inventec_d6556_util.py b/platform/broadcom/sonic-platform-modules-inventec/d6556/utils/inventec_d6556_util.py new file mode 100644 index 000000000000..2ca077945f5a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/utils/inventec_d6556_util.py @@ -0,0 +1,238 @@ +#!/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 "[D6556]"+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 inv_eeprom 0x53 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo inv_cpld 0x55 > /sys/bus/i2c/devices/i2c-0/new_device'] + + +drivers =[ +'gpio_ich', +'lpc_ich', +'i2c-i801', +'i2c-mux', +'i2c-mux-pca954x', +'i2c-dev', +'inv_eeprom', +'inv_platform', +'inv_psoc', +'inv_cpld', +'swps', +'inv_pthread'] + + + +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) + status, output = exec_cmd("rmmod gpio_ich ", 1) + status, output = exec_cmd("rmmod lpc_ich ", 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(10,18): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-2/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(18,26): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-3/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(26,34): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-4/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(34,42): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(42,50): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-6/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(50,58): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-7/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(58,66): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-8/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 "D6556 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/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/Makefile new file mode 100755 index 000000000000..b596d1c4bc4d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/Makefile @@ -0,0 +1,8 @@ +obj-m += inv_cpld.o inv_psoc.o +obj-m += inv_platform.o +obj-m += inv_eeprom.o +obj-m += swps.o +obj-m += inv_pthread.o +swps-objs := inv_swps.o io_expander.o transceiver.o + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_cpld.c new file mode 100644 index 000000000000..028e24b9eb86 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_cpld.c @@ -0,0 +1,456 @@ +/* + * 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_RESET_OFFSET 0x08 +#define CPLD_PSU_OFFSET 0x09 +#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_reset(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_RESET_OFFSET, 1); + + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld reset fail\n"); + + + status = sprintf (buf, "The CPLD 1 cpld_reset = %d\n", b[0]); + + return strlen(buf); +} + +static ssize_t set_reset(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, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_write(client, &temp, CPLD_RESET_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +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(reset, S_IWUSR|S_IRUGO, show_reset, set_reset, 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_reset.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/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 new file mode 100644 index 000000000000..52f6a5691d3e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_platform.c @@ -0,0 +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 + +//#include "I2CHostCommunication.h" + +#define USE_SMBUS 1 + +//#define offsetof(st, m) ((size_t)(&((st *)0)->m)) +#define FAN_NUM 5 +#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 reserve1; //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_grn; //offset: 28 + u8 led_red; //offset: 29 + + //pwm duty + u8 pwm[FAN_NUM]; //offset: 2a + u8 pwm_psu[PSU_NUM]; //offset: 2f + + //fan rpm + u16 fan[FAN_NUM*2]; //offset: 31 + //u16 fan_psu[PSU_NUM]; + + //gpi + u8 gpi_fan; //offset: 45 + + //psu state + u8 psu_state; //offset: 46 + + //temperature + u16 temp[5]; //offset: 47 + u16 temp_psu[PSU_NUM]; //offset: 51 + + //version + u8 version[2]; //offset: 55 + + u8 reserve2[3]; //offset: 57 + struct psoc_psu_layout psu_info; //offset: 5a +}; + + +/* 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) //0x01 +#define PWM_OFFSET PSOC_OFF(pwm) +#define PWM_PSU_OFFSET PSOC_OFF(pwm_psu) +#define THERMAL_OFFSET PSOC_OFF(temp) +#define RPM_OFFSET PSOC_OFF(fan) +//#define RPM_PSU_OFFSET PSOC_OFF(fan_psu) +#define DIAG_FLAG_OFFSET PSOC_OFF(ctl) +#define FAN_LED_OFFSET PSOC_OFF(led_grn) +#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; +}; + +/*-----------------------------------------------------------------------*/ + +static ssize_t psoc_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 psoc_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 +} + +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; +} + +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; +} + +static int psoc_write_value(struct i2c_client *client, unsigned offset, u16 value) +{ + //TBD + return 0; +} + + +//PSOC i2c bridge regsters +#define PSOC_I2C_STATUS PSOC_OFF(i2c_st) +#define PSOC_I2C_CNTRL PSOC_OFF(i2c_ctl) +#define PSOC_I2C_ADDR PSOC_OFF(i2c_addr) +#define PSOC_I2C_DATA PSOC_OFF(i2c_data) + +//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) + +#define PMBUS_MFR_ID (0x99) +#define PMBUS_MFR_MODEL (0x9A) +#define PMBUS_MFR_REVISION (0x9B) +#define PMBUS_MFR_DATE (0x9D) +#define PMBUS_MFR_SERIAL (0x9E) + +static int psoc_i2c_bridge_read(struct i2c_client *client, + unsigned char bus, + unsigned char chip, + char *addr, int alen, + unsigned char *data, int len ) +{ + unsigned char txdata[28], rxdata[28]; + int index, timeout; + + txdata[PSOC_I2C_STATUS] = 0; /* the status */ + txdata[PSOC_I2C_CNTRL] = ((alen & 3) << 5) | (len & 0x1f); /* the sizes */ + txdata[PSOC_I2C_ADDR] = (chip << 1) | PSOC_I2C_READ; /* read address */ + for(index = 0; index < alen; index++) + txdata[PSOC_I2C_DATA + index] = addr[index]; /* the chip address */ + for(; index < alen+len; index++) + txdata[PSOC_I2C_DATA + index] = 0; /* clear the chip data */ + + psoc_i2c_write(client, &txdata[PSOC_I2C_CNTRL], PSOC_I2C_CNTRL, 2 + alen + len); + + //delay a while ??? + //--------------------------------------------------------------------- + //start write + txdata[PSOC_I2C_STATUS] = PSOC_I2C_START; /* the start bit*/ + if(bus) + txdata[PSOC_I2C_STATUS] |= PSOC_PMB_SEL;/* bus id */ + psoc_i2c_write(client, &txdata[PSOC_I2C_STATUS], PSOC_I2C_STATUS, 1); + + //delay a while + timeout = 40; //40*20==>800 ms + do { + psoc_i2c_read(client, &rxdata[PSOC_I2C_STATUS], PSOC_I2C_STATUS, 1); + + //check rxdata[5] error bit(1) and complete bit(0) ,TBD + if((rxdata[PSOC_I2C_STATUS] & 0x2) == 0x2) { + //printk("i2c bridge fail!!!\n"); + timeout = 0; + break; + } + if((rxdata[PSOC_I2C_STATUS] & PSOC_I2C_START) == 0) { + /* comand complete */ + psoc_i2c_read(client, &rxdata[PSOC_I2C_DATA+alen], PSOC_I2C_DATA+alen, len); + break; + } + + //delay + msleep(20); + } while(timeout--); + + if(timeout <= 0) { + return -1; + } + + //--------------------------------------------------------------------- + + for(index=0; index < len; index++) { + data[index] = rxdata[PSOC_I2C_DATA + alen + index]; + } + + return 0; +} + + +/* +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 */ + +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); + status = __swab16(status); + + 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; + + 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; + + 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; + + mutex_lock(&data->update_lock); + + status = psoc_read16(client, offset); + status = __swab16(status); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + status); +} +static ssize_t show_fan_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 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 index = attr->index; + int type = -1; + + mutex_lock(&data->update_lock); + status = psoc_read8(client, FAN_GPI_OFFSET); + mutex_unlock(&data->update_lock); + + if( (status & 1<update_lock); + status = psoc_i2c_read(client, (u8*)&temp, SWITCH_TMP_OFFSET, 2); + status = __swab16(status); + 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(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 reg = attr->index & 0xFF; + u8 len = ((attr->index & 0xFF00) >> 8); + u8 chip = (attr->index >> 16)? 0x59:0x58; + u8 bus = 1; + unsigned char value[2] = {0,0};; + + if (len == 2) + { + mutex_lock(&data->update_lock); + psoc_i2c_bridge_read(client, bus, chip, ®, 1, value, 2); + mutex_unlock(&data->update_lock); + + status = value[1]<<8 | value[0]; + //status1 = value[1]<<8 | value[0]; + + return sprintf(buf, "%ld\n", pmbus_reg2data_linear(status, (reg==PMBUS_READ_VOUT)?1:0) ); + } + else + { //len is not defined. + u8 tmpbuf[32]; + mutex_lock(&data->update_lock); + //length of block read + psoc_i2c_bridge_read(client, bus, chip, ®, 1, &len, 1); + //data included length + psoc_i2c_bridge_read(client, bus, chip, ®, 1, tmpbuf, len+1); + mutex_unlock(&data->update_lock); + + memcpy(buf, tmpbuf+1, len); + buf[len]='\n'; + + return len+1; + } +} + +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, PWM_OFFSET+0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_OFFSET+1); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_OFFSET+2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_OFFSET+3); +#if (FAN_NUM >= 5) +static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_OFFSET+4); +#endif +static SENSOR_DEVICE_ATTR(pwm_psu1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_PSU_OFFSET+0); +static SENSOR_DEVICE_ATTR(pwm_psu2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_PSU_OFFSET+1); + +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*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7*2 + RPM_OFFSET); +#if (FAN_NUM >= 5) +static SENSOR_DEVICE_ATTR(fan9_input, S_IRUGO, show_rpm, 0, 8*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan10_input, S_IRUGO, show_rpm, 0, 9*2 + RPM_OFFSET); +#endif +static SENSOR_DEVICE_ATTR(rpm_psu1, S_IRUGO, show_rpm, 0, 8*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(rpm_psu2, S_IRUGO, show_rpm, 0, 9*2 + RPM_OFFSET); + +static SENSOR_DEVICE_ATTR(switch_tmp, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0); +static SENSOR_DEVICE_ATTR(temp6_input, 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(fan1_type, S_IRUGO, show_fan_type, 0, 0); +static SENSOR_DEVICE_ATTR(fan2_type, S_IRUGO, show_fan_type, 0, 1); +static SENSOR_DEVICE_ATTR(fan3_type, S_IRUGO, show_fan_type, 0, 2); +static SENSOR_DEVICE_ATTR(fan4_type, S_IRUGO, show_fan_type, 0, 3); + +static SENSOR_DEVICE_ATTR(psu1_vin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_VIN); +static SENSOR_DEVICE_ATTR(psu1_vout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_VOUT); +static SENSOR_DEVICE_ATTR(psu1_iin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_IIN); +static SENSOR_DEVICE_ATTR(psu1_iout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_IOUT); +static SENSOR_DEVICE_ATTR(psu1_pin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_PIN); +static SENSOR_DEVICE_ATTR(psu1_pout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_POUT); + +static SENSOR_DEVICE_ATTR(psu1_vendor, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_ID); +static SENSOR_DEVICE_ATTR(psu1_model, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu1_version, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu1_date, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_DATE); +static SENSOR_DEVICE_ATTR(psu1_sn, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_SERIAL); + +static SENSOR_DEVICE_ATTR(psu2_vin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_VIN); +static SENSOR_DEVICE_ATTR(psu2_vout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_VOUT); +static SENSOR_DEVICE_ATTR(psu2_iin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_IIN); +static SENSOR_DEVICE_ATTR(psu2_iout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_IOUT); +static SENSOR_DEVICE_ATTR(psu2_pin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_PIN); +static SENSOR_DEVICE_ATTR(psu2_pout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_POUT); + +static SENSOR_DEVICE_ATTR(psu2_vendor, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_ID); +static SENSOR_DEVICE_ATTR(psu2_model, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu2_version, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu2_date, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_DATE); +static SENSOR_DEVICE_ATTR(psu2_sn, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_SERIAL); + +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)); + +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin)); + + + +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, +#if (FAN_NUM >= 5) + //&sensor_dev_attr_pwm5.dev_attr.attr, +#endif + &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, +#if (FAN_NUM >= 5) + //&sensor_dev_attr_fan9_input.dev_attr.attr, + //&sensor_dev_attr_fan10_input.dev_attr.attr, +#endif + + &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, + &sensor_dev_attr_temp6_input.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, + + //fan type + &sensor_dev_attr_fan1_type.dev_attr.attr, + &sensor_dev_attr_fan2_type.dev_attr.attr, + &sensor_dev_attr_fan3_type.dev_attr.attr, + &sensor_dev_attr_fan4_type.dev_attr.attr, + + //psu + &sensor_dev_attr_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psu2_pout.dev_attr.attr, + + &sensor_dev_attr_psu1_vendor.dev_attr.attr, + &sensor_dev_attr_psu1_model.dev_attr.attr, + &sensor_dev_attr_psu1_version.dev_attr.attr, + &sensor_dev_attr_psu1_date.dev_attr.attr, + &sensor_dev_attr_psu1_sn.dev_attr.attr, + &sensor_dev_attr_psu2_vendor.dev_attr.attr, + &sensor_dev_attr_psu2_model.dev_attr.attr, + &sensor_dev_attr_psu2_version.dev_attr.attr, + &sensor_dev_attr_psu2_date.dev_attr.attr, + &sensor_dev_attr_psu2_sn.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, + + // Add new fields which matching standard + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.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; + + 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; + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.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/d7032q28b/modules/inv_pthread.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_pthread.c new file mode 100644 index 000000000000..b0f905d6a7d9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_pthread.c @@ -0,0 +1,1305 @@ +/***************************** + Redwood platform +******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SHOW_ATTR_WARNING ("N/A") +#define SHOW_ATTR_NOTPRINT ("Not Available") +#define SHOW_ATTR_NOTSUPPORT ("Not Support") + +#define INV_HWMID_MAX (10) +#define INV_HWMID_INIT (-1) + +/*access userspace data to kernel space*/ +#define ACC_R (0) +#define ACC_W (1) + +#define TINY_BUF_SIZE (8) +#define MAX_PATH_SIZE (64) +#define MIN_ACC_SIZE (32) +#define MAX_ACC_SIZE (256) + +/* + * LED definitions + */ +#define STATUS_LED_MODE_AUTO 0 +#define STATUS_LED_MODE_DIAG 1 +#define STATUS_LED_MODE_MANU 2 + +#define STATUS_LED_GRN0 10 // 0 - 000: off +#define STATUS_LED_GRN1 11 // 1 - 001: 0.5hz +#define STATUS_LED_GRN2 12 // 2 - 010: 1 hz +#define STATUS_LED_GRN3 13 // 3 - 011: 2 hz +#define STATUS_LED_GRN7 17 // 7 - 111: on +#define STATUS_LED_RED0 20 // 0 - 000: off +#define STATUS_LED_RED1 21 // 1 - 001: 0.5hz +#define STATUS_LED_RED2 22 // 2 - 010: 1 hz +#define STATUS_LED_RED3 23 // 3 - 011: 2 hz +#define STATUS_LED_RED7 27 // 7 - 111: on +#define STATUS_LED_INVALID 0 // Invalid + +ssize_t status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2); +ssize_t status_led_grn(const char *freq); +ssize_t status_led_red(const char *freq); +ssize_t status_led_diag_mode_enable(void); +ssize_t status_led_diag_mode_disable(void); +int status_led_check_color(void); +int status_led_check_diag_mode(void); + +#if 1 +/* For timestamps in SYSFS_LOG */ +#define SYSFS_LOG printk +#else +//#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[SYSFS] %s/%d: " fmt, __func__, __LINE__, ##args) +#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[p_thread] " fmt, ##args) +#endif + +#define INV_PTHREAD_KERNEL_MODULE (1) +#define SWITCH_HEALTH_LED_CHANGE_VIA_GPIO (1) + +/* inventec_class *********************************/ +static struct kobject *status_kobj; +static struct kset *status_kset; + + +static struct mutex rw_lock; + +static int hwm_psoc = INV_HWMID_INIT; +static int hwm_cpld = INV_HWMID_INIT; + +int get_hwm_psoc(void) +{ + return hwm_psoc; +} + +int get_hwm_cpld(void) +{ + return hwm_cpld; +} + +static ssize_t access_user_space(const char *name, int mode, char *buf, size_t len, loff_t offset) +{ + struct file *fp; + mm_segment_t fs; + loff_t pos = offset; + char *mark = NULL; + ssize_t vfs_ret = 0; + + if (mode == ACC_R) { + fp = filp_open(name, O_RDONLY, S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_read(fp, buf, len, &pos); + + mark = strpbrk(buf, "\n"); + if (mark) + *mark = '\0'; + + filp_close(fp, NULL); + set_fs(fs); + } else if (mode == ACC_W) { + fp = filp_open(name, O_WRONLY, S_IWUSR | S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_write(fp, buf, len, &pos); + filp_close(fp, NULL); + set_fs(fs); + } + + return vfs_ret; +} + +int inventec_strtol(const char *sbufp, char **endp, unsigned int base) +{ + char *endptr; + int value = simple_strtol(sbufp, &endptr, base); + if (value == 0 && sbufp == endptr) { + *endp = NULL; + return value; + } + *endp = (char*)1; + return value; +} + +int inventec_singlechar_to_int(const char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } + else + if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } + else + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } + return -1; +} + +int inventec_store_input(char *inputp, int count) +{ + int i = 0; + while(inputp[i] != '\n' && inputp[i] != '\0' && i < count) { + i++; + } + inputp[i] = '\0'; + return strlen(inputp); +} + +#if 0 +/* + * Time stamps for kernel log on yocto + */ +#include + +void SYSFS_LOG(char *fmt, ...) +{ + char buf[80], ts[32]; + va_list args; + int hlen; + + inventec_tmstmp(&ts[0]); + hlen = sprintf(buf, "[SYSFS] %s ", ts); // Do not edit this line + + va_start(args, fmt); + vsprintf(&buf[hlen-1], fmt, args); + va_end(args); + printk(KERN_WARNING "[p_thread] %s\n", buf); +} +#endif + +ssize_t +inventec_show_attr(char *buf_p, const char *invdevp) +{ + int inv_len = MAX_ACC_SIZE; /* INV driver return max length */ + char tmp_buf[MAX_ACC_SIZE]; + char *str_negative = "-", *mark = NULL; + + /* [Step2] Get data by uaccess */ + memset(tmp_buf, 0, sizeof(tmp_buf)); + mutex_lock(&rw_lock); + if (access_user_space(invdevp, ACC_R, tmp_buf, inv_len, 0) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + mutex_unlock(&rw_lock); + + /* [Step3] Check return value + * - Ex: When transceiver not plugged + * => SWPS return error code "-202" + * => Pic8 need return "NA" (assume) + */ + if (strcspn(tmp_buf, str_negative) == 0) { + /* error case: "-202" */ + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + + /* OK case:*/ + mark = strpbrk(tmp_buf, "\n"); + if (mark) { *mark = '\0'; } + + return sprintf(buf_p, "%s\n", tmp_buf); +} + +ssize_t +inventec_store_attr(const char *buf_p, size_t count, const char *invdevp) +{ + ssize_t ret = 0; + + /* [Step2] Get data by uaccess */ + mutex_lock(&rw_lock); + if ((ret = access_user_space(invdevp, ACC_W, (char*)buf_p, count, 0)) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return -EINVAL; + } + mutex_unlock(&rw_lock); + + /* OK case:*/ + return ret; +} + +int sysfs_detect_hwmon_index(void) +{ + char hwmon_buf[MAX_ACC_SIZE]; + char hwmon_path[MAX_PATH_SIZE]; + int hwid = 0; + + for (hwid = 0; + hwid < INV_HWMID_MAX && (hwm_psoc == INV_HWMID_INIT || hwm_cpld == INV_HWMID_INIT); + hwid++) { + memset(hwmon_buf, 0, sizeof(hwmon_buf)); + sprintf(hwmon_path, "/sys/class/hwmon/hwmon%d/device/name", hwid); + + inventec_show_attr(hwmon_buf, hwmon_path); + if (strncmp(hwmon_buf, "inv_psoc", 8) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_bmc", 7) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_cpld", 8) == 0) { + hwm_cpld = hwid; + } + } + if (hwid >= INV_HWMID_MAX) { + printk(KERN_ERR "[p_thread] detect hwmon index failed, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return -1; + } + printk(KERN_INFO "[p_thread] detect hwmon index success, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return 0; +} + +static int __init +inventec_class_init(void) +{ + mutex_init(&rw_lock); + +#ifdef INV_PTHREAD_KERNEL_MODULE + if (sysfs_detect_hwmon_index() < 0) { + return -1; + } +#endif + + printk(KERN_INFO "[p_thread] [%s/%d] Module initial success.\n",__func__,__LINE__); + + return 0; +} + +static void __exit +inventec_class_exit(void) +{ + printk(KERN_INFO "[p_thread] [%s/%d] Remove module.\n",__func__,__LINE__); +} + +/* fan device *************************************/ +#define FAN_DEV_PATH_STATE "/sys/class/hwmon/hwmon%d/device/fan_gpi" +#define FAN_DEV_PATH_FAN1_INPUT "/sys/class/hwmon/hwmon%d/device/fan1_input" +#define FAN_DEV_PATH_FAN2_INPUT "/sys/class/hwmon/hwmon%d/device/fan2_input" +#define FAN_DEV_PATH_FAN3_INPUT "/sys/class/hwmon/hwmon%d/device/fan3_input" +#define FAN_DEV_PATH_FAN4_INPUT "/sys/class/hwmon/hwmon%d/device/fan4_input" +#define FAN_DEV_PATH_FAN5_INPUT "/sys/class/hwmon/hwmon%d/device/fan5_input" +#define FAN_DEV_PATH_FAN6_INPUT "/sys/class/hwmon/hwmon%d/device/fan6_input" +#define FAN_DEV_PATH_FAN7_INPUT "/sys/class/hwmon/hwmon%d/device/fan7_input" +#define FAN_DEV_PATH_FAN8_INPUT "/sys/class/hwmon/hwmon%d/device/fan8_input" + +static char fan_dev_path_state[MAX_PATH_SIZE]; +static char fan_dev_path_fan1_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan2_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan3_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan4_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan5_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan6_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan7_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan8_input[MAX_PATH_SIZE]; + +void sysfs_fan_path_init(void) +{ + sprintf(&fan_dev_path_state[0], FAN_DEV_PATH_STATE, get_hwm_psoc()); + sprintf(&fan_dev_path_fan1_input[0],FAN_DEV_PATH_FAN1_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan2_input[0],FAN_DEV_PATH_FAN2_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan3_input[0],FAN_DEV_PATH_FAN3_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan4_input[0],FAN_DEV_PATH_FAN4_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan5_input[0],FAN_DEV_PATH_FAN5_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan6_input[0],FAN_DEV_PATH_FAN6_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan7_input[0],FAN_DEV_PATH_FAN7_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan8_input[0],FAN_DEV_PATH_FAN8_INPUT, get_hwm_psoc()); +} + +#define FAN_STATE_NORMAL "normal" +#define FAN_STATE_FAULTY "faulty" +#define FAN_STATE_UNINSTALLED "uninstalled" +#define FAN_STATE_UNKNOW "unknown state" +#define FAN_STATE_INVALID "Invalid state value" +#define FAN_STATE_READ_ERROR "state read error" + +#define FAN_LOG_UNINSTALLED "removed" +#define FAN_LOG_NORMAL "inserted" + +//#define FAN_STATE_BIT_NORMAL 0 +#define FAN_STATE_BIT_FAULTY 0 +#define FAN_STATE_BIT_UNINSTALLED 1 +#define FAN_STATE_BIT_UNKNOW 2 +#define FAN_STATE_BIT_INVALID 3 +#define FAN_STATE_BIT_READ_ERROR 4 + +static struct fans_tbl_s { + char *fan_name; + char *fan_front; + char *fan_rear; + unsigned int fan_state; +} fans_tbl[] = { + {"fan1", fan_dev_path_fan1_input, + fan_dev_path_fan2_input, 0}, + {"fan2", fan_dev_path_fan3_input, + fan_dev_path_fan4_input, 0}, + {"fan3", fan_dev_path_fan5_input, + fan_dev_path_fan6_input, 0}, + {"fan4", fan_dev_path_fan7_input, + fan_dev_path_fan8_input, 0}, +}; +#define FAN_TBL_TOTAL ( sizeof(fans_tbl)/ sizeof(const struct fans_tbl_s) ) + +#define FAN_STATE_CHECK(i,b) (fans_tbl[i].fan_state & (1< 0) + { + printk(KERN_ERR "[p_thread] All fans failed.\n"); + printk(KERN_ERR "[p_thread] System shutdown immediately in %d seconds.\n", cd_shutdown); + } + cd_shutdown -= 1; + } + return ret; +} + +/* End of faninfo_device */ + +static int __init +fan_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_fan_path_init(); +#endif + return 0; +} + + +static void __exit +fan_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove fan module.\n"); +} + +/* psu device *************************************/ +static unsigned int psu_voltin = 0; +#define PSU_VOLTIN_ACDC (70000) + +/* + * normal/unpower/uninstall/fault are PSU states output from driver level + * checkpsu/error are defined by sysfs + */ +#define PSU_STATE_VAL_NORMAL (0) +#define PSU_STATE_VAL_UNPOWER (2) +#define PSU_STATE_VAL_FAULT (4) +#define PSU_STATE_VAL_UNINSTALL (7) +#define PSU_STATE_VAL_CHECKPSU (8) +#define PSU_STATE_VAL_ERROR (9) + +#define PSU_STATE_NORMAL ("0 : normal") +#define PSU_STATE_UNPOWER ("2 : unpowered") +#define PSU_STATE_FAULT ("4 : fault") +#define PSU_STATE_UNINSTALL ("7 : not installed") +#define PSU_STATE_CHECKPSU ("8 : check psu") +#define PSU_STATE_ERROR ("9 : state error") + +#define PSU_STATE_LEN_NORMAL (strlen(PSU_STATE_NORMAL)) +#define PSU_STATE_LEN_UNPOWER (strlen(PSU_STATE_UNPOWER)) +#define PSU_STATE_LEN_FAULT (strlen(PSU_STATE_FAULT)) +#define PSU_STATE_LEN_UNINSTALL (strlen(PSU_STATE_UNINSTALL)) +#define PSU_STATE_LEN_CHECKPSU (strlen(PSU_STATE_CHECKPSU)) + +typedef struct { + char *inv_dev_attrp; + char *inv_dev_pathp; +} psu_dev_t; + +typedef struct { + const char *psu_name; + int psu_major; + dev_t psu_devt; + struct device *psu_dev_p; + psu_dev_t *psu_dev_namep; + int psu_dev_total; + char *psu_inv_pathp; + void *psu_tracking; + char *psu_currentin; + char *psu_currentout; + char *psu_powerin; + char *psu_powerout; + char *psu_voltin; + char *psu_voltout; +} psu_dev_group_t; + +#define PSU_DEV_PATH_TEMPLATE "/sys/class/hwmon/hwmon%d/device/%s" + +static char psu_dev_path_state[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltin[MAX_PATH_SIZE]; +#if 0 +static char psu_dev_path_vendor[MAX_PATH_SIZE]; +static char psu_dev_path_version[MAX_PATH_SIZE]; +static char psu_dev_path_sn[MAX_PATH_SIZE]; +static char psu_dev_path_temperature[MAX_PATH_SIZE]; +static char psu_dev_path_fan_speed[MAX_PATH_SIZE]; +static char psu_dev_path_fan_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_fan_faulty[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_psu_rpm[MAX_PATH_SIZE]; +#endif + +void sysfs_psu_path_init(void) +{ + sprintf(&psu_dev_path_state[0], PSU_DEV_PATH_TEMPLATE, get_hwm_cpld(), "\%s" ); + sprintf(&psu_dev_path_psu_voltin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#if 0 + sprintf(&psu_dev_path_vendor[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_version[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_sn[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_temperature[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_speed[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_faulty[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_voltout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_rpm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#endif +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +#if 0 + { "vendor", psu_dev_path_vendor }, + { "version", psu_dev_path_version }, + { "sn", psu_dev_path_sn }, + { "temperature", psu_dev_path_temperature }, + { "fan_speed", psu_dev_path_fan_speed }, + { "fan_pwm", psu_dev_path_fan_pwm }, + { "fan_faulty", psu_dev_path_fan_faulty }, + { "psu_currentin", psu_dev_path_psu_currentin }, + { "psu_currentout", psu_dev_path_psu_currentout }, + { "psu_powerin", psu_dev_path_psu_powerin }, + { "psu_powerout", psu_dev_path_psu_powerout }, + { "psu_voltout", psu_dev_path_psu_voltout }, + { "psu_pwm", psu_dev_path_psu_pwm }, + { "psu_rpm", psu_dev_path_psu_rpm }, +#endif +}; +#define PSU_DEV_NAME_TOTAL ( sizeof(psu_dev_name) / sizeof(const psu_dev_t) ) + +static psu_dev_group_t psu_dev_group[] = { + { + .psu_name = "psu1", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, + { + .psu_name = "psu2", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, +}; +#define PSU_DEV_GROUP_TOTAL ( sizeof(psu_dev_group)/ sizeof(const psu_dev_group_t) ) + +static char psu_state[4][MIN_ACC_SIZE]; + +static struct psu_wire_tbl_s { + char *psu_attr; + char *psu_name; + char *psu_wire; + char *psu_state; +} psu_wire_tbl[] = { + { "state", "psu1", "psu0", psu_state[0] }, // Using cpld + { "state", "psu2", "psu1", psu_state[1] }, + { "psu_voltin", "psu1", "psoc_psu1_vin", psu_state[2] }, + { "psu_voltin", "psu2", "psoc_psu2_vin", psu_state[3] }, +}; +#define PSU_WIRE_TBL_TOTAL ( sizeof(psu_wire_tbl)/ sizeof(const struct psu_wire_tbl_s) ) + +static char * +psu_attr_get_wirep(const char *psu_attrp, const char *psu_namep, char **psu_statepp) +{ + int i; + + for (i = 0; i < PSU_WIRE_TBL_TOTAL; i++) { + if (strncmp(psu_wire_tbl[i].psu_attr, psu_attrp, strlen(psu_attrp)) == 0 && + strncmp(psu_wire_tbl[i].psu_name, psu_namep, strlen(psu_namep)) == 0) { + if (psu_statepp) { + *psu_statepp = psu_wire_tbl[i].psu_state; + } + return psu_wire_tbl[i].psu_wire; + } + } + return NULL; +} + +int psu_check_state_normal(char *statep) +{ + if (strstr(statep, "normal")) { + return 1; + } + return 0; +} + +#define PSU_ATTR_VOLTIN ("psu_voltin") +#define PSU_ATTR_VOLTIN_LEN (10) + +/* Get PSU voltin for determon AC(110v) or DC(48v) */ +void psu_get_voltin(void) +{ + char acc_path[MAX_PATH_SIZE], volt[MIN_ACC_SIZE]; + psu_dev_t *devnamep; + unsigned int voltin; + char *invwirep; + int i, j; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + //psu_dev_group[i].psu_name; + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_VOLTIN, PSU_ATTR_VOLTIN_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_VOLTIN, psu_dev_group[i].psu_name, NULL); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_DEBUG "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(volt, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + continue; + } + else { + voltin = simple_strtol(&volt[0], NULL, 10); + printk(KERN_DEBUG "[p_thread] Read %s %s = %u\n",acc_path,volt,voltin); + if (voltin > psu_voltin) { + psu_voltin = voltin; + } + } + } + } + } + + SYSFS_LOG("[p_thread] PSU voltin = %u\n", psu_voltin); +} + +#define PSU_ATTR_STATE ("state") +#define PSU_ATTR_STATE_LEN (5) + +/* psus_control() by inv_thread */ +int psus_control(int log_only) +{ + char acc_path[MAX_PATH_SIZE], state[MIN_ACC_SIZE]; + psu_dev_t *devnamep = NULL; + char *invwirep = NULL; + char *psu_statep = NULL; + int i, j, flag = 0; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_STATE, PSU_ATTR_STATE_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_STATE, psu_dev_group[i].psu_name, &psu_statep); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_INFO "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(state, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + if (strncmp(psu_statep, PSU_STATE_ERROR, strlen(PSU_STATE_ERROR)) != 0) { + strcpy(psu_statep, PSU_STATE_ERROR); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_ERROR); + } + flag = 1; + } + else + if (strstr(state, "normal")) { + //printk(KERN_INFO "[p_thread] %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + } + else + if (psu_voltin > PSU_VOLTIN_ACDC) { /* AC PSUS */ + //printk(KERN_INFO "[p_thread] RYU: %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + flag = 1; + } + else { /* DC PSUS */ + if (strncmp(psu_statep, PSU_STATE_CHECKPSU, PSU_STATE_LEN_CHECKPSU) != 0) { + strcpy(psu_statep, PSU_STATE_CHECKPSU); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_CHECKPSU); + } + flag = 1; + } + } + } + } + + if (log_only) { + return 0; + } + + //SYSFS_LOG("[p_thread] RYU: %s: flag = %d\n",psu_wire_tbl[i].psu_name,flag); + if (flag == 1) { + status_led_grn("3"); + return 1; + } + return 0; +} + +/* End of psuinfo_device */ + +static int __init +psu_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_psu_path_init(); +#endif + return 0; +} + + +static void __exit +psu_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove psu module.\n"); +} + +/* led device *************************************/ +#define STATUS_LED_GRN_PATH "/sys/class/hwmon/hwmon%d/device/grn_led" +#define STATUS_LED_RED_PATH "/sys/class/hwmon/hwmon%d/device/red_led" + +#define FAN_LED_GRN1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn1" +#define FAN_LED_GRN2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn2" +#define FAN_LED_GRN3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn3" +#define FAN_LED_GRN4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn4" +#define FAN_LED_RED1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red1" +#define FAN_LED_RED2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red2" +#define FAN_LED_RED3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red3" +#define FAN_LED_RED4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red4" + +#define HWMON_DEVICE_DIAG_PATH "/sys/class/hwmon/hwmon%d/device/diag" +#define HWMON_DEVICE_CTRL_PATH "/sys/class/hwmon/hwmon%d/device/ctl" + +static char status_led_grn_path[MAX_PATH_SIZE]; +static char status_led_red_path[MAX_PATH_SIZE]; +static char fan_led_grn1_path[MAX_PATH_SIZE]; +static char fan_led_grn2_path[MAX_PATH_SIZE]; +static char fan_led_grn3_path[MAX_PATH_SIZE]; +static char fan_led_grn4_path[MAX_PATH_SIZE]; +static char fan_led_red1_path[MAX_PATH_SIZE]; +static char fan_led_red2_path[MAX_PATH_SIZE]; +static char fan_led_red3_path[MAX_PATH_SIZE]; +static char fan_led_red4_path[MAX_PATH_SIZE]; +static char hwmon_device_diag_path[MAX_PATH_SIZE]; +static char hwmon_device_ctrl_path[MAX_PATH_SIZE]; + +void sysfs_led_path_init(void) +{ + sprintf(&status_led_grn_path[0], STATUS_LED_GRN_PATH, get_hwm_cpld()); + sprintf(&status_led_red_path[0], STATUS_LED_RED_PATH, get_hwm_cpld()); + sprintf(&fan_led_grn1_path[0], FAN_LED_GRN1_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn2_path[0], FAN_LED_GRN2_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn3_path[0], FAN_LED_GRN3_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn4_path[0], FAN_LED_GRN4_PATH, get_hwm_psoc()); + sprintf(&fan_led_red1_path[0], FAN_LED_RED1_PATH, get_hwm_psoc()); + sprintf(&fan_led_red2_path[0], FAN_LED_RED2_PATH, get_hwm_psoc()); + sprintf(&fan_led_red3_path[0], FAN_LED_RED3_PATH, get_hwm_psoc()); + sprintf(&fan_led_red4_path[0], FAN_LED_RED4_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_diag_path[0], HWMON_DEVICE_DIAG_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_ctrl_path[0], HWMON_DEVICE_CTRL_PATH, get_hwm_cpld()); +} + +/* return 0/off 1/green 2/red */ +int +status_led_check_color(void) +{ + char tmpbuf[MIN_ACC_SIZE]; + int ret = STATUS_LED_INVALID; + + if (inventec_show_attr(&tmpbuf[0], status_led_grn_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_GRN0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_GRN1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_GRN2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_GRN3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_GRN7; + } + return ret; + } + + if (inventec_show_attr(&tmpbuf[0], status_led_red_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_RED0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_RED1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_RED2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_RED3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_RED7; + } + return ret; + } + return ret; +} + +/* + * Store attr Section + */ +static DEFINE_MUTEX(diag_mutex); + +ssize_t status_led_diag_mode_enable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '0') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("1", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + mutex_unlock(&diag_mutex); + } + + return ret; +} + +ssize_t status_led_diag_mode_disable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '1') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("0", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + mutex_unlock(&diag_mutex); + } + return 1; +} + +ssize_t +status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2) +{ + ssize_t ret; + + ret = inventec_store_attr(tmp1, strlen(tmp1), path1); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(tmp2, strlen(tmp2), path2); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_red(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_grn_path[0]); + + if (ret < 0) { + return ret; + } + + ret = inventec_store_attr(freq, strlen(freq), &status_led_red_path[0]); + + if (ret < 0) { + return ret; + } + + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_grn(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +static int status_led_diag_mode = STATUS_LED_MODE_AUTO; + +int status_led_check_diag_mode(void) +{ + return status_led_diag_mode; +} + +/* End of ledinfo_device */ + +static int __init +led_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); +#endif + return 0; +} + + +static void __exit +led_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove led module.\n"); +} + +/* sensor device **********************************/ +#define SENSOR_DEV_PATH_SWITCH_TEMP "/sys/class/hwmon/hwmon%d/device/switch_tmp" + +static char sensor_dev_path_switch_temp[MAX_PATH_SIZE]; + +void sysfs_sensor_path_init(void) +{ + sprintf(&sensor_dev_path_switch_temp[0], SENSOR_DEV_PATH_SWITCH_TEMP, get_hwm_psoc()); +} + +void switch_temp_update(void) +{ + char buf[MIN_ACC_SIZE]; + ssize_t count = inventec_show_attr(&buf[0], "proc/switch/temp"); + if (count > 0) { + //printk(KERN_ERR "[p_thread] [STEMP] Switch temperature is out of range: %d\n", stemp); + inventec_store_attr(&buf[0], count, sensor_dev_path_switch_temp); + } +} + +/**************************************************/ +/* From system_device */ +static int inv_pthread_control = 1; + +int thread_control(void) +{ + return inv_pthread_control; +} + +void thread_control_set(int val) +{ + inv_pthread_control = val; +} +/* End system_device */ + +#define THREAD_SLEEP_MINS (3) +#define THREAD_DELAY_MINS (THREAD_SLEEP_MINS + THREAD_SLEEP_MINS + 1) + +extern void psu_get_voltin(void); + +static struct task_struct *thread_st; +static int thread_data; + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO +void led_set_gpio_to_change_status_led(void) +{ + ssize_t ret = inventec_store_attr("253", 3, "/sys/class/gpio/export"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 253 to /sys/class/gpio/export failed\n"); + return; + } + + printk("[p_thread] Write 253 to /sys/class/gpio/export\n"); + + ret = inventec_store_attr("out", 3, "/sys/class/gpio/gpio253/direction"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write low to /sys/class/gpio/gpio253/direction failed\n"); + return; + } + + //pull high and then low + ret = inventec_store_attr("1", 1, "sys/class/gpio/gpio253/value"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 1 to sys/class/gpio/gpio253/value failed\n"); + } + + //pull low + ret = inventec_store_attr("0", 1, "sys/class/gpio/gpio253/value"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 0 to sys/class/gpio/gpio253/value failed\n"); + } + + SYSFS_LOG("[p_thread] Set gpio to support status led change successfully\n"); +} +#endif + +// Function executed by kernel thread +static int thread_fn(void *unused) +{ + /* Delay for guarantee HW ready */ + ssleep(THREAD_DELAY_MINS); + +#ifndef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); + sysfs_fan_path_init(); + sysfs_psu_path_init(); +#endif + //sysfs_sensor_path_init(); + + /* Default status init */ + status_led_grn("7"); + + psu_get_voltin(); + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO + led_set_gpio_to_change_status_led(); +#endif + + while (1) + { + ssleep(THREAD_SLEEP_MINS); + + if (thread_control() == 0) { + printk(KERN_INFO "[p_thread] %s/%d: Thread Stop by inv_pthread control\n",__func__,__LINE__); + break; + } + + if (status_led_check_diag_mode() == STATUS_LED_MODE_MANU) { + /* status led in change color/freq mode, higher priority. Ignore fans sttaus */ + continue; + } + + // switch_temp_update(); + + if (fans_control() > 0) { + psus_control(1); + continue; + } + else + if (psus_control(0) > 0) { + continue; + } + + if (status_led_check_color() != STATUS_LED_GRN7) { /* status led red, change it to green */ + status_led_grn("7"); + } + } + +#ifndef INV_PTHREAD_KERNEL_MODULE +err_inv_pthread_fn_1: +#endif + do_exit(0); + printk(KERN_INFO "[p_thread] %s/%d: Thread Stopped\n",__func__,__LINE__); + return 0; +} + + +static ssize_t s_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + int fan_absence; + size_t count; + + fan_absence = fans_control(); + count += sprintf(&buf[count], "%d\n", fan_absence); + return count; +} + +static ssize_t s_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) +{ + return count; +} + +static struct attribute status_att = { + .name = "fan_absence", + .mode = 0777, +}; + +static const struct sysfs_ops status_ops = { + .show = s_show, + .store = s_store, +}; + +static struct kobj_type status_ktype = { + .sysfs_ops = &status_ops, +}; + + +static int __init inv_pthread_init(void) +{ + int retval; + + status_kobj = kzalloc(sizeof(*status_kobj), GFP_KERNEL); + if(!status_kobj) + return PTR_ERR(status_kobj); + + status_kset = kset_create_and_add("platform_status", NULL, kernel_kobj); + if(!status_kset) + return -1; + + status_kobj->kset = status_kset; + + retval = kobject_init_and_add(status_kobj, &status_ktype, NULL, "fan"); + if(retval) + return retval; + + retval = sysfs_create_file(status_kobj, &status_att); + + + inventec_class_init(); + fan_device_init(); + psu_device_init(); + led_device_init(); + + thread_control_set(1); + + printk(KERN_INFO "[p_thread] %s/%d: Creating Thread\n",__func__,__LINE__); + //Create the kernel thread with name 'inv_pthread' + thread_st = kthread_run(thread_fn, (void*)&thread_data, "inv_pthread"); + if (thread_st) + printk(KERN_INFO "[p_thread] inv_pthread Created successfully\n"); + else + printk(KERN_ERR "[p_thread] inv_pthread creation failed\n"); + + return retval; +} + +static void __exit inv_pthread_exit(void) +{ + thread_control_set(0); + /* Delay for guarantee thread exit */ + ssleep(THREAD_DELAY_MINS); + + fan_device_exit(); + psu_device_exit(); + led_device_exit(); + inventec_class_exit(); + + sysfs_remove_file(status_kobj, &status_att); + kset_unregister(status_kset); + kobject_del(status_kobj); + + printk(KERN_INFO "[p_thread] inv_pthread cleaning Up\n"); +} + +module_init(inv_pthread_init); +module_exit(inv_pthread_exit); + +MODULE_AUTHOR("Robert "); +MODULE_DESCRIPTION("Inventec Platform Management Thread"); +MODULE_VERSION("version 1.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_swps.c new file mode 100644 index 000000000000..03ef85a0443c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_swps.c @@ -0,0 +1,618 @@ +#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_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..6625efc00ed2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/utils/inventec_d7032_util.py @@ -0,0 +1,222 @@ +#!/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', +'inv_pthread'] + + + +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) + status, output = exec_cmd("rmmod gpio_ich",1) + status, output = exec_cmd("insmod /lib/modules/3.16.0-5-amd64/extra/gpio-ich.ko gpiobase=0",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 + exec_cmd("rmmod gpio_ich",1) + #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/d7054q28b/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/Makefile new file mode 100755 index 000000000000..37cbc2f4e8be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/Makefile @@ -0,0 +1,7 @@ +obj-m += inv_cpld.o inv_psoc.o +obj-m += inv_platform.o +obj-m += inv_pthread.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(temp6_input, 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)); + +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin)); + + +//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, + &sensor_dev_attr_temp6_input.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, + + // Add new fields which matching standard + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.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_pthread.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_pthread.c new file mode 100644 index 000000000000..4ca41e432be1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_pthread.c @@ -0,0 +1,1284 @@ +/***************************** + Cypress platform +******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INV_PTHREAD_KERNEL_MODULE + +#define SHOW_ATTR_WARNING ("N/A") +#define SHOW_ATTR_NOTPRINT ("Not Available") +#define SHOW_ATTR_NOTSUPPORT ("Not Support") + +#define INV_HWMID_MAX (10) +#define INV_HWMID_INIT (-1) + +/*access userspace data to kernel space*/ +#define ACC_R (0) +#define ACC_W (1) + +#define TINY_BUF_SIZE (8) +#define MAX_PATH_SIZE (64) +#define MIN_ACC_SIZE (32) +#define MAX_ACC_SIZE (256) + +/* + * LED definitions + */ +#define STATUS_LED_MODE_AUTO 0 +#define STATUS_LED_MODE_DIAG 1 +#define STATUS_LED_MODE_MANU 2 + +#define STATUS_LED_GRN0 10 // 0 - 000: off +#define STATUS_LED_GRN1 11 // 1 - 001: 0.5hz +#define STATUS_LED_GRN2 12 // 2 - 010: 1 hz +#define STATUS_LED_GRN3 13 // 3 - 011: 2 hz +#define STATUS_LED_GRN7 17 // 7 - 111: on +#define STATUS_LED_RED0 20 // 0 - 000: off +#define STATUS_LED_RED1 21 // 1 - 001: 0.5hz +#define STATUS_LED_RED2 22 // 2 - 010: 1 hz +#define STATUS_LED_RED3 23 // 3 - 011: 2 hz +#define STATUS_LED_RED7 27 // 7 - 111: on +#define STATUS_LED_INVALID 0 // Invalid + +ssize_t status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2); +ssize_t status_led_grn(const char *freq); +ssize_t status_led_red(const char *freq); +ssize_t status_led_diag_mode_enable(void); +ssize_t status_led_diag_mode_disable(void); +int status_led_check_color(void); +int status_led_check_diag_mode(void); + +#if 1 +/* For timestamps in SYSFS_LOG */ +#define SYSFS_LOG printk +#else +//#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[SYSFS] %s/%d: " fmt, __func__, __LINE__, ##args) +#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[p_thread] " fmt, ##args) +#endif + + +/* inventec_class *********************************/ +static struct kobject *status_kobj; +static struct kset *status_kset; + + +static struct mutex rw_lock; + +static int hwm_psoc = INV_HWMID_INIT; +static int hwm_cpld = INV_HWMID_INIT; + +int get_hwm_psoc(void) +{ + return hwm_psoc; +} + +int get_hwm_cpld(void) +{ + return hwm_cpld; +} + +static ssize_t access_user_space(const char *name, int mode, char *buf, size_t len, loff_t offset) +{ + struct file *fp; + mm_segment_t fs; + loff_t pos = offset; + char *mark = NULL; + ssize_t vfs_ret = 0; + + if (mode == ACC_R) { + fp = filp_open(name, O_RDONLY, S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_read(fp, buf, len, &pos); + + mark = strpbrk(buf, "\n"); + if (mark) + *mark = '\0'; + + filp_close(fp, NULL); + set_fs(fs); + } else if (mode == ACC_W) { + fp = filp_open(name, O_WRONLY, S_IWUSR | S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_write(fp, buf, len, &pos); + filp_close(fp, NULL); + set_fs(fs); + } + + return vfs_ret; +} + +int inventec_strtol(const char *sbufp, char **endp, unsigned int base) +{ + char *endptr; + int value = simple_strtol(sbufp, &endptr, base); + if (value == 0 && sbufp == endptr) { + *endp = NULL; + return value; + } + *endp = (char*)1; + return value; +} + +int inventec_singlechar_to_int(const char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } + else + if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } + else + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } + return -1; +} + +int inventec_store_input(char *inputp, int count) +{ + int i = 0; + while(inputp[i] != '\n' && inputp[i] != '\0' && i < count) { + i++; + } + inputp[i] = '\0'; + return strlen(inputp); +} + +#if 0 +/* + * Time stamps for kernel log on yocto + */ +#include + +void SYSFS_LOG(char *fmt, ...) +{ + char buf[80], ts[32]; + va_list args; + int hlen; + + inventec_tmstmp(&ts[0]); + hlen = sprintf(buf, "[SYSFS] %s ", ts); // Do not edit this line + + va_start(args, fmt); + vsprintf(&buf[hlen-1], fmt, args); + va_end(args); + printk(KERN_WARNING "[p_thread] %s\n", buf); +} +#endif + +ssize_t +inventec_show_attr(char *buf_p, const char *invdevp) +{ + int inv_len = MAX_ACC_SIZE; /* INV driver return max length */ + char tmp_buf[MAX_ACC_SIZE]; + char *str_negative = "-", *mark = NULL; + + /* [Step2] Get data by uaccess */ + memset(tmp_buf, 0, sizeof(tmp_buf)); + mutex_lock(&rw_lock); + if (access_user_space(invdevp, ACC_R, tmp_buf, inv_len, 0) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + mutex_unlock(&rw_lock); + + /* [Step3] Check return value + * - Ex: When transceiver not plugged + * => SWPS return error code "-202" + * => Pic8 need return "NA" (assume) + */ + if (strcspn(tmp_buf, str_negative) == 0) { + /* error case: "-202" */ + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + + /* OK case:*/ + mark = strpbrk(tmp_buf, "\n"); + if (mark) { *mark = '\0'; } + + return sprintf(buf_p, "%s\n", tmp_buf); +} + +ssize_t +inventec_store_attr(const char *buf_p, size_t count, const char *invdevp) +{ + ssize_t ret = 0; + + /* [Step2] Get data by uaccess */ + mutex_lock(&rw_lock); + if ((ret = access_user_space(invdevp, ACC_W, (char*)buf_p, count, 0)) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return -EINVAL; + } + mutex_unlock(&rw_lock); + + /* OK case:*/ + return ret; +} + +int sysfs_detect_hwmon_index(void) +{ + char hwmon_buf[MAX_ACC_SIZE]; + char hwmon_path[MAX_PATH_SIZE]; + int hwid = 0; + + for (hwid = 0; + hwid < INV_HWMID_MAX && (hwm_psoc == INV_HWMID_INIT || hwm_cpld == INV_HWMID_INIT); + hwid++) { + memset(hwmon_buf, 0, sizeof(hwmon_buf)); + sprintf(hwmon_path, "/sys/class/hwmon/hwmon%d/device/name", hwid); + + inventec_show_attr(hwmon_buf, hwmon_path); + if (strncmp(hwmon_buf, "inv_psoc", 8) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_bmc", 7) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_cpld", 8) == 0) { + hwm_cpld = hwid; + } + } + if (hwid >= INV_HWMID_MAX) { + printk(KERN_ERR "[p_thread] detect hwmon index failed, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return -1; + } + printk(KERN_INFO "[p_thread] detect hwmon index success, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return 0; +} + +static int __init +inventec_class_init(void) +{ + mutex_init(&rw_lock); + +#ifdef INV_PTHREAD_KERNEL_MODULE + if (sysfs_detect_hwmon_index() < 0) { + return -1; + } +#endif + + printk(KERN_INFO "[p_thread] [%s/%d] Module initial success.\n",__func__,__LINE__); + + return 0; +} + +static void __exit +inventec_class_exit(void) +{ + printk(KERN_INFO "[p_thread] [%s/%d] Remove module.\n",__func__,__LINE__); +} + +/* fan device *************************************/ +#define FAN_DEV_PATH_STATE "/sys/class/hwmon/hwmon%d/device/fan_gpi" +#define FAN_DEV_PATH_FAN1_INPUT "/sys/class/hwmon/hwmon%d/device/fan1_input" +#define FAN_DEV_PATH_FAN2_INPUT "/sys/class/hwmon/hwmon%d/device/fan2_input" +#define FAN_DEV_PATH_FAN3_INPUT "/sys/class/hwmon/hwmon%d/device/fan3_input" +#define FAN_DEV_PATH_FAN4_INPUT "/sys/class/hwmon/hwmon%d/device/fan4_input" +#define FAN_DEV_PATH_FAN5_INPUT "/sys/class/hwmon/hwmon%d/device/fan5_input" +#define FAN_DEV_PATH_FAN6_INPUT "/sys/class/hwmon/hwmon%d/device/fan6_input" +#define FAN_DEV_PATH_FAN7_INPUT "/sys/class/hwmon/hwmon%d/device/fan7_input" +#define FAN_DEV_PATH_FAN8_INPUT "/sys/class/hwmon/hwmon%d/device/fan8_input" + +static char fan_dev_path_state[MAX_PATH_SIZE]; +static char fan_dev_path_fan1_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan2_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan3_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan4_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan5_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan6_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan7_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan8_input[MAX_PATH_SIZE]; + +void sysfs_fan_path_init(void) +{ + sprintf(&fan_dev_path_state[0], FAN_DEV_PATH_STATE, get_hwm_psoc()); + sprintf(&fan_dev_path_fan1_input[0],FAN_DEV_PATH_FAN1_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan2_input[0],FAN_DEV_PATH_FAN2_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan3_input[0],FAN_DEV_PATH_FAN3_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan4_input[0],FAN_DEV_PATH_FAN4_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan5_input[0],FAN_DEV_PATH_FAN5_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan6_input[0],FAN_DEV_PATH_FAN6_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan7_input[0],FAN_DEV_PATH_FAN7_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan8_input[0],FAN_DEV_PATH_FAN8_INPUT, get_hwm_psoc()); +} + +#define FAN_STATE_NORMAL "normal" +#define FAN_STATE_FAULTY "faulty" +#define FAN_STATE_UNINSTALLED "uninstalled" +#define FAN_STATE_UNKNOW "unknown state" +#define FAN_STATE_INVALID "Invalid state value" +#define FAN_STATE_READ_ERROR "state read error" + +#define FAN_LOG_UNINSTALLED "removed" +#define FAN_LOG_NORMAL "inserted" + +//#define FAN_STATE_BIT_NORMAL 0 +#define FAN_STATE_BIT_FAULTY 0 +#define FAN_STATE_BIT_UNINSTALLED 1 +#define FAN_STATE_BIT_UNKNOW 2 +#define FAN_STATE_BIT_INVALID 3 +#define FAN_STATE_BIT_READ_ERROR 4 + +static struct fans_tbl_s { + char *fan_name; + char *fan_front; + char *fan_rear; + unsigned int fan_state; +} fans_tbl[] = { + {"fan1", fan_dev_path_fan1_input, + fan_dev_path_fan2_input, 0}, + {"fan2", fan_dev_path_fan3_input, + fan_dev_path_fan4_input, 0}, + {"fan3", fan_dev_path_fan5_input, + fan_dev_path_fan6_input, 0}, + {"fan4", fan_dev_path_fan7_input, + fan_dev_path_fan8_input, 0}, +}; +#define FAN_TBL_TOTAL ( sizeof(fans_tbl)/ sizeof(const struct fans_tbl_s) ) + +#define FAN_STATE_CHECK(i,b) (fans_tbl[i].fan_state & (1< 0) + { + printk(KERN_ERR "[p_thread] All fans failed.\n"); + printk(KERN_ERR "[p_thread] System shutdown immediately in %d seconds.\n", cd_shutdown); + } + cd_shutdown -= 1; + } + return ret; +} + +/* End of faninfo_device */ + +static int __init +fan_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_fan_path_init(); +#endif + return 0; +} + + +static void __exit +fan_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove fan module.\n"); +} + +/* psu device *************************************/ +static unsigned int psu_voltin = 0; +#define PSU_VOLTIN_ACDC (70000) + +/* + * normal/unpower/uninstall/fault are PSU states output from driver level + * checkpsu/error are defined by sysfs + */ +#define PSU_STATE_VAL_NORMAL (0) +#define PSU_STATE_VAL_UNPOWER (2) +#define PSU_STATE_VAL_FAULT (4) +#define PSU_STATE_VAL_UNINSTALL (7) +#define PSU_STATE_VAL_CHECKPSU (8) +#define PSU_STATE_VAL_ERROR (9) + +#define PSU_STATE_NORMAL ("0 : normal") +#define PSU_STATE_UNPOWER ("2 : unpowered") +#define PSU_STATE_FAULT ("4 : fault") +#define PSU_STATE_UNINSTALL ("7 : not installed") +#define PSU_STATE_CHECKPSU ("8 : check psu") +#define PSU_STATE_ERROR ("9 : state error") + +#define PSU_STATE_LEN_NORMAL (strlen(PSU_STATE_NORMAL)) +#define PSU_STATE_LEN_UNPOWER (strlen(PSU_STATE_UNPOWER)) +#define PSU_STATE_LEN_FAULT (strlen(PSU_STATE_FAULT)) +#define PSU_STATE_LEN_UNINSTALL (strlen(PSU_STATE_UNINSTALL)) +#define PSU_STATE_LEN_CHECKPSU (strlen(PSU_STATE_CHECKPSU)) + +typedef struct { + char *inv_dev_attrp; + char *inv_dev_pathp; +} psu_dev_t; + +typedef struct { + const char *psu_name; + int psu_major; + dev_t psu_devt; + struct device *psu_dev_p; + psu_dev_t *psu_dev_namep; + int psu_dev_total; + char *psu_inv_pathp; + void *psu_tracking; + char *psu_currentin; + char *psu_currentout; + char *psu_powerin; + char *psu_powerout; + char *psu_voltin; + char *psu_voltout; +} psu_dev_group_t; + +#define PSU_DEV_PATH_TEMPLATE "/sys/class/hwmon/hwmon%d/device/%s" + +static char psu_dev_path_state[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltin[MAX_PATH_SIZE]; +#if 0 +static char psu_dev_path_vendor[MAX_PATH_SIZE]; +static char psu_dev_path_version[MAX_PATH_SIZE]; +static char psu_dev_path_sn[MAX_PATH_SIZE]; +static char psu_dev_path_temperature[MAX_PATH_SIZE]; +static char psu_dev_path_fan_speed[MAX_PATH_SIZE]; +static char psu_dev_path_fan_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_fan_faulty[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_psu_rpm[MAX_PATH_SIZE]; +#endif + +void sysfs_psu_path_init(void) +{ + sprintf(&psu_dev_path_state[0], PSU_DEV_PATH_TEMPLATE, get_hwm_cpld(), "\%s" ); + sprintf(&psu_dev_path_psu_voltin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#if 0 + sprintf(&psu_dev_path_vendor[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_version[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_sn[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_temperature[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_speed[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_faulty[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_voltout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_rpm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#endif +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +#if 0 + { "vendor", psu_dev_path_vendor }, + { "version", psu_dev_path_version }, + { "sn", psu_dev_path_sn }, + { "temperature", psu_dev_path_temperature }, + { "fan_speed", psu_dev_path_fan_speed }, + { "fan_pwm", psu_dev_path_fan_pwm }, + { "fan_faulty", psu_dev_path_fan_faulty }, + { "psu_currentin", psu_dev_path_psu_currentin }, + { "psu_currentout", psu_dev_path_psu_currentout }, + { "psu_powerin", psu_dev_path_psu_powerin }, + { "psu_powerout", psu_dev_path_psu_powerout }, + { "psu_voltout", psu_dev_path_psu_voltout }, + { "psu_pwm", psu_dev_path_psu_pwm }, + { "psu_rpm", psu_dev_path_psu_rpm }, +#endif +}; +#define PSU_DEV_NAME_TOTAL ( sizeof(psu_dev_name) / sizeof(const psu_dev_t) ) + +static psu_dev_group_t psu_dev_group[] = { + { + .psu_name = "psu1", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, + { + .psu_name = "psu2", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, +}; +#define PSU_DEV_GROUP_TOTAL ( sizeof(psu_dev_group)/ sizeof(const psu_dev_group_t) ) + +static char psu_state[4][MIN_ACC_SIZE]; + +static struct psu_wire_tbl_s { + char *psu_attr; + char *psu_name; + char *psu_wire; + char *psu_state; +} psu_wire_tbl[] = { + { "state", "psu1", "psu0", psu_state[0] }, // Using cpld + { "state", "psu2", "psu1", psu_state[1] }, + { "psu_voltin", "psu1", "psoc_psu1_vin", psu_state[2] }, + { "psu_voltin", "psu2", "psoc_psu2_vin", psu_state[3] }, +}; +#define PSU_WIRE_TBL_TOTAL ( sizeof(psu_wire_tbl)/ sizeof(const struct psu_wire_tbl_s) ) + +static char * +psu_attr_get_wirep(const char *psu_attrp, const char *psu_namep, char **psu_statepp) +{ + int i; + + for (i = 0; i < PSU_WIRE_TBL_TOTAL; i++) { + if (strncmp(psu_wire_tbl[i].psu_attr, psu_attrp, strlen(psu_attrp)) == 0 && + strncmp(psu_wire_tbl[i].psu_name, psu_namep, strlen(psu_namep)) == 0) { + if (psu_statepp) { + *psu_statepp = psu_wire_tbl[i].psu_state; + } + return psu_wire_tbl[i].psu_wire; + } + } + return NULL; +} + +int psu_check_state_normal(char *statep) +{ + if (strstr(statep, "normal")) { + return 1; + } + return 0; +} + +#define PSU_ATTR_VOLTIN ("psu_voltin") +#define PSU_ATTR_VOLTIN_LEN (10) + +/* Get PSU voltin for determon AC(110v) or DC(48v) */ +void psu_get_voltin(void) +{ + char acc_path[MAX_PATH_SIZE], volt[MIN_ACC_SIZE]; + psu_dev_t *devnamep; + unsigned int voltin; + char *invwirep; + int i, j; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + //psu_dev_group[i].psu_name; + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_VOLTIN, PSU_ATTR_VOLTIN_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_VOLTIN, psu_dev_group[i].psu_name, NULL); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_DEBUG "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(volt, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + continue; + } + else { + voltin = simple_strtol(&volt[0], NULL, 10); + printk(KERN_DEBUG "[p_thread] Read %s %s = %u\n",acc_path,volt,voltin); + if (voltin > psu_voltin) { + psu_voltin = voltin; + } + } + } + } + } + + SYSFS_LOG("[p_thread] PSU voltin = %u\n", psu_voltin); +} + +#define PSU_ATTR_STATE ("state") +#define PSU_ATTR_STATE_LEN (5) + +/* psus_control() by inv_thread */ +int psus_control(int log_only) +{ + char acc_path[MAX_PATH_SIZE], state[MIN_ACC_SIZE]; + psu_dev_t *devnamep = NULL; + char *invwirep = NULL; + char *psu_statep = NULL; + int i, j, flag = 0; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_STATE, PSU_ATTR_STATE_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_STATE, psu_dev_group[i].psu_name, &psu_statep); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_INFO "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(state, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + if (strncmp(psu_statep, PSU_STATE_ERROR, strlen(PSU_STATE_ERROR)) != 0) { + strcpy(psu_statep, PSU_STATE_ERROR); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_ERROR); + } + flag = 1; + } + else + if (strstr(state, "normal")) { + //printk(KERN_INFO "[p_thread] %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + } + else + if (psu_voltin > PSU_VOLTIN_ACDC) { /* AC PSUS */ + //printk(KERN_INFO "[p_thread] RYU: %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + flag = 1; + } + else { /* DC PSUS */ + if (strncmp(psu_statep, PSU_STATE_CHECKPSU, PSU_STATE_LEN_CHECKPSU) != 0) { + strcpy(psu_statep, PSU_STATE_CHECKPSU); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_CHECKPSU); + } + flag = 1; + } + } + } + } + + if (log_only) { + return 0; + } + + //SYSFS_LOG("[p_thread] RYU: %s: flag = %d\n",psu_wire_tbl[i].psu_name,flag); + if (flag == 1) { + status_led_grn("3"); + return 1; + } + return 0; +} + +/* End of psuinfo_device */ + +static int __init +psu_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_psu_path_init(); +#endif + return 0; +} + + +static void __exit +psu_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove psu module.\n"); +} + +/* led device *************************************/ +#define STATUS_LED_GRN_PATH "/sys/class/hwmon/hwmon%d/device/grn_led" +#define STATUS_LED_RED_PATH "/sys/class/hwmon/hwmon%d/device/red_led" + +#define FAN_LED_GRN1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn1" +#define FAN_LED_GRN2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn2" +#define FAN_LED_GRN3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn3" +#define FAN_LED_GRN4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn4" +#define FAN_LED_RED1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red1" +#define FAN_LED_RED2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red2" +#define FAN_LED_RED3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red3" +#define FAN_LED_RED4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red4" + +#define HWMON_DEVICE_DIAG_PATH "/sys/class/hwmon/hwmon%d/device/diag" +#define HWMON_DEVICE_CTRL_PATH "/sys/class/hwmon/hwmon%d/device/ctl" + +static char status_led_grn_path[MAX_PATH_SIZE]; +static char status_led_red_path[MAX_PATH_SIZE]; +static char fan_led_grn1_path[MAX_PATH_SIZE]; +static char fan_led_grn2_path[MAX_PATH_SIZE]; +static char fan_led_grn3_path[MAX_PATH_SIZE]; +static char fan_led_grn4_path[MAX_PATH_SIZE]; +static char fan_led_red1_path[MAX_PATH_SIZE]; +static char fan_led_red2_path[MAX_PATH_SIZE]; +static char fan_led_red3_path[MAX_PATH_SIZE]; +static char fan_led_red4_path[MAX_PATH_SIZE]; +static char hwmon_device_diag_path[MAX_PATH_SIZE]; +static char hwmon_device_ctrl_path[MAX_PATH_SIZE]; + +void sysfs_led_path_init(void) +{ + sprintf(&status_led_grn_path[0], STATUS_LED_GRN_PATH, get_hwm_cpld()); + sprintf(&status_led_red_path[0], STATUS_LED_RED_PATH, get_hwm_cpld()); + sprintf(&fan_led_grn1_path[0], FAN_LED_GRN1_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn2_path[0], FAN_LED_GRN2_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn3_path[0], FAN_LED_GRN3_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn4_path[0], FAN_LED_GRN4_PATH, get_hwm_psoc()); + sprintf(&fan_led_red1_path[0], FAN_LED_RED1_PATH, get_hwm_psoc()); + sprintf(&fan_led_red2_path[0], FAN_LED_RED2_PATH, get_hwm_psoc()); + sprintf(&fan_led_red3_path[0], FAN_LED_RED3_PATH, get_hwm_psoc()); + sprintf(&fan_led_red4_path[0], FAN_LED_RED4_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_diag_path[0], HWMON_DEVICE_DIAG_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_ctrl_path[0], HWMON_DEVICE_CTRL_PATH, get_hwm_cpld()); +} + +/* return 0/off 1/green 2/red */ +int +status_led_check_color(void) +{ + char tmpbuf[MIN_ACC_SIZE]; + int ret = STATUS_LED_INVALID; + + if (inventec_show_attr(&tmpbuf[0], status_led_grn_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_GRN0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_GRN1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_GRN2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_GRN3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_GRN7; + } + return ret; + } + + if (inventec_show_attr(&tmpbuf[0], status_led_red_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_RED0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_RED1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_RED2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_RED3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_RED7; + } + return ret; + } + return ret; +} + +/* + * Store attr Section + */ +static DEFINE_MUTEX(diag_mutex); + +ssize_t status_led_diag_mode_enable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '0') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("1", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + mutex_unlock(&diag_mutex); + } + + return ret; +} + +ssize_t status_led_diag_mode_disable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '1') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("0", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + mutex_unlock(&diag_mutex); + } + return 1; +} + +ssize_t +status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2) +{ + ssize_t ret; + + ret = inventec_store_attr(tmp1, strlen(tmp1), path1); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(tmp2, strlen(tmp2), path2); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_red(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_grn(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +static int status_led_diag_mode = STATUS_LED_MODE_AUTO; + +int status_led_check_diag_mode(void) +{ + return status_led_diag_mode; +} + +/* End of ledinfo_device */ + +static int __init +led_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); +#endif + return 0; +} + + +static void __exit +led_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove led module.\n"); +} + +/* sensor device **********************************/ +#define SENSOR_DEV_PATH_SWITCH_TEMP "/sys/class/hwmon/hwmon%d/device/switch_tmp" + +static char sensor_dev_path_switch_temp[MAX_PATH_SIZE]; + +void sysfs_sensor_path_init(void) +{ + sprintf(&sensor_dev_path_switch_temp[0], SENSOR_DEV_PATH_SWITCH_TEMP, get_hwm_psoc()); +} + +void switch_temp_update(void) +{ + char buf[MIN_ACC_SIZE]; + ssize_t count = inventec_show_attr(&buf[0], "proc/switch/temp"); + if (count > 0) { + //printk(KERN_ERR "[p_thread] [STEMP] Switch temperature is out of range: %d\n", stemp); + inventec_store_attr(&buf[0], count, sensor_dev_path_switch_temp); + } +} + +/**************************************************/ +/* From system_device */ +static int inv_pthread_control = 1; + +int thread_control(void) +{ + return inv_pthread_control; +} + +void thread_control_set(int val) +{ + inv_pthread_control = val; +} +/* End system_device */ + +#define THREAD_SLEEP_MINS (3) +#define THREAD_DELAY_MINS (THREAD_SLEEP_MINS + THREAD_SLEEP_MINS + 1) + +extern void psu_get_voltin(void); + +static struct task_struct *thread_st; +static int thread_data; + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO +void led_set_gpio_to_change_status_led(void) +{ + ssize_t ret = inventec_store_attr("57", 2, "/sys/class/gpio/export"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 57 to /sys/class/gpio/export failed\n"); + return; + } + ret = inventec_store_attr("low", 3, "/sys/class/gpio/gpio57/direction"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write low to /sys/class/gpio/gpio57/direction failed\n"); + return; + } + SYSFS_LOG("[p_thread] Set gpio to support status led change successfully\n"); +} +#endif + +// Function executed by kernel thread +static int thread_fn(void *unused) +{ + /* Delay for guarantee HW ready */ + ssleep(THREAD_DELAY_MINS); + +#ifndef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); + sysfs_fan_path_init(); + sysfs_psu_path_init(); +#endif + //sysfs_sensor_path_init(); + + /* Default status init */ + status_led_grn("7"); + + psu_get_voltin(); + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO + led_set_gpio_to_change_status_led(); +#endif + + while (1) + { + ssleep(THREAD_SLEEP_MINS); + + if (thread_control() == 0) { + printk(KERN_INFO "[p_thread] %s/%d: Thread Stop by inv_pthread control\n",__func__,__LINE__); + break; + } + + if (status_led_check_diag_mode() == STATUS_LED_MODE_MANU) { + /* status led in change color/freq mode, higher priority. Ignore fans sttaus */ + continue; + } + + //switch_temp_update(); + + if (fans_control() > 0) { + psus_control(1); + continue; + } + else + if (psus_control(0) > 0) { + continue; + } + + if (status_led_check_color() != STATUS_LED_GRN7) { /* status led red, change it to green */ + status_led_grn("7"); + } + } + +#ifndef INV_PTHREAD_KERNEL_MODULE +err_inv_pthread_fn_1: +#endif + do_exit(0); + printk(KERN_INFO "[p_thread] %s/%d: Thread Stopped\n",__func__,__LINE__); + return 0; +} + + +static ssize_t s_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + int fan_absence; + size_t count; + + fan_absence = fans_control(); + count += sprintf(&buf[count], "%d\n", fan_absence); + return count; +} + +static ssize_t s_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) +{ + return count; +} + +static struct attribute status_att = { + .name = "fan_absence", + .mode = 0777, +}; + +static const struct sysfs_ops status_ops = { + .show = s_show, + .store = s_store, +}; + +static struct kobj_type status_ktype = { + .sysfs_ops = &status_ops, +}; + + +static int __init inv_pthread_init(void) +{ + int retval; + + status_kobj = kzalloc(sizeof(*status_kobj), GFP_KERNEL); + if(!status_kobj) + return PTR_ERR(status_kobj); + + status_kset = kset_create_and_add("platform_status", NULL, kernel_kobj); + if(!status_kset) + return -1; + + status_kobj->kset = status_kset; + + retval = kobject_init_and_add(status_kobj, &status_ktype, NULL, "fan"); + if(retval) + return retval; + + retval = sysfs_create_file(status_kobj, &status_att); + + + inventec_class_init(); + fan_device_init(); + psu_device_init(); + led_device_init(); + + thread_control_set(1); + + printk(KERN_INFO "[p_thread] %s/%d: Creating Thread\n",__func__,__LINE__); + //Create the kernel thread with name 'inv_pthread' + thread_st = kthread_run(thread_fn, (void*)&thread_data, "inv_pthread"); + if (thread_st) + printk(KERN_INFO "[p_thread] inv_pthread Created successfully\n"); + else + printk(KERN_ERR "[p_thread] inv_pthread creation failed\n"); + + return retval; +} + +static void __exit inv_pthread_exit(void) +{ + thread_control_set(0); + /* Delay for guarantee thread exit */ + ssleep(THREAD_DELAY_MINS); + + fan_device_exit(); + psu_device_exit(); + led_device_exit(); + inventec_class_exit(); + + sysfs_remove_file(status_kobj, &status_att); + kset_unregister(status_kset); + kobject_del(status_kobj); + + printk(KERN_INFO "[p_thread] inv_pthread cleaning Up\n"); +} + +module_init(inv_pthread_init); +module_exit(inv_pthread_exit); + +MODULE_AUTHOR("Robert "); +MODULE_DESCRIPTION("Inventec Platform Management Thread"); +MODULE_VERSION("version 1.0"); +MODULE_LICENSE("GPL"); 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 + * 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_SFP: + return &eeprom_map_sfp; + 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/d7054q28b/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/transceiver.h new file mode 100644 index 000000000000..0e79f0b9027f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/transceiver.h @@ -0,0 +1,168 @@ +#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_SFP "SFP" +#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/d7054q28b/utils/inventec_d7054_util.py b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/utils/inventec_d7054_util.py new file mode 100755 index 000000000000..246893ba05b7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/utils/inventec_d7054_util.py @@ -0,0 +1,235 @@ +#!/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 pca9548 0x71> /sys/bus/i2c/devices/i2c-0/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-2/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-3/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-4/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-5/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-6/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-7/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-8/new_device', +'echo inv_eeprom 0x53 > /sys/bus/i2c/devices/i2c-0/new_device'] +#'echo inv_psoc 0x66> /sys/bus/i2c/devices/i2c-0/new_device', +#'echo inv_cpld 0x55> /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', +'inv_pthread', +'swps'] + + + +def system_install(): + global FORCE + + #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(10,18): + 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(18,26): + 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 + for i in range(26,34): + 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(34,42): + 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(42,50): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-6/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(50,58): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-7/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(58,64): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-8/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 " D7054 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/d7264q28b/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/Makefile new file mode 100755 index 000000000000..37cbc2f4e8be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/Makefile @@ -0,0 +1,7 @@ +obj-m += inv_cpld.o inv_psoc.o +obj-m += inv_platform.o +obj-m += inv_pthread.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/d7264q28b/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_cpld.c new file mode 100644 index 000000000000..42401d626672 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_cpld.c @@ -0,0 +1,470 @@ +/* + * 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 +#define CPLD_BIOSCS_OFFSET 0x04 + + +/* 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 ssize_t show_bios_cs(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_BIOSCS_OFFSET, 1); + + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld BIOS_CS fail\n"); + + + status = sprintf (buf, "0x%X\n", b[0] & 0x01); + + return strlen(buf); +} + +static ssize_t set_bios_cs(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_BIOSCS_OFFSET, 1); + if(temp) byte |= 0x01; + else byte &= ~(0x01); + cpld_i2c_write(client, &byte, CPLD_BIOSCS_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 + "4 Hz", //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; + + 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 SENSOR_DEVICE_ATTR(bios_cs, S_IWUSR|S_IRUGO, show_bios_cs, set_bios_cs, 0); + +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, + + &sensor_dev_attr_bios_cs.dev_attr.attr, + NULL +}; + +static const struct attribute_group cpld_group = { + .attrs = cpld_attributes, +}; + +static struct attribute *cpld2_attributes[] = { + //info + &sensor_dev_attr_info.dev_attr.attr, + + NULL +}; + +static const struct attribute_group cpld2_group = { + .attrs = cpld2_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 */ + if(id->driver_data==1) // CPLD2 + status = sysfs_create_group(&client->dev.kobj, &cpld2_group); + else // default CPLD1 + 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, }, + { "inv_cpld2", 1, }, + { /* 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/d7264q28b/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_eeprom.c new file mode 100644 index 000000000000..3d13f3b04719 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/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/d7264q28b/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_platform.c new file mode 100644 index 000000000000..720a4cd2257b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_platform.c @@ -0,0 +1,239 @@ +#include +//#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),}, +}; + +static struct pca954x_platform_mode mux_modes_0_7[] = { + {.adap_id = bus_id(66),}, {.adap_id = bus_id(67),}, + {.adap_id = bus_id(68),}, {.adap_id = bus_id(69),}, + {.adap_id = bus_id(70),}, {.adap_id = bus_id(71),}, + {.adap_id = bus_id(72),}, {.adap_id = bus_id(73),}, +}; + +//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 pca954x_platform_data mux_data_0_7 = { + .modes = mux_modes_0_7, + .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 + {"inv_cpld2", 0, 0x77, 0, 0, 0},//cpld2 + {"pca9548", 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 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 i2c_board_info i2c_device_info9[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_7, 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 + {bus_id(9), ARRAY_SIZE(i2c_device_info9), i2c_device_info9 }, //mux 7 + +}; + +///////////////////////////////////////////////////////////////////////////////////////// +#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 = 1, // 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,k; + + 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 gpio69=32*2+8*0+5 + outl( inl(0x533) | (1<<2), 0x533); + outl( inl(0x541) | (1<<3), 0x541); + outl( inl(0x540) | (1<<5), 0x540); //RST_I2C_MUX_N (GPIO69) + outl( inl(0x500) | (1<<7), 0x500); //SYS_RDY_N (GPIO7) + outl( inl(0x501) | (1<<7), 0x501); //BMC_HEART_BEAT (GPIO15) + outl( inl(0x503) | (1<<2)|(1<<3), 0x503); //PSOC_HEART_BEAT(26),CPLD_HEART_BEAT(27) + + 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 +#include +#include +#include + +#define IPMI_MAX_INTF (4) +#define NETFN_OEM 0x30 +#define CMD_GETDATA 0x31 +#define CMD_SETDATA 0x32 +#define FAN_NUM 4 +#define PSU_NUM 2 + +#define PSU1 0x5800 +#define PSU2 0x5900 +#define BMC_PMBusNumber 3 +#define PMBus_Vender 0x99 +#define PMBus_Serial 0x9E +#define PMBus_Temp2 0x8E +#define PMBus_Version 0x9B +#define MaxLeng_Result 0x20 + +#define MAX_IPMI_RECV_LENGTH 0xff + +static long pmbus_reg2data_linear(int data, int linear16); +struct ipmi_result{ + char result[MAX_IPMI_RECV_LENGTH]; + int result_length; +}; + +DEFINE_MUTEX(ipmi_mutex); +DEFINE_MUTEX(ipmi2_mutex); +static struct ipmi_result ipmiresult; +static struct device *hwmon_dev; +static ipmi_user_t ipmi_mh_user = NULL; +static void msg_handler(struct ipmi_recv_msg *msg,void* handler_data); +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 +}; + +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) + + +static void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data) +{ + struct ipmi_result *msg_result = recv_msg->user_msg_data; + + if(recv_msg->msg.data[0]==0 && recv_msg->msg.data_len>0) { + msg_result->result_length=recv_msg->msg.data_len-1; + memcpy(msg_result->result, &recv_msg->msg.data[1], recv_msg->msg.data_len-1); + } + ipmi_free_recv_msg(recv_msg); + mutex_unlock(&ipmi_mutex); + + return; +} + +int start_ipmi_command(char NetFn, char cmd,char *data,int data_length, char* result, int* result_length) +{ + int rv=0,i; + int timeout; + + //wait previous command finish at least 50msec + timeout=50; + while((mutex_is_locked(&ipmi_mutex) == 1 || (mutex_is_locked(&ipmi2_mutex) == 1)) && (--timeout)>0) { usleep_range(1000,1010); } + if(timeout==0) { return -1; } + mutex_lock(&ipmi_mutex); + mutex_lock(&ipmi2_mutex); + + if(ipmi_mh_user == NULL) { + for (i=0,rv=1; i0) { usleep_range(1000,1100);} + if(timeout==0) { + mutex_unlock(&ipmi2_mutex); + return -1; + } + else { + *result_length=ipmiresult.result_length; + memcpy(result,ipmiresult.result,*result_length); + mutex_unlock(&ipmi2_mutex); + return 0; + } + } + return 0; +} +EXPORT_SYMBOL(start_ipmi_command); + +static ssize_t psoc_ipmi_read(u8 *buf, u8 offset, size_t count) +{ + uint8_t data[2]; + int result_len=0; + int rv; + + data[0] = offset; + data[1] = count; + + rv=start_ipmi_command(NETFN_OEM, CMD_GETDATA,data,2, buf, &result_len); + + return result_len; +} + +static ssize_t psoc_ipmi_write(char *buf, unsigned offset, size_t count) +{ + uint8_t data[count+1],result[1]; + int result_len; + + data[0] = offset; + memcpy(&data[1],buf,count); + + start_ipmi_command(NETFN_OEM, CMD_SETDATA,data,count+1, result, &result_len); + return count; +} + + +static u16 psoc_read16(u8 offset) +{ + u16 value = 0; + u8 buf[]={0,0}; + + if(psoc_ipmi_read(buf, offset, 2) == 2) + value = (buf[0]<<8 | buf[1]<<0); + + return value; +} + +static u8 psoc_read8(u8 offset) +{ + u8 value = 0; + u8 buf = 0; + + if(psoc_ipmi_read(&buf, offset, 1) == 1) + value = buf; + + return value; +} + +/* +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=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 byte=0; + int shift = (attr->index == 0)?3:0; + + status = psoc_ipmi_read(&byte, PSOC_PSU_OFFSET, 1); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + +static ssize_t show_ipmi_pmbus(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=0; + + data[0] = BMC_PMBusNumber; + 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(start_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_thermal(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index * 2 + THERMAL_OFFSET; + + status = psoc_read16(offset); + + 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=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index + PWM_OFFSET; + + status = psoc_read8(offset); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t set_pwm(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index + PWM_OFFSET; + + u8 pwm = simple_strtol(buf, NULL, 10); + if(pwm > 255) pwm = 255; + + psoc_ipmi_write(&pwm, offset, 1); + + return count; +} + + +static ssize_t show_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index*2 + RPM_OFFSET; + + status = psoc_read16(offset); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t show_switch_tmp(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + u16 temp = 0; + + status = psoc_ipmi_read((u8*)&temp, SWITCH_TMP_OFFSET, 2); + + 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) +{ + 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)); + psoc_ipmi_write((u8*)&temp2, SWITCH_TMP_OFFSET, 2); + + + return count; +} + +static ssize_t show_diag(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + u8 diag_flag = 0; + + status = psoc_ipmi_read((u8*)&diag_flag, DIAG_FLAG_OFFSET, 1); + + status = sprintf (buf, "%d\n", ((diag_flag & 0x80)?1:0)); + + return strlen(buf); +} + +static ssize_t set_diag(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + u8 value = 0; + u8 diag = simple_strtol(buf, NULL, 10); + + diag = diag?1:0; + + psoc_ipmi_read((u8*)&value, DIAG_FLAG_OFFSET, 1); + if(diag) value |= (1<<7); + else value &= ~(1<<7); + psoc_ipmi_write((u8*)&value, DIAG_FLAG_OFFSET, 1); + + return count; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + + status = psoc_read16(VERSION_OFFSET); + + return sprintf(buf, "ver: %x.%x\n", (status & 0xFF00)>>8, (status & 0xFF) ); +} + +static ssize_t show_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + return sprintf (buf, "inv_psoc\n"); +} + + +static ssize_t show_fan_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 bit = attr->index; + + status = psoc_read8(FAN_LED_OFFSET); + + return sprintf(buf, "%d\n", + (status & (1<index; + u8 led_state = 0; + + u8 v = simple_strtol(buf, NULL, 10); + + led_state = psoc_read8(FAN_LED_OFFSET); + if(v) led_state |= (1<index; + + status = psoc_read8(offset); + + 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=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index + PSU_INFO_OFFSET; + + status = psoc_read16(offset); + + 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(temp6_input, 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(name, S_IRUGO, show_name, NULL, 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)); + +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin)); + +//IPMI +static SENSOR_DEVICE_ATTR(thermal2_psu1, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Temp2); +static SENSOR_DEVICE_ATTR(psoc_psu1_vender, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Vender); +static SENSOR_DEVICE_ATTR(psoc_psu1_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Serial); +static SENSOR_DEVICE_ATTR(psoc_psu1_version, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Version); + +static SENSOR_DEVICE_ATTR(thermal2_psu2, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Temp2); +static SENSOR_DEVICE_ATTR(psoc_psu2_vender, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Vender); +static SENSOR_DEVICE_ATTR(psoc_psu2_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Serial); +static SENSOR_DEVICE_ATTR(psoc_psu2_version, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Version); + + +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, + &sensor_dev_attr_temp6_input.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 + &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, + + // Add new fields which matching standard + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + + //ipmi_i2c_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_name.dev_attr.attr, + + NULL +}; + +static const struct attribute_group psoc_group = { + .attrs = psoc_attributes, +}; + +static int __init inv_psoc_init(void) +{ + int ret; + + printk("+%s\n", __func__); + + hwmon_dev = hwmon_device_register(NULL); + if (IS_ERR(hwmon_dev)) { + goto fail_hwmon_device_register; + } + + ret = sysfs_create_group(&hwmon_dev->kobj, &psoc_group); + if (ret) { + goto fail_create_group_hwmon; + } + + printk(" Enable IPMI PSoC protocol.\n"); + return ret; + +fail_create_group_hwmon: + hwmon_device_unregister(hwmon_dev); +fail_hwmon_device_register: + return -ENOMEM; +} + +static void __exit inv_psoc_exit(void) +{ + sysfs_remove_group(&hwmon_dev->kobj, &psoc_group); + + if(ipmi_mh_user!=NULL) {ipmi_destroy_user(ipmi_mh_user);} + if(hwmon_dev != NULL) hwmon_device_unregister(hwmon_dev); +} + +MODULE_AUTHOR("Ting.Jack "); +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/d7264q28b/modules/inv_pthread.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_pthread.c new file mode 100644 index 000000000000..a45db7423f25 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_pthread.c @@ -0,0 +1,1303 @@ +/***************************** + Sequoia platform +******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INV_PTHREAD_KERNEL_MODULE + +#define SHOW_ATTR_WARNING ("N/A") +#define SHOW_ATTR_NOTPRINT ("Not Available") +#define SHOW_ATTR_NOTSUPPORT ("Not Support") + +#define INV_HWMID_MAX (10) +#define INV_HWMID_INIT (-1) + +/*access userspace data to kernel space*/ +#define ACC_R (0) +#define ACC_W (1) + +#define TINY_BUF_SIZE (8) +#define MAX_PATH_SIZE (64) +#define MIN_ACC_SIZE (32) +#define MAX_ACC_SIZE (256) + +/* + * LED definitions + */ +#define STATUS_LED_MODE_AUTO 0 +#define STATUS_LED_MODE_DIAG 1 +#define STATUS_LED_MODE_MANU 2 + +#define STATUS_LED_GRN0 10 // 0 - 000: off +#define STATUS_LED_GRN1 11 // 1 - 001: 0.5hz +#define STATUS_LED_GRN2 12 // 2 - 010: 1 hz +#define STATUS_LED_GRN3 13 // 3 - 011: 2 hz +#define STATUS_LED_GRN7 17 // 7 - 111: on +#define STATUS_LED_RED0 20 // 0 - 000: off +#define STATUS_LED_RED1 21 // 1 - 001: 0.5hz +#define STATUS_LED_RED2 22 // 2 - 010: 1 hz +#define STATUS_LED_RED3 23 // 3 - 011: 2 hz +#define STATUS_LED_RED7 27 // 7 - 111: on +#define STATUS_LED_INVALID 0 // Invalid + +ssize_t status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2); +ssize_t status_led_grn(const char *freq); +ssize_t status_led_red(const char *freq); +ssize_t status_led_diag_mode_enable(void); +ssize_t status_led_diag_mode_disable(void); +int status_led_check_color(void); +int status_led_check_diag_mode(void); + +#if 1 +/* For timestamps in SYSFS_LOG */ +#define SYSFS_LOG printk +#else +//#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[SYSFS] %s/%d: " fmt, __func__, __LINE__, ##args) +#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[p_thread] " fmt, ##args) +#endif + + +/* inventec_class *********************************/ +static struct kobject *status_kobj; +static struct kset *status_kset; + + +static struct mutex rw_lock; + +static int hwm_psoc = INV_HWMID_INIT; +static int hwm_cpld = INV_HWMID_INIT; +static int hwm_cpld2 = INV_HWMID_INIT; + +int get_hwm_psoc(void) +{ + return hwm_psoc; +} + +int get_hwm_cpld(void) +{ + return hwm_cpld; +} + +static ssize_t access_user_space(const char *name, int mode, char *buf, size_t len, loff_t offset) +{ + struct file *fp; + mm_segment_t fs; + loff_t pos = offset; + char *mark = NULL; + ssize_t vfs_ret = 0; + + if (mode == ACC_R) { + fp = filp_open(name, O_RDONLY, S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_read(fp, buf, len, &pos); + + mark = strpbrk(buf, "\n"); + if (mark) + *mark = '\0'; + + filp_close(fp, NULL); + set_fs(fs); + } else if (mode == ACC_W) { + fp = filp_open(name, O_WRONLY, S_IWUSR | S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_write(fp, buf, len, &pos); + filp_close(fp, NULL); + set_fs(fs); + } + + return vfs_ret; +} + +int inventec_strtol(const char *sbufp, char **endp, unsigned int base) +{ + char *endptr; + int value = simple_strtol(sbufp, &endptr, base); + if (value == 0 && sbufp == endptr) { + *endp = NULL; + return value; + } + *endp = (char*)1; + return value; +} + +int inventec_singlechar_to_int(const char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } + else + if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } + else + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } + return -1; +} + +int inventec_store_input(char *inputp, int count) +{ + int i = 0; + while(inputp[i] != '\n' && inputp[i] != '\0' && i < count) { + i++; + } + inputp[i] = '\0'; + return strlen(inputp); +} + +#if 0 +/* + * Time stamps for kernel log on yocto + */ +#include + +void SYSFS_LOG(char *fmt, ...) +{ + char buf[80], ts[32]; + va_list args; + int hlen; + + inventec_tmstmp(&ts[0]); + hlen = sprintf(buf, "[SYSFS] %s ", ts); // Do not edit this line + + va_start(args, fmt); + vsprintf(&buf[hlen-1], fmt, args); + va_end(args); + printk(KERN_WARNING "[p_thread] %s\n", buf); +} +#endif + +ssize_t +inventec_show_attr(char *buf_p, const char *invdevp) +{ + int inv_len = MAX_ACC_SIZE; /* INV driver return max length */ + char tmp_buf[MAX_ACC_SIZE]; + char *str_negative = "-", *mark = NULL; + + /* [Step2] Get data by uaccess */ + memset(tmp_buf, 0, sizeof(tmp_buf)); + mutex_lock(&rw_lock); + if (access_user_space(invdevp, ACC_R, tmp_buf, inv_len, 0) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + mutex_unlock(&rw_lock); + + /* [Step3] Check return value + * - Ex: When transceiver not plugged + * => SWPS return error code "-202" + * => Pic8 need return "NA" (assume) + */ + if (strcspn(tmp_buf, str_negative) == 0) { + /* error case: "-202" */ + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + + /* OK case:*/ + mark = strpbrk(tmp_buf, "\n"); + if (mark) { *mark = '\0'; } + + return sprintf(buf_p, "%s\n", tmp_buf); +} + +ssize_t +inventec_store_attr(const char *buf_p, size_t count, const char *invdevp) +{ + ssize_t ret = 0; + + /* [Step2] Get data by uaccess */ + mutex_lock(&rw_lock); + if ((ret = access_user_space(invdevp, ACC_W, (char*)buf_p, count, 0)) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return -EINVAL; + } + mutex_unlock(&rw_lock); + + /* OK case:*/ + return ret; +} + +int sysfs_detect_hwmon_index(void) +{ + char hwmon_buf[MAX_ACC_SIZE]; + char hwmon_path[MAX_PATH_SIZE]; + int hwid = 0; + + for (hwid = 0; + hwid < INV_HWMID_MAX && (hwm_psoc == INV_HWMID_INIT || hwm_cpld == INV_HWMID_INIT); + hwid++) { + memset(hwmon_buf, 0, sizeof(hwmon_buf)); + sprintf(hwmon_path, "/sys/class/hwmon/hwmon%d/name", hwid); + + inventec_show_attr(hwmon_buf, hwmon_path); + if (strncmp(hwmon_buf, "inv_psoc", 8) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_bmc", 7) == 0) { + hwm_psoc = hwid; + } + + sprintf(hwmon_path, "/sys/class/hwmon/hwmon%d/device/name", hwid); + inventec_show_attr(hwmon_buf, hwmon_path); + if (strncmp(hwmon_buf, "inv_cpld2", 9) == 0) { + hwm_cpld2 = hwid; + } + else + if (strncmp(hwmon_buf, "inv_cpld", 8) == 0) { + hwm_cpld = hwid; + } + } + if (hwid >= INV_HWMID_MAX) { + printk(KERN_ERR "[p_thread] detect hwmon index failed, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return -1; + } + printk(KERN_INFO "[p_thread] detect hwmon index success, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return 0; +} + +static int __init +inventec_class_init(void) +{ + mutex_init(&rw_lock); + +#ifdef INV_PTHREAD_KERNEL_MODULE + if (sysfs_detect_hwmon_index() < 0) { + return -1; + } +#endif + + printk(KERN_INFO "[p_thread] [%s/%d] Module initial success.\n",__func__,__LINE__); + + return 0; +} + +static void __exit +inventec_class_exit(void) +{ + printk(KERN_INFO "[p_thread] [%s/%d] Remove module.\n",__func__,__LINE__); +} + +/* fan device *************************************/ +#define FAN_DEV_PATH_STATE "/sys/class/hwmon/hwmon%d/fan_gpi" +#define FAN_DEV_PATH_FAN1_INPUT "/sys/class/hwmon/hwmon%d/fan1_input" +#define FAN_DEV_PATH_FAN2_INPUT "/sys/class/hwmon/hwmon%d/fan2_input" +#define FAN_DEV_PATH_FAN3_INPUT "/sys/class/hwmon/hwmon%d/fan3_input" +#define FAN_DEV_PATH_FAN4_INPUT "/sys/class/hwmon/hwmon%d/fan4_input" +#define FAN_DEV_PATH_FAN5_INPUT "/sys/class/hwmon/hwmon%d/fan5_input" +#define FAN_DEV_PATH_FAN6_INPUT "/sys/class/hwmon/hwmon%d/fan6_input" +#define FAN_DEV_PATH_FAN7_INPUT "/sys/class/hwmon/hwmon%d/fan7_input" +#define FAN_DEV_PATH_FAN8_INPUT "/sys/class/hwmon/hwmon%d/fan8_input" + +static char fan_dev_path_state[MAX_PATH_SIZE]; +static char fan_dev_path_fan1_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan2_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan3_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan4_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan5_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan6_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan7_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan8_input[MAX_PATH_SIZE]; + +void sysfs_fan_path_init(void) +{ + sprintf(&fan_dev_path_state[0], FAN_DEV_PATH_STATE, get_hwm_psoc()); + sprintf(&fan_dev_path_fan1_input[0],FAN_DEV_PATH_FAN1_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan2_input[0],FAN_DEV_PATH_FAN2_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan3_input[0],FAN_DEV_PATH_FAN3_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan4_input[0],FAN_DEV_PATH_FAN4_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan5_input[0],FAN_DEV_PATH_FAN5_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan6_input[0],FAN_DEV_PATH_FAN6_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan7_input[0],FAN_DEV_PATH_FAN7_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan8_input[0],FAN_DEV_PATH_FAN8_INPUT, get_hwm_psoc()); +} + +#define FAN_STATE_NORMAL "normal" +#define FAN_STATE_FAULTY "faulty" +#define FAN_STATE_UNINSTALLED "uninstalled" +#define FAN_STATE_UNKNOW "unknown state" +#define FAN_STATE_INVALID "Invalid state value" +#define FAN_STATE_READ_ERROR "state read error" + +#define FAN_LOG_UNINSTALLED "removed" +#define FAN_LOG_NORMAL "inserted" + +//#define FAN_STATE_BIT_NORMAL 0 +#define FAN_STATE_BIT_FAULTY 0 +#define FAN_STATE_BIT_UNINSTALLED 1 +#define FAN_STATE_BIT_UNKNOW 2 +#define FAN_STATE_BIT_INVALID 3 +#define FAN_STATE_BIT_READ_ERROR 4 + +static struct fans_tbl_s { + char *fan_name; + char *fan_front; + char *fan_rear; + unsigned int fan_state; +} fans_tbl[] = { + {"fan1", fan_dev_path_fan1_input, + fan_dev_path_fan2_input, 0}, + {"fan2", fan_dev_path_fan3_input, + fan_dev_path_fan4_input, 0}, + {"fan3", fan_dev_path_fan5_input, + fan_dev_path_fan6_input, 0}, + {"fan4", fan_dev_path_fan7_input, + fan_dev_path_fan8_input, 0}, +}; +#define FAN_TBL_TOTAL ( sizeof(fans_tbl)/ sizeof(const struct fans_tbl_s) ) + +#define FAN_STATE_CHECK(i,b) (fans_tbl[i].fan_state & (1< 0) + { + printk(KERN_ERR "[p_thread] All fans failed.\n"); + printk(KERN_ERR "[p_thread] System shutdown immediately in %d seconds.\n", cd_shutdown); + } + cd_shutdown -= 1; + } + return ret; +} + +/* End of faninfo_device */ + +static int __init +fan_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_fan_path_init(); +#endif + return 0; +} + + +static void __exit +fan_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove fan module.\n"); +} + +/* psu device *************************************/ +static unsigned int psu_voltin = 0; +#define PSU_VOLTIN_ACDC (70000) + +/* + * normal/unpower/uninstall/fault are PSU states output from driver level + * checkpsu/error are defined by sysfs + */ +#define PSU_STATE_VAL_NORMAL (0) +#define PSU_STATE_VAL_UNPOWER (2) +#define PSU_STATE_VAL_FAULT (4) +#define PSU_STATE_VAL_UNINSTALL (7) +#define PSU_STATE_VAL_CHECKPSU (8) +#define PSU_STATE_VAL_ERROR (9) + +#define PSU_STATE_NORMAL ("0 : normal") +#define PSU_STATE_UNPOWER ("2 : unpowered") +#define PSU_STATE_FAULT ("4 : fault") +#define PSU_STATE_UNINSTALL ("7 : not installed") +#define PSU_STATE_CHECKPSU ("8 : check psu") +#define PSU_STATE_ERROR ("9 : state error") + +#define PSU_STATE_LEN_NORMAL (strlen(PSU_STATE_NORMAL)) +#define PSU_STATE_LEN_UNPOWER (strlen(PSU_STATE_UNPOWER)) +#define PSU_STATE_LEN_FAULT (strlen(PSU_STATE_FAULT)) +#define PSU_STATE_LEN_UNINSTALL (strlen(PSU_STATE_UNINSTALL)) +#define PSU_STATE_LEN_CHECKPSU (strlen(PSU_STATE_CHECKPSU)) + +typedef struct { + char *inv_dev_attrp; + char *inv_dev_pathp; +} psu_dev_t; + +typedef struct { + const char *psu_name; + int psu_major; + dev_t psu_devt; + struct device *psu_dev_p; + psu_dev_t *psu_dev_namep; + int psu_dev_total; + char *psu_inv_pathp; + void *psu_tracking; + char *psu_currentin; + char *psu_currentout; + char *psu_powerin; + char *psu_powerout; + char *psu_voltin; + char *psu_voltout; +} psu_dev_group_t; + +#define PSU_PSOC_DEV_PATH_TEMPLATE "/sys/class/hwmon/hwmon%d/%s" +#define PSU_CPLD_DEV_PATH_TEMPLATE "/sys/class/hwmon/hwmon%d/device/%s" + +static char psu_dev_path_state[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltin[MAX_PATH_SIZE]; +#if 0 +static char psu_dev_path_vendor[MAX_PATH_SIZE]; +static char psu_dev_path_version[MAX_PATH_SIZE]; +static char psu_dev_path_sn[MAX_PATH_SIZE]; +static char psu_dev_path_temperature[MAX_PATH_SIZE]; +static char psu_dev_path_fan_speed[MAX_PATH_SIZE]; +static char psu_dev_path_fan_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_fan_faulty[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_psu_rpm[MAX_PATH_SIZE]; +#endif + +void sysfs_psu_path_init(void) +{ + sprintf(&psu_dev_path_state[0], PSU_CPLD_DEV_PATH_TEMPLATE, get_hwm_cpld(), "\%s" ); + sprintf(&psu_dev_path_psu_voltin[0], PSU_PSOC_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#if 0 + sprintf(&psu_dev_path_vendor[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_version[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_sn[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_temperature[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_speed[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_faulty[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_voltout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_rpm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#endif +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +#if 0 + { "vendor", psu_dev_path_vendor }, + { "version", psu_dev_path_version }, + { "sn", psu_dev_path_sn }, + { "temperature", psu_dev_path_temperature }, + { "fan_speed", psu_dev_path_fan_speed }, + { "fan_pwm", psu_dev_path_fan_pwm }, + { "fan_faulty", psu_dev_path_fan_faulty }, + { "psu_currentin", psu_dev_path_psu_currentin }, + { "psu_currentout", psu_dev_path_psu_currentout }, + { "psu_powerin", psu_dev_path_psu_powerin }, + { "psu_powerout", psu_dev_path_psu_powerout }, + { "psu_voltout", psu_dev_path_psu_voltout }, + { "psu_pwm", psu_dev_path_psu_pwm }, + { "psu_rpm", psu_dev_path_psu_rpm }, +#endif +}; +#define PSU_DEV_NAME_TOTAL ( sizeof(psu_dev_name) / sizeof(const psu_dev_t) ) + +static psu_dev_group_t psu_dev_group[] = { + { + .psu_name = "psu1", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, + { + .psu_name = "psu2", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, +}; +#define PSU_DEV_GROUP_TOTAL ( sizeof(psu_dev_group)/ sizeof(const psu_dev_group_t) ) + +static char psu_state[4][MIN_ACC_SIZE]; + +static struct psu_wire_tbl_s { + char *psu_attr; + char *psu_name; + char *psu_wire; + char *psu_state; +} psu_wire_tbl[] = { + { "state", "psu1", "psu0", psu_state[0] }, // Using cpld + { "state", "psu2", "psu1", psu_state[1] }, + { "psu_voltin", "psu1", "psoc_psu1_vin", psu_state[2] }, + { "psu_voltin", "psu2", "psoc_psu2_vin", psu_state[3] }, +}; +#define PSU_WIRE_TBL_TOTAL ( sizeof(psu_wire_tbl)/ sizeof(const struct psu_wire_tbl_s) ) + +static char * +psu_attr_get_wirep(const char *psu_attrp, const char *psu_namep, char **psu_statepp) +{ + int i; + + for (i = 0; i < PSU_WIRE_TBL_TOTAL; i++) { + if (strncmp(psu_wire_tbl[i].psu_attr, psu_attrp, strlen(psu_attrp)) == 0 && + strncmp(psu_wire_tbl[i].psu_name, psu_namep, strlen(psu_namep)) == 0) { + if (psu_statepp) { + *psu_statepp = psu_wire_tbl[i].psu_state; + } + return psu_wire_tbl[i].psu_wire; + } + } + return NULL; +} + +int psu_check_state_normal(char *statep) +{ + if (strstr(statep, "normal")) { + return 1; + } + return 0; +} + +#define PSU_ATTR_VOLTIN ("psu_voltin") +#define PSU_ATTR_VOLTIN_LEN (10) + +/* Get PSU voltin for determon AC(110v) or DC(48v) */ +void psu_get_voltin(void) +{ + char acc_path[MAX_PATH_SIZE], volt[MIN_ACC_SIZE]; + psu_dev_t *devnamep; + unsigned int voltin; + char *invwirep; + int i, j; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + //psu_dev_group[i].psu_name; + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_VOLTIN, PSU_ATTR_VOLTIN_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_VOLTIN, psu_dev_group[i].psu_name, NULL); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_DEBUG "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(volt, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + continue; + } + else { + voltin = simple_strtol(&volt[0], NULL, 10); + printk(KERN_DEBUG "[p_thread] Read %s %s = %u\n",acc_path,volt,voltin); + if (voltin > psu_voltin) { + psu_voltin = voltin; + } + } + } + } + } + + SYSFS_LOG("[p_thread] PSU voltin = %u\n", psu_voltin); +} + +#define PSU_ATTR_STATE ("state") +#define PSU_ATTR_STATE_LEN (5) + +/* psus_control() by inv_thread */ +int psus_control(int log_only) +{ + char acc_path[MAX_PATH_SIZE], state[MIN_ACC_SIZE]; + psu_dev_t *devnamep = NULL; + char *invwirep = NULL; + char *psu_statep = NULL; + int i, j, flag = 0; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_STATE, PSU_ATTR_STATE_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_STATE, psu_dev_group[i].psu_name, &psu_statep); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_INFO "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(state, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + if (strncmp(psu_statep, PSU_STATE_ERROR, strlen(PSU_STATE_ERROR)) != 0) { + strcpy(psu_statep, PSU_STATE_ERROR); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_ERROR); + } + flag = 1; + } + else + if (strstr(state, "normal")) { + //printk(KERN_INFO "[p_thread] %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + } + else + if (psu_voltin > PSU_VOLTIN_ACDC) { /* AC PSUS */ + //printk(KERN_INFO "[p_thread] RYU: %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + flag = 1; + } + else { /* DC PSUS */ + if (strncmp(psu_statep, PSU_STATE_CHECKPSU, PSU_STATE_LEN_CHECKPSU) != 0) { + strcpy(psu_statep, PSU_STATE_CHECKPSU); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_CHECKPSU); + } + flag = 1; + } + } + } + } + + if (log_only) { + return 0; + } + + //SYSFS_LOG("[p_thread] RYU: %s: flag = %d\n",psu_wire_tbl[i].psu_name,flag); + if (flag == 1) { + status_led_grn("3"); + return 1; + } + return 0; +} + +/* End of psuinfo_device */ + +static int __init +psu_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_psu_path_init(); +#endif + return 0; +} + + +static void __exit +psu_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove psu module.\n"); +} + +/* led device *************************************/ +#define STATUS_LED_GRN_PATH "/sys/class/hwmon/hwmon%d/device/grn_led" +#define STATUS_LED_RED_PATH "/sys/class/hwmon/hwmon%d/device/red_led" + +#define FAN_LED_GRN1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn1" +#define FAN_LED_GRN2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn2" +#define FAN_LED_GRN3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn3" +#define FAN_LED_GRN4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn4" +#define FAN_LED_RED1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red1" +#define FAN_LED_RED2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red2" +#define FAN_LED_RED3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red3" +#define FAN_LED_RED4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red4" + +#define HWMON_DEVICE_DIAG_PATH "/sys/class/hwmon/hwmon%d/device/diag" +#define HWMON_DEVICE_CTRL_PATH "/sys/class/hwmon/hwmon%d/device/ctl" + +static char status_led_grn_path[MAX_PATH_SIZE]; +static char status_led_red_path[MAX_PATH_SIZE]; +static char fan_led_grn1_path[MAX_PATH_SIZE]; +static char fan_led_grn2_path[MAX_PATH_SIZE]; +static char fan_led_grn3_path[MAX_PATH_SIZE]; +static char fan_led_grn4_path[MAX_PATH_SIZE]; +static char fan_led_red1_path[MAX_PATH_SIZE]; +static char fan_led_red2_path[MAX_PATH_SIZE]; +static char fan_led_red3_path[MAX_PATH_SIZE]; +static char fan_led_red4_path[MAX_PATH_SIZE]; +static char hwmon_device_diag_path[MAX_PATH_SIZE]; +static char hwmon_device_ctrl_path[MAX_PATH_SIZE]; + +void sysfs_led_path_init(void) +{ + sprintf(&status_led_grn_path[0], STATUS_LED_GRN_PATH, get_hwm_cpld()); + sprintf(&status_led_red_path[0], STATUS_LED_RED_PATH, get_hwm_cpld()); + sprintf(&fan_led_grn1_path[0], FAN_LED_GRN1_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn2_path[0], FAN_LED_GRN2_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn3_path[0], FAN_LED_GRN3_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn4_path[0], FAN_LED_GRN4_PATH, get_hwm_psoc()); + sprintf(&fan_led_red1_path[0], FAN_LED_RED1_PATH, get_hwm_psoc()); + sprintf(&fan_led_red2_path[0], FAN_LED_RED2_PATH, get_hwm_psoc()); + sprintf(&fan_led_red3_path[0], FAN_LED_RED3_PATH, get_hwm_psoc()); + sprintf(&fan_led_red4_path[0], FAN_LED_RED4_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_diag_path[0], HWMON_DEVICE_DIAG_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_ctrl_path[0], HWMON_DEVICE_CTRL_PATH, get_hwm_cpld()); +} + +/* return 0/off 1/green 2/red */ +int +status_led_check_color(void) +{ + char tmpbuf[MIN_ACC_SIZE]; + int ret = STATUS_LED_INVALID; + + if (inventec_show_attr(&tmpbuf[0], status_led_grn_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_GRN0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_GRN1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_GRN2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_GRN3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_GRN7; + } + return ret; + } + + if (inventec_show_attr(&tmpbuf[0], status_led_red_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_RED0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_RED1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_RED2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_RED3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_RED7; + } + return ret; + } + return ret; +} + +/* + * Store attr Section + */ +static DEFINE_MUTEX(diag_mutex); + +ssize_t status_led_diag_mode_enable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '0') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("1", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + mutex_unlock(&diag_mutex); + } + + return ret; +} + +ssize_t status_led_diag_mode_disable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '1') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("0", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + mutex_unlock(&diag_mutex); + } + return 1; +} + +ssize_t +status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2) +{ + ssize_t ret; + + ret = inventec_store_attr(tmp1, strlen(tmp1), path1); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(tmp2, strlen(tmp2), path2); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_red(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_grn(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +static int status_led_diag_mode = STATUS_LED_MODE_AUTO; + +int status_led_check_diag_mode(void) +{ + return status_led_diag_mode; +} + +void sys_ready(void) +{ + ssize_t ret; + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + SYSFS_LOG("[p_thread] set ctl fail"); + } + SYSFS_LOG("[p_thread] set ctl successfully"); +} + +/* End of ledinfo_device */ + +static int __init +led_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); + sys_ready(); +#endif + return 0; +} + + +static void __exit +led_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove led module.\n"); +} + +/* sensor device **********************************/ +#define SENSOR_DEV_PATH_SWITCH_TEMP "/sys/class/hwmon/hwmon%d/device/switch_tmp" + +static char sensor_dev_path_switch_temp[MAX_PATH_SIZE]; + +void sysfs_sensor_path_init(void) +{ + sprintf(&sensor_dev_path_switch_temp[0], SENSOR_DEV_PATH_SWITCH_TEMP, get_hwm_psoc()); +} + +void switch_temp_update(void) +{ + char buf[MIN_ACC_SIZE]; + ssize_t count = inventec_show_attr(&buf[0], "proc/switch/temp"); + if (count > 0) { + //printk(KERN_ERR "[p_thread] [STEMP] Switch temperature is out of range: %d\n", stemp); + inventec_store_attr(&buf[0], count, sensor_dev_path_switch_temp); + } +} + +/**************************************************/ +/* From system_device */ +static int inv_pthread_control = 1; + +int thread_control(void) +{ + return inv_pthread_control; +} + +void thread_control_set(int val) +{ + inv_pthread_control = val; +} +/* End system_device */ + +#define THREAD_SLEEP_MINS (3) +#define THREAD_DELAY_MINS (THREAD_SLEEP_MINS + THREAD_SLEEP_MINS + 1) + +extern void psu_get_voltin(void); + +static struct task_struct *thread_st; +static int thread_data; + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO +void led_set_gpio_to_change_status_led(void) +{ + ssize_t ret = inventec_store_attr("57", 2, "/sys/class/gpio/export"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 57 to /sys/class/gpio/export failed\n"); + return; + } + ret = inventec_store_attr("low", 3, "/sys/class/gpio/gpio57/direction"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write low to /sys/class/gpio/gpio57/direction failed\n"); + return; + } + SYSFS_LOG("[p_thread] Set gpio to support status led change successfully\n"); +} +#endif + +// Function executed by kernel thread +static int thread_fn(void *unused) +{ + /* Delay for guarantee HW ready */ + ssleep(THREAD_DELAY_MINS); + +#ifndef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); + sysfs_fan_path_init(); + sysfs_psu_path_init(); +#endif + //sysfs_sensor_path_init(); + + /* Default status init */ + status_led_grn("7"); + + psu_get_voltin(); + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO + led_set_gpio_to_change_status_led(); +#endif + + while (1) + { + ssleep(THREAD_SLEEP_MINS); + + if (thread_control() == 0) { + printk(KERN_INFO "[p_thread] %s/%d: Thread Stop by inv_pthread control\n",__func__,__LINE__); + break; + } + + if (status_led_check_diag_mode() == STATUS_LED_MODE_MANU) { + /* status led in change color/freq mode, higher priority. Ignore fans sttaus */ + continue; + } + + //switch_temp_update(); + + if (fans_control() > 0) { + psus_control(1); + continue; + } + else + if (psus_control(0) > 0) { + continue; + } + + if (status_led_check_color() != STATUS_LED_GRN7) { /* status led red, change it to green */ + status_led_grn("7"); + } + } + +#ifndef INV_PTHREAD_KERNEL_MODULE +err_inv_pthread_fn_1: +#endif + do_exit(0); + printk(KERN_INFO "[p_thread] %s/%d: Thread Stopped\n",__func__,__LINE__); + return 0; +} + + +static ssize_t s_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + int fan_absence; + size_t count; + + fan_absence = fans_control(); + count += sprintf(&buf[count], "%d\n", fan_absence); + return count; +} + +static ssize_t s_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) +{ + return count; +} + +static struct attribute status_att = { + .name = "fan_absence", + .mode = 0777, +}; + +static const struct sysfs_ops status_ops = { + .show = s_show, + .store = s_store, +}; + +static struct kobj_type status_ktype = { + .sysfs_ops = &status_ops, +}; + + +static int __init inv_pthread_init(void) +{ + int retval; + + status_kobj = kzalloc(sizeof(*status_kobj), GFP_KERNEL); + if(!status_kobj) + return PTR_ERR(status_kobj); + + status_kset = kset_create_and_add("platform_status", NULL, kernel_kobj); + if(!status_kset) + return -1; + + status_kobj->kset = status_kset; + + retval = kobject_init_and_add(status_kobj, &status_ktype, NULL, "fan"); + if(retval) + return retval; + + retval = sysfs_create_file(status_kobj, &status_att); + + + inventec_class_init(); + fan_device_init(); + psu_device_init(); + led_device_init(); + + thread_control_set(1); + + printk(KERN_INFO "[p_thread] %s/%d: Creating Thread\n",__func__,__LINE__); + //Create the kernel thread with name 'inv_pthread' + thread_st = kthread_run(thread_fn, (void*)&thread_data, "inv_pthread"); + if (thread_st) + printk(KERN_INFO "[p_thread] inv_pthread Created successfully\n"); + else + printk(KERN_ERR "[p_thread] inv_pthread creation failed\n"); + + return retval; +} + +static void __exit inv_pthread_exit(void) +{ + thread_control_set(0); + /* Delay for guarantee thread exit */ + ssleep(THREAD_DELAY_MINS); + + fan_device_exit(); + psu_device_exit(); + led_device_exit(); + inventec_class_exit(); + + sysfs_remove_file(status_kobj, &status_att); + kset_unregister(status_kset); + kobject_del(status_kobj); + + printk(KERN_INFO "[p_thread] inv_pthread cleaning Up\n"); +} + +module_init(inv_pthread_init); +module_exit(inv_pthread_exit); + +MODULE_AUTHOR("Robert "); +MODULE_DESCRIPTION("Inventec Platform Management Thread"); +MODULE_VERSION("version 1.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.c new file mode 100644 index 000000000000..58c1a0aeb048 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.c @@ -0,0 +1,719 @@ +#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,const void *data){ + + 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 = secquoia_ioexp_layout; + port_layout = secquoia_port_layout; + ioexp_total = ARRAY_SIZE(secquoia_ioexp_layout); + port_total = ARRAY_SIZE(secquoia_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_SEQUOIA_NABC: + 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/d7264q28b/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.h new file mode 100644 index 000000000000..3d462ed3c944 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.h @@ -0,0 +1,184 @@ +#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_DEV_MODCTL "module" +#define SWP_RESET_PWD "inventec" +#define SWP_POLLING_PERIOD (300) /* msec */ +#define SWP_POLLING_ENABLE (1) +#define SWP_AUTOCONFIG_ENABLE (1) + +/* Module information */ +#define SWP_AUTHOR "Neil " +#define SWP_DESC "Inventec port and transceiver driver" +#define SWP_VERSION "4.2.5" +#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_SEQUOIA_GA (171) +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_SEQUOIA_GA + +/* Define platform flag and kernel version */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_SEQUOIA_GA) + #define SWPS_SEQUOIA (1) + #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_SEQUOIA_GA, "Sequoia_GA" }; + +/* ========================================== + * Sequoia Layout configuration + * ========================================== + */ + +struct inv_ioexp_layout_s secquoia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + +struct inv_port_layout_s secquoia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 1, 11, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 2, 12, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 3, 13, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 4, 14, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + { 5, 15, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 6, 16, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + { 7, 17, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + { 8, 18, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + { 9, 19, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {10, 20, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {11, 21, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {12, 22, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} }, + {13, 23, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} }, + {14, 24, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121, 122, 123, 124} }, + {15, 25, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} }, + {16, 26, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {137, 138, 139, 140} }, + {17, 27, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {129, 130, 131, 132} }, + {18, 28, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {153, 154, 155, 156} }, + {19, 29, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {145, 146, 147, 148} }, + {20, 30, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {169, 170, 171, 172} }, + {21, 31, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {161, 162, 163, 164} }, + {22, 32, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {185, 186, 187, 188} }, + {23, 33, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {177, 178, 179, 180} }, + {24, 34, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {201, 202, 203, 204} }, + {25, 35, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {193, 194, 195, 196} }, + {26, 36, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {217, 218, 219, 220} }, + {27, 37, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {209, 210, 211, 212} }, + {28, 38, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {233, 234, 235, 236} }, + {29, 39, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {225, 226, 227, 228} }, + {30, 40, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {249, 250, 251, 252} }, + {31, 41, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {241, 242, 243, 244} }, + {32, 45, 4, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + {33, 44, 4, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + {34, 43, 4, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + {35, 42, 4, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + {36, 49, 4, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {37, 48, 4, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {38, 47, 4, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {39, 46, 4, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {40, 53, 5, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {41, 52, 5, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {42, 51, 5, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {43, 50, 5, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {44, 57, 5, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} }, + {45, 56, 5, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} }, + {46, 55, 5, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125, 126, 127, 128} }, + {47, 54, 5, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117, 118, 119, 120} }, + {48, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {141, 142, 143, 144} }, + {49, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {133, 134, 135, 136} }, + {50, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {157, 158, 159, 160} }, + {51, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {149, 150, 151, 152} }, + {52, 65, 6, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {173, 174, 175, 176} }, + {53, 64, 6, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {165, 166, 167, 168} }, + {54, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {189, 190, 191, 192} }, + {55, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {181, 182, 183, 184} }, + {56, 69, 7, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {205, 206, 207, 208} }, + {57, 68, 7, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {197, 198, 199, 200} }, + {58, 67, 7, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {221, 222, 223, 224} }, + {59, 66, 7, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {213, 214, 215, 216} }, + {60, 73, 7, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {237, 238, 239, 240} }, + {61, 72, 7, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {229, 230, 231, 232} }, + {62, 71, 7, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {253, 254, 255, 256} }, + {63, 70, 7, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {245, 246, 247, 248} }, +}; + + +#endif /* INV_SWPS_H */ + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.c new file mode 100644 index 000000000000..231884f3e442 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.c @@ -0,0 +1,1786 @@ +#include +#include +#include "io_expander.h" + +static struct ioexp_obj_s *ioexp_head_p = NULL; +static struct ioexp_obj_s *ioexp_tail_p = NULL; + + +/* ========== Register IOEXP layout ========== + */ +struct ioexp_map_s ioexp_map_magnolia_nab = { + + .chip_amount = 2, + .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_magnolia_7ab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {1, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {1, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {1, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 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) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 2}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 3}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 1, 7}, /* 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) */ + }, +}; + + +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) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 0, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 0, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 0, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 0, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 0, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 0, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 0, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 1, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 1, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 1, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 1, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 1, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 1, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 1, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +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) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(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) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_5a = { + + .chip_amount = 1, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_6abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 0}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 3}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 0}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + {2, 1, 5}, /* map_present[8] = MOD_ABS_PORT(X+8) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {1, 0, 1}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 6}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 1, 3}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {2, 0, 1}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {2, 0, 6}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + {2, 1, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 2}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 7}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 1, 4}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {2, 0, 2}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {2, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + {2, 1, 4}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+8) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {1, 0, 0}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 0, 5}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 2}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {2, 0, 0}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {2, 0, 5}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + {2, 1, 2}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_sequoia_nabc = { + + .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, 1, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {0, 1, 6}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {0, 1, 7}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 3}, /* 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, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {0, 0, 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_check_by_mode(struct ioexp_obj_s *self){ + + switch (self->mode){ + case IOEXP_MODE_DIRECT: + return self->fsm_4_direct(self); + + case IOEXP_MODE_POLLING: + if (self->state >= 0){ + return 0; + } + switch (self->state){ + case STATE_IOEXP_INIT: + return ERR_IOEXP_UNINIT; + case STATE_IOEXP_ABNORMAL: + return ERR_IOEXP_ABNORMAL; + default: + return ERR_IOEXP_NOSTATE; + } + break; + + default: + break; + } + SWPS_ERR("%s: Exception occurs. :%d \n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +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; + + /* Check and get address */ + err_code = _common_check_by_mode(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; + + /* Check and get address */ + err_code = _common_check_by_mode(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){ + /* [Transmit Fault (Tx_Fault)] + * A catastrophic laser fault will activate the transmitter signal, + * TX_FAULT, and disable the laser. This signal is an open collector + * output (pull-up required on the host board). A low signal indicates + * normal laser operation and a high signal indicates a fault. The + * TX_FAULT will be latched high when a laser fault occurs and is + * cleared by toggling the TX_DISABLE input or power cycling the + * transceiver. The transmitter fault condition can also be monitored + * via the two-wire serial interface. + * (address A2, byte 110, bit 2). + * + * 0: Normal + * 1: Abnormal + */ + 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_get_hard_rs0(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + "common_get_hard_rs0"); +} + + +int +common_get_hard_rs1(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + "common_get_hard_rs1"); +} + + +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 +common_set_hard_rs0(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + input_val, + "common_set_hard_rs0"); +} + + +int +common_set_hard_rs1(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + input_val, + "common_set_hard_rs1"); +} + + +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; +} + + +int +fake_ioexp_init(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_ioexp_update(struct ioexp_obj_s *self){ + return 1; +} + + +int +fake_update_func(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_get_func(struct ioexp_obj_s *self, + int virt_offset){ + SWPS_WARN("Someone called fake_get_func\n"); + return -1; +} + +int +fake_set_func(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + SWPS_WARN("Someone called fake_set_func\n"); + return -1; +} + + +/* ========== 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; + + /* 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; + } + } + } + /* 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; + + case IOEXP_MODE_POLLING: + /* Check system and channel is ready */ + if (self->state == STATE_IOEXP_INIT){ + if (!_is_channel_ready(self)){ + self->state = STATE_IOEXP_INIT; + SWPS_WARN("%s: IOEXP:%d channel not ready.\n", + __func__, self->ioexp_id); + return 0; + } + } + /* Execute initial callback */ + 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; +} + + +int +common_ioexp_fsm_4_polling(struct ioexp_obj_s *self){ + + int result_val, i, show_e; + int fail_retry = 3; + char *func_name = "common_ioexp_fsm_4_polling"; + +#ifdef DEBUG_SWPS + show_e = 1; +#else + show_e = 0; +#endif + + 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; + } + /* Case: System (Channel) not ready */ + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, wait and retry */ + return 0; + } + /* Case: Initial done */ + SWPS_INFO("IOEXP-%d: initial done. :%d\n", + self->ioexp_id, self->ioexp_type); + return result_val; + + case STATE_IOEXP_NORMAL: + /* Retry mechanism for case of i2c topology not stable */ + for (i=0; iupdate_all(self, show_e, func_name); + if (result_val >= 0) { + self->state = STATE_IOEXP_NORMAL; + return 0; + } + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: detect I2C crash :%d\n", + __func__, self->ioexp_id); + break; + } + SWPS_DEBUG("IOEXP-%d: unstable :%d\n", + self->ioexp_id, result_val); + } + SWPS_INFO("IOEXP-%d: NORMAL -> ABNORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_e, func_name); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_INFO("IOEXP-%d: ABNORMAL -> NORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("IOEXP-%d: Exception occurs :%d\n", + self->ioexp_id, self->state); + return ERR_IOEXP_UNEXCPT; +} + + +/* ========== Object private functions for check & update ========== + */ +int +common_ioexp_check(struct ioexp_obj_s *self){ + + int result; + + if (self->mode != IOEXP_MODE_POLLING){ + SWPS_ERR("%s: not polling mode :%d\n", + __func__, self->mode); + return ERR_IOEXP_NOTSUPPORT; + } + mutex_lock(&self->lock); + result = self->fsm_4_polling(self); + mutex_unlock(&self->lock); + return result; +} + + +/* ========== Functions for Factory pattern ========== + */ +static struct ioexp_map_s * +get_ioexp_map(int ioexp_type){ + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + return &ioexp_map_magnolia_nab; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + return &ioexp_map_magnolia_7ab; + case IOEXP_TYPE_REDWOOD_P01P08: + return &ioexp_map_redwood_p01p08_p17p24; + case IOEXP_TYPE_REDWOOD_P09P16: + return &ioexp_map_redwood_p09p16_p25p32; + case IOEXP_TYPE_HUDSON32IGA_P01P08: + return &ioexp_map_hudson32iga_p01p08_p17p24; + case IOEXP_TYPE_HUDSON32IGA_P09P16: + return &ioexp_map_hudson32iga_p09p16_p25p32; + case IOEXP_TYPE_CYPRESS_NABC: + return &ioexp_map_cypress_nabc; + case IOEXP_TYPE_CYPRESS_7ABC: + return &ioexp_map_cypress_7abc; + case IOEXP_TYPE_TAHOE_5A: + return &ioexp_map_tahoe_5a; + case IOEXP_TYPE_TAHOE_6ABC: + return &ioexp_map_tahoe_6abc; + case IOEXP_TYPE_SEQUOIA_NABC: + return &ioexp_map_sequoia_nabc; + 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_POLLING: /* Direct access device mode */ + case IOEXP_MODE_DIRECT: /* Polling mode, read from cache */ + 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_MAGINOLIA_NAB: + 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->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = 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; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + return 0; + 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->get_hard_rs0 = common_get_hard_rs0; + self->get_hard_rs1 = common_get_hard_rs1; + 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; + self->set_hard_rs0 = common_set_hard_rs0; + self->set_hard_rs1 = common_set_hard_rs1; + return 0; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + 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->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = ioexp_get_not_support; + 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; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + 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_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_NABC: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + self->init = common_ioexp_init; + self->check = common_ioexp_check; + self->update_all = common_ioexp_update_all; + self->fsm_4_direct = common_ioexp_fsm_4_direct; + self->fsm_4_polling = common_ioexp_fsm_4_polling; + 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__); +} + + +int +check_ioexp_objs(void){ + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while (ioexp_curr_p){ + if ( (ioexp_curr_p->check(ioexp_curr_p)) < 0){ + SWPS_INFO("check IOEXP-%d fail! :%d\n", + ioexp_curr_p->ioexp_id, ioexp_curr_p->ioexp_type); + return -1; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} + + +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; +} + + +void +unlock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_unlock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } +} + + +int +lock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_lock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} + + +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} + + +static int +_scan_channel_tier_1(int force, + int show_err) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + int ready = 0; + + if (!ioexp_curr_p) { + goto err_scan_tier_1_channel; + } + while(ioexp_curr_p) { + ready = _is_channel_ready(ioexp_curr_p); + if ((!ready) && (!force)) { + goto err_scan_tier_1_channel; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; + +err_scan_tier_1_channel: + if (show_err) { + if (ioexp_curr_p) { + SWPS_INFO("%s: IOEXP-%d fail\n", __func__, ioexp_curr_p->ioexp_id); + } else { + SWPS_INFO("%s: IOEXP is null.\n", __func__); + } + } + return -1; +} + + +static int +_scan_channel_tier_1_single(void) { + + int ret = 0; + int chan_id = 0; + int fake_cid = 0; + int fake_offs = 0; + int fake_addr = 0; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + + if (ioexp_head_p->ioexp_id != ioexp_tail_p->ioexp_id) { + return 0; + } + /* Setup i2c_client */ + chan_id = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chan_id; + fake_addr = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chip_addr; + adap = i2c_get_adapter((chan_id + 1)); + if(!adap){ + SWPS_INFO("%s: Can not get adap!\n", __func__); + return 0; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + SWPS_INFO("%s: Can not kzalloc client!\n", __func__); + return 0; + } + client->adapter = adap; + client->addr = fake_addr; + /* Fouce move ioexp ptr to next */ + ret = i2c_smbus_read_byte_data(client, fake_offs); + SWPS_DEBUG("%s: move ioexp_ptr done. :%d\n", __func__, ret); + kfree(client); + return 1; +} + + +int +resync_channel_tier_1(void) { + + char *emsg = "ERR"; + + if (!ioexp_head_p) { + emsg = "ioexp_head_p is NULL"; + goto err_resync_ioexp_status_1; + } + /* Run all */ + if (ioexp_head_p->ioexp_id == ioexp_tail_p->ioexp_id) { + _scan_channel_tier_1_single(); + } else { + _scan_channel_tier_1(1, 0); + } + /* Check all */ + if (_scan_channel_tier_1(0, 1) < 0) { + emsg = "resync tier-1 channel fail"; + goto err_resync_ioexp_status_1; + } + return 0; + +err_resync_ioexp_status_1: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.h new file mode 100644 index 000000000000..4e39fcefa620 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.h @@ -0,0 +1,173 @@ +#ifndef IO_EXPANDER_H +#define IO_EXPANDER_H + +#include + + +/* IOEXP type define (SFP series) */ +#define IOEXP_TYPE_MAGINOLIA_NAB (10101) +#define IOEXP_TYPE_CYPRESS_NABC (10102) + +/* IOEXP type define (QSFP series) */ +#define IOEXP_TYPE_MAGINOLIA_7AB (10201) +#define IOEXP_TYPE_REDWOOD_P01P08 (10202) +#define IOEXP_TYPE_REDWOOD_P09P16 (10203) +#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204) +#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205) +#define IOEXP_TYPE_SPRUCE_7AB (10206) +#define IOEXP_TYPE_CYPRESS_7ABC (10207) +#define IOEXP_TYPE_TAHOE_5A (10208) +#define IOEXP_TYPE_TAHOE_6ABC (10209) +#define IOEXP_TYPE_SEQUOIA_NABC (10210) + +/* IOEXP mode define */ +#define IOEXP_MODE_POLLING (19000) +#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_ABNORMAL (-103) +#define ERR_IOEXP_NOSTATE (-104) +#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[10]; /* IOEXP for SFP / QSFP */ + struct ioexp_bitmap_s map_tx_disable[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_tx_fault[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_rxlos[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_reset[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_lpmod[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_modsel[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs0[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs1[10]; /* 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 (*get_hard_rs0)(struct ioexp_obj_s *self, int virt_offset); + int (*get_hard_rs1)(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); + int (*set_hard_rs0)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_hard_rs1)(struct ioexp_obj_s *self, int virt_offset, int input_val); + + /* =========================================== + * Object private functions + * =========================================== + */ + int (*init)(struct ioexp_obj_s *self); + int (*check)(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); + int (*fsm_4_polling)(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); +int check_ioexp_objs(void); +void clean_ioexp_objs(void); + +void unlock_ioexp_all(void); +int lock_ioexp_all(void); + +int check_channel_tier_1(void); +int resync_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/d7264q28b/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.c new file mode 100644 index 000000000000..0bbd78935433 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.c @@ -0,0 +1,8212 @@ +#include +#include +#include +#include +#include "io_expander.h" +#include "transceiver.h" + + +/* ========== Register EEPROM address mapping ========== + */ +struct eeprom_map_s eeprom_map_sfp = { + .addr_br =0x50, .page_br =-1, .offset_br =12, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =94, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =-1, .offset_connector =2, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =-1, .offset_diag_type =92 , .length_diag_type =1, + .addr_extbr =-1, .page_extbr =-1, .offset_extbr =-1, .length_extbr =-1, + .addr_ext_id =0x50, .page_ext_id =-1, .offset_ext_id =1, .length_ext_id =1, + .addr_id =0x50, .page_id =-1, .offset_id =0, .length_id =1, + .addr_len_sm =0x50, .page_len_sm =-1, .offset_len_sm =15, .length_len_sm =1, + .addr_len_smf =0x50, .page_len_smf =-1, .offset_len_smf =14, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =-1, .offset_len_om1 =17, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =-1, .offset_len_om2 =16, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =-1, .offset_len_om3 =19, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =-1, .offset_len_om4 =18, .length_len_om4 =1, + .addr_option =0x50, .page_option =-1, .offset_option =64, .length_option =2, + .addr_rate_id =0x50, .page_rate_id =-1, .offset_rate_id =13, .length_rate_id =1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =0x51, .page_rx_em =-1, .offset_rx_em =115, .length_rx_em =1, + .addr_rx_los =-1, .page_rx_los =-1, .offset_rx_los =-1, .length_rx_los =-1, + .addr_rx_power =0x51, .page_rx_power =-1, .offset_rx_power =104, .length_rx_power =2, + .addr_soft_rs0 =0x51, .page_soft_rs0 =-1, .offset_soft_rs0 =110, .length_soft_rs0 =1, + .addr_soft_rs1 =0x51, .page_soft_rs1 =-1, .offset_soft_rs1 =118, .length_soft_rs0 =1, + .addr_temp =0x51, .page_temp =-1, .offset_temp =96, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =-1, .offset_trancomp =3, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =-1, .offset_trancomp_ext =36, .length_trancomp_ext =1, + .addr_tx_bias =0x51, .page_tx_bias =-1, .offset_tx_bias =100, .length_tx_bias =2, + .addr_tx_disable =-1, .page_tx_disable =-1, .offset_tx_disable =-1, .length_tx_disable =-1, + .addr_tx_eq =0x51, .page_tx_eq =-1, .offset_tx_eq =114, .length_tx_eq =1, + .addr_tx_fault =-1, .page_tx_fault =-1, .offset_tx_fault =-1, .length_tx_fault =-1, + .addr_tx_power =0x51, .page_tx_power =-1, .offset_tx_power =102, .length_tx_power =2, + .addr_vendor_name =0x50, .page_vendor_name =-1, .offset_vendor_name =20, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =-1, .offset_vendor_pn =40, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =-1, .offset_vendor_rev =56, .length_vendor_rev =4, + .addr_vendor_sn =0x50, .page_vendor_sn =-1, .offset_vendor_sn =68, .length_vendor_sn =16, + .addr_voltage =0x51, .page_voltage =-1, .offset_voltage =98, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =-1, .offset_wavelength =60, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =-1, .page_rx_em =-1, .offset_rx_em =-1, .length_rx_em =-1, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =-1, .page_tx_eq =-1, .offset_tx_eq =-1, .length_tx_eq =-1, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp28 = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =0x50, .page_cdr =-1, .offset_cdr =98, .length_cdr =1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =0x50, .page_rx_am =3, .offset_rx_am =238, .length_rx_am =2, + .addr_rx_em =0x50, .page_rx_em =3, .offset_rx_em =236, .length_rx_em =2, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =0x50, .page_tx_eq =3, .offset_tx_eq =234, .length_tx_eq =2, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + + +/* ========== Utility Functions ========== + */ +static int +get_bit(uint8_t origin_byte, int bit_shift) { + return (int)((origin_byte >> bit_shift) & 0x1); +} + +static int +transform_word_to_int(uint8_t hight_byte, + uint8_t low_byte) { + return ((((int)hight_byte) << 8) + (int)low_byte); +} + +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 +_is_transvr_support_ctle(struct transvr_obj_s *self); + +static int +_transvr_init_handler(struct transvr_obj_s *self); + +int +_transvr_clean_handler(struct transvr_obj_s *self); + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self); + + +void +lock_transvr_obj(struct transvr_obj_s *self) { + + mutex_lock(&self->lock); + self->curr_page = VAL_TRANSVR_PAGE_FREE; +} + + +void +unlock_transvr_obj(struct transvr_obj_s *self) { + + self->curr_page = VAL_TRANSVR_PAGE_FREE; + mutex_unlock(&self->lock); +} + + +static int +_check_by_mode(struct transvr_obj_s *self, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + char *caller_name){ + + int return_val = ERR_TRANSVR_UNEXCPT; + + switch (self->mode){ + case TRANSVR_MODE_POLLING: + switch (self->state){ + case STATE_TRANSVR_CONNECTED: + goto ok_check_by_mode_1; + case STATE_TRANSVR_NEW: + case STATE_TRANSVR_INIT: + return ERR_TRANSVR_UNINIT; + case STATE_TRANSVR_DISCONNECTED: + return ERR_TRANSVR_UNPLUGGED; + case STATE_TRANSVR_UNEXCEPTED: + return ERR_TRANSVR_ABNORMAL; + case STATE_TRANSVR_ISOLATED: + return ERR_TRNASVR_BE_ISOLATED; + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + + case TRANSVR_MODE_DIRECT: + return_val = self->fsm_4_direct(self, caller_name); + if (return_val < 0){ + return return_val; + } + goto ok_check_by_mode_1; + + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + +ok_check_by_mode_1: + return attr_update_func(self, 0); + +err_check_by_mode_1: + SWPS_INFO("_check_by_mode: mode:%d state:%d\n", self->mode, self->state); + return ERR_TRANSVR_UNEXCPT; +} + + +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; +} + +/* +static int +_common_setup_password(struct transvr_obj_s *self, + int addr, + int page, + int offs, + uint8_t pwd[4], + int show_e) { + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, 4, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_setup_password; + } + for (i=0; i<4; i++) { + err = i2c_smbus_write_byte_data(self->i2c_client_p, + (offs + i), + pwd[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_setup_password; + } + } + return 0; + +err_common_setup_password: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} +*/ + +static int +_common_update_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + uint8_t *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_uint8_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_uint8_attr; + } + buf[i] = err; + } + return 0; + +err_common_update_uint8_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_int_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_int_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_int_attr; + } + buf[i] = (int)err; + } + return 0; + +err_common_update_int_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_INT_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_string_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + char buf[], + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_string_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_string_attr; + } + buf[i] = (char)err; + } + return 0; + +err_common_update_string_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = 'e'; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + uint8_t update, + uint8_t *buf, + char *caller, + int show_e){ + int len = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + if ((*buf) == update){ + return 0; + } + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + err = i2c_smbus_write_byte_data(self->i2c_client_p, + offset, + update); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + (*buf) = update; + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_array(struct transvr_obj_s *self, + int addr, + int page, + int offs, + int len, + uint8_t update[], + uint8_t buf[], + char *caller, + int show_e){ + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + for (i=0; ii2c_client_p, + (offs + i), + update[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + buf[i] = update[i]; + } + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, emsg, caller, err, i); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_attr_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_id, + self->eeprom_map_p->page_id, + self->eeprom_map_p->offset_id, + self->eeprom_map_p->length_id, + &(self->id), + "_common_update_attr_id", + show_err); +} + + +static int +_common_update_attr_extended_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_ext_id, + self->eeprom_map_p->page_ext_id, + self->eeprom_map_p->offset_ext_id, + self->eeprom_map_p->length_ext_id, + &(self->ext_id), + "_common_update_attr_extended_id", + show_err); +} + + +static int +_common_update_attr_connector(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_connector, + self->eeprom_map_p->page_connector, + self->eeprom_map_p->offset_connector, + self->eeprom_map_p->length_connector, + &(self->connector), + "_common_update_attr_connector", + show_err); +} + + +static int +_common_update_attr_transvr_comp(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp, + self->eeprom_map_p->page_trancomp, + self->eeprom_map_p->offset_trancomp, + self->eeprom_map_p->length_trancomp, + self->transvr_comp, + "_common_update_attr_transvr_comp", + show_err); +} + + +static int +_common_update_attr_transvr_comp_ext(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp_ext, + self->eeprom_map_p->page_trancomp_ext, + self->eeprom_map_p->offset_trancomp_ext, + self->eeprom_map_p->length_trancomp_ext, + &(self->transvr_comp_ext), + "_common_update_attr_transvr_comp_ext", + show_err); +} + + +static int +_common_update_attr_vendor_name(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_name, + self->eeprom_map_p->page_vendor_name, + self->eeprom_map_p->offset_vendor_name, + self->eeprom_map_p->length_vendor_name, + self->vendor_name, + "_common_update_attr_vendor_name", + show_err); +} + + +static int +_common_update_attr_vendor_pn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_pn, + self->eeprom_map_p->page_vendor_pn, + self->eeprom_map_p->offset_vendor_pn, + self->eeprom_map_p->length_vendor_pn, + self->vendor_pn, + "_common_update_attr_vendor_pn", + show_err); +} + + +static int +_common_update_attr_vendor_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_rev, + self->eeprom_map_p->page_vendor_rev, + self->eeprom_map_p->offset_vendor_rev, + self->eeprom_map_p->length_vendor_rev, + self->vendor_rev, + "_common_update_attr_vendor_rev", + show_err); +} + + +static int +_common_update_attr_vendor_sn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_sn, + self->eeprom_map_p->page_vendor_sn, + self->eeprom_map_p->offset_vendor_sn, + self->eeprom_map_p->length_vendor_sn, + self->vendor_sn, + "_common_update_attr_vendor_sn", + show_err); +} + + +static int +_common_update_attr_br(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_br, + self->eeprom_map_p->page_br, + self->eeprom_map_p->offset_br, + self->eeprom_map_p->length_br, + &(self->br), + "_common_update_attr_br", + show_err); +} + + +static int +_common_update_attr_len_smf(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_smf, + self->eeprom_map_p->page_len_smf, + self->eeprom_map_p->offset_len_smf, + self->eeprom_map_p->length_len_smf, + &(self->len_smf), + "_common_update_attr_len_smf", + show_err); +} + + +static int +_common_update_attr_len_om1(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om1, + self->eeprom_map_p->page_len_om1, + self->eeprom_map_p->offset_len_om1, + self->eeprom_map_p->length_len_om1, + &(self->len_om1), + "_common_update_attr_len_om1", + show_err); +} + +static int +_common_update_attr_len_om2(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om2, + self->eeprom_map_p->page_len_om2, + self->eeprom_map_p->offset_len_om2, + self->eeprom_map_p->length_len_om2, + &(self->len_om2), + "_common_update_attr_len_om2", + show_err); +} + +static int +_common_update_attr_len_om3(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om3, + self->eeprom_map_p->page_len_om3, + self->eeprom_map_p->offset_len_om3, + self->eeprom_map_p->length_len_om3, + &(self->len_om3), + "_common_update_attr_len_om3", + show_err); +} + + +static int +_common_update_attr_len_om4(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om4, + self->eeprom_map_p->page_len_om4, + self->eeprom_map_p->offset_len_om4, + self->eeprom_map_p->length_len_om4, + &(self->len_om4), + "_common_update_attr_len_om4", + show_err); +} + + +static int +_common_update_attr_option(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_option, + self->eeprom_map_p->page_option, + self->eeprom_map_p->offset_option, + self->eeprom_map_p->length_option, + self->option, + "_common_update_attr_option", + show_err); +} + + +static int +_common_update_attr_comp_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_comp_rev, + self->eeprom_map_p->page_comp_rev, + self->eeprom_map_p->offset_comp_rev, + self->eeprom_map_p->length_comp_rev, + &(self->comp_rev), + "_common_update_attr_comp_rev", + show_err); +} + + +static int +_common_update_attr_diag_type(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_diag_type, + self->eeprom_map_p->page_diag_type, + self->eeprom_map_p->offset_diag_type, + self->eeprom_map_p->length_diag_type, + &(self->diag_type), + "_common_update_attr_diag_type", + show_err); +} + + +static int +_common_update_attr_wavelength(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_wavelength, + self->eeprom_map_p->page_wavelength, + self->eeprom_map_p->offset_wavelength, + self->eeprom_map_p->length_wavelength, + self->wavelength, + "_common_update_attr_wavelength", + show_err); +} + + +int +_common_get_option_value(struct transvr_obj_s *self, + int offset, + int bit_shift) { + /* SFP: + * - option[0] = A0h / 64 + * - option[1] = A0h / 65 + * QSFP: + * - option[0] = 00h / 193 + * - option[1] = 00h / 194 + * - option[2] = 00h / 195 + */ + return (self->option[offset] & (1 << bit_shift)); +} + + +static int +_sfp_update_attr_len_sm(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_sm, + self->eeprom_map_p->page_len_sm, + self->eeprom_map_p->offset_len_sm, + self->eeprom_map_p->length_len_sm, + &(self->len_sm), + "_common_update_attr_len_sm", + show_err); +} + + +static int +_sfp_update_attr_rate_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_rate_id, + self->eeprom_map_p->page_rate_id, + self->eeprom_map_p->offset_rate_id, + self->eeprom_map_p->length_rate_id, + &(self->rate_id), + "_sfp_update_attr_rate_id", + show_err); +} + + +static int +_sfp_update_attr_soft_rs0(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + self->eeprom_map_p->length_soft_rs0, + &(self->soft_rs0), + "_sfp_update_attr_soft_rs0", + show_err); +} + + +static int +_sfp_update_attr_soft_rs1(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + self->eeprom_map_p->length_soft_rs1, + &(self->soft_rs1), + "_sfp_update_attr_soft_rs1", + show_err); +} + + +int +_sfp_is_diag_support(struct transvr_obj_s *self){ + + uint8_t bit_mask = 0xC0; /* 1100 0000 */ + uint8_t en_val = 0x40; /* 0100 0000 */ + uint8_t checkval = (self->diag_type & bit_mask); + + if (checkval == en_val) { + return 1; + } + return 0; +} + + +static int +_sfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_sfp_update_attr_curr_temp", + show_err); +} + + +static int +_sfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_sfp_update_attr_curr_voltage", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_sfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_sfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_sfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_sfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_sfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_sfp_update_attr_rx_em", + show_err); +} + + +static int +_sfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_sfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_cdr(struct transvr_obj_s *self, + int show_err){ + if (self->type != TRANSVR_TYPE_QSFP_28){ + self->cdr = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + self->eeprom_map_p->length_cdr, + &(self->cdr), + "_common_update_attr_cdr", + show_err); +} + + +static int +_qsfg_update_attr_extbr(struct transvr_obj_s *self, + int show_err) { + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_extbr, + self->eeprom_map_p->page_extbr, + self->eeprom_map_p->offset_extbr, + self->eeprom_map_p->length_extbr, + &(self->extbr), + "_common_update_attr_extbr", + show_err); +} + + +static int +_qsfp_is_diag_support(struct transvr_obj_s *self, + int diag_type) { + /* Input Parm: diag_type + * => 1 : temperature + * => 2 : voltage + * => 3 : tx relate + * => 4 : rx relate + */ + uint8_t mask_b2 = 0x04; /* 0000 0100 */ + uint8_t mask_b3 = 0x08; /* 0000 1000 */ + + switch (diag_type) { + case 1: /* temperature */ + case 2: /* voltage */ + /* Direct access target, because of spec not defined */ + return 1; + case 3: + case 4: + /* [Note] + * Due to lot of transceiver vendor defined it not rigorously and + * consider of general support, we seem it as supported if there + * are bit-2 OR bit-3 defined by transceiver vendor. + */ + if ( ((self->diag_type & mask_b2) == mask_b2 ) || + ((self->diag_type & mask_b3) == mask_b3 ) ){ + return 1; + } + return 0; + default: + SWPS_INFO("%s: undefined diag_type:%d\n", + __func__, diag_type); + break; + } + return 0; +} + + +int +_qsfp_is_implement_tx_disable(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-4 + */ + int byte = 2; + int bit = 4; + return _common_get_option_value(self, byte, bit); +} + + +int +_qsfp_is_implement_tx_fault(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-3 + */ + int byte = 2; + int bit = 3; + return _common_get_option_value(self, byte, bit); +} + + +static int +_qsfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + int diag_type = 1; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_qsfp_update_attr_curr_temp", + show_err); +} + + +static int +_qsfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + int diag_type = 2; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_qsfp_update_attr_curr_voltage", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_qsfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_qsfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_qsfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 4; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_qsfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_qsfp_update_attr_soft_rx_los(struct transvr_obj_s *self, + int show_err){ + + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_los, + self->eeprom_map_p->page_rx_los, + self->eeprom_map_p->offset_rx_los, + self->eeprom_map_p->length_rx_los, + &(self->rx_los), + "_qsfp_update_attr_soft_rx_los", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_disable(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_disable(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_update_attr_soft_tx_disable", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_fault(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_fault(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_fault, + self->eeprom_map_p->page_tx_fault, + self->eeprom_map_p->offset_tx_fault, + self->eeprom_map_p->length_tx_fault, + &(self->tx_fault), + "_qsfp_update_attr_soft_tx_fault", + show_err); +} + + +static int +_qsfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_qsfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_rx_am(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + self->rx_am, + "_qsfp_update_attr_rx_am", + show_err); +} + + +static int +_qsfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_qsfp_update_attr_rx_em", + show_err); +} + + +int +_common_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = "err"; + + if (_common_update_attr_id(self, show_err) < 0) { + err_str = "_common_update_attr_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_extended_id(self, show_err) < 0) { + err_str = "_common_update_attr_extended_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_connector(self, show_err) < 0) { + err_str = "_common_update_attr_connector"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp_ext(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp_ext"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_name(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_name"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_pn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_pn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_rev(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_sn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_sn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_br(self, show_err) < 0) { + err_str = "_common_update_attr_br"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_smf(self, show_err) < 0) { + err_str = "_common_update_attr_len_smf"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om1(self, show_err) < 0) { + err_str = "_common_update_attr_len_om1"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om2(self, show_err) < 0) { + err_str = "_common_update_attr_len_om2"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om3(self, show_err) < 0) { + err_str = "_common_update_attr_len_om3"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om4(self, show_err) < 0) { + err_str = "_common_update_attr_len_om4"; + goto err_common_update_attr_all; + } + if (_common_update_attr_option(self, show_err) < 0) { + err_str = "_common_update_attr_option"; + goto err_common_update_attr_all; + } + if (_common_update_attr_comp_rev(self, show_err) < 0) { + err_str = "_common_update_attr_comp_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_diag_type(self, show_err) < 0) { + err_str = "_common_update_attr_diag_type"; + goto err_common_update_attr_all; + } + if (_common_update_attr_wavelength(self, show_err) < 0) { + err_str = "_common_update_attr_wavelength"; + goto err_common_update_attr_all; + } + return 0; + +err_common_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_sfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_len_sm(self, show_err) < 0) { + err_str = "_sfp_update_attr_len_sm"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_rate_id(self, show_err) < 0) { + err_str = "_sfp_update_attr_rate_id"; + goto err_sfp_update_attr_all; + } + if ((self->rate_id) > 0) { + if (_sfp_update_attr_soft_rs0(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs0"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_soft_rs1(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs1"; + goto err_sfp_update_attr_all; + } + } + return 0; + +err_sfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_qsfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_qsfp_update_attr_all; + } + if (_qsfg_update_attr_extbr(self, show_err) < 0) { + err_str = "_qsfg_update_attr_extbr"; + goto err_qsfp_update_attr_all; + } + if (self->type == TRANSVR_TYPE_QSFP_28) { + if (_qsfp_update_attr_cdr(self, 1) < 0) { + err_str = "_qsfp_update_attr_cdr"; + goto err_qsfp_update_attr_all; + } + } + return 0; + +err_qsfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +/* ========== Object functions for common type ========== + */ +int +_common_count_temp(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + int sign = 0; + int high = 0; + int low = 0; + int lmax = 8; + + /* Count high */ + sign = get_bit(high_byte,7); + SWP_BIT_CLEAR(high_byte, 7); + high = (int)high_byte; + if (sign == 1) { + high = 0 - high; + } + /* Count low */ + low = (get_bit(low_byte, 7) * 500); + low += (get_bit(low_byte, 6) * 250); + low += (get_bit(low_byte, 5) * 125); + low += (get_bit(low_byte, 4) * 62); + low = (low / 100); + /* Integrate High and Low */ + return snprintf(buf_p, lmax, "%d.%d\n", high, low); +} + + +int +_common_count_voltage(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note]: + * Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts. Practical + * considerations to be defined by transceiver manufacturer will + * tend to limit the actual bounds of the supply voltage measurement. + * Accuracy is vendor specific but must be better than 3% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. Note that in some transceivers, transmitter supply + * voltage and receiver supply voltage are isolated. In that case, + * only one supply is monitored. Refer to the device specification + * for more detail. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 100 uV (1mV=1000uV) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 Volt */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_tx_bias(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 2 uA (1mA=1000uA) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total*2) / 1000); + val_f = (((total*2) - (val_i*1000)) / 100); + /* Return Unit: 1 mA */ + return snprintf(buf_p, lmax, "%d.%01d\n", val_i, val_f); +} + + +int +_common_count_tx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_rx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_wavelength(struct transvr_obj_s *self, + uint8_t high_byte, + uint8_t low_byte) { + /* [Note] + * SFP : uint 1 um. + * QSFP: unit 0.05 um. + */ + int total = 0; + + total = transform_word_to_int(high_byte, low_byte); + switch (self->type) { + case TRANSVR_TYPE_SFP: + return total; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + return (total/20); + + default: + break; + } + return ERR_TRANSVR_UNDEFINED; +} + + +int +common_get_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_id, + "common_get_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->id; +} + + +int +common_get_ext_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "common_get_ext_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->ext_id; +} + + +int +common_get_connector(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_connector, + "common_get_connector"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->connector; +} + + +int +common_get_vendor_name(struct transvr_obj_s *self, char *buf){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_name, + "common_get_vendor_name"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); +} + + +int +common_get_vendor_pn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_pn, + "common_get_vendor_pn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); +} + + +int +common_get_vendor_rev(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_rev, + "common_get_vendor_rev"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); +} + + +int +common_get_vendor_sn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_sn, + "common_get_vendor_sn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); +} + + +int +common_get_br(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return (int)self->br; + } + err = _check_by_mode(self, + &_common_update_attr_br, + "common_get_br"); + if (err < 0){ + return err; + } + /* Transform to INT to show error case */ + return (int)self->br; +} + + +int +common_get_len_smf(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_smf; + } + err = _check_by_mode(self, + &_common_update_attr_len_smf, + "common_get_len_smf"); + if (err < 0){ + return err; + } + return self->len_smf; +} + + +int +common_get_len_om1(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om1; + } + err = _check_by_mode(self, + &_common_update_attr_len_om1, + "common_get_len_om1"); + if (err < 0){ + return err; + } + return self->len_om1; +} + + +int +common_get_len_om2(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om2; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om2, + "common_get_len_om2"); + if (err < 0){ + return err; + } + return self->len_om2; +} + + +int +common_get_len_om3(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om3; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om3, + "common_get_len_om3"); + if (err < 0){ + return err; + } + return self->len_om3; +} + + +int +common_get_len_om4(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om4; + } + err = _check_by_mode(self, + &_common_update_attr_len_om4, + "common_get_len_om4"); + if (err < 0){ + return err; + } + return self->len_om4; +} + + +int +common_get_comp_extended(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp_ext, + "common_get_comp_extended"); + if (err_code < 0){ + return err_code; + } + return self->transvr_comp_ext; +} + + +int +common_get_comp_rev(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_comp_rev, + "common_get_comp_rev"); + if (err_code < 0){ + return err_code; + } + return self->comp_rev; +} + + +int +common_get_info(struct transvr_obj_s *self){ + + if (self->state != STATE_TRANSVR_CONNECTED) { + return self->state; + } + return self->info; +} + + +int +_common_get_if_lane(struct transvr_obj_s *self, + char *result){ + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_M_STR); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + memset(tmp_str, 0, LEN_TRANSVR_M_STR); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_M_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_M_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_M_STR); + } + if (i == 0) { + return EVENT_TRANSVR_TASK_FAIL; + } + return 0; +} + + +int +common_get_if_lane(struct transvr_obj_s *self, + char *buf_p){ + + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + if (self->ioexp_obj_p->state != STATE_IOEXP_NORMAL) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n", ERR_TRANSVR_ABNORMAL); + } + if (_common_get_if_lane(self, tmp_str) < 0) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n" ,ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%s\n" ,tmp_str); +} + + +int +sfp_get_len_sm(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_len_sm, + "sfp_get_len_sm"); + if (err_code < 0){ + return err_code; + } + return self->len_sm; +} + + +int +sfp_get_rate_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_rate_id, + "sfp_get_rate_id"); + if (err_code < 0){ + return err_code; + } + return self->rate_id; +} + + +int +sfp_get_soft_rs0(struct transvr_obj_s *self){ + /* Note: + * SFP Soft Rate_Select Select [aka. "RS(0)"] address + * A2h, offset: 110, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs0, + "sfp_get_soft_rs0"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs0 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_soft_rs1(struct transvr_obj_s *self){ + /* Note: + * SFP Soft RS(1) Select address + * A2h, offset: 118, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs1, + "sfp_get_soft_rs1"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs1 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_temp, + "sfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +sfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_voltage, + "sfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +sfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_bias, + "sfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _common_count_tx_bias(self->curr_tx_bias[0], + self->curr_tx_bias[1], + buf_p); +} + + +int +sfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_power, + "sfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_tx_power(self->curr_tx_power[0], + self->curr_tx_power[1], + buf_p); +} + + +int +sfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_rx_power, + "sfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_rx_power(self->curr_rx_power[0], + self->curr_rx_power[0], + buf_p); +} + + +int +sfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->rx_em[0]); +} + + +int +sfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->tx_eq[0]); +} + + +int +_sfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: A0h / 36 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +__sfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* SFP Specification Compliance: A0h / 3-10 + * transvr_comp[0-7] = 3 - 10 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_get_comp_10g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[0] = address A0h / 3 + * + * 3 7: 10G Base-ER + * 3 6: 10GBASE-LRM + * 3 5: 10GBASE-LR + * 3 4: 10GBASE-SR + */ + int bitmask = 0xf0; /* 11110000 */ + return (__sfp_get_comp_attr(self, 0) & bitmask); +} + + +int +_sfp_get_comp_1g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[3] = address A0h / 6 + * + * 6 7: BASE-PX *3 + * 6 6: BASE-BX10 *3 + * 6 5: 100BASE-FX + * 6 4: 100BASE-LX/LX10 + * 6 3: 1000BASE-T + * 6 2: 1000BASE-CX + * 6 1: 1000BASE-LX *3 + * 6 0: 1000BASE-SX + */ + return __sfp_get_comp_attr(self, 3); +} + + +int +_sfp_get_cable_tech(struct transvr_obj_s *self) { + /* transvr_comp[5] = address A0h / 8 + * + * 8 3: Active Cable *8 + * 8 2: Passive Cable *8 + */ + int bitmask = 0x0c; /* 00001100 */ + return (__sfp_get_comp_attr(self, 5) & bitmask); +} + + +int +sfp_get_comp_eth_1(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_1"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_1g_eth_comp(self); +} + + +int +sfp_get_comp_eth_10(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_10"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_10g_eth_comp(self); +} + + +int +_sfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: A0h / 2 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Note] Optical and Cable Variants Specification Compliance (SFF-8472) + * [Addr] A0h, Bytes 60-61 + * [Note] For optical variants, as defined by having zero's in A0h Byte 8 + * bits 2 and 3, Bytes 60 and 61 denote nominal transmitter output + * wavelength at room temperature. 16 bit value with byte 60 as high + * order byte and byte 61 as low order byte. The laser wavelength is + * equal to the 16 bit integer value in nm. This field allows the user + * to read the laser wavelength directly, so it is not necessary to + * infer it from the Transceiver Codes A0h Bytes 3 to 10 (see Table + * 5-3). This also allows specification of wavelengths not covered + * in the Transceiver Codes, such as those used in coarse WDM systems. + * + * For passive and active cable variants, a value of 00h for both A0h + * Byte 60 and Byte 61 denotes laser wavelength or cable specification + * compliance is unspecified. + */ + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +int +__qsfp_get_power_cls(struct transvr_obj_s *self, + int direct_access){ + + int err_code; + uint8_t detect_val; + + /* Detect and Update power class attribute */ + if (direct_access){ + err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_power_cls"); + } else { + err_code = self->ext_id; + } + if (err_code <0){ + return err_code; + } + if (err_code == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data */ + detect_val = self->ext_id; + SWP_BIT_CLEAR(detect_val, 2); /* Bit2: CDR RX present */ + SWP_BIT_CLEAR(detect_val, 3); /* Bit3: CDR TX present */ + SWP_BIT_CLEAR(detect_val, 4); /* Bit4: CLEI present */ + SWP_BIT_CLEAR(detect_val, 5); /* Bit5: reserved */ + /* Identify power class */ + switch (detect_val) { + case 0: /* Class_1: 00000000 */ + return 1; + case 64: /* Class_2: 01000000 */ + return 2; + case 128: /* Class_3: 10000000 */ + return 3; + case 192: /* Class_4: 11000000 */ + return 4; + case 1: /* Class_5: 00000001 */ + case 193: /* Class_5: 11000001 */ + return 5; + case 2: /* Class_6: 00000010 */ + case 194: /* Class_6: 11000010 */ + return 6; + case 3: /* Class_7: 00000011 */ + case 195: /* Class_7: 11000011 */ + return 7; + default: + break; + } + SWPS_INFO("%s: Detect undefined power class:%d\n", __func__, detect_val); + return ERR_TRANSVR_UNDEFINED; +} + + +int +qsfp_get_power_cls(struct transvr_obj_s *self) { + return __qsfp_get_power_cls(self, 1); +} + + +int +__qsfp_get_cdr_present(struct transvr_obj_s *self, + int direct_access){ + + int retval; + int BIT_SHIFT = 2; + int BIT_MASK = 0x3; + + /* Detect and Update power class attribute */ + if (direct_access) { + retval = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_cdr_present"); + if (retval < 0){ + return retval; + } + } + retval = self->ext_id; + if (retval == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data and return */ + return (int)(retval >> BIT_SHIFT & BIT_MASK); +} + + +int +qsfp_get_cdr_present(struct transvr_obj_s *self) { + return __qsfp_get_cdr_present(self, 1); +} + + +int +qsfp_get_cdr(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + "qsfp_get_cdr"); + if (err_code <0){ + return err_code; + } + + return self->cdr; +} + + +int +__qsfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* QSFP Specification Compliance: 00h / 131-138 + * transvr_comp[0-7] = 131 - 138 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_get_comp_10_40_100_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[0] = address 00h / 131 + * + * 131 7: Extended: See section 6.3.23. The Extended Specification Compliance + * Codes are maintained in the Transceiver Management section of SFF- + * 8024. + * 131 6: 10GBASE-LRM + * 131 5: 10GBASE-LR + * 131 4: 10GBASE-SR + * 131 3: 40GBASE-CR4 + * 131 2: 40GBASE-SR4 + * 131 1: 40GBASE-LR4 + * 131 0: 40G Active Cable (XLPPI) + */ + return __qsfp_get_comp_attr(self, 0); +} + + +int +_qsfp_get_comp_sonet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 132 7-3: Reserved + * 132 2: OC 48, long reach + * 132 1: OC 48, intermediate reach + * 132 0: OC 48 short reach + */ + return __qsfp_get_comp_attr(self, 1); +} + + +int +_qsfp_get_comp_sas_sata(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 133 7: SAS 24.0 Gb/s + * 133 6: SAS 12.0 Gb/s + * 133 5: SAS 6.0 Gb/s + * 133 4: SAS 3.0 Gb/s + * 133 3-0: Reserved + */ + return __qsfp_get_comp_attr(self, 2); +} + + +int +_qsfp_get_comp_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 134 7-4: Reserved + * 134 3: 1000BASE-T + * 134 2: 1000BASE-CX + * 134 1: 1000BASE-LX + * 134 0: 1000BASE-SX + */ + return __qsfp_get_comp_attr(self, 3); +} + + +int +_qsfp_get_comp_fc_link_length(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 7: Very long distance (V) + * 135 6: Short distance (S) + * 135 5: Intermediate distance (I) + * 135 4: Long distance (L) + * 135 3: Medium (M) + */ + int mask = 0xFC; /* 11111100 */ + return (__qsfp_get_comp_attr(self, 4) & mask); +} + + +int +_qsfp_get_comp_fc_trans_tech(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 2: Reserved + * 135 1: Longwave laser (LC) + * 135 0: Electrical inter-enclosure (EL) + * + * 136 7: Electrical intra-enclosure + * 136 6: Shortwave laser w/o OFC (SN) + * 136 5: Shortwave laser w OFC (SL) + * 136 4: Longwave Laser (LL) + * 136 3-0: Reserved + * + * return value = [bit 8-15:addr 135][bit 0-7:addr 136] + */ + int mask_135 = 7; /* 00000111 */ + int val_135 = (__qsfp_get_comp_attr(self, 4) & mask_135); + int val_136 = __qsfp_get_comp_attr(self, 5); + return ((val_135 << 7) + val_136); +} + + +int +_qsfp_get_comp_fc_trans_media(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 137 7: Twin Axial Pair (TW) + * 137 6: Shielded Twisted Pair (TP) + * 137 5: Miniature Coax (MI) + * 137 4: Video Coax (TV) + * 137 3: Multi-mode 62.5 m (M6) + * 137 2: Multi-mode 50 m (M5) + * 137 1: Multi-mode 50 um (OM3) + * 137 0: Single Mode (SM) + */ + return __qsfp_get_comp_attr(self, 6); +} + + +int +_qsfp_get_comp_fc_speed(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 138 7: 1200 MBps (per channel) + * 138 6: 800 MBps + * 138 5: 1600 MBps (per channel) + * 138 4: 400 MBps + * 138 3: 3200 MBps (per channel) + * 138 2: 200 MBps + * 138 1: Extended: See section 6.3.23. The Extended Specification + * Compliance Codes are maintained in the Transceiver Management + * section of SFF-8024. + * 138 0: 100 MBps + */ + return __qsfp_get_comp_attr(self, 7); +} + + +int +_qsfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: 00h / 192 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_comp_eth(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_eth"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_ethernet(self); +} + + +int +qsfp_get_comp_10_40(struct transvr_obj_s *self) { + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_10_40"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_10_40_100_ethernet(self); +} + + +int +_qsfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: 00h / 130 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_temp, + "qsfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +qsfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_voltage, + "qsfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +qsfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->tx_eq[0], self->tx_eq[1]); +} + + +int +qsfp_get_transvr_rx_am(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_get_transvr_rx_am"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_am[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_am[0], self->rx_am[1]); +} + + +int +qsfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_em[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_em[0], self->rx_em[1]); +} + + +int +_qsfp_get_channel_diag(uint8_t *data_array, + int (*count_func)(uint8_t high_byte, uint8_t low_byte, char *buf_p), + char *ch_name, + char *result_p) { + int i, high, low; + int len_max = 128; + char ch_buf[4][16] = { DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL }; + + for (i=0; i<4; i++) { + high = (i*2); + low = ((i*2) + 1); + count_func(data_array[high], data_array[low], ch_buf[i]); + } + return snprintf(result_p, len_max, + "%s-%d:%s%s-%d:%s%s-%d:%s%s-%d:%s", + ch_name, 1, ch_buf[0], + ch_name, 2, ch_buf[1], + ch_name, 3, ch_buf[2], + ch_name, 4, ch_buf[3]); +} + + +int +qsfp_get_soft_rx_los(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_rx_los, + "qsfp_get_soft_rx_los"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->rx_los & mask)); +} + + +int +qsfp_get_soft_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_get_soft_tx_disable"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_disable & mask)); +} + + +int +qsfp_get_soft_tx_fault(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_fault, + "qsfp_get_soft_tx_fault"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_fault & mask)); +} + + +int +qsfp_get_auto_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + if (self->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "%d\n", ERR_TRANSVR_FUNC_DISABLE); + } + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "0x%02x\n", self->auto_tx_disable); +} + + +int +qsfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_bias, + "qsfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _qsfp_get_channel_diag(self->curr_tx_bias, + _common_count_tx_bias, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_power, + "qsfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_tx_power, + _common_count_tx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "RX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_rx_power, + "qsfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_rx_power, + _common_count_rx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Desc] Wavelength or Copper Cable Attenuation (SFF-8636) + * [Addr] 00h 186-187 + * [Note] + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is + * a 16-bit hex value with Byte 186 as high order byte and Byte 187 as + * low order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. + * If the free side device is identified as copper cable these registers will + * be used to define the cable attenuation. An indication of 0 dB attenuation + * refers to the case where the attenuation is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +/* Public Function for Setup Features + */ +static int +__sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + uint8_t update_val = (*attr_p); + + switch (input_val) { + case 0: + SWP_BIT_CLEAR(update_val, bit_shift); + break; + case 1: + SWP_BIT_SET(update_val, bit_shift); + break; + default: + retval = ERR_TRANSVR_UNEXCPT; + err_code = ERR_TRANSVR_UNEXCPT; + err_msg = "Exception occurs"; + goto err_private_sfp_set_soft_rs_1; + } + err_code = _common_set_uint8_attr(self, + address, + page, + offset, + update_val, + attr_p, + caller, + show_err); + if (err_code < 0) { + retval = err_code; + err_msg = "Write data via i2c fail!"; + goto err_private_sfp_set_soft_rs_1; + } + (*attr_p) = update_val; + return 0; + +err_private_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +static int +_sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + /* Check input value */ + if ((input_val != 0) && (input_val != 1)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + switch (err_code) { + case 0: + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "Not support this feature"; + break; + case ERR_TRANSVR_UNINIT: + retval = ERR_TRANSVR_UNINIT; + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + retval = ERR_TRANSVR_UNPLUGGED; + err_msg = "Transceiver unplugged!"; + break; + default: + retval = err_code; + err_msg = "Check Rate_ID fail!"; + break; + } + goto err_common_sfp_set_soft_rs_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + attr_update_func, + caller); + if ( (err_code < 0) || + ((*attr_p) == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Generate and update value */ + return __sfp_set_soft_rs(self, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + +err_common_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +sfp_set_soft_rs0(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(0)"] address + * A2h, offset: 110, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + bit_shift, + &_sfp_update_attr_soft_rs0, + &(self->soft_rs0), + "sfp_set_soft_rs0", + show_err); +} + + +int +sfp_set_soft_rs1(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(1)"] address + * A2h, offset: 118, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + bit_shift, + &_sfp_update_attr_soft_rs1, + &(self->soft_rs1), + "sfp_set_soft_rs1", + show_err); +} + + +int +__sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_tx_eq; + } + setv = (uint8_t)input; + if (self->tx_eq[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + setv, + &(self->tx_eq[0]), + "_sfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_tx_eq; + } + return 0; + +err_sfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; itx_eq[0]; + if (_sfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if (self->tx_eq[0] == tmp){ + return 0; + } + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +sfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_tx_eq(self, input, 1); +} + + +int +__sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_rx_em; + } + setv = (uint8_t)input; + if (self->rx_em[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + setv, + &(self->rx_em[0]), + "_sfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_rx_em; + } + return 0; + +err_sfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; irx_em[0]; + if (_sfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if (self->rx_em[0] == tmp){ + return 0; + } + } + return -1; +} + + +int +sfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_rx_em(self, input, 1); +} + + +static int +__qsfp_set_cdr(struct transvr_obj_s *self, + int input_val, + int show_err) { + + uint8_t update_val; + int CDR_FEATURE_SUPPORTED = 0x3; + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_name = "__qsfp_set_cdr"; + + /* Check input value */ + if ((input_val < 0) || (input_val > 0xff)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_qsfp_set_cdr_1; + } + update_val = (uint8_t)input_val; + /* Check CDR supported by transceiver */ + err_code = qsfp_get_cdr_present(self); + if (err_code < 0) { + retval = err_code; + switch (err_code) { + case ERR_TRANSVR_UNINIT: + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + err_msg = "Transceiver unplugged!"; + break; + default: + err_msg = "Check CDR present fail!"; + break; + } + goto err_qsfp_set_cdr_1; + } + if (err_code != CDR_FEATURE_SUPPORTED) { + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "This transceiver not support CDR!"; + goto err_qsfp_set_cdr_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + func_name); + if ( (err_code < 0) || + (self->cdr == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_qsfp_set_cdr_1; + } + /* Write input value to transceiver */ + return _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + update_val, + &(self->cdr), + func_name, + show_err); + +err_qsfp_set_cdr_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +qsfp_set_cdr(struct transvr_obj_s *self, + int input_val) { + return __qsfp_set_cdr(self, input_val, 1); +} + + +int +qsfp_set_soft_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int show_err = 1; + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + int update_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_soft_tx_disable"); + if (retval < 0) { + snprintf(err_msg, 63, "Not ready. err:%d", retval); + goto err_qsfp_set_soft_tx_disable; + } + if ((input_val > in_max) || + (input_val < in_min) ){ + retval = ERR_TRANSVR_BADINPUT; + snprintf(err_msg, 63, "Input value:%d incorrect!", input_val); + goto err_qsfp_set_soft_tx_disable; + } + if ((self->tx_disable & 0x0f) == input_val) { + return 0; + } + update_val = ((self->tx_disable & 0xf0) & input_val); + retval = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + input_val, + &(self->tx_disable), + "qsfp_set_tx_disable", + show_err); + if (retval < 0) { + snprintf(err_msg, 63, "_common_set_uint8_attr:%d fail!", retval); + goto err_qsfp_set_soft_tx_disable; + } + return 0; + +err_qsfp_set_soft_tx_disable: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return retval; +} + + +int +_qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + uint8_t update) { + + uint8_t tx_enable = 0x0; + int show_e = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Handle timing issues */ + if (update != tx_enable) { + /* Note: + * Because there are some txvr has timing issues, + * therefore we need to execute reset cycle first. + * (enable -> other settings) + */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + tx_enable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set reset value fail"; + goto err_qsfp_set_auto_tx_disable; + } + mdelay(10); + } + /* Setup target value */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->auto_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set target value fail"; + goto err_qsfp_set_auto_tx_disable; + } + /* Check and update */ + err = _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C get value fail"; + goto err_qsfp_set_auto_tx_disable; + } + if (self->tx_disable != update) { + emsg = "data not become effective"; + goto err_qsfp_set_auto_tx_disable; + } + return 0; + +err_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s\n", + __func__, emsg, self->swp_name); + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Update settings*/ + if (input_val == VAL_TRANSVR_FUNCTION_DISABLE) { + emsg = "User disable auto tx_disable"; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + goto out_qsfp_set_auto_tx_disable; + } + if ((input_val > in_max) || (input_val < in_min) ){ + SWPS_INFO("%s: Input value:%d incorrect! :%s\n", + __func__, input_val, self->swp_name); + return ERR_TRANSVR_BADINPUT; + } + self->auto_tx_disable = input_val; + /* Check current soft tx_disable */ + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_auto_tx_disable"); + switch (retval) { + case 0: + break; + case ERR_TRANSVR_UNPLUGGED: + emsg = "Doesn't need to update"; + goto out_qsfp_set_auto_tx_disable; + default: + SWPS_INFO("%s: setup fail :%d :%s\n", + __func__, retval, self->swp_name); + return retval; + } + return _qsfp_set_auto_tx_disable(self, input_val); + +out_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s :%d\n :%d", + __func__, emsg, self->swp_name, input_val, retval); + return 0; +} + + +int +__qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_tx_eq; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->tx_eq[0] == setv[0]) && + (self->tx_eq[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + setv, + self->tx_eq, + "_qsfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_tx_eq; + } + return 0; + +err_qsfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; itx_eq[0]; + tmp[1] = self->tx_eq[1]; + if (_qsfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if ((self->tx_eq[0] == tmp[0]) && + (self->tx_eq[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_tx_eq(self, input, 1); +} + + +int +__qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_am; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_am[0] == setv[0]) && + (self->rx_am[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + setv, + self->rx_am, + "_qsfp_set_rx_am", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_am; + } + return 0; + +err_qsfp_set_rx_am: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_am[0]; + tmp[1] = self->rx_am[1]; + if (_qsfp_update_attr_rx_am(self, show_e) < 0){ + continue; + } + if ((self->rx_am[0] == tmp[0]) && + (self->rx_am[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_am(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_set_rx_am"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_am(self, input, 1); +} + + +int +__qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_em; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_em[0] == setv[0]) && + (self->rx_em[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + setv, + self->rx_em, + "_qsfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_em; + } + return 0; + +err_qsfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_em[0]; + tmp[1] = self->rx_em[1]; + if (_qsfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if ((self->rx_em[0] == tmp[0]) && + (self->rx_em[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_em(self, input, 1); +} + + +int +common_transvr_dump(struct transvr_obj_s* self){ + + char *type_name = "Undefined"; + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + switch (self->type) { + case TRANSVR_TYPE_SFP: + type_name = STR_TRANSVR_SFP; + break; + case TRANSVR_TYPE_QSFP: + type_name = STR_TRANSVR_QSFP; + break; + case TRANSVR_TYPE_QSFP_PLUS: + type_name = STR_TRANSVR_QSFP_PLUS; + break; + case TRANSVR_TYPE_QSFP_28: + type_name = STR_TRANSVR_QSFP28; + break; + case TRANSVR_TYPE_FAKE: + type_name = "FAKE"; + goto ok_common_transvr_dump; + case TRANSVR_TYPE_UNPLUGGED: + type_name = "UNPLUGGED"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_INCONSISTENT: + type_name = "INCONSISTENT"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_ERROR: + type_name = "ERROR"; + goto err_common_transvr_dump; + + default: + type_name = "UNEXPECTED"; + goto err_common_transvr_dump; + } + printk(KERN_INFO "[SWPS] Dump %s information:\n", self->swp_name); + printk(KERN_INFO " |- :%s\n", type_name); + printk(KERN_INFO " |- :%s\n", self->vendor_name); + printk(KERN_INFO " |- :%s\n", self->vendor_pn); + printk(KERN_INFO " |- :%s\n", self->vendor_rev); + printk(KERN_INFO " |- :%s\n", self->vendor_sn); + printk(KERN_INFO " |- :0x%02x\n", self->br); + printk(KERN_INFO " |- :0x%02x\n", self->comp_rev); + printk(KERN_INFO " |- :%d\n", self->len_om1); + printk(KERN_INFO " |- :%d\n", self->len_om2); + printk(KERN_INFO " |- :%d\n", self->len_om3); + printk(KERN_INFO " |- :%d\n", self->len_om4); + return 0; + +ok_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return 0; + +err_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return -1; +} + + +int +sfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_sm); + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :0x%02x\n", self->rate_id); + return 0; +} + + +int +qsfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :Class_%d\n", __qsfp_get_power_cls(self, 0)); + return 0; +} + + +int +fake_transvr_dump(struct transvr_obj_s* self) { + + printk(KERN_INFO "[SWPS] Dump transceiver information: %s\n", self->swp_name); + printk(KERN_INFO " |- :FAKE\n"); + printk(KERN_INFO " |- :FAKE_VENDER_NAME\n"); + printk(KERN_INFO " |- :FAKE_VENDER_PN\n"); + printk(KERN_INFO " |- :FAKE_VENDER_REV\n"); + printk(KERN_INFO " |- :FAKE_VENDER_SN\n"); + printk(KERN_INFO " |- :0x99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " '- :0x99\n"); + return 0; +} + + +/* ========== Object functions for fake type ========== + */ +int +fake_transvr_update(struct transvr_obj_s *self, + int show_err){ + self->state = STATE_TRANSVR_CONNECTED; + return 0; +} + + +int +fake_get_binary(struct transvr_obj_s *self){ + return 1; +} + +int +fake_get_int(struct transvr_obj_s *self){ + return 99; +} + + +int +fake_get_hex(struct transvr_obj_s *self){ + return 0x0f; +} + + +int +fake_get_str(struct transvr_obj_s *self, char *buf) { + return snprintf(buf, 16, "fake_get_str\n"); +} + + +int +fake_set_int(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: %d\n", __func__, input); + return 0; +} + + +int +fake_set_hex(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: 0x%02x\n", __func__, input); + return 0; +} + + +/* ========== Object functions for unsupported ========== + */ +int +unsupported_get_func(struct transvr_obj_s *self){ + return ERR_TRANSVR_NOTSUPPORT; +} + + +int +unsupported_get_func2(struct transvr_obj_s *self, + char *buf_p) { + int len = snprintf(buf_p, 8, "%d\n", ERR_TRANSVR_NOTSUPPORT); + return len; +} + + +int +unsupported_set_func(struct transvr_obj_s *self, + int input_val){ + return ERR_TRANSVR_NOTSUPPORT; +} + + + +/* ========== Object functions for long term task ========== + * + * [Note] + * SWPS transceiver worker is likely the green-thread (coroutine). + * Due to resource and performance considerations. SWPS run all + * features in one kthread at the same time, and handle by it self. + */ + +/* For Transceiver Task Handling + */ +static struct transvr_worker_s * +transvr_task_get(struct transvr_obj_s *self, + char *func_name) { + + struct transvr_worker_s *curr_p = self->worker_p; + + while(curr_p != NULL){ + if (strcmp((curr_p->func_name), func_name) == 0 ) { + return curr_p; + } + curr_p = curr_p->next_p; + } + return NULL; +} + + +static struct transvr_worker_s* +transvr_task_creat(struct transvr_obj_s *self, + int (*main_task)(struct transvr_worker_s *task), + int (*post_task)(struct transvr_worker_s *task), + char *caller) { + + struct transvr_worker_s *task_p = NULL; + struct transvr_worker_s *curr_p = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check task not exist */ + task_p = transvr_task_get(self, caller); + if (task_p) { + snprintf(err_msg, sizeof(err_msg), "Task already created!"); + goto err_transvr_task_creat; + } + /* Create task worker */ + task_p = kzalloc(sizeof(struct transvr_worker_s), GFP_KERNEL); + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_transvr_task_creat; + } + /* Setup task data */ + task_p->transvr_p = self; + task_p->next_p = NULL; + task_p->trigger_time = 0; + task_p->retry = 1; + task_p->state = STATE_T_TASK_INIT; + task_p->main_task = main_task; + task_p->post_task = post_task; + task_p->p_data = NULL; + snprintf(task_p->func_name, sizeof(task_p->func_name), "%s", caller); + /* Setup Link List */ + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p->next_p != NULL) { + curr_p = curr_p->next_p; + } + curr_p->next_p = task_p; + task_p->pre_p = curr_p; + } else { + self->worker_p = task_p; + task_p->pre_p = NULL; + } + return task_p; + +err_transvr_task_creat: + SWPS_ERR("%s: %s :%s :%s\n", + __func__, err_msg, caller, self->swp_name); + return NULL; +} + + +static void +transvr_task_free_one(struct transvr_worker_s *task_p){ + + struct transvr_worker_s *pre_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (task_p) { + pre_p = task_p->pre_p; + next_p = task_p->next_p; + + if ((pre_p) && (next_p)) { + pre_p->next_p = next_p; + next_p->pre_p = pre_p; + + } else if ((!pre_p) && (next_p)) { + next_p->pre_p = NULL; + + } else if ((pre_p) && (!next_p)) { + pre_p->next_p = NULL; + + } else if ((!pre_p) && (!next_p)) { + task_p->transvr_p->worker_p = NULL; + } else { + SWPS_ERR("%s: Unexcept case!\n :%s", + __func__, task_p->transvr_p->swp_name); + } + kfree(task_p->p_data); + kfree(task_p); + } +} + + +static void +transvr_task_free_all(struct transvr_obj_s *self) { + + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p) { + next_p = curr_p->next_p; + transvr_task_free_one(curr_p); + curr_p = next_p; + } + self->worker_p = NULL; + } +} + + +static int +_transvr_task_run_main(struct transvr_worker_s *task_p) { + + int retval = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "main_task is NULL!"); + goto main_transvr_task_err; + } + if ((task_p->trigger_time) == 0){ + goto main_transvr_task_run; + } + if (time_before(jiffies, task_p->trigger_time)){ + goto main_transvr_task_wait; + } + goto main_transvr_task_run; + +main_transvr_task_run: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + task_p->retry -= 1; + } + retval = task_p->main_task(task_p); + if (retval < 0) { + if (task_p->retry > 0) { + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + } + goto main_transvr_task_identify; + +main_transvr_task_identify: + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + + case EVENT_TRANSVR_TASK_DONE: + task_p->state = STATE_T_TASK_DONE; + return EVENT_TRANSVR_TASK_DONE; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + +main_transvr_task_wait: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + +main_transvr_task_err: + task_p->state = STATE_T_TASK_FAIL; + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, retval, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +_transvr_task_run_post(struct transvr_worker_s *task_p) { + + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if ((task_p->post_task) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + switch (task_p->state) { + case STATE_T_TASK_WAIT: + case STATE_T_TASK_INIT: + goto post_transvr_task_wait; + + case STATE_T_TASK_DONE: + case STATE_T_TASK_FAIL: + goto post_transvr_task_run; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Unexcept task state"); + goto post_transvr_task_err; + +post_transvr_task_run: + task_p->post_task(task_p); + return EVENT_TRANSVR_TASK_DONE; + +post_transvr_task_wait: + return EVENT_TRANSVR_TASK_WAIT; + +post_transvr_task_err: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, task_p->state, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_one(struct transvr_worker_s *task_p) { + + int retval_main = DEBUG_TRANSVR_INT_VAL; + int retval_post = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval_main = _transvr_task_run_main(task_p); + if (retval_main < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute main_task fail!"); + goto err_transvr_task_run_one; + } + retval_post = _transvr_task_run_post(task_p); + if (retval_post < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute post_task fail!"); + goto err_transvr_task_run_one; + } + return retval_main; + +err_transvr_task_run_one: + SWPS_INFO("%s: %s
:%d :%d :%s :%s\n", + __func__, err_msg, retval_main, retval_post, + task_p->func_name, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_all(struct transvr_obj_s *self) { + + int haserr = 0; + int retval = DEBUG_TRANSVR_INT_VAL; + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if ((self->worker_p) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + curr_p = self->worker_p; + while (curr_p != NULL) { + next_p = curr_p->next_p; + retval = transvr_task_run_one(curr_p); + if (curr_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + curr_p = next_p; + continue; + } + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + break; + case EVENT_TRANSVR_TASK_DONE: + transvr_task_free_one(curr_p); + break; + case EVENT_TRANSVR_TASK_FAIL: + + default: + haserr = 1; + transvr_task_free_one(curr_p); + break; + } + curr_p = next_p; + } + if (haserr) { + return EVENT_TRANSVR_TASK_FAIL; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +static void +transvr_task_set_delay(struct transvr_worker_s *task_p, + unsigned long delay_msec) { + + task_p->trigger_time = (jiffies + (delay_msec * (HZ/1000))); +} + + +static void +transvr_task_set_retry(struct transvr_worker_s *task_p, + unsigned long retry_times) { + + task_p->retry = retry_times; +} + + +/* For Transceiver Post Task + */ +int +taskfunc_post_do_nothing(struct transvr_worker_s *task_p) { + + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_post_handle_task_state(struct transvr_worker_s *task_p) { + + struct transvr_obj_s* tp = task_p->transvr_p; + + switch (task_p->state) { + case STATE_T_TASK_INIT: + case STATE_T_TASK_WAIT: + return EVENT_TRANSVR_TASK_WAIT; + + case STATE_T_TASK_DONE: + tp->state = STATE_TRANSVR_CONNECTED; + tp->send_uevent(tp, KOBJ_ADD); + return EVENT_TRANSVR_TASK_DONE; + + case STATE_T_TASK_FAIL: + tp->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_TASK_FAIL; + + default: + break; + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +/* For Transceiver Main Task + */ +int +_taskfunc_sfp_setup_soft_rs(struct transvr_worker_s *task_p, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller) { + + int show_err = 0; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_soft_rs"; + + err_code = _sfp_update_attr_soft_rs0(task_p->transvr_p, 0); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + err_code = __sfp_set_soft_rs(task_p->transvr_p, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_setup_soft_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_code); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +__taskfunc_sfp_setup_hard_rs(struct transvr_worker_s *task_p, + int input_val, + int (*get_func)(struct ioexp_obj_s *self, int virt_offset), + int (*set_func)(struct ioexp_obj_s *self, int virt_offset, int input_val)) { + + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + + err_val = get_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset); + + if (err_val < 0) { + if (err_val == ERR_IOEXP_NOTSUPPORT) { + return EVENT_TRANSVR_TASK_DONE; + } + err_str = "Get current hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + if (err_val == input_val) { + return EVENT_TRANSVR_TASK_DONE; + } + err_val = set_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_p_taskfunc_sfp_setup_hard_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_hard_rs0(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs0, + task_p->transvr_p->ioexp_obj_p->set_hard_rs0); +} + + +int +_taskfunc_sfp_setup_hard_rs1(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs1, + task_p->transvr_p->ioexp_obj_p->set_hard_rs1); +} + + +int +_taskfunc_sfp_setup_rs0(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs0"; + + err_val = _taskfunc_sfp_setup_hard_rs0(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs0, + task_p->transvr_p->eeprom_map_p->page_soft_rs0, + task_p->transvr_p->eeprom_map_p->offset_soft_rs0, + bit_shift, + &(task_p->transvr_p->soft_rs0), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs0_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs0(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_rs1(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs1"; + + err_val = _taskfunc_sfp_setup_hard_rs1(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs1, + task_p->transvr_p->eeprom_map_p->page_soft_rs1, + task_p->transvr_p->eeprom_map_p->offset_soft_rs1, + bit_shift, + &(task_p->transvr_p->soft_rs1), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs1_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs1(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_sfp_setup_SFF8431_case1(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs0(task_p, update_val); +} + + + +int +taskfunc_sfp_setup_SFF8431_case2(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs1(task_p, update_val); +} + + +int +taskfunc_sfp_setup_SFF8431_case3(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + int update_rs0 = 1; + int update_rs1 = 1; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _taskfunc_sfp_setup_rs0(task_p, update_rs0); + if (err_code < 0) { + return err_code; + } + return _taskfunc_sfp_setup_rs1(task_p, update_rs1); +} + + +int +taskfunc_sfp_handle_1g_rj45(struct transvr_worker_s *task_p) { + + /* Not all of platform support 0x56 for transceiver + * external PHY, Support list as below: + * => 1. Magnolia-PVT (PS: EVT & DVT not ready) + */ + int ext_phy_addr = 0x56; + int ext_phy_page = -1; + int ext_phy_offs = 0x11; + int ext_phy_len = 1; + int lstate_mask = 0x04; /* 00000100 */ + int show_err = 0; + int fail_retry = 5; + int fail_delay = 1000; /* msec */ + int err_code = DEBUG_TRANSVR_INT_VAL; + uint8_t detect_val = DEBUG_TRANSVR_HEX_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + int *tmp_p = NULL; + char *func_name = "taskfunc_sfp_handle_1g_rj45"; + + if (task_p->transvr_p->state != STATE_TRANSVR_CONNECTED) { + return EVENT_TRANSVR_TASK_DONE; + } + if ( (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000) && + (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000_up) ) { + goto err_taskfunc_sfp_handle_1g_rj45_1; + } + err_code = _common_update_uint8_attr(task_p->transvr_p, + ext_phy_addr, + ext_phy_page, + ext_phy_offs, + ext_phy_len, + &detect_val, + func_name, + show_err); + if ( (err_code < 0) || + (detect_val == DEBUG_TRANSVR_HEX_VAL) ) { + snprintf(err_str, sizeof(err_str), "Detect external link status fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + if ((detect_val & lstate_mask) == lstate_mask) { + goto ok_taskfunc_sfp_handle_1g_rj45_link_up; + } + goto ok_taskfunc_sfp_handle_1g_rj45_link_down; + +ok_taskfunc_sfp_handle_1g_rj45_link_up: + /* Filter out noise */ + if (!(task_p->p_data)) { + tmp_p = kzalloc(sizeof(int), GFP_KERNEL); + if (!tmp_p) { + snprintf(err_str, sizeof(err_str), "kzalloc p_data fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + *tmp_p = TRANSVR_CLASS_BASE_T_1000_up; + task_p->p_data = tmp_p; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + } + if ((*(int *)(task_p->p_data)) != TRANSVR_CLASS_BASE_T_1000_up) { + kfree(task_p->p_data); + task_p->p_data = NULL; + snprintf(err_str, sizeof(err_str), "Internal error"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + kfree(task_p->p_data); + task_p->p_data = NULL; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_link_down: + if (task_p->p_data) { + kfree(task_p->p_data); + task_p->p_data = NULL; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_done: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_1: + snprintf(err_str, sizeof(err_str), "Detect transceiver:%d not Base-T, remove task.", + task_p->transvr_p->info); + SWPS_INFO("%s: %s :%s\n", __func__, err_str, task_p->transvr_p->swp_name); + transvr_task_set_retry(task_p, 0); + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_2: + if (task_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, fail_retry); + } + if ((task_p->retry) == 0) { + /* Error case: + * => In this case, SWPS will stop external Link state monitor features + * and keeps transvr_p->info on TRANSVR_CLASS_BASE_T_1000_up. + * Upper layer will see it always Linkup that because of these type of + * transceiver has external phy, BCM chip see it as Loopback transceiver. + */ + SWPS_WARN("%s can not access external PHY of Base-T SFP transceiver\n", + task_p->transvr_p->swp_name); + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + return EVENT_TRANSVR_TASK_DONE; + } else { + transvr_task_set_delay(task_p, fail_delay); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_qsfp_setup_power_mod(struct transvr_obj_s *self, + int setup_val) { + + int curr_val = DEBUG_TRANSVR_INT_VAL; + int err_val = DEBUG_TRANSVR_INT_VAL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + curr_val = self->ioexp_obj_p->get_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset); + if (curr_val < 0){ + err_msg = "Get current value fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + if (curr_val == setup_val){ + return EVENT_TRANSVR_TASK_DONE; + } + err_val = self->ioexp_obj_p->set_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset, + setup_val); + if (err_val < 0){ + err_msg = "Setup power mode fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_qsfp_setup_power_mod_1: + SWPS_INFO("%s: %s :%d :%d :%d\n", + __func__, err_msg, err_val, curr_val, setup_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_qsfp_handle_tx_disable(struct transvr_worker_s *task_p) { + + int i = 0; + int retry = 5; + int delay_ms = 100; + + if (task_p->transvr_p->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return EVENT_TRANSVR_TASK_DONE; + } + if (!_qsfp_is_implement_tx_disable(task_p->transvr_p)) { + return EVENT_TRANSVR_TASK_DONE; + } + for (i=0; itransvr_p, + task_p->transvr_p->auto_tx_disable) + == EVENT_TRANSVR_TASK_DONE) { + goto ok_taskfunc_qsfp_handle_tx_disable; + } + mdelay(delay_ms); + } + SWPS_INFO("%s auto setup tx_disable:0x%02x fail.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_INIT_FAIL; + +ok_taskfunc_qsfp_handle_tx_disable: + SWPS_INFO("%s auto setup tx_disable:0x%02x ok.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_qsfp_set_hpmod(struct transvr_worker_s *task_p) { + + int err = DEBUG_TRANSVR_INT_VAL; + int HIGH_POWER_MODE = 0; + + /* Handle power mode */ + err = _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + HIGH_POWER_MODE); + if (err < 0) { + SWPS_INFO("%s: setup hpmod fail :%d :%s\n", + __func__, err, task_p->transvr_p->swp_name); + return err; + } + /* Handle auto tx_disable + * [Note] + * => Because there are some transceiver have timing issues or + * setup sequence issues, therefore we handle auto tx_disable + * after handle power mode. + */ + mdelay(100); + return taskfunc_qsfp_handle_tx_disable(task_p); +} + + +int +taskfunc_qsfp_set_lpmod(struct transvr_worker_s *task_p) { + + int LOW_POWER_MODE = 1; + return _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + LOW_POWER_MODE); +} + + +static int +initfunc_sfp_handle_multi_rate_mode(struct transvr_obj_s *self) { + + int task_retry = 3; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "sfp_handle_multi_rate_mode"; + struct transvr_worker_s *task_p = NULL; + + switch (self->rate_id) { + case 0x00: /* Unspecified */ + case 0x03: /* Unspecified */ + case 0x05: /* Unspecified */ + case 0x07: /* Unspecified */ + case 0x09: /* Unspecified */ + case 0x0B: /* Unspecified */ + case 0x0D: /* Unspecified */ + case 0x0F: /* Unspecified */ + goto sfp_handle_multi_rate_mode_4_unspecified; + + case 0x02: /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case1, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x04: /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case2, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x06: /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case3, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x01: /* SFF-8079 (4/2/1G Rate_Select & AS0/AS1) */ + err_str = "SFF-8079 (4/2/1G Rate_Select & AS0/AS1)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x08: /* FC-PI-5 (16/8/4G Rx Rate_select only) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Rx Rate_select only)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0A: /* FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0C: /* FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + */ + err_str = "FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0E: /* 10/8G Rx and Tx Rate_Select controlling the operation or + * locking modes of the internal signal conditioner, retimer + * or CDR, according to the logic table defined in Table 10-2, + * High Bit Rate (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = + * 8.5 Gb/s. In this mode, the default value of bit 110.3 (Soft + * Rate Select RS(0), Table 9-11) and of bit 118.3 (Soft Rate + * Select RS(1), Table 10-1) is 1. + */ + err_str = "cable type: 0x0E"; + goto sfp_handle_multi_rate_mode_4_not_support; + + default: + err_str = "cable type: UNKNOW"; + goto sfp_handle_multi_rate_mode_4_not_support; + } + +sfp_handle_multi_rate_mode_4_sff8431: + if (!task_p) { + err_str = "Create task fail!"; + goto sfp_handle_multi_rate_mode_4_fail_1; + } + transvr_task_set_retry(task_p, task_retry); + return EVENT_TRANSVR_TASK_WAIT; + +sfp_handle_multi_rate_mode_4_unspecified: + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_not_support: + SWPS_INFO("%s: Does not support %s :%s :0x%02x\n", + func_str, err_str, self->swp_name, self->rate_id); + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_fail_1: + SWPS_INFO("%s: %s :%s :0x%02x, :%d\n", + func_str, err_str, self->swp_name, self->rate_id, err_code); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +initfunc_sfp_handle_1g_rj45(struct transvr_obj_s *self) { + + struct transvr_worker_s *task_p = NULL; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_sfp_handle_1g_rj45"; + + + if (self->info == TRANSVR_CLASS_BASE_T_1000) { + task_p = transvr_task_creat(self, + taskfunc_sfp_handle_1g_rj45, + taskfunc_post_do_nothing, + func_str); + if (!task_p) { + snprintf(err_str, sizeof(err_str), "Create task fail"); + goto err_initfunc_sfp_handle_1g_rj45; + } + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_initfunc_sfp_handle_1g_rj45: + SWPS_INFO("%s: %s :%s :%d\n", + __func__, err_str, self->swp_name, detect_cls); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +initfunc_qsfp_handle_power_mode(struct transvr_obj_s *self) { + + int err_code = EVENT_TRANSVR_EXCEP_INIT; + int power_class = DEBUG_TRANSVR_INT_VAL; + int hpmod_retry = 3; + int lpower_config = 1; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + unsigned long hpmod_delay = 500; /* msec */ + struct transvr_worker_s *task_p = NULL; + + /* Handle power mode for IOEXP */ + power_class = __qsfp_get_power_cls(self, 0); + switch (power_class) { + case 1: /* Case: Low power mode (Class = 1) */ + err_code = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (err_code < 0){ + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + return EVENT_TRANSVR_TASK_DONE; + + case 2: /* Case: High power mode (Class > 1) */ + case 3: + case 4: + case 5: + case 6: + case 7: + task_p = transvr_task_creat(self, + taskfunc_qsfp_set_hpmod, + taskfunc_post_handle_task_state, + "transvr_init_qsfp"); + if (!task_p) { + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + transvr_task_set_retry(task_p, hpmod_retry); + transvr_task_set_delay(task_p, hpmod_delay); + return EVENT_TRANSVR_TASK_WAIT; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Exception case"); + goto err_initfunc_qsfp_handle_power_mode; + +err_initfunc_qsfp_handle_power_mode: + SWPS_INFO("%s: %s :%s \n", __func__, err_msg, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +initfunc_qsfp28_handle_cdr(struct transvr_obj_s *self) { + + uint8_t DEFAULT_VAL_CDR = 0xff; + int CDR_FUNC_EXISTED = 0x3; + int show_err = 1; + int err_val = EVENT_TRANSVR_TASK_FAIL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_qsfp28_handle_cdr"; + + err_val = __qsfp_get_cdr_present(self, 0); + if ( (err_val < 0) || + (err_val == DEBUG_TRANSVR_HEX_VAL) ) { + err_msg = "detect cdr_present fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + if (err_val == CDR_FUNC_EXISTED) { + err_val = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->offset_cdr, + DEFAULT_VAL_CDR, + &(self->cdr), + func_str, + show_err); + if (err_val < 0) { + err_msg = "set CDR fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_qsfp_handle_cdr_1: + SWPS_INFO("%s: %s :%d :%s\n", + func_str, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + +/* ========== 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 +_sfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = _sfp_get_comp_extended(self); + + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_25G_AOC; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_25G_SR; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_25G_LR; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_25G_ER; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x0c: /* 25GBASE-CR CA-S */ + case 0x0d: /* 25GBASE-CR CA-N */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L1_25G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_10_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _sfp_get_comp_10g_eth_comp(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 10G Optical (x1) */ + if ((detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + } + if ((detect_val & 0x80) == 0x80) { /* 10000000 : 10GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_1g = 0x0b; + int upper_bound_1g = 0x1A; + int lower_bound_10g = 0x60; + int upper_bound_10g = 0x75; + int lower_bound_25g = 0xf0; + int upper_bound_25g = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 25G */ + if ((notmal_br >= lower_bound_25g) && + (notmal_br <= upper_bound_25g) ) { + return TRANSVR_CLASS_25G; + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + /* Check 1G */ + if ((notmal_br >= lower_bound_1g) && + (notmal_br <= upper_bound_1g) ) { + return TRANSVR_CLASS_1G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + int speed_br = DEBUG_TRANSVR_INT_VAL; + int speed_tmp = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + + speed_br = _sfp_detect_if_sp_by_br(self); + detect_val = _sfp_get_comp_1g_eth_comp(self); + + if (detect_val < 0) { + snprintf(err_str, sizeof(err_str), "Detect abnormal value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + } + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 1G (x1) */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 1000BASE-SX */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_SX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x02) == 0x02) { /* 00000010 : 1000BASE-LX *3 */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_LX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 1000BASE-CX */ + speed_tmp = TRANSVR_CLASS_COPPER_L1_1G; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + /* Case: 1000 Base-T (x1) */ + if ((detect_val & 0x08) == 0x08) { /* 00001000 : 1000BASE-T */ + return TRANSVR_CLASS_BASE_T_1000; + } + /* Case: 100 Base */ + if ( ((detect_val & 0x10) == 0x10) || /* 00010000 : 100BASE-LX/LX10 */ + ((detect_val & 0x20) == 0x20) || /* 00100000 : 100BASE-FX */ + ((detect_val & 0x40) == 0x40) || /* 01000000 : BASE-BX10 *3 */ + ((detect_val & 0x80) == 0x80) ){ /* 10000000 : BASE-PX *3 */ + return TRANSVR_CLASS_OPTICAL_100; + } + /* Case: ERROR */ + snprintf(err_str, sizeof(err_str), "Case:ERROR, value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + +ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g: + switch (speed_br) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_1G: + return speed_tmp; + case TRANSVR_CLASS_10G: + goto ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G; + } + +ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G: + switch (speed_tmp) { + case TRANSVR_CLASS_OPTICAL_1G_SX: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case TRANSVR_CLASS_OPTICAL_1G_LX: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case TRANSVR_CLASS_COPPER_L1_1G: + return TRANSVR_CLASS_COPPER_L1_10G; + default: + break; + } + snprintf(err_str, sizeof(err_str), "transfer_1to10 fail, speed:%d", speed_tmp); + goto err_p_sfp_detect_class_by_1g_ethernet; + +err_p_sfp_detect_class_by_1g_ethernet: + SWPS_INFO("%s: %s :%s", __func__, err_str, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int is_active = 0; + int conn_val = DEBUG_TRANSVR_INT_VAL; + int check_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _sfp_detect_if_sp_by_br(self); + conn_val = _sfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 */ + case 0x0d: /* MPO 2x16 */ + /* + * ToDo: Need verify Optical Pigtail + */ + goto ok_sfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + /* + * ToDo: Need check ACC use case + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x23: /* No separable connector */ + /* + * ToDo: Standard not clear, not all transceiver vendor + * have the same defined + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_check_active_passive: + check_val = _sfp_get_cable_tech(self); + switch(check_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_unknow; + case 0x04: /* Passive */ + goto ok_sfp_detect_class_by_feature_4_copper; + case 0x08: /* Active */ + is_active = 1; + goto ok_sfp_detect_class_by_feature_4_aoc; + default: + snprintf(err_msg, sizeof(err_msg), + "_sfp_get_cable_tech return Non define value:%d", + check_val); + break; + } + goto err_sfp_detect_class_by_feature_1; + +ok_sfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_25G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_25G_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_25G_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_25G_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_25G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + case TRANSVR_CLASS_1G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_1G_SX; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_1G_LX; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_1G_EX; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_1G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_sfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_OPTICAL_25G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_S_AOC; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_OPTICAL_1G_AOC; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_COPPER_L1_25G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L1_10G; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_COPPER_L1_1G; + default: + return TRANSVR_CLASS_COPPER; + } + +ok_sfp_detect_class_by_feature_4_unknow: + return TRANSVR_CLASS_UNSPECIFIED; + +err_sfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +sft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _sfp_detect_class_by_extend_comp(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 10G Compliance */ + detect_val = _sfp_detect_class_by_10_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 1G Compliance */ + detect_val = _sfp_detect_class_by_1g_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_BASE_T_1000: + case TRANSVR_CLASS_OPTICAL_100: + /* + * ToDo: Need Check 0.1G + */ + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_COPPER_L1_10G: + /* Transfer speed case + * => Example: Raycom 10G DAC + */ + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 1G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check by connector, br, wavelength */ + detect_val = _sfp_detect_class_by_feature(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_OPTICAL_1G: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_COPPER: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_COPPER_L1_10G: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined get_connector:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sft_detect_transceiver_class_1; + +err_sft_detect_transceiver_class_1: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_trident2_if_type_1; + +err_sfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SR); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_KR); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_tomahawk_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_tomahawk_if_type_1; + +err_sfp_set_tomahawk_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = sft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _sfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TOMAHAWK: + return _sfp_set_tomahawk_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_sfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = sft_detect_transvr_class(self); + switch(detect_val) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_SP_100); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + detect_val); + goto err_sfp_detect_if_speed_1; + } + /* Check by BR */ + detect_val = _sfp_detect_if_sp_by_br(self); + switch (detect_val) { + case TRANSVR_CLASS_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + default: + break; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_detect_if_speed_1; + +err_sfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_extended(self); + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_100G_AOC; + + case 0x06: /* 100G CWDM4 */ + case 0x09: /* Obsolete (assigned before 100G CWDM4 MSA required FEC) */ + case 0x17: /* 100G CLR4 */ + case 0x1A: /* 100GE-DWDM2 */ + return TRANSVR_CLASS_OPTICAL_100G; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_100G_SR4; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_100G_LR4; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_100G_ER4; + + case 0x07: /* 100G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_100G_PSM4; + + case 0x12: /* 40G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_40G; + + case 0x11: /* 4 x 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + + case 0x10: /* 40GBASE-ER4 */ + return TRANSVR_CLASS_OPTICAL_40G_ER4; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L4_100G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_class_by_10_40_100_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_10_40_100_ethernet(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 40G Optical */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 40G Active Cable (XLPPI) */ + return TRANSVR_CLASS_OPTICAL_40G_AOC; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 40GBASE-SR4 */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + } + if ( (detect_val & 0x02) == 0x02) { /* 00000010 : 40GBASE-LR4 */ + return TRANSVR_CLASS_OPTICAL_40G_LR4; + } + if ( (detect_val & 0x08) == 0x08) { /* 00001000 : 40GBASE-CR4 */ + return TRANSVR_CLASS_COPPER_L4_40G; + } + /* Case: 10G Optical */ + if ( (detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + } + /* Case: Extend Compliance */ + if ( ((detect_val & 0x80) == 0x80) ){ /* 10000000 : Use Extend Compliance */ + return TRANSVR_CLASS_EXTEND_COMP; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_10g = 0x10; + int upper_bound_10g = 0x25; + int lower_bound_40g = 0x60; + int upper_bound_40g = 0x75; + int lower_bound_100g = 0x60; + int upper_bound_100g = 0x75; + int used_extend_br = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + int extend_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 40G */ + if ((notmal_br >= lower_bound_40g) && + (notmal_br <= upper_bound_40g) ) { + return TRANSVR_CLASS_40G; + } + /* Check 100G */ + if (notmal_br == used_extend_br) { + extend_br = (int)(self->extbr); /* updated by update_all() */ + if ((extend_br >= lower_bound_100g) && + (extend_br <= upper_bound_100g) ) { + return TRANSVR_CLASS_100G; + } + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_qsfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int conn_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _qsfp_detect_if_sp_by_br(self); + conn_val = _qsfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 (Multifiber Parallel Optic) */ + case 0x0d: /* MPO 2x16 */ + goto ok_qsfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + goto ok_qsfp_detect_class_by_feature_4_copper; + case 0x23: /* No separable connector */ + if ((_qsfp_get_comp_fc_link_length(self) > 0) || + (_qsfp_get_comp_fc_trans_tech(self) > 0) || + (_qsfp_get_comp_fc_trans_media(self) > 0) || + (_qsfp_get_comp_fc_speed(self) > 0) ) { + goto ok_qsfp_detect_class_by_feature_4_aoc; + } + goto ok_qsfp_detect_class_by_feature_4_copper; + default: + snprintf(err_msg, sizeof(err_msg), + "_qsfp_get_connector_type return Non define value:%d", + conn_val); + goto err_qsfp_detect_class_by_feature_1; + } + return TRANSVR_CLASS_UNSPECIFIED; + +ok_qsfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_100G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_100G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_100G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_100G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_100G; + + case TRANSVR_CLASS_40G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_40G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_40G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_40G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_40G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_Q_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_OPTICAL_100G_AOC; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_OPTICAL_40G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_Q_AOC; + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_COPPER_L4_100G; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_COPPER_L4_40G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L4_10G; + default: + return TRANSVR_CLASS_COPPER; + } + +err_qsfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", + __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +qsft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _qsfp_detect_class_by_extend_comp(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_COPPER_L4_100G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check 10/40G/100G Ethernet Compliance */ + detect_val = _qsfp_detect_class_by_10_40_100_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_COPPER_L4_40G: + return detect_val; + case TRANSVR_CLASS_EXTEND_COMP: + /* Format incorrect case (We already checked the Extend + * Compliance is 0 + */ + snprintf(err_msg, sizeof(err_msg), + "Transceiver format incorrect"); + goto err_qsft_detect_transvr_class_1; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10/40/100:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check by Connector type, BR and wavelength */ + detect_val = _qsfp_detect_class_by_feature(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_COPPER_L4_100G: + case TRANSVR_CLASS_COPPER_L4_40G: + case TRANSVR_CLASS_COPPER_L4_10G: + case TRANSVR_CLASS_COPPER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined connector:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), + "Can not identify!"); + goto err_qsft_detect_transvr_class_1; + +err_qsft_detect_transvr_class_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: LR4 or LR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: /* Need Check: ER4 or ER */ + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_KR4); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = qsft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _qsfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TOMAHAWK: + return _qsfp_set_tomahawk_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 8; + char tmp_result[8] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = qsft_detect_transvr_class(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G Copper */ + case TRANSVR_CLASS_COPPER_L4_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + break; + /* Copper */ + case TRANSVR_CLASS_COPPER: + break; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined class case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Check br and extbr */ + detect_val = _qsfp_detect_if_sp_by_br(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + case TRANSVR_CLASS_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined BR case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_detect_if_speed_1; + +err_qsfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_common_set_lane_map_str(struct transvr_obj_s* self, + char *result) { + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + char err_msg[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_L_STR); + snprintf(result, LEN_TRANSVR_L_STR, "%s=", TRANSVR_UEVENT_KEY_LANE); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + if (tmp_val > 256) { + snprintf(err_msg, sizeof(err_msg), + "detect abnormal value:%d", tmp_val); + goto err_common_set_lane_map_str_1; + } + memset(tmp_str, 0, sizeof(tmp_str)); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_L_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_L_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_L_STR); + } + if (i == 0) { + goto err_common_set_lane_map_str_2; + } + return 0; + +err_common_set_lane_map_str_1: + SWPS_INFO("%s: %s", __func__, err_msg); +err_common_set_lane_map_str_2: + snprintf(result, LEN_TRANSVR_L_STR, "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_common_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action, + int (*detect_if_type)(struct transvr_obj_s *self, char *result), + int (*detect_if_speed)(struct transvr_obj_s *self, char *result), + int send_anyway) { + + char *uevent_envp[4]; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + char tmp_str[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_1[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_2[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_3[64] = DEBUG_TRANSVR_STR_VAL; + + if (TRANSVR_UEVENT_ENABLE != 1) { + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_get_if_lane(self, tmp_str) < 0) { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + } else { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, tmp_str); + } + switch (u_action) { + case KOBJ_ADD: + /* Detect type */ + if (detect_if_type(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface type fail!"); + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, tmp_str); + uevent_envp[0] = tmp_str_1; + /* Detect speed */ + if (detect_if_speed(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface speed fail!"); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, tmp_str); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + case KOBJ_REMOVE: + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + default: + snprintf(err_msg, sizeof(err_msg), "kobject_action:%d not support", u_action); + goto private_common_send_uevent_4_fail; + } + snprintf(err_msg, sizeof(err_msg), "%s", "Exception case"); + goto private_common_send_uevent_4_fail; + +private_common_send_uevent_4_fail: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + if (send_anyway) { + goto private_common_send_uevent_4_send; + } + return ERR_TRANSVR_UEVENT_FAIL; + +private_common_send_uevent_4_send: + return kobject_uevent_env(&(self->transvr_dev_p->kobj), + u_action, + uevent_envp); +} + +int +sfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_sfp_detect_if_type, + &_sfp_detect_if_speed, + send_anyway); +} + + +int +qsfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_qsfp_detect_if_type, + &_qsfp_detect_if_speed, + send_anyway); +} + + +int +fake_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + return EVENT_TRANSVR_TASK_DONE; +} + + +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; +} + + +static int +_is_except_happened_4_pmode(struct transvr_obj_s* self, + int new_state) { + + int event_chk = 0; + + if (self->temp == 0){ + return 0; + } + switch (new_state) { + case STATE_TRANSVR_INIT: + event_chk = EVENT_TRANSVR_EXCEP_INIT; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_CONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_UP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_DISCONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_DOWN; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_SWAPPED: + event_chk = EVENT_TRANSVR_EXCEP_SWAP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_UNEXCEPTED: + event_chk = EVENT_TRANSVR_EXCEP_EXCEP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_ISOLATED: + event_chk = EVENT_TRANSVR_EXCEP_ISOLATED; + goto check_event_happened_4_pmode; + + default: + SWPS_INFO("%s: unexcepted case:%d\n", __func__, new_state); + break; + } + return 0; + +check_event_happened_4_pmode: + if (self->temp == event_chk){ + return 1; + } + return 0; +} + + +int +common_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + /* [Return Value]: + * ERR_TRANSVR_UNINIT : (1) Initial not ready + * ERR_TRANSVR_UNPLUGGED : (1) Any -> Down + * ERR_TRANSVR_TASK_BUSY : (1) Wait Initial task + * ERR_TRANSVR_UNEXCPT : (1) Initial fail + * (2) Task fail + * (3) Reload fail + * ERR_TRNASVR_BE_ISOLATED : (1) Already be isolated + * OK Case (return 0) : (1) action_4_connected + * (2) action_4_nothing (initial retry) + */ + int curr_state[2]; + int old_state = self->state; + int old_type = self->type; + int new_state = STATE_TRANSVR_UNEXCEPTED; + int new_type = TRANSVR_TYPE_ERROR; + int return_val = ERR_TRANSVR_UNEXCPT; + + /* Never initial */ + if (self->state == STATE_TRANSVR_NEW) { + goto comfsm_action_4_reinit_obj; + } + /* Detect current state */ + switch (detect_transvr_state(self, curr_state)) { + case 0: + new_state = curr_state[0]; + new_type = curr_state[1]; + break; + + case ERR_TRNASVR_BE_ISOLATED: + new_state = STATE_TRANSVR_ISOLATED; + new_type = old_type; + break; + + case ERR_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case ERR_TRANSVR_UNEXCPT: + default: + new_state = STATE_TRANSVR_UNEXCEPTED; + new_type = old_type; + } + /* State handling */ + switch (old_state) { + case STATE_TRANSVR_INIT: /* INIT -> */ + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 1-1: UP -> INIT */ + SWPS_INFO("Detect %s is present. :1-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 1-2: UP -> UP */ + return_val = 0; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 1-3: UP -> DOWN */ + SWPS_INFO("Detect %s is removed. :1-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 1-4: UP -> SWAP */ + SWPS_INFO("Detect %s is swapped. :1-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 1-5: UP -> UNEXPET */ + SWPS_INFO("Detect %s has error. :1-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 1-6: UP -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :1-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_DISCONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 2-1: DOWN -> INIT */ + SWPS_INFO("Detect %s is present. :2-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 2-2: DOWN -> UP */ + SWPS_INFO("Detect %s is present. :2-2\n",self->swp_name); + goto comfsm_action_4_reinit_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 2-3: DOWN -> DOWN */ + return_val = ERR_TRANSVR_UNPLUGGED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_SWAPPED: /* Case 2-4: DOWN -> SWAP */ + SWPS_INFO("Detect %s is swapped. :2-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 2-5: DOWN -> UNEXPET */ + SWPS_INFO("Detect %s has error. :2-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 2-6: DOWN -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :2-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_UNEXCEPTED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 3-1: UNEXPET -> INIT */ + SWPS_INFO("Detect %s is present. :3-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 3-2: UNEXPET -> UP */ + SWPS_INFO("Detect %s is present. :3-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 3-3: UNEXPET -> DOWN */ + SWPS_INFO("Detect %s is removed. :3-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 3-4: UNEXPET -> SWAP */ + SWPS_INFO("Detect %s is swapped. :3-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 3-5: UNEXPET -> UNEXPET */ + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRANSVR_UNEXCPT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 3-6: UNEXPET -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :3-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 4-1: ISOLATE -> INIT */ + SWPS_INFO("Detect %s internal error. :4-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 4-2: ISOLATE -> UP */ + SWPS_INFO("Detect %s internal error. :4-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 4-3: ISOLATE -> DOWN */ + SWPS_INFO("Detect %s is removed. :4-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 4-4: ISOLATE -> SWAP */ + SWPS_INFO("Detect %s internal error. :4-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 4-5: ISOLATE -> UNEXPET */ + SWPS_INFO("Detect %s internal error. :4-5\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 4-6: ISOLATE -> ISOLATE */ + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + default: + break; + } + goto comfsm_action_4_unexpected; + + default: + break; + } + goto comfsm_action_4_unexpected; + + +comfsm_action_4_keep_state: + return return_val; + +comfsm_action_4_reinit_obj: + SWPS_DEBUG("FSM action: %s re-initial.\n", self->swp_name); + return_val = _transvr_init_handler(self); + goto comfsm_action_4_identify_event; + +comfsm_action_4_reload_obj: + SWPS_DEBUG("FSM action: %s reload.\n", self->swp_name); + self->type = new_type; + return_val = reload_transvr_obj(self, new_type); + goto comfsm_action_4_identify_event; + +comfsm_action_4_identify_event: + switch (return_val) { + case EVENT_TRANSVR_INIT_UP: + case EVENT_TRANSVR_TASK_DONE: + goto comfsm_action_4_connected; + + case EVENT_TRANSVR_INIT_DOWN: + goto comfsm_action_4_disconnected; + + case EVENT_TRANSVR_INIT_REINIT: + goto comfsm_action_4_nothing; + + case EVENT_TRANSVR_TASK_WAIT: + self->state = STATE_TRANSVR_INIT; + return ERR_TRANSVR_TASK_BUSY; + + case EVENT_TRANSVR_TASK_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_TASK_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_INIT_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_INIT_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_RELOAD_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_RELOAD_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case EVENT_TRANSVR_EXCEP_ISOLATED: + goto comfsm_action_4_isolate_obj; + + default: + SWPS_INFO("%s detect undefined event:%d.\n", self->swp_name, return_val); + goto comfsm_action_4_unexpected; + } + +comfsm_action_4_nothing: + SWPS_DEBUG("FSM action: %s do nothing.\n", self->swp_name); + return 0; + +comfsm_action_4_connected: + SWPS_DEBUG("FSM action: %s Connected.\n", self->swp_name); + self->state = STATE_TRANSVR_CONNECTED; + self->type = new_type; + self->send_uevent(self, KOBJ_ADD); + _transvr_clean_retry(self); + return 0; + +comfsm_action_4_disconnected: + SWPS_DEBUG("FSM action: %s Disconnected. \n", self->swp_name); + self->state = STATE_TRANSVR_DISCONNECTED; + self->temp = EVENT_TRANSVR_TASK_DONE; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_retry(self); + _transvr_clean_handler(self); + return ERR_TRANSVR_UNPLUGGED; + +comfsm_action_4_report_i2c_crash: + SWPS_DEBUG("FSM action: %s report I2C crash.\n", self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_I2C_CRASH; + +comfsm_action_4_isolate_obj: + SWPS_DEBUG("FSM action: %s isolate.\n", self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return ERR_TRNASVR_BE_ISOLATED; + +comfsm_action_4_unexpected: + SWPS_INFO("FSM action: %s unexpected.\n", self->swp_name); + SWPS_INFO("Dump: :%d :0x%02x :%d :0x%02x\n", + old_state, old_type, new_state, new_type); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_handler(self); + 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; +} + + +int +fake_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + + +/* ========== Object functions for Initial procedure ========== + */ +int +transvr_init_common(struct transvr_obj_s *self){ + /* Nothing to update */ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_fake(struct transvr_obj_s *self){ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_sfp(struct transvr_obj_s *self){ + + int tmp_val = DEBUG_TRANSVR_INT_VAL; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_msg = "ERR"; + + self->info = sft_detect_transvr_class(self); + /* Disable auto_config */ + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + /* Handle multi-rate */ + err_code = initfunc_sfp_handle_multi_rate_mode(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_multi_rate_mode fail!"; + goto err_transvr_init_sfp_1; + } + /* Handle 1G- RJ45 */ + tmp_val = err_code; + err_code = initfunc_sfp_handle_1g_rj45(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_1g_rj45 fail!"; + goto err_transvr_init_sfp_1; + } + tmp_val = (tmp_val > err_code ? tmp_val : err_code); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_sfp_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_code, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp(struct transvr_obj_s *self){ + + int err = EVENT_TRANSVR_EXCEP_EXCEP; + char *emsg = "ERR"; + + self->info = qsft_detect_transvr_class(self); + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + err = initfunc_qsfp_handle_power_mode(self); + if (err < 0){ + emsg = "initfunc_qsfp_handle_tx_disable fail!"; + goto err_transvr_init_qsfp; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, emsg, err, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp28(struct transvr_obj_s *self){ + + int tmp_val = EVENT_TRANSVR_EXCEP_EXCEP; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_msg = "ERR"; + + /* Handle QSFP common */ + err_val = transvr_init_qsfp(self); + if (err_val < 0){ + err_msg = "transvr_init_qsfp fail!"; + goto err_transvr_init_qsfp28_1; + } + /* Disable auto_config */ + if (!self->auto_config) { + return err_val; + } + /* Handle CDR */ + tmp_val = err_val; + err_val = initfunc_qsfp28_handle_cdr(self); + if (err_val < 0){ + err_msg = "Handle CDR fail!"; + goto err_transvr_init_qsfp28_1; + } + tmp_val = (tmp_val > err_val ? tmp_val : err_val); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp28_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +/* ========== 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 +_is_transvr_support_ctle(struct transvr_obj_s *self) { + + switch (self->info) { + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return 1; + default: + break; + } + return 0; +} + + +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; + } + if (self->clean == NULL) { + snprintf(emsg, elimit, "clean() is null"); + goto initer_err_case_unexcept_0; + } + self->clean(self); + + /* 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_1; + } + + /* 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_1; + } + } + + /* 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_1; + } + + /* 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_1; + } + goto initer_ok_case_up; + + +initer_ok_case_wait: + self->dump_all(self); + return EVENT_TRANSVR_TASK_WAIT; + +initer_ok_case_up: + self->state = STATE_TRANSVR_CONNECTED; + self->temp = 0; + self->dump_all(self); + 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_1: + self->clean(self); +initer_err_case_unexcept_0: + self->state = STATE_TRANSVR_UNEXCEPTED; + if (_is_except_happened_4_pmode(self, d_state) && + (self->mode == TRANSVR_MODE_POLLING) ){ + SWPS_INFO("%s: %s :%s\n", __func__, emsg, self->swp_name); + SWPS_INFO("Dump: :%d :%d :%d :%d\n", + self->state, self->type, d_state, d_type); + } + 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; +} + + +/* ========== Object functions for Clean procedure ========== + */ +int +_transvr_clean_handler(struct transvr_obj_s *self){ + + int retval = DEBUG_TRANSVR_INT_VAL; + + if (!self->clean) { + SWPS_ERR("%s: %s clean() is NULL.\n", + __func__, self->swp_name); + return EVENT_TRANSVR_TASK_FAIL; + } + retval = self->clean(self); + if (retval != EVENT_TRANSVR_TASK_DONE){ + SWPS_ERR("%s: %s clean() fail. [ERR]:%d\n", + __func__, self->swp_name, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +common_transvr_clean(struct transvr_obj_s *self){ + + transvr_task_free_all(self); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +qsfp_transvr_clean(struct transvr_obj_s *self){ + + int retval; + int lpower_config = 1; + + retval = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (retval < 0){ + SWPS_ERR("%s: Set lpmod fail! :%d\n", + __func__, retval); + return retval; + } + retval = common_transvr_clean(self); + if (retval < 0){ + SWPS_ERR("%s: common_transvr_clean fail! :%d\n", + __func__, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +fake_transvr_clean(struct transvr_obj_s *self){ + + return EVENT_TRANSVR_TASK_DONE; +} + + +/* ========== Object functions for check and update ========== + */ +int +common_transvr_check(struct transvr_obj_s *self){ + + char fun_str[32] = "common_transvr_check"; + + if (self->mode != TRANSVR_MODE_POLLING) { + SWPS_ERR("%s: mode:%d is not TRANSVR_MODE_POLLING\n", + fun_str, self->mode); + return ERR_TRANSVR_UNEXCPT; + } + /* Trigger delay task */ + transvr_task_run_all(self); + /* Trigger state machine to check and update */ + return self->fsm_4_polling(self, fun_str); +} + + +int +fake_transvr_check(struct transvr_obj_s *self){ + return 0; +} + + +/* ========== Functions for Factory pattern ========== + */ +static int +setup_transvr_public_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = unsupported_get_func; + self->get_br = common_get_br; + self->get_len_sm = sfp_get_len_sm; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = sfp_get_comp_eth_1; + self->get_comp_eth_10 = sfp_get_comp_eth_10; + self->get_comp_eth_10_40 = unsupported_get_func; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = sfp_get_rate_id; + self->get_soft_rs0 = sfp_get_soft_rs0; + self->get_soft_rs1 = sfp_get_soft_rs1; + self->get_info = common_get_info; + self->get_if_type = sfp_get_if_type; + self->get_if_speed = sfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = sfp_get_transvr_temp; + self->get_curr_vol = sfp_get_transvr_voltage; + self->get_soft_rx_los = unsupported_get_func2; + self->get_soft_tx_disable = unsupported_get_func2; + self->get_soft_tx_fault = unsupported_get_func2; + self->get_auto_tx_disable = unsupported_get_func2; + self->get_tx_bias = sfp_get_transvr_tx_bias; + self->get_tx_power = sfp_get_transvr_tx_power; + self->get_rx_power = sfp_get_transvr_rx_power; + self->get_tx_eq = sfp_get_transvr_tx_eq; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = sfp_get_transvr_rx_em; + self->get_wavelength = sfp_get_wavelength; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = sfp_set_soft_rs0; + self->set_soft_rs1 = sfp_set_soft_rs1; + self->set_soft_tx_disable = unsupported_set_func; + self->set_auto_tx_disable = unsupported_set_func; + self->set_tx_eq = sfp_set_tx_eq; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = sfp_set_rx_em; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = unsupported_get_func2; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = unsupported_get_func2; + self->get_wavelength = qsfp_get_wavelength; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = unsupported_set_func; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = qsfp_get_cdr; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = qsfp_get_transvr_tx_eq; + self->get_rx_am = qsfp_get_transvr_rx_am; + self->get_rx_em = qsfp_get_transvr_rx_em; + self->get_wavelength = qsfp_get_wavelength; + self->set_cdr = qsfp_set_cdr; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = qsfp_set_tx_eq; + self->set_rx_am = qsfp_set_rx_am; + self->set_rx_em = qsfp_set_rx_em; + return 0; + + case TRANSVR_TYPE_FAKE: + self->get_id = fake_get_hex; + self->get_ext_id = fake_get_hex; + self->get_connector = fake_get_hex; + self->get_vendor_name = fake_get_str; + self->get_vendor_pn = fake_get_str; + self->get_vendor_rev = fake_get_str; + self->get_vendor_sn = fake_get_str; + self->get_power_cls = fake_get_int; + self->get_br = fake_get_hex; + self->get_len_sm = fake_get_int; + self->get_len_smf = fake_get_int; + self->get_len_om1 = fake_get_int; + self->get_len_om2 = fake_get_int; + self->get_len_om3 = fake_get_int; + self->get_len_om4 = fake_get_int; + self->get_comp_rev = fake_get_hex; + self->get_comp_eth_1 = fake_get_hex; + self->get_comp_eth_10 = fake_get_hex; + self->get_comp_eth_10_40 = fake_get_hex; + self->get_comp_extend = fake_get_hex; + self->get_cdr = fake_get_hex; + self->get_rate_id = fake_get_hex; + self->get_soft_rs0 = fake_get_binary; + self->get_soft_rs1 = fake_get_binary; + self->get_info = fake_get_int; + self->get_if_type = fake_get_str; + self->get_if_speed = fake_get_str; + self->get_if_lane = fake_get_str; + self->get_curr_temp = fake_get_str; + self->get_curr_vol = fake_get_str; + self->get_soft_rx_los = fake_get_str; + self->get_soft_tx_disable = fake_get_str; + self->get_soft_tx_fault = fake_get_str; + self->get_auto_tx_disable = fake_get_str; + self->get_tx_bias = fake_get_str; + self->get_tx_power = fake_get_str; + self->get_rx_power = fake_get_str; + self->get_tx_eq = fake_get_str; + self->get_rx_am = fake_get_str; + self->get_rx_em = fake_get_str; + self->get_wavelength = fake_get_str; + self->set_cdr = fake_set_hex; + self->set_soft_rs0 = fake_set_int; + self->set_soft_rs1 = fake_set_int; + self->set_soft_tx_disable = fake_set_int; + self->set_auto_tx_disable = fake_set_int; + self->set_tx_eq = fake_set_int; + self->set_rx_am = fake_set_int; + self->set_rx_em = fake_set_int; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static int +setup_transvr_private_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->init = transvr_init_sfp; + self->clean = common_transvr_clean; + self->check = common_transvr_check; + self->update_all = _sfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = sfp_send_uevent; + self->dump_all = sfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->init = transvr_init_qsfp; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->init = transvr_init_qsfp28; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_FAKE: + self->init = transvr_init_fake; + self->clean = fake_transvr_clean; + self->check = fake_transvr_check; + self->update_all = fake_transvr_update; + self->fsm_4_direct = fake_fsm_4_direct_mode; + self->fsm_4_polling = fake_fsm_4_polling_mode; + self->send_uevent = fake_send_uevent; + self->dump_all = fake_transvr_dump; + 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_SFP: + return &eeprom_map_sfp; + 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 */ + case TRANSVR_MODE_POLLING: /* Polling mode, read from cache */ + 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_transvr_dsize_attr(struct transvr_obj_s *self){ + + char *emsg = DEBUG_TRANSVR_STR_VAL; + + self->vendor_name = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_name){ + emsg = "vendor_name"; + goto err_setup_d_attr; + } + self->vendor_pn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_pn){ + emsg = "vendor_pn"; + goto err_setup_d_attr; + } + self->vendor_rev = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_rev){ + emsg = "vendor_rev"; + goto err_setup_d_attr; + } + self->vendor_sn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_sn){ + emsg = "vendor_sn"; + goto err_setup_d_attr; + } + self->worker_p = NULL; + return 0; + +err_setup_d_attr: + SWPS_ERR("%s: %s kzalloc fail!", __func__, emsg); + return ERR_TRANSVR_UNEXCPT; +} + + +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 dynamic size attributes */ + if (setup_transvr_dsize_attr(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_public_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_private_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare i2c client object */ + if (setup_i2c_client(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + return result_p; + +err_create_transvr_dattr_fail: + kfree(result_p->vendor_sn); + kfree(result_p->vendor_rev); + kfree(result_p->vendor_pn); + kfree(result_p->vendor_name); +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; + } + /* Replace call back functions */ + if (setup_transvr_public_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + 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; +} + + +int +isolate_transvr_obj(struct transvr_obj_s *self) { + + self->state = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s be isolated\n", __func__, self->swp_name); + return 0; +} + + +int +resync_channel_tier_2(struct transvr_obj_s *self) { + + int val = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_ISOLATED) { + return 0; + } + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + val = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (val < 0) { + return -1; + } + return 0; +} + + +/* ----------------------------------------- + * ToDo List + * ----------------------------------------- + * 1. _sfp_detect_class_by_feature() + * => Need check ACC use case. + * 2. _sfp_detect_class_by_1g_ethernet() + * => Need check 0.1G use case. + * 3. Loopback transceiver use case. + * => Less much data + * 4. _qsfp_detect_class_by_extend_comp() + * => Verify 100G CWDM4 + * => Verify Obsolete (assigned before 100G CWDM4 MSA required FEC) + * => Verify 100G CLR4 + * => Verify 100GE-DWDM2 + * => Verify 40G PSM4 Parallel SMF + * => Verify 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. + * => Verify 100G ACC or 25GAUI C2M ACC. + * => Verify 25GBASE-LR + * => Verify 40G Active Cable (XLPPI) + */ + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.h new file mode 100644 index 000000000000..ddd22c38caf0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.h @@ -0,0 +1,792 @@ +#ifndef TRANSCEIVER_H +#define TRANSCEIVER_H + +#include + +/* advanced features control */ +#define TRANSVR_INFO_DUMP_ENABLE (1) +#define TRANSVR_INFO_CACHE_ENABLE (1) +#define TRANSVR_UEVENT_ENABLE (1) + +/* 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 class for base info */ +#define TRANSVR_CLASS_UNSPECIFIED (0) +#define TRANSVR_CLASS_ERROR (-26001) +#define TRANSVR_CLASS_1G (26001) +#define TRANSVR_CLASS_10G (26011) +#define TRANSVR_CLASS_25G (26021) +#define TRANSVR_CLASS_40G (26041) +#define TRANSVR_CLASS_100G (26101) +#define TRANSVR_CLASS_NO_SPERARABLE (26901) +#define TRANSVR_CLASS_EXTEND_COMP (26902) +/* Transceiver class for Optical 1G */ +#define TRANSVR_CLASS_OPTICAL (27000) +#define TRANSVR_CLASS_OPTICAL_100 (27001) +#define TRANSVR_CLASS_OPTICAL_1G (27002) +#define TRANSVR_CLASS_OPTICAL_1G_AOC (27003) +#define TRANSVR_CLASS_OPTICAL_1G_SX (27004) +#define TRANSVR_CLASS_OPTICAL_1G_LX (27005) +#define TRANSVR_CLASS_OPTICAL_1G_EX (27006) +/* Transceiver class for Optical 10G */ +#define TRANSVR_CLASS_OPTICAL_10G (27010) +#define TRANSVR_CLASS_OPTICAL_10G_S_AOC (27011) +#define TRANSVR_CLASS_OPTICAL_10G_S_SR (27012) +#define TRANSVR_CLASS_OPTICAL_10G_S_LR (27013) +#define TRANSVR_CLASS_OPTICAL_10G_S_ER (27014) +#define TRANSVR_CLASS_OPTICAL_10G_Q_AOC (27015) +#define TRANSVR_CLASS_OPTICAL_10G_Q_SR (27016) +#define TRANSVR_CLASS_OPTICAL_10G_Q_LR (27017) +#define TRANSVR_CLASS_OPTICAL_10G_Q_ER (27018) +/* Transceiver class for Optical 25G */ +#define TRANSVR_CLASS_OPTICAL_25G (27020) +#define TRANSVR_CLASS_OPTICAL_25G_AOC (27021) +#define TRANSVR_CLASS_OPTICAL_25G_SR (27022) +#define TRANSVR_CLASS_OPTICAL_25G_LR (27023) +#define TRANSVR_CLASS_OPTICAL_25G_ER (27024) +/* Transceiver class for Optical 40G */ +#define TRANSVR_CLASS_OPTICAL_40G (27040) +#define TRANSVR_CLASS_OPTICAL_40G_AOC (27041) +#define TRANSVR_CLASS_OPTICAL_40G_SR4 (27042) +#define TRANSVR_CLASS_OPTICAL_40G_LR4 (27043) +#define TRANSVR_CLASS_OPTICAL_40G_ER4 (27044) +/* Transceiver class for Optical 100G */ +#define TRANSVR_CLASS_OPTICAL_100G (27100) +#define TRANSVR_CLASS_OPTICAL_100G_AOC (27101) +#define TRANSVR_CLASS_OPTICAL_100G_SR4 (27102) +#define TRANSVR_CLASS_OPTICAL_100G_LR4 (27103) +#define TRANSVR_CLASS_OPTICAL_100G_ER4 (27104) +#define TRANSVR_CLASS_OPTICAL_100G_PSM4 (27105) +/* Transceiver class for Copper */ +#define TRANSVR_CLASS_COPPER (28000) +#define TRANSVR_CLASS_COPPER_L1_1G (28001) +#define TRANSVR_CLASS_COPPER_L1_10G (28011) +#define TRANSVR_CLASS_COPPER_L4_10G (28012) +#define TRANSVR_CLASS_COPPER_L1_25G (28021) +#define TRANSVR_CLASS_COPPER_L4_40G (28041) +#define TRANSVR_CLASS_COPPER_L4_100G (28101) +/* Transceiver class for Base-T */ +#define TRANSVR_CLASS_BASE_T_1000 (29001) +#define TRANSVR_CLASS_BASE_T_1000_up (29002) +/* For uevent message */ +#define TRANSVR_UEVENT_KEY_IF "IF_TYPE" +#define TRANSVR_UEVENT_KEY_SP "IF_SPEED" +#define TRANSVR_UEVENT_KEY_LANE "IF_LANE" +#define TRANSVR_UEVENT_UNKNOW "UNKNOW" +#define TRANSVR_IF_KR "KR" +#define TRANSVR_IF_KR4 "KR4" +#define TRANSVR_IF_SR "SR" +#define TRANSVR_IF_SR4 "SR4" +#define TRANSVR_IF_SFI "SFI" +#define TRANSVR_IF_IF_GMII "GMII" +#define TRANSVR_IF_IF_XGMII "XGMII" +#define TRANSVR_IF_SP_100 "100" +#define TRANSVR_IF_SP_1G "1000" +#define TRANSVR_IF_SP_10G "10000" +#define TRANSVR_IF_SP_25G "25000" +#define TRANSVR_IF_SP_40G "40000" +#define TRANSVR_IF_SP_100G "100000" + +/* Transceiver mode define */ +#define TRANSVR_MODE_DIRECT (21000) +#define TRANSVR_MODE_POLLING (21001) + +/* 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. */ + +/* Task state define */ +#define STATE_T_TASK_WAIT (110) +#define STATE_T_TASK_DONE (0) +#define STATE_T_TASK_INIT (-110) +#define STATE_T_TASK_FAIL (-410) + + +/* 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_UEVENT_FAIL (-213) +#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_SFP "SFP" +#define STR_TRANSVR_QSFP "QSFP" +#define STR_TRANSVR_QSFP_PLUS "QSFP+" +#define STR_TRANSVR_QSFP28 "QSFP28" + +/* For transvr buf len */ +#define LEN_TRANSVR_S_STR (16) +#define LEN_TRANSVR_M_STR (32) +#define LEN_TRANSVR_L_STR (64) + +/* Optical wavelength */ +#define VAL_OPTICAL_WAVELENGTH_SR (850) +#define VAL_OPTICAL_WAVELENGTH_LR (1310) +#define VAL_OPTICAL_WAVELENGTH_ER (1550) + +/* BCM chip type define */ +#define BCM_CHIP_TYPE_TRIDENT_2 (31001) /* Magnolia, Hudson32i, Spruce */ +#define BCM_CHIP_TYPE_TOMAHAWK (31002) /* Redwood, Cypress */ + +/* Info from transceiver EEPROM */ +struct eeprom_map_s { + int addr_br; int page_br; int offset_br; int length_br; + int addr_cdr; int page_cdr; int offset_cdr; int length_cdr; + int addr_comp_rev; int page_comp_rev; int offset_comp_rev; int length_comp_rev; + int addr_connector; int page_connector; int offset_connector; int length_connector; + int addr_diag_type; int page_diag_type; int offset_diag_type; int length_diag_type; + int addr_extbr; int page_extbr; int offset_extbr; int length_extbr; + int addr_ext_id; int page_ext_id; int offset_ext_id; int length_ext_id; + int addr_id; int page_id; int offset_id; int length_id; + int addr_len_sm; int page_len_sm; int offset_len_sm; int length_len_sm; + int addr_len_smf; int page_len_smf; int offset_len_smf; int length_len_smf; + int addr_len_om1; int page_len_om1; int offset_len_om1; int length_len_om1; + int addr_len_om2; int page_len_om2; int offset_len_om2; int length_len_om2; + int addr_len_om3; int page_len_om3; int offset_len_om3; int length_len_om3; + int addr_len_om4; int page_len_om4; int offset_len_om4; int length_len_om4; + int addr_option; int page_option; int offset_option; int length_option; + int addr_rate_id; int page_rate_id; int offset_rate_id; int length_rate_id; + int addr_rx_am; int page_rx_am; int offset_rx_am; int length_rx_am; + int addr_rx_em; int page_rx_em; int offset_rx_em; int length_rx_em; + int addr_rx_los; int page_rx_los; int offset_rx_los; int length_rx_los; + int addr_rx_power; int page_rx_power; int offset_rx_power; int length_rx_power; + int addr_soft_rs0; int page_soft_rs0; int offset_soft_rs0; int length_soft_rs0; + int addr_soft_rs1; int page_soft_rs1; int offset_soft_rs1; int length_soft_rs1; + int addr_temp; int page_temp; int offset_temp; int length_temp; + int addr_trancomp; int page_trancomp; int offset_trancomp; int length_trancomp; + int addr_trancomp_ext; int page_trancomp_ext; int offset_trancomp_ext; int length_trancomp_ext; + int addr_tx_bias; int page_tx_bias; int offset_tx_bias; int length_tx_bias; + int addr_tx_disable; int page_tx_disable; int offset_tx_disable; int length_tx_disable; + int addr_tx_eq; int page_tx_eq; int offset_tx_eq; int length_tx_eq; + int addr_tx_fault; int page_tx_fault; int offset_tx_fault; int length_tx_fault; + int addr_tx_power; int page_tx_power; int offset_tx_power; int length_tx_power; + int addr_vendor_name; int page_vendor_name; int offset_vendor_name; int length_vendor_name; + int addr_vendor_pn; int page_vendor_pn; int offset_vendor_pn; int length_vendor_pn; + int addr_vendor_rev; int page_vendor_rev; int offset_vendor_rev; int length_vendor_rev; + int addr_vendor_sn; int page_vendor_sn; int offset_vendor_sn; int length_vendor_sn; + int addr_voltage; int page_voltage; int offset_voltage; int length_voltage; + int addr_wavelength; int page_wavelength; int offset_wavelength; int length_wavelength; +}; + + +struct transvr_worker_s; + +/* Class of transceiver object */ +struct transvr_obj_s { + + /* ========== Object private property ========== + * [Prop]: id + * [Desc]: Type of serial transceiver. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh /QSFP28:11h + */ + uint8_t id; + + /* [Prop]: connector + * [Desc]: Connector type. + * [Note]: SFP : A0h / 2 + * QSFP: 00h / 130 + */ + uint8_t connector; + + /* [Prop]: transvr_comp + * [Desc]: Transceiver compliance code. + * [Note]: SFP: SFF-8472 + * - Normal : A0h / offset 3-10 + * - Extended: A0h / offset 36 + * QSFP: SFF-8436 & SFF-8636 + * - Normal : 00h / offset 131-138 + * - Extended: 00h / offset 192 + */ + uint8_t transvr_comp[8]; + uint8_t transvr_comp_ext; + + /* [Prop]: vendor_name + * [Desc]: SFP vendor name (ASCII 16 byte char). + * [Note]: ex:FINISAR CORP. + */ + char *vendor_name; + + /* [Prop]: vendor_pn + * [Desc]: Part number provided by SFP vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_pn; + + /* [Prop]: vendor_rev + * [Desc]: Revision level for part number provided by vendor (ASCII 4 byte char). + * [Note]: + */ + char *vendor_rev; + + /* [Prop]: vendor_sn + * [Desc]: Serial number provided by vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_sn; + + /* [Prop]: Extended identifier + * [Desc]: SFP: + * => None + * + * QSFP: + * => This byte contained two information: + * (1) Power consumption class + * (2) CDR function present + * [Note]: Bit description as below: + * [SFP] + * None + * + * [QSFP] + * (1) Power consumption class: + * Class 1: 1.5W (Bit6-7 = 00:) + * Class 2: 2.0W (Bit6-7 = 01:) + * Class 3: 2.5W (Bit6-7 = 10:) + * Class 4: 3.5W (Bit6-7 = 11:) + * Class 5: 4.0W (Bit0-1 = 01:) + * Class 6: 4.5W (Bit0-1 = 10:) + * Class 7: 5.0W (Bit0-1 = 11:) + * (2) CDR function present: + * Bit2: 0 = No CDR in RX + * 1 = CDR present in RX + * Bit3: 0 = No CDR in TX + * 1 = CDR present in TX + */ + uint8_t ext_id; + + /* [Prop]: br + * [Desc]: Nominal bit rate, units of 100 MBits/sec. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh + * has val: 0x67 + * no val : + */ + uint8_t br; + + /* [Prop]: extbr + * [Desc]: Extended br (00h/222) + * [Desc]: Nominal bit rate per channel, units of 250 Mbps. + * Complements. Byte 140. See Table 32A. + */ + uint8_t extbr; + + /* [Prop]: len_sm + * [Desc]: Length (single mode)-(100's)m + * [Note]: This value specifies the link length that is supported by the transceiver + * while operating in compliance with the applicable standards using single mode + * fiber. The value is in units of 100 meters. A value of 255 means that the + * transceiver supports a link length greater than 25.4 km. A value of zero means + * that the transceiver does not support single mode fiber or that the length + * information must be determined from the transceiver technology. + */ + int len_sm; + + /* [Prop]: len_smf + * [Desc]: Length (single mode)-km + * [Note]: Addition to EEPROM data from original GBIC definition. This value specifies + * the link length that is supported by the transceiver while operating in + * compliance with the applicable standards using single mode fiber. The value + * is in units of kilometers. A value of 255 means that the transceiver supports + * a link length greater than 254 km. A value of zero means that the transceiver + * does not support single mode fiber or that the length information must be + * determined from the transceiver technology. + */ + int len_smf; + + /* [Prop]: len_om1 + * [Desc]: Link length supported for 62.5 um OM1 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om1; + + /* [Prop]: len_om2 + * [Desc]: Link length supported for 50 um OM2 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om2; + + /* [Prop]: len_om3 + * [Desc]: Length (50um, OM3) + * [Note]: This value specifies link length that is supported by the transceiver while + * operating in compliance with applicable standards using 50 micron multimode + * OM3 [2000 MHz*km] fiber. The value is in units of 10 meters. A value of 255 + * means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber + * or that the length information must be determined from the transceiver technology. + */ + int len_om3; + + /* [Prop]: len_om4 + * [Desc]: Length (50um, OM4) and Length (Active Cable or Copper) + * [Note]: For optical links, this value specifies link length that is supported by the + * transceiver while operating in compliance with applicable standards using 50 micron + * multimode OM4 [4700 MHz*km] fiber. The value is in units of 10 meters. A value of + * 255 means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber or that + * the length information must be determined from the transceiver codes specified in Table 5-3. + * + * For copper links, this value specifies minimum link length supported by the transceiver + * while operating in compliance with applicable standards using copper cable. For active + * cable, this value represents actual length. The value is in units of 1 meter. A value of 255 + * means the transceiver supports a link length greater than 254 meters. A value of zero means + * the transceiver does not support copper or active cables or the length information must be + * determined from transceiver technology. Further information about cable design, equalization, + * and connectors is usually required to guarantee meeting a particular length requirement. + */ + int len_om4; + + /* [Prop]: comp_rev + * [Desc]: SFF spec revision compliance + * [Note]: Indicates which revision of SFF SFF-8472 (SFP) / SFF-8636 (QSFP) the transceiver + * complies with. (unsigned integer) + */ + uint8_t comp_rev; + + /* [Prop]: CDR + * [Desc]: For transceivers with CDR capability, setting the CDR to ON engages the internal + * retiming function. Setting the CDR to OFF enables an internal bypassing mode ,which + * directs traffic around the internal CDR. (Reference: SFF-8636) + * [Note]: value=0xff: ON. + * value=0x00: OFF. + */ + uint8_t cdr; + + /* [Prop]: rate_id + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Addr: A0h / Offset: 13 + * 2. Value description: + * 00h Unspecified + * 01h SFF-8079 (4/2/1G Rate_Select & AS0/AS1) + * 02h SFF-8431 (8/4/2G Rx Rate_Select only) + * 03h Unspecified * + * 04h SFF-8431 (8/4/2G Tx Rate_Select only) + * 05h Unspecified * + * 06h SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) + * 07h Unspecified * + * 08h FC-PI-5 (16/8/4G Rx Rate_select only) High=16G only, Low=8G/4G + * 09h Unspecified * + * 0Ah FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) High=16G only, + * Low=8G/4G + * 0Bh Unspecified * + * 0Ch FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + * 0Dh Unspecified * + * 0Eh 10/8G Rx and Tx Rate_Select controlling the operation or locking + * modes of the internal signal conditioner, retimer or CDR, according + * to the logic table defined in Table 10-2, High Bit Rate + * (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = 8.5 Gb/s. In this mode, + * the default value of bit 110.3 (Soft Rate Select RS(0), Table 9-11) + * and of bit 118.3 (Soft Rate Select RS(1), Table 10-1) is 1. + * 0Fh Unspecified * + * 10h-FFh Unallocated + */ + int rate_id; + + /* [Prop]: soft_rs0 + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Writing '1' selects full bandwidth operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(0) or RS(0) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 110 / Bit: 3 + */ + uint8_t soft_rs0; + + /* [Prop]: soft_rs1 + * [Desc]: Soft Rate Select 1(TX). + * [Note]: 1. Writing '1' selects full bandwidth TX operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(1) or RS(1) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 118 / Bit: 3 + */ + uint8_t soft_rs1; + + /* [Prop]: diag_type + * [Desc]: DIAGNOSTIC MONITORING TYPE (A0h/92) + * [Note]: Description in SFF-8472 as below: + * Bit7: Reserved for legacy diagnostic implementations. Must be '0' for compliance + * with this document. + * Bit6: Digital diagnostic monitoring implemented (described in this document). + * Must be '1' for compliance with this document. + * Bit5 Internally calibrated + * Bit4 Externally calibrated + * Bit3 Received power measurement type.0 = OMA, 1 = average power + * Bit2 Address change required see section above, "addressing modes" + * Bit1-0 Unallocated + */ + uint8_t diag_type; + + /* [Prop]: curr_temp + * [Desc]: Transceiver Current Temperature (A2h/96-97) + * [Note]: 1. Dependent on diag_type. + * 2. 96: High byte + * 3. 97: Low byte + * 4. This feature only for SFP + */ + uint8_t curr_temp[2]; + + /* [Prop]: curr_vol + * [Desc]: Transceiver Current Voltage (SFP:A2h/108-109; QSFP:00h/22-23) + * [Note]: 1. Dependent on diag_type. + * 2. 98: High byte + * 3. 99: Low byte + * 4. This feature only for SFP + * 5. Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts + */ + uint8_t curr_voltage[2]; + + /* [Prop]: curr_tx_bias + * [Desc]: Transceiver TX Bias Current (SFP:A2h/100-101; QSFP:00h/26-27) + * [Note]: 1. Dependent on diag_type. + * 2. 100: High byte + * 3. 101: Low byte + * 4. This feature only for SFP + * 5. Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + uint8_t curr_tx_bias[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + uint8_t curr_tx_power[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + uint8_t curr_rx_power[8]; + + /* [Prop]: wavelength + * [Desc]: Wavelength or Copper Cable Attenuation + * [Note]: (Following is info from SFF-8636) + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is a + * 16-bit hex value with Byte 186 as high order byte and Byte 187 as low + * order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. If the free side device is identified as + * copper cable these registers will be used to define the cable attenuation. + * An indication of 0 dB attenuation refers to the case where the attenuation + * is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + uint8_t wavelength[2]; + + /* [Prop]: Amplitude control + * [Desc]: Amplitude control + * [Note]: QSFP28 => SFF-8636 03H Byte-238/239 + */ + uint8_t rx_am[2]; + + /* [Prop]: Emphasis control + * [Desc]: Emphasis control + * [Note]: SFP+/28 => SFF-8472 A2H Byte-115 + * QSFP28 => SFF-8636 03H Byte-236/237 + */ + uint8_t rx_em[2]; + + /* [Prop]: Soft Rx LOS + * [Desc]: Soft Rx LOS which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 3: + * - Bit 0: L-Rx1 LOS + * - Bit 1: L-Rx2 LOS + * - Bit 2: L-Rx3 LOS + * - Bit 3: L-Rx4 LOS + */ + uint8_t rx_los; + + /* [Prop]: Soft Tx Disable + * [Desc]: Soft Tx Disable which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Disable + * - Bit 1: Tx2 Disable + * - Bit 2: Tx3 Disable + * - Bit 3: Tx4 Disable + */ + uint8_t tx_disable; + + /* [Prop]: Soft Tx Fault + * [Desc]: Soft Tx Fault which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Fault + * - Bit 1: Tx2 Fault + * - Bit 2: Tx3 Fault + * - Bit 3: Tx4 Fault + */ + uint8_t tx_fault; + + /* [Prop]: Transceiver EQUALIZATION + * [Desc]: Transceiver EQUALIZATION + * [Note]: SFP+/28 => SFF-8472 A2H Byte-114 + * QSFP28 => SFF-8636 03H Byte-234/235 + */ + uint8_t tx_eq[2]; + + /* [Prop]: OPTION VALUES + * [Desc]: The bits in the option field shall specify the options implemented in the transceiver. + * [Note]: SFP+/28 => SFF-8472 A0H Byte-64/65 + * QSFP+/28 => SFF-8636 00H Byte-193/195 + */ + uint8_t option[3]; + + + /* ========== 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 transvr_worker_s *worker_p; + struct mutex lock; + char swp_name[32]; + int auto_config; + 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 public functions ========== + */ + int (*get_id)(struct transvr_obj_s *self); + int (*get_ext_id)(struct transvr_obj_s *self); + int (*get_connector)(struct transvr_obj_s *self); + int (*get_vendor_name)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_pn)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_rev)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_sn)(struct transvr_obj_s *self, char *buf_p); + int (*get_power_cls)(struct transvr_obj_s *self); + int (*get_br)(struct transvr_obj_s *self); + int (*get_len_sm)(struct transvr_obj_s *self); + int (*get_len_smf)(struct transvr_obj_s *self); + int (*get_len_om1)(struct transvr_obj_s *self); + int (*get_len_om2)(struct transvr_obj_s *self); + int (*get_len_om3)(struct transvr_obj_s *self); + int (*get_len_om4)(struct transvr_obj_s *self); + int (*get_comp_rev)(struct transvr_obj_s *self); + int (*get_comp_eth_1)(struct transvr_obj_s *self); + int (*get_comp_eth_10)(struct transvr_obj_s *self); + int (*get_comp_eth_10_40)(struct transvr_obj_s *self); + int (*get_comp_extend)(struct transvr_obj_s *self); + int (*get_cdr)(struct transvr_obj_s *self); + int (*get_rate_id)(struct transvr_obj_s *self); + int (*get_soft_rs0)(struct transvr_obj_s *self); + int (*get_soft_rs1)(struct transvr_obj_s *self); + int (*get_info)(struct transvr_obj_s *self); + int (*get_if_type)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_speed)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_lane)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_temp)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_vol)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_rx_los)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_fault)(struct transvr_obj_s *self, char *buf_p); + int (*get_auto_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_bias)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_eq)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_am)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_em)(struct transvr_obj_s *self, char *buf_p); + int (*get_wavelength)(struct transvr_obj_s *self, char *buf_p); + int (*set_cdr)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs0)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs1)(struct transvr_obj_s *self, int input_val); + int (*set_soft_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_auto_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_tx_eq)(struct transvr_obj_s *self, int input_val); + int (*set_rx_am)(struct transvr_obj_s *self, int input_val); + int (*set_rx_em)(struct transvr_obj_s *self, int input_val); + + /* ========== Object private functions ========== + */ + int (*init)(struct transvr_obj_s *self); + int (*clean)(struct transvr_obj_s *self); + int (*check)(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); + int (*fsm_4_polling)(struct transvr_obj_s* self, char *caller_name); + int (*send_uevent)(struct transvr_obj_s* self, enum kobject_action u_action); + int (*dump_all)(struct transvr_obj_s* self); +}; + + +/* For AVL Mapping */ +struct transvr_avl_s { + char vendor_name[32]; + char vendor_pn[32]; + int (*init)(struct transvr_obj_s *self); +}; + + +/* Worker for long term task of transceiver */ +struct transvr_worker_s { + /* Task Parameter */ + struct transvr_obj_s *transvr_p; + struct transvr_worker_s *next_p; + struct transvr_worker_s *pre_p; + unsigned long trigger_time; + char func_name[64]; + int retry; + int state; + + /* Task private data */ + void *p_data; + + /* Call back function */ + int (*main_task)(struct transvr_worker_s *task); + int (*post_task)(struct transvr_worker_s *task); +}; + + +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 lock_transvr_obj(struct transvr_obj_s *self); +void unlock_transvr_obj(struct transvr_obj_s *self); +int isolate_transvr_obj(struct transvr_obj_s *self); + +int resync_channel_tier_2(struct transvr_obj_s *self); + +void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg); + +#endif /* TRANSCEIVER_H */ + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/utils/inventec_d7264_util.py b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/utils/inventec_d7264_util.py new file mode 100755 index 000000000000..fea26decf2a5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/utils/inventec_d7264_util.py @@ -0,0 +1,242 @@ +#!/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 "[D7264]"+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 =[ +'gpio-ich', +'lpc_ich', +'i2c-i801', +'i2c-mux', +'i2c-mux-pca954x', +'i2c-dev', +'inv_eeprom', +'inv_platform', +'inv_psoc', +'inv_cpld', +'inv_pthread', +'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(10,17): + 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(18,25): + 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 + for i in range(26,33): + 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(34,41): + 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(42,49): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-6/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(50,57): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-7/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(58,65): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-8/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(66,73): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-9/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 " D7264 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/debian/changelog b/platform/broadcom/sonic-platform-modules-inventec/debian/changelog new file mode 100644 index 000000000000..46aebb02ec8e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/changelog @@ -0,0 +1,25 @@ +sonic-inventec-platform-modules (1.1.0) unstable; urgency=low + * Add support for Inventec d7264 + + -- alvin lin Thu, 12 Jul 2018 16:00:00 +0800 + +sonic-inventec-platform-modules (1.1.0) unstable; urgency=low + * Add support for Inventec d6556 + + -- alvin lin Thu, 12 Jul 2018 16:00:00 +0800 + +sonic-inventec-platform-modules (1.1.0) unstable; urgency=low + * Add support for Inventec d6254 + + -- alvin lin Wed, 09 May 2018 16:00:00 +0800 + +sonic-inventec-platform-modules (1.1.0) unstable; urgency=low + * Add support for Inventec d7054 + + -- developer Tue, 18 Jul 2017 16:30:45 +0800 + +sonic-inventec-platform-modules (1.0.0) unstable; urgency=low + + * Add support for Inventec d7032 + + -- developer Wed, 05 Oct 2016 16:30:45 +0800 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/compat b/platform/broadcom/sonic-platform-modules-inventec/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/control b/platform/broadcom/sonic-platform-modules-inventec/debian/control new file mode 100644 index 000000000000..464211650fa9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/control @@ -0,0 +1,31 @@ +Source: sonic-inventec-platform-modules +Section: main +Priority: extra +Maintainer: Inventec +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-d7032q28b +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led + +Package: platform-modules-d7054q28b +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led + +Package: platform-modules-d6254qs +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led + +Package: platform-modules-d6556 +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led + +Package: platform-modules-d7264q28b +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6254qs.init b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6254qs.init new file mode 100644 index 000000000000..92405e28fd26 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6254qs.init @@ -0,0 +1,73 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Inventec d6254qs board. +### END INIT INFO + +DIR=/usr/share/sonic/device/x86_64-inventec_d6254qs-r0/plugins +MONITOR_DAEMON=$DIR/transceiver_monitor.py +MONITOR_DAEMON_NAME=transceiver_monitor +LED_DAEMON=$DIR/led_proc.py +LED_DAEMON_NAME=led_proc +ASIC_DAEMON=$DIR/asic_monitor.py +ASIC_DAEMON_NAME=asic_monitor +ASIC_DAEMON_NAM=asic_monitor +PLATFORM_STATUS_DAEMON=$DIR/platform_status.py +PLATFORM_STATUS_DAEMON_NAME=platform_status + +# The process ID of the script when it runs is stored here: +MONITOR_PIDFILE=/var/run/$MONITOR_DAEMON_NAME.pid +LED_PIDFILE=/var/run/$LED_DAEMON_NAME.pid +ASIC_PIDFILE=/var/run/$ASIC_DAEMON_NAME.pid +PLATFORM_STATUS_PIDFILE=/var/run/$PLATFORM_STATUS_DAEMON_NAME.pid + +do_monitor_start() { + /sbin/start-stop-daemon --quiet --oknodo --pidfile $LED_PIDFILE --make-pidfile --startas $LED_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $MONITOR_PIDFILE --make-pidfile --startas $MONITOR_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $ASIC_PIDFILE --make-pidfile --startas $ASIC_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_STATUS_PIDFILE --make-pidfile --startas $PLATFORM_STATUS_DAEMON --start --background -- $DAEMON_OPTS +} + +do_monitor_stop() { + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $MONITOR_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $LED_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $ASIC_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_STATUS_PIDFILE --retry 10 +} + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + /usr/local/bin/inventec_d6254_util.py -f install + do_monitor_${1} + echo "done." + ;; + +stop) + + /usr/local/bin/inventec_d6254_util.py -f clean + do_monitor_${1} + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-d6254qs.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6254qs.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6254qs.install new file mode 100644 index 000000000000..c4c32c02b299 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6254qs.install @@ -0,0 +1,6 @@ +d6254qs/utils/inventec_d6254_util.py usr/local/bin +common/utils/transceiver_monitor.py usr/share/sonic/device/x86_64-inventec_d6254qs-r0/plugins +common/utils/led_proc.py usr/share/sonic/device/x86_64-inventec_d6254qs-r0/plugins +common/utils/asic_monitor.py usr/share/sonic/device/x86_64-inventec_d6254qs-r0/plugins +common/utils/platform_status.py usr/share/sonic/device/x86_64-inventec_d6254qs-r0/plugins +systemd/platform-modules-d6254qs.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6556.init b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6556.init new file mode 100644 index 000000000000..fc6ba5a261bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6556.init @@ -0,0 +1,72 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Inventec d6556 board. +### END INIT INFO + +DIR=/usr/share/sonic/device/x86_64-inventec_d6556-r0/plugins +MONITOR_DAEMON=$DIR/transceiver_monitor.py +MONITOR_DAEMON_NAME=transceiver_monitor +LED_DAEMON=$DIR/led_proc.py +LED_DAEMON_NAME=led_proc +ASIC_DAEMON=$DIR/asic_monitor.py +ASIC_DAEMON_NAME=asic_monitor +PLATFORM_STATUS_DAEMON=$DIR/platform_status.py +PLATFORM_STATUS_DAEMON_NAME=platform_status + +# The process ID of the script when it runs is stored here: +MONITOR_PIDFILE=/var/run/$MONITOR_DAEMON_NAME.pid +LED_PIDFILE=/var/run/$LED_DAEMON_NAME.pid +ASIC_PIDFILE=/var/run/$ASIC_DAEMON_NAME.pid +PLATFORM_STATUS_PIDFILE=/var/run/$PLATFORM_STATUS_DAEMON_NAME.pid + +do_monitor_start() { + /sbin/start-stop-daemon --quiet --oknodo --pidfile $LED_PIDFILE --make-pidfile --startas $LED_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $MONITOR_PIDFILE --make-pidfile --startas $MONITOR_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $ASIC_PIDFILE --make-pidfile --startas $ASIC_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_STATUS_PIDFILE --make-pidfile --startas $PLATFORM_STATUS_DAEMON --start --background -- $DAEMON_OPTS +} + +do_monitor_stop() { + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $MONITOR_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $LED_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $ASIC_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_STATUS_PIDFILE --retry 10 +} + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + /usr/local/bin/inventec_d6556_util.py -f install + do_monitor_${1} + echo "done." + ;; + +stop) + + /usr/local/bin/inventec_d6556_util.py -f clean + do_monitor_${1} + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-d6556.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6556.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6556.install new file mode 100644 index 000000000000..f9e9de9a8b10 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6556.install @@ -0,0 +1,6 @@ +d6556/utils/inventec_d6556_util.py usr/local/bin +common/utils/transceiver_monitor.py usr/share/sonic/device/x86_64-inventec_d6556-r0/plugins +common/utils/led_proc.py usr/share/sonic/device/x86_64-inventec_d6556-r0/plugins +common/utils/asic_monitor.py usr/share/sonic/device/x86_64-inventec_d6556-r0/plugins +common/utils/platform_status.py usr/share/sonic/device/x86_64-inventec_d6556-r0/plugins +systemd/platform-modules-d6556.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7032q28b.init b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7032q28b.init new file mode 100644 index 000000000000..bcc9610abedb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7032q28b.init @@ -0,0 +1,72 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Inventec d7032q28b board. +### END INIT INFO + +DIR=/usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/plugins +MONITOR_DAEMON=$DIR/transceiver_monitor.py +MONITOR_DAEMON_NAME=transceiver_monitor +LED_DAEMON=$DIR/led_proc.py +LED_DAEMON_NAME=led_proc +ASIC_DAEMON=$DIR/asic_monitor.py +ASIC_DAEMON_NAME=asic_monitor +PLATFORM_STATUS_DAEMON=$DIR/platform_status.py +PLATFORM_STATUS_DAEMON_NAME=platform_status + +# The process ID of the script when it runs is stored here: +MONITOR_PIDFILE=/var/run/$MONITOR_DAEMON_NAME.pid +LED_PIDFILE=/var/run/$LED_DAEMON_NAME.pid +ASIC_PIDFILE=/var/run/$ASIC_DAEMON_NAME.pid +PLATFORM_STATUS_PIDFILE=/var/run/$PLATFORM_STATUS_DAEMON_NAME.pid + +do_monitor_start() { + /sbin/start-stop-daemon --quiet --oknodo --pidfile $LED_PIDFILE --make-pidfile --startas $LED_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $MONITOR_PIDFILE --make-pidfile --startas $MONITOR_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $ASIC_PIDFILE --make-pidfile --startas $ASIC_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_STATUS_PIDFILE --make-pidfile --startas $PLATFORM_STATUS_DAEMON --start --background -- $DAEMON_OPTS +} + +do_monitor_stop() { + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $MONITOR_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $LED_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $ASIC_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_STATUS_PIDFILE --retry 10 +} + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + /usr/local/bin/inventec_d7032_util.py -f install + do_monitor_${1} + echo "done." + ;; + +stop) + + /usr/local/bin/inventec_d7032_util.py -f clean + do_monitor_${1} + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-d7032q28b.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7032q28b.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7032q28b.install new file mode 100644 index 000000000000..49ef07def38a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7032q28b.install @@ -0,0 +1,6 @@ +d7032q28b/utils/inventec_d7032_util.py usr/local/bin +common/utils/transceiver_monitor.py usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/plugins +common/utils/led_proc.py usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/plugins +common/utils/asic_monitor.py usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/plugins +common/utils/platform_status.py usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/plugins +systemd/platform-modules-d7032q28b.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7054q28b.init b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7054q28b.init new file mode 100644 index 000000000000..809ad6255556 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7054q28b.init @@ -0,0 +1,72 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Inventec d7054q28b board. +### END INIT INFO + +DIR=/usr/share/sonic/device/x86_64-inventec_d7054q28b-r0/plugins +MONITOR_DAEMON=$DIR/transceiver_monitor.py +MONITOR_DAEMON_NAME=transceiver_monitor +LED_DAEMON=$DIR/led_proc.py +LED_DAEMON_NAME=led_proc +ASIC_DAEMON=$DIR/asic_monitor.py +ASIC_DAEMON_NAME=asic_monitor +PLATFORM_STATUS_DAEMON=$DIR/platform_status.py +PLATFORM_STATUS_DAEMON_NAME=platform_status + +# The process ID of the script when it runs is stored here: +MONITOR_PIDFILE=/var/run/$MONITOR_DAEMON_NAME.pid +LED_PIDFILE=/var/run/$LED_DAEMON_NAME.pid +ASIC_PIDFILE=/var/run/$ASIC_DAEMON_NAME.pid +PLATFORM_STATUS_PIDFILE=/var/run/$PLATFORM_STATUS_DAEMON_NAME.pid + +do_monitor_start() { + /sbin/start-stop-daemon --quiet --oknodo --pidfile $LED_PIDFILE --make-pidfile --startas $LED_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $MONITOR_PIDFILE --make-pidfile --startas $MONITOR_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $ASIC_PIDFILE --make-pidfile --startas $ASIC_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_STATUS_PIDFILE --make-pidfile --startas $PLATFORM_STATUS_DAEMON --start --background -- $DAEMON_OPTS +} + +do_monitor_stop() { + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $MONITOR_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $LED_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $ASIC_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_STATUS_PIDFILE --retry 10 +} + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + /usr/local/bin/inventec_d7054_util.py -f install + do_monitor_${1} + echo "done." + ;; + +stop) + + /usr/local/bin/inventec_d7054_util.py -f clean + do_monitor_${1} + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-d7054q28b.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7054q28b.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7054q28b.install new file mode 100644 index 000000000000..0ffc0a4f92a3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7054q28b.install @@ -0,0 +1,6 @@ +d7054q28b/utils/inventec_d7054_util.py usr/local/bin +common/utils/transceiver_monitor.py usr/share/sonic/device/x86_64-inventec_d7054q28b-r0/plugins +common/utils/led_proc.py usr/share/sonic/device/x86_64-inventec_d7054q28b-r0/plugins +common/utils/asic_monitor.py usr/share/sonic/device/x86_64-inventec_d7054q28b-r0/plugins +common/utils/platform_status.py usr/share/sonic/device/x86_64-inventec_d7054q28b-r0/plugins +systemd/platform-modules-d7054q28b.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7264q28b.init b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7264q28b.init new file mode 100644 index 000000000000..606c7a7cdd09 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7264q28b.init @@ -0,0 +1,67 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Inventec d7264q28b board. +### END INIT INFO + +DIR=/usr/share/sonic/device/x86_64-inventec_d7264q28b-r0/plugins +MONITOR_DAEMON=$DIR/transceiver_monitor.py +MONITOR_DAEMON_NAME=transceiver_monitor +ASIC_DAEMON=$DIR/asic_monitor.py +ASIC_DAEMON_NAME=asic_monitor +PLATFORM_STATUS_DAEMON=$DIR/platform_status.py +PLATFORM_STATUS_DAEMON_NAME=platform_status + +# The process ID of the script when it runs is stored here: +MONITOR_PIDFILE=/var/run/$MONITOR_DAEMON_NAME.pid +ASIC_PIDFILE=/var/run/$ASIC_DAEMON_NAME.pid +PLATFORM_STATUS_PIDFILE=/var/run/$PLATFORM_STATUS_DAEMON_NAME.pid + +do_monitor_start() { + /sbin/start-stop-daemon --quiet --oknodo --pidfile $MONITOR_PIDFILE --make-pidfile --startas $MONITOR_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $ASIC_PIDFILE --make-pidfile --startas $ASIC_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_STATUS_PIDFILE --make-pidfile --startas $PLATFORM_STATUS_DAEMON --start --background -- $DAEMON_OPTS +} + +do_monitor_stop() { + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $MONITOR_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $ASIC_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_STATUS_PIDFILE --retry 10 +} + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + /usr/local/bin/inventec_d7264_util.py -f install + do_monitor_${1} + echo "done." + ;; + +stop) + + /usr/local/bin/inventec_d7264_util.py -f clean + do_monitor_${1} + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-d7264q28b.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7264q28b.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7264q28b.install new file mode 100644 index 000000000000..66e77e1ddf89 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7264q28b.install @@ -0,0 +1,5 @@ +d7264q28b/utils/inventec_d7264_util.py usr/local/bin +common/utils/transceiver_monitor.py usr/share/sonic/device/x86_64-inventec_d7264q28b-r0/plugins +common/utils/asic_monitor.py usr/share/sonic/device/x86_64-inventec_d7264q28b-r0/plugins +common/utils/platform_status.py usr/share/sonic/device/x86_64-inventec_d7264q28b-r0/plugins +systemd/platform-modules-d7264q28b.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/rules b/platform/broadcom/sonic-platform-modules-inventec/debian/rules new file mode 100755 index 000000000000..2e396e167822 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/rules @@ -0,0 +1,47 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= d7032q28b d7054q28b d6254qs d6556 d7264q28b + +%: + dh $@ --with=systemd + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -pplatform-modules-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -pplatform-modules-$${mod} usr/local/bin; \ + cp $(MOD_SRC_DIR)/$${mod}/utils/* \ + debian/platform-modules-$${mod}/usr/local/bin; \ + done) + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6254qs.service b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6254qs.service new file mode 100644 index 000000000000..b7aa6dc0e1e7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6254qs.service @@ -0,0 +1,13 @@ +[Unit] +Description=Inventec d6254qs Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-d6254qs start +ExecStop=-/etc/init.d/platform-modules-d6254qs stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6556.service b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6556.service new file mode 100644 index 000000000000..6fbd6711ede8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6556.service @@ -0,0 +1,13 @@ +[Unit] +Description=Inventec d7032q28b Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-d6556 start +ExecStop=-/etc/init.d/platform-modules-d6556 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7032q28b.service b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7032q28b.service new file mode 100644 index 000000000000..b96374b343f4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7032q28b.service @@ -0,0 +1,13 @@ +[Unit] +Description=Inventec d7032q28b Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-d7032q28b start +ExecStop=-/etc/init.d/platform-modules-d7032q28b stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7054q28b.service b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7054q28b.service new file mode 100644 index 000000000000..0c2d463598ad --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7054q28b.service @@ -0,0 +1,13 @@ +[Unit] +Description=Inventec d7054q28b Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-d7054q28b start +ExecStop=-/etc/init.d/platform-modules-d7054q28b stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7264q28b.service b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7264q28b.service new file mode 100644 index 000000000000..a4cda3934357 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7264q28b.service @@ -0,0 +1,13 @@ +[Unit] +Description=Inventec d7032q28b Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-d7264q28b start +ExecStop=-/etc/init.d/platform-modules-d7264q28b stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-mitac/.gitignore b/platform/broadcom/sonic-platform-modules-mitac/.gitignore new file mode 100644 index 000000000000..38e72f05332d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/.gitignore @@ -0,0 +1,17 @@ +# Build file +ly1200-32x/modules/*.mod.c +ly1200-32x/modules/*.mod.o +ly1200-32x/modules/*.o +ly1200-32x/modules/*.ko +ly1200-32x/modules/*.cmd +ly1200-32x/modules/Module.symvers +ly1200-32x/modules/modules.order +ly1200-32x/modules/.tmp_versions + +debian/sonic-platform-mitac-ly1200-32x/ +debian/sonic-platform-mitac-ly1200-32x.debhelper.log +debian/sonic-platform-mitac-ly1200-32x.postinst.debhelper +debian/sonic-platform-mitac-ly1200-32x.postrm.debhelper +debian/sonic-platform-mitac-ly1200-32x.prerm.debhelper +debian/sonic-platform-mitac-ly1200-32x.substvars +debian/files diff --git a/platform/broadcom/sonic-platform-modules-mitac/LICENSE b/platform/broadcom/sonic-platform-modules-mitac/LICENSE new file mode 100644 index 000000000000..c07c63913aeb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2018 MiTAC Technology Corporation + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-mitac/README.md b/platform/broadcom/sonic-platform-modules-mitac/README.md new file mode 100644 index 000000000000..d7d47a58debf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/README.md @@ -0,0 +1 @@ +platform drivers of MiTAC products for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/changelog b/platform/broadcom/sonic-platform-modules-mitac/debian/changelog new file mode 100644 index 000000000000..592bb3a71134 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/changelog @@ -0,0 +1,5 @@ +sonic-mitac-platform-modules (1.0) unstable; urgency=low + + * Initial release + + -- MiTAC Network Thu, 01 Sep 2017 11:26:38 +0800 diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/compat b/platform/broadcom/sonic-platform-modules-mitac/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/control b/platform/broadcom/sonic-platform-modules-mitac/debian/control new file mode 100644 index 000000000000..8e20f8524d74 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/control @@ -0,0 +1,12 @@ +Source: sonic-mitac-platform-modules +Section: main +Priority: extra +Maintainer: MiTAC network +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-mitac-ly1200-32x +Architecture: amd64 +Depends: linux-image-3.16.0-5-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/rules b/platform/broadcom/sonic-platform-modules-mitac/debian/rules new file mode 100755 index 000000000000..7f9f99827d21 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/rules @@ -0,0 +1,41 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_PRE_NAME := sonic-platform-mitac +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= ly1200-32x + +%: + dh $@ + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}\ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin;\ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + mkdir -p debian/$(PACKAGE_PRE_NAME)-$${mod}/opt; \ + cp -rfL $(MOD_SRC_DIR)/$${mod}/opt/* \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/opt; \ + mkdir -p debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/init.d; \ + cp -rfL $(MOD_SRC_DIR)/$${mod}/etc/* \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/etc; \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init b/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init new file mode 100644 index 000000000000..d2f7dbf610ab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init @@ -0,0 +1,51 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup ly1200-32x board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + echo 0 > /proc/sys/kernel/perf_cpu_time_max_percent + + /etc/init.d/gpe start + /etc/init.d/i2c_init start + /etc/init.d/sys_polld start + /opt/script/start_watchdog.sh & + /opt/script/start_service.sh & + echo "done." + ;; + +stop) + echo -n "cleaning... " + + /etc/init.d/gpe stop + /etc/init.d/i2c_init stop + /etc/init.d/xcvr_servd stop + /etc/init.d/sys_servd stop + /etc/init.d/sys_polld stop + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-mitac-ly1200-32x.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.upstart b/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.upstart new file mode 100644 index 000000000000..39533b8226af --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.upstart @@ -0,0 +1,5 @@ +description "SONiC platform service" + +respawn + +exec /etc/init.d/sonic-platform-mitac-ly1200-32x start diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld new file mode 100755 index 000000000000..936f01e8b640 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld @@ -0,0 +1,35 @@ +#!/bin/bash +### BEGIN INIT INFO +# Provides: fan-ctrld +# Required-Start: +# Required-Stop: +# Default-Start: rc.local +# Default-Stop: +# Short-Description: Daemon fan-ctrld +### END INIT INFO + +N=/etc/init.d/fan-ctrld +D_PATH=/opt/fan-ctrl/fan-ctrl + +set -e + +stop_fan_ctrld () { + pkill -f $D_PATH +} + +case "$1" in + start) + $D_PATH & + ;; + stop) + stop_fan_ctrld + ;; + reload|restart|force-reload) + ;; + *) + echo "Usage: $N {start}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/gpe b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/gpe new file mode 100755 index 000000000000..c326442db047 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/gpe @@ -0,0 +1,39 @@ +#! /bin/bash +### BEGIN INIT INFO +# Provides: gpe +# Required-Start: +# Required-Stop: +# Default-Start: rc.local +# Default-Stop: +# Short-Description: Daemon gpe +### END INIT INFO + +# Load kernel modules +load_module () { + if [ `lsmod | grep -c "gpe "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_gpe.ko + fi +} + +remove_module () { + rmmod mitac-ly1200-32x_gpe +} + +case "$1" in + start) + load_module + ;; + stop) + remove_module + ;; + reload|restart|force-reload) + remove_module + load_module + ;; + *) + echo "Usage: $N {start|stop|reload|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init new file mode 100755 index 000000000000..caddfce3325d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init @@ -0,0 +1,214 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup ly1200-32x board. +### END INIT INFO + +I2C_I801_RM_PRINT=0 +I2C_ISMT_RM_PRINT=0 +I2C_I801_INS_PRINT=0 +I2C_ISMT_INS_PRINT=0 +I2C_I801_RM_RETRY=0 +I2C_ISMT_RM_RETRY=0 +I2C_I801_INS_RETRY=0 +I2C_ISMT_INS_RETRY=0 +RETRY=3 + +# process name/id +DAEMON_NAME=`basename $0` +DAEMON_PID="$$" + +# default log file +DEF_LOG_FILE="/var/log/syslog" + +#/* +#* FEATURE: +#* log_msg +#* PURPOSE: +#* log message +#* PARAMETERS: +#* msg (IN) message +#* RETURNS: +#* +#*/ +function log_msg() { + local msg=$1 + + echo -e "`date +"%b %_d %T"` `hostname` $DAEMON_NAME[$DAEMON_PID]: ${msg}" >> ${DEF_LOG_FILE} +} + + +# Load kernel modules +load_modules () { + #----------remove i801 start--------------------- + if [ `lsmod | grep -c "i2c_i801 "` -eq 1 ]; then + rmmod i2c_i801 + while [ `lsmod | grep -c "i2c_i801 "` -eq 1 ] + do + if [ $I2C_I801_RM_PRINT -eq 0 ]; then + I2C_I801_RM_PRINT=1 + log_msg "Wait for i2c_i801 remove." + fi + if [ $I2C_I801_RM_RETRY -lt $RETRY ];then + I2C_I801_RM_RETRY=$((I2C_I801_RM_RETRY + 1)) + else + break + fi + sleep 1 + done + if [ $I2C_I801_RM_PRINT -eq 1 ]; then + log_msg "i2c_i801 remove success." + fi + fi + #----------remove i801 end------------------------ + + + #----------remove ismt start---------------------- + if [ `lsmod | grep -c "i2c_ismt "` -eq 1 ]; then + rmmod i2c_ismt + while [ `lsmod | grep -c "i2c_ismt "` -eq 1 ] + do + if [ $I2C_ISMT_RM_PRINT -eq 0 ]; then + I2C_ISMT_RM_PRINT=1 + log_msg "Wait for i2c_ismt remove." + fi + if [ $I2C_ISMT_RM_RETRY -lt $RETRY ];then + I2C_ISMT_RM_RETRY=$((I2C_ISMT_RM_RETRY + 1)) + else + break + fi + sleep 1 + done + if [ $I2C_ISMT_RM_PRINT -eq 1 ]; then + log_msg "i2c_ismt remove success." + fi + fi + #----------remove ismt end------------------------ + + #----------insert i801 start---------------------- + insmod /lib/modules/`uname -r`/kernel/drivers/i2c/busses/i2c-i801.ko + while [ `lsmod | grep -c "i2c_i801 "` -eq 0 ] + do + if [ $I2C_I801_INS_PRINT -eq 0 ]; then + I2C_I801_INS_PRINT=1 + log_msg "Wait for i2c_i801 insert." + fi + if [ $I2C_I801_INS_RETRY -lt $RETRY ];then + I2C_I801_INS_RETRY=$((I2C_I801_INS_RETRY + 1)) + else + break + fi + sleep 1 + done + if [ $I2C_I801_INS_PRINT -eq 1 ]; then + log_msg "i2c_i801 insert success." + fi + #----------insert i801 end------------------------ + + #----------insert ismt start---------------------- + insmod /lib/modules/`uname -r`/kernel/drivers/i2c/busses/i2c-ismt.ko + while [ `lsmod | grep -c "i2c_ismt "` -eq 0 ] + do + if [ $I2C_ISMT_INS_PRINT -eq 0 ]; then + I2C_ISMT_INS_PRINT=1 + log_msg "Wait for i2c_ismt insert." + fi + if [ $I2C_ISMT_INS_RETRY -lt $RETRY ];then + I2C_ISMT_INS_RETRY=$((I2C_ISMT_INS_RETRY + 1)) + else + break + fi + sleep 1 + done + if [ $I2C_ISMT_INS_PRINT -eq 1 ]; then + log_msg "i2c_ismt insert success." + fi + #----------insert ismt start------------------------ + if [ `lsmod | grep -c "at24 "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/kernel/drivers/misc/eeprom/at24.ko + fi + if [ `lsmod | grep -c "i2c_mux "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/kernel/drivers/i2c/i2c-mux.ko + fi + if [ `lsmod | grep -c "i2c_mux_pca954x "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/kernel/drivers/i2c/muxes/i2c-mux-pca954x.ko + fi + if [ `lsmod | grep -c "lm75 "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/kernel/drivers/hwmon/lm75.ko + fi + if [ `lsmod | grep -c "max31790 "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/kernel/drivers/hwmon/max31790.ko + fi + if [ `lsmod | grep -c "sff_8436_eeprom "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/kernel/drivers/misc/eeprom/sff_8436_eeprom.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_fse000 "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_fse000.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_system_cpld "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_system_cpld.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_master_cpld "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_master_cpld.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_slave_cpld "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_slave_cpld.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_cb_i2c "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_cb_i2c.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_sb_i2c "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_sb_i2c.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_pb_i2c "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_pb_i2c.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_fb_i2c "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_fb_i2c.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_fb_module_i2c "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_fb_module_i2c.ko + fi +} + +# Load i2c_dev modules +load_i2c_dev_modules () { + if [ `lsmod | grep -c "i2c_dev "` -eq 0 ]; then + modprobe i2c_dev + fi +} + +case "$1" in +start) + echo -n "Setting up board... " + load_i2c_dev_modules + load_modules + echo "done." + ;; + +stop) + echo -n "cleaning... " + + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/i2c_init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld new file mode 100755 index 000000000000..1df43346f257 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld @@ -0,0 +1,48 @@ +#!/bin/bash +### BEGIN INIT INFO +# Provides: sys-polld +# Required-Start: +# Required-Stop: +# Default-Start: rc.local +# Default-Stop: +# Short-Description: Daemon sys-polld +### END INIT INFO + +N=/etc/init.d/sys-polld +D_PATH=/opt/system-check/system-check.sh + +set -e + +stop_syspolld () { + local GCOUNT=`ps aux | grep -c "$D_PATH"` + local KILL_COUNT=0 + + while [ $GCOUNT -gt 1 ] + do + local ID=`ps aux | grep "$D_PATH" | head -n 1 | awk -F' ' '{print $2}'` + kill -15 $ID + GCOUNT=`ps aux | grep -c "$D_PATH"` + KILL_COUNT=`expr $KILL_COUNT + 1` + if [ $KILL_COUNT -eq 100 ]; then + echo "Error: kill sys-polld $KILL_COUNT times. stop kill process." + GCOUNT=0 + fi + done +} + +case "$1" in + start) + $D_PATH & + ;; + stop) + stop_syspolld + ;; + reload|restart|force-reload) + ;; + *) + echo "Usage: $N {start}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd new file mode 100755 index 000000000000..09ee087d5db0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd @@ -0,0 +1,28 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: sys-servd +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: rc.local +# Default-Stop: 0 1 6 +# Short-Description: Daemon sys-servd +### END INIT INFO + +# Author: Eddy Weng + +DESC="Service script for /opt/sys-serv/sys-servd" +DAEMON=/opt/sys-serv/sys-servd + +case "$1" in + start) + start-stop-daemon --start --exec $DAEMON + ;; + stop) + start-stop-daemon --stop --name sys-servd + ;; + *) + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd new file mode 100755 index 000000000000..1558614fd43c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd @@ -0,0 +1,28 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: xcvr-servd +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: rc.local +# Default-Stop: 0 1 6 +# Short-Description: Daemon xcvr-servd +### END INIT INFO + +# Author: Yencheng Lin + +DESC="Service script for /opt/xcvr-serv/xcvr-servd" +DAEMON=/opt/xcvr-serv/xcvr-servd + +case "$1" in + start) + start-stop-daemon --start --exec $DAEMON + ;; + stop) + start-stop-daemon --stop --name xcvr-servd + ;; + *) + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc0.d/K02xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc0.d/K02xcvr_servd new file mode 120000 index 000000000000..d71f756d3deb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc0.d/K02xcvr_servd @@ -0,0 +1 @@ +../init.d/xcvr_servd \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc1.d/K02xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc1.d/K02xcvr_servd new file mode 120000 index 000000000000..d71f756d3deb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc1.d/K02xcvr_servd @@ -0,0 +1 @@ +../init.d/xcvr_servd \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc6.d/K02xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc6.d/K02xcvr_servd new file mode 120000 index 000000000000..d71f756d3deb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc6.d/K02xcvr_servd @@ -0,0 +1 @@ +../init.d/xcvr_servd \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/Makefile new file mode 100644 index 000000000000..fc3f88de8eb3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/Makefile @@ -0,0 +1,5 @@ +obj-m:=mitac_ly1200_32x_fb_i2c.o mitac_ly1200_32x_fse000.o \ +mitac_ly1200_32x_master_cpld.o mitac_ly1200_32x_sb_i2c.o \ +mitac_ly1200_32x_system_cpld.o mitac_ly1200_32x_cb_i2c.o \ +mitac_ly1200_32x_fb_module_i2c.o mitac_ly1200_32x_gpe.o \ +mitac_ly1200_32x_pb_i2c.o mitac_ly1200_32x_slave_cpld.o diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/bms_i2c.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/bms_i2c.h new file mode 100644 index 000000000000..dd63607f39c7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/bms_i2c.h @@ -0,0 +1,26 @@ +#ifndef _BMS_I2C_H_ +#define _BMS_I2C_H_ + +const char *bms_i2c_adapter_names[] = { + "SMBus I801 adapter", + "SMBus iSMT adapter", +}; + +enum i2c_adapter_type { + I2C_ADAPTER_I801 = 0, + I2C_ADAPTER_ISMT, +}; + +enum bms_module_switch_bus { + I2C_STAGE1_MUX_CHAN0 = 0, + I2C_STAGE1_MUX_CHAN1, + I2C_STAGE1_MUX_CHAN2, + I2C_STAGE1_MUX_CHAN3, + I2C_STAGE1_MUX_CHAN4, + I2C_STAGE1_MUX_CHAN5, + I2C_STAGE1_MUX_CHAN6, + I2C_STAGE1_MUX_CHAN7, +}; + +#endif /* _BMS_I2C_H_ */ + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_reg.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_reg.h new file mode 100644 index 000000000000..dfdc89dbe57d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_reg.h @@ -0,0 +1,275 @@ +#ifndef __MASTER_CPLD_REG +#define __MASTER_CPLD_REG + +static int master_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name); +static int master_cpld_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name); + +/* generic CPLD read function */ +#define FLD_RAW_RD_FUNC(_reg, _fld, _wdh) static ssize_t \ +master_cpld_##_fld##_raw_read(struct device *dev, struct device_attribute *attr, char *buf) { \ + return master_cpld_raw_read(dev, attr, buf, _reg##_offset, _reg##_width, _fld##_shift, _fld##_width, _fld##_mask, #_reg); \ +} + +/* generic CPLD write function */ +#define FLD_RAW_WR_FUNC(_reg, _fld, _wdh) static ssize_t \ +master_cpld_##_fld##_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { \ + return master_cpld_raw_write(dev, attr, buf, count, _reg##_offset, _reg##_width, _fld##_shift, _fld##_width, _fld##_mask, #_reg); \ +} + +/* CPLD register definition macros */ +#define REG_DEF(_reg, _off, _wdh) \ +static unsigned int _reg##_offset = (unsigned int)(_off); \ +static unsigned int _reg##_width = (unsigned int)(_wdh); + +/* CPLD register field definition macros, with generic read/write function */ +#define FLD_RAW_RO_DEF(_reg, _fld, _sft, _wdh) \ +static unsigned int _fld##_shift = (unsigned int)(_sft); \ +static unsigned int _fld##_width = (unsigned int)(_wdh); \ +static unsigned int _fld##_mask = ((((unsigned int)1) << (_wdh)) - 1); \ +FLD_RAW_RD_FUNC(_reg, _fld, _wdh) + +#define FLD_RAW_RW_DEF(_reg, _fld, _sft, _wdh) \ +static unsigned int _fld##_shift = (unsigned int)(_sft); \ +static unsigned int _fld##_width = (unsigned int)(_wdh); \ +static unsigned int _fld##_mask = ((((unsigned int)1) << (_wdh)) - 1); \ +FLD_RAW_RD_FUNC(_reg, _fld, _wdh) FLD_RAW_WR_FUNC(_reg, _fld, _wdh) + +/* declare master CPLD registers */ +/* register name offset width */ +/* --------------------------------------- ------- ----- */ +REG_DEF( mstr_cpld_rev, 0x00, 8) +REG_DEF( mstr_cpld_gpr, 0x01, 8) +REG_DEF( mb_brd_rev_type, 0x02, 8) +REG_DEF( mstr_srr, 0x03, 8) +REG_DEF( eeprom_wp, 0x04, 8) +REG_DEF( mstr_irq, 0x05, 8) +REG_DEF( system_led, 0x06, 8) +REG_DEF( fan_tray_3_1_led, 0x07, 8) +REG_DEF( fan_tray_6_4_led, 0x08, 8) +REG_DEF( fan_tray_status, 0x09, 8) +REG_DEF( fan_type_status, 0x0A, 8) +REG_DEF( psu_en_status, 0x0B, 8) +REG_DEF( mb_pwr_en_status, 0x0C, 8) +REG_DEF( mb_pwr_status, 0x0D, 8) + +REG_DEF( zqsfp28_present_8_1_status, 0x10, 8) +REG_DEF( zqsfp28_present_16_9_status, 0x11, 8) +REG_DEF( zqsfp28_rst_8_1, 0x12, 8) +REG_DEF( zqsfp28_rst_16_9, 0x13, 8) +REG_DEF( zqsfp28_modsel_8_1, 0x14, 8) +REG_DEF( zqsfp28_modsel_16_9, 0x15, 8) +REG_DEF( zqsfp28_lpmode_8_1, 0x16, 8) +REG_DEF( zqsfp28_lpmode_16_9, 0x17, 8) +REG_DEF( zqsfp28_irq_8_1_status, 0x18, 8) +REG_DEF( zqsfp28_irq_16_9_status, 0x19, 8) +REG_DEF( zqsfp28_irq_msk_8_1_status, 0x1A, 8) +REG_DEF( zqsfp28_irq_msk_16_9_status, 0x1B, 8) + + +/* declare master CPLD register's fields */ +/* register name field name shift width */ +/* ---------------------- ---------------- ------ ----- */ +FLD_RAW_RO_DEF( mstr_cpld_rev, mjr_rev, 4, 4) +FLD_RAW_RO_DEF( mstr_cpld_rev, mnr_rev, 0, 4) + +FLD_RAW_RW_DEF( mstr_cpld_gpr, scrtch_reg, 0, 8) + +FLD_RAW_RO_DEF( mb_brd_rev_type, brd_rev, 4, 4) +FLD_RAW_RO_DEF( mb_brd_rev_type, brd_type, 0, 4) + +FLD_RAW_RW_DEF( mstr_srr, mb_rst, 2, 1) +FLD_RAW_RW_DEF( mstr_srr, npu_rst, 1, 1) +FLD_RAW_RW_DEF( mstr_srr, mgmt_phy_rst, 0, 1) + +FLD_RAW_RW_DEF( eeprom_wp, mb_eeprom_wp, 2, 1) +FLD_RAW_RW_DEF( eeprom_wp, cpld_spi_wp, 1, 1) +FLD_RAW_RW_DEF( eeprom_wp, fan_eeprom_wp, 0, 1) + +FLD_RAW_RW_DEF( mstr_irq, ps2_int_msk, 7, 1) +FLD_RAW_RW_DEF( mstr_irq, ps1_int_msk, 6, 1) +FLD_RAW_RW_DEF( mstr_irq, usb_fault_msk, 5, 1) +FLD_RAW_RW_DEF( mstr_irq, pcie_int_msk, 4, 1) +FLD_RAW_RW_DEF( mstr_irq, fan_alert_int_msk, 3, 1) +FLD_RAW_RO_DEF( mstr_irq, usb_fault, 2, 1) +FLD_RAW_RO_DEF( mstr_irq, pcie_int, 1, 1) +FLD_RAW_RO_DEF( mstr_irq, fan_alert_int, 0, 1) + +FLD_RAW_RW_DEF( system_led, system_led_fld, 6, 2) +FLD_RAW_RW_DEF( system_led, power_led, 4, 2) +FLD_RAW_RW_DEF( system_led, fan_led, 2, 2) +FLD_RAW_RW_DEF( system_led, locate_led, 1, 1) + +FLD_RAW_RW_DEF( fan_tray_3_1_led, led_test, 6, 2) +FLD_RAW_RW_DEF( fan_tray_3_1_led, fan_tray3_led, 4, 2) +FLD_RAW_RW_DEF( fan_tray_3_1_led, fan_tray2_led, 2, 2) +FLD_RAW_RW_DEF( fan_tray_3_1_led, fan_tray1_led, 0, 2) + +FLD_RAW_RW_DEF( fan_tray_6_4_led, fan_tray6_led, 4, 2) +FLD_RAW_RW_DEF( fan_tray_6_4_led, fan_tray5_led, 2, 2) +FLD_RAW_RW_DEF( fan_tray_6_4_led, fan_tray4_led, 0, 2) + +FLD_RAW_RO_DEF( fan_tray_status, fan_tray6_present, 5, 1) +FLD_RAW_RO_DEF( fan_tray_status, fan_tray5_present, 4, 1) +FLD_RAW_RO_DEF( fan_tray_status, fan_tray4_present, 3, 1) +FLD_RAW_RO_DEF( fan_tray_status, fan_tray3_present, 2, 1) +FLD_RAW_RO_DEF( fan_tray_status, fan_tray2_present, 1, 1) +FLD_RAW_RO_DEF( fan_tray_status, fan_tray1_present, 0, 1) + +FLD_RAW_RO_DEF( fan_type_status, fan_type6, 5, 1) +FLD_RAW_RO_DEF( fan_type_status, fan_type5, 4, 1) +FLD_RAW_RO_DEF( fan_type_status, fan_type4, 3, 1) +FLD_RAW_RO_DEF( fan_type_status, fan_type3, 2, 1) +FLD_RAW_RO_DEF( fan_type_status, fan_type2, 1, 1) +FLD_RAW_RO_DEF( fan_type_status, fan_type1, 0, 1) + +FLD_RAW_RO_DEF( psu_en_status, ps1_ps, 7, 1) +FLD_RAW_RO_DEF( psu_en_status, ps1_pg, 6, 1) +FLD_RAW_RO_DEF( psu_en_status, ps1_int, 5, 1) +FLD_RAW_RW_DEF( psu_en_status, ps1_on, 4, 1) +FLD_RAW_RO_DEF( psu_en_status, ps2_ps, 3, 1) +FLD_RAW_RO_DEF( psu_en_status, ps2_pg, 2, 1) +FLD_RAW_RO_DEF( psu_en_status, ps2_int, 1, 1) +FLD_RAW_RW_DEF( psu_en_status, ps2_on, 0, 1) + +FLD_RAW_RW_DEF( mb_pwr_en_status, usb1_vbus_en, 7, 1) +FLD_RAW_RO_DEF( mb_pwr_en_status, v5p0_en, 5, 1) +FLD_RAW_RO_DEF( mb_pwr_en_status, v3p3_en, 4, 1) +FLD_RAW_RO_DEF( mb_pwr_en_status, vcc_1v8_en, 3, 1) +FLD_RAW_RO_DEF( mb_pwr_en_status, mac_avs1v_en, 2, 1) +FLD_RAW_RO_DEF( mb_pwr_en_status, mac1v_en, 1, 1) +FLD_RAW_RO_DEF( mb_pwr_en_status, vcc_1v25_en, 0, 1) + +FLD_RAW_RO_DEF( mb_pwr_status, vcc_3p3_cpld, 6, 1) +FLD_RAW_RO_DEF( mb_pwr_status, vcc5v_pg, 5, 1) +FLD_RAW_RO_DEF( mb_pwr_status, vcc3v3_pg, 4, 1) +FLD_RAW_RO_DEF( mb_pwr_status, vcc_1v8_pg, 3, 1) +FLD_RAW_RO_DEF( mb_pwr_status, mac_avs1v_pg, 2, 1) +FLD_RAW_RO_DEF( mb_pwr_status, mac1v_pg, 1, 1) +FLD_RAW_RO_DEF( mb_pwr_status, vcc_1v25_pg, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port8_present, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port7_present, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port6_present, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port5_present, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port4_present, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port3_present, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port2_present, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port1_present, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port16_present, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port15_present, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port14_present, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port13_present, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port12_present, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port11_present, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port10_present, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port9_present, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port8_rst, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port7_rst, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port6_rst, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port5_rst, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port4_rst, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port3_rst, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port2_rst, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port1_rst, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port16_rst, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port15_rst, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port14_rst, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port13_rst, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port12_rst, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port11_rst, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port10_rst, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port9_rst, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port8_modsel, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port7_modsel, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port6_modsel, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port5_modsel, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port4_modsel, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port3_modsel, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port2_modsel, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port1_modsel, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port16_modsel, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port15_modsel, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port14_modsel, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port13_modsel, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port12_modsel, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port11_modsel, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port10_modsel, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port9_modsel, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port8_lpmode, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port7_lpmode, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port6_lpmode, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port5_lpmode, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port4_lpmode, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port3_lpmode, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port2_lpmode, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port1_lpmode, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port16_lpmode, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port15_lpmode, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port14_lpmode, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port13_lpmode, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port12_lpmode, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port11_lpmode, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port10_lpmode, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port9_lpmode, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port8_irq_status, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port7_irq_status, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port6_irq_status, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port5_irq_status, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port4_irq_status, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port3_irq_status, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port2_irq_status, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port1_irq_status, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port16_irq_status, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port15_irq_status, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port14_irq_status, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port13_irq_status, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port12_irq_status, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port11_irq_status, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port10_irq_status, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port9_irq_status, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port8_irq_msk, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port7_irq_msk, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port6_irq_msk, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port5_irq_msk, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port4_irq_msk, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port3_irq_msk, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port2_irq_msk, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port1_irq_msk, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port16_irq_msk, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port15_irq_msk, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port14_irq_msk, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port13_irq_msk, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port12_irq_msk, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port11_irq_msk, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port10_irq_msk, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port9_irq_msk, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port_1_8_present, 0, 8) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port_9_16_present, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port_1_8_rst, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port_9_16_rst, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port_1_8_modsel, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port_9_16_modsel, 0, 8) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port_1_8_irq_status, 0, 8) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port_9_16_irq_status,0, 8) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port_1_8_irq_msk, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port_9_16_irq_msk, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port_1_8_lpmode, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port_9_16_lpmode, 0, 8) + +FLD_RAW_RO_DEF( fan_tray_status, fan_tray1_6_present, 0, 8) +FLD_RAW_RO_DEF( psu_en_status, psu_en_status_fld, 0, 8) +#endif /* __MASTER_CPLD_REG */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h new file mode 100644 index 000000000000..e851ca5fb487 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h @@ -0,0 +1,226 @@ +#ifndef __MASTER_CPLD_SYSFS +#define __MASTER_CPLD_SYSFS + +/* generic CPLD sysfs file definition macros */ +#define SYSFS_RAW_RO_ATTR_DEF(field) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO, master_cpld_##field##_raw_read, NULL); + +#define SYSFS_RAW_RW_ATTR_DEF(field) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO | S_IWUGO, master_cpld_##field##_raw_read, master_cpld_##field##_raw_write); + +#define SYSFS_MISC_RO_ATTR_DEF(field, _read) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO, _read, NULL); + +#define SYSFS_MISC_RW_ATTR_DEF(field, _read, _write) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO | S_IWUGO, _read, _write); + +#define SYSFS_ATTR_PTR(field) \ +&field.attr + +/* declare master CPLD file system */ +SYSFS_RAW_RO_ATTR_DEF(mjr_rev) +SYSFS_RAW_RO_ATTR_DEF(mnr_rev) + +SYSFS_RAW_RW_ATTR_DEF(scrtch_reg) + +SYSFS_RAW_RO_ATTR_DEF(brd_rev) +SYSFS_RAW_RO_ATTR_DEF(brd_type) + +SYSFS_RAW_RW_ATTR_DEF(mb_rst) +SYSFS_RAW_RW_ATTR_DEF(npu_rst) +SYSFS_RAW_RW_ATTR_DEF(mgmt_phy_rst) + +SYSFS_RAW_RW_ATTR_DEF(mb_eeprom_wp) +SYSFS_RAW_RW_ATTR_DEF(cpld_spi_wp) +SYSFS_RAW_RW_ATTR_DEF(fan_eeprom_wp) + +SYSFS_RAW_RW_ATTR_DEF(ps2_int_msk) +SYSFS_RAW_RW_ATTR_DEF(ps1_int_msk) +SYSFS_RAW_RW_ATTR_DEF(usb_fault_msk) +SYSFS_RAW_RW_ATTR_DEF(pcie_int_msk) +SYSFS_RAW_RW_ATTR_DEF(fan_alert_int_msk) +SYSFS_RAW_RO_ATTR_DEF(usb_fault) +SYSFS_RAW_RO_ATTR_DEF(pcie_int) +SYSFS_RAW_RO_ATTR_DEF(fan_alert_int) + +SYSFS_RAW_RW_ATTR_DEF(system_led_fld) +SYSFS_RAW_RW_ATTR_DEF(power_led) +SYSFS_RAW_RW_ATTR_DEF(fan_led) +SYSFS_RAW_RW_ATTR_DEF(locate_led) + +SYSFS_RAW_RW_ATTR_DEF(led_test) +SYSFS_RAW_RW_ATTR_DEF(fan_tray3_led) +SYSFS_RAW_RW_ATTR_DEF(fan_tray2_led) +SYSFS_RAW_RW_ATTR_DEF(fan_tray1_led) + +SYSFS_RAW_RW_ATTR_DEF(fan_tray6_led) +SYSFS_RAW_RW_ATTR_DEF(fan_tray5_led) +SYSFS_RAW_RW_ATTR_DEF(fan_tray4_led) + +SYSFS_RAW_RO_ATTR_DEF(fan_tray6_present) +SYSFS_RAW_RO_ATTR_DEF(fan_tray5_present) +SYSFS_RAW_RO_ATTR_DEF(fan_tray4_present) +SYSFS_RAW_RO_ATTR_DEF(fan_tray3_present) +SYSFS_RAW_RO_ATTR_DEF(fan_tray2_present) +SYSFS_RAW_RO_ATTR_DEF(fan_tray1_present) + +SYSFS_RAW_RO_ATTR_DEF(fan_type6) +SYSFS_RAW_RO_ATTR_DEF(fan_type5) +SYSFS_RAW_RO_ATTR_DEF(fan_type4) +SYSFS_RAW_RO_ATTR_DEF(fan_type3) +SYSFS_RAW_RO_ATTR_DEF(fan_type2) +SYSFS_RAW_RO_ATTR_DEF(fan_type1) + +SYSFS_RAW_RO_ATTR_DEF(ps1_ps) +SYSFS_RAW_RO_ATTR_DEF(ps1_pg) +SYSFS_RAW_RO_ATTR_DEF(ps1_int) +SYSFS_RAW_RW_ATTR_DEF(ps1_on) +SYSFS_RAW_RO_ATTR_DEF(ps2_ps) +SYSFS_RAW_RO_ATTR_DEF(ps2_pg) +SYSFS_RAW_RO_ATTR_DEF(ps2_int) +SYSFS_RAW_RW_ATTR_DEF(ps2_on) + +SYSFS_RAW_RW_ATTR_DEF(usb1_vbus_en) +SYSFS_RAW_RO_ATTR_DEF(v5p0_en) +SYSFS_RAW_RO_ATTR_DEF(v3p3_en) +SYSFS_RAW_RO_ATTR_DEF(vcc_1v8_en) +SYSFS_RAW_RO_ATTR_DEF(mac_avs1v_en) +SYSFS_RAW_RO_ATTR_DEF(mac1v_en) +SYSFS_RAW_RO_ATTR_DEF(vcc_1v25_en) + +SYSFS_RAW_RO_ATTR_DEF(vcc_3p3_cpld) +SYSFS_RAW_RO_ATTR_DEF(vcc5v_pg) +SYSFS_RAW_RO_ATTR_DEF(vcc3v3_pg) +SYSFS_RAW_RO_ATTR_DEF(vcc_1v8_pg) +SYSFS_RAW_RO_ATTR_DEF(mac_avs1v_pg) +SYSFS_RAW_RO_ATTR_DEF(mac1v_pg) +SYSFS_RAW_RO_ATTR_DEF(vcc_1v25_pg) + +SYSFS_RAW_RO_ATTR_DEF(port8_present) +SYSFS_RAW_RO_ATTR_DEF(port7_present) +SYSFS_RAW_RO_ATTR_DEF(port6_present) +SYSFS_RAW_RO_ATTR_DEF(port5_present) +SYSFS_RAW_RO_ATTR_DEF(port4_present) +SYSFS_RAW_RO_ATTR_DEF(port3_present) +SYSFS_RAW_RO_ATTR_DEF(port2_present) +SYSFS_RAW_RO_ATTR_DEF(port1_present) + +SYSFS_RAW_RO_ATTR_DEF(port16_present) +SYSFS_RAW_RO_ATTR_DEF(port15_present) +SYSFS_RAW_RO_ATTR_DEF(port14_present) +SYSFS_RAW_RO_ATTR_DEF(port13_present) +SYSFS_RAW_RO_ATTR_DEF(port12_present) +SYSFS_RAW_RO_ATTR_DEF(port11_present) +SYSFS_RAW_RO_ATTR_DEF(port10_present) +SYSFS_RAW_RO_ATTR_DEF(port9_present) + +SYSFS_RAW_RW_ATTR_DEF(port8_rst) +SYSFS_RAW_RW_ATTR_DEF(port7_rst) +SYSFS_RAW_RW_ATTR_DEF(port6_rst) +SYSFS_RAW_RW_ATTR_DEF(port5_rst) +SYSFS_RAW_RW_ATTR_DEF(port4_rst) +SYSFS_RAW_RW_ATTR_DEF(port3_rst) +SYSFS_RAW_RW_ATTR_DEF(port2_rst) +SYSFS_RAW_RW_ATTR_DEF(port1_rst) + +SYSFS_RAW_RW_ATTR_DEF(port16_rst) +SYSFS_RAW_RW_ATTR_DEF(port15_rst) +SYSFS_RAW_RW_ATTR_DEF(port14_rst) +SYSFS_RAW_RW_ATTR_DEF(port13_rst) +SYSFS_RAW_RW_ATTR_DEF(port12_rst) +SYSFS_RAW_RW_ATTR_DEF(port11_rst) +SYSFS_RAW_RW_ATTR_DEF(port10_rst) +SYSFS_RAW_RW_ATTR_DEF(port9_rst) + +SYSFS_RAW_RW_ATTR_DEF(port8_modsel) +SYSFS_RAW_RW_ATTR_DEF(port7_modsel) +SYSFS_RAW_RW_ATTR_DEF(port6_modsel) +SYSFS_RAW_RW_ATTR_DEF(port5_modsel) +SYSFS_RAW_RW_ATTR_DEF(port4_modsel) +SYSFS_RAW_RW_ATTR_DEF(port3_modsel) +SYSFS_RAW_RW_ATTR_DEF(port2_modsel) +SYSFS_RAW_RW_ATTR_DEF(port1_modsel) + +SYSFS_RAW_RW_ATTR_DEF(port16_modsel) +SYSFS_RAW_RW_ATTR_DEF(port15_modsel) +SYSFS_RAW_RW_ATTR_DEF(port14_modsel) +SYSFS_RAW_RW_ATTR_DEF(port13_modsel) +SYSFS_RAW_RW_ATTR_DEF(port12_modsel) +SYSFS_RAW_RW_ATTR_DEF(port11_modsel) +SYSFS_RAW_RW_ATTR_DEF(port10_modsel) +SYSFS_RAW_RW_ATTR_DEF(port9_modsel) + +SYSFS_RAW_RW_ATTR_DEF(port8_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port7_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port6_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port5_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port4_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port3_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port2_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port1_lpmode) + +SYSFS_RAW_RW_ATTR_DEF(port16_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port15_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port14_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port13_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port12_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port11_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port10_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port9_lpmode) + +SYSFS_RAW_RO_ATTR_DEF(port8_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port7_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port6_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port5_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port4_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port3_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port2_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port1_irq_status) + +SYSFS_RAW_RO_ATTR_DEF(port16_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port15_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port14_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port13_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port12_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port11_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port10_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port9_irq_status) + +SYSFS_RAW_RW_ATTR_DEF(port8_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port7_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port6_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port5_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port4_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port3_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port2_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port1_irq_msk) + +SYSFS_RAW_RW_ATTR_DEF(port16_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port15_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port14_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port13_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port12_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port11_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port10_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port9_irq_msk) + +SYSFS_RAW_RO_ATTR_DEF(port_1_8_present) +SYSFS_RAW_RO_ATTR_DEF(port_9_16_present) +SYSFS_RAW_RW_ATTR_DEF(port_1_8_rst) +SYSFS_RAW_RW_ATTR_DEF(port_9_16_rst) +SYSFS_RAW_RW_ATTR_DEF(port_1_8_modsel) +SYSFS_RAW_RW_ATTR_DEF(port_9_16_modsel) +SYSFS_RAW_RO_ATTR_DEF(port_1_8_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port_9_16_irq_status) +SYSFS_RAW_RW_ATTR_DEF(port_1_8_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port_9_16_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port_1_8_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port_9_16_lpmode) + +SYSFS_RAW_RO_ATTR_DEF(fan_tray1_6_present) +SYSFS_RAW_RO_ATTR_DEF(psu_en_status_fld) +#endif /* __MASTER_CPLD_SYSFS */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_cb_i2c.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_cb_i2c.c new file mode 100644 index 000000000000..11fffe251785 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_cb_i2c.c @@ -0,0 +1,163 @@ +#include +#include +#include +#include "bms_i2c.h" + +#define BMS_CB_I2C_CLIENT_NUM 5 +#define BMS_CB_ADAPTER_BASE 0 + +static struct i2c_client *bms_cb_clients[BMS_CB_I2C_CLIENT_NUM] = {NULL}; +static int bms_cb_client_index = 0; + +static int __init __find_i2c_adap(struct device *dev, void *data) +{ + const char *name = data; + static const char *prefix = "i2c-"; + struct i2c_adapter *adapter; + + if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) + { + return 0; + } + adapter = to_i2c_adapter(dev); + + return (strncmp(adapter->name, name, strlen(name)) == 0); +} + +static int __init find_i2c_adapter_num(enum i2c_adapter_type type) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + const char *name = bms_i2c_adapter_names[type]; + + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + + +static __init struct i2c_client *bms_cb_setup_spd( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("spd", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + + +static __init struct i2c_client *bms_cb_setup_eeprom_24c02( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("24c02", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + +static __init struct i2c_client *bms_cb_setup_tmp75( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("tmp75", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + +static __init struct i2c_client *bms_cb_setup_system_cpld(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("system_cpld", 0x31), + }; + + return i2c_new_device(adap, &info); +} + +static int __init bms_cb_setup_devices_i801(void) +{ + struct i2c_adapter *adap; + int adap_num = find_i2c_adapter_num(I2C_ADAPTER_I801); + + if (adap_num < 0) + return adap_num; + + adap = i2c_get_adapter(adap_num); + if (!adap) { + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + goto exit; + } + + bms_cb_clients[bms_cb_client_index++] = bms_cb_setup_spd(adap, 0x50); + bms_cb_clients[bms_cb_client_index++] = bms_cb_setup_spd(adap, 0x52); + bms_cb_clients[bms_cb_client_index++] = bms_cb_setup_tmp75(adap, 0x4e); + +exit: + return 0; +} + +static int __init bms_cb_setup_devices_ismt(void) +{ + struct i2c_adapter *adap; + int adap_num = find_i2c_adapter_num(I2C_ADAPTER_ISMT); + + if (adap_num < 0) + return adap_num; + + adap = i2c_get_adapter(adap_num); + if (!adap) { + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + return 0; + } + + bms_cb_clients[bms_cb_client_index++] = bms_cb_setup_system_cpld(adap); + bms_cb_clients[bms_cb_client_index++] = bms_cb_setup_eeprom_24c02(adap, 0x56); + return 0; +} + +static int __init bms_cb_i2c_init(void) +{ + /* Initial bms_cb_slients array. */ + memset(bms_cb_clients, 0x0, BMS_CB_I2C_CLIENT_NUM); + + bms_cb_setup_devices_i801(); + mdelay(200); + bms_cb_setup_devices_ismt(); + + return 0; +} + + +static void __exit bms_cb_i2c_exit(void){ + int i; + + for (i=(bms_cb_client_index-1); i>=0; i--) { + if (bms_cb_clients[i]) { + i2c_unregister_device(bms_cb_clients[i]); + bms_cb_clients[i] = NULL; + } + } + + bms_cb_client_index = 0; + +} + + +module_init(bms_cb_i2c_init); +module_exit(bms_cb_i2c_exit); + + +MODULE_DESCRIPTION("mitac_ly1200_32x_cb_i2c driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fb_i2c.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fb_i2c.c new file mode 100644 index 000000000000..d228bc481279 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fb_i2c.c @@ -0,0 +1,153 @@ +#include +#include +#include "bms_i2c.h" + +#define BMS_FB_I2C_CLIENT_NUM 3 + + +static struct i2c_client *bms_fb_clients[BMS_FB_I2C_CLIENT_NUM] = {NULL}; +static int bms_fb_client_index = 0; + +static int __init __find_i2c_adap(struct device *dev, void *data) +{ + const char *name = data; + static const char *prefix = "i2c-"; + struct i2c_adapter *adapter; + + if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) + { + return 0; + } + adapter = to_i2c_adapter(dev); + + return (strncmp(adapter->name, name, strlen(name)) == 0); +} + +static int __init find_i2c_adapter_num(enum i2c_adapter_type type) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + const char *name = bms_i2c_adapter_names[type]; + + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + +static int __init find_i2c_mux_adapter_num(int parent_num, int num) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + char name[48]; + + snprintf(name, sizeof(name), "i2c-%d-mux (chan_id %d)", + parent_num, num); + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + +static __init struct i2c_client *bms_fb_setup_tmp75( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("tmp75", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + +static __init struct i2c_client *bms_fb_setup_max31790( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("max31790", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + +static int __init bms_fb_setup_devices(void) +{ + struct i2c_adapter *adap; + int adap_num; + int parent_num; + + parent_num = find_i2c_adapter_num(I2C_ADAPTER_ISMT); + if (parent_num < 0) + return parent_num; + + /* Mux chan1 steup */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN1); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_fb_clients[bms_fb_client_index++] = bms_fb_setup_max31790(adap, 0x20); + bms_fb_clients[bms_fb_client_index++] = bms_fb_setup_max31790(adap, 0x23); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN1); + } + + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN2); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_fb_clients[bms_fb_client_index++] = bms_fb_setup_tmp75(adap, 0x4d); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN2); + } + + return 0; +} + +static int __init bms_fb_i2c_init(void) +{ + bms_fb_setup_devices(); + + return 0; +} + +static void __exit bms_fb_i2c_exit(void){ + int i; + + for (i=(bms_fb_client_index-1); i>=0; i--) { + if (bms_fb_clients[i]) { + i2c_unregister_device(bms_fb_clients[i]); + bms_fb_clients[i] = NULL; + } + } + + bms_fb_client_index = 0; + +} + +module_init(bms_fb_i2c_init); +module_exit(bms_fb_i2c_exit); + + +MODULE_DESCRIPTION("mitac_ly1200_32x_fb_i2c driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fb_module_i2c.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fb_module_i2c.c new file mode 100644 index 000000000000..174dba197217 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fb_module_i2c.c @@ -0,0 +1,138 @@ +#include +#include +#include "bms_i2c.h" + +#define BMS_FB_MODULE_I2C_CLIENT_NUM 6 + +static struct i2c_client *bms_fb_module_clients[BMS_FB_MODULE_I2C_CLIENT_NUM] = {NULL}; +static int bms_fb_module_client_index = 0; + +static int __init __find_i2c_adap(struct device *dev, void *data) +{ + const char *name = data; + static const char *prefix = "i2c-"; + struct i2c_adapter *adapter; + + if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) + { + return 0; + } + adapter = to_i2c_adapter(dev); + + return (strncmp(adapter->name, name, strlen(name)) == 0); +} + +static int __init find_i2c_adapter_num(enum i2c_adapter_type type) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + const char *name = bms_i2c_adapter_names[type]; + + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + +static int __init find_i2c_mux_adapter_num(int parent_num, int num) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + char name[48]; + + snprintf(name, sizeof(name), "i2c-%d-mux (chan_id %d)", + parent_num, num); + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + + +static __init struct i2c_client *bms_fb_module_setup_eeprom_24c02( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("24c02", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + +static int __init bms_fb_module_setup_devices(void) +{ + struct i2c_adapter *adap; + int adap_num; + int parent_num; + + parent_num = find_i2c_adapter_num(I2C_ADAPTER_ISMT); + if (parent_num < 0) + return parent_num; + + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN1); + if (adap_num < 0) + return adap_num; + + adap = i2c_get_adapter(adap_num); + if (!adap) { + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + goto exit; + } + + bms_fb_module_clients[bms_fb_module_client_index++] = bms_fb_module_setup_eeprom_24c02(adap, 0x50); + bms_fb_module_clients[bms_fb_module_client_index++] = bms_fb_module_setup_eeprom_24c02(adap, 0x51); + bms_fb_module_clients[bms_fb_module_client_index++] = bms_fb_module_setup_eeprom_24c02(adap, 0x52); + bms_fb_module_clients[bms_fb_module_client_index++] = bms_fb_module_setup_eeprom_24c02(adap, 0x53); + bms_fb_module_clients[bms_fb_module_client_index++] = bms_fb_module_setup_eeprom_24c02(adap, 0x54); + bms_fb_module_clients[bms_fb_module_client_index++] = bms_fb_module_setup_eeprom_24c02(adap, 0x55); + +exit: + return 0; +} + +static int __init bms_fb_module_i2c_init(void) +{ + /* Initial bms_sb_slients array. */ + memset(bms_fb_module_clients, 0x0, BMS_FB_MODULE_I2C_CLIENT_NUM); + + bms_fb_module_setup_devices(); + + return 0; +} + +static void __exit bms_fb_module_i2c_exit(void){ + int i; + + for (i=(bms_fb_module_client_index-1); i>=0; i--) { + if (bms_fb_module_clients[i]) { + i2c_unregister_device(bms_fb_module_clients[i]); + bms_fb_module_clients[i] = NULL; + } + } + + bms_fb_module_client_index = 0; + +} + +module_init(bms_fb_module_i2c_init); +module_exit(bms_fb_module_i2c_exit); + + +MODULE_DESCRIPTION("mitac_ly1200_32x_fb_module_i2c driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fse000.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fse000.c new file mode 100644 index 000000000000..362821706857 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fse000.c @@ -0,0 +1,1787 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pmbus.h" +#include + +/* + * Number of additional attribute pointers to allocate + * with each call to krealloc + */ +#define PMBUS_ATTR_ALLOC_SIZE 32 + +/* + * Index into status register array, per status register group + */ +#define PB_STATUS_BASE 0 +#define PB_STATUS_VOUT_BASE (PB_STATUS_BASE + PMBUS_PAGES) +#define PB_STATUS_IOUT_BASE (PB_STATUS_VOUT_BASE + PMBUS_PAGES) +#define PB_STATUS_FAN_BASE (PB_STATUS_IOUT_BASE + PMBUS_PAGES) +#define PB_STATUS_FAN34_BASE (PB_STATUS_FAN_BASE + PMBUS_PAGES) +#define PB_STATUS_TEMP_BASE (PB_STATUS_FAN34_BASE + PMBUS_PAGES) +#define PB_STATUS_INPUT_BASE (PB_STATUS_TEMP_BASE + PMBUS_PAGES) +#define PB_STATUS_VMON_BASE (PB_STATUS_INPUT_BASE + 1) + +#define PB_NUM_STATUS_REG (PB_STATUS_VMON_BASE + 1) + +#define PMBUS_NAME_SIZE 24 +#define PMBUS_BLOCK_READ_SIZE 32 + +struct pmbus_sensor { + struct pmbus_sensor *next; + char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */ + struct device_attribute attribute; + u8 page; /* page number */ + u16 reg; /* register */ + enum pmbus_sensor_classes class; /* sensor class */ + bool update; /* runtime sensor update needed */ + int data; /* Sensor data. + Negative if there was a read error */ +}; +#define to_pmbus_sensor(_attr) \ + container_of(_attr, struct pmbus_sensor, attribute) + +struct pmbus_st { + char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */ + struct sensor_device_attribute attribute; + u16 base; +}; +#define to_pmbus_status(_attr) \ + container_of(_attr, struct pmbus_st, attribute) + +struct pmbus_mfr { + struct pmbus_mfr *next; + char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */ + struct device_attribute attribute; + u8 page; /* page number */ + u16 reg; /* register */ + int data; /* Sensor data. + Negative if there was a read error */ + char data_buf[PMBUS_BLOCK_READ_SIZE]; +}; +#define to_pmbus_mfr(_attr) \ + container_of(_attr, struct pmbus_mfr, attribute) + +struct pmbus_boolean { + char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */ + struct sensor_device_attribute attribute; + struct pmbus_sensor *s1; + struct pmbus_sensor *s2; +}; +#define to_pmbus_boolean(_attr) \ + container_of(_attr, struct pmbus_boolean, attribute) + +struct pmbus_label { + char name[PMBUS_NAME_SIZE]; /* sysfs label name */ + struct device_attribute attribute; + char label[PMBUS_NAME_SIZE]; /* label */ +}; +#define to_pmbus_label(_attr) \ + container_of(_attr, struct pmbus_label, attribute) + +struct pmbus_data { + struct device *dev; + struct device *hwmon_dev; + + u32 flags; /* from platform data */ + + int exponent[PMBUS_PAGES]; + /* linear mode: exponent for output voltages */ + + const struct pmbus_driver_info *info; + + int max_attributes; + int num_attributes; + struct attribute_group group; + const struct attribute_group *groups[2]; + + struct pmbus_sensor *sensors; + struct pmbus_mfr *mfr; + + struct mutex update_lock; + bool valid; + unsigned long last_updated; /* in jiffies */ + + /* + * A single status register covers multiple attributes, + * so we keep them all together. + */ + u8 status[PB_NUM_STATUS_REG]; + u8 status_register; + + u8 currpage; +}; + +void pmbus_clear_cache(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + + data->valid = false; +} + +int pmbus_set_page(struct i2c_client *client, u8 page) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int rv = 0; + int newpage; + + if (page != data->currpage) { + rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); + newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); + if (newpage != page) + rv = -EIO; + else + data->currpage = page; + } + return rv; +} + +int pmbus_write_byte(struct i2c_client *client, int page, u8 value) +{ + int rv; + + if (page >= 0) { + rv = pmbus_set_page(client, page); + if (rv < 0) + return rv; + } + + return i2c_smbus_write_byte(client, value); +} + +/* + * _pmbus_write_byte() is similar to pmbus_write_byte(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_write_byte(struct i2c_client *client, int page, u8 value) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + int status; + + if (info->write_byte) { + status = info->write_byte(client, page, value); + if (status != -ENODATA) + return status; + } + return pmbus_write_byte(client, page, value); +} + +int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word) +{ + int rv; + + rv = pmbus_set_page(client, page); + if (rv < 0) + return rv; + + return i2c_smbus_write_word_data(client, reg, word); +} + +/* + * _pmbus_write_word_data() is similar to pmbus_write_word_data(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_write_word_data(struct i2c_client *client, int page, int reg, + u16 word) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + int status; + + if (info->write_word_data) { + status = info->write_word_data(client, page, reg, word); + if (status != -ENODATA) + return status; + } + if (reg >= PMBUS_VIRT_BASE) + return -ENXIO; + return pmbus_write_word_data(client, page, reg, word); +} + +int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg) +{ + int rv; + + rv = pmbus_set_page(client, page); + if (rv < 0) + return rv; + + return i2c_smbus_read_word_data(client, reg); +} + +int pmbus_read_block_data(struct i2c_client *client, u8 reg, u8* value) +{ + return i2c_smbus_read_block_data(client, reg, value); +} + +static int _pmbus_read_block_data(struct i2c_client *client, int page, int reg, u8* value) +{ + int rv; + + rv = pmbus_set_page(client, page); + if (rv < 0) + return rv; + return pmbus_read_block_data(client, reg, value); +} + +/* + * _pmbus_read_word_data() is similar to pmbus_read_word_data(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + int status; + + if (info->read_word_data) { + status = info->read_word_data(client, page, reg); + if (status != -ENODATA) + return status; + } + if (reg >= PMBUS_VIRT_BASE) + return -ENXIO; + return pmbus_read_word_data(client, page, reg); +} + +int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg) +{ + int rv; + + if (page >= 0) { + rv = pmbus_set_page(client, page); + if (rv < 0) + return rv; + } + + return i2c_smbus_read_byte_data(client, reg); +} + +/* + * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + int status; + + if (info->read_byte_data) { + status = info->read_byte_data(client, page, reg); + if (status != -ENODATA) + return status; + } + return pmbus_read_byte_data(client, page, reg); +} + +static void pmbus_clear_fault_page(struct i2c_client *client, int page) +{ + _pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); +} + +void pmbus_clear_faults(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int i; + + for (i = 0; i < data->info->pages; i++) + pmbus_clear_fault_page(client, i); +} + +static int pmbus_check_status_cml(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int status, status2; + + status = _pmbus_read_byte_data(client, -1, data->status_register); + if (status < 0 || (status & PB_STATUS_CML)) { + status2 = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML); + if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND)) + return -EIO; + } + return 0; +} + +static bool pmbus_check_register(struct i2c_client *client, + int (*func)(struct i2c_client *client, + int page, int reg), + int page, int reg) +{ + int rv; + struct pmbus_data *data = i2c_get_clientdata(client); + + rv = func(client, page, reg); + if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK)) + rv = pmbus_check_status_cml(client); + pmbus_clear_fault_page(client, -1); + return rv >= 0; +} + +bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg) +{ + return pmbus_check_register(client, _pmbus_read_byte_data, page, reg); +} + +bool pmbus_check_word_register(struct i2c_client *client, int page, int reg) +{ + return pmbus_check_register(client, _pmbus_read_word_data, page, reg); +} + +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + + return data->info; +} + +static struct _pmbus_status { + u32 func; + u16 base; + u16 reg; +} pmbus_status[] = { + { PMBUS_HAVE_STATUS_VOUT, PB_STATUS_VOUT_BASE, PMBUS_STATUS_VOUT }, + { PMBUS_HAVE_STATUS_IOUT, PB_STATUS_IOUT_BASE, PMBUS_STATUS_IOUT }, + { PMBUS_HAVE_STATUS_TEMP, PB_STATUS_TEMP_BASE, + PMBUS_STATUS_TEMPERATURE }, + { PMBUS_HAVE_STATUS_FAN12, PB_STATUS_FAN_BASE, PMBUS_STATUS_FAN_12 }, + { PMBUS_HAVE_STATUS_FAN34, PB_STATUS_FAN34_BASE, PMBUS_STATUS_FAN_34 }, +}; + +static struct _pmbus_status_reg { + char name[PMBUS_NAME_SIZE]; + u16 base; + u8 offset; +} pmbus_status_reg[] = { + { "vout_ov_fault", PB_STATUS_VOUT_BASE, PB_VOLTAGE_UV_FAULT}, + { "vout_uv_fault", PB_STATUS_VOUT_BASE, PB_VOLTAGE_OV_FAULT}, + { "ot_fault", PB_STATUS_TEMP_BASE, PB_TEMP_OT_FAULT}, + { "ot_warning", PB_STATUS_TEMP_BASE, PB_TEMP_OT_WARNING}, + { "vin_uv_warning", PB_STATUS_INPUT_BASE, PB_VOLTAGE_UV_WARNING}, + { "vin_uv_fault", PB_STATUS_INPUT_BASE, PB_VOLTAGE_UV_FAULT}, +}; + +static struct _pmbus_mfr_reg { + char name[PMBUS_NAME_SIZE]; + u16 reg; +} pmbus_mfr_reg[] = { + { "mfr_id", PMBUS_MFR_ID}, + { "mfr_model", PMBUS_MFR_MODEL}, + { "mfr_revision", PMBUS_MFR_REVISION}, + { "mfr_location", PMBUS_MFR_LOCATION}, + { "mfr_date", PMBUS_MFR_DATE}, + { "mfr_serial", PMBUS_MFR_SERIAL}, +}; + +static struct pmbus_data *pmbus_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev->parent); + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + struct pmbus_sensor *sensor; + struct pmbus_mfr *mfr; + + mutex_lock(&data->update_lock); + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { + int i, j; + + for (i = 0; i < info->pages; i++) { + data->status[PB_STATUS_BASE + i] + = _pmbus_read_byte_data(client, i, + data->status_register); + for (j = 0; j < ARRAY_SIZE(pmbus_status); j++) { + struct _pmbus_status *s = &pmbus_status[j]; + + if (!(info->func[i] & s->func)) + continue; + data->status[s->base + i] + = _pmbus_read_byte_data(client, i, + s->reg); + } + } + + if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) + data->status[PB_STATUS_INPUT_BASE] + = _pmbus_read_byte_data(client, 0, + PMBUS_STATUS_INPUT); + + if (info->func[0] & PMBUS_HAVE_STATUS_VMON) + data->status[PB_STATUS_VMON_BASE] + = _pmbus_read_byte_data(client, 0, + PMBUS_VIRT_STATUS_VMON); + + for (sensor = data->sensors; sensor; sensor = sensor->next) { + if (!data->valid || sensor->update) + sensor->data + = _pmbus_read_word_data(client, + sensor->page, + sensor->reg); + } + + /* read mfg data */ + for (mfr = data->mfr; mfr; mfr = mfr->next) { + mfr->data = _pmbus_read_block_data(client, mfr->page, mfr->reg, mfr->data_buf); + } + + pmbus_clear_faults(client); + data->last_updated = jiffies; + data->valid = 1; + } + mutex_unlock(&data->update_lock); + return data; +} + +/* + * Convert linear sensor values to milli- or micro-units + * depending on sensor type. + */ +static long pmbus_reg2data_linear(struct pmbus_data *data, + struct pmbus_sensor *sensor) +{ + s16 exponent; + s32 mantissa; + long val; + + if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */ + exponent = data->exponent[sensor->page]; + mantissa = (u16) sensor->data; + } else { /* LINEAR11 */ + exponent = ((s16)sensor->data) >> 11; + mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5; + } + + val = mantissa; + + /* scale result to milli-units for all sensors except fans */ + if (sensor->class != PSC_FAN) + val = val * 1000L; + + /* scale result to micro-units for power sensors */ + if (sensor->class == PSC_POWER) + val = val * 1000L; + + if (exponent >= 0) + val <<= exponent; + else + val >>= -exponent; + + return val; +} + +/* + * Convert direct sensor values to milli- or micro-units + * depending on sensor type. + */ +static long pmbus_reg2data_direct(struct pmbus_data *data, + struct pmbus_sensor *sensor) +{ + long val = (s16) sensor->data; + long m, b, R; + + m = data->info->m[sensor->class]; + b = data->info->b[sensor->class]; + R = data->info->R[sensor->class]; + + if (m == 0) + return 0; + + /* X = 1/m * (Y * 10^-R - b) */ + R = -R; + /* scale result to milli-units for everything but fans */ + if (sensor->class != PSC_FAN) { + R += 3; + b *= 1000; + } + + /* scale result to micro-units for power sensors */ + if (sensor->class == PSC_POWER) { + R += 3; + b *= 1000; + } + + while (R > 0) { + val *= 10; + R--; + } + while (R < 0) { + val = DIV_ROUND_CLOSEST(val, 10); + R++; + } + + return (val - b) / m; +} + +/* + * Convert VID sensor values to milli- or micro-units + * depending on sensor type. + * We currently only support VR11. + */ +static long pmbus_reg2data_vid(struct pmbus_data *data, + struct pmbus_sensor *sensor) +{ + long val = sensor->data; + + if (val < 0x02 || val > 0xb2) + return 0; + return DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100); +} + +static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor) +{ + long val; + + switch (data->info->format[sensor->class]) { + case direct: + val = pmbus_reg2data_direct(data, sensor); + break; + case vid: + val = pmbus_reg2data_vid(data, sensor); + break; + case linear: + default: + val = pmbus_reg2data_linear(data, sensor); + break; + } + return val; +} + +#define MAX_MANTISSA (1023 * 1000) +#define MIN_MANTISSA (511 * 1000) + +static u16 pmbus_data2reg_linear(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + s16 exponent = 0, mantissa; + bool negative = false; + + /* simple case */ + if (val == 0) + return 0; + + if (sensor->class == PSC_VOLTAGE_OUT) { + /* LINEAR16 does not support negative voltages */ + if (val < 0) + return 0; + + /* + * For a static exponents, we don't have a choice + * but to adjust the value to it. + */ + if (data->exponent[sensor->page] < 0) + val <<= -data->exponent[sensor->page]; + else + val >>= data->exponent[sensor->page]; + val = DIV_ROUND_CLOSEST(val, 1000); + return val & 0xffff; + } + + if (val < 0) { + negative = true; + val = -val; + } + + /* Power is in uW. Convert to mW before converting. */ + if (sensor->class == PSC_POWER) + val = DIV_ROUND_CLOSEST(val, 1000L); + + /* + * For simplicity, convert fan data to milli-units + * before calculating the exponent. + */ + if (sensor->class == PSC_FAN) + val = val * 1000; + + /* Reduce large mantissa until it fits into 10 bit */ + while (val >= MAX_MANTISSA && exponent < 15) { + exponent++; + val >>= 1; + } + /* Increase small mantissa to improve precision */ + while (val < MIN_MANTISSA && exponent > -15) { + exponent--; + val <<= 1; + } + + /* Convert mantissa from milli-units to units */ + mantissa = DIV_ROUND_CLOSEST(val, 1000); + + /* Ensure that resulting number is within range */ + if (mantissa > 0x3ff) + mantissa = 0x3ff; + + /* restore sign */ + if (negative) + mantissa = -mantissa; + + /* Convert to 5 bit exponent, 11 bit mantissa */ + return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800); +} + +static u16 pmbus_data2reg_direct(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + long m, b, R; + + m = data->info->m[sensor->class]; + b = data->info->b[sensor->class]; + R = data->info->R[sensor->class]; + + /* Power is in uW. Adjust R and b. */ + if (sensor->class == PSC_POWER) { + R -= 3; + b *= 1000; + } + + /* Calculate Y = (m * X + b) * 10^R */ + if (sensor->class != PSC_FAN) { + R -= 3; /* Adjust R and b for data in milli-units */ + b *= 1000; + } + val = val * m + b; + + while (R > 0) { + val *= 10; + R--; + } + while (R < 0) { + val = DIV_ROUND_CLOSEST(val, 10); + R++; + } + + return val; +} + +static u16 pmbus_data2reg_vid(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + val = clamp_val(val, 500, 1600); + + return 2 + DIV_ROUND_CLOSEST((1600 - val) * 100, 625); +} + +static u16 pmbus_data2reg(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + u16 regval; + + switch (data->info->format[sensor->class]) { + case direct: + regval = pmbus_data2reg_direct(data, sensor, val); + break; + case vid: + regval = pmbus_data2reg_vid(data, sensor, val); + break; + case linear: + default: + regval = pmbus_data2reg_linear(data, sensor, val); + break; + } + return regval; +} + +/* + * Return boolean calculated from converted data. + * defines a status register index and mask. + * The mask is in the lower 8 bits, the register index is in bits 8..23. + * + * The associated pmbus_boolean structure contains optional pointers to two + * sensor attributes. If specified, those attributes are compared against each + * other to determine if a limit has been exceeded. + * + * If the sensor attribute pointers are NULL, the function returns true if + * (status[reg] & mask) is true. + * + * If sensor attribute pointers are provided, a comparison against a specified + * limit has to be performed to determine the boolean result. + * In this case, the function returns true if v1 >= v2 (where v1 and v2 are + * sensor values referenced by sensor attribute pointers s1 and s2). + * + * To determine if an object exceeds upper limits, specify = . + * To determine if an object exceeds lower limits, specify = . + * + * If a negative value is stored in any of the referenced registers, this value + * reflects an error code which will be returned. + */ +static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b, + int index) +{ + struct pmbus_sensor *s1 = b->s1; + struct pmbus_sensor *s2 = b->s2; + u16 reg = (index >> 8) & 0xffff; + u8 mask = index & 0xff; + int ret, status; + u8 regval; + + status = data->status[reg]; + if (status < 0) + return status; + + regval = status & mask; + if (!s1 && !s2) { + ret = !!regval; + } else if (!s1 || !s2) { + WARN(1, "Bad boolean descriptor %p: s1=%p, s2=%p\n", b, s1, s2); + return 0; + } else { + long v1, v2; + + if (s1->data < 0) + return s1->data; + if (s2->data < 0) + return s2->data; + + v1 = pmbus_reg2data(data, s1); + v2 = pmbus_reg2data(data, s2); + ret = !!(regval && v1 >= v2); + } + return ret; +} + +static ssize_t pmbus_show_boolean(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct pmbus_boolean *boolean = to_pmbus_boolean(attr); + struct pmbus_data *data = pmbus_update_device(dev); + int val; + + val = pmbus_get_boolean(data, boolean, attr->index); + if (val < 0) + return val; + return snprintf(buf, PAGE_SIZE, "%d\n", val); +} + +static ssize_t pmbus_show_sensor(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct pmbus_data *data = pmbus_update_device(dev); + struct pmbus_sensor *sensor = to_pmbus_sensor(devattr); + + if (sensor->data < 0) + return sensor->data; + + return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor)); +} + +static ssize_t pmbus_show_status(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct pmbus_st *status = to_pmbus_status(attr); + struct pmbus_data *data = pmbus_update_device(dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", !!(data->status[status->base] & attr->index)); +} + +static ssize_t pmbus_show_mfr(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct pmbus_mfr *mfr; + + pmbus_update_device(dev); + mfr = to_pmbus_mfr(devattr); + + if (mfr->data < 0) + return mfr->data; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,16,49) + /* mfr->data[0] is data length, we don't want show data length when show command */ + return snprintf(buf, PAGE_SIZE, "%s\n", &mfr->data_buf[1]); +#else + return snprintf(buf, PAGE_SIZE, "%s\n", &mfr->data_buf); +#endif +} + +static ssize_t pmbus_set_sensor(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev->parent); + struct pmbus_data *data = i2c_get_clientdata(client); + struct pmbus_sensor *sensor = to_pmbus_sensor(devattr); + ssize_t rv = count; + long val = 0; + int ret; + u16 regval; + + if (kstrtol(buf, 10, &val) < 0) + return -EINVAL; + + mutex_lock(&data->update_lock); + regval = pmbus_data2reg(data, sensor, val); + ret = _pmbus_write_word_data(client, sensor->page, sensor->reg, regval); + if (ret < 0) + rv = ret; + else + sensor->data = regval; + mutex_unlock(&data->update_lock); + return rv; +} + +static ssize_t pmbus_show_label(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct pmbus_label *label = to_pmbus_label(da); + + return snprintf(buf, PAGE_SIZE, "%s\n", label->label); +} + +static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr) +{ + if (data->num_attributes >= data->max_attributes - 1) { + int new_max_attrs = data->max_attributes + PMBUS_ATTR_ALLOC_SIZE; + void *new_attrs = krealloc(data->group.attrs, + new_max_attrs * sizeof(void *), + GFP_KERNEL); + if (!new_attrs) + return -ENOMEM; + data->group.attrs = new_attrs; + data->max_attributes = new_max_attrs; + } + + data->group.attrs[data->num_attributes++] = attr; + data->group.attrs[data->num_attributes] = NULL; + return 0; +} + +static void pmbus_dev_attr_init(struct device_attribute *dev_attr, + const char *name, + umode_t mode, + ssize_t (*show)(struct device *dev, + struct device_attribute *attr, + char *buf), + ssize_t (*store)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count)) +{ + sysfs_attr_init(&dev_attr->attr); + dev_attr->attr.name = name; + dev_attr->attr.mode = mode; + dev_attr->show = show; + dev_attr->store = store; +} + +static void pmbus_attr_init(struct sensor_device_attribute *a, + const char *name, + umode_t mode, + ssize_t (*show)(struct device *dev, + struct device_attribute *attr, + char *buf), + ssize_t (*store)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count), + int idx) +{ + pmbus_dev_attr_init(&a->dev_attr, name, mode, show, store); + a->index = idx; +} + +static int pmbus_add_boolean(struct pmbus_data *data, + const char *name, const char *type, int seq, + struct pmbus_sensor *s1, + struct pmbus_sensor *s2, + u16 reg, u8 mask) +{ + struct pmbus_boolean *boolean; + struct sensor_device_attribute *a; + + boolean = devm_kzalloc(data->dev, sizeof(*boolean), GFP_KERNEL); + if (!boolean) + return -ENOMEM; + + a = &boolean->attribute; + + snprintf(boolean->name, sizeof(boolean->name), "%s%d_%s", + name, seq, type); + boolean->s1 = s1; + boolean->s2 = s2; + pmbus_attr_init(a, boolean->name, S_IRUGO, pmbus_show_boolean, NULL, + (reg << 8) | mask); + + return pmbus_add_attribute(data, &a->dev_attr.attr); +} + +static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data, + const char *name, const char *type, + int seq, int page, int reg, + enum pmbus_sensor_classes class, + bool update, bool readonly) +{ + struct pmbus_sensor *sensor; + struct device_attribute *a; + + sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return NULL; + a = &sensor->attribute; + + snprintf(sensor->name, sizeof(sensor->name), "%s%d_%s", + name, seq, type); + sensor->page = page; + sensor->reg = reg; + sensor->class = class; + sensor->update = update; + pmbus_dev_attr_init(a, sensor->name, + readonly ? S_IRUGO : S_IRUGO | S_IWUSR, + pmbus_show_sensor, pmbus_set_sensor); + + if (pmbus_add_attribute(data, &a->attr)) + return NULL; + + sensor->next = data->sensors; + data->sensors = sensor; + + return sensor; +} + +static int pmbus_add_status(struct pmbus_data *data, + const char *name, u16 base, + u8 offset) +{ + struct pmbus_st *status; + struct sensor_device_attribute *a; + + status = devm_kzalloc(data->dev, sizeof(*status), GFP_KERNEL); + if (!status) + return -ENOMEM; + + a = &status->attribute; + + snprintf(status->name, sizeof(status->name), "%s", name); + + status->base = base; + + pmbus_attr_init(a, status->name, S_IRUGO, + pmbus_show_status, NULL, offset); + + return pmbus_add_attribute(data, &a->dev_attr.attr); +} + +static struct pmbus_mfr *pmbus_add_mfr(struct pmbus_data *data, + const char *name, + int page, int reg) +{ + struct pmbus_mfr *mfr; + struct device_attribute *a; + + mfr = devm_kzalloc(data->dev, sizeof(*mfr), GFP_KERNEL); + if (!mfr) + return NULL; + a = &mfr->attribute; + + snprintf(mfr->name, sizeof(mfr->name), "%s", name); + mfr->page = page; + mfr->reg = reg; + pmbus_dev_attr_init(a, mfr->name, S_IRUGO, + pmbus_show_mfr, NULL); + + if (pmbus_add_attribute(data, &a->attr)) + return NULL; + + mfr->next = data->mfr; + data->mfr = mfr; + + return mfr; +} + +static int pmbus_add_label(struct pmbus_data *data, + const char *name, int seq, + const char *lstring, int index) +{ + struct pmbus_label *label; + struct device_attribute *a; + + label = devm_kzalloc(data->dev, sizeof(*label), GFP_KERNEL); + if (!label) + return -ENOMEM; + + a = &label->attribute; + + snprintf(label->name, sizeof(label->name), "%s%d_label", name, seq); + if (!index) + strncpy(label->label, lstring, sizeof(label->label) - 1); + else + snprintf(label->label, sizeof(label->label), "%s%d", lstring, + index); + + pmbus_dev_attr_init(a, label->name, S_IRUGO, pmbus_show_label, NULL); + return pmbus_add_attribute(data, &a->attr); +} + +/* + * Search for attributes. Allocate sensors, booleans, and labels as needed. + */ + +/* + * The pmbus_limit_attr structure describes a single limit attribute + * and its associated alarm attribute. + */ +struct pmbus_limit_attr { + u16 reg; /* Limit register */ + u16 sbit; /* Alarm attribute status bit */ + bool update; /* True if register needs updates */ + bool low; /* True if low limit; for limits with compare + functions only */ + const char *attr; /* Attribute name */ + const char *alarm; /* Alarm attribute name */ +}; + +/* + * The pmbus_sensor_attr structure describes one sensor attribute. This + * description includes a reference to the associated limit attributes. + */ +struct pmbus_sensor_attr { + u16 reg; /* sensor register */ + u8 gbit; /* generic status bit */ + u8 nlimit; /* # of limit registers */ + enum pmbus_sensor_classes class;/* sensor class */ + const char *label; /* sensor label */ + bool paged; /* true if paged sensor */ + bool update; /* true if update needed */ + bool compare; /* true if compare function needed */ + u32 func; /* sensor mask */ + u32 sfunc; /* sensor status mask */ + int sbase; /* status base register */ + const struct pmbus_limit_attr *limit;/* limit registers */ +}; + +/* + * Add a set of limit attributes and, if supported, the associated + * alarm attributes. + * returns 0 if no alarm register found, 1 if an alarm register was found, + * < 0 on errors. + */ +static int pmbus_add_limit_attrs(struct i2c_client *client, + struct pmbus_data *data, + const struct pmbus_driver_info *info, + const char *name, int index, int page, + struct pmbus_sensor *base, + const struct pmbus_sensor_attr *attr) +{ + const struct pmbus_limit_attr *l = attr->limit; + int nlimit = attr->nlimit; + int have_alarm = 0; + int i, ret; + struct pmbus_sensor *curr; + + for (i = 0; i < nlimit; i++) { + if (pmbus_check_word_register(client, page, l->reg)) { + curr = pmbus_add_sensor(data, name, l->attr, index, + page, l->reg, attr->class, + attr->update || l->update, + false); + if (!curr) + return -ENOMEM; + if (l->sbit && (info->func[page] & attr->sfunc)) { + ret = pmbus_add_boolean(data, name, + l->alarm, index, + attr->compare ? l->low ? curr : base + : NULL, + attr->compare ? l->low ? base : curr + : NULL, + attr->sbase + page, l->sbit); + if (ret) + return ret; + have_alarm = 1; + } + } + l++; + } + return have_alarm; +} + +static int pmbus_add_sensor_attrs_one(struct i2c_client *client, + struct pmbus_data *data, + const struct pmbus_driver_info *info, + const char *name, + int index, int page, + const struct pmbus_sensor_attr *attr) +{ + struct pmbus_sensor *base; + int ret; + + if (attr->label) { + ret = pmbus_add_label(data, name, index, attr->label, + attr->paged ? page + 1 : 0); + if (ret) + return ret; + } + base = pmbus_add_sensor(data, name, "input", index, page, attr->reg, + attr->class, true, true); + if (!base) + return -ENOMEM; + if (attr->sfunc) { + ret = pmbus_add_limit_attrs(client, data, info, name, + index, page, base, attr); + if (ret < 0) + return ret; + /* + * Add generic alarm attribute only if there are no individual + * alarm attributes, if there is a global alarm bit, and if + * the generic status register for this page is accessible. + */ + if (!ret && attr->gbit && + pmbus_check_byte_register(client, page, + data->status_register)) { + ret = pmbus_add_boolean(data, name, "alarm", index, + NULL, NULL, + PB_STATUS_BASE + page, + attr->gbit); + if (ret) + return ret; + } + } + return 0; +} + +static int pmbus_add_sensor_attrs(struct i2c_client *client, + struct pmbus_data *data, + const char *name, + const struct pmbus_sensor_attr *attrs, + int nattrs) +{ + const struct pmbus_driver_info *info = data->info; + int index, i; + int ret; + + index = 1; + for (i = 0; i < nattrs; i++) { + int page, pages; + + pages = attrs->paged ? info->pages : 1; + for (page = 0; page < pages; page++) { + if (!(info->func[page] & attrs->func)) + continue; + ret = pmbus_add_sensor_attrs_one(client, data, info, + name, index, page, + attrs); + if (ret) + return ret; + index++; + } + attrs++; + } + return 0; +} + +static const struct pmbus_sensor_attr voltage_attributes[] = { + { + .reg = PMBUS_READ_VOUT, + .class = PSC_VOLTAGE_OUT, + .label = "vout", + .paged = true, + .func = PMBUS_HAVE_VOUT, + .sfunc = PMBUS_HAVE_STATUS_VOUT, + .sbase = PB_STATUS_VOUT_BASE, + .gbit = PB_STATUS_VOUT_OV, + } +}; + +static const struct pmbus_limit_attr iout_limit_attrs[] = { + { + .reg = PMBUS_IOUT_OC_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_IOUT_OC_WARNING, + }, { + .reg = PMBUS_IOUT_OC_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_IOUT_OC_FAULT, + } +}; + +static const struct pmbus_sensor_attr current_attributes[] = { + { + .reg = PMBUS_READ_IIN, + .class = PSC_CURRENT_IN, + .label = "iin", + .func = PMBUS_HAVE_IIN, + .sfunc = PMBUS_HAVE_STATUS_INPUT, + .sbase = PB_STATUS_INPUT_BASE, + }, { + .reg = PMBUS_READ_IOUT, + .class = PSC_CURRENT_OUT, + .label = "iout", + .paged = true, + .func = PMBUS_HAVE_IOUT, + .sfunc = PMBUS_HAVE_STATUS_IOUT, + .sbase = PB_STATUS_IOUT_BASE, + .gbit = PB_STATUS_IOUT_OC, + .limit = iout_limit_attrs, + .nlimit = ARRAY_SIZE(iout_limit_attrs), + } +}; + +/* Temperature atributes */ +static const struct pmbus_limit_attr temp_limit_attrs[] = { + { + .reg = PMBUS_OT_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_TEMP_OT_WARNING, + } +}; + +static const struct pmbus_limit_attr temp_limit_attrs2[] = { + { + .reg = PMBUS_OT_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_TEMP_OT_WARNING, + } +}; + +static const struct pmbus_limit_attr temp_limit_attrs3[] = { + { + .reg = PMBUS_OT_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_TEMP_OT_WARNING, + } +}; + +static const struct pmbus_sensor_attr temp_attributes[] = { + { + .reg = PMBUS_READ_TEMPERATURE_1, + .class = PSC_TEMPERATURE, + .paged = true, + .update = true, + .compare = true, + .func = PMBUS_HAVE_TEMP, + .sfunc = PMBUS_HAVE_STATUS_TEMP, + .sbase = PB_STATUS_TEMP_BASE, + .gbit = PB_STATUS_TEMPERATURE, + .limit = temp_limit_attrs, + .nlimit = ARRAY_SIZE(temp_limit_attrs), + }, { + .reg = PMBUS_READ_TEMPERATURE_2, + .class = PSC_TEMPERATURE, + .paged = true, + .update = true, + .compare = true, + .func = PMBUS_HAVE_TEMP2, + .sfunc = PMBUS_HAVE_STATUS_TEMP, + .sbase = PB_STATUS_TEMP_BASE, + .gbit = PB_STATUS_TEMPERATURE, + .limit = temp_limit_attrs2, + .nlimit = ARRAY_SIZE(temp_limit_attrs2), + }, { + .reg = PMBUS_READ_TEMPERATURE_3, + .class = PSC_TEMPERATURE, + .paged = true, + .update = true, + .compare = true, + .func = PMBUS_HAVE_TEMP3, + .sfunc = PMBUS_HAVE_STATUS_TEMP, + .sbase = PB_STATUS_TEMP_BASE, + .gbit = PB_STATUS_TEMPERATURE, + .limit = temp_limit_attrs3, + .nlimit = ARRAY_SIZE(temp_limit_attrs3), + } +}; + +static const int pmbus_fan_registers[] = { + PMBUS_READ_FAN_SPEED_1, +}; + +static const int pmbus_fan_config_registers[] = { + PMBUS_FAN_CONFIG_12, +}; + +static const int pmbus_fan_status_registers[] = { + PMBUS_STATUS_FAN_12, +}; + +static const u32 pmbus_fan_flags[] = { + PMBUS_HAVE_FAN12, +}; + +static const u32 pmbus_fan_status_flags[] = { + PMBUS_HAVE_STATUS_FAN12, +}; + +/* Fans */ +static int pmbus_add_fan_attributes(struct i2c_client *client, + struct pmbus_data *data) +{ + const struct pmbus_driver_info *info = data->info; + int index = 1; + int page; + int ret; + + for (page = 0; page < info->pages; page++) { + int f; + + for (f = 0; f < ARRAY_SIZE(pmbus_fan_registers); f++) { + int regval; + + if (!(info->func[page] & pmbus_fan_flags[f])) + break; + + if (!pmbus_check_word_register(client, page, + pmbus_fan_registers[f])) + break; + + /* + * Skip fan if not installed. + * Each fan configuration register covers multiple fans, + * so we have to do some magic. + */ + regval = _pmbus_read_byte_data(client, page, + pmbus_fan_config_registers[f]); + if (regval < 0 || + (!(regval & (PB_FAN_1_INSTALLED >> ((f & 1) * 4))))) + continue; + + if (pmbus_add_sensor(data, "fan", "input", index, + page, pmbus_fan_registers[f], + PSC_FAN, true, true) == NULL) + return -ENOMEM; + + /* + * Each fan status register covers multiple fans, + * so we have to do some magic. + */ + if ((info->func[page] & pmbus_fan_status_flags[f]) && + pmbus_check_byte_register(client, + page, pmbus_fan_status_registers[f])) { + int base; + + if (f > 1) /* fan 3, 4 */ + base = PB_STATUS_FAN34_BASE + page; + else + base = PB_STATUS_FAN_BASE + page; + ret = pmbus_add_boolean(data, "fan", + "alarm", index, NULL, NULL, base, + PB_FAN_FAN1_WARNING >> (f & 1)); + if (ret) + return ret; + ret = pmbus_add_boolean(data, "fan", + "fault", index, NULL, NULL, base, + PB_FAN_FAN1_FAULT >> (f & 1)); + if (ret) + return ret; + } + index++; + } + } + return 0; +} + +/* mfr items */ +static int pmbus_add_mfr_attributes(struct i2c_client *client, + struct pmbus_data *data) +{ + int page = 0; + int i; + + for(i = 0; i < ARRAY_SIZE(pmbus_mfr_reg);i++){ + + if (pmbus_add_mfr(data, pmbus_mfr_reg[i].name, page, pmbus_mfr_reg[i].reg) == NULL){ + return -ENOMEM; + } + } + + return 0; +} + +/* status items */ +static int pmbus_add_status_attributes(struct i2c_client *client, + struct pmbus_data *data) +{ + int i; + + for(i = 0; i < ARRAY_SIZE(pmbus_status_reg);i++){ + if (pmbus_add_status(data, pmbus_status_reg[i].name, pmbus_status_reg[i].base, pmbus_status_reg[i].offset)){ + return -ENOMEM; + } + } + + return 0; +} + +static int pmbus_find_attributes(struct i2c_client *client, + struct pmbus_data *data) +{ + int ret; + + /* Voltage sensors */ + ret = pmbus_add_sensor_attrs(client, data, "in", voltage_attributes, + ARRAY_SIZE(voltage_attributes)); + if (ret) + return ret; + + /* Current sensors */ + ret = pmbus_add_sensor_attrs(client, data, "curr", current_attributes, + ARRAY_SIZE(current_attributes)); + if (ret) + return ret; + + /* Temperature sensors */ + ret = pmbus_add_sensor_attrs(client, data, "temp", temp_attributes, + ARRAY_SIZE(temp_attributes)); + if (ret) + return ret; + + /* Fans */ + ret = pmbus_add_fan_attributes(client, data); + if (ret) + return ret; + + /* mfr data */ + ret = pmbus_add_mfr_attributes(client, data); + if (ret) + return ret; + + /* status data */ + ret = pmbus_add_status_attributes(client, data); + return ret; +} + +/* + * Identify chip parameters. + * This function is called for all chips. + */ +static int pmbus_identify_common(struct i2c_client *client, + struct pmbus_data *data, int page) +{ + int vout_mode = -1; + + if (pmbus_check_byte_register(client, page, PMBUS_VOUT_MODE)) + vout_mode = _pmbus_read_byte_data(client, page, + PMBUS_VOUT_MODE); + if (vout_mode >= 0 && vout_mode != 0xff) { + /* + * Not all chips support the VOUT_MODE command, + * so a failure to read it is not an error. + */ + switch (vout_mode >> 5) { + case 0: /* linear mode */ + if (data->info->format[PSC_VOLTAGE_OUT] != linear) + return -ENODEV; + + data->exponent[page] = ((s8)(vout_mode << 3)) >> 3; + break; + case 1: /* VID mode */ + if (data->info->format[PSC_VOLTAGE_OUT] != vid) + return -ENODEV; + break; + case 2: /* direct mode */ + if (data->info->format[PSC_VOLTAGE_OUT] != direct) + return -ENODEV; + break; + default: + return -ENODEV; + } + } + + pmbus_clear_fault_page(client, page); + return 0; +} + +static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, + struct pmbus_driver_info *info) +{ + struct device *dev = &client->dev; + int page, ret; + + /* + * Some PMBus chips don't support PMBUS_STATUS_BYTE, so try + * to use PMBUS_STATUS_WORD instead if that is the case. + * Bail out if both registers are not supported. + */ + data->status_register = PMBUS_STATUS_BYTE; + ret = i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE); + if (ret < 0 || ret == 0xff) { + data->status_register = PMBUS_STATUS_WORD; + ret = i2c_smbus_read_word_data(client, PMBUS_STATUS_WORD); + if (ret < 0 || ret == 0xffff) { + dev_err(dev, "PMBus status register not found\n"); + return -ENODEV; + } + } + + pmbus_clear_faults(client); + + if (info->identify) { + ret = (*info->identify)(client, info); + if (ret < 0) { + dev_err(dev, "Chip identification failed\n"); + return ret; + } + } + + if (info->pages <= 0 || info->pages > PMBUS_PAGES) { + dev_err(dev, "Bad number of PMBus pages: %d\n", info->pages); + return -ENODEV; + } + + /* Current only using page 1 in BMS project */ + info->pages = 1; + + for (page = 0; page < info->pages; page++) { + ret = pmbus_identify_common(client, data, page); + if (ret < 0) { + dev_err(dev, "Failed to identify chip capabilities\n"); + return ret; + } + } + return 0; +} + +int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info) +{ + struct device *dev = &client->dev; + const struct pmbus_platform_data *pdata = dev_get_platdata(dev); + struct pmbus_data *data; + int ret; + + if (!info) + return -ENODEV; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE + | I2C_FUNC_SMBUS_BYTE_DATA + | I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->dev = dev; + + if (pdata) + data->flags = pdata->flags; + data->info = info; + + ret = pmbus_init_common(client, data, info); + if (ret < 0) + return ret; + + ret = pmbus_find_attributes(client, data); + if (ret) + goto out_kfree; + + /* + * If there are no attributes, something is wrong. + * Bail out instead of trying to register nothing. + */ + if (!data->num_attributes) { + dev_err(dev, "No attributes found\n"); + ret = -ENODEV; + goto out_kfree; + } + + data->groups[0] = &data->group; + data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + if (IS_ERR(data->hwmon_dev)) { + ret = PTR_ERR(data->hwmon_dev); + dev_err(dev, "Failed to register hwmon device\n"); + goto out_kfree; + } + return 0; + +out_kfree: + kfree(data->group.attrs); + return ret; +} + +int pmbus_do_remove(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + kfree(data->group.attrs); + return 0; +} + + +/* + * Find sensor groups and status registers on each page. + */ +static void pmbus_find_sensor_groups(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int page; + + /* Sensors detected on page 0 only */ + if (pmbus_check_word_register(client, 0, PMBUS_READ_VIN)) + info->func[0] |= PMBUS_HAVE_VIN; + if (pmbus_check_word_register(client, 0, PMBUS_READ_VCAP)) + info->func[0] |= PMBUS_HAVE_VCAP; + if (pmbus_check_word_register(client, 0, PMBUS_READ_IIN)) + info->func[0] |= PMBUS_HAVE_IIN; + if (pmbus_check_word_register(client, 0, PMBUS_READ_PIN)) + info->func[0] |= PMBUS_HAVE_PIN; + if (info->func[0] + && pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT)) + info->func[0] |= PMBUS_HAVE_STATUS_INPUT; + if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) && + pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) { + info->func[0] |= PMBUS_HAVE_FAN12; + if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN12; + } + if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) && + pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) { + info->func[0] |= PMBUS_HAVE_FAN34; + if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN34; + } + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) + info->func[0] |= PMBUS_HAVE_TEMP; + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2)) + info->func[0] |= PMBUS_HAVE_TEMP2; + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3)) + info->func[0] |= PMBUS_HAVE_TEMP3; + if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 + | PMBUS_HAVE_TEMP3) + && pmbus_check_byte_register(client, 0, + PMBUS_STATUS_TEMPERATURE)) + info->func[0] |= PMBUS_HAVE_STATUS_TEMP; + + /* Sensors detected on all pages */ + for (page = 0; page < info->pages; page++) { + if (pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) { + info->func[page] |= PMBUS_HAVE_VOUT; + if (pmbus_check_byte_register(client, page, + PMBUS_STATUS_VOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_VOUT; + } + if (pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) { + info->func[page] |= PMBUS_HAVE_IOUT; + if (pmbus_check_byte_register(client, 0, + PMBUS_STATUS_IOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_IOUT; + } + if (pmbus_check_word_register(client, page, PMBUS_READ_POUT)) + info->func[page] |= PMBUS_HAVE_POUT; + } +} + +/* + * Identify chip parameters. + */ +static int pmbus_identify(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int ret = 0; + + if (!info->pages) { + /* + * Check if the PAGE command is supported. If it is, + * keep setting the page number until it fails or until the + * maximum number of pages has been reached. Assume that + * this is the number of pages supported by the chip. + */ + if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) { + int page; + + for (page = 1; page < PMBUS_PAGES; page++) { + if (pmbus_set_page(client, page) < 0) + break; + } + pmbus_set_page(client, 0); + info->pages = page; + } else { + info->pages = 1; + } + } + + if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) { + int vout_mode; + + vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); + if (vout_mode >= 0 && vout_mode != 0xff) { + switch (vout_mode >> 5) { + case 0: + break; + case 1: + info->format[PSC_VOLTAGE_OUT] = vid; + break; + case 2: + info->format[PSC_VOLTAGE_OUT] = direct; + break; + default: + ret = -ENODEV; + goto abort; + } + } + } + + /* + * We should check if the COEFFICIENTS register is supported. + * If it is, and the chip is configured for direct mode, we can read + * the coefficients from the chip, one set per group of sensor + * registers. + * + * To do this, we will need access to a chip which actually supports the + * COEFFICIENTS command, since the command is too complex to implement + * without testing it. Until then, abort if a chip configured for direct + * mode was detected. + */ + if (info->format[PSC_VOLTAGE_OUT] == direct) { + ret = -ENODEV; + goto abort; + } + + /* Try to find sensor groups */ + pmbus_find_sensor_groups(client, info); +abort: + return ret; +} + +static int pmbus_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pmbus_driver_info *info; + + info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), + GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->pages = id->driver_data; + info->identify = pmbus_identify; + + return pmbus_do_probe(client, id, info); +} + +/* + * Use driver_data to set the number of pages supported by the chip. + */ +static const struct i2c_device_id pmbus_id[] = { + {"fse000", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, pmbus_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver pmbus_driver = { + .driver = { + .name = "fse000", + }, + .probe = pmbus_probe, + .remove = pmbus_do_remove, + .id_table = pmbus_id, +}; + +module_i2c_driver(pmbus_driver); + +MODULE_DESCRIPTION("mitac_ly1200_32x_fse000 driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_gpe.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_gpe.c new file mode 100644 index 000000000000..3ced2b0a399b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_gpe.c @@ -0,0 +1,93 @@ +#include +#include + +#define BMS_GPE_CLASS "bms_acpi" +#define BMS_GPE_DRIVER_NAME "bms_gpe" +#define BMS_GPE_DEVICE_NAME "bms_acpi_gpe" + +static int bms_gpe[] = {0x01, 0x02, 0x47}; +static int bms_gpe_num = sizeof(bms_gpe) / sizeof(bms_gpe[0]); + +static u32 bms_gpe_handler(acpi_handle handle, u32 gpe_num, void *context) +{ + struct acpi_device *device = context; + + acpi_bus_generate_netlink_event(device->pnp.device_class,dev_name(&device->dev), + gpe_num, 0); + return ACPI_INTERRUPT_HANDLED; /* GPE will be disable afterward */ +} + +static int bms_gpe_add(struct acpi_device *device) +{ + acpi_status status; + int i = 0; + char info_str[60] = { 0 }; + char temp[6] = { 0 }; + + if (!device) { + printk("No device of BMS GPE\n"); + return -EINVAL; + } + + strcpy(acpi_device_name(device), BMS_GPE_DEVICE_NAME); + strcpy(acpi_device_class(device), BMS_GPE_CLASS); + + strncat(info_str, "Initialized GPE list = ", 23); + for (i = 0; i < bms_gpe_num; i++) { + status = acpi_install_gpe_handler(NULL, bms_gpe[i], + ACPI_GPE_LEVEL_TRIGGERED, + &bms_gpe_handler, device); + if (status != AE_OK) { + printk("Fail to claim BMS GPE%X (code:0x%X)\n",bms_gpe[i],status); + return -EINVAL; + } + snprintf(temp, sizeof(temp), "0x%.2X ", bms_gpe[i]); + strncat(info_str, temp, 6); + } + + dev_info(&device->dev, "%s.\n", info_str); + + return 0; +} + +static int bms_gpe_remove(struct acpi_device *device) +{ + int i = 0; + for (i = 0; i < bms_gpe_num; i++) { + acpi_remove_gpe_handler(NULL, bms_gpe[i], &bms_gpe_handler); + } + return 0; +} + +static const struct acpi_device_id bms_acpi_device_ids[] = { + { "PNP0C01", 0 }, + { /* END OF LIST */ } +}; + +static struct acpi_driver bms_gpe_driver = { + .name = BMS_GPE_DRIVER_NAME, + .class = BMS_GPE_CLASS, + .ids = bms_acpi_device_ids, + .ops = { + .add = bms_gpe_add, + .remove = bms_gpe_remove, + }, +}; + +static int __init bms_gpe_init(void) +{ + printk(KERN_INFO "%s: init.\n", __FUNCTION__); + return acpi_bus_register_driver(&bms_gpe_driver); +} + +static void __exit bms_gpe_exit(void) +{ + printk(KERN_INFO "%s: exit.\n", __FUNCTION__); + acpi_bus_unregister_driver(&bms_gpe_driver); +} + +module_init(bms_gpe_init); +module_exit(bms_gpe_exit); +MODULE_AUTHOR("Yencheng Lin "); +MODULE_DESCRIPTION("mitac_ly1200_32x_gpe driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_master_cpld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_master_cpld.c new file mode 100644 index 000000000000..921a2ea424a3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_master_cpld.c @@ -0,0 +1,503 @@ +#include +#include + +#include "master_cpld_reg.h" +#include "master_cpld_sysfs.h" + +static int debug_flag = 0; + +struct master_cpld_data { + struct mutex lock; + + struct i2c_client *client; + struct device_attribute bin; +}; + + +static const struct i2c_device_id master_cpld_ids[] = { + { "master_cpld", 0 }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, master_cpld_ids); + +static int master_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){ + unsigned int reg_val = 0, fld_val; + static int debug_flag; + struct master_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int err; + + if (reg_width != 8){ + printk("%s: Register table width setting failed.\n", reg_name); + return -EINVAL; + } + mutex_lock(&data->lock); + if ((err = i2c_smbus_read_byte_data(client, (u8)reg_offset)) < 0) { + /* CPLD read error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c read failed, error code = %d.\n", reg_name, err); + return err; + } + reg_val = err; + if (debug_flag) { + printk("%s: reg_offset = %d, width = %d, cur value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + mutex_unlock(&data->lock); + if (fld_width == reg_width) {fld_val = reg_val & fld_mask;} + else {fld_val = (reg_val >> fld_shift) & fld_mask;} + return sprintf(buf, "0x%x\n", fld_val); +} + +static int master_cpld_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){ + int ret_code; + unsigned int reg_val, fld_val; + unsigned long val; + static int debug_flag; + struct master_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + if (reg_width != 8){ + printk("%s: Register table width setting failed.\n", reg_name); + return -EINVAL; + } + /* Parse buf and store to fld_val */ + if ((ret_code = kstrtoul(buf, 16, &val))){ + printk("%s: Conversion value = %s failed, errno = %d.\n", reg_name, buf, ret_code); + return ret_code; + } + fld_val = (unsigned int)val; + mutex_lock(&data->lock); + if ((ret_code = i2c_smbus_read_byte_data(client, (u8)reg_offset)) < 0) { + /* Handle CPLD read error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c read failed, error code = %d.\n", reg_name, ret_code); + return ret_code; + } + reg_val = ret_code; + if (debug_flag) { + printk("%s: offset = %d, width = %d, cur value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + if (fld_width == reg_width) {reg_val = fld_val & fld_mask;} + else {reg_val = (reg_val & ~(fld_mask << fld_shift)) | + ((fld_val & (fld_mask)) << fld_shift);} + if ((ret_code = i2c_smbus_write_byte_data(client, (u8)reg_offset, (u8)reg_val)) != 0) { + /* Handle CPLD write error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c write failed, error code = %d.\n", reg_name, ret_code); + return ret_code; + } + else if (debug_flag) { + printk("%s: offset = %d, width = %d, new value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + mutex_unlock(&data->lock); + return count; +} + +/*--------------------special file for debug---------------------- */ +static ssize_t master_cpld_debug_read(struct device *dev, struct device_attribute *attr, + char *buf){ + + return sprintf(buf, "%d\n", debug_flag); +} + + +static ssize_t master_cpld_debug_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int temp; + int error; + + error = kstrtoint(buf, 10, &temp); + if (error){ + printk(KERN_INFO "%s: Conversion value = %s failed.\n", __FUNCTION__, buf); + return count; + } + debug_flag = temp; + + if(debug_flag) + printk("%s, debug_flag = %d\n", __FUNCTION__, debug_flag); + + return count; +} +SYSFS_MISC_RW_ATTR_DEF(debug, master_cpld_debug_read, master_cpld_debug_write) + + + + +/* ----------------define port group---------------------------- */ +static struct attribute *port1_attributes[] = { + SYSFS_ATTR_PTR(port1_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port1_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port1_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port1_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port1_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port1_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + + +static struct attribute *port2_attributes[] = { + SYSFS_ATTR_PTR(port2_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port2_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port2_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port2_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port2_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port2_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + + +static struct attribute *port3_attributes[] = { + SYSFS_ATTR_PTR(port3_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port3_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port3_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port3_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port3_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port3_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + +static struct attribute *port4_attributes[] = { + SYSFS_ATTR_PTR(port4_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port4_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port4_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port4_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port4_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port4_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + +static struct attribute *port5_attributes[] = { + SYSFS_ATTR_PTR(port5_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port5_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port5_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port5_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port5_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port5_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + +static struct attribute *port6_attributes[] = { + SYSFS_ATTR_PTR(port6_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port6_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port6_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port6_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port6_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port6_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + +static struct attribute *port7_attributes[] = { + SYSFS_ATTR_PTR(port7_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port7_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port7_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port7_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port7_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port7_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + +static struct attribute *port8_attributes[] = { + SYSFS_ATTR_PTR(port8_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port8_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port8_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port8_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port8_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port8_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + +static struct attribute *port9_attributes[] = { + SYSFS_ATTR_PTR(port9_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port9_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port9_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port9_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port9_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port9_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port10_attributes[] = { + SYSFS_ATTR_PTR(port10_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port10_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port10_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port10_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port10_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port10_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port11_attributes[] = { + SYSFS_ATTR_PTR(port11_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port11_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port11_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port11_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port11_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port11_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port12_attributes[] = { + SYSFS_ATTR_PTR(port12_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port12_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port12_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port12_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port12_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port12_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port13_attributes[] = { + SYSFS_ATTR_PTR(port13_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port13_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port13_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port13_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port13_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port13_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port14_attributes[] = { + SYSFS_ATTR_PTR(port14_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port14_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port14_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port14_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port14_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port14_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port15_attributes[] = { + SYSFS_ATTR_PTR(port15_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port15_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port15_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port15_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port15_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port15_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port16_attributes[] = { + SYSFS_ATTR_PTR(port16_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port16_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port16_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port16_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port16_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port16_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + + +static const struct attribute_group master_cpld_port_group[] = { + {.attrs = port1_attributes, + .name = "port1",}, + {.attrs = port2_attributes, + .name = "port2",}, + {.attrs = port3_attributes, + .name = "port3",}, + {.attrs = port4_attributes, + .name = "port4",}, + {.attrs = port5_attributes, + .name = "port5",}, + {.attrs = port6_attributes, + .name = "port6",}, + {.attrs = port7_attributes, + .name = "port7",}, + {.attrs = port8_attributes, + .name = "port8",}, + {.attrs = port9_attributes, + .name = "port9",}, + {.attrs = port10_attributes, + .name = "port10",}, + {.attrs = port11_attributes, + .name = "port11",}, + {.attrs = port12_attributes, + .name = "port12",}, + {.attrs = port13_attributes, + .name = "port13",}, + {.attrs = port14_attributes, + .name = "port14",}, + {.attrs = port15_attributes, + .name = "port15",}, + {.attrs = port16_attributes, + .name = "port16",} +}; + +/* ----------------define misc group---------------------------- */ +static struct attribute *misc_attributes[] = { + SYSFS_ATTR_PTR(mjr_rev), /* register: mstr_cpld_rev */ + SYSFS_ATTR_PTR(mnr_rev), /* register: mstr_cpld_rev */ + + SYSFS_ATTR_PTR(scrtch_reg), /* register: mstr_cpld_gpr */ + + SYSFS_ATTR_PTR(brd_rev), /* register: mb_brd_rev_type */ + SYSFS_ATTR_PTR(brd_type), /* register: mb_brd_rev_type */ + + SYSFS_ATTR_PTR(mb_rst), /* register: mstr_srr */ + SYSFS_ATTR_PTR(npu_rst), /* register: mstr_srr */ + SYSFS_ATTR_PTR(mgmt_phy_rst), /* register: mstr_srr */ + + SYSFS_ATTR_PTR(mb_eeprom_wp), /* register: eeprom_wp */ + SYSFS_ATTR_PTR(cpld_spi_wp), /* register: eeprom_wp */ + SYSFS_ATTR_PTR(fan_eeprom_wp), /* register: eeprom_wp */ + + SYSFS_ATTR_PTR(ps2_int_msk), /* register: mstr_irq */ + SYSFS_ATTR_PTR(ps1_int_msk), /* register: mstr_irq */ + SYSFS_ATTR_PTR(usb_fault_msk), /* register: mstr_irq */ + SYSFS_ATTR_PTR(pcie_int_msk), /* register: mstr_irq */ + SYSFS_ATTR_PTR(fan_alert_int_msk), /* register: mstr_irq */ + SYSFS_ATTR_PTR(usb_fault), /* register: mstr_irq */ + SYSFS_ATTR_PTR(pcie_int), /* register: mstr_irq */ + SYSFS_ATTR_PTR(fan_alert_int), /* register: mstr_irq */ + SYSFS_ATTR_PTR(system_led_fld), /* register: mstr_irq */ + SYSFS_ATTR_PTR(power_led), /* register: mstr_irq */ + SYSFS_ATTR_PTR(fan_led), /* register: mstr_irq */ + SYSFS_ATTR_PTR(locate_led), /* register: mstr_irq */ + + SYSFS_ATTR_PTR(led_test), /* register: fan_tray_3_1_led */ + SYSFS_ATTR_PTR(fan_tray3_led), /* register: fan_tray_3_1_led */ + SYSFS_ATTR_PTR(fan_tray2_led), /* register: fan_tray_3_1_led */ + SYSFS_ATTR_PTR(fan_tray1_led), /* register: fan_tray_3_1_led */ + SYSFS_ATTR_PTR(fan_tray6_led), /* register: fan_tray_6_4_led */ + SYSFS_ATTR_PTR(fan_tray5_led), /* register: fan_tray_6_4_led */ + SYSFS_ATTR_PTR(fan_tray4_led), /* register: fan_tray_6_4_led */ + + SYSFS_ATTR_PTR(fan_tray6_present), /* register: fan_tray_status */ + SYSFS_ATTR_PTR(fan_tray5_present), /* register: fan_tray_status */ + SYSFS_ATTR_PTR(fan_tray4_present), /* register: fan_tray_status */ + SYSFS_ATTR_PTR(fan_tray3_present), /* register: fan_tray_status */ + SYSFS_ATTR_PTR(fan_tray2_present), /* register: fan_tray_status */ + SYSFS_ATTR_PTR(fan_tray1_present), /* register: fan_tray_status */ + + SYSFS_ATTR_PTR(fan_type6), /* register: fan_type_status */ + SYSFS_ATTR_PTR(fan_type5), /* register: fan_type_status */ + SYSFS_ATTR_PTR(fan_type4), /* register: fan_type_status */ + SYSFS_ATTR_PTR(fan_type3), /* register: fan_type_status */ + SYSFS_ATTR_PTR(fan_type2), /* register: fan_type_status */ + SYSFS_ATTR_PTR(fan_type1), /* register: fan_type_status */ + + SYSFS_ATTR_PTR(ps1_ps), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps1_pg), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps1_int), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps1_on), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps2_ps), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps2_pg), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps2_int), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps2_on), /* register: psu_en_status */ + + SYSFS_ATTR_PTR(usb1_vbus_en), /* register: mb_pwr_en_status */ + SYSFS_ATTR_PTR(v5p0_en), /* register: mb_pwr_en_status */ + SYSFS_ATTR_PTR(v3p3_en), /* register: mb_pwr_en_status */ + SYSFS_ATTR_PTR(vcc_1v8_en), /* register: mb_pwr_en_status */ + SYSFS_ATTR_PTR(mac_avs1v_en), /* register: mb_pwr_en_status */ + SYSFS_ATTR_PTR(mac1v_en), /* register: mb_pwr_en_status */ + SYSFS_ATTR_PTR(vcc_1v25_en), /* register: mb_pwr_en_status */ + + SYSFS_ATTR_PTR(vcc_3p3_cpld), /* register: mb_pwr_status */ + SYSFS_ATTR_PTR(vcc5v_pg), /* register: mb_pwr_status */ + SYSFS_ATTR_PTR(vcc3v3_pg), /* register: mb_pwr_status */ + SYSFS_ATTR_PTR(vcc_1v8_pg), /* register: mb_pwr_status */ + SYSFS_ATTR_PTR(mac_avs1v_pg), /* register: mb_pwr_status */ + SYSFS_ATTR_PTR(mac1v_pg), /* register: mb_pwr_status */ + SYSFS_ATTR_PTR(vcc_1v25_pg), /* register: mb_pwr_status */ + + SYSFS_ATTR_PTR(port_1_8_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port_9_16_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port_1_8_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port_9_16_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port_1_8_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port_9_16_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port_1_8_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port_9_16_irq_status),/* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port_1_8_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + SYSFS_ATTR_PTR(port_9_16_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + SYSFS_ATTR_PTR(port_1_8_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port_9_16_lpmode), /* register: zqsfp28_lpmode_16_9 */ + + SYSFS_ATTR_PTR(fan_tray1_6_present), /* register: fan_tray_status */ + SYSFS_ATTR_PTR(psu_en_status_fld), /* register: psu_en_status*/ + + SYSFS_ATTR_PTR(debug), /* debug flag for print more messages */ + NULL +}; +static const struct attribute_group master_cpld_group_misc = { + .attrs = misc_attributes, +}; + +static int master_cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct master_cpld_data *master_cpld; + int err, i; + int grp_number = (int)( sizeof(master_cpld_port_group) / sizeof(master_cpld_port_group[0])); + + /* allocate memory to master_cpld */ + master_cpld = devm_kzalloc(&client->dev, sizeof(struct master_cpld_data) , GFP_KERNEL); + + if (!master_cpld) + return -ENOMEM; + + mutex_init(&master_cpld->lock); + + for(i = 0 ; i < grp_number ; i++){ + err = sysfs_create_group(&client->dev.kobj, &master_cpld_port_group[i]); + if (err){ + printk("%s: Error creeat port group %d.\n", __FUNCTION__, i+1); + } + } + err = sysfs_create_group(&client->dev.kobj, &master_cpld_group_misc); + if (err){ + printk("%s: Error creeat misc group.\n", __FUNCTION__); + } + + master_cpld->client = client; + i2c_set_clientdata(client, master_cpld); + + printk(KERN_INFO "%s: Master CPLD LCMXO3LF created.\n", __FUNCTION__); + + return 0; + +} + +static int master_cpld_remove(struct i2c_client *client) +{ + int i; + int grp_number = (int)( sizeof(master_cpld_port_group) / sizeof(master_cpld_port_group[0])); + + for(i = 0 ; i < grp_number ; i++){ + sysfs_remove_group(&client->dev.kobj, &master_cpld_port_group[i]); + } + sysfs_remove_group(&client->dev.kobj, &master_cpld_group_misc); + + printk(KERN_INFO "%s: Master CPLD removed.\n", __FUNCTION__); + return 0; +} + +static struct i2c_driver master_cpld_driver = { + .driver = { + .name = "master_cpld", + .owner = THIS_MODULE, + }, + .probe = master_cpld_probe, + .remove = master_cpld_remove, + .id_table = master_cpld_ids, +}; + +static int __init master_cpld_init(void) +{ + printk(KERN_INFO "%s: init.\n", __FUNCTION__); + return i2c_add_driver(&master_cpld_driver); +} +module_init(master_cpld_init); + +static void __exit master_cpld_exit(void) +{ + printk(KERN_INFO "%s: exit.\n", __FUNCTION__); + i2c_del_driver(&master_cpld_driver); +} +module_exit(master_cpld_exit); + +MODULE_DESCRIPTION("mitac_ly1200_32x_master_cpld driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_pb_i2c.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_pb_i2c.c new file mode 100644 index 000000000000..bad9260ab4ca --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_pb_i2c.c @@ -0,0 +1,137 @@ +#include +#include +#include "bms_i2c.h" + +#define BMS_PB_I2C_CLIENT_NUM 6 + +static struct i2c_client *bms_pb_clients[BMS_PB_I2C_CLIENT_NUM] = {NULL}; +static int bms_pb_client_index = 0; + +static int __init __find_i2c_adap(struct device *dev, void *data) +{ + const char *name = data; + static const char *prefix = "i2c-"; + struct i2c_adapter *adapter; + + if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) + { + return 0; + } + adapter = to_i2c_adapter(dev); + + return (strncmp(adapter->name, name, strlen(name)) == 0); +} + +static int __init find_i2c_adapter_num(enum i2c_adapter_type type) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + const char *name = bms_i2c_adapter_names[type]; + + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + + +static int __init find_i2c_mux_adapter_num(int parent_num, int num) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + char name[48]; + + snprintf(name, sizeof(name), "i2c-%d-mux (chan_id %d)", + parent_num, num); + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + +static __init struct i2c_client *bms_pb_setup_eeprom_24c01( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("24c01", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + + +static int __init bms_pb_setup_devices(void) +{ + struct i2c_adapter *adap; + int adap_num; + int parent_num; + + parent_num = find_i2c_adapter_num(I2C_ADAPTER_ISMT); + if (parent_num < 0) + return parent_num; + + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN3); + if (adap_num < 0) + return adap_num; + + adap = i2c_get_adapter(adap_num); + if (!adap) { + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + goto exit; + } + + bms_pb_clients[bms_pb_client_index++] = bms_pb_setup_eeprom_24c01(adap, 0x50); + bms_pb_clients[bms_pb_client_index++] = bms_pb_setup_eeprom_24c01(adap, 0x51); + +exit: + return 0; +} + +static int __init bms_pb_i2c_init(void) +{ + /* Initial bms_sb_slients array. */ + memset(bms_pb_clients, 0x0, BMS_PB_I2C_CLIENT_NUM); + + bms_pb_setup_devices(); + return 0; +} + + +static void __exit bms_pb_i2c_exit(void){ + int i; + + for (i=(bms_pb_client_index-1); i>=0; i--) { + if (bms_pb_clients[i]) { + i2c_unregister_device(bms_pb_clients[i]); + bms_pb_clients[i] = NULL; + } + } + + bms_pb_client_index = 0; + + +} + + +module_init(bms_pb_i2c_init); +module_exit(bms_pb_i2c_exit); + + +MODULE_DESCRIPTION("mitac_ly1200_32x_pb_i2c driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_sb_i2c.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_sb_i2c.c new file mode 100644 index 000000000000..e2a9718863ff --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_sb_i2c.c @@ -0,0 +1,514 @@ +#include +#include +#include +#include +#include +#include +#include "bms_i2c.h" + +/* Don't include MAC_AVS_1V */ +#define BMS_SB_I2C_CLIENT_NUM 35 +#define BMS_SB_ADAPTER_BASE 2 +#define BMS_SB_STAGE2_MUX_BUS_BASE 6 + + +static struct i2c_client *bms_sb_clients[BMS_SB_I2C_CLIENT_NUM] = {NULL}; +static int bms_sb_client_index = 0; + +enum bms_sb_switch_stage2_mux0_bus { + I2C_STAGE2_MUX0_CHAN0 = 0, + I2C_STAGE2_MUX0_CHAN1, + I2C_STAGE2_MUX0_CHAN2, + I2C_STAGE2_MUX0_CHAN3, + I2C_STAGE2_MUX0_CHAN4, + I2C_STAGE2_MUX0_CHAN5, + I2C_STAGE2_MUX0_CHAN6, + I2C_STAGE2_MUX0_CHAN7, +}; + +enum bms_sb_switch_stage2_mux1_bus { + I2C_STAGE2_MUX1_CHAN8 = 0, + I2C_STAGE2_MUX1_CHAN9, + I2C_STAGE2_MUX1_CHAN10, + I2C_STAGE2_MUX1_CHAN11, + I2C_STAGE2_MUX1_CHAN12, + I2C_STAGE2_MUX1_CHAN13, + I2C_STAGE2_MUX1_CHAN14, + I2C_STAGE2_MUX1_CHAN15, +}; + +enum bms_sb_switch_stage2_mux2_bus { + I2C_STAGE2_MUX2_CHAN16 = 0, + I2C_STAGE2_MUX2_CHAN17, + I2C_STAGE2_MUX2_CHAN18, + I2C_STAGE2_MUX2_CHAN19, + I2C_STAGE2_MUX2_CHAN20, + I2C_STAGE2_MUX2_CHAN21, + I2C_STAGE2_MUX2_CHAN22, + I2C_STAGE2_MUX2_CHAN23, +}; + +enum bms_sb_switch_stage2_mux3_bus { + I2C_STAGE2_MUX3_CHAN24 = 0, + I2C_STAGE2_MUX3_CHAN25, + I2C_STAGE2_MUX3_CHAN26, + I2C_STAGE2_MUX3_CHAN27, + I2C_STAGE2_MUX3_CHAN28, + I2C_STAGE2_MUX3_CHAN29, + I2C_STAGE2_MUX3_CHAN30, + I2C_STAGE2_MUX3_CHAN31, +}; + +static struct pca954x_platform_mode pmode_pca9548_mux[] = { + { .adap_id = BMS_SB_ADAPTER_BASE + 0, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 1, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 2, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 3, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 4, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 5, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 6, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 7, }, +}; + +static struct pca954x_platform_data platdata_pca9548_mux = { + .modes = pmode_pca9548_mux, + .num_modes = ARRAY_SIZE(pmode_pca9548_mux), +}; + +static struct pca954x_platform_mode pmode_stage1_pca9548_mux0[] = { + { .adap_id = BMS_SB_ADAPTER_BASE + 8, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 9, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 10, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 11, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 12, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 13, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 14, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 15, }, +}; + +static struct pca954x_platform_data platdata_stage1_pca9548_mux0 = { + .modes = pmode_stage1_pca9548_mux0, + .num_modes = ARRAY_SIZE(pmode_stage1_pca9548_mux0), +}; + +static struct pca954x_platform_mode pmode_stage1_pca9548_mux1[] = { + { .adap_id = BMS_SB_ADAPTER_BASE + 16, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 17, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 18, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 19, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 20, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 21, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 22, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 23, }, +}; + +static struct pca954x_platform_data platdata_stage1_pca9548_mux1 = { + .modes = pmode_stage1_pca9548_mux1, + .num_modes = ARRAY_SIZE(pmode_stage1_pca9548_mux1), +}; + +static struct pca954x_platform_mode pmode_stage1_pca9548_mux2[] = { + { .adap_id = BMS_SB_ADAPTER_BASE + 24, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 25, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 26, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 27, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 28, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 29, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 30, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 31, }, +}; + +static struct pca954x_platform_data platdata_stage1_pca9548_mux2 = { + .modes = pmode_stage1_pca9548_mux2, + .num_modes = ARRAY_SIZE(pmode_stage1_pca9548_mux2), +}; + +static struct pca954x_platform_mode pmode_stage1_pca9548_mux3[] = { + { .adap_id = BMS_SB_ADAPTER_BASE + 32, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 33, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 34, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 35, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 36, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 37, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 38, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 39, }, +}; + +static struct pca954x_platform_data platdata_stage1_pca9548_mux3 = { + .modes = pmode_stage1_pca9548_mux3, + .num_modes = ARRAY_SIZE(pmode_stage1_pca9548_mux3), +}; + +static int __init __find_i2c_adap(struct device *dev, void *data) +{ + const char *name = data; + static const char *prefix = "i2c-"; + struct i2c_adapter *adapter; + + if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) + { + return 0; + } + adapter = to_i2c_adapter(dev); + + return (strncmp(adapter->name, name, strlen(name)) == 0); +} + +static int __init find_i2c_adapter_num(enum i2c_adapter_type type) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + const char *name = bms_i2c_adapter_names[type]; + + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + +static int __init find_i2c_mux_adapter_num(int parent_num, int num) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + char name[48]; + + snprintf(name, sizeof(name), "i2c-%d-mux (chan_id %d)", + parent_num, num); + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + +static __init struct i2c_client *bms_sb_setup_eeprom_24c04( + struct i2c_adapter *adap) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("24c04", 0x50), + }; + + return i2c_new_device(adap, &info_spd); +} + +static __init struct i2c_client *bms_sb_setup_tmp75( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("tmp75", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + +static __init struct i2c_client *bms_sb_setup_switch(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("pca9548", 0x70), + .platform_data = &platdata_pca9548_mux, + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_stage1_mux0(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("pca9548", 0x71), + .platform_data = &platdata_stage1_pca9548_mux0, + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_stage1_mux1(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("pca9548", 0x72), + .platform_data = &platdata_stage1_pca9548_mux1, + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_stage1_mux2(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &platdata_stage1_pca9548_mux2, + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_stage1_mux3(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("pca9548", 0x74), + .platform_data = &platdata_stage1_pca9548_mux3, + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_slave_cpld(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("slave_cpld", 0x33), + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_master_cpld(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("master_cpld", 0x32), + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_sff8436(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("sff8436", 0x50), + }; + + return i2c_new_device(adap, &info); +} + +static int __init bms_sb_setup_devices_ismt(void) +{ + struct i2c_adapter *adap; + int adap_num = find_i2c_adapter_num(I2C_ADAPTER_ISMT); + + if (adap_num < 0) + return adap_num; + + adap = i2c_get_adapter(adap_num); + if (!adap) { + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + return 0; + } + + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_switch(adap); + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_master_cpld(adap); + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_slave_cpld(adap); + + return 0; +} + +static int __init bms_sb_setup_devices_stage1(void) +{ + struct i2c_adapter *adap; + int adap_num; + int parent_num; + + parent_num = find_i2c_adapter_num(I2C_ADAPTER_ISMT); + if (parent_num < 0) + return parent_num; + + /* Mux chan0 steup */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN0); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_eeprom_24c04(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN0); + } + + /* Mux chan1 connect to fan board */ + + /* Mux chan2 steup */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN2); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_tmp75(adap, 0x4a); + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_tmp75(adap, 0x4b); + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_tmp75(adap, 0x4c); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN2); + } + + /* Mux chan3 connect to power board */ + + /* Mux chan4 setup for i2c mux0 */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN4); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_stage1_mux0(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN4); + } + + /* Mux chan5 setup for i2c mux1 */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN5); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_stage1_mux1(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN5); + } + + /* Mux chan6 setup for i2c mux2 */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN6); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_stage1_mux2(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN6); + } + + /* Mux chan7 setup for i2c mux3 */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN7); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_stage1_mux3(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN7); + } + + return 0; +} + +static int __init bms_sb_setup_devices_stage2(void) +{ + struct i2c_adapter *adap; + int adap_num; + int i2c_base = sizeof(bms_i2c_adapter_names) / sizeof(bms_i2c_adapter_names[0]); + int i; + + /* stage2 mux0 chan0~7 install sff8436 */ + for(i = I2C_STAGE2_MUX0_CHAN0; i <= I2C_STAGE2_MUX0_CHAN7; i++){ + adap_num = find_i2c_mux_adapter_num(I2C_STAGE1_MUX_CHAN4 + i2c_base, I2C_STAGE2_MUX0_CHAN0 + i); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_sff8436(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN4 + i2c_base); + } + } + + /* stage2 mux1 chan0~7 install sff8436 */ + for(i = I2C_STAGE2_MUX1_CHAN8; i <= I2C_STAGE2_MUX1_CHAN15; i++){ + adap_num = find_i2c_mux_adapter_num(I2C_STAGE1_MUX_CHAN5 + i2c_base, I2C_STAGE2_MUX1_CHAN8 + i); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_sff8436(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN5 + i2c_base); + } + } + + /* stage2 mux2 chan0~7 install sff8436 */ + for(i = I2C_STAGE2_MUX2_CHAN16; i <= I2C_STAGE2_MUX2_CHAN23; i++){ + adap_num = find_i2c_mux_adapter_num(I2C_STAGE1_MUX_CHAN6 + i2c_base, I2C_STAGE2_MUX2_CHAN16 + i); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_sff8436(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN6 + i2c_base); + } + } + + /* stage2 mux3 chan0~7 install sff8436 */ + for(i = I2C_STAGE2_MUX3_CHAN24; i <= I2C_STAGE2_MUX3_CHAN31; i++){ + adap_num = find_i2c_mux_adapter_num(I2C_STAGE1_MUX_CHAN7 + i2c_base, I2C_STAGE2_MUX3_CHAN24 + i); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_sff8436(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN7 + i2c_base); + } + } +} + +static int __init bms_sb_i2c_init(void) +{ + /* Initial bms_sb_slients array. */ + memset(bms_sb_clients, 0x0, BMS_SB_I2C_CLIENT_NUM); + + bms_sb_setup_devices_ismt(); + mdelay(200); + bms_sb_setup_devices_stage1(); + mdelay(200); + bms_sb_setup_devices_stage2(); + + return 0; +} + +static void __exit bms_sb_i2c_exit(void){ + int i; + + for (i=(bms_sb_client_index-1); i>=0; i--) { + if (bms_sb_clients[i]) { + i2c_unregister_device(bms_sb_clients[i]); + bms_sb_clients[i] = NULL; + } + } + + bms_sb_client_index = 0; + +} + +module_init(bms_sb_i2c_init); +module_exit(bms_sb_i2c_exit); + +MODULE_DESCRIPTION("mitac_ly1200_32x_sb_i2c driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_slave_cpld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_slave_cpld.c new file mode 100644 index 000000000000..8809573fa4ad --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_slave_cpld.c @@ -0,0 +1,427 @@ +#include +#include + +#include "slave_cpld_reg.h" +#include "slave_cpld_sysfs.h" + +static int debug_flag = 0; + +struct slave_cpld_data { + struct mutex lock; + + struct i2c_client *client; + struct device_attribute bin; +}; + + +static const struct i2c_device_id slave_cpld_ids[] = { + { "slave_cpld", 0 }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, slave_cpld_ids); + +static int slave_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){ + unsigned int reg_val = 0, fld_val; + static int debug_flag; + struct slave_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int err; + + if (reg_width != 8){ + printk("%s: Register table width setting failed.\n", reg_name); + return -EINVAL; + } + mutex_lock(&data->lock); + if ((err = i2c_smbus_read_byte_data(client, (u8)reg_offset)) < 0) { + /* CPLD read error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c read failed, error code = %d.\n", reg_name, err); + return err; + } + reg_val = err; + if (debug_flag) { + printk("%s: reg_offset = %d, width = %d, cur value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + mutex_unlock(&data->lock); + if (fld_width == reg_width) {fld_val = reg_val & fld_mask;} + else {fld_val = (reg_val >> fld_shift) & fld_mask;} + return sprintf(buf, "0x%x\n", fld_val); +} + +static int slave_cpld_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){ + int ret_code; + unsigned int reg_val, fld_val; + unsigned long val; + static int debug_flag; + struct slave_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + if (reg_width != 8){ + printk("%s: Register table width setting failed.\n", reg_name); + return -EINVAL; + } + /* Parse buf and store to fld_val */ + if ((ret_code = kstrtoul(buf, 16, &val))){ + printk("%s: Conversion value = %s failed, errno = %d.\n", reg_name, buf, ret_code); + return ret_code; + } + fld_val = (unsigned int)val; + mutex_lock(&data->lock); + if ((ret_code = i2c_smbus_read_byte_data(client, (u8)reg_offset)) < 0) { + /* Handle CPLD read error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c read failed, error code = %d.\n", reg_name, ret_code); + return ret_code; + } + reg_val = ret_code; + if (debug_flag) { + printk("%s: offset = %d, width = %d, cur value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + if (fld_width == reg_width) {reg_val = fld_val & fld_mask;} + else {reg_val = (reg_val & ~(fld_mask << fld_shift)) | + ((fld_val & (fld_mask)) << fld_shift);} + if ((ret_code = i2c_smbus_write_byte_data(client, (u8)reg_offset, (u8)reg_val)) != 0) { + /* Handle CPLD write error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c write failed, error code = %d.\n", reg_name, ret_code); + return ret_code; + } + else if (debug_flag) { + printk("%s: offset = %d, width = %d, new value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + mutex_unlock(&data->lock); + return count; +} + +/*--------------------special file for debug---------------------- */ +static ssize_t slave_cpld_debug_read(struct device *dev, struct device_attribute *attr, + char *buf){ + + return sprintf(buf, "%d\n", debug_flag); +} + + +static ssize_t slave_cpld_debug_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int temp; + int error; + + error = kstrtoint(buf, 10, &temp); + if (error){ + printk(KERN_INFO "%s: Conversion value = %s failed.\n", __FUNCTION__, buf); + return count; + } + debug_flag = temp; + + if(debug_flag) + printk("%s, debug_flag = %d\n", __FUNCTION__, debug_flag); + + return count; +} +SYSFS_MISC_RW_ATTR_DEF(debug, slave_cpld_debug_read, slave_cpld_debug_write) + + + + +/* ----------------define port group---------------------------- */ +static struct attribute *port17_attributes[] = { + SYSFS_ATTR_PTR(port17_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port17_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port17_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port17_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port17_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port17_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port18_attributes[] = { + SYSFS_ATTR_PTR(port18_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port18_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port18_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port18_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port18_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port18_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port19_attributes[] = { + SYSFS_ATTR_PTR(port19_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port19_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port19_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port19_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port19_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port19_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port20_attributes[] = { + SYSFS_ATTR_PTR(port20_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port20_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port20_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port20_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port20_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port20_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port21_attributes[] = { + SYSFS_ATTR_PTR(port21_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port21_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port21_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port21_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port21_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port21_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port22_attributes[] = { + SYSFS_ATTR_PTR(port22_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port22_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port22_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port22_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port22_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port22_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port23_attributes[] = { + SYSFS_ATTR_PTR(port23_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port23_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port23_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port23_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port23_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port23_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port24_attributes[] = { + SYSFS_ATTR_PTR(port24_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port24_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port24_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port24_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port24_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port24_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port25_attributes[] = { + SYSFS_ATTR_PTR(port25_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port25_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port25_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port25_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port25_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port25_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port26_attributes[] = { + SYSFS_ATTR_PTR(port26_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port26_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port26_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port26_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port26_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port26_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port27_attributes[] = { + SYSFS_ATTR_PTR(port27_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port27_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port27_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port27_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port27_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port27_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port28_attributes[] = { + SYSFS_ATTR_PTR(port28_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port28_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port28_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port28_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port28_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port28_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port29_attributes[] = { + SYSFS_ATTR_PTR(port29_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port29_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port29_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port29_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port29_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port29_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port30_attributes[] = { + SYSFS_ATTR_PTR(port30_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port30_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port30_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port30_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port30_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port30_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port31_attributes[] = { + SYSFS_ATTR_PTR(port31_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port31_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port31_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port31_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port31_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port31_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port32_attributes[] = { + SYSFS_ATTR_PTR(port32_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port32_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port32_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port32_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port32_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port32_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static const struct attribute_group slave_cpld_port_group[] = { + {.attrs = port17_attributes, + .name = "port17",}, + {.attrs = port18_attributes, + .name = "port18",}, + {.attrs = port19_attributes, + .name = "port19",}, + {.attrs = port20_attributes, + .name = "port20",}, + {.attrs = port21_attributes, + .name = "port21",}, + {.attrs = port22_attributes, + .name = "port22",}, + {.attrs = port23_attributes, + .name = "port23",}, + {.attrs = port24_attributes, + .name = "port24",}, + {.attrs = port25_attributes, + .name = "port25",}, + {.attrs = port26_attributes, + .name = "port26",}, + {.attrs = port27_attributes, + .name = "port27",}, + {.attrs = port28_attributes, + .name = "port28",}, + {.attrs = port29_attributes, + .name = "port29",}, + {.attrs = port30_attributes, + .name = "port30",}, + {.attrs = port31_attributes, + .name = "port31",}, + {.attrs = port32_attributes, + .name = "port32",} +}; + +/* ----------------define misc group---------------------------- */ +static struct attribute *misc_attributes[] = { + SYSFS_ATTR_PTR(mjr_rev), /* register: slv_cpld_rev */ + SYSFS_ATTR_PTR(mnr_rev), /* register: slv_cpld_rev */ + SYSFS_ATTR_PTR(scrtch_reg), /* register: slv_cpld_gpr */ + SYSFS_ATTR_PTR(brd_rev), /* register: mb_brd_rev_type */ + SYSFS_ATTR_PTR(brd_type), /* register: mb_brd_rev_type */ + + SYSFS_ATTR_PTR(port_17_24_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port_25_32_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port_17_24_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port_25_32_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port_17_24_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port_25_32_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port_17_24_irq_status),/* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port_25_32_irq_status),/* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port_17_24_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + SYSFS_ATTR_PTR(port_25_32_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + SYSFS_ATTR_PTR(port_17_24_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port_25_32_lpmode), /* register: zqsfp28_lpmode_32_25 */ + + SYSFS_ATTR_PTR(debug), /* debug flag for print more messages */ + NULL +}; +static const struct attribute_group slave_cpld_group_misc = { + .attrs = misc_attributes, +}; + +static int slave_cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct slave_cpld_data *slave_cpld; + int err, i; + int grp_number = (int)( sizeof(slave_cpld_port_group) / sizeof(slave_cpld_port_group[0])); + + /* allocate memory to slave_cpld */ + slave_cpld = devm_kzalloc(&client->dev, sizeof(struct slave_cpld_data) , GFP_KERNEL); + + if (!slave_cpld) + return -ENOMEM; + + mutex_init(&slave_cpld->lock); + + for(i = 0 ; i < grp_number ; i++){ + err = sysfs_create_group(&client->dev.kobj, &slave_cpld_port_group[i]); + if (err){ + printk("%s: Error creeat port group %d.\n", __FUNCTION__, i+1); + } + } + err = sysfs_create_group(&client->dev.kobj, &slave_cpld_group_misc); + if (err){ + printk("%s: Error creeat misc group.\n", __FUNCTION__); + } + + slave_cpld->client = client; + i2c_set_clientdata(client, slave_cpld); + + printk(KERN_INFO "%s: Slave CPLD LCMXO3LF created.\n", __FUNCTION__); + + return 0; + +} + +static int slave_cpld_remove(struct i2c_client *client) +{ + int i; + int grp_number = (int)( sizeof(slave_cpld_port_group) / sizeof(slave_cpld_port_group[0])); + + for(i = 0 ; i < grp_number ; i++){ + sysfs_remove_group(&client->dev.kobj, &slave_cpld_port_group[i]); + } + sysfs_remove_group(&client->dev.kobj, &slave_cpld_group_misc); + + printk(KERN_INFO "%s: Slave CPLD removed.\n", __FUNCTION__); + return 0; +} + +static struct i2c_driver slave_cpld_driver = { + .driver = { + .name = "slave_cpld", + .owner = THIS_MODULE, + }, + .probe = slave_cpld_probe, + .remove = slave_cpld_remove, + .id_table = slave_cpld_ids, +}; + +static int __init slave_cpld_init(void) +{ + printk(KERN_INFO "%s: init.\n", __FUNCTION__); + return i2c_add_driver(&slave_cpld_driver); +} +module_init(slave_cpld_init); + +static void __exit slave_cpld_exit(void) +{ + printk(KERN_INFO "%s: exit.\n", __FUNCTION__); + i2c_del_driver(&slave_cpld_driver); +} +module_exit(slave_cpld_exit); + +MODULE_DESCRIPTION("mitac_ly1200_32x_slave_cpld driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c new file mode 100644 index 000000000000..e5af8b70bf9a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c @@ -0,0 +1,541 @@ +#define CONFIG_DRV_SYSCPLD_WDT 1 + +#include +#include + +#include "system_cpld_reg.h" +#include "system_cpld_sysfs.h" +#ifdef CONFIG_DRV_SYSCPLD_WDT +#include +#include +#include +#include +#include +#include +#endif + +static int debug_flag = 0; + +struct system_cpld_data { + struct mutex lock; + + struct i2c_client *client; + struct device_attribute bin; +}; +struct system_cpld_data *system_cpld; + +static const struct i2c_device_id system_cpld_ids[] = { + { "system_cpld", 0 }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, system_cpld_ids); + +static int system_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){ + unsigned int reg_val = 0, fld_val; + static int debug_flag; + struct system_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int err; + + if (reg_width != 8){ + printk("%s: Register table width setting failed.\n", reg_name); + return -EINVAL; + } + mutex_lock(&data->lock); + if ((err = i2c_smbus_read_byte_data(client, (u8)reg_offset)) < 0) { + /* CPLD read error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c read failed, error code = %d.\n", reg_name, err); + return err; + } + reg_val = err; + if (debug_flag) { + printk("%s: reg_offset = %d, width = %d, cur value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + mutex_unlock(&data->lock); + if (fld_width == reg_width) {fld_val = reg_val & fld_mask;} + else {fld_val = (reg_val >> fld_shift) & fld_mask;} + return sprintf(buf, "0x%x\n", fld_val); +} + +static int system_cpld_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){ + int ret_code; + unsigned int reg_val, fld_val; + unsigned long val; + static int debug_flag; + struct system_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + if (reg_width != 8){ + printk("%s: Register table width setting failed.\n", reg_name); + return -EINVAL; + } + /* Parse buf and store to fld_val */ + if ((ret_code = kstrtoul(buf, 16, &val))){ + printk("%s: Conversion value = %s failed, errno = %d.\n", reg_name, buf, ret_code); + return ret_code; + } + fld_val = (unsigned int)val; + mutex_lock(&data->lock); + if ((ret_code = i2c_smbus_read_byte_data(client, (u8)reg_offset)) < 0) { + /* Handle CPLD read error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c read failed, error code = %d.\n", reg_name, ret_code); + return ret_code; + } + reg_val = ret_code; + if (debug_flag) { + printk("%s: offset = %d, width = %d, cur value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + if (fld_width == reg_width) {reg_val = fld_val & fld_mask;} + else {reg_val = (reg_val & ~(fld_mask << fld_shift)) | + ((fld_val & (fld_mask)) << fld_shift);} + if ((ret_code = i2c_smbus_write_byte_data(client, (u8)reg_offset, (u8)reg_val)) != 0) { + /* Handle CPLD write error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c write failed, error code = %d.\n", reg_name, ret_code); + return ret_code; + } + else if (debug_flag) { + printk("%s: offset = %d, width = %d, new value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + mutex_unlock(&data->lock); + return count; +} + +/*--------------------special file for debug---------------------- */ +static ssize_t system_cpld_debug_read(struct device *dev, struct device_attribute *attr, + char *buf){ + + return sprintf(buf, "%d\n", debug_flag); +} + + +static ssize_t system_cpld_debug_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int temp; + int error; + + error = kstrtoint(buf, 10, &temp); + if (error){ + printk(KERN_INFO "%s: Conversion value = %s failed.\n", __FUNCTION__, buf); + return count; + } + debug_flag = temp; + + if(debug_flag) + printk("%s, debug_flag = %d\n", __FUNCTION__, debug_flag); + + return count; +} +SYSFS_MISC_RW_ATTR_DEF(debug, system_cpld_debug_read, system_cpld_debug_write) + + +/* ----------------define misc group---------------------------- */ +static struct attribute *misc_attributes[] = { + SYSFS_ATTR_PTR(mjr_rev), /* register: sys_cpld_rev */ + SYSFS_ATTR_PTR(mnr_rev), /* register: sys_cpld_rev */ + + SYSFS_ATTR_PTR(scrtch_reg), /* register: sys_cpld_gpr */ + + SYSFS_ATTR_PTR(brd_rev), /* register: cpu_brd_rev_type */ + SYSFS_ATTR_PTR(brd_type), /* register: cpu_brd_rev_type */ + + SYSFS_ATTR_PTR(ssd_present), /* register: sys_srr */ + SYSFS_ATTR_PTR(spi_cs_sel), /* register: sys_srr */ + SYSFS_ATTR_PTR(rst_bios_switch), /* register: sys_srr */ + SYSFS_ATTR_PTR(cpld_upgrade_rst), /* register: sys_srr */ + + SYSFS_ATTR_PTR(cpld_spi_wp), /* register: sys_eeprom_wp */ + SYSFS_ATTR_PTR(system_id_eeprom_wp), /* register: sys_eeprom_wp */ + SYSFS_ATTR_PTR(spi_me_wp), /* register: sys_eeprom_wp */ + SYSFS_ATTR_PTR(spi_bios_wp), /* register: sys_eeprom_wp */ + SYSFS_ATTR_PTR(spi_bak_bios_wp), /* register: sys_eeprom_wp */ + + SYSFS_ATTR_PTR(vrhot_irq_en), /* register: sys_irq */ + SYSFS_ATTR_PTR(cpu_thermtrip_irq_en), /* register: sys_irq */ + SYSFS_ATTR_PTR(temp_alert_irq_en), /* register: sys_irq */ + SYSFS_ATTR_PTR(vrhot_irq), /* register: sys_irq */ + SYSFS_ATTR_PTR(cpu_thermtrip_irq), /* register: sys_irq */ + SYSFS_ATTR_PTR(temp_alert_irq), /* register: sys_irq */ + + SYSFS_ATTR_PTR(wd_timer), /* register: sys_wd */ + SYSFS_ATTR_PTR(wd_en), /* register: sys_wd */ + SYSFS_ATTR_PTR(wd_punch), /* register: sys_wd */ + + SYSFS_ATTR_PTR(mb_rst_en), /* register: sys_mb_rst_en */ + + SYSFS_ATTR_PTR(pwr_v3p3_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_vcc_vnn_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_vccsram_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_vddq_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_vcc_ref_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_v1p05_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_v1p8_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_v2p5_en), /* register: cpu_pwr_en_status */ + + SYSFS_ATTR_PTR(pg_v3p3), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_vcc_vnn), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_vccsram), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_vddq), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_vcc_ref), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_v1p05), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_v1p8), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_v2p5), /* register: cpu_pwr_status */ + + SYSFS_ATTR_PTR(debug), /* debug flag for print more messages */ + NULL +}; +static const struct attribute_group system_cpld_group_misc = { + .attrs = misc_attributes, +}; + +#ifdef CONFIG_DRV_SYSCPLD_WDT +/* + ***************************************************************************** + * + * Watchdog Driver + * + ***************************************************************************** + */ +/* wdt_timeout[] are defined by CPLD spec , -1 means researved + 300 sec is not supported */ +int wdt_timeout[]={15,30,60,90,120,180,240,300,-1,-1,-1,-1,-1,-1,-1,-1}; +#define WD_TIMO_MAX_NUM 16 +/* Default margin */ +#define WD_TIMO 30 + +static int wdt_margin = WD_TIMO; +module_param(wdt_margin, int, 0); +MODULE_PARM_DESC(wdt_margin, "Watchdog timeout in seconds (default " + __MODULE_STRING(WD_TIMO) "s)"); + +static unsigned long wdt_is_open; +static int boot_flag; + +/** + * wdt_ping: + * + * Reload counter one with the watchdog timeout. We don't bother reloading + * the cascade counter. + */ +static void wdt_ping(void) +{ + struct device *dev = &system_cpld->client->dev; + struct device_attribute *fake_attr=NULL; + char *buf="0";/* 0: punch is defined by CPLD spec */ + int err; + err = system_cpld_wd_punch_raw_write(dev, fake_attr, buf, (size_t)0); + if(err < 0){ + system_cpld_wd_punch_raw_write(dev, fake_attr, buf, (size_t)0); + } +} + +/** + * wdt_disable: + * + * disables watchdog. + */ +static void wdt_disable(void) +{ + struct device *dev = &system_cpld->client->dev; + struct device_attribute *fake_attr=NULL; + char *buf="0";/* 0: disable is defined by CPLD spec */ + int err; + err = system_cpld_wd_en_raw_write(dev, fake_attr, buf, (size_t)0); + if(err < 0){ + system_cpld_wd_en_raw_write(dev, fake_attr, buf, (size_t)0); + } +} + +/** + * wdt_enable: + * + * enables watchdog. + */ +static void wdt_enable(void) +{ + struct device *dev = &system_cpld->client->dev; + struct device_attribute *fake_attr=NULL; + char *buf="1";/* 1: enable is defined by CPLD spec */ + int err; + err = system_cpld_wd_en_raw_write(dev, fake_attr, buf, (size_t)0); + if(err < 0){ + system_cpld_wd_en_raw_write(dev, fake_attr, buf, (size_t)0); + } +} + +/** + * wdt_set_timeout: + * + * set watchdog timeout. + */ +static void wdt_set_timeout(int index) +{ + struct device *dev = &system_cpld->client->dev; + struct device_attribute *fake_attr=NULL; + char buf[1]; + if ( WD_TIMO_MAX_NUM == 16 ) { + sprintf(buf,"%x",index); + system_cpld_wd_timer_raw_write(dev, fake_attr, buf, (size_t)0); + } + else + printk(KERN_INFO "%s: It is out of spec.\n", __FUNCTION__); +} + +/** + * wdt_write: + * @file: file handle to the watchdog + * @buf: buffer to write (unused as data does not matter here + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ +static ssize_t wdt_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + wdt_ping(); + return 1; + } + return 0; +} + +/** + * wdt_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. We only actually usefully support + * querying capabilities and current status. + */ +static int wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int new_margin, rv, i; + static struct watchdog_info ident = { + .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, + .firmware_version = 1, + .identity = "SYS_CPLD WTD" + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info __user *)arg, &ident, + sizeof(ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(boot_flag, (int __user *)arg); + case WDIOC_KEEPALIVE: + wdt_ping(); + return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_margin, (int __user *)arg)) + return -EFAULT; + /* Arbitrary, can't find the card's limits */ + if (new_margin <= 1) + return -EINVAL; + for( i=0; i= WD_TIMO_MAX_NUM || i < 0 ) + return -EINVAL; + wdt_set_timeout(i); + case WDIOC_GETTIMEOUT: + return put_user(wdt_margin, (int __user *)arg); + + case WDIOC_SETOPTIONS: + if (copy_from_user(&rv, (int __user *)arg, sizeof(int))) + return -EFAULT; + + if (rv & WDIOS_DISABLECARD) { + pr_info("System CPLD: disable watchdog\n"); + wdt_disable(); + } + + if (rv & WDIOS_ENABLECARD) { + pr_info("System CPLD: enable watchdog\n"); + wdt_enable(); + } + return -EINVAL; + } + return -ENOTTY; +} + +static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret; + + ret = wdt_ioctl(file, cmd, arg); + + return ret; +} + +/** + * wdt_open: + * @inode: inode of device + * @file: file handle to device + * + */ +static int wdt_open(struct inode *inode, struct file *file) +{ + if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) { + if (test_and_set_bit(0, &wdt_is_open)) { + return -EBUSY; + } + /* + * Activate + */ + + wdt_enable(); + return nonseekable_open(inode, file); + } + return -ENODEV; +} + +/** + * wdt_close: + * @inode: inode to board + * @file: file handle to board + * + */ +static int wdt_release(struct inode *inode, struct file *file) +{ + if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) + clear_bit(0, &wdt_is_open); + return 0; +} + +/** + * notify_sys: + * @this: our notifier block + * @code: the event being reported + * @unused: unused + * + * Our notifier is called on system shutdowns. We want to turn the card + * off at reboot otherwise the machine will reboot again during memory + * test or worse yet during the following fsck. This would suck, in fact + * trust me - if it happens it does suck. + */ +static int wdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + /* Disable Watchdog */ + wdt_disable(); + return NOTIFY_DONE; +} + +static const struct file_operations wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = wdt_write, + .unlocked_ioctl = wdt_unlocked_ioctl, + .open = wdt_open, + .release = wdt_release, +}; + +static struct miscdevice wdt_dev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &wdt_fops, +}; + +/* + * The WDT card needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ +static struct notifier_block wdt_notifier = { + .notifier_call = wdt_notify_sys, +}; +#endif /* CONFIG_DRV_SYSCPLD_WDT */ + +static int system_cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int err; + + /* allocate memory to system_cpld */ + system_cpld = devm_kzalloc(&client->dev, sizeof(struct system_cpld_data) , GFP_KERNEL); + + if (!system_cpld) + return -ENOMEM; + + mutex_init(&system_cpld->lock); + + err = sysfs_create_group(&client->dev.kobj, &system_cpld_group_misc); + if (err){ + printk("%s: Error creeat misc group.\n", __FUNCTION__); + } + + system_cpld->client = client; + i2c_set_clientdata(client, system_cpld); + + printk(KERN_INFO "%s: System CPLD LCMXO3LF created.\n", __FUNCTION__); + +#ifdef CONFIG_DRV_SYSCPLD_WDT + err = misc_register(&wdt_dev); + if (err) + return err; + err = register_reboot_notifier(&wdt_notifier); + if (err) { + misc_deregister(&wdt_dev); + return err; + } + printk(KERN_INFO "%s: System CPLD watchdog created.\n", __FUNCTION__); +#endif + + return 0; + +} + +static int system_cpld_remove(struct i2c_client *client) +{ +#ifdef CONFIG_DRV_SYSCPLD_WDT + misc_deregister(&wdt_dev); + unregister_reboot_notifier(&wdt_notifier); +#endif + sysfs_remove_group(&client->dev.kobj, &system_cpld_group_misc); + + printk(KERN_INFO "%s: System CPLD removed.\n", __FUNCTION__); + return 0; +} + +static struct i2c_driver system_cpld_driver = { + .driver = { + .name = "system_cpld", + .owner = THIS_MODULE, + }, + .probe = system_cpld_probe, + .remove = system_cpld_remove, + .id_table = system_cpld_ids, +}; + +static int __init system_cpld_init(void) +{ + printk(KERN_INFO "%s: init.\n", __FUNCTION__); + return i2c_add_driver(&system_cpld_driver); +} +module_init(system_cpld_init); + +static void __exit system_cpld_exit(void) +{ + printk(KERN_INFO "%s: exit.\n", __FUNCTION__); + i2c_del_driver(&system_cpld_driver); +} +module_exit(system_cpld_exit); + +MODULE_DESCRIPTION("mitac_ly1200_32x_system_cpld driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/pmbus.h new file mode 100644 index 000000000000..55cb8663e6e9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/pmbus.h @@ -0,0 +1,366 @@ +#ifndef PMBUS_H +#define PMBUS_H + +/* + * Registers + */ +#define PMBUS_PAGE 0x00 +#define PMBUS_OPERATION 0x01 +#define PMBUS_ON_OFF_CONFIG 0x02 +#define PMBUS_CLEAR_FAULTS 0x03 +#define PMBUS_PHASE 0x04 + +#define PMBUS_CAPABILITY 0x19 +#define PMBUS_QUERY 0x1A + +#define PMBUS_VOUT_MODE 0x20 +#define PMBUS_VOUT_COMMAND 0x21 +#define PMBUS_VOUT_TRIM 0x22 +#define PMBUS_VOUT_CAL_OFFSET 0x23 +#define PMBUS_VOUT_MAX 0x24 +#define PMBUS_VOUT_MARGIN_HIGH 0x25 +#define PMBUS_VOUT_MARGIN_LOW 0x26 +#define PMBUS_VOUT_TRANSITION_RATE 0x27 +#define PMBUS_VOUT_DROOP 0x28 +#define PMBUS_VOUT_SCALE_LOOP 0x29 +#define PMBUS_VOUT_SCALE_MONITOR 0x2A + +#define PMBUS_COEFFICIENTS 0x30 +#define PMBUS_POUT_MAX 0x31 + +#define PMBUS_FAN_CONFIG_12 0x3A +#define PMBUS_FAN_COMMAND_1 0x3B +#define PMBUS_FAN_COMMAND_2 0x3C +#define PMBUS_FAN_CONFIG_34 0x3D +#define PMBUS_FAN_COMMAND_3 0x3E +#define PMBUS_FAN_COMMAND_4 0x3F + +#define PMBUS_VOUT_OV_FAULT_LIMIT 0x40 +#define PMBUS_VOUT_OV_FAULT_RESPONSE 0x41 +#define PMBUS_VOUT_OV_WARN_LIMIT 0x42 +#define PMBUS_VOUT_UV_WARN_LIMIT 0x43 +#define PMBUS_VOUT_UV_FAULT_LIMIT 0x44 +#define PMBUS_VOUT_UV_FAULT_RESPONSE 0x45 +#define PMBUS_IOUT_OC_FAULT_LIMIT 0x46 +#define PMBUS_IOUT_OC_FAULT_RESPONSE 0x47 +#define PMBUS_IOUT_OC_LV_FAULT_LIMIT 0x48 +#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE 0x49 +#define PMBUS_IOUT_OC_WARN_LIMIT 0x4A +#define PMBUS_IOUT_UC_FAULT_LIMIT 0x4B +#define PMBUS_IOUT_UC_FAULT_RESPONSE 0x4C + +#define PMBUS_OT_FAULT_LIMIT 0x4F +#define PMBUS_OT_FAULT_RESPONSE 0x50 +#define PMBUS_OT_WARN_LIMIT 0x51 +#define PMBUS_UT_WARN_LIMIT 0x52 +#define PMBUS_UT_FAULT_LIMIT 0x53 +#define PMBUS_UT_FAULT_RESPONSE 0x54 +#define PMBUS_VIN_OV_FAULT_LIMIT 0x55 +#define PMBUS_VIN_OV_FAULT_RESPONSE 0x56 +#define PMBUS_VIN_OV_WARN_LIMIT 0x57 +#define PMBUS_VIN_UV_WARN_LIMIT 0x58 +#define PMBUS_VIN_UV_FAULT_LIMIT 0x59 + +#define PMBUS_IIN_OC_FAULT_LIMIT 0x5B +#define PMBUS_IIN_OC_WARN_LIMIT 0x5D + +#define PMBUS_POUT_OP_FAULT_LIMIT 0x68 +#define PMBUS_POUT_OP_WARN_LIMIT 0x6A +#define PMBUS_PIN_OP_WARN_LIMIT 0x6B + +#define PMBUS_STATUS_BYTE 0x78 +#define PMBUS_STATUS_WORD 0x79 +#define PMBUS_STATUS_VOUT 0x7A +#define PMBUS_STATUS_IOUT 0x7B +#define PMBUS_STATUS_INPUT 0x7C +#define PMBUS_STATUS_TEMPERATURE 0x7D +#define PMBUS_STATUS_CML 0x7E +#define PMBUS_STATUS_OTHER 0x7F +#define PMBUS_STATUS_MFR_SPECIFIC 0x80 +#define PMBUS_STATUS_FAN_12 0x81 +#define PMBUS_STATUS_FAN_34 0x82 + +#define PMBUS_READ_VIN 0x88 +#define PMBUS_READ_IIN 0x89 +#define PMBUS_READ_VCAP 0x8A +#define PMBUS_READ_VOUT 0x8B +#define PMBUS_READ_IOUT 0x8C +#define PMBUS_READ_TEMPERATURE_1 0x8D +#define PMBUS_READ_TEMPERATURE_2 0x8E +#define PMBUS_READ_TEMPERATURE_3 0x8F +#define PMBUS_READ_FAN_SPEED_1 0x90 +#define PMBUS_READ_FAN_SPEED_2 0x91 +#define PMBUS_READ_FAN_SPEED_3 0x92 +#define PMBUS_READ_FAN_SPEED_4 0x93 +#define PMBUS_READ_DUTY_CYCLE 0x94 +#define PMBUS_READ_FREQUENCY 0x95 +#define PMBUS_READ_POUT 0x96 +#define PMBUS_READ_PIN 0x97 + +#define PMBUS_REVISION 0x98 +#define PMBUS_MFR_ID 0x99 +#define PMBUS_MFR_MODEL 0x9A +#define PMBUS_MFR_REVISION 0x9B +#define PMBUS_MFR_LOCATION 0x9C +#define PMBUS_MFR_DATE 0x9D +#define PMBUS_MFR_SERIAL 0x9E + +/* + * Virtual registers. + * Useful to support attributes which are not supported by standard PMBus + * registers but exist as manufacturer specific registers on individual chips. + * Must be mapped to real registers in device specific code. + * + * Semantics: + * Virtual registers are all word size. + * READ registers are read-only; writes are either ignored or return an error. + * RESET registers are read/write. Reading reset registers returns zero + * (used for detection), writing any value causes the associated history to be + * reset. + * Virtual registers have to be handled in device specific driver code. Chip + * driver code returns non-negative register values if a virtual register is + * supported, or a negative error code if not. The chip driver may return + * -ENODATA or any other error code in this case, though an error code other + * than -ENODATA is handled more efficiently and thus preferred. Either case, + * the calling PMBus core code will abort if the chip driver returns an error + * code when reading or writing virtual registers. + */ +#define PMBUS_VIRT_BASE 0x100 +#define PMBUS_VIRT_READ_TEMP_AVG (PMBUS_VIRT_BASE + 0) +#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 1) +#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 2) +#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 3) +#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 4) +#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 5) +#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 6) +#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 7) +#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 8) +#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 9) +#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 10) +#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 11) +#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 12) +#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 13) +#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 14) +#define PMBUS_VIRT_READ_POUT_AVG (PMBUS_VIRT_BASE + 15) +#define PMBUS_VIRT_READ_POUT_MAX (PMBUS_VIRT_BASE + 16) +#define PMBUS_VIRT_RESET_POUT_HISTORY (PMBUS_VIRT_BASE + 17) +#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 18) +#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 19) +#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 20) +#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 21) +#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 22) +#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 23) +#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 24) +#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 25) +#define PMBUS_VIRT_READ_TEMP2_AVG (PMBUS_VIRT_BASE + 26) +#define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 27) +#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 28) +#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 29) + +#define PMBUS_VIRT_READ_VMON (PMBUS_VIRT_BASE + 30) +#define PMBUS_VIRT_VMON_UV_WARN_LIMIT (PMBUS_VIRT_BASE + 31) +#define PMBUS_VIRT_VMON_OV_WARN_LIMIT (PMBUS_VIRT_BASE + 32) +#define PMBUS_VIRT_VMON_UV_FAULT_LIMIT (PMBUS_VIRT_BASE + 33) +#define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34) +#define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35) + +/* + * CAPABILITY + */ +#define PB_CAPABILITY_SMBALERT (1<<4) +#define PB_CAPABILITY_ERROR_CHECK (1<<7) + +/* + * VOUT_MODE + */ +#define PB_VOUT_MODE_MODE_MASK 0xe0 +#define PB_VOUT_MODE_PARAM_MASK 0x1f + +#define PB_VOUT_MODE_LINEAR 0x00 +#define PB_VOUT_MODE_VID 0x20 +#define PB_VOUT_MODE_DIRECT 0x40 + +/* + * Fan configuration + */ +#define PB_FAN_2_PULSE_MASK ((1 << 0) | (1 << 1)) +#define PB_FAN_2_RPM (1 << 2) +#define PB_FAN_2_INSTALLED (1 << 3) +#define PB_FAN_1_PULSE_MASK ((1 << 4) | (1 << 5)) +#define PB_FAN_1_RPM (1 << 6) +#define PB_FAN_1_INSTALLED (1 << 7) + +/* + * STATUS_BYTE, STATUS_WORD (lower) + */ +#define PB_STATUS_NONE_ABOVE (1<<0) +#define PB_STATUS_CML (1<<1) +#define PB_STATUS_TEMPERATURE (1<<2) +#define PB_STATUS_VIN_UV (1<<3) +#define PB_STATUS_IOUT_OC (1<<4) +#define PB_STATUS_VOUT_OV (1<<5) +#define PB_STATUS_OFF (1<<6) +#define PB_STATUS_BUSY (1<<7) + +/* + * STATUS_WORD (upper) + */ +#define PB_STATUS_UNKNOWN (1<<8) +#define PB_STATUS_OTHER (1<<9) +#define PB_STATUS_FANS (1<<10) +#define PB_STATUS_POWER_GOOD_N (1<<11) +#define PB_STATUS_WORD_MFR (1<<12) +#define PB_STATUS_INPUT (1<<13) +#define PB_STATUS_IOUT_POUT (1<<14) +#define PB_STATUS_VOUT (1<<15) + +/* + * STATUS_IOUT + */ +#define PB_POUT_OP_WARNING (1<<0) +#define PB_POUT_OP_FAULT (1<<1) +#define PB_POWER_LIMITING (1<<2) +#define PB_CURRENT_SHARE_FAULT (1<<3) +#define PB_IOUT_UC_FAULT (1<<4) +#define PB_IOUT_OC_WARNING (1<<5) +#define PB_IOUT_OC_LV_FAULT (1<<6) +#define PB_IOUT_OC_FAULT (1<<7) + +/* + * STATUS_VOUT, STATUS_INPUT + */ +#define PB_VOLTAGE_UV_FAULT (1<<4) +#define PB_VOLTAGE_UV_WARNING (1<<5) +#define PB_VOLTAGE_OV_WARNING (1<<6) +#define PB_VOLTAGE_OV_FAULT (1<<7) + +/* + * STATUS_INPUT + */ +#define PB_PIN_OP_WARNING (1<<0) +#define PB_IIN_OC_WARNING (1<<1) +#define PB_IIN_OC_FAULT (1<<2) + +/* + * STATUS_TEMPERATURE + */ +#define PB_TEMP_UT_FAULT (1<<4) +#define PB_TEMP_UT_WARNING (1<<5) +#define PB_TEMP_OT_WARNING (1<<6) +#define PB_TEMP_OT_FAULT (1<<7) + +/* + * STATUS_FAN + */ +#define PB_FAN_AIRFLOW_WARNING (1<<0) +#define PB_FAN_AIRFLOW_FAULT (1<<1) +#define PB_FAN_FAN2_SPEED_OVERRIDE (1<<2) +#define PB_FAN_FAN1_SPEED_OVERRIDE (1<<3) +#define PB_FAN_FAN2_WARNING (1<<4) +#define PB_FAN_FAN1_WARNING (1<<5) +#define PB_FAN_FAN2_FAULT (1<<6) +#define PB_FAN_FAN1_FAULT (1<<7) + +/* + * CML_FAULT_STATUS + */ +#define PB_CML_FAULT_OTHER_MEM_LOGIC (1<<0) +#define PB_CML_FAULT_OTHER_COMM (1<<1) +#define PB_CML_FAULT_PROCESSOR (1<<3) +#define PB_CML_FAULT_MEMORY (1<<4) +#define PB_CML_FAULT_PACKET_ERROR (1<<5) +#define PB_CML_FAULT_INVALID_DATA (1<<6) +#define PB_CML_FAULT_INVALID_COMMAND (1<<7) + +enum pmbus_sensor_classes { + PSC_VOLTAGE_IN = 0, + PSC_VOLTAGE_OUT, + PSC_CURRENT_IN, + PSC_CURRENT_OUT, + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ + +/* Functionality bit mask */ +#define PMBUS_HAVE_VIN (1 << 0) +#define PMBUS_HAVE_VCAP (1 << 1) +#define PMBUS_HAVE_VOUT (1 << 2) +#define PMBUS_HAVE_IIN (1 << 3) +#define PMBUS_HAVE_IOUT (1 << 4) +#define PMBUS_HAVE_PIN (1 << 5) +#define PMBUS_HAVE_POUT (1 << 6) +#define PMBUS_HAVE_FAN12 (1 << 7) +#define PMBUS_HAVE_FAN34 (1 << 8) +#define PMBUS_HAVE_TEMP (1 << 9) +#define PMBUS_HAVE_TEMP2 (1 << 10) +#define PMBUS_HAVE_TEMP3 (1 << 11) +#define PMBUS_HAVE_STATUS_VOUT (1 << 12) +#define PMBUS_HAVE_STATUS_IOUT (1 << 13) +#define PMBUS_HAVE_STATUS_INPUT (1 << 14) +#define PMBUS_HAVE_STATUS_TEMP (1 << 15) +#define PMBUS_HAVE_STATUS_FAN12 (1 << 16) +#define PMBUS_HAVE_STATUS_FAN34 (1 << 17) +#define PMBUS_HAVE_VMON (1 << 18) +#define PMBUS_HAVE_STATUS_VMON (1 << 19) + +enum pmbus_data_format { linear = 0, direct, vid }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + /* + * Support one set of coefficients for each sensor type + * Used for chips providing data in direct mode. + */ + int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */ + int b[PSC_NUM_CLASSES]; /* offset */ + int R[PSC_NUM_CLASSES]; /* exponent */ + + u32 func[PMBUS_PAGES]; /* Functionality, per page */ + /* + * The following functions map manufacturing specific register values + * to PMBus standard register values. Specify only if mapping is + * necessary. + * Functions return the register value (read) or zero (write) if + * successful. A return value of -ENODATA indicates that there is no + * manufacturer specific register, but that a standard PMBus register + * may exist. Any other negative return value indicates that the + * register does not exist, and that no attempt should be made to read + * the standard register. + */ + int (*read_byte_data)(struct i2c_client *client, int page, int reg); + int (*read_word_data)(struct i2c_client *client, int page, int reg); + int (*write_word_data)(struct i2c_client *client, int page, int reg, + u16 word); + int (*write_byte)(struct i2c_client *client, int page, u8 value); + /* + * The identify function determines supported PMBus functionality. + * This function is only necessary if a chip driver supports multiple + * chips, and the chip functionality is not pre-determined. + */ + int (*identify)(struct i2c_client *client, + struct pmbus_driver_info *info); +}; + +/* Function declarations */ + +void pmbus_clear_cache(struct i2c_client *client); +int pmbus_set_page(struct i2c_client *client, u8 page); +int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); +int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); +int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); +int pmbus_write_byte(struct i2c_client *client, int page, u8 value); +void pmbus_clear_faults(struct i2c_client *client); +bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); +bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); +int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info); +int pmbus_do_remove(struct i2c_client *client); +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client + *client); + +#endif /* PMBUS_H */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_reg.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_reg.h new file mode 100644 index 000000000000..a8169bdb88ee --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_reg.h @@ -0,0 +1,192 @@ +#ifndef __SLAVE_CPLD_REG +#define __SLAVE_CPLD_REG + +static int slave_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name); +static int slave_cpld_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name); + +/* generic CPLD read function */ +#define FLD_RAW_RD_FUNC(_reg, _fld, _wdh) static ssize_t \ +slave_cpld_##_fld##_raw_read(struct device *dev, struct device_attribute *attr, char *buf) { \ + return slave_cpld_raw_read(dev, attr, buf, _reg##_offset, _reg##_width, _fld##_shift, _fld##_width, _fld##_mask, #_reg); \ +} + +/* generic CPLD write function */ +#define FLD_RAW_WR_FUNC(_reg, _fld, _wdh) static ssize_t \ +slave_cpld_##_fld##_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { \ + return slave_cpld_raw_write(dev, attr, buf, count, _reg##_offset, _reg##_width, _fld##_shift, _fld##_width, _fld##_mask, #_reg); \ +} + +/* CPLD register definition macros */ +#define REG_DEF(_reg, _off, _wdh) \ +static unsigned int _reg##_offset = (unsigned int)(_off); \ +static unsigned int _reg##_width = (unsigned int)(_wdh); + +/* CPLD register field definition macros, with generic read/write function */ +#define FLD_RAW_RO_DEF(_reg, _fld, _sft, _wdh) \ +static unsigned int _fld##_shift = (unsigned int)(_sft); \ +static unsigned int _fld##_width = (unsigned int)(_wdh); \ +static unsigned int _fld##_mask = ((((unsigned int)1) << (_wdh)) - 1); \ +FLD_RAW_RD_FUNC(_reg, _fld, _wdh) + +#define FLD_RAW_RW_DEF(_reg, _fld, _sft, _wdh) \ +static unsigned int _fld##_shift = (unsigned int)(_sft); \ +static unsigned int _fld##_width = (unsigned int)(_wdh); \ +static unsigned int _fld##_mask = ((((unsigned int)1) << (_wdh)) - 1); \ +FLD_RAW_RD_FUNC(_reg, _fld, _wdh) FLD_RAW_WR_FUNC(_reg, _fld, _wdh) + +/* declare slave CPLD registers */ +/* register name offset width */ +/* --------------------------------------- ------- ----- */ +REG_DEF( slv_cpld_rev, 0x00, 8) +REG_DEF( slv_cpld_gpr, 0x01, 8) +REG_DEF( mb_brd_rev_type, 0x02, 8) + +REG_DEF( zqsfp28_present_24_17_status, 0x10, 8) +REG_DEF( zqsfp28_present_32_25_status, 0x11, 8) +REG_DEF( zqsfp28_rst_24_17, 0x12, 8) +REG_DEF( zqsfp28_rst_32_25, 0x13, 8) +REG_DEF( zqsfp28_modsel_24_17, 0x14, 8) +REG_DEF( zqsfp28_modsel_32_25, 0x15, 8) +REG_DEF( zqsfp28_lpmode_24_17, 0x16, 8) +REG_DEF( zqsfp28_lpmode_32_25, 0x17, 8) +REG_DEF( zqsfp28_irq_24_17_status, 0x18, 8) +REG_DEF( zqsfp28_irq_32_25_status, 0x19, 8) +REG_DEF( zqsfp28_irq_msk_24_17_status, 0x1A, 8) +REG_DEF( zqsfp28_irq_msk_32_25_status, 0x1B, 8) + + +/* declare slave CPLD register's fields */ +/* register name field name shift width */ +/* ---------------------- ---------------- ------ ----- */ +FLD_RAW_RO_DEF( slv_cpld_rev, mjr_rev, 4, 4) +FLD_RAW_RO_DEF( slv_cpld_rev, mnr_rev, 0, 4) + +FLD_RAW_RW_DEF( slv_cpld_gpr, scrtch_reg, 0, 8) + +FLD_RAW_RO_DEF( mb_brd_rev_type, brd_rev, 4, 4) +FLD_RAW_RO_DEF( mb_brd_rev_type, brd_type, 0, 4) + +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port24_present, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port23_present, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port22_present, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port21_present, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port20_present, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port19_present, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port18_present, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port17_present, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port32_present, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port31_present, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port30_present, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port29_present, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port28_present, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port27_present, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port26_present, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port25_present, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port24_rst, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port23_rst, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port22_rst, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port21_rst, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port20_rst, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port19_rst, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port18_rst, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port17_rst, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port32_rst, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port31_rst, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port30_rst, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port29_rst, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port28_rst, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port27_rst, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port26_rst, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port25_rst, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port24_modsel, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port23_modsel, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port22_modsel, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port21_modsel, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port20_modsel, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port19_modsel, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port18_modsel, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port17_modsel, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port32_modsel, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port31_modsel, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port30_modsel, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port29_modsel, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port28_modsel, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port27_modsel, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port26_modsel, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port25_modsel, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port24_lpmode, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port23_lpmode, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port22_lpmode, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port21_lpmode, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port20_lpmode, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port19_lpmode, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port18_lpmode, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port17_lpmode, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port32_lpmode, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port31_lpmode, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port30_lpmode, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port29_lpmode, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port28_lpmode, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port27_lpmode, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port26_lpmode, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port25_lpmode, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port24_irq_status, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port23_irq_status, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port22_irq_status, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port21_irq_status, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port20_irq_status, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port19_irq_status, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port18_irq_status, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port17_irq_status, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port32_irq_status, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port31_irq_status, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port30_irq_status, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port29_irq_status, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port28_irq_status, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port27_irq_status, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port26_irq_status, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port25_irq_status, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port24_irq_msk, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port23_irq_msk, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port22_irq_msk, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port21_irq_msk, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port20_irq_msk, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port19_irq_msk, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port18_irq_msk, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port17_irq_msk, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port32_irq_msk, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port31_irq_msk, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port30_irq_msk, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port29_irq_msk, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port28_irq_msk, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port27_irq_msk, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port26_irq_msk, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port25_irq_msk, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port_17_24_present, 0, 8) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port_25_32_present, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port_17_24_rst, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port_25_32_rst, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port_17_24_modsel, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port_25_32_modsel, 0, 8) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port_17_24_irq_status,0, 8) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port_25_32_irq_status,0, 8) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port_17_24_irq_msk, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port_25_32_irq_msk, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port_17_24_lpmode, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port_25_32_lpmode, 0, 8) + +#endif /* __SLAVE_CPLD_REG */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h new file mode 100644 index 000000000000..92d00d29d493 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h @@ -0,0 +1,155 @@ +#ifndef __SLAVE_CPLD_SYSFS +#define __SLAVE_CPLD_SYSFS + +/* generic CPLD sysfs file definition macros */ +#define SYSFS_RAW_RO_ATTR_DEF(field) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO, slave_cpld_##field##_raw_read, NULL); + +#define SYSFS_RAW_RW_ATTR_DEF(field) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO | S_IWUGO, slave_cpld_##field##_raw_read, slave_cpld_##field##_raw_write); + +#define SYSFS_MISC_RO_ATTR_DEF(field, _read) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO, _read, NULL); + +#define SYSFS_MISC_RW_ATTR_DEF(field, _read, _write) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO | S_IWUGO, _read, _write); + +#define SYSFS_ATTR_PTR(field) \ +&field.attr + + +/* declare slave CPLD file system */ +SYSFS_RAW_RO_ATTR_DEF(mjr_rev) +SYSFS_RAW_RO_ATTR_DEF(mnr_rev) + +SYSFS_RAW_RW_ATTR_DEF(scrtch_reg) + +SYSFS_RAW_RO_ATTR_DEF(brd_rev) +SYSFS_RAW_RO_ATTR_DEF(brd_type) + +SYSFS_RAW_RO_ATTR_DEF(port24_present) +SYSFS_RAW_RO_ATTR_DEF(port23_present) +SYSFS_RAW_RO_ATTR_DEF(port22_present) +SYSFS_RAW_RO_ATTR_DEF(port21_present) +SYSFS_RAW_RO_ATTR_DEF(port20_present) +SYSFS_RAW_RO_ATTR_DEF(port19_present) +SYSFS_RAW_RO_ATTR_DEF(port18_present) +SYSFS_RAW_RO_ATTR_DEF(port17_present) + +SYSFS_RAW_RO_ATTR_DEF(port32_present) +SYSFS_RAW_RO_ATTR_DEF(port31_present) +SYSFS_RAW_RO_ATTR_DEF(port30_present) +SYSFS_RAW_RO_ATTR_DEF(port29_present) +SYSFS_RAW_RO_ATTR_DEF(port28_present) +SYSFS_RAW_RO_ATTR_DEF(port27_present) +SYSFS_RAW_RO_ATTR_DEF(port26_present) +SYSFS_RAW_RO_ATTR_DEF(port25_present) + +SYSFS_RAW_RW_ATTR_DEF(port24_rst) +SYSFS_RAW_RW_ATTR_DEF(port23_rst) +SYSFS_RAW_RW_ATTR_DEF(port22_rst) +SYSFS_RAW_RW_ATTR_DEF(port21_rst) +SYSFS_RAW_RW_ATTR_DEF(port20_rst) +SYSFS_RAW_RW_ATTR_DEF(port19_rst) +SYSFS_RAW_RW_ATTR_DEF(port18_rst) +SYSFS_RAW_RW_ATTR_DEF(port17_rst) + +SYSFS_RAW_RW_ATTR_DEF(port32_rst) +SYSFS_RAW_RW_ATTR_DEF(port31_rst) +SYSFS_RAW_RW_ATTR_DEF(port30_rst) +SYSFS_RAW_RW_ATTR_DEF(port29_rst) +SYSFS_RAW_RW_ATTR_DEF(port28_rst) +SYSFS_RAW_RW_ATTR_DEF(port27_rst) +SYSFS_RAW_RW_ATTR_DEF(port26_rst) +SYSFS_RAW_RW_ATTR_DEF(port25_rst) + +SYSFS_RAW_RW_ATTR_DEF(port24_modsel) +SYSFS_RAW_RW_ATTR_DEF(port23_modsel) +SYSFS_RAW_RW_ATTR_DEF(port22_modsel) +SYSFS_RAW_RW_ATTR_DEF(port21_modsel) +SYSFS_RAW_RW_ATTR_DEF(port20_modsel) +SYSFS_RAW_RW_ATTR_DEF(port19_modsel) +SYSFS_RAW_RW_ATTR_DEF(port18_modsel) +SYSFS_RAW_RW_ATTR_DEF(port17_modsel) + +SYSFS_RAW_RW_ATTR_DEF(port32_modsel) +SYSFS_RAW_RW_ATTR_DEF(port31_modsel) +SYSFS_RAW_RW_ATTR_DEF(port30_modsel) +SYSFS_RAW_RW_ATTR_DEF(port29_modsel) +SYSFS_RAW_RW_ATTR_DEF(port28_modsel) +SYSFS_RAW_RW_ATTR_DEF(port27_modsel) +SYSFS_RAW_RW_ATTR_DEF(port26_modsel) +SYSFS_RAW_RW_ATTR_DEF(port25_modsel) + +SYSFS_RAW_RW_ATTR_DEF(port24_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port23_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port22_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port21_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port20_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port19_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port18_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port17_lpmode) + +SYSFS_RAW_RW_ATTR_DEF(port32_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port31_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port30_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port29_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port28_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port27_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port26_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port25_lpmode) + +SYSFS_RAW_RO_ATTR_DEF(port24_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port23_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port22_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port21_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port20_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port19_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port18_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port17_irq_status) + +SYSFS_RAW_RO_ATTR_DEF(port32_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port31_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port30_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port29_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port28_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port27_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port26_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port25_irq_status) + +SYSFS_RAW_RW_ATTR_DEF(port24_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port23_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port22_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port21_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port20_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port19_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port18_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port17_irq_msk) + +SYSFS_RAW_RW_ATTR_DEF(port32_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port31_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port30_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port29_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port28_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port27_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port26_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port25_irq_msk) + +SYSFS_RAW_RO_ATTR_DEF(port_17_24_present) +SYSFS_RAW_RO_ATTR_DEF(port_25_32_present) +SYSFS_RAW_RW_ATTR_DEF(port_17_24_rst) +SYSFS_RAW_RW_ATTR_DEF(port_25_32_rst) +SYSFS_RAW_RW_ATTR_DEF(port_17_24_modsel) +SYSFS_RAW_RW_ATTR_DEF(port_25_32_modsel) +SYSFS_RAW_RO_ATTR_DEF(port_17_24_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port_25_32_irq_status) +SYSFS_RAW_RW_ATTR_DEF(port_17_24_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port_25_32_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port_17_24_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port_25_32_lpmode) + +#endif /* __SLAVE_CPLD_SYSFS */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_reg.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_reg.h new file mode 100644 index 000000000000..ba66519efe8a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_reg.h @@ -0,0 +1,107 @@ +#ifndef __SYSTEM_CPLD_REG +#define __SYSTEM_CPLD_REG + +static int system_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name); +static int system_cpld_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name); + +/* generic CPLD read function */ +#define FLD_RAW_RD_FUNC(_reg, _fld, _wdh) static ssize_t \ +system_cpld_##_fld##_raw_read(struct device *dev, struct device_attribute *attr, char *buf) { \ + return system_cpld_raw_read(dev, attr, buf, _reg##_offset, _reg##_width, _fld##_shift, _fld##_width, _fld##_mask, #_reg); \ +} + +/* generic CPLD write function */ +#define FLD_RAW_WR_FUNC(_reg, _fld, _wdh) static ssize_t \ +system_cpld_##_fld##_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { \ + return system_cpld_raw_write(dev, attr, buf, count, _reg##_offset, _reg##_width, _fld##_shift, _fld##_width, _fld##_mask, #_reg); \ +} + +/* CPLD register definition macros */ +#define REG_DEF(_reg, _off, _wdh) \ +static unsigned int _reg##_offset = (unsigned int)(_off); \ +static unsigned int _reg##_width = (unsigned int)(_wdh); + +/* CPLD register field definition macros, with generic read/write function */ +#define FLD_RAW_RO_DEF(_reg, _fld, _sft, _wdh) \ +static unsigned int _fld##_shift = (unsigned int)(_sft); \ +static unsigned int _fld##_width = (unsigned int)(_wdh); \ +static unsigned int _fld##_mask = ((((unsigned int)1) << (_wdh)) - 1); \ +FLD_RAW_RD_FUNC(_reg, _fld, _wdh) + +#define FLD_RAW_RW_DEF(_reg, _fld, _sft, _wdh) \ +static unsigned int _fld##_shift = (unsigned int)(_sft); \ +static unsigned int _fld##_width = (unsigned int)(_wdh); \ +static unsigned int _fld##_mask = ((((unsigned int)1) << (_wdh)) - 1); \ +FLD_RAW_RD_FUNC(_reg, _fld, _wdh) FLD_RAW_WR_FUNC(_reg, _fld, _wdh) + +/* declare system CPLD registers */ +/* register name offset width */ +/* --------------------------------------- ------- ----- */ +REG_DEF( sys_cpld_rev, 0x00, 8) +REG_DEF( sys_cpld_gpr, 0x01, 8) +REG_DEF( cpu_brd_rev_type, 0x02, 8) +REG_DEF( sys_srr, 0x03, 8) +REG_DEF( sys_eeprom_wp, 0x04, 8) +REG_DEF( sys_irq, 0x05, 8) +REG_DEF( sys_wd, 0x06, 8) +REG_DEF( sys_mb_rst_en, 0x07, 8) +REG_DEF( cpu_pwr_en_status, 0x08, 8) +REG_DEF( cpu_pwr_status, 0x09, 8) + + +/* declare system CPLD register's fields */ +/* register name field name shift width */ +/* ---------------------- ---------------- ------ ----- */ +FLD_RAW_RO_DEF( sys_cpld_rev, mjr_rev, 4, 4) +FLD_RAW_RO_DEF( sys_cpld_rev, mnr_rev, 0, 4) + +FLD_RAW_RW_DEF( sys_cpld_gpr, scrtch_reg, 0, 8) + +FLD_RAW_RO_DEF( cpu_brd_rev_type, brd_rev, 4, 4) +FLD_RAW_RO_DEF( cpu_brd_rev_type, brd_type, 0, 4) + +FLD_RAW_RO_DEF( sys_srr, ssd_present, 3, 1) +FLD_RAW_RW_DEF( sys_srr, spi_cs_sel, 2, 1) +FLD_RAW_RW_DEF( sys_srr, rst_bios_switch, 1, 1) +FLD_RAW_RW_DEF( sys_srr, cpld_upgrade_rst, 0, 1) + +FLD_RAW_RW_DEF( sys_eeprom_wp, cpld_spi_wp, 4, 1) +FLD_RAW_RW_DEF( sys_eeprom_wp, system_id_eeprom_wp, 3, 1) +FLD_RAW_RW_DEF( sys_eeprom_wp, spi_me_wp, 2, 1) +FLD_RAW_RW_DEF( sys_eeprom_wp, spi_bios_wp, 1, 1) +FLD_RAW_RW_DEF( sys_eeprom_wp, spi_bak_bios_wp, 0, 1) + +FLD_RAW_RW_DEF( sys_irq, vrhot_irq_en, 6, 1) +FLD_RAW_RW_DEF( sys_irq, cpu_thermtrip_irq_en,5, 1) +FLD_RAW_RW_DEF( sys_irq, temp_alert_irq_en, 4, 1) +FLD_RAW_RO_DEF( sys_irq, vrhot_irq, 2, 1) +FLD_RAW_RO_DEF( sys_irq, cpu_thermtrip_irq, 1, 1) +FLD_RAW_RO_DEF( sys_irq, temp_alert_irq, 0, 1) + +FLD_RAW_RW_DEF( sys_wd, wd_timer, 4, 4) +FLD_RAW_RW_DEF( sys_wd, wd_en, 1, 1) +FLD_RAW_RW_DEF( sys_wd, wd_punch, 0, 1) + +FLD_RAW_RW_DEF( sys_mb_rst_en, mb_rst_en, 0, 1) + +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_v3p3_en, 7, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_vcc_vnn_en, 6, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_vccsram_en, 5, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_vddq_en, 4, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_vcc_ref_en, 3, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_v1p05_en, 2, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_v1p8_en, 1, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_v2p5_en, 0, 1) + +FLD_RAW_RO_DEF( cpu_pwr_status, pg_v3p3, 7, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_vcc_vnn, 6, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_vccsram, 5, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_vddq, 4, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_vcc_ref, 3, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_v1p05, 2, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_v1p8, 1, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_v2p5, 0, 1) + +#endif /* __SYSTEM_CPLD_REG */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h new file mode 100644 index 000000000000..e6b03bd1bd0d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h @@ -0,0 +1,76 @@ +#ifndef __SYSTEM_CPLD_SYSFS +#define __SYSTEM_CPLD_SYSFS + +/* generic CPLD sysfs file definition macros */ +#define SYSFS_RAW_RO_ATTR_DEF(field) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO, system_cpld_##field##_raw_read, NULL); + +#define SYSFS_RAW_RW_ATTR_DEF(field) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO | S_IWUGO, system_cpld_##field##_raw_read, system_cpld_##field##_raw_write); + +#define SYSFS_MISC_RO_ATTR_DEF(field, _read) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO, _read, NULL); + +#define SYSFS_MISC_RW_ATTR_DEF(field, _read, _write) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO | S_IWUGO, _read, _write); + +#define SYSFS_ATTR_PTR(field) \ +&field.attr + + +/* declare system CPLD file system */ +SYSFS_RAW_RO_ATTR_DEF(mjr_rev) +SYSFS_RAW_RO_ATTR_DEF(mnr_rev) + +SYSFS_RAW_RW_ATTR_DEF(scrtch_reg) + +SYSFS_RAW_RO_ATTR_DEF(brd_rev) +SYSFS_RAW_RO_ATTR_DEF(brd_type) + +SYSFS_RAW_RO_ATTR_DEF(ssd_present) +SYSFS_RAW_RW_ATTR_DEF(spi_cs_sel) +SYSFS_RAW_RW_ATTR_DEF(rst_bios_switch) +SYSFS_RAW_RW_ATTR_DEF(cpld_upgrade_rst) + +SYSFS_RAW_RW_ATTR_DEF(cpld_spi_wp) +SYSFS_RAW_RW_ATTR_DEF(system_id_eeprom_wp) +SYSFS_RAW_RW_ATTR_DEF(spi_me_wp) +SYSFS_RAW_RW_ATTR_DEF(spi_bios_wp) +SYSFS_RAW_RW_ATTR_DEF(spi_bak_bios_wp) + +SYSFS_RAW_RW_ATTR_DEF(vrhot_irq_en) +SYSFS_RAW_RW_ATTR_DEF(cpu_thermtrip_irq_en) +SYSFS_RAW_RW_ATTR_DEF(temp_alert_irq_en) +SYSFS_RAW_RO_ATTR_DEF(vrhot_irq) +SYSFS_RAW_RO_ATTR_DEF(cpu_thermtrip_irq) +SYSFS_RAW_RO_ATTR_DEF(temp_alert_irq) + +SYSFS_RAW_RW_ATTR_DEF(wd_timer) +SYSFS_RAW_RW_ATTR_DEF(wd_en) +SYSFS_RAW_RW_ATTR_DEF(wd_punch) + +SYSFS_RAW_RW_ATTR_DEF(mb_rst_en) + +SYSFS_RAW_RO_ATTR_DEF(pwr_v3p3_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_vcc_vnn_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_vccsram_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_vddq_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_vcc_ref_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_v1p05_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_v1p8_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_v2p5_en) + +SYSFS_RAW_RO_ATTR_DEF(pg_v3p3) +SYSFS_RAW_RO_ATTR_DEF(pg_vcc_vnn) +SYSFS_RAW_RO_ATTR_DEF(pg_vccsram) +SYSFS_RAW_RO_ATTR_DEF(pg_vddq) +SYSFS_RAW_RO_ATTR_DEF(pg_vcc_ref) +SYSFS_RAW_RO_ATTR_DEF(pg_v1p05) +SYSFS_RAW_RO_ATTR_DEF(pg_v1p8) +SYSFS_RAW_RO_ATTR_DEF(pg_v2p5) + +#endif /* __SYSTEM_CPLD_SYSFS */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-ctrl b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-ctrl new file mode 100755 index 000000000000..73ff759b6f45 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-ctrl @@ -0,0 +1,679 @@ +#!/bin/bash +#/* +#********************************************************************** +#* +#* @filename fan-ctrl +#* +#* @purpose system daemon for controlling system fan pwm +#* +#* @create 2017/06/21 +#* +#* @author nixon.chu +#* +#* @history 2017/06/21: init version +#* +#********************************************************************** +#*/ + +DIR=$(dirname $0) + +# include files +source ${DIR}/funcs.sh + +#/* +#********************************************************************** +#* +#* CONSTANT VARIABLES +#* +#********************************************************************** +#*/ + +# process name/id +DAEMON_NAME=`basename $0` +DAEMON_PID="$$" + +# define symbol for fan/temperature type sensor +SYMBOL_TEMP="TEMP_" +SYMBOL_FAN="FAN_" + +# describe the structure of temperature sensor by id +STRUCT_TEMP_NAME=0 +STRUCT_TEMP_CMD=1 +STRUCT_TEMP_MAX=2 +STRUCT_TEMP_SIZE=$(( ${STRUCT_TEMP_MAX} + 1 )) + +# describe the structure of fan sensor by id +STRUCT_FAN_CMD=0 +STRUCT_FAN_SIZE=$(( ${STRUCT_FAN_CMD} + 1 )) + +# default fan zone configuration file +DEF_ZONE_CONF="${DIR}/fan-zone.conf" + +# default fan zone thermal configuration file +DEF_TEMP_CONF="${DIR}/fan-zone-thermal.conf" + +# default interval (sec) +DEF_INTERVAL=10 + +# default hysteresis (deg C) +DEF_HYSIS=3 + +# default debug mode (0: OFF, 1: ON) +DEF_DEBUG_MODE=0 + +# default log file +DEF_LOG_FILE="/var/log/syslog" + +# default fan level +DEF_FAN_LEVEL=0 + +# default minimum pwm (38.25=255x15%) +DEF_MIN_PWM=39 + +# default zone id +DEF_ZONE_ID=0 + +# error codes +E_STATUS_GOOD=0 +E_STATUS_FAULT=1 +E_INVALID_ARGS=11 +E_INVALID_CONF=12 + +# message levels +MSG_EMERG=0 +MSG_ALERT=1 +MSG_CRIT=2 +MSG_ERR=3 +MSG_WARNING=4 +MSG_NOTICE=5 +MSG_INFO=6 +MSG_DEBUG=7 + +# default message level +DEF_MSG_LEVEL=$MSG_WARNING + +#/* +#********************************************************************** +#* +#* GLOBAL VARIABLES +#* +#********************************************************************** +#*/ + +# temperature sensor group +GBL_TEMP_GRP=() +GBL_TEMP_NUM=${#GBL_TEMP_GRP[@]} + +# fan sensor group +GBL_FAN_GRP=() +GBL_FAN_NUM=${#GBL_FAN_GRP[@]} + +# fan level table +GBL_FAN_LEVEL=() +GBL_LEVEL_NUM=${#GBL_FAN_LEVEL[@]} + +# load defaults +GBL_ZONE_CONF=$DEF_ZONE_CONF +GBL_TEMP_CONF=$DEF_TEMP_CONF +GBL_INTERVAL=$DEF_INTERVAL +GBL_HYSIS=$DEF_HYSIS +GBL_DEBUG_MODE=$DEF_DEBUG_MODE +GBL_LOG_FILE=$DEF_LOG_FILE +GBL_CUR_LEVEL=$DEF_FAN_LEVEL +GBL_MIN_PWM=$DEF_MIN_PWM +GBL_ZONE_ID=$DEF_ZONE_ID +GBL_MSG_LEVEL=$DEF_MSG_LEVEL + +# temperature sensors' readings/statuses/properties (properties list have to be converted with fan level table) +GBL_TEMP_READINGS=() +GBL_TEMP_STATUSES=() +GBL_TEMP_PROPERTY=() + +#/* +#********************************************************************** +#* +#* FUNCTIONS +#* +#********************************************************************** +#*/ + +#/* +#* FEATURE: +#* usage +#* PURPOSE: +#* show the usage of this daemon +#* PARAMETERS: +#* +#* RETURNS: +#* success, this function returns @E_INVALID_ARGS. +#*/ +function usage() { + local dbg_mode + + [ $GBL_DEBUG_MODE -eq 0 ] && dbg_mode="off" || dbg_mode="on" + + echo -e "Usage: $0 [-z zone_file] [-t thermal_file] [-o log_file] [-d]" >&2 + echo -e "" >&2 + echo -e "Arguments:" >&2 + echo -e " -z, --zone-config Fan zone configuration file (default: $DEF_ZONE_CONF)" >&2 + echo -e " -t, --temp-config Fan zone thermal configuration file (default: $DEF_TEMP_CONF)" >&2 + echo -e " -o, --log-file Log file (default: $DEF_LOG_FILE)" >&2 + echo -e " -d, --debug Debug mode (default: $dbg_mode)" >&2 + exit ${E_INVALID_ARGS} +} + +#/* +#* FEATURE: +#* print_msg +#* PURPOSE: +#* print message by message level +#* PARAMETERS: +#* msg_lvl (IN) message level +#* msg (IN) message +#* RETURNS: +#* +#*/ +function print_msg() { + local msg_lvl=$1 + local msg=$2 + + [ $msg_lvl -le $GBL_MSG_LEVEL ] && echo "${msg}" >&2 +} + +#/* +#* FEATURE: +#* err_msg +#* PURPOSE: +#* log error message +#* PARAMETERS: +#* msg (IN) message +#* err_no (IN) error code +#* RETURNS: +#* success, this function returns non-zero error code. +#*/ +function err_msg() { + local msg=$1 + local err_no=$2 + + log_msg $MSG_ERROR "${msg}" + exit ${err_no} +} + +#/* +#* FEATURE: +#* log_msg +#* PURPOSE: +#* log message +#* PARAMETERS: +#* msg_lvl (IN) message level +#* msg (IN) message +#* RETURNS: +#* +#*/ +function log_msg() { + local msg_lvl=$1 + local msg=$2 + + if [ $GBL_LOG_FILE == $DEF_LOG_FILE ]; then + `logger -t $DAEMON_NAME -p $msg_lvl $msg` + else + echo -e "`date +"%b %_d %T"` `hostname` $DAEMON_NAME[$DAEMON_PID]: ${msg}" >> ${GBL_LOG_FILE} + fi + + print_msg $msg_lvl "${msg}" +} + +#/* +#* FEATURE: +#* debug_temp_grp +#* PURPOSE: +#* debug function for showing the temperature sensor group configs +#* @GBL_TEMP_GRP[]: store sensor group configs (sensor name, command, and max_temp) +#* PARAMETERS: +#* +#* RETURNS: +#* +#*/ +function debug_temp_grp() { + if [ $GBL_DEBUG_MODE -ne 0 ]; then + echo "********* Sensor Group *********" + for ((i=0; i<$GBL_TEMP_NUM; i++)) + do + echo -en "`fetch_temp_struct $i $STRUCT_TEMP_NAME`\t" + echo -en "`fetch_temp_struct $i $STRUCT_TEMP_CMD`\t" + echo "`fetch_temp_struct $i $STRUCT_TEMP_MAX`" + done + fi +} + +#/* +#* FEATURE: +#* debug_temp_readings +#* PURPOSE: +#* debug function for showing the temperature sensors' readings +#* @GBL_TEMP_READINGS[]: store current reading for temperature sensors +#* PARAMETERS: +#* +#* RETURNS: +#* +#*/ +function debug_temp_readings() { + if [ $GBL_DEBUG_MODE -ne 0 ]; then + echo "********* Sensor Reading *********" + for ((i=0; i<$GBL_TEMP_NUM; i++)) + do + echo -e "`fetch_temp_struct $i $STRUCT_TEMP_NAME`\t${GBL_TEMP_READINGS[$i]}" + done + fi +} + +#/* +#* FEATURE: +#* debug_temp_property +#* PURPOSE: +#* debug function for showing the temperature sensors' properties +#* @GBL_TEMP_PROPERTY[]: store temperature sensors' properties (asserted temperature for each fan levels) +#* PARAMETERS: +#* +#* RETURNS: +#* +#*/ +function debug_temp_property() { + local size base start_idx level + if [ $GBL_DEBUG_MODE -ne 0 ]; then + echo "********* Sensor Table *********" + for ((i=0; i<${GBL_TEMP_NUM}; i++)) + do + # show array @GBL_TEMP_PROPERTY[]: format name(1) + fan levels(2-?) + size=$(( ${GBL_LEVEL_NUM}+1 )) + base=$i*${size} + start_idx=$(( $base+1 )) + level=${GBL_LEVEL_NUM} + echo -e "${GBL_TEMP_PROPERTY[$base]}\t\t${GBL_TEMP_PROPERTY[@]:$start_idx:$level}" + done + fi +} + +#/* +#* FEATURE: +#* fetch_temp_struct +#* PURPOSE: +#* fetch the member value of specific temperature sensor +#* PARAMETERS: +#* id (IN) sensor id +#* member_id (IN) member id +#* RETURNS: +#* success, returns member value +#*/ +function fetch_temp_struct() { + local id member_id index_base data + + id=$1 + member_id=$2 + + index_base=$(( $id * $STRUCT_TEMP_SIZE )) + data=${GBL_TEMP_GRP[$(($index_base+$member_id))]} + # remove unuseful characters, such as double quotes('"') and the start/end space(' ') of a string. + data=`echo $data | sed 's/^ *\| *$//g' | sed 's/^"\|\"$//g'` + echo $data +} + +#/* +#* FEATURE: +#* fetch_temp_property +#* PURPOSE: +#* fetch the properties of specific temperature sensor +#* PARAMETERS: +#* name (IN) sensor name +#* RETURNS: +#* success, returns an asserted temperature list +#*/ +function fetch_temp_property() { + local name size base start_idx length + + name=$1 + + size=$(( $GBL_LEVEL_NUM+1 )) + for ((i=0; i<${GBL_TEMP_NUM}; i++)) + do + base=$i*${size} + # find sensor by name + if [ ${GBL_TEMP_PROPERTY[${base}]} == "${name}" ]; then + start_idx=$(( $base+1 )) + length=$GBL_LEVEL_NUM + echo ${GBL_TEMP_PROPERTY[@]:$start_idx:$length} + break + fi + done +} + +#/* +#* FEATURE: +#* debug_fan_speed +#* PURPOSE: +#* debug function for showing system current fan level and PWM +#* @GBL_CUR_LEVEL: system current/output fan level +#* PARAMETERS: +#* +#* RETURNS: +#* +#*/ +function debug_fan_speed() { + if [ $GBL_DEBUG_MODE -ne 0 ]; then + # For human readable, the representation of fan level will start from 1. + echo "Current Level: $(( $GBL_CUR_LEVEL+1 )), PWM: ${GBL_FAN_LEVEL[$GBL_CUR_LEVEL]}" + fi +} + +#/* +#* FEATURE: +#* arg_parse +#* PURPOSE: +#* parser for input arguments +#* PARAMETERS: +#* arg_lists[] (IN) argument list +#* RETURNS: +#* +#*/ +function arg_parse() { + while [[ $# -ge 1 ]] + do + key="$1" + case $key in + -z|--zone-config) + [ $# -lt 2 ] && usage + GBL_ZONE_CONF=$2 + [ ! -e $GBL_ZONE_CONF ] && usage + shift # past argument + ;; + -t|--temp-config) + [ $# -lt 2 ] && usage + GBL_TEMP_CONF=$2 + [ ! -e $GBL_TEMP_CONF ] && usage + shift # past argument + ;; + -o|--log-file) + [ $# -lt 2 ] && usage + GBL_LOG_FILE=$2 + shift # past argument + ;; + -d|--debug) + GBL_DEBUG_MODE=1 + ;; + *) + usage # unknown option + ;; + esac + shift # past argument or value + done +} + +#/* +#* FEATURE: +#* valid_conf +#* PURPOSE: +#* check if configuration files are valid +#* PARAMETERS: +#* +#* RETURNS: +#* success, this function returns nothing +#* fail, returns @E_INVALID_CONF +#*/ +function valid_conf() { + local list_1 list_2 match_num + + list_1=("${!1}") + list_2=("${!2}") + + # validate zone config + [ ${GBL_TEMP_NUM} -eq 0 ] && err_msg "config: status=invalid. reason=no TEMPERATURE SENSORS defined." "${E_INVALID_CONF}" + [ ${GBL_FAN_NUM} -eq 0 ] && err_msg "config: status=invalid. reason=no FAN defined." "${E_INVALID_CONF}" + + # validate thermal config + [ ${GBL_LEVEL_NUM} -eq 0 ] && err_msg "config: status=invalid. reason=no FAN LEVELS defined." "${E_INVALID_CONF}" + [ ${#list_2[@]} -ne ${GBL_TEMP_NUM} ] && err_msg "config: status=invalid. reason=the number of temperature sensors is inconsistent." "${E_INVALID_CONF}" + + # compare temperature sensor name between configuration files + match_num=0 + for i in ${!list_1[@]} + do + for j in ${!list_2[@]} + do + [ "${list_1[$i]}" == "${list_2[$j]}" ] && match_num=$(( $match_num+1 )) + done + done + [ $match_num -ne ${GBL_TEMP_NUM} ] && err_msg "config: status=invalid. reason=the name of temperature sensors is inconsistent." "${E_INVALID_CONF}" + + # validate pwm values + for pwm in ${GBL_FAN_LEVEL[@]} + do + expr $pwm + $GBL_MIN_PWM >/dev/null 2>&1 + [ $? -ne 0 ] && err_msg "config: status=invalid. reason=the value of pwm is not integer." "$E_INVALID_CONF" + [ $pwm -lt $GBL_MIN_PWM ] && err_msg "config: status=invalid. reason=the value of fan level is less than MIN_PWM($GBL_MIN_PWM)." "$E_INVALID_CONF" + done +} + +#/* +#* FEATURE: +#* initialize +#* PURPOSE: +#* load zone config and thermal config +#* PARAMETERS: +#* +#* RETURNS: +#* +#*/ +function initialize() { + local data conf_interval conf_hysis conf_min_pwm conf_zone_id conf_msg_level temp_list_1 temp_list_2 + + log_msg $MSG_INFO "Initializing fan control service..." + + # fetch temperature sensor name from configuration files + temp_list_1=(`cat ${GBL_ZONE_CONF} | grep "^${SYMBOL_TEMP}" | awk -F "," {'print $1'}`) + temp_list_2=(`cat ${GBL_TEMP_CONF} | grep "^${SYMBOL_TEMP}" | awk {'print $1'}`) + + # calculate the number of temperature/fan sensors + GBL_TEMP_NUM=${#temp_list_1[@]} + GBL_FAN_NUM=(`cat ${GBL_ZONE_CONF} | grep "^${SYMBOL_FAN}" | awk {'print $2'} | wc -l`) + + # calculate the number of fan levels + GBL_FAN_LEVEL=(`cat ${GBL_TEMP_CONF} | grep "^PWM" | awk -F "PWM" {'print $2'}`) + GBL_LEVEL_NUM=${#GBL_FAN_LEVEL[@]} + + # check if the interval/hyteresis should be updated. + conf_interval=`cat ${GBL_ZONE_CONF} | grep "^INTERVAL=" | awk -F "=" {'print $2'} | tail` + [ ! -z ${conf_interval} ] && GBL_INTERVAL=${conf_interval} + conf_hysis=`cat ${GBL_ZONE_CONF} | grep "^HYTERESIS=" | awk -F "=" {'print $2'} | tail` + [ ! -z ${conf_hysis} ] && GBL_HYSIS=${conf_hysis} + conf_min_pwm=`cat ${GBL_ZONE_CONF} | grep "^MIN_PWM=" | awk -F "=" {'print $2'} | tail` + [ ! -z ${conf_min_pwm} ] && GBL_MIN_PWM=${conf_min_pwm} + conf_zone_id=`cat ${GBL_ZONE_CONF} | grep "^ZONE_ID=" | awk -F "=" {'print $2'} | tail` + [ ! -z ${conf_zone_id} ] && GBL_ZONE_ID=${conf_zone_id} + conf_msg_level=`cat ${GBL_ZONE_CONF} | grep "^MSG_LEVEL=" | awk -F "=" {'print $2'} | tail` + [ ! -z ${conf_msg_level} ] && GBL_MSG_LEVEL=${conf_msg_level} + + # load zone config + for ((i=1; i<=${GBL_TEMP_NUM}; i++)) + do + GBL_TEMP_STATUSES+=($E_STATUS_GOOD) + data=`cat ${GBL_ZONE_CONF} | grep "^${SYMBOL_TEMP}" | awk NR==$i` + # FIXME + GBL_TEMP_GRP+=("`echo $data | awk -F ", " {'print $1'}`") + GBL_TEMP_GRP+=("`echo $data | awk -F ", " {'print $2'}`") + GBL_TEMP_GRP+=("`echo $data | awk -F ", " {'print $3'}`") + done + debug_temp_grp + + for ((i=1; i<=${GBL_FAN_NUM}; i++)) + do + data=`cat ${GBL_ZONE_CONF} | grep "^${SYMBOL_FAN}" | awk NR==$i{'print $2'}` + GBL_FAN_GRP+=("`echo $data`") + done + + # load thermal config + for ((i=0; i<${GBL_TEMP_NUM}; i++)) + do + index=$(( $i * ${STRUCT_TEMP_SIZE} + ${STRUCT_TEMP_NAME} )) + sensor_name=${GBL_TEMP_GRP[$index]} + GBL_TEMP_PROPERTY+=(`cat ${GBL_TEMP_CONF} | grep "^${sensor_name}" | tail`) + done + debug_temp_property + + # check if the config files is valid + valid_conf temp_list_1[@] temp_list_2[@] +} + +#/* +#* FEATURE: +#* temperature_collection +#* PURPOSE: +#* collect all temperature sensor readlings +#* PARAMETERS: +#* +#* RETURNS: +#* success, returns a series of reading @GBL_TEMP_READINGS[] +#*/ +function temperature_collection() { + local name cmd max_temp reading status pre_status + + GBL_TEMP_READINGS=() + for ((i=0; i<${GBL_TEMP_NUM}; i++)) + do + # read temperature sensor value & record sensor status + name=`fetch_temp_struct $i ${STRUCT_TEMP_NAME}` + cmd=`fetch_temp_struct $i ${STRUCT_TEMP_CMD}` + max_temp=`fetch_temp_struct $i ${STRUCT_TEMP_MAX}` + reading=`eval ${cmd} 2>/dev/null` + if [ $? -eq 0 ]; then + GBL_TEMP_READINGS+=($reading) + status=$E_STATUS_GOOD + else + GBL_TEMP_READINGS+=($max_temp) + status=$E_STATUS_FAULT + fi + + # Compare previous status of temperature sensor, then update it. + pre_status=${GBL_TEMP_STATUSES[$i]} + if [ $pre_status -eq $E_STATUS_GOOD ] && [ $status -eq $E_STATUS_FAULT ]; then + # Good -> Fault + log_msg $MSG_WARN "[ZONE_${GBL_ZONE_ID}] Sensor $name: status=ERROR. reason=read sensor failed." + elif [ $pre_status -eq $E_STATUS_FAULT ] && [ $status -eq $E_STATUS_GOOD ]; then + # Fault -> Good + log_msg $MSG_WARN "[ZONE_${GBL_ZONE_ID}] Sensor $name: status=RECOVER. reason=reading is $reading deg C" + fi + GBL_TEMP_STATUSES[$i]=$status + done + debug_temp_readings +} + +#/* +#* FEATURE: +#* fan_level_selection +#* PURPOSE: +#* select proper fan level by temperature sensor reading +#* PARAMETERS: +#* reading_list (IN) sensor reading list +#* RETURNS: +#* success, returns a fan level value +#*/ +function fan_level_selection() { + local reading_list name reading temp_list highest_level pre_level next_level hysis_temp res res1 + + reading_list=("${!1}") + highest_level=0 + pre_level=${GBL_CUR_LEVEL} + next_level=0 + + # search fan table by each temperature sensor reading + for ((i=0; i<${GBL_TEMP_NUM}; i++)) + do + name=`fetch_temp_struct $i $STRUCT_TEMP_NAME` + reading=${reading_list[$i]} + temp_list=(`fetch_temp_property ${name}`) + for j in ${!temp_list[@]} + do + res=`echo $reading \<= ${temp_list[$j]} | bc -l` + if [ $res -eq 1 ] || [ $j -eq $((${#temp_list[@]}-1)) ]; then + if [ $j -gt $highest_level ]; then + highest_level=$j + fi + break + fi + done + done + + if [ $highest_level -lt $pre_level ]; then + # Determine if require decreasing current fan level @assert_level + local pass_num + pass_num=0 + for ((i=0; i<${GBL_TEMP_NUM}; i++)) + do + name=`fetch_temp_struct $i $STRUCT_TEMP_NAME` + reading=${reading_list[$i]} + temp_list=(`fetch_temp_property ${name}`) + assert_level=$(( $pre_level-1 )) + hysis_temp=`echo ${temp_list[$assert_level]} - $GBL_HYSIS | bc` + res=`echo $reading \<= $hysis_temp | bc -l` + if [ $res -eq 1 ]; then + pass_num=$(( $pass_num+1 )) + else + break + fi + done + if [ $pass_num -eq ${GBL_TEMP_NUM} ]; then + # Decrease fan pwm: All sensor reading should less than its own hysteresis temperature + next_level=${highest_level} + else + # Keep current fan pwm + next_level=${pre_level} + fi + else + # Increase fan pwm + next_level=${highest_level} + fi + GBL_CUR_LEVEL=${next_level} +} + +#/* +#* FEATURE: +#* apply_fan_level +#* PURPOSE: +#* convert given fan level to PWM, then output to fans +#* PARAMETERS: +#* fan_list (IN) fan devices list +#* fan_level (IN) fan level +#* RETURNS: +#* success, returns a pwm value +#*/ +function apply_fan_level() { + local fan_level fan_list + + fan_list=("${!1}") + fan_level=$2 + + for fan in ${fan_list[@]} + do + echo ${GBL_FAN_LEVEL[$fan_level]} > $fan + done + debug_fan_speed +} + +#/* +#********************************************************************** +#* +#* MAIN +#* +#********************************************************************** +#*/ +Platform_init +arg_parse $@ +initialize +log_msg $MSG_INFO "Starting fan control service..." +while [ true ]; do + temperature_collection + fan_level_selection GBL_TEMP_READINGS[@] + apply_fan_level GBL_FAN_GRP[@] ${GBL_CUR_LEVEL} + sleep $GBL_INTERVAL +done + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf new file mode 100644 index 000000000000..56409f5c3e30 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf @@ -0,0 +1,12 @@ +##### Temperature vs Fan table ##### +## FORMAT: "PWM" fan speed(range from 0 to 255) +# Duty Cycle 25% 30% 35% 40% 45% 50% 55% 60% 65% 70% 75% 80% 85% 90% 95% 100% +PWM 64 77 89 102 115 128 140 153 166 179 191 204 217 230 242 255 +## FORMAT: sensor name(TEMP_XXX) with asserted temperature by each levels +TEMP_CPU 52 55 58 61 64 67 70 73 76 79 82 85 88 91 94 97 +TEMP_SWITCH 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120 +#TEMP_HDD 25 +#TEMP_TMP75_CPU 25 +#TEMP_TMP75_CENTER 25 +#TEMP_TMP75_RIGHT 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93 +TEMP_TMP75_FAN 26.5 31.5 36.5 41.5 46.5 51.5 56.5 61.5 66.5 71.5 76.5 81.5 86.5 91.5 96.5 101.5 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf new file mode 100644 index 000000000000..6c459d874feb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf @@ -0,0 +1,12 @@ +##### Temperature vs Fan table ##### +## FORMAT: "PWM" fan speed(range from 0 to 255) +# Duty Cycle 25% 30% 35% 40% 45% 50% 55% 60% 65% 70% 75% 80% 85% 90% 95% 100% +PWM 64 77 89 102 115 128 140 153 166 179 191 204 217 230 242 255 +## FORMAT: sensor name(TEMP_XXX) with asserted temperature by each levels +TEMP_CPU 60 65 70 73 76 79 82 85 88 91 94 97 100 103 106 109 +TEMP_SWITCH 73 76 79 82 85 88 91 94 97 100 103 106 109 112 115 118 +#TEMP_HDD 25 +#TEMP_TMP75_CPU 25 +#TEMP_TMP75_CENTER 25 +TEMP_TMP75_RIGHT 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93 +#TEMP_TMP75_FAN 25 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone_B2F.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone_B2F.conf new file mode 100644 index 000000000000..b51f3b7aa67d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone_B2F.conf @@ -0,0 +1,38 @@ +##### ZONE ID ##### +ZONE_ID=0 + +##### SENSOR GROUP START ##### +## FORMAT: name(TEMP_XXX), command, max_temp(deg C) +TEMP_CPU, "data=`sensors | grep coretemp -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $4'} | sed 's/^+\|°C//g'", 110 +TEMP_SWITCH, "[ `file /var/run/docker-syncd/sswsyncd.socket | grep -c " socket"` -ne 1 ] && exit 1; [ `ss -a | grep "/var/run/sswsyncd/sswsyncd.socket" |grep -c "LISTEN"` -ne 1 ] && exit 1; data=`bcmcmd -c "show temp" | grep "temperature monitor"`; [ $? -ne 0 ] && exit 1; switch_temps=(`echo "$data" | awk {'print $5'} | sed 's/,//g'`); high_temp=0; for reading in ${switch_temps[@]}; do res=`echo "$reading > $high_temp" | bc -l`; [ $res -eq 1 ] && high_temp=$reading; done; echo $high_temp", 120 +#TEMP_HDD, "data=`hddtemp /dev/sdb | grep -v "not available"`; [ $? -ne 0 ] && exit 1; echo "$data" | awk -F ": " {'print $3'} | sed 's/°C//g'", 85 +#TEMP_TMP75_CPU, "data=`sensors | grep tmp75-i2c-0-4e -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +#TEMP_TMP75_CENTER, "data=`sensors | grep tmp75-i2c-4-4a -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +#TEMP_TMP75_RIGHT, "data=`sensors | grep tmp75-i2c-4-4c -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +TEMP_TMP75_FAN, "data=`sensors | grep tmp75-i2c-4-4d -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +##### SENSOR GROUP END ##### + +##### FAN GROUP START ##### +## FORMAT: name(FAN_YYY) input_files +FAN_1 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm1 +FAN_2 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm2 +FAN_3 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm3 +FAN_4 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm4 +FAN_5 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm5 +FAN_6 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm6 +FAN_7 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm1 +FAN_8 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm2 +FAN_9 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm3 +FAN_10 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm4 +FAN_11 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm5 +FAN_12 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm6 +##### FAN GROUP END ##### + +##### INTERVAL (sec) ##### +INTERVAL=10 + +##### HYTERESIS (deg C) ##### +HYTERESIS=2 + +##### MINIMUM PWM (38.25=255x15%) ##### +MIN_PWM=39 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone_F2B.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone_F2B.conf new file mode 100644 index 000000000000..2d5987c5c66b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone_F2B.conf @@ -0,0 +1,38 @@ +##### ZONE ID ##### +ZONE_ID=0 + +##### SENSOR GROUP START ##### +## FORMAT: name(TEMP_XXX), command, max_temp(deg C) +TEMP_CPU, "data=`sensors | grep coretemp -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $4'} | sed 's/^+\|°C//g'", 110 +TEMP_SWITCH, "[ `file /var/run/docker-syncd/sswsyncd.socket | grep -c " socket"` -ne 1 ] && exit 1; [ `ss -a | grep "/var/run/sswsyncd/sswsyncd.socket" |grep -c "LISTEN"` -ne 1 ] && exit 1; data=`bcmcmd -c "show temp" | grep "temperature monitor"`; [ $? -ne 0 ] && exit 1; switch_temps=(`echo "$data" | awk {'print $5'} | sed 's/,//g'`); high_temp=0; for reading in ${switch_temps[@]}; do res=`echo "$reading > $high_temp" | bc -l`; [ $res -eq 1 ] && high_temp=$reading; done; echo $high_temp", 120 +#TEMP_HDD, "data=`hddtemp /dev/sdb | grep -v "not available"`; [ $? -ne 0 ] && exit 1; echo "$data" | awk -F ": " {'print $3'} | sed 's/°C//g'", 85 +#TEMP_TMP75_CPU, "data=`sensors | grep tmp75-i2c-0-4e -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +#TEMP_TMP75_CENTER, "data=`sensors | grep tmp75-i2c-4-4a -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +TEMP_TMP75_RIGHT, "data=`sensors | grep tmp75-i2c-4-4c -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +#TEMP_TMP75_FAN, "data=`sensors | grep tmp75-i2c-4-4d -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +##### SENSOR GROUP END ##### + +##### FAN GROUP START ##### +## FORMAT: name(FAN_YYY) input_files +FAN_1 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm1 +FAN_2 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm2 +FAN_3 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm3 +FAN_4 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm4 +FAN_5 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm5 +FAN_6 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm6 +FAN_7 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm1 +FAN_8 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm2 +FAN_9 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm3 +FAN_10 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm4 +FAN_11 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm5 +FAN_12 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm6 +##### FAN GROUP END ##### + +##### INTERVAL (sec) ##### +INTERVAL=10 + +##### HYTERESIS (deg C) ##### +HYTERESIS=2 + +##### MINIMUM PWM (38.25=255x15%) ##### +MIN_PWM=39 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/funcs.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/funcs.sh new file mode 100755 index 000000000000..3e417f699543 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/funcs.sh @@ -0,0 +1,22 @@ +#!/bin/bash +#/* +#********************************************************************** +#* +#* @filename funcs.sh +#* +#* @purpose api functions script for fan-ctrl +#* +#* @create 2017/08/09 +#* +#* @author nixon.chu +#* +#* @history 2017/08/09: init version +#* +#********************************************************************** +#*/ + +DIR=$(dirname $0) + +function Platform_init() { + ${DIR}/init.sh +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/init.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/init.sh new file mode 100755 index 000000000000..06df071fa147 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/init.sh @@ -0,0 +1,26 @@ +#!/bin/bash +DIR=$(dirname $0) + +# board type +BOARD_TYPE=`cat /sys/bus/i2c/devices/1-0032/brd_type` + +# fan tables +FORWARD_SENSOR_CONF=${DIR}/fan-zone_F2B.conf +FORWARD_PWM_CONF=${DIR}/fan-zone-thermal_F2B.conf +REVERSE_SENSOR_CONF=${DIR}/fan-zone_B2F.conf +REVERSE_PWM_CONF=${DIR}/fan-zone-thermal_B2F.conf + +# Nixon: Please refer to "BMS CPLD Design Spec." +# board type : BRD_TYPE[3:0] +# 0x0 (0000b): BMS_AC_PSU_NORMAL_FAN, 0x2 (0010b): BMS_DC_PSU_NORMAL_FAN +# 0x1 (0001b): BMS_AC_PSU_REVERSE_FAN, 0x3 (0011b): BMS_DC_PSU_REVERSE_FAN +case $BOARD_TYPE in + 0x0|0x2) + ln -sf $FORWARD_SENSOR_CONF ${DIR}/fan-zone.conf + ln -sf $FORWARD_PWM_CONF ${DIR}/fan-zone-thermal.conf + ;; + 0x1|0x3) + ln -sf $REVERSE_SENSOR_CONF ${DIR}/fan-zone.conf + ln -sf $REVERSE_PWM_CONF ${DIR}/fan-zone-thermal.conf + ;; +esac diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/funcs.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/funcs.sh new file mode 100755 index 000000000000..4b0c4c35471f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/funcs.sh @@ -0,0 +1,23 @@ +#/bin/bash + +# process name/id +DAEMON_NAME=`basename $0` +DAEMON_PID="$$" + +DEF_SEVERITY="INFO" + +#/* +#* FEATURE: +#* log_msg +#* PURPOSE: +#* log message +#* PARAMETERS: +#* msg (IN) message +#* RETURNS: +#* +#*/ +function log_msg() { + local msg=$1 + + `logger -t $DAEMON_NAME -p $DEF_SEVERITY $msg` +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_service.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_service.sh new file mode 100755 index 000000000000..2bc9589738d0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_service.sh @@ -0,0 +1,99 @@ +#/bin/bash + +DIR=$(dirname $0) + +# include files +source ${DIR}/funcs.sh + +ACPI_INSTALL_PRINT=0 +ACPID_INSTALL_PRINT=0 +BC_INSTALL_PRINT=0 +ACPID_SOCKET_PRINT=0 +ACPI_PRINT=0 + + +while [ 1 ] +do + if [ `dpkg -l |grep -c "acpi "` -eq "0" ]; then + dpkg -i /opt/debs/acpi_1.7-1_amd64.deb + if [ "$?" -ne "0" ]; then + if [ $ACPI_INSTALL_PRINT -eq 0 ]; then + ACPI_INSTALL_PRINT=1 + log_msg "Wait for acpi package install." + fi + sleep 1 + continue + else + log_msg "Install acpi package success." + fi + fi + break +done + +while [ 1 ] +do + if [ `dpkg -l |grep -c "acpid "` -eq "0" ]; then + dpkg -i /opt/debs/acpid_2.0.23-2_amd64.deb + if [ "$?" -ne "0" ]; then + if [ $ACPID_INSTALL_PRINT -eq 0 ]; then + ACPID_INSTALL_PRINT=1 + log_msg "Wait for acpid package install." + fi + sleep 1 + continue + else + log_msg "Install acpid package success." + fi + fi + break +done + +while [ 1 ] +do + if [ `dpkg -l |grep -c " bc "` -eq "0" ]; then + dpkg -i /opt/debs/bc_1.06.95-9_amd64.deb + if [ "$?" -ne "0" ]; then + if [ $BC_INSTALL_PRINT -eq 0 ]; then + BC_INSTALL_PRINT=1 + log_msg "Wait for bc package install." + fi + sleep 1 + continue + else + log_msg "Install bc package success." + fi + fi + break +done + +while [ 1 ] +do + if [ ! -e "/sys/firmware/acpi/interrupts/gpe01" ]; then + if [ $ACPI_PRINT -eq 0 ]; then + ACPI_PRINT=1 + log_msg "Wait for acpi daemon start." + fi + sleep 1 + continue + fi + log_msg "The acpi daemon start." + break +done + +while [ 1 ] +do + if [ ! -e "/var/run/acpid.socket" ]; then + if [ $ACPID_SOCKET_PRINT -eq 0 ]; then + ACPID_SOCKET_PRINT=1 + log_msg "Wait for acipd daemon start." + fi + sleep 1 + continue + fi + log_msg "The acpid daemon start." + break +done + +/etc/init.d/xcvr_servd start +/etc/init.d/sys_servd start +exit 0; diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_watchdog.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_watchdog.sh new file mode 100755 index 000000000000..2268e5e0d16e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_watchdog.sh @@ -0,0 +1,32 @@ +#/bin/bash + +DIR=$(dirname $0) + +# include files +source ${DIR}/funcs.sh + +WATCHDOG_PRINT=0 + +while [ 1 ] +do + if [ `dpkg -l |grep -c "watchdog "` -eq "0" ]; then + dpkg -i /opt/debs/watchdog_5.14-3_amd64.deb + if [ "$?" -ne "0" ]; then + if [ $WATCHDOG_PRINT -eq 0 ]; then + WATCHDOG_PRINT=1 + log_msg "Wait for watchdog package install." + fi + sleep 1 + continue + else + log_msg "Install watchdog package success." + fi + fi + break +done + +ln -sf /opt/watchdog/watchdog.conf /etc/watchdog.conf + +/usr/sbin/watchdog -c /etc/watchdog.conf + +exit 0; diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/sys-servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/sys-servd new file mode 100755 index 000000000000..a1b4f177897c Binary files /dev/null and b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/sys-servd differ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/system-check/system-check.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/system-check/system-check.sh new file mode 100755 index 000000000000..f44ed046330d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/system-check/system-check.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +SW_READY_STAMP='/tmp/.BcmSdkReady' +SYSTEM_INIT=0 +CURRENTR_LED=0 + +# 0 was not ready, 1 was ready +SYSTEM_READY=1 + +function check_sdk_ready() { + if [ `file /var/run/docker-syncd/sswsyncd.socket | grep -c " socket"` -ne 1 ]; then + SYSTEM_READY=0 + return 1 + else + if [ `ss -a | grep "/var/run/sswsyncd/sswsyncd.socket" |grep -c "LISTEN"` -ne 1 ]; then + SYSTEM_READY=0 + return 1 + fi + fi + return 0 +} + +while [ true ] +do + SYSTEM_READY=1 + #-----check start------------ + check_sdk_ready + #-----cech end--------------- + + if [ "$SYSTEM_INIT" -eq "0" ]; then + if [ $SYSTEM_READY -eq 1 ]; then + SYSTEM_INIT=1 + # set SYSTEM LED to Green + echo 0x01 > /sys/bus/i2c/devices/1-0032/system_led_fld + CURRENTR_LED=1 + fi + else + if [ $SYSTEM_READY -eq 0 ]; then + # set SYSTEM LED to Amber + if [ "$CURRENTR_LED" -ne "2" ]; then + echo 0x02 > /sys/bus/i2c/devices/1-0032/system_led_fld + CURRENTR_LED=2 + fi + else + # set SYS LED to Green + if [ "$CURRENTR_LED" -ne "1" ]; then + echo 0x01 > /sys/bus/i2c/devices/1-0032/system_led_fld + CURRENTR_LED=1 + fi + fi + fi + sleep 10 +done + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/watchdog/watchdog.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/watchdog/watchdog.conf new file mode 100644 index 000000000000..81f0b7b819bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/watchdog/watchdog.conf @@ -0,0 +1,45 @@ +#ping = 172.31.14.1 +#ping = 172.26.1.255 +#interface = eth0 +#file = /var/log/messages +#change = 1407 + +# Uncomment to enable test. Setting one of these values to '0' disables it. +# These values will hopefully never reboot your machine during normal use +# (if your machine is really hung, the loadavg will go much higher than 25) +#max-load-1 = 24 +#max-load-5 = 18 +#max-load-15 = 12 + +# Note that this is the number of pages! +# To get the real size, check how large the pagesize is on your machine. +#min-memory = 1 +#allocatable-memory = 1 + +#repair-binary = /usr/sbin/repair +#repair-timeout = +#test-binary = +#test-timeout = + +watchdog-device = /dev/watchdog + +# Defaults compiled into the binary +#temperature-device = +#max-temperature = 120 + +# Defaults compiled into the binary +#admin = root +#interval = 1 +#logtick = 1 +#log-dir = /var/log/watchdog + +# This greatly decreases the chance that watchdog won't be scheduled before +# your machine is really loaded +realtime = yes +priority = 99 + +# Check if rsyslogd is still running by enabling the following line +#pidfile = /var/run/rsyslogd.pid + +# timeout : 15 , 30 , 60 , 90 , 120 , 180 , 240 sec +watchdog-timeout = 120 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/xcvr-servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/xcvr-servd new file mode 100755 index 000000000000..c882ff8e335a Binary files /dev/null and b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/xcvr-servd differ diff --git a/platform/broadcom/sonic-platform-modules-quanta/.gitignore b/platform/broadcom/sonic-platform-modules-quanta/.gitignore new file mode 100755 index 000000000000..7f287d538227 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/.gitignore @@ -0,0 +1,50 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-quanta/LICENSE b/platform/broadcom/sonic-platform-modules-quanta/LICENSE new file mode 100755 index 000000000000..609b3082d11c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2018 Quanta Computer 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 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-quanta/README.md b/platform/broadcom/sonic-platform-modules-quanta/README.md new file mode 100644 index 000000000000..bcc06271904a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-quanta +SONiC platform folder which contain drivers for Quanta Switch diff --git a/platform/broadcom/sonic-platform-modules-quanta/debian/changelog b/platform/broadcom/sonic-platform-modules-quanta/debian/changelog new file mode 100755 index 000000000000..77d3407ec943 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/debian/changelog @@ -0,0 +1,6 @@ +sonic-quanta-platform-modules (1.0) unstable; urgency=low + + * Add support for Quanta IX1B-32X + * Initial release + + -- Chih-Pei Chang Jonathan Tsai Wed, 20 Dec 2017 09:26:01 +0800 diff --git a/platform/broadcom/sonic-platform-modules-quanta/debian/compat b/platform/broadcom/sonic-platform-modules-quanta/debian/compat new file mode 100755 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-quanta/debian/control b/platform/broadcom/sonic-platform-modules-quanta/debian/control new file mode 100755 index 000000000000..af058ee98f2d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/debian/control @@ -0,0 +1,12 @@ +Source: sonic-quanta-platform-modules +Section: main +Priority: extra +Maintainer: Chih-Pei Chang , Jonathan Tsai +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-quanta-ix1b-32x +Architecture: amd64 +Depends: linux-image-3.16.0-5-amd64 +Description: kernel modules for platform devices such as psu, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-quanta/debian/rules b/platform/broadcom/sonic-platform-modules-quanta/debian/rules new file mode 100755 index 000000000000..45bb29742a1c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/debian/rules @@ -0,0 +1,86 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-quanta +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= ix1b-32x +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CLASSES_DIR := classes +CONF_DIR := conf + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + $(PYTHON) $${mod}/setup.py build; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/Makefile new file mode 100755 index 000000000000..fd73f274ef53 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m:=qci_pmbus.o qci_cpld_qsfp28.o qci_platform_ix1b.o + + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/pmbus.h new file mode 100755 index 000000000000..fa9beb3eb60c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/pmbus.h @@ -0,0 +1,387 @@ +/* + * pmbus.h - Common defines and structures for PMBus devices + * + * Copyright (c) 2010, 2011 Ericsson AB. + * Copyright (c) 2012 Guenter Roeck + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PMBUS_H +#define PMBUS_H + +/* + * Registers + */ +#define PMBUS_PAGE 0x00 +#define PMBUS_OPERATION 0x01 +#define PMBUS_ON_OFF_CONFIG 0x02 +#define PMBUS_CLEAR_FAULTS 0x03 +#define PMBUS_PHASE 0x04 + +#define PMBUS_CAPABILITY 0x19 +#define PMBUS_QUERY 0x1A + +#define PMBUS_VOUT_MODE 0x20 +#define PMBUS_VOUT_COMMAND 0x21 +#define PMBUS_VOUT_TRIM 0x22 +#define PMBUS_VOUT_CAL_OFFSET 0x23 +#define PMBUS_VOUT_MAX 0x24 +#define PMBUS_VOUT_MARGIN_HIGH 0x25 +#define PMBUS_VOUT_MARGIN_LOW 0x26 +#define PMBUS_VOUT_TRANSITION_RATE 0x27 +#define PMBUS_VOUT_DROOP 0x28 +#define PMBUS_VOUT_SCALE_LOOP 0x29 +#define PMBUS_VOUT_SCALE_MONITOR 0x2A + +#define PMBUS_COEFFICIENTS 0x30 +#define PMBUS_POUT_MAX 0x31 + +#define PMBUS_FAN_CONFIG_12 0x3A +#define PMBUS_FAN_COMMAND_1 0x3B +#define PMBUS_FAN_COMMAND_2 0x3C +#define PMBUS_FAN_CONFIG_34 0x3D +#define PMBUS_FAN_COMMAND_3 0x3E +#define PMBUS_FAN_COMMAND_4 0x3F + +#define PMBUS_VOUT_OV_FAULT_LIMIT 0x40 +#define PMBUS_VOUT_OV_FAULT_RESPONSE 0x41 +#define PMBUS_VOUT_OV_WARN_LIMIT 0x42 +#define PMBUS_VOUT_UV_WARN_LIMIT 0x43 +#define PMBUS_VOUT_UV_FAULT_LIMIT 0x44 +#define PMBUS_VOUT_UV_FAULT_RESPONSE 0x45 +#define PMBUS_IOUT_OC_FAULT_LIMIT 0x46 +#define PMBUS_IOUT_OC_FAULT_RESPONSE 0x47 +#define PMBUS_IOUT_OC_LV_FAULT_LIMIT 0x48 +#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE 0x49 +#define PMBUS_IOUT_OC_WARN_LIMIT 0x4A +#define PMBUS_IOUT_UC_FAULT_LIMIT 0x4B +#define PMBUS_IOUT_UC_FAULT_RESPONSE 0x4C + +#define PMBUS_OT_FAULT_LIMIT 0x4F +#define PMBUS_OT_FAULT_RESPONSE 0x50 +#define PMBUS_OT_WARN_LIMIT 0x51 +#define PMBUS_UT_WARN_LIMIT 0x52 +#define PMBUS_UT_FAULT_LIMIT 0x53 +#define PMBUS_UT_FAULT_RESPONSE 0x54 +#define PMBUS_VIN_OV_FAULT_LIMIT 0x55 +#define PMBUS_VIN_OV_FAULT_RESPONSE 0x56 +#define PMBUS_VIN_OV_WARN_LIMIT 0x57 +#define PMBUS_VIN_UV_WARN_LIMIT 0x58 +#define PMBUS_VIN_UV_FAULT_LIMIT 0x59 + +#define PMBUS_IIN_OC_FAULT_LIMIT 0x5B +#define PMBUS_IIN_OC_WARN_LIMIT 0x5D + +#define PMBUS_POUT_OP_FAULT_LIMIT 0x68 +#define PMBUS_POUT_OP_WARN_LIMIT 0x6A +#define PMBUS_PIN_OP_WARN_LIMIT 0x6B + +#define PMBUS_STATUS_BYTE 0x78 +#define PMBUS_STATUS_WORD 0x79 +#define PMBUS_STATUS_VOUT 0x7A +#define PMBUS_STATUS_IOUT 0x7B +#define PMBUS_STATUS_INPUT 0x7C +#define PMBUS_STATUS_TEMPERATURE 0x7D +#define PMBUS_STATUS_CML 0x7E +#define PMBUS_STATUS_OTHER 0x7F +#define PMBUS_STATUS_MFR_SPECIFIC 0x80 +#define PMBUS_STATUS_FAN_12 0x81 +#define PMBUS_STATUS_FAN_34 0x82 + +#define PMBUS_READ_VIN 0x88 +#define PMBUS_READ_IIN 0x89 +#define PMBUS_READ_VCAP 0x8A +#define PMBUS_READ_VOUT 0x8B +#define PMBUS_READ_IOUT 0x8C +#define PMBUS_READ_TEMPERATURE_1 0x8D +#define PMBUS_READ_TEMPERATURE_2 0x8E +#define PMBUS_READ_TEMPERATURE_3 0x8F +#define PMBUS_READ_FAN_SPEED_1 0x90 +#define PMBUS_READ_FAN_SPEED_2 0x91 +#define PMBUS_READ_FAN_SPEED_3 0x92 +#define PMBUS_READ_FAN_SPEED_4 0x93 +#define PMBUS_READ_DUTY_CYCLE 0x94 +#define PMBUS_READ_FREQUENCY 0x95 +#define PMBUS_READ_POUT 0x96 +#define PMBUS_READ_PIN 0x97 + +#define PMBUS_REVISION 0x98 +#define PMBUS_MFR_ID 0x99 +#define PMBUS_MFR_MODEL 0x9A +#define PMBUS_MFR_REVISION 0x9B +#define PMBUS_MFR_LOCATION 0x9C +#define PMBUS_MFR_DATE 0x9D +#define PMBUS_MFR_SERIAL 0x9E + +/* + * Virtual registers. + * Useful to support attributes which are not supported by standard PMBus + * registers but exist as manufacturer specific registers on individual chips. + * Must be mapped to real registers in device specific code. + * + * Semantics: + * Virtual registers are all word size. + * READ registers are read-only; writes are either ignored or return an error. + * RESET registers are read/write. Reading reset registers returns zero + * (used for detection), writing any value causes the associated history to be + * reset. + * Virtual registers have to be handled in device specific driver code. Chip + * driver code returns non-negative register values if a virtual register is + * supported, or a negative error code if not. The chip driver may return + * -ENODATA or any other error code in this case, though an error code other + * than -ENODATA is handled more efficiently and thus preferred. Either case, + * the calling PMBus core code will abort if the chip driver returns an error + * code when reading or writing virtual registers. + */ +#define PMBUS_VIRT_BASE 0x100 +#define PMBUS_VIRT_READ_TEMP_AVG (PMBUS_VIRT_BASE + 0) +#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 1) +#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 2) +#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 3) +#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 4) +#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 5) +#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 6) +#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 7) +#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 8) +#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 9) +#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 10) +#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 11) +#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 12) +#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 13) +#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 14) +#define PMBUS_VIRT_READ_POUT_AVG (PMBUS_VIRT_BASE + 15) +#define PMBUS_VIRT_READ_POUT_MAX (PMBUS_VIRT_BASE + 16) +#define PMBUS_VIRT_RESET_POUT_HISTORY (PMBUS_VIRT_BASE + 17) +#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 18) +#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 19) +#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 20) +#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 21) +#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 22) +#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 23) +#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 24) +#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 25) +#define PMBUS_VIRT_READ_TEMP2_AVG (PMBUS_VIRT_BASE + 26) +#define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 27) +#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 28) +#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 29) + +#define PMBUS_VIRT_READ_VMON (PMBUS_VIRT_BASE + 30) +#define PMBUS_VIRT_VMON_UV_WARN_LIMIT (PMBUS_VIRT_BASE + 31) +#define PMBUS_VIRT_VMON_OV_WARN_LIMIT (PMBUS_VIRT_BASE + 32) +#define PMBUS_VIRT_VMON_UV_FAULT_LIMIT (PMBUS_VIRT_BASE + 33) +#define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34) +#define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35) + +/* + * CAPABILITY + */ +#define PB_CAPABILITY_SMBALERT (1<<4) +#define PB_CAPABILITY_ERROR_CHECK (1<<7) + +/* + * VOUT_MODE + */ +#define PB_VOUT_MODE_MODE_MASK 0xe0 +#define PB_VOUT_MODE_PARAM_MASK 0x1f + +#define PB_VOUT_MODE_LINEAR 0x00 +#define PB_VOUT_MODE_VID 0x20 +#define PB_VOUT_MODE_DIRECT 0x40 + +/* + * Fan configuration + */ +#define PB_FAN_2_PULSE_MASK ((1 << 0) | (1 << 1)) +#define PB_FAN_2_RPM (1 << 2) +#define PB_FAN_2_INSTALLED (1 << 3) +#define PB_FAN_1_PULSE_MASK ((1 << 4) | (1 << 5)) +#define PB_FAN_1_RPM (1 << 6) +#define PB_FAN_1_INSTALLED (1 << 7) + +/* + * STATUS_BYTE, STATUS_WORD (lower) + */ +#define PB_STATUS_NONE_ABOVE (1<<0) +#define PB_STATUS_CML (1<<1) +#define PB_STATUS_TEMPERATURE (1<<2) +#define PB_STATUS_VIN_UV (1<<3) +#define PB_STATUS_IOUT_OC (1<<4) +#define PB_STATUS_VOUT_OV (1<<5) +#define PB_STATUS_OFF (1<<6) +#define PB_STATUS_BUSY (1<<7) + +/* + * STATUS_WORD (upper) + */ +#define PB_STATUS_UNKNOWN (1<<8) +#define PB_STATUS_OTHER (1<<9) +#define PB_STATUS_FANS (1<<10) +#define PB_STATUS_POWER_GOOD_N (1<<11) +#define PB_STATUS_WORD_MFR (1<<12) +#define PB_STATUS_INPUT (1<<13) +#define PB_STATUS_IOUT_POUT (1<<14) +#define PB_STATUS_VOUT (1<<15) + +/* + * STATUS_IOUT + */ +#define PB_POUT_OP_WARNING (1<<0) +#define PB_POUT_OP_FAULT (1<<1) +#define PB_POWER_LIMITING (1<<2) +#define PB_CURRENT_SHARE_FAULT (1<<3) +#define PB_IOUT_UC_FAULT (1<<4) +#define PB_IOUT_OC_WARNING (1<<5) +#define PB_IOUT_OC_LV_FAULT (1<<6) +#define PB_IOUT_OC_FAULT (1<<7) + +/* + * STATUS_VOUT, STATUS_INPUT + */ +#define PB_VOLTAGE_UV_FAULT (1<<4) +#define PB_VOLTAGE_UV_WARNING (1<<5) +#define PB_VOLTAGE_OV_WARNING (1<<6) +#define PB_VOLTAGE_OV_FAULT (1<<7) + +/* + * STATUS_INPUT + */ +#define PB_PIN_OP_WARNING (1<<0) +#define PB_IIN_OC_WARNING (1<<1) +#define PB_IIN_OC_FAULT (1<<2) + +/* + * STATUS_TEMPERATURE + */ +#define PB_TEMP_UT_FAULT (1<<4) +#define PB_TEMP_UT_WARNING (1<<5) +#define PB_TEMP_OT_WARNING (1<<6) +#define PB_TEMP_OT_FAULT (1<<7) + +/* + * STATUS_FAN + */ +#define PB_FAN_AIRFLOW_WARNING (1<<0) +#define PB_FAN_AIRFLOW_FAULT (1<<1) +#define PB_FAN_FAN2_SPEED_OVERRIDE (1<<2) +#define PB_FAN_FAN1_SPEED_OVERRIDE (1<<3) +#define PB_FAN_FAN2_WARNING (1<<4) +#define PB_FAN_FAN1_WARNING (1<<5) +#define PB_FAN_FAN2_FAULT (1<<6) +#define PB_FAN_FAN1_FAULT (1<<7) + +/* + * CML_FAULT_STATUS + */ +#define PB_CML_FAULT_OTHER_MEM_LOGIC (1<<0) +#define PB_CML_FAULT_OTHER_COMM (1<<1) +#define PB_CML_FAULT_PROCESSOR (1<<3) +#define PB_CML_FAULT_MEMORY (1<<4) +#define PB_CML_FAULT_PACKET_ERROR (1<<5) +#define PB_CML_FAULT_INVALID_DATA (1<<6) +#define PB_CML_FAULT_INVALID_COMMAND (1<<7) + +enum pmbus_sensor_classes { + PSC_VOLTAGE_IN = 0, + PSC_VOLTAGE_OUT, + PSC_CURRENT_IN, + PSC_CURRENT_OUT, + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ + +/* Functionality bit mask */ +#define PMBUS_HAVE_VIN (1 << 0) +#define PMBUS_HAVE_VCAP (1 << 1) +#define PMBUS_HAVE_VOUT (1 << 2) +#define PMBUS_HAVE_IIN (1 << 3) +#define PMBUS_HAVE_IOUT (1 << 4) +#define PMBUS_HAVE_PIN (1 << 5) +#define PMBUS_HAVE_POUT (1 << 6) +#define PMBUS_HAVE_FAN12 (1 << 7) +#define PMBUS_HAVE_FAN34 (1 << 8) +#define PMBUS_HAVE_TEMP (1 << 9) +#define PMBUS_HAVE_TEMP2 (1 << 10) +#define PMBUS_HAVE_TEMP3 (1 << 11) +#define PMBUS_HAVE_STATUS_VOUT (1 << 12) +#define PMBUS_HAVE_STATUS_IOUT (1 << 13) +#define PMBUS_HAVE_STATUS_INPUT (1 << 14) +#define PMBUS_HAVE_STATUS_TEMP (1 << 15) +#define PMBUS_HAVE_STATUS_FAN12 (1 << 16) +#define PMBUS_HAVE_STATUS_FAN34 (1 << 17) +#define PMBUS_HAVE_VMON (1 << 18) +#define PMBUS_HAVE_STATUS_VMON (1 << 19) + +enum pmbus_data_format { linear = 0, direct, vid }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + /* + * Support one set of coefficients for each sensor type + * Used for chips providing data in direct mode. + */ + int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */ + int b[PSC_NUM_CLASSES]; /* offset */ + int R[PSC_NUM_CLASSES]; /* exponent */ + + u32 func[PMBUS_PAGES]; /* Functionality, per page */ + /* + * The following functions map manufacturing specific register values + * to PMBus standard register values. Specify only if mapping is + * necessary. + * Functions return the register value (read) or zero (write) if + * successful. A return value of -ENODATA indicates that there is no + * manufacturer specific register, but that a standard PMBus register + * may exist. Any other negative return value indicates that the + * register does not exist, and that no attempt should be made to read + * the standard register. + */ + int (*read_byte_data)(struct i2c_client *client, int page, int reg); + int (*read_word_data)(struct i2c_client *client, int page, int reg); + int (*write_word_data)(struct i2c_client *client, int page, int reg, + u16 word); + int (*write_byte)(struct i2c_client *client, int page, u8 value); + /* + * The identify function determines supported PMBus functionality. + * This function is only necessary if a chip driver supports multiple + * chips, and the chip functionality is not pre-determined. + */ + int (*identify)(struct i2c_client *client, + struct pmbus_driver_info *info); +}; + +/* Function declarations */ + +void pmbus_clear_cache(struct i2c_client *client); +int pmbus_set_page(struct i2c_client *client, u8 page); +int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); +int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); +int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); +int pmbus_write_byte(struct i2c_client *client, int page, u8 value); +void pmbus_clear_faults(struct i2c_client *client); +bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); +bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); +int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info); +int pmbus_do_remove(struct i2c_client *client); +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client + *client); + +#endif /* PMBUS_H */ diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_cpld_qsfp28.c b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_cpld_qsfp28.c new file mode 100755 index 000000000000..15c5369fd219 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_cpld_qsfp28.c @@ -0,0 +1,409 @@ +/* + * A CPLD driver for monitor QSFP28 module I/O + * + * The CPLD is customize by Quanta for controlling QSFP28 module signals, + * they are RESET , INTERREPT , Module_Present, LPMODE + * Each CPLD control 16 modules, each module use 4 bits in register. + * + * Copyright (C) 2015 Quanta Inc. + * + * Author: Luffy Cheng + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDA(cpld_ida); + +enum platform_type { + QSFP28 = 0, + NONE +}; + +static struct class *cpld_class = NULL; + +struct sfp_data { + struct i2c_client *cpld_client; + char name[8]; + u8 port_id; + u8 cpld_port; +}; + +struct cpld_data { + struct mutex lock; + struct device *port_dev[16]; + struct sfp_data *port_data[16]; +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int cpld_remove(struct i2c_client *client); + +static const struct i2c_device_id cpld_id[] = { + { "CPLD-QSFP28", QSFP28 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qci_cpld_qsfp28", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, +// .address_list = normal_i2c, +}; + +#define CPLD_ID_PREFIX "port-" +#define CPLD_ID_FORMAT CPLD_ID_PREFIX "%d" + +#define RESET_MASK 0x08 +#define INTERRUPT_MASK 0x04 +#define MODULE_PRESENT_MASK 0x02 +#define LPMODE_MASK 0x01 + +static inline u8 get_group_cmd(u8 group) +{ + //FIXME: if group cmd change + return (group + 1); +} + +static inline u8 port_remapping(u8 phy_port) +{ + /* FIXME: implement by hardware design */ + /* The CPLD register port mapping is weird : + * MSB -------- LSB (word data) + * P3 P4 P1 P2 (per port 4 bits) + * For easy coding bit shift, we treat it as hw port swap + */ + return (phy_port % 2) ? (phy_port - 1) : (phy_port + 1); +} + +static ssize_t get_reset(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= RESET_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_interrupt(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= INTERRUPT_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_module_present(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= MODULE_PRESENT_MASK; + + //FIXME: if present is not low active + return sprintf(buf, "%d\n", value ? 0 : 1); +} + +static ssize_t get_lpmode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= LPMODE_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t set_reset(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + long disable; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + if (kstrtol(buf, 0, &disable)) + return -EINVAL; + + if ((disable != 1) && (disable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value &= ~(RESET_MASK << (group_port * 4)); + if (disable) + value |= (RESET_MASK << (group_port * 4)); + + dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value); + + i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value); +// mutex_unlock(&data->lock); + + return count; +} + +static ssize_t set_lpmode(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + long disable; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + if (kstrtol(buf, 0, &disable)) + return -EINVAL; + + if ((disable != 1) && (disable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value &= ~(LPMODE_MASK << (group_port * 4)); + if (disable) + value |= (LPMODE_MASK << (group_port * 4)); + + dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value); + + i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value); +// mutex_unlock(&data->lock); + + return count; +} + +static DEVICE_ATTR(reset, S_IWUSR | S_IRUGO, get_reset, set_reset); +static DEVICE_ATTR(lpmode, S_IWUSR | S_IRUGO, get_lpmode, set_lpmode); +static DEVICE_ATTR(module_present, S_IRUGO, get_module_present, NULL); +static DEVICE_ATTR(interrupt, S_IRUGO, get_interrupt, NULL); + +static const struct attribute *sfp_attrs[] = { + &dev_attr_reset.attr, + &dev_attr_lpmode.attr, + &dev_attr_module_present.attr, + &dev_attr_interrupt.attr, + NULL, +}; + +static const struct attribute_group sfp_attr_group = { + .attrs = (struct attribute **) sfp_attrs, +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cpld_data *data; + struct sfp_data *port_data; + struct device *port_dev; + int port_nr, i, err; + + if (!cpld_class) + { + cpld_class = class_create(THIS_MODULE, "cpld-qsfp28"); + if (IS_ERR(cpld_class)) { + pr_err("couldn't create sysfs class\n"); + return PTR_ERR(cpld_class); + } + } + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* register sfp port data to sysfs */ + for (i = 0; i < 16; i++) + { + port_nr = ida_simple_get(&cpld_ida, 1, 99, GFP_KERNEL); + if (port_nr < 0) + return ERR_PTR(port_nr); + + port_data = kzalloc(sizeof(struct sfp_data), GFP_KERNEL); + + port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), port_data, CPLD_ID_FORMAT, port_nr); + if (IS_ERR(port_dev)) { + err = PTR_ERR(port_dev); + // printk("err_status\n"); + } + + data->port_dev[i] = port_dev; + data->port_data[i] = port_data; + + dev_info(&client->dev, "Register qsfp28 port-%d\n", port_nr); + + /* FIXME: implement Logical/Physical port remapping */ + //port_data->cpld_port = i; + port_data->cpld_port = port_remapping(i); + sprintf(port_data->name, "port-%d", port_nr); + port_data->port_id = port_nr; + dev_set_drvdata(port_dev, port_data); + port_dev->init_name = port_data->name; + port_data->cpld_client = client; + + err = sysfs_create_group(&port_dev->kobj, &sfp_attr_group); + // if (status) printk("err status\n"); + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s device found\n", client->name); + + + return 0; + +//FIXME: implement error check +exit_remove: +// sysfs_remove_group(&client->dev.kobj, &data->attrs); + return err; +} + +/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */ +static int idr_has_entry(int id, void *p, void *data) +{ + return 1; +} + +static bool cpld_idr_is_empty(struct idr *idp) +{ + return !idr_for_each(idp, idr_has_entry, NULL); +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + int i, id; + + for (i = 15; i >= 0; i--) + { + dev_info(data->port_dev[i], "Remove qsfp28 port-%d\n", data->port_data[i]->port_id); + device_unregister(data->port_dev[i]); + ida_simple_remove(&cpld_ida, data->port_data[i]->port_id); + kfree(data->port_data[i]); + } + + if (cpld_idr_is_empty(&cpld_ida.idr)) + class_destroy(cpld_class); + + return 0; +} + +module_i2c_driver(cpld_driver); + +MODULE_AUTHOR("Luffy Cheng "); +MODULE_DESCRIPTION("Quanta Switch SFP CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_platform.h b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_platform.h new file mode 100755 index 000000000000..0737c8ce8170 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_platform.h @@ -0,0 +1,64 @@ +/* + * Driver model definations for Quanta Platform drivers + * + * Copyright (C) 2015-2016 Quanta QCT + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#ifndef __QCI_PLATFORM_H_INCLUDED +#define __QCI_PLATFORM_H_INCLUDED + +#define MUX_INFO(bus, deselect) \ + {.adap_id = bus, .deselect_on_exit = deselect} + +#define GPIO_INFO(id, gpio_nr) \ + {.gpio_id = id, .system_gpio_nr = gpio_nr} + +struct platform_gpio { + int gpio_id; + int system_gpio_nr; +}; + +/* FIXME: Please add important GPIO which need to be request */ +enum PLATFORM_GPIO_ID { + GPIO_PSU1_PRSNT, + GPIO_PSU1_PWRGD, + GPIO_PSU2_PRSNT, + GPIO_PSU2_PWRGD, +}; + +#define LED_ON LED_FULL + +#define LED_INFO(id) \ + {.led_id = id, .cdev = NULL} + +struct platform_led { + int led_id; + struct led_classdev *cdev; +}; + +enum PLATFORM_LED_ID { + SYSLED_AMBER, + SYSLED_GREEN, + FRONT_PSU1_GREEN, + FRONT_PSU1_RED, + FRONT_PSU2_GREEN, + FRONT_PSU2_RED, + FRONT_FAN_GREEN, + FRONT_FAN_RED, + REAR_FAN1_RED, + REAR_FAN2_RED, + REAR_FAN3_RED, + REAR_FAN4_RED, + REAR_FAN5_RED, + REAR_FAN6_RED, + TOTAL_LED_NR +}; + +extern int qci_platform_get_gpio(int platform_gpio); +extern int qci_platform_set_led(int led_id, bool led_on); + +#endif /* __QCI_PLATFORM_H_INCLUDED */ diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_platform_ix1b.c b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_platform_ix1b.c new file mode 100755 index 000000000000..f783c88fb9a1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_platform_ix1b.c @@ -0,0 +1,491 @@ +/* + * Quanta IX1B platform driver + * + * + * Copyright (C) 2014 Quanta Computer 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 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(3,12,0) +#include +#else +#include +#endif +#include "qci_platform.h" + +#define QUANTA_CPU_RGL + +static struct pca954x_platform_mode pca9548sfp1_modes[] = { + MUX_INFO(0x20, 1), + MUX_INFO(0x21, 1), + MUX_INFO(0x22, 1), + MUX_INFO(0x23, 1), + MUX_INFO(0x24, 1), + MUX_INFO(0x25, 1), + MUX_INFO(0x26, 1), + MUX_INFO(0x27, 1), +}; + +static struct pca954x_platform_data pca9548sfp1_data = { + .modes = pca9548sfp1_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp2_modes[] = { + MUX_INFO(0x28, 1), + MUX_INFO(0x29, 1), + MUX_INFO(0x2a, 1), + MUX_INFO(0x2b, 1), + MUX_INFO(0x2c, 1), + MUX_INFO(0x2d, 1), + MUX_INFO(0x2e, 1), + MUX_INFO(0x2f, 1), +}; + +static struct pca954x_platform_data pca9548sfp2_data = { + .modes = pca9548sfp2_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp3_modes[] = { + MUX_INFO(0x30, 1), + MUX_INFO(0x31, 1), + MUX_INFO(0x32, 1), + MUX_INFO(0x33, 1), + MUX_INFO(0x34, 1), + MUX_INFO(0x35, 1), + MUX_INFO(0x36, 1), + MUX_INFO(0x37, 1), +}; + +static struct pca954x_platform_data pca9548sfp3_data = { + .modes = pca9548sfp3_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp4_modes[] = { + MUX_INFO(0x38, 1), + MUX_INFO(0x39, 1), + MUX_INFO(0x3a, 1), + MUX_INFO(0x3b, 1), + MUX_INFO(0x3c, 1), + MUX_INFO(0x3d, 1), + MUX_INFO(0x3e, 1), + MUX_INFO(0x3f, 1), +}; + +static struct pca954x_platform_data pca9548sfp4_data = { + .modes = pca9548sfp4_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9546_1_modes[] = { + MUX_INFO(0x10, 1), + MUX_INFO(0x11, 1), + MUX_INFO(0x12, 1), + MUX_INFO(0x13, 1), +}; + +static struct pca954x_platform_data pca9546_1_data = { + .modes = pca9546_1_modes, + .num_modes = 4, +}; + +static struct pca954x_platform_mode pca9546_2_modes[] = { + MUX_INFO(0x14, 1), + MUX_INFO(0x15, 1), + MUX_INFO(0x16, 1), + MUX_INFO(0x17, 1), +}; + +static struct pca954x_platform_data pca9546_2_data = { + .modes = pca9546_2_modes, + .num_modes = 4, +}; + +/* CPU gpio base defined in devicetree + * default is ARCH_NR_GPIOS - 32, (256-32=224) + * It must match devicetree default gpio base + * */ +#define PCA9555_PSU_GPIO_BASE 0x10 +#define PCA9555_FAN_GPIO_BASE 0x20 +#define PCA9555_ID_GPIO_BASE 0x30 + +#if defined(QUANTA_CPU_RGL) +#define PCA9555_CPU_LED_GPIO_BASE 0x80 + +static struct pca954x_platform_mode pca9546_cpu1_modes[] = { + MUX_INFO(0x18, 1), + MUX_INFO(0x19, 1), + MUX_INFO(0x1a, 1), + MUX_INFO(0x1b, 1), +}; + +static struct pca954x_platform_data pca9546_cpu1_data = { + .modes = pca9546_cpu1_modes, + .num_modes = 4, +}; + +static struct pca953x_platform_data pca9555_cpuled_data = { + .gpio_base = PCA9555_CPU_LED_GPIO_BASE, +}; +#endif + +static struct pca953x_platform_data pca9555psu1_data = { + .gpio_base = PCA9555_PSU_GPIO_BASE, +}; + +static struct pca953x_platform_data pca9555fan_data = { + .gpio_base = PCA9555_FAN_GPIO_BASE, +}; + +static struct pca953x_platform_data pca9555ID_data = { + .gpio_base = PCA9555_ID_GPIO_BASE, +}; + +static struct i2c_board_info ix1b_i2c_devices[] = { + { + I2C_BOARD_INFO("pca9546", 0x77), + .platform_data = &pca9546_1_data, + }, + { + I2C_BOARD_INFO("pca9546", 0x72), + .platform_data = &pca9546_2_data, + }, + { + I2C_BOARD_INFO("pca9555", 0x26), + .platform_data = &pca9555psu1_data, + }, + { + I2C_BOARD_INFO("24c02", 0x54), + }, + { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &pca9548sfp1_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x74), + .platform_data = &pca9548sfp2_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x75), + .platform_data = &pca9548sfp3_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x76), + .platform_data = &pca9548sfp4_data, + }, + { + I2C_BOARD_INFO("CPLD-QSFP28", 0x38), + }, + { + I2C_BOARD_INFO("CPLD-QSFP28", 0x39), + }, + { + I2C_BOARD_INFO("pca9555", 0x23), + .platform_data = &pca9555ID_data, + }, + { + I2C_BOARD_INFO("pca9555", 0x25), + .platform_data = &pca9555fan_data, + }, + { + I2C_BOARD_INFO("qci_pmbus_ix1b", 0x5f), + }, + { + I2C_BOARD_INFO("qci_pmbus_ix1b", 0x59), + }, +#if defined(QUANTA_CPU_RGL) + { + I2C_BOARD_INFO("pca9546", 0x71), + .platform_data = &pca9546_cpu1_data, + }, + { + I2C_BOARD_INFO("pca9555", 0x20), + .platform_data = &pca9555_cpuled_data, + }, + { + I2C_BOARD_INFO("24c02", 0x50), + }, +#endif +}; + +static struct platform_driver ix1b_platform_driver = { + .driver = { + .name = "qci-ix1b", + .owner = THIS_MODULE, + }, +}; + +static struct platform_led ix1b_leds[] = { +#if defined(QUANTA_CPU_RGL) + LED_INFO(SYSLED_AMBER), + LED_INFO(SYSLED_GREEN), +#endif + LED_INFO(FRONT_PSU1_GREEN), + LED_INFO(FRONT_PSU1_RED), + LED_INFO(FRONT_PSU2_GREEN), + LED_INFO(FRONT_PSU2_RED), + LED_INFO(FRONT_FAN_GREEN), + LED_INFO(FRONT_FAN_RED), + LED_INFO(REAR_FAN1_RED), + LED_INFO(REAR_FAN2_RED), + LED_INFO(REAR_FAN3_RED), + LED_INFO(REAR_FAN4_RED), +}; + +static struct gpio_led system_led[] = { +#if defined(QUANTA_CPU_RGL) + { + .name = "sysled_amber", + .default_trigger = "timer", + .gpio = (PCA9555_CPU_LED_GPIO_BASE + 10), + .active_low = 0, + }, + { + .name = "sysled_green", + .gpio = (PCA9555_CPU_LED_GPIO_BASE + 11), + .active_low = 0, + }, +#endif + { + .name = "front_led_psu1_green", + .gpio = (PCA9555_PSU_GPIO_BASE + 10), + .active_low = 0, + }, + { + .name = "front_led_psu1_red", + .gpio = (PCA9555_PSU_GPIO_BASE + 11), + .active_low = 0, + }, + { + .name = "front_led_psu2_green", + .gpio = (PCA9555_PSU_GPIO_BASE + 12), + .active_low = 0, + }, + { + .name = "front_led_psu2_red", + .gpio = (PCA9555_PSU_GPIO_BASE + 13), + .active_low = 0, + }, + { + .name = "front_led_fan_green", + .gpio = (PCA9555_PSU_GPIO_BASE + 14), + .active_low = 0, + }, + { + .name = "front_led_fan_red", + .gpio = (PCA9555_PSU_GPIO_BASE + 15), + .active_low = 0, + }, + { + .name = "rear_led_fan1_red", + .gpio = (PCA9555_FAN_GPIO_BASE + 12), + .active_low = 0, + }, + { + .name = "rear_led_fan2_red", + .gpio = (PCA9555_FAN_GPIO_BASE + 13), + .active_low = 0, + }, + { + .name = "rear_led_fan3_red", + .gpio = (PCA9555_FAN_GPIO_BASE + 14), + .active_low = 0, + }, + { + .name = "rear_led_fan4_red", + .gpio = (PCA9555_FAN_GPIO_BASE + 15), + .active_low = 0, + }, +}; + +static struct gpio_led_platform_data system_led_data = { + .num_leds = ARRAY_SIZE(system_led), + .leds = system_led +}; + +static struct platform_device system_led_dev = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &system_led_data, + }, +}; + +static struct platform_device *ix1b_device; + +struct gpio_led_data { + struct led_classdev cdev; + unsigned gpio; + struct work_struct work; + u8 new_level; + u8 can_sleep; + u8 active_low; + u8 blinking; + int (*platform_gpio_blink_set)(unsigned gpio, int state, + unsigned long *delay_on, unsigned long *delay_off); +}; + +struct gpio_leds_priv { + int num_leds; + struct gpio_led_data leds[]; +}; + +static int __init ix1b_platform_init(void) +{ + struct i2c_client *client; + struct i2c_adapter *adapter; + struct gpio_leds_priv *priv; + int i; + int ret; + + ret = platform_driver_register(&ix1b_platform_driver); + if (ret < 0) + return ret; + + /* Register platform stuff */ + ix1b_device = platform_device_alloc("qci-ix1b", -1); + if (!ix1b_device) { + ret = -ENOMEM; + goto fail_platform_driver; + } + + ret = platform_device_add(ix1b_device); + if (ret) + goto fail_platform_device; + + adapter = i2c_get_adapter(0); + client = i2c_new_device(adapter, &ix1b_i2c_devices[0]); // pca9546_1 + printk("[CC] NEW device pca9546_1\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[1]); // pca9546_2 + printk("[CC] NEW device pca9546_2\n"); +#if defined(QUANTA_CPU_RGL) + client = i2c_new_device(adapter, &ix1b_i2c_devices[14]); // cpu pca9546_1 + printk("[CC] NEW device cpu pca9546_1\n"); +#endif + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x14); + client = i2c_new_device(adapter, &ix1b_i2c_devices[12]); // pmbus_psu1 + printk("[CC] NEW device pmbus_psu1\n"); + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x15); + client = i2c_new_device(adapter, &ix1b_i2c_devices[13]); // pmbus_psu2 + printk("[CC] NEW device pmbus_psu2\n"); + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x16); + client = i2c_new_device(adapter, &ix1b_i2c_devices[2]); // pca9555-PSU1 + printk("[CC] NEW device pca9555-PSU1\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[3]); // MB_BOARDINFO_EEPROM + printk("[CC] NEW device MB_BOARDINFO_EEPROM\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[10]); // pca9555-ID + printk("[CC] NEW device pca9555-ID\n"); + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x17); + client = i2c_new_device(adapter, &ix1b_i2c_devices[11]); // pca9555-fan + printk("[CC] NEW device pca9555-fan\n"); + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x10); + client = i2c_new_device(adapter, &ix1b_i2c_devices[4]); // pca9548_2 SFP + printk("[CC] NEW device pca9548_2 SFP\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[5]); // pca9548_3 SFP + printk("[CC] NEW device pca9548_3 SFP\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[6]); // pca9548_4 SFP + printk("[CC] NEW device pca9548_4 SFP\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[8]); // CPLD2 + printk("[CC] NEW device CPLD2\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[9]); // CPLD3 + printk("[CC] NEW device CPLD3\n"); + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x11); + client = i2c_new_device(adapter, &ix1b_i2c_devices[7]); // pca9548_5 SFP + printk("[CC] NEW device pca9548_5 SFP\n"); + i2c_put_adapter(adapter); + +#if defined(QUANTA_CPU_RGL) + adapter = i2c_get_adapter(0x18); + client = i2c_new_device(adapter, &ix1b_i2c_devices[15]); // cpu pca9555_1 + printk("[CC] NEW device cpu pca9555_1\n"); + i2c_put_adapter(adapter); + + for(i = 0x20; i < 0x40; i++) + { + adapter = i2c_get_adapter(i); + client = i2c_new_device(adapter, &ix1b_i2c_devices[16]); // eeprom for loopback module + i2c_put_adapter(adapter); + } + printk("[CC] NEW device eeprom\n"); +#endif + + /* Register LED devices */ + platform_device_register(&system_led_dev); + priv = platform_get_drvdata(&system_led_dev); + for (i = 0; i < priv->num_leds; i++) { + printk("leds-gpio gpio-%d: Register led %s\n", priv->leds[i].gpio, priv->leds[i].cdev.name); + ix1b_leds[i].cdev = &(priv->leds[i].cdev); + } + printk("[CC] NEW device led\n"); + + return 0; + +fail_platform_device: + platform_device_put(ix1b_device); + +fail_platform_driver: + platform_driver_unregister(&ix1b_platform_driver); + return ret; +} + +static void __exit ix1b_platform_exit(void) +{ + platform_device_unregister(ix1b_device); + platform_driver_unregister(&ix1b_platform_driver); +} + +module_init(ix1b_platform_init); +module_exit(ix1b_platform_exit); + + +MODULE_AUTHOR("Quanta Computer Inc."); +MODULE_DESCRIPTION("Quanta IX1B Platform Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_pmbus.c b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_pmbus.c new file mode 100755 index 000000000000..f54a0f204d67 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_pmbus.c @@ -0,0 +1,487 @@ +/* + * QUANTA Generic PMBUS driver + * + * + * Based on generic pmbus driver and ltc2978 driver + * + * Author: Chih-Pei Chang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +//#include <../drivers/hwmon/pmbus/pmbus.h> +#include "pmbus.h" +#include + +enum projects { ly8, ix1, ix2, ix1b }; + +#define DELAY_TIME 1000 /* uS */ + +/* Needed to access the mutex. Copied from pmbus_core.c */ +#define PB_STATUS_BASE 0 +#define PB_STATUS_VOUT_BASE (PB_STATUS_BASE + PMBUS_PAGES) +#define PB_STATUS_IOUT_BASE (PB_STATUS_VOUT_BASE + PMBUS_PAGES) +#define PB_STATUS_FAN_BASE (PB_STATUS_IOUT_BASE + PMBUS_PAGES) +#define PB_STATUS_FAN34_BASE (PB_STATUS_FAN_BASE + PMBUS_PAGES) +#define PB_STATUS_TEMP_BASE (PB_STATUS_FAN34_BASE + PMBUS_PAGES) +#define PB_STATUS_INPUT_BASE (PB_STATUS_TEMP_BASE + PMBUS_PAGES) +#define PB_STATUS_VMON_BASE (PB_STATUS_INPUT_BASE + 1) +#define PB_NUM_STATUS_REG (PB_STATUS_VMON_BASE + 1) +struct pmbus_data { + struct device *dev; + struct device *hwmon_dev; + + u32 flags; /* from platform data */ + + int exponent[PMBUS_PAGES]; + /* linear mode: exponent for output voltages */ + + const struct pmbus_driver_info *info; + + int max_attributes; + int num_attributes; + struct attribute_group group; + const struct attribute_group *groups[2]; + + struct pmbus_sensor *sensors; + + struct mutex update_lock; + bool valid; + unsigned long last_updated; /* in jiffies */ + + /* + * A single status register covers multiple attributes, + * so we keep them all together. + */ + u8 status[PB_NUM_STATUS_REG]; + u8 status_register; + + u8 currpage; +}; + +static int qci_pmbus_read_block(struct i2c_client *client, u8 command, int data_len, u8 *data) +{ + int result = 0; + int retry_count = 3; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (result < 0) { + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static ssize_t qci_pmbus_show_mfr_id(struct device *dev, + struct device_attribute *da, char *buf) +{ + int ret, len; + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1], *str; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + ret = qci_pmbus_read_block(client, PMBUS_MFR_ID, I2C_SMBUS_BLOCK_MAX, block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read Manufacturer ID\n"); + return ret; + } + len = block_buffer[0]; + block_buffer[(len+1)] = '\0'; + str = &(block_buffer[1]); + + return snprintf(buf, PAGE_SIZE, "%s\n", str); +} + +static ssize_t qci_pmbus_show_mfr_model(struct device *dev, + struct device_attribute *da, char *buf) +{ + int ret, len; + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1], *str; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + ret = qci_pmbus_read_block(client, PMBUS_MFR_MODEL, I2C_SMBUS_BLOCK_MAX, block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read Manufacturer Model\n"); + return ret; + } + len = block_buffer[0]; + block_buffer[(len+1)] = '\0'; + str = &(block_buffer[1]); + + return snprintf(buf, PAGE_SIZE, "%s\n", str); +} + +static ssize_t qci_pmbus_show_mfr_revision(struct device *dev, + struct device_attribute *da, char *buf) +{ + int ret, len; + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1], *str; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + ret = qci_pmbus_read_block(client, PMBUS_MFR_REVISION, I2C_SMBUS_BLOCK_MAX, block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read Manufacturer Revision\n"); + return ret; + } + len = block_buffer[0]; + block_buffer[(len+1)] = '\0'; + str = &(block_buffer[1]); + + return snprintf(buf, PAGE_SIZE, "%s\n", str); +} + +static ssize_t qci_pmbus_show_mfr_location(struct device *dev, + struct device_attribute *da, char *buf) +{ + int ret, len; + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1], *str; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + ret = qci_pmbus_read_block(client, PMBUS_MFR_LOCATION, I2C_SMBUS_BLOCK_MAX, block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read Manufacture Location\n"); + return ret; + } + len = block_buffer[0]; + block_buffer[(len+1)] = '\0'; + str = &(block_buffer[1]); + + return snprintf(buf, PAGE_SIZE, "%s\n", str); +} + +static ssize_t qci_pmbus_show_mfr_serial(struct device *dev, + struct device_attribute *da, char *buf) +{ + int ret, len; + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1], *str; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + ret = qci_pmbus_read_block(client, PMBUS_MFR_SERIAL, I2C_SMBUS_BLOCK_MAX, block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read Manufacturer Serial\n"); + return ret; + } + len = block_buffer[0]; + block_buffer[(len+1)] = '\0'; + str = &(block_buffer[1]); + + return snprintf(buf, PAGE_SIZE, "%s\n", str); +} + + +static DEVICE_ATTR(mfr_id, S_IRUGO, qci_pmbus_show_mfr_id, NULL); +static DEVICE_ATTR(mfr_model, S_IRUGO, qci_pmbus_show_mfr_model, NULL); +static DEVICE_ATTR(mfr_revision, S_IRUGO, qci_pmbus_show_mfr_revision, NULL); +static DEVICE_ATTR(mfr_location, S_IRUGO, qci_pmbus_show_mfr_location, NULL); +static DEVICE_ATTR(mfr_serial, S_IRUGO, qci_pmbus_show_mfr_serial, NULL); + + +static struct attribute *qci_pmbus_inventory_attrs[] = { + &dev_attr_mfr_id.attr, + &dev_attr_mfr_model.attr, + &dev_attr_mfr_revision.attr, + &dev_attr_mfr_location.attr, + &dev_attr_mfr_serial.attr, + NULL +}; + +static struct attribute_group qci_pmbus_inventory_attr_grp = { + .attrs = qci_pmbus_inventory_attrs +}; + +/* FIXME: add project specific id here */ +static const struct i2c_device_id qci_pmbus_id[] = { + {"qci_pmbus_ly8", ly8}, + {"qci_pmbus_ix1", ix1}, + {"qci_pmbus_ix2", ix2}, + {"qci_pmbus_ix1b", ix1b}, + {} +}; +MODULE_DEVICE_TABLE(i2c, qci_pmbus_id); + +/* + * Find sensor groups and status registers on each page. + */ +static void qci_pmbus_find_sensor_groups(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int page; + + /* Sensors detected on page 0 only */ + if (pmbus_check_word_register(client, 0, PMBUS_READ_VIN)) + info->func[0] |= PMBUS_HAVE_VIN; + if (pmbus_check_word_register(client, 0, PMBUS_READ_VCAP)) + info->func[0] |= PMBUS_HAVE_VCAP; + if (pmbus_check_word_register(client, 0, PMBUS_READ_IIN)) + info->func[0] |= PMBUS_HAVE_IIN; + if (pmbus_check_word_register(client, 0, PMBUS_READ_PIN)) + info->func[0] |= PMBUS_HAVE_PIN; + if (info->func[0] + && pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT)) + info->func[0] |= PMBUS_HAVE_STATUS_INPUT; + if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) && + pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) { + info->func[0] |= PMBUS_HAVE_FAN12; + if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN12; + } + if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) && + pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) { + info->func[0] |= PMBUS_HAVE_FAN34; + if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN34; + } + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) + info->func[0] |= PMBUS_HAVE_TEMP; + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2)) + info->func[0] |= PMBUS_HAVE_TEMP2; + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3)) + info->func[0] |= PMBUS_HAVE_TEMP3; + if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 + | PMBUS_HAVE_TEMP3) + && pmbus_check_byte_register(client, 0, + PMBUS_STATUS_TEMPERATURE)) + info->func[0] |= PMBUS_HAVE_STATUS_TEMP; + + /* Sensors detected on all pages */ + for (page = 0; page < info->pages; page++) { + if (pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) { + info->func[page] |= PMBUS_HAVE_VOUT; + if (pmbus_check_byte_register(client, page, + PMBUS_STATUS_VOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_VOUT; + } + if (pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) { + info->func[page] |= PMBUS_HAVE_IOUT; + if (pmbus_check_byte_register(client, 0, + PMBUS_STATUS_IOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_IOUT; + } + if (pmbus_check_word_register(client, page, PMBUS_READ_POUT)) + info->func[page] |= PMBUS_HAVE_POUT; + } +} + +/* + * Identify chip parameters. + */ +static int qci_pmbus_identify(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int ret = 0; + + if (!info->pages) { + /* + * Check if the PAGE command is supported. If it is, + * keep setting the page number until it fails or until the + * maximum number of pages has been reached. Assume that + * this is the number of pages supported by the chip. + */ + if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) { + int page; + + for (page = 1; page < PMBUS_PAGES; page++) { + if (pmbus_set_page(client, page) < 0) + break; + } + pmbus_set_page(client, 0); + info->pages = page; + } else { + info->pages = 1; + } + } + + if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) { + int vout_mode; + + vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); + if (vout_mode >= 0 && vout_mode != 0xff) { + switch (vout_mode >> 5) { + case 0: + break; + case 1: + info->format[PSC_VOLTAGE_OUT] = vid; + break; + case 2: + info->format[PSC_VOLTAGE_OUT] = direct; + break; + default: + ret = -ENODEV; + goto abort; + } + } + } + + /* + * We should check if the COEFFICIENTS register is supported. + * If it is, and the chip is configured for direct mode, we can read + * the coefficients from the chip, one set per group of sensor + * registers. + * + * To do this, we will need access to a chip which actually supports the + * COEFFICIENTS command, since the command is too complex to implement + * without testing it. Until then, abort if a chip configured for direct + * mode was detected. + */ + if (info->format[PSC_VOLTAGE_OUT] == direct) { + ret = -ENODEV; + goto abort; + } + + /* if no function pre-defined, try to find sensor groups */ + if (info->func[0] == 0) qci_pmbus_find_sensor_groups(client, info); +abort: + return ret; +} + +int qci_pmbus_set_page(struct i2c_client *client, u8 page) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int rv = 0; + int newpage; + + if (page != data->currpage) { + rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); + udelay(DELAY_TIME); + newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); + if (newpage != page) + rv = -EIO; + else + data->currpage = page; + } + return rv; +} + +int qci_write_byte(struct i2c_client *client, int page, u8 value) +{ + int rv; + + if (page >= 0) { + rv = qci_pmbus_set_page(client, page); + if (rv < 0) + return rv; + } + + rv = i2c_smbus_write_byte(client, value); + udelay(DELAY_TIME); + return rv; +} + +int qci_write_word_data(struct i2c_client *client, int page, int reg, u16 word) +{ + int rv; + + rv = qci_pmbus_set_page(client, page); + if (rv < 0) + return rv; + + rv = i2c_smbus_write_word_data(client, reg, word); + udelay(DELAY_TIME); + return rv; +} + +static int qci_pmbus_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct pmbus_driver_info *info; + int ret, i; + + dev_info(dev, "qci_pmbus_probe\n"); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) + return -ENODEV; + + info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), + GFP_KERNEL); + + if (!info) + return -ENOMEM; + + info->func[0] = 0; + + /* FIXME: add project specific function table here */ + switch (id->driver_data) { + case ly8: + info->pages = 1; + info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT + | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 + | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT + | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT + ; + break; + case ix1: + case ix2: + case ix1b: + info->pages = 1; + info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN + | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT + | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 + | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 + | PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP + | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT + | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT + | PMBUS_HAVE_POUT + ; + break; + default: + break; + } + info->write_word_data = qci_write_word_data; + info->write_byte = qci_write_byte; + info->identify = qci_pmbus_identify; /* FIXME: reserve for future use */ + + /* Register sysfs hooks */ + ret = sysfs_create_group(&dev->kobj, &qci_pmbus_inventory_attr_grp); + if (ret) { + dev_err(dev, "Failed to create sysfs entries\n"); + return -1; + } + + return pmbus_do_probe(client, id, info); +} + +/* This is the driver that will be inserted */ +static struct i2c_driver qci_pmbus_driver = { + .driver = { + .name = "qci-pmbus", + }, + .probe = qci_pmbus_probe, + .remove = pmbus_do_remove, + .id_table = qci_pmbus_id, +}; + +module_i2c_driver(qci_pmbus_driver); + + +MODULE_AUTHOR("Quanta Computer Inc."); +MODULE_VERSION("1.0"); +MODULE_DESCRIPTION("QUANTA generic PMBus driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/service/ix1b-platform-init.service b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/service/ix1b-platform-init.service new file mode 100755 index 000000000000..a51c0cca6914 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/service/ix1b-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Quanta IX1B-32X Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/quanta_ix1b_util.py install +ExecStop=/usr/local/bin/quanta_ix1b_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/setup.py b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/setup.py new file mode 100755 index 000000000000..e37687db7eca --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='ix1b_32x', + version='1.0', + description='Module to initialize Quanta IX1B-32X platforms', + + packages=['ix1b_32x'], + package_dir={'ix1b_32x': 'ix1b-32x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/utils/quanta_ix1b_util.py b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/utils/quanta_ix1b_util.py new file mode 100755 index 000000000000..f530cf3dbb7b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/utils/quanta_ix1b_util.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Quanta Computer 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 "[IX1B-32X]"+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 =[ +#turn on module power +'echo 53 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio53/direction', +'echo 1 >/sys/class/gpio/gpio53/value', +#turn on 100G led by default +'i2cset -y 0x13 0x38 0x00 0xff', +'i2cset -y 0x13 0x38 0x01 0xff', +'i2cset -y 0x13 0x39 0x00 0xff', +'i2cset -y 0x13 0x39 0x01 0xff' +] + +drivers =[ +'lpc_ich', +'i2c-i801', +'i2c-dev', +'i2c-mux-pca954x', +'gpio-pca953x', +'qci_pmbus', +'leds-gpio', +'qci_cpld_qsfp28', +'qci_platform_ix1b' +] + + + +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) + #setup driver dependency + status, output = exec_cmd("depmod -a ", 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 + + 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 " ix1b driver already installed...." + 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+"i2c-0", 0) + return ret1 + +if __name__ == "__main__": + main() + + + diff --git a/platform/broadcom/sonic-platform-modules-s6000/.gitignore b/platform/broadcom/sonic-platform-modules-s6000/.gitignore new file mode 100644 index 000000000000..7f287d538227 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/.gitignore @@ -0,0 +1,50 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-s6000/LICENSE b/platform/broadcom/sonic-platform-modules-s6000/LICENSE new file mode 100644 index 000000000000..676cdeec726b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, 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 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-s6000/MAINTAINERS b/platform/broadcom/sonic-platform-modules-s6000/MAINTAINERS new file mode 100644 index 000000000000..65e3129fcc13 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/MAINTAINERS @@ -0,0 +1,7 @@ +# This file describes the maintainers for sonic-platform-modules-s6000 +# See the SONiC project governance document for more information + +Name = "Shuotian Cheng" +Email = "shuche@microsoft.com" +Github = stcheng +Mailinglist = sonicproject@googlegroups.com diff --git a/platform/broadcom/sonic-platform-modules-s6000/README.md b/platform/broadcom/sonic-platform-modules-s6000/README.md new file mode 100644 index 000000000000..7913d168a30a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-s6000 +Device drivers for support of Dell S6000 for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-s6000/debian/changelog b/platform/broadcom/sonic-platform-modules-s6000/debian/changelog new file mode 100644 index 000000000000..0a6b7820bdeb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/debian/changelog @@ -0,0 +1,5 @@ +platform-modules-s6000 (1.0) unstable; urgency=low + + * Initial release + + -- Shuotian Cheng Mon, 11 Nov 2015 11:11:11 -0800 diff --git a/platform/broadcom/sonic-platform-modules-s6000/debian/compat b/platform/broadcom/sonic-platform-modules-s6000/debian/compat new file mode 100644 index 000000000000..45a4fb75db86 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/broadcom/sonic-platform-modules-s6000/debian/control b/platform/broadcom/sonic-platform-modules-s6000/debian/control new file mode 100644 index 000000000000..eb91ec6718f3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/debian/control @@ -0,0 +1,12 @@ +Source: platform-modules-s6000 +Section: main +Priority: extra +Maintainer: Shuotian Cheng +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-s6000 +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-s6000/debian/copyright b/platform/broadcom/sonic-platform-modules-s6000/debian/copyright new file mode 100644 index 000000000000..6fbc5a7f6ca0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/debian/copyright @@ -0,0 +1,16 @@ +Provides linux sysfs interface to Dell S6000 platform hardware peripherals +Copyright (C) 2016 Microsoft + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-s6000/debian/platform-modules-s6000.init b/platform/broadcom/sonic-platform-modules-s6000/debian/platform-modules-s6000.init new file mode 100755 index 000000000000..f16f7e01ef6e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/debian/platform-modules-s6000.init @@ -0,0 +1,99 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S6000 board. +### END INIT INFO + +add_i2c_devices() { + + echo 24c02 0x50 > /sys/class/i2c-adapter/i2c-1/new_device + echo 24c02 0x51 > /sys/class/i2c-adapter/i2c-1/new_device + echo dni_dps460 0x58 > /sys/class/i2c-adapter/i2c-1/new_device + echo dni_dps460 0x59 > /sys/class/i2c-adapter/i2c-1/new_device + echo jc42 0x18 > /sys/class/i2c-adapter/i2c-10/new_device + echo emc1403 0x4d > /sys/class/i2c-adapter/i2c-10/new_device + echo spd 0x50 > /sys/class/i2c-adapter/i2c-10/new_device + echo 24c02 0x53 > /sys/class/i2c-adapter/i2c-10/new_device + echo max6620 0x29 > /sys/class/i2c-adapter/i2c-11/new_device + echo max6620 0x2a > /sys/class/i2c-adapter/i2c-11/new_device + echo ltc4215 0x40 > /sys/class/i2c-adapter/i2c-11/new_device + echo ltc4215 0x42 > /sys/class/i2c-adapter/i2c-11/new_device + echo tmp75 0x4c > /sys/class/i2c-adapter/i2c-11/new_device + echo tmp75 0x4d > /sys/class/i2c-adapter/i2c-11/new_device + echo tmp75 0x4e > /sys/class/i2c-adapter/i2c-11/new_device + echo 24c02 0x51 > /sys/class/i2c-adapter/i2c-11/new_device + echo 24c02 0x52 > /sys/class/i2c-adapter/i2c-11/new_device + echo 24c02 0x53 > /sys/class/i2c-adapter/i2c-11/new_device + for i in `seq 0 31`; do + echo sff8436 0x50 > /sys/class/i2c-adapter/i2c-$((20+i))/new_device + done +} + +remove_i2c_devices() { + echo 0x50 > /sys/class/i2c-adapter/i2c-1/delete_device + echo 0x51 > /sys/class/i2c-adapter/i2c-1/delete_device + echo 0x58 > /sys/class/i2c-adapter/i2c-1/delete_device + echo 0x59 > /sys/class/i2c-adapter/i2c-1/delete_device + echo 0x18 > /sys/class/i2c-adapter/i2c-10/delete_device + echo 0x4d > /sys/class/i2c-adapter/i2c-10/delete_device + echo 0x50 > /sys/class/i2c-adapter/i2c-10/delete_device + echo 0x53 > /sys/class/i2c-adapter/i2c-10/delete_device + echo 0x29 > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x2a > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x40 > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x42 > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x4c > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x4d > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x4e > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x51 > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x52 > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x53 > /sys/class/i2c-adapter/i2c-11/delete_device + for i in `seq 0 31`; do + echo 0x50 > /sys/class/i2c-adapter/i2c-$((20+i))/delete_device + done +} + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + modprobe i2c_mux_gpio + modprobe dell_s6000_platform + + add_i2c_devices + + /usr/local/bin/set-fan-speed 15000 + /usr/local/bin/reset-qsfp + + echo "done." + ;; + +stop) + echo "done." + + remove_i2c_devices + + rmmod dell_s6000_platform + rmmod i2c_mux_gpio + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-s6000.init {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/broadcom/sonic-platform-modules-s6000/debian/platform-modules-s6000.install b/platform/broadcom/sonic-platform-modules-s6000/debian/platform-modules-s6000.install new file mode 100644 index 000000000000..a059f39ff3c4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/debian/platform-modules-s6000.install @@ -0,0 +1 @@ +systemd/platform-modules-s6000.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-s6000/debian/rules b/platform/broadcom/sonic-platform-modules-s6000/debian/rules new file mode 100755 index 000000000000..5473743ea38d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/debian/rules @@ -0,0 +1,32 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_NAME := platform-modules-s6000 +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MODULE_SRC := $(shell pwd)/modules +SCRIPT_SRC := $(shell pwd)/scripts + +%: + dh $@ --with=systemd + +override_dh_auto_build: + make -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + +override_dh_auto_install: + dh_installdirs -p$(PACKAGE_NAME) $(KERNEL_SRC)/$(INSTALL_MOD_DIR) + cp $(MODULE_SRC)/*.ko debian/$(PACKAGE_NAME)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) + dh_installdirs -p$(PACKAGE_NAME) usr/local/bin + cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_NAME)/usr/local/bin + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + rm -f $(MODULE_SRC)/*.o $(MODULE_SRC)/*.ko $(MODULE_SRC)/*.mod.c $(MODULE_SRC)/.*.cmd + rm -f $(MODULE_SRC)/Module.markers $(MODULE_SRC)/Module.symvers $(MODULE_SRC)/modules.order + rm -rf $(MODULE_SRC)/.tmp_versions + diff --git a/platform/broadcom/sonic-platform-modules-s6000/modules/Makefile b/platform/broadcom/sonic-platform-modules-s6000/modules/Makefile new file mode 100644 index 000000000000..12e80d01010c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/modules/Makefile @@ -0,0 +1 @@ +obj-m := dell_s6000_platform.o diff --git a/platform/broadcom/sonic-platform-modules-s6000/modules/dell_s6000_platform.c b/platform/broadcom/sonic-platform-modules-s6000/modules/dell_s6000_platform.c new file mode 100644 index 000000000000..cbd56c579dd2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/modules/dell_s6000_platform.c @@ -0,0 +1,1222 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define S6000_MUX_BASE_NR 10 +#define QSFP_MODULE_BASE_NR 20 + +/* 74CBTLV3253 Dual 1-of-4 multiplexer/demultiplexer */ +#define MUX_CHANNEL_NUM 2 + +#define CPLD_DEVICE_NUM 3 +#define QSFP_MODULE_NUM 16 +#define QSFP_DEVICE_NUM 2 + + +static void device_release(struct device *dev) +{ + return; +} + +/* + * S6000 74CBTLV3253 MUX + */ +static const unsigned s6000_mux_gpios[] = { + 1, 2 +}; + +static const unsigned s6000_mux_values[] = { + 0, 1, 2, 3 +}; + +static struct i2c_mux_gpio_platform_data s6000_mux_platform_data = { + .parent = 2, + .base_nr = S6000_MUX_BASE_NR, + .values = s6000_mux_values, + .n_values = ARRAY_SIZE(s6000_mux_values), + .gpios = s6000_mux_gpios, + .n_gpios = ARRAY_SIZE(s6000_mux_gpios), + .idle = 0, +}; + +static struct platform_device s6000_mux = { + .name = "i2c-mux-gpio", + .id = 0, + .dev = { + .platform_data = &s6000_mux_platform_data, + .release = device_release + }, +}; + +/* + * S6000 CPLD + */ + +enum cpld_type { + system_cpld, + master_cpld, + slave_cpld, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +static struct cpld_platform_data s6000_cpld_platform_data[] = { + [system_cpld] = { + .reg_addr = 0x31, + }, + + [master_cpld] = { + .reg_addr = 0x32, + }, + + [slave_cpld] = { + .reg_addr = 0x33, + }, +}; + +static struct platform_device s6000_cpld = { + .name = "dell-s6000-cpld", + .id = 0, + .dev = { + .platform_data = s6000_cpld_platform_data, + .release = device_release + }, +}; + +/* + * S6000 QSFP MUX + */ + +struct qsfp_mux_platform_data { + int parent; + int base_nr; + int reg_addr; + struct i2c_client *cpld; +}; + +struct qsfp_mux { + struct qsfp_mux_platform_data data; +}; + +static struct qsfp_mux_platform_data s6000_qsfp_mux_platform_data[] = { + { + .parent = S6000_MUX_BASE_NR + 2, + .base_nr = QSFP_MODULE_BASE_NR, + .cpld = NULL, + .reg_addr = 0x0, + }, + { + .parent = S6000_MUX_BASE_NR + 3, + .base_nr = QSFP_MODULE_BASE_NR + QSFP_MODULE_NUM, + .cpld = NULL, + .reg_addr = 0xa, + }, +}; + +static struct platform_device s6000_qsfp_mux[] = { + { + .name = "dell-s6000-qsfp-mux", + .id = 0, + .dev = { + .platform_data = &s6000_qsfp_mux_platform_data[0], + .release = device_release, + }, + }, + { + .name = "dell-s6000-qsfp-mux", + .id = 1, + .dev = { + .platform_data = &s6000_qsfp_mux_platform_data[1], + .release = device_release, + }, + }, +}; + +static int cpld_reg_write_byte(struct i2c_client *client, u8 regaddr, u8 val) +{ + union i2c_smbus_data data; + + data.byte = val; + return client->adapter->algo->smbus_xfer(client->adapter, client->addr, + client->flags, + I2C_SMBUS_WRITE, + regaddr, I2C_SMBUS_BYTE_DATA, &data); +} + +static int qsfp_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct qsfp_mux *mux = i2c_mux_priv(muxc); + unsigned short mask = ~(unsigned short)(1 << chan); + + cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(mask & 0xff)); + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr + 1, (u8)(mask >> 8)); +} + +static int __init qsfp_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct qsfp_mux *mux; + struct qsfp_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); + if (!mux) { + return -ENOMEM; + } + + mux->data = *pdata; + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -EPROBE_DEFER; + } + + muxc = i2c_mux_alloc(parent, &pdev->dev, QSFP_MODULE_NUM, 0, 0, + qsfp_mux_select, NULL); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = mux; + + platform_set_drvdata(pdev, muxc); + + for (i = 0; i < QSFP_MODULE_NUM; i++) { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + dev_info(&pdev->dev, "%d port mux on %s adapter\n", QSFP_MODULE_NUM, parent->name); + + return 0; + +add_adapter_failed: + i2c_mux_del_adapters(muxc); +alloc_failed: + i2c_put_adapter(parent); + + return ret; +} + +static int qsfp_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + + i2c_mux_del_adapters(muxc); + + i2c_put_adapter(muxc->parent); + + return 0; +} + +static struct platform_driver qsfp_mux_driver = { + .probe = qsfp_mux_probe, + .remove = qsfp_mux_remove, + .driver = { + .owner = THIS_MODULE, + .name = "dell-s6000-qsfp-mux", + }, +}; + +/* TODO */ +/* module_platform_driver */ + +static ssize_t get_modsel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x0); + if (ret < 0) + return sprintf(buf, "na"); + data = (u32)ret & 0xff; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x1); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0xa); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0xb); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x2); + if (ret < 0) + return sprintf(buf, "na"); + data = (u32)ret & 0xff; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x3); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0xc); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0xd); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + i2c_smbus_write_byte_data(pdata[slave_cpld].client, 0x2, (u8)(data & 0xff)); + i2c_smbus_write_byte_data(pdata[slave_cpld].client, 0x3, (u8)((data >> 8) & 0xff)); + i2c_smbus_write_byte_data(pdata[master_cpld].client, 0xc, (u8)((data >> 16) & 0xff)); + i2c_smbus_write_byte_data(pdata[master_cpld].client, 0xd, (u8)((data >> 24) & 0xff)); + + return count; +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x6); + if (ret < 0) + return sprintf(buf, "na"); + data = (u32)ret & 0xff; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x10); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x11); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + i2c_smbus_write_byte_data(pdata[slave_cpld].client, 0x6, (u8)(data & 0xff)); + i2c_smbus_write_byte_data(pdata[slave_cpld].client, 0x7, (u8)((data >> 8)& 0xff)); + i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x10, (u8)((data >> 16) & 0xff)); + i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x11, (u8)((data >> 24) & 0xff)); + + return count; +} + +static ssize_t get_modprs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x4); + if (ret < 0) + return sprintf(buf, "read error"); + data = (u32)ret & 0xff; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x5); + if (ret < 0) + return sprintf(buf, "read error"); + data |= (u32)(ret & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0xe); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0xf); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); +} + +static ssize_t set_power_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 10, &data); + if (err) + return err; + + if (data) + { + i2c_smbus_write_byte_data(pdata[system_cpld].client, 0x1, (u8)(0xfd)); + } + + return count; +} + +static ssize_t get_power_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + return sprintf(buf, "0\n"); +} + +static ssize_t get_fan_prs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return sprintf(buf, "read error"); + data = (u32)((ret & 0xc0) >> 6); + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x9); + if (ret < 0) + return sprintf(buf, "read error"); + data |= (u32)((ret & 0x01) << 2); + data = ~data & 0x7; + + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t get_psu0_prs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x3); + if (ret < 0) + return sprintf(buf, "read error"); + + if (!(ret & 0x80)) + data = 1; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t get_psu1_prs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x3); + if (ret < 0) + return sprintf(buf, "read error"); + + if (!(ret & 0x08)) + data = 1; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t get_psu0_status(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x3); + if (ret < 0) + return sprintf(buf, "read error"); + + if (!(ret & 0x40)) + data = 1; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t get_psu1_status(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x3); + if (ret < 0) + return sprintf(buf, "read error"); + + if (!(ret & 0x04)) + data = 1; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t get_system_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x60) >> 5; + + switch (data) + { + case 0: + ret = sprintf(buf, "blink_green\n"); + break; + case 1: + ret = sprintf(buf, "green\n"); + break; + case 2: + ret = sprintf(buf, "yellow\n"); + break; + default: + ret = sprintf(buf, "blink_yellow\n"); + } + + return ret; +} + +static ssize_t set_system_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "blink_green", 11)) + { + data = 0; + } + else if (!strncmp(buf, "green", 5)) + { + data = 1; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 2; + } + else if (!strncmp(buf, "blink_yellow", 12)) + { + data = 3; + } + else + { + return -1; + } + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return ret; + + i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x7, (u8)((ret & 0x9F) | (data << 5))); + + return count; +} + +static ssize_t get_locator_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x18) >> 3; + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "blink_blue\n"); + break; + case 2: + ret = sprintf(buf, "blue\n"); + break; + default: + ret = sprintf(buf, "invalid\n"); + } + + return ret; +} + +static ssize_t set_locator_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "blink_blue", 10)) + { + data = 1; + } + else if (!strncmp(buf, "blue", 4)) + { + data = 2; + } + else + { + return -1; + } + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return ret; + + i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x7, (u8)((ret & 0xE7) | (data << 3))); + + return count; +} + +static ssize_t get_power_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x06) >> 1; + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "yellow\n"); + break; + case 2: + ret = sprintf(buf, "green\n"); + break; + default: + ret = sprintf(buf, "blink_yellow\n"); + } + + return ret; +} + +static ssize_t set_power_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 1; + } + else if (!strncmp(buf, "green", 5)) + { + data = 2; + } + else if (!strncmp(buf, "blink_yellow", 12)) + { + data = 3; + } + else + { + return -1; + } + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return ret; + + i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x7, (u8)((ret & 0xF9) | (data << 1))); + + return count; +} + +static ssize_t get_master_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x1); + + switch (data) + { + case 0: + ret = sprintf(buf, "green\n"); + break; + default: + ret = sprintf(buf, "off\n"); + break; + } + + return ret; +} + +static ssize_t set_master_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "green", 5)) + { + data = 0; + } + else if (!strncmp(buf, "off", 3)) + { + data = 1; + } + else + { + return -1; + } + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return ret; + + i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x7, (u8)((ret & 0xFE) | data)); + + return count; +} + +static ssize_t get_fan_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x9); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x18) >> 3; + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "yellow\n"); + break; + case 2: + ret = sprintf(buf, "green\n"); + break; + default: + ret = sprintf(buf, "blink_yellow\n"); + } + + return ret; +} + +static ssize_t set_fan_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 1; + } + else if (!strncmp(buf, "green", 5)) + { + data = 2; + } + else if (!strncmp(buf, "blink_yellow", 12)) + { + data = 3; + } + else + { + return -1; + } + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x9); + if (ret < 0) + return ret; + + i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x9, (u8)((ret & 0xE7) | (data << 3))); + + return count; +} + +static ssize_t get_fan0_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x3); + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "green\n"); + break; + case 2: + ret = sprintf(buf, "yellow\n"); + break; + default: + ret = sprintf(buf, "unknown\n"); + } + + return ret; +} + +static ssize_t set_fan0_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 2; + } + else if (!strncmp(buf, "green", 5)) + { + data = 1; + } + else + { + return -1; + } + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return ret; + + i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x8, (u8)((ret & 0xFC) | data)); + + return count; +} + + +static ssize_t get_fan1_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0xc) >> 2; + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "green\n"); + break; + case 2: + ret = sprintf(buf, "yellow\n"); + break; + default: + ret = sprintf(buf, "unknown\n"); + } + + return ret; +} + +static ssize_t set_fan1_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 2; + } + else if (!strncmp(buf, "green", 5)) + { + data = 1; + } + else + { + return -1; + } + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return ret; + + i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x8, (u8)((ret & 0xF3) | (data << 2))); + + return count; +} + +static ssize_t get_fan2_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x30) >> 4; + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "green\n"); + break; + case 2: + ret = sprintf(buf, "yellow\n"); + break; + default: + ret = sprintf(buf, "unknown\n"); + } + + return ret; +} + +static ssize_t set_fan2_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 2; + } + else if (!strncmp(buf, "green", 5)) + { + data = 1; + } + else + { + return -1; + } + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return ret; + + i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x8, (u8)((ret & 0xCF) | (data << 4))); + + return count; +} + +static DEVICE_ATTR(qsfp_modsel, S_IRUGO, get_modsel, NULL); +static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL); +static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode); +static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset); +static DEVICE_ATTR(power_reset, S_IRUGO | S_IWUSR, get_power_reset, set_power_reset); +static DEVICE_ATTR(fan_prs, S_IRUGO, get_fan_prs, NULL); +static DEVICE_ATTR(psu0_prs, S_IRUGO, get_psu0_prs, NULL); +static DEVICE_ATTR(psu1_prs, S_IRUGO, get_psu1_prs, NULL); +static DEVICE_ATTR(psu0_status, S_IRUGO, get_psu0_status, NULL); +static DEVICE_ATTR(psu1_status, S_IRUGO, get_psu1_status, NULL); +static DEVICE_ATTR(system_led, S_IRUGO | S_IWUSR, get_system_led, set_system_led); +static DEVICE_ATTR(locator_led, S_IRUGO | S_IWUSR, get_locator_led, set_locator_led); +static DEVICE_ATTR(power_led, S_IRUGO | S_IWUSR, get_power_led, set_power_led); +static DEVICE_ATTR(master_led, S_IRUGO | S_IWUSR, get_master_led, set_master_led); +static DEVICE_ATTR(fan_led, S_IRUGO | S_IWUSR, get_fan_led, set_fan_led); +static DEVICE_ATTR(fan0_led, S_IRUGO | S_IWUSR, get_fan0_led, set_fan0_led); +static DEVICE_ATTR(fan1_led, S_IRUGO | S_IWUSR, get_fan1_led, set_fan1_led); +static DEVICE_ATTR(fan2_led, S_IRUGO | S_IWUSR, get_fan2_led, set_fan2_led); + +static struct attribute *s6000_cpld_attrs[] = { + &dev_attr_qsfp_modsel.attr, + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_power_reset.attr, + &dev_attr_fan_prs.attr, + &dev_attr_psu0_prs.attr, + &dev_attr_psu1_prs.attr, + &dev_attr_psu0_status.attr, + &dev_attr_psu1_status.attr, + &dev_attr_system_led.attr, + &dev_attr_locator_led.attr, + &dev_attr_power_led.attr, + &dev_attr_master_led.attr, + &dev_attr_fan_led.attr, + &dev_attr_fan0_led.attr, + &dev_attr_fan1_led.attr, + &dev_attr_fan2_led.attr, + NULL, +}; + +static struct attribute_group s6000_cpld_attr_grp = { + .attrs = s6000_cpld_attrs, +}; + +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int i; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(S6000_MUX_BASE_NR); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", + S6000_MUX_BASE_NR); + return -ENODEV; + } + + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + pdata[i].client = i2c_new_dummy(parent, pdata[i].reg_addr); + if (!pdata[i].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[i].reg_addr); + goto error; + } + } + + ret = sysfs_create_group(&pdev->dev.kobj, &s6000_cpld_attr_grp); + if (ret) + goto error; + + return 0; + +error: + i--; + for (; i >= 0; i--) { + if (pdata[i].client) { + i2c_unregister_device(pdata[i].client); + } + } + + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + int i; + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + + sysfs_remove_group(&pdev->dev.kobj, &s6000_cpld_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } else { + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + if (pdata[i].client) { + if (!parent) { + parent = (pdata[i].client)->adapter; + } + i2c_unregister_device(pdata[i].client); + } + } + } + + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "dell-s6000-cpld", + }, +}; + +static int __init dell_s6000_platform_init(void) +{ + int ret = 0; + struct cpld_platform_data *cpld_pdata; + struct qsfp_mux_platform_data *qsfp_pdata; + int i; + + printk("delll_s6000_platform module initialization\n"); + + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpld driver\n"); + goto error_cpld_driver; + } + + ret = platform_driver_register(&qsfp_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register qsfp mux driver\n"); + goto error_qsfp_mux_driver; + } + + ret = platform_device_register(&s6000_mux); + if (ret) { + printk(KERN_WARNING "Fail to create gpio mux\n"); + goto error_mux; + } + + ret = platform_device_register(&s6000_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpld device\n"); + goto error_cpld; + } + + cpld_pdata = s6000_cpld.dev.platform_data; + qsfp_pdata = s6000_qsfp_mux[0].dev.platform_data; + qsfp_pdata->cpld = cpld_pdata[slave_cpld].client; + qsfp_pdata = s6000_qsfp_mux[1].dev.platform_data; + qsfp_pdata->cpld = cpld_pdata[master_cpld].client; + + for (i = 0; i < QSFP_DEVICE_NUM; i++) { + ret = platform_device_register(&s6000_qsfp_mux[i]); + if (ret) { + printk(KERN_WARNING "fail to create qsfp mux %d\n", i); + goto error_qsfp_mux; + } + } + + if (ret) + goto error_qsfp_mux; + + return 0; + +error_qsfp_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&s6000_qsfp_mux[i]); + } + platform_device_unregister(&s6000_cpld); +error_cpld: + platform_device_unregister(&s6000_mux); +error_mux: + platform_driver_unregister(&qsfp_mux_driver); +error_qsfp_mux_driver: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +} + +static void __exit dell_s6000_platform_exit(void) +{ + int i; + + for (i = 0; i < MUX_CHANNEL_NUM; i++) + platform_device_unregister(&s6000_qsfp_mux[i]); + platform_device_unregister(&s6000_cpld); + platform_device_unregister(&s6000_mux); + + platform_driver_unregister(&cpld_driver); + platform_driver_unregister(&qsfp_mux_driver); +} + +module_init(dell_s6000_platform_init); +module_exit(dell_s6000_platform_exit); + +MODULE_DESCRIPTION("DELL S6000 Platform Support"); +MODULE_AUTHOR("Guohan Lu "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-s6000/scripts/reset-qsfp b/platform/broadcom/sonic-platform-modules-s6000/scripts/reset-qsfp new file mode 100755 index 000000000000..6b017ed37c26 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/scripts/reset-qsfp @@ -0,0 +1,25 @@ +#!/bin/bash + +# Usage: +# Reset QSFP manually by writing 1/0 to QSFP reset pin + +QSFP_RESET=/sys/bus/platform/devices/dell-s6000-cpld.0/qsfp_reset + +logger -t platform-modules "Reset QSFP modules" + +# Retry three times +for i in `seq 1 3` +do + if [ -w $QSFP_RESET ]; then + echo 0x00000000 > $QSFP_RESET + # Sleep 1 second to reset QSFP + sleep 1 + echo 0xffffffff > $QSFP_RESET + exit 0 + fi + # Sleep for 3 seconds to wait for device tree to be ready + sleep 3 +done + +logger -p user.error -t platform-modules "Failed to reset QSFP modules!" +exit 1 diff --git a/platform/broadcom/sonic-platform-modules-s6000/scripts/set-fan-speed b/platform/broadcom/sonic-platform-modules-s6000/scripts/set-fan-speed new file mode 100755 index 000000000000..00c738f23a8d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/scripts/set-fan-speed @@ -0,0 +1,58 @@ +#!/bin/bash + +# Usage: +# Set all fans speed to $1 + +usage() { + echo "This script must be run with super-user privilege." + echo "Warning! Wrongly set fan speed may result in physical damage to the device." + echo "" + echo "usage: set-fan-speed speed_in_rpm" + echo "example: set-fan-speed 15000" +} + +if [ $# -ne 1 ]; then + usage + exit 1 +fi + +PSU_FAN1=/sys/class/i2c-adapter/i2c-1/1-0058/fan1_target +PSU_FAN2=/sys/class/i2c-adapter/i2c-1/1-0059/fan1_target + +# Three fan trays with each contains two separate fans +# fan1-fan4 fan2-fan5 fan3-fan6 +FAN1=/sys/class/i2c-adapter/i2c-11/11-0029/fan1_target +FAN2=/sys/class/i2c-adapter/i2c-11/11-0029/fan2_target +FAN3=/sys/class/i2c-adapter/i2c-11/11-0029/fan3_target +FAN4=/sys/class/i2c-adapter/i2c-11/11-0029/fan4_target +FAN5=/sys/class/i2c-adapter/i2c-11/11-002a/fan1_target +FAN6=/sys/class/i2c-adapter/i2c-11/11-002a/fan2_target + +speed=$1 +logger -t platform-modules "Trying to set fan speed to $speed" + +# Retry three times +for i in `seq 1 3` +do + if [ -w $FAN1 -o -w $FAN2 -o -w $FAN3 ]; then + # set default psu fan speed + echo $speed > $PSU_FAN1 + echo $speed > $PSU_FAN2 + # set default fan speed + echo $speed > $FAN1 + echo $speed > $FAN2 + echo $speed > $FAN3 + echo $speed > $FAN4 + echo $speed > $FAN5 + echo $speed > $FAN6 + + logger -t platform-modules "Fan speed is set to $speed" + + exit 0 + fi + # Sleep for 3 seconds to wait for device tree to be ready + sleep 3 +done + +logger -p user.error -t platform-modules "Failed to set fan speed!" +exit 1 diff --git a/platform/broadcom/sonic-platform-modules-s6000/systemd/platform-modules-s6000.service b/platform/broadcom/sonic-platform-modules-s6000/systemd/platform-modules-s6000.service new file mode 100644 index 000000000000..246dee9b64f3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-s6000/systemd/platform-modules-s6000.service @@ -0,0 +1,13 @@ +[Unit] +Description=Dell S6000 Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-s6000 start +ExecStop=-/etc/init.d/platform-modules-s6000 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/cavium/cavm-platform-modules.mk b/platform/cavium/cavm-platform-modules.mk new file mode 100644 index 000000000000..4ac72a4c4aab --- /dev/null +++ b/platform/cavium/cavm-platform-modules.mk @@ -0,0 +1,3 @@ +CAVM_PLATFORM_DEB = cavm_platform_modules.deb +$(CAVM_PLATFORM_DEB)_SRC_PATH = $(PLATFORM_PATH)/cavm_platform_modules +SONIC_MAKE_DEBS += $(CAVM_PLATFORM_DEB) diff --git a/platform/cavium/cavm-sai.mk b/platform/cavium/cavm-sai.mk new file mode 100644 index 000000000000..0008135729c5 --- /dev/null +++ b/platform/cavium/cavm-sai.mk @@ -0,0 +1,13 @@ +# Cavium SAI + +CAVM_SAI_GITHUB = https://github.com/XPliant/OpenXPS/raw/13a7eaf10f523e7887964ca235f19095fcc88537/SAI/cavm-sai/ + +CAVM_LIBSAI = libsai.deb +CAVM_SAI = sai.deb +XP_TOOLS = xp-tools.deb + +$(CAVM_LIBSAI)_URL = $(CAVM_SAI_GITHUB)/$(CAVM_LIBSAI) +$(CAVM_SAI)_URL = $(CAVM_SAI_GITHUB)/$(CAVM_SAI) +$(XP_TOOLS)_URL = $(CAVM_SAI_GITHUB)/$(XP_TOOLS) + +SONIC_ONLINE_DEBS += $(CAVM_LIBSAI) $(CAVM_SAI) $(XP_TOOLS) diff --git a/platform/cavium/cavm-xpnet.mk b/platform/cavium/cavm-xpnet.mk new file mode 100644 index 000000000000..ed86558a36ae --- /dev/null +++ b/platform/cavium/cavm-xpnet.mk @@ -0,0 +1,6 @@ +CAVM_SAI_URL = https://github.com/XPliant/OpenXPS/raw/c26aea6a7098936ab3692e148238d73fa8962585/SAI + +CAVM_XPNET_DEB = xp80-Pcie-Endpoint.deb +$(CAVM_XPNET_DEB)_URL = $(CAVM_SAI_URL)/netdev/$(CAVM_XPNET_DEB) + +SONIC_ONLINE_DEBS += $(CAVM_XPNET_DEB) diff --git a/platform/cavium/cavm_platform_modules/DEBIAN/changelog b/platform/cavium/cavm_platform_modules/DEBIAN/changelog new file mode 100644 index 000000000000..b138dba26289 --- /dev/null +++ b/platform/cavium/cavm_platform_modules/DEBIAN/changelog @@ -0,0 +1,6 @@ + +cavm-platform-modules (1.0) unstable; urgency=low + + * Initial release + +-- Nadiya.Stetskovych@cavium.com Thu, 12 Jan 2017 19:24:41 +0200 diff --git a/platform/cavium/cavm_platform_modules/DEBIAN/control b/platform/cavium/cavm_platform_modules/DEBIAN/control new file mode 100755 index 000000000000..75f8adc0cbd2 --- /dev/null +++ b/platform/cavium/cavm_platform_modules/DEBIAN/control @@ -0,0 +1,6 @@ +Package: cavm-platform-modules +Version: 1.0 +Architecture: amd64 +Depends: linux-image-3.16.0-4-amd64 +Maintainer: Nadiya.Stetskovych@cavium.com +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/cavium/cavm_platform_modules/Makefile b/platform/cavium/cavm_platform_modules/Makefile new file mode 100644 index 000000000000..aeb274aa5a42 --- /dev/null +++ b/platform/cavium/cavm_platform_modules/Makefile @@ -0,0 +1,33 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = cavm_platform_modules.deb +DEB_BUILD_DIR = cavm-platform-modules-deb +SCRIPT_SRC = $(DEB_BUILD_DIR)/ +SYSTEMD_DIR = /etc/systemd/system + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + rm -rf SONiC + git clone https://github.com/edge-core/SONiC.git + + # build + pushd SONiC/AS7512-32X/module/ + + KERNEL_SRC=/lib/modules/$(KVERSION)/build make + popd + mkdir -p $(DEB_BUILD_DIR)/lib/modules/$(KVERSION) + mkdir -p $(DEB_BUILD_DIR)/usr/bin + mkdir -p $(DEB_BUILD_DIR)$(SYSTEMD_DIR)/multi-user.target.wants/ + + cp SONiC/AS7512-32X/module/*.ko $(DEB_BUILD_DIR)/lib/modules/$(KVERSION) + cp SONiC/AS7512-32X/accton_as7512_util.py $(DEB_BUILD_DIR)/usr/bin + chmod +x $(DEB_BUILD_DIR)/usr/bin/accton_as7512_util.py + cp as7512-platform-init.service $(DEB_BUILD_DIR)$(SYSTEMD_DIR) + ln -s $(SYSTEMD_DIR)/as7512-platform-init.service $(DEB_BUILD_DIR)$(SYSTEMD_DIR)/multi-user.target.wants/as7512-platform-init.service + cp -r DEBIAN $(DEB_BUILD_DIR) + dpkg-deb -b $(DEB_BUILD_DIR) $(MAIN_TARGET) + + mv $(MAIN_TARGET) $(DEST)/ + rm -rf $(DEB_BUILD_DIR) diff --git a/platform/cavium/cavm_platform_modules/as7512-platform-init.service b/platform/cavium/cavm_platform_modules/as7512-platform-init.service new file mode 100644 index 000000000000..69f03c0b2e45 --- /dev/null +++ b/platform/cavium/cavm_platform_modules/as7512-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Accton AS7512-32X Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/bin/accton_as7512_util.py install +ExecStop=/usr/bin/accton_as7512_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/cavium/cavm_sdk/filelist.txt b/platform/cavium/cavm_sdk/filelist.txt new file mode 100644 index 000000000000..bc40295dfbdc --- /dev/null +++ b/platform/cavium/cavm_sdk/filelist.txt @@ -0,0 +1,7 @@ +## Get vendor SAI SDK +## https://github.com/Azure/sonic-buildimage/blob/master/README.md#3-get-vendor-sai-sdk + +libsai.deb +sai.deb +xp-tools.deb +xpshell.deb diff --git a/platform/cavium/docker-orchagent-cavm.mk b/platform/cavium/docker-orchagent-cavm.mk new file mode 100644 index 000000000000..282cdaa9172d --- /dev/null +++ b/platform/cavium/docker-orchagent-cavm.mk @@ -0,0 +1,24 @@ +# docker image for orchagent + +DOCKER_ORCHAGENT_CAVM = docker-orchagent-cavm.gz +$(DOCKER_ORCHAGENT_CAVM)_PATH = $(DOCKERS_PATH)/docker-orchagent +$(DOCKER_ORCHAGENT_CAVM)_DEPENDS += $(SWSS) $(REDIS_TOOLS) $(IPROUTE2) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_ORCHAGENT_CAVM)_DEPENDS += $(SWSS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_ORCHAGENT_CAVM)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_CAVM) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_CAVM) + +$(DOCKER_ORCHAGENT_CAVM)_CONTAINER_NAME = swss +$(DOCKER_ORCHAGENT_CAVM)_RUN_OPT += --net=host --privileged -t +$(DOCKER_ORCHAGENT_CAVM)_RUN_OPT += -v /etc/network/interfaces:/etc/network/interfaces:ro +$(DOCKER_ORCHAGENT_CAVM)_RUN_OPT += -v /etc/network/interfaces.d/:/etc/network/interfaces.d/:ro +$(DOCKER_ORCHAGENT_CAVM)_RUN_OPT += -v /host/machine.conf:/host/machine.conf:ro +$(DOCKER_ORCHAGENT_CAVM)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_ORCHAGENT_CAVM)_RUN_OPT += -v /var/log/swss:/var/log/swss:rw + +$(DOCKER_ORCHAGENT_CAVM)_BASE_IMAGE_FILES += swssloglevel:/usr/bin/swssloglevel +$(DOCKER_ORCHAGENT_CAVM)_FILES += $(ARP_UPDATE_SCRIPT) diff --git a/platform/cavium/docker-ptf-cavm.mk b/platform/cavium/docker-ptf-cavm.mk new file mode 100644 index 000000000000..4665345586a8 --- /dev/null +++ b/platform/cavium/docker-ptf-cavm.mk @@ -0,0 +1,7 @@ +# docker image for docker-ptf-cavm + +DOCKER_PTF_CAVM = docker-ptf-cavm.gz +$(DOCKER_PTF_CAVM)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift +$(DOCKER_PTF_CAVM)_DEPENDS += $(PYTHON_SAITHRIFT_CAVM) +$(DOCKER_PTF_CAVM)_LOAD_DOCKERS += $(DOCKER_PTF) +SONIC_DOCKER_IMAGES += $(DOCKER_PTF_CAVM) diff --git a/platform/cavium/docker-saiserver-cavm/Dockerfile b/platform/cavium/docker-saiserver-cavm/Dockerfile new file mode 100644 index 000000000000..2f667c8038ed --- /dev/null +++ b/platform/cavium/docker-saiserver-cavm/Dockerfile @@ -0,0 +1,30 @@ +FROM docker-base + +RUN apt-get update \ + && apt-get install -y libsensors4-dev \ + python \ + python-dev + +COPY deps /root/deps + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; \ + dpkg_apt /root/deps/xp-tools.deb \ + && dpkg_apt /root/deps/libsai.deb \ + && dpkg_apt /root/deps/sai.deb \ + && dpkg_apt /root/deps/libthrift-0.9.3_*.deb \ + && dpkg_apt /root/deps/libnl-3-200_*.deb \ + && dpkg_apt /root/deps/libnl-genl-3-200_*.deb \ + && dpkg_apt /root/deps/libnl-route-3-200_*.deb + + +COPY ["deps/saiserver", "start.sh", "/usr/bin/"] + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +COPY ["portmap.ini", "profile.ini", "/etc/sai/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf deps + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/cavium/docker-saiserver-cavm/portmap.ini b/platform/cavium/docker-saiserver-cavm/portmap.ini new file mode 100644 index 000000000000..c35776dcfcc5 --- /dev/null +++ b/platform/cavium/docker-saiserver-cavm/portmap.ini @@ -0,0 +1,33 @@ +# alias lanes +Ethernet0 16,17,18,19 +Ethernet4 20,21,22,23 +Ethernet8 24,25,26,27 +Ethernet12 28,29,30,31 +Ethernet16 32,33,34,35 +Ethernet20 36,37,38,39 +Ethernet24 40,41,42,43 +Ethernet28 44,45,46,47 +Ethernet32 0,1,2,3 +Ethernet36 4,5,6,7 +Ethernet40 8,9,10,11 +Ethernet44 12,13,14,15 +Ethernet48 48,49,50,51 +Ethernet52 52,53,54,55 +Ethernet56 56,57,58,59 +Ethernet60 60,61,62,63 +Ethernet64 127,126,125,124 +Ethernet68 123,122,121,120 +Ethernet72 115,114,113,112 +Ethernet76 119,118,117,116 +Ethernet80 79,78,77,76 +Ethernet84 75,74,73,72 +Ethernet88 64,65,66,67 +Ethernet92 71,70,68,69 +Ethernet96 111,110,109,108 +Ethernet100 107,106,105,104 +Ethernet104 103,102,101,100 +Ethernet108 99,98,97,96 +Ethernet112 95,94,93,92 +Ethernet116 91,90,89,88 +Ethernet120 87,86,85,84 +Ethernet124 83,82,81,80 diff --git a/platform/cavium/docker-saiserver-cavm/profile.ini b/platform/cavium/docker-saiserver-cavm/profile.ini new file mode 100644 index 000000000000..2b85ae77ebef --- /dev/null +++ b/platform/cavium/docker-saiserver-cavm/profile.ini @@ -0,0 +1,4 @@ +#SKU_128X10 +mode=0 + +hwId=as7512 diff --git a/platform/cavium/docker-saiserver-cavm/start.sh b/platform/cavium/docker-saiserver-cavm/start.sh new file mode 100755 index 000000000000..09cc0ddb5416 --- /dev/null +++ b/platform/cavium/docker-saiserver-cavm/start.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start saiserver diff --git a/platform/cavium/docker-saiserver-cavm/supervisord.conf b/platform/cavium/docker-saiserver-cavm/supervisord.conf new file mode 100644 index 000000000000..cb67a0fc9a47 --- /dev/null +++ b/platform/cavium/docker-saiserver-cavm/supervisord.conf @@ -0,0 +1,28 @@ +[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:saiserver] +command=/usr/bin/saiserver -p /etc/sai/profile.ini -f /etc/sai/portmap.ini +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/cavium/docker-syncd-cavm-rpc.mk b/platform/cavium/docker-syncd-cavm-rpc.mk new file mode 100644 index 000000000000..e0136f5324b6 --- /dev/null +++ b/platform/cavium/docker-syncd-cavm-rpc.mk @@ -0,0 +1,15 @@ +# docker image for cavium syncd with rpc + +DOCKER_SYNCD_CAVM_RPC = docker-syncd-cavm-rpc.gz +$(DOCKER_SYNCD_CAVM_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-cavm-rpc +$(DOCKER_SYNCD_CAVM_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(CAVM_LIBSAI) $(XP_TOOLS) $(REDIS_TOOLS) +$(DOCKER_SYNCD_CAVM_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_CAVM) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_CAVM_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_CAVM_RPC) +endif + +$(DOCKER_SYNCD_CAVM_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_CAVM_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_CAVM_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_CAVM_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/cavium/docker-syncd-cavm-rpc/Dockerfile.j2 b/platform/cavium/docker-syncd-cavm-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..0c70dcd8e845 --- /dev/null +++ b/platform/cavium/docker-syncd-cavm-rpc/Dockerfile.j2 @@ -0,0 +1,51 @@ +FROM docker-syncd-cavm + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_cavm_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -P syncd + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_cavm_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + && wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/cavium/docker-syncd-cavm-rpc/ptf_nn_agent.conf b/platform/cavium/docker-syncd-cavm-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/cavium/docker-syncd-cavm-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/cavium/docker-syncd-cavm.mk b/platform/cavium/docker-syncd-cavm.mk new file mode 100644 index 000000000000..8a3b0857dadf --- /dev/null +++ b/platform/cavium/docker-syncd-cavm.mk @@ -0,0 +1,15 @@ +# docker image for cavium syncd + +DOCKER_SYNCD_CAVM = docker-syncd-cavm.gz +$(DOCKER_SYNCD_CAVM)_PATH = $(PLATFORM_PATH)/docker-syncd-cavm +$(DOCKER_SYNCD_CAVM)_DEPENDS += $(SYNCD) $(CAVM_LIBSAI) $(XP_TOOLS) $(REDIS_TOOLS) +$(DOCKER_SYNCD_CAVM)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_CAVM) +ifneq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_CAVM) +endif + +$(DOCKER_SYNCD_CAVM)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_CAVM)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_CAVM)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_CAVM)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/cavium/docker-syncd-cavm/Dockerfile.j2 b/platform/cavium/docker-syncd-cavm/Dockerfile.j2 new file mode 100755 index 000000000000..5594c8e576bc --- /dev/null +++ b/platform/cavium/docker-syncd-cavm/Dockerfile.j2 @@ -0,0 +1,33 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_syncd_cavm_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get -y install libpcap-dev libxml2-dev python-dev swig libsensors4-dev libjemalloc1 + +RUN dpkg -i \ +{% for deb in docker_syncd_cavm_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +COPY ["profile.ini", "/etc/ssw/AS7512/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/cavium/docker-syncd-cavm/profile.ini b/platform/cavium/docker-syncd-cavm/profile.ini new file mode 100644 index 000000000000..017996f7d7cc --- /dev/null +++ b/platform/cavium/docker-syncd-cavm/profile.ini @@ -0,0 +1,2 @@ +mode=1 +hwId=as7512 diff --git a/platform/cavium/docker-syncd-cavm/start.sh b/platform/cavium/docker-syncd-cavm/start.sh new file mode 100755 index 000000000000..623316050475 --- /dev/null +++ b/platform/cavium/docker-syncd-cavm/start.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start syncd diff --git a/platform/cavium/docker-syncd-cavm/supervisord.conf b/platform/cavium/docker-syncd-cavm/supervisord.conf new file mode 100644 index 000000000000..1af5d70a1d0c --- /dev/null +++ b/platform/cavium/docker-syncd-cavm/supervisord.conf @@ -0,0 +1,28 @@ +[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:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/cavium/libsaithrift-dev.mk b/platform/cavium/libsaithrift-dev.mk new file mode 100644 index 000000000000..f8c42f31ca7e --- /dev/null +++ b/platform/cavium/libsaithrift-dev.mk @@ -0,0 +1,7 @@ +# libsaithrift-dev package + +LIBSAITHRIFT_DEV_CAVM = libsaithrift-dev_1.2.1_amd64.deb +$(LIBSAITHRIFT_DEV_CAVM)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV_CAVM)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(THRIFT_COMPILER) $(CAVM_LIBSAI) $(CAVM_SAI) +$(LIBSAITHRIFT_DEV_CAVM)_RDEPENDS += $(LIBTHRIFT) $(CAVM_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV_CAVM) diff --git a/platform/cavium/one-image.mk b/platform/cavium/one-image.mk new file mode 100644 index 000000000000..696578451990 --- /dev/null +++ b/platform/cavium/one-image.mk @@ -0,0 +1,9 @@ +# sonic cavium one image installer + +SONIC_ONE_IMAGE = sonic-cavium.bin +$(SONIC_ONE_IMAGE)_MACHINE = cavium +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(CAVM_PLATFORM_DEB) +$(SONIC_ONE_IMAGE)_INSTALLS += $(CAVM_XPNET_DEB) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/cavium/platform.conf b/platform/cavium/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/cavium/python-saithrift.mk b/platform/cavium/python-saithrift.mk new file mode 100644 index 000000000000..606823b625b8 --- /dev/null +++ b/platform/cavium/python-saithrift.mk @@ -0,0 +1,6 @@ +# python-saithrift package + +PYTHON_SAITHRIFT_CAVM = python-saithrift_1.2.1_amd64.deb +$(PYTHON_SAITHRIFT_CAVM)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(PYTHON_SAITHRIFT_CAVM)_DEPENDS += $(CAVM_LIBSAI) $(CAVM_SAI) $(THRIFT_COMPILER) $(PYTHON_THRIFT) $(LIBTHRIFT_DEV) +SONIC_DPKG_DEBS += $(PYTHON_SAITHRIFT_CAVM) diff --git a/platform/cavium/rules.mk b/platform/cavium/rules.mk new file mode 100644 index 000000000000..37a9bd7c994b --- /dev/null +++ b/platform/cavium/rules.mk @@ -0,0 +1,21 @@ +include $(PLATFORM_PATH)/cavm-sai.mk +include $(PLATFORM_PATH)/docker-syncd-cavm.mk +include $(PLATFORM_PATH)/docker-syncd-cavm-rpc.mk +include $(PLATFORM_PATH)/docker-orchagent-cavm.mk +include $(PLATFORM_PATH)/cavm-platform-modules.mk +include $(PLATFORM_PATH)/cavm-xpnet.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/python-saithrift.mk +include $(PLATFORM_PATH)/docker-ptf-cavm.mk + +SONIC_ALL += $(SONIC_ONE_IMAGE) \ + $(DOCKER_FPM) \ + $(DOCKER_PTF_CAVM) \ + $(DOCKER_SYNCD_CAVM_RPC) + +# Inject cavium sai into sairedis +$(LIBSAIREDIS)_DEPENDS += $(CAVM_SAI) $(CAVM_LIBSAI) $(LIBSAITHRIFT_DEV_CAVM) + +# Runtime dependency on cavium sai is set only for syncd +$(SYNCD)_RDEPENDS += $(CAVM_SAI) diff --git a/platform/centec/docker-orchagent-centec.mk b/platform/centec/docker-orchagent-centec.mk new file mode 100644 index 000000000000..891f5550bac6 --- /dev/null +++ b/platform/centec/docker-orchagent-centec.mk @@ -0,0 +1,24 @@ +# docker image for orchagent + +DOCKER_ORCHAGENT_CENTEC = docker-orchagent-centec.gz +$(DOCKER_ORCHAGENT_CENTEC)_PATH = $(DOCKERS_PATH)/docker-orchagent +$(DOCKER_ORCHAGENT_CENTEC)_DEPENDS += $(SWSS) $(REDIS_TOOLS) $(IPROUTE2) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_ORCHAGENT_CENTEC)_DEPENDS += $(SWSS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_ORCHAGENT_CENTEC)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_CENTEC) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_CENTEC) + +$(DOCKER_ORCHAGENT_CENTEC)_CONTAINER_NAME = swss +$(DOCKER_ORCHAGENT_CENTEC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_ORCHAGENT_CENTEC)_RUN_OPT += -v /etc/network/interfaces:/etc/network/interfaces:ro +$(DOCKER_ORCHAGENT_CENTEC)_RUN_OPT += -v /etc/network/interfaces.d/:/etc/network/interfaces.d/:ro +$(DOCKER_ORCHAGENT_CENTEC)_RUN_OPT += -v /host/machine.conf:/host/machine.conf:ro +$(DOCKER_ORCHAGENT_CENTEC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_ORCHAGENT_CENTEC)_RUN_OPT += -v /var/log/swss:/var/log/swss:rw + +$(DOCKER_ORCHAGENT_CENTEC)_BASE_IMAGE_FILES += swssloglevel:/usr/bin/swssloglevel +$(DOCKER_ORCHAGENT_CENTEC)_FILES += $(ARP_UPDATE_SCRIPT) diff --git a/platform/centec/docker-ptf-centec.mk b/platform/centec/docker-ptf-centec.mk new file mode 100644 index 000000000000..ff84ed0becb7 --- /dev/null +++ b/platform/centec/docker-ptf-centec.mk @@ -0,0 +1,7 @@ +# docker image for docker-ptf-centec + +DOCKER_PTF_CENTEC = docker-ptf-centec.gz +$(DOCKER_PTF_CENTEC)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift +$(DOCKER_PTF_CENTEC)_DEPENDS += $(PYTHON_SAITHRIFT_CENTEC) +$(DOCKER_PTF_CENTEC)_LOAD_DOCKERS += $(DOCKER_PTF) +SONIC_DOCKER_IMAGES += $(DOCKER_PTF_CENTEC) diff --git a/platform/centec/docker-syncd-centec-rpc.mk b/platform/centec/docker-syncd-centec-rpc.mk new file mode 100644 index 000000000000..1798a034980d --- /dev/null +++ b/platform/centec/docker-syncd-centec-rpc.mk @@ -0,0 +1,16 @@ +# docker image for centec syncd with rpc + +DOCKER_SYNCD_CENTEC_RPC = docker-syncd-centec-rpc.gz +$(DOCKER_SYNCD_CENTEC_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-centec-rpc +$(DOCKER_SYNCD_CENTEC_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) +$(DOCKER_SYNCD_CENTEC_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_CENTEC) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_CENTEC_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_CENTEC_RPC) +endif + +$(DOCKER_SYNCD_CENTEC_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/centec/docker-syncd-centec-rpc/Dockerfile.j2 b/platform/centec/docker-syncd-centec-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..db58e7731be8 --- /dev/null +++ b/platform/centec/docker-syncd-centec-rpc/Dockerfile.j2 @@ -0,0 +1,51 @@ +FROM docker-syncd-centec + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_centec_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -P syncd + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_centec_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + && wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/centec/docker-syncd-centec-rpc/ptf_nn_agent.conf b/platform/centec/docker-syncd-centec-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/centec/docker-syncd-centec-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/centec/docker-syncd-centec.mk b/platform/centec/docker-syncd-centec.mk new file mode 100644 index 000000000000..c4335ab356ac --- /dev/null +++ b/platform/centec/docker-syncd-centec.mk @@ -0,0 +1,16 @@ +# docker image for centec syncd + +DOCKER_SYNCD_CENTEC = docker-syncd-centec.gz +$(DOCKER_SYNCD_CENTEC)_PATH = $(PLATFORM_PATH)/docker-syncd-centec +$(DOCKER_SYNCD_CENTEC)_DEPENDS += $(SYNCD) +$(DOCKER_SYNCD_CENTEC)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_CENTEC) +ifneq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_CENTEC) +endif + +$(DOCKER_SYNCD_CENTEC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_CENTEC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_CENTEC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_CENTEC)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd +$(DOCKER_SYNCD_CENTEC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/centec/docker-syncd-centec/Dockerfile.j2 b/platform/centec/docker-syncd-centec/Dockerfile.j2 new file mode 100755 index 000000000000..d5b9bc73eeca --- /dev/null +++ b/platform/centec/docker-syncd-centec/Dockerfile.j2 @@ -0,0 +1,32 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_syncd_centec_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_syncd_centec_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +## TODO: add kmod into Depends +RUN apt-get install -f kmod + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/centec/docker-syncd-centec/start.sh b/platform/centec/docker-syncd-centec/start.sh new file mode 100755 index 000000000000..623316050475 --- /dev/null +++ b/platform/centec/docker-syncd-centec/start.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start syncd diff --git a/platform/centec/docker-syncd-centec/supervisord.conf b/platform/centec/docker-syncd-centec/supervisord.conf new file mode 100644 index 000000000000..1af5d70a1d0c --- /dev/null +++ b/platform/centec/docker-syncd-centec/supervisord.conf @@ -0,0 +1,28 @@ +[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:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/centec/libsaithrift-dev.mk b/platform/centec/libsaithrift-dev.mk new file mode 100644 index 000000000000..b0e13fa02828 --- /dev/null +++ b/platform/centec/libsaithrift-dev.mk @@ -0,0 +1,7 @@ +# libsaithrift-dev package + +LIBSAITHRIFT_DEV_CENTEC = libsaithrift-dev_1.3.5_amd64.deb +$(LIBSAITHRIFT_DEV_CENTEC)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV_CENTEC)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(THRIFT_COMPILER) $(CENTEC_SAI) +$(LIBSAITHRIFT_DEV_CENTEC)_RDEPENDS += $(LIBTHRIFT) $(CENTEC_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV_CENTEC) diff --git a/platform/centec/one-image.mk b/platform/centec/one-image.mk new file mode 100644 index 000000000000..ec8448433aaa --- /dev/null +++ b/platform/centec/one-image.mk @@ -0,0 +1,9 @@ +# sonic centec one image installer + +SONIC_ONE_IMAGE = sonic-centec.bin +$(SONIC_ONE_IMAGE)_MACHINE = centec +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E582_48X6Q_PLATFORM_MODULE) \ + $(CENTEC_E582_48X2Q4Z_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/centec/platform-modules-centec-e582.mk b/platform/centec/platform-modules-centec-e582.mk new file mode 100644 index 000000000000..e22653075ecb --- /dev/null +++ b/platform/centec/platform-modules-centec-e582.mk @@ -0,0 +1,20 @@ +# Centec E582-48X6Q Platform modules + + +CENTEC_E582_48X6Q_PLATFORM_MODULE_VERSION =1.1 +CENTEC_E582_48X2Q4Z_PLATFORM_MODULE_VERSION =1.1 + +export CENTEC_E582_48X6Q_PLATFORM_MODULE_VERSION +export CENTEC_E582_48X2Q4Z_PLATFORM_MODULE_VERSION + +CENTEC_E582_48X6Q_PLATFORM_MODULE = platform-modules-e582-48x6q_$(CENTEC_E582_48X6Q_PLATFORM_MODULE_VERSION)_amd64.deb + +$(CENTEC_E582_48X6Q_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-e582 +$(CENTEC_E582_48X6Q_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(CENTEC_E582_48X6Q_PLATFORM_MODULE)_PLATFORM = x86_64-centec_e582_48x6q-r0 +SONIC_STRETCH_DEBS += $(CENTEC_E582_48X6Q_PLATFORM_MODULE) +SONIC_DPKG_DEBS += $(CENTEC_E582_48X6Q_PLATFORM_MODULE) + +CENTEC_E582_48X2Q4Z_PLATFORM_MODULE = platform-modules-e582-48x2q4z_$(CENTEC_E582_48X2Q4Z_PLATFORM_MODULE_VERSION)_amd64.deb +$(CENTEC_E582_48X2Q4Z_PLATFORM_MODULE)_PLATFORM = x86_64-centec_e582_48x2q4z-r0 +$(eval $(call add_extra_package,$(CENTEC_E582_48X6Q_PLATFORM_MODULE),$(CENTEC_E582_48X2Q4Z_PLATFORM_MODULE))) diff --git a/platform/centec/platform.conf b/platform/centec/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/centec/python-saithrift.mk b/platform/centec/python-saithrift.mk new file mode 100644 index 000000000000..b62beff89237 --- /dev/null +++ b/platform/centec/python-saithrift.mk @@ -0,0 +1,6 @@ +# python-saithrift package + +PYTHON_SAITHRIFT_CENTEC = python-saithrift_1.3.5_amd64.deb +$(PYTHON_SAITHRIFT_CENTEC)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(PYTHON_SAITHRIFT_CENTEC)_DEPENDS += $(CENTEC_SAI) $(THRIFT_COMPILER) $(PYTHON_THRIFT) $(LIBTHRIFT_DEV) +SONIC_DPKG_DEBS += $(PYTHON_SAITHRIFT_CENTEC) diff --git a/platform/centec/rules.mk b/platform/centec/rules.mk new file mode 100644 index 000000000000..823144dc25ce --- /dev/null +++ b/platform/centec/rules.mk @@ -0,0 +1,19 @@ +include $(PLATFORM_PATH)/platform-modules-centec-e582.mk +include $(PLATFORM_PATH)/sdk.mk +include $(PLATFORM_PATH)/docker-orchagent-centec.mk +include $(PLATFORM_PATH)/docker-syncd-centec.mk +include $(PLATFORM_PATH)/docker-syncd-centec-rpc.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/python-saithrift.mk +include $(PLATFORM_PATH)/docker-ptf-centec.mk + +SONIC_ALL += $(SONIC_ONE_IMAGE) \ + $(DOCKER_PTF_CENTEC) \ + $(DOCKER_SYNCD_CENTEC_RPC) + +# Inject centec sai into sairedis +$(LIBSAIREDIS)_DEPENDS += $(CENTEC_SAI) $(LIBSAITHRIFT_DEV_CENTEC) + +# Runtime dependency on centec sai is set only for syncd +$(SYNCD)_RDEPENDS += $(CENTEC_SAI) diff --git a/platform/centec/sdk.mk b/platform/centec/sdk.mk new file mode 100644 index 000000000000..c529762dafc8 --- /dev/null +++ b/platform/centec/sdk.mk @@ -0,0 +1,5 @@ +# Centec SAI +CENTEC_SAI = libsai_1.3.3_amd64.deb +$(CENTEC_SAI)_URL = https://github.com/CentecNetworks/goldengate-sai/raw/master/lib/SONiC_1.3.3/libsai_1.3.3-1.0_amd64.deb + +SONIC_ONLINE_DEBS += $(CENTEC_SAI) diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/cfg/48x2q4z-modules.conf b/platform/centec/sonic-platform-modules-e582/48x2q4z/cfg/48x2q4z-modules.conf new file mode 100644 index 000000000000..7a7881c8c0d3 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/cfg/48x2q4z-modules.conf @@ -0,0 +1,14 @@ +# /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. + +i2c-i801 +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-pca954x +lm77 +adt7470 +tun diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/cfg/config_db.json b/platform/centec/sonic-platform-modules-e582/48x2q4z/cfg/config_db.json new file mode 100644 index 000000000000..3a5c8ba914b5 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/cfg/config_db.json @@ -0,0 +1,302 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": 65100, + "deployment_id": null, + "hostname": "switch1", + "type": "LeafRouter", + "hwsku": "E582-48x6q" + + } + }, + "BGP_PEER_RANGE": {}, + "VLAN": {}, + "PORT": { + "Ethernet1": { + "alias": "eth-0-1", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet2": { + "alias": "eth-0-2", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet3": { + "alias": "eth-0-3", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet4": { + "alias": "eth-0-4", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet5": { + "alias": "eth-0-5", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet6": { + "alias": "eth-0-6", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet7": { + "alias": "eth-0-7", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet8": { + "alias": "eth-0-8", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet9": { + "alias": "eth-0-9", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet10": { + "alias": "eth-0-10", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet11": { + "alias": "eth-0-11", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet12": { + "alias": "eth-0-12", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet13": { + "alias": "eth-0-13", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet14": { + "alias": "eth-0-14", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet15": { + "alias": "eth-0-15", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet16": { + "alias": "eth-0-16", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet17": { + "alias": "eth-0-17", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet18": { + "alias": "eth-0-18", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet19": { + "alias": "eth-0-19", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet20": { + "alias": "eth-0-20", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet21": { + "alias": "eth-0-21", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet22": { + "alias": "eth-0-22", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet23": { + "alias": "eth-0-23", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet24": { + "alias": "eth-0-24", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet25": { + "alias": "eth-0-25", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet26": { + "alias": "eth-0-26", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet27": { + "alias": "eth-0-27", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet28": { + "alias": "eth-0-28", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet29": { + "alias": "eth-0-29", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet30": { + "alias": "eth-0-30", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet31": { + "alias": "eth-0-31", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet32": { + "alias": "eth-0-32", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet33": { + "alias": "eth-0-33", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet34": { + "alias": "eth-0-34", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet35": { + "alias": "eth-0-35", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet36": { + "alias": "eth-0-36", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet37": { + "alias": "eth-0-37", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet38": { + "alias": "eth-0-38", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet39": { + "alias": "eth-0-39", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet40": { + "alias": "eth-0-40", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet41": { + "alias": "eth-0-41", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet42": { + "alias": "eth-0-42", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet43": { + "alias": "eth-0-43", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet44": { + "alias": "eth-0-44", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet45": { + "alias": "eth-0-45", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet46": { + "alias": "eth-0-46", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet47": { + "alias": "eth-0-47", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet48": { + "alias": "eth-0-48", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet49": { + "alias": "eth-0-49", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet50": { + "alias": "eth-0-50", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet51": { + "alias": "eth-0-51", + "speed": "100000", + "mtu": "9100" + }, + "Ethernet52": { + "alias": "eth-0-52", + "speed": "100000", + "mtu": "9100" + }, + "Ethernet53": { + "alias": "eth-0-53", + "speed": "100000", + "mtu": "9100" + }, + "Ethernet54": { + "alias": "eth-0-54", + "speed": "100000", + "mtu": "9100" + } + }, + "SYSLOG_SERVER": {}, + "VLAN_INTERFACE": {}, + "PORTCHANNEL_INTERFACE": {}, + "PORTCHANNEL": {}, + "MGMT_INTERFACE": {}, + "DHCP_SERVER": {}, + "LOOPBACK_INTERFACE": { + "Loopback0|127.0.0.1/8": {} + }, + "ACL_TABLE": {}, + "INTERFACE": { + "Ethernet1|192.168.1.1/24": {}, + "Ethernet2|192.168.2.1/24": {}, + "Ethernet3|192.168.3.1/24": {}, + "Ethernet4|192.168.4.1/24": {} + } +} diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/cfg/config_db_l2l3.json b/platform/centec/sonic-platform-modules-e582/48x2q4z/cfg/config_db_l2l3.json new file mode 100644 index 000000000000..dd40332f9049 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/cfg/config_db_l2l3.json @@ -0,0 +1,610 @@ +{ + "QUEUE": { + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54|0-2": { + "wred_profile": "[WRED_PROFILE|AZURE_LOSSY]" + }, + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54|3-4": { + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]", + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54|5-7": { + "wred_profile": "[WRED_PROFILE|AZURE_LOSSY]" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS": { + "red_max_threshold": "32760", + "yellow_max_threshold": "32760", + "green_min_threshold": "4095", + "red_min_threshold": "4095", + "yellow_min_threshold": "4095", + "green_max_threshold": "32760", + "wred_yellow_enable": "true", + "wred_green_enable": "true" + }, + "AZURE_LOSSY": { + "red_max_threshold": "32760", + "yellow_max_threshold": "32760", + "green_min_threshold": "4095", + "red_min_threshold": "4095", + "yellow_min_threshold": "4095", + "green_max_threshold": "32760", + "wred_yellow_enable": "true", + "wred_green_enable": "true" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "56": "7", + "54": "6", + "28": "3", + "48": "6", + "29": "3", + "60": "7", + "61": "7", + "62": "7", + "63": "7", + "49": "6", + "34": "4", + "24": "3", + "25": "3", + "26": "3", + "27": "3", + "20": "2", + "21": "2", + "22": "2", + "23": "2", + "46": "5", + "47": "5", + "44": "5", + "45": "5", + "42": "5", + "43": "5", + "40": "5", + "41": "5", + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "5": "0", + "4": "0", + "7": "0", + "6": "0", + "9": "1", + "8": "1", + "35": "4", + "13": "1", + "12": "1", + "15": "1", + "58": "7", + "11": "1", + "10": "1", + "39": "4", + "38": "4", + "59": "7", + "14": "1", + "17": "2", + "16": "2", + "19": "2", + "18": "2", + "31": "3", + "30": "3", + "51": "6", + "36": "4", + "53": "6", + "52": "6", + "33": "4", + "55": "6", + "37": "4", + "32": "4", + "57": "7", + "50": "6" + } + }, + "DEVICE_METADATA": { + "localhost": { + "hwsku": "E582-48x6q", + "hostname": "switch1", + "bgp_asn": "None", + "deployment_id": "None", + "type": "LeafRouter" + } + }, + "PORT": { + "Ethernet1": { + "alias": "eth-0-1", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet2": { + "alias": "eth-0-2", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet3": { + "alias": "eth-0-3", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet4": { + "alias": "eth-0-4", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet5": { + "alias": "eth-0-5", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet6": { + "alias": "eth-0-6", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet7": { + "alias": "eth-0-7", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet8": { + "alias": "eth-0-8", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet9": { + "alias": "eth-0-9", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet10": { + "alias": "eth-0-10", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet11": { + "alias": "eth-0-11", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet12": { + "alias": "eth-0-12", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet13": { + "alias": "eth-0-13", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet14": { + "alias": "eth-0-14", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet15": { + "alias": "eth-0-15", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet16": { + "alias": "eth-0-16", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet17": { + "alias": "eth-0-17", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet18": { + "alias": "eth-0-18", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet19": { + "alias": "eth-0-19", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet20": { + "alias": "eth-0-20", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet21": { + "alias": "eth-0-21", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet22": { + "alias": "eth-0-22", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet23": { + "alias": "eth-0-23", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet24": { + "alias": "eth-0-24", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet25": { + "alias": "eth-0-25", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet26": { + "alias": "eth-0-26", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet27": { + "alias": "eth-0-27", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet28": { + "alias": "eth-0-28", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet29": { + "alias": "eth-0-29", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet30": { + "alias": "eth-0-30", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet31": { + "alias": "eth-0-31", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet32": { + "alias": "eth-0-32", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet33": { + "alias": "eth-0-33", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet34": { + "alias": "eth-0-34", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet35": { + "alias": "eth-0-35", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet36": { + "alias": "eth-0-36", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet37": { + "alias": "eth-0-37", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet38": { + "alias": "eth-0-38", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet39": { + "alias": "eth-0-39", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet40": { + "alias": "eth-0-40", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet41": { + "alias": "eth-0-41", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet42": { + "alias": "eth-0-42", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet43": { + "alias": "eth-0-43", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet44": { + "alias": "eth-0-44", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet45": { + "alias": "eth-0-45", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet46": { + "alias": "eth-0-46", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet47": { + "alias": "eth-0-47", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet48": { + "alias": "eth-0-48", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet49": { + "alias": "eth-0-49", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet50": { + "alias": "eth-0-50", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet51": { + "alias": "eth-0-51", + "speed": "100000", + "mtu": "9100" + }, + "Ethernet52": { + "alias": "eth-0-52", + "speed": "100000", + "mtu": "9100" + }, + "Ethernet53": { + "alias": "eth-0-53", + "speed": "100000", + "mtu": "9100" + }, + "Ethernet54": { + "alias": "eth-0-54", + "speed": "100000", + "mtu": "9100" + } + }, + "PORT_QOS_MAP": { + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54": { + "pfc_enable": "3,4", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP|AZURE]" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type": "DWRR", + "weight": "25" + }, + "scheduler.1": { + "type": "DWRR", + "weight": "30" + }, + "scheduler.2": { + "type": "DWRR", + "weight": "20" + } + }, + "VLAN": { + "Vlan500": { + "dhcp_servers": [ + "192.168.5.1", + "192.168.5.2", + "192.168.5.3", + "192.168.5.4" + ], + "members": [ + "Ethernet5", + "Ethernet6", + "Ethernet7", + "Ethernet8" + ], + "vlanid": "500" + }, + "Vlan600": { + "dhcp_servers": [ + "192.168.6.1", + "192.168.6.2", + "192.168.6.3", + "192.168.6.4" + ], + "members": [ + "Ethernet5", + "Ethernet6" + ], + "vlanid": "600" + }, + "Vlan700": { + "dhcp_servers": [ + "192.168.7.1", + "192.168.7.2", + "192.168.7.3", + "192.168.7.4" + ], + "members": [ + "Ethernet5", + "Ethernet7" + ], + "vlanid": "700" + }, + "Vlan800": { + "dhcp_servers": [ + "192.168.8.1", + "192.168.8.2", + "192.168.8.3", + "192.168.8.4" + ], + "members": [ + "Ethernet5", + "Ethernet8" + ], + "vlanid": "800" + } + }, + "VLAN_MEMBER": { + "Vlan500|Ethernet5": { + "tagging_mode": "tagged" + }, + "Vlan500|Ethernet6": { + "tagging_mode": "untagged" + }, + "Vlan500|Ethernet7": { + "tagging_mode": "untagged" + }, + "Vlan500|Ethernet8": { + "tagging_mode": "untagged" + }, + "Vlan600|Ethernet5": { + "tagging_mode": "tagged" + }, + "Vlan600|Ethernet6": { + "tagging_mode": "tagged" + }, + "Vlan700|Ethernet5": { + "tagging_mode": "tagged" + }, + "Vlan700|Ethernet7": { + "tagging_mode": "tagged" + }, + "Vlan800|Ethernet5": { + "tagging_mode": "tagged" + }, + "Vlan800|Ethernet8": { + "tagging_mode": "tagged" + } + }, + "INTERFACE": { + "Ethernet1|192.168.1.1/24": {}, + "Ethernet2|192.168.2.1/24": {}, + "Ethernet3|192.168.3.1/24": {}, + "Ethernet4|192.168.4.1/24": {} + }, + "VLAN_INTERFACE": { + "Vlan500|192.168.5.1/24": {}, + "Vlan600|192.168.6.1/24": {}, + "Vlan700|192.168.7.1/24": {}, + "Vlan800|192.168.8.1/24": {} + }, + "LOOPBACK_INTERFACE": { + "Loopback0|127.0.0.1/8": {} + }, + "CABLE_LENGTH": { + "AZURE": { + "Ethernet8": "40m", + "Ethernet9": "40m", + "Ethernet2": "40m", + "Ethernet3": "40m", + "Ethernet1": "40m", + "Ethernet6": "40m", + "Ethernet7": "40m", + "Ethernet4": "40m", + "Ethernet5": "40m", + "Ethernet22": "40m", + "Ethernet50": "40m", + "Ethernet51": "40m", + "Ethernet52": "40m", + "Ethernet53": "40m", + "Ethernet54": "40m", + "Ethernet38": "40m", + "Ethernet39": "40m", + "Ethernet18": "40m", + "Ethernet19": "40m", + "Ethernet14": "40m", + "Ethernet15": "40m", + "Ethernet16": "40m", + "Ethernet17": "40m", + "Ethernet10": "40m", + "Ethernet11": "40m", + "Ethernet12": "40m", + "Ethernet35": "40m", + "Ethernet37": "40m", + "Ethernet32": "40m", + "Ethernet33": "40m", + "Ethernet30": "40m", + "Ethernet31": "40m", + "Ethernet49": "40m", + "Ethernet48": "40m", + "Ethernet47": "40m", + "Ethernet36": "40m", + "Ethernet45": "40m", + "Ethernet44": "40m", + "Ethernet43": "40m", + "Ethernet42": "40m", + "Ethernet41": "40m", + "Ethernet40": "40m", + "Ethernet29": "40m", + "Ethernet28": "40m", + "Ethernet34": "40m", + "Ethernet46": "40m", + "Ethernet21": "40m", + "Ethernet20": "40m", + "Ethernet23": "40m", + "Ethernet13": "40m", + "Ethernet25": "40m", + "Ethernet24": "40m", + "Ethernet27": "40m", + "Ethernet26": "40m" + } + }, + "CRM": { + "Config": { + "acl_table_threshold_type": "percentage", + "nexthop_group_threshold_type": "percentage", + "fdb_entry_high_threshold": "85", + "acl_entry_threshold_type": "percentage", + "ipv6_neighbor_low_threshold": "70", + "nexthop_group_member_low_threshold": "70", + "acl_group_high_threshold": "85", + "ipv4_route_high_threshold": "85", + "acl_counter_high_threshold": "85", + "ipv4_route_low_threshold": "70", + "ipv4_route_threshold_type": "percentage", + "ipv4_neighbor_low_threshold": "70", + "acl_group_threshold_type": "percentage", + "ipv4_nexthop_high_threshold": "85", + "ipv6_route_threshold_type": "percentage", + "nexthop_group_low_threshold": "70", + "ipv4_neighbor_high_threshold": "85", + "ipv6_route_high_threshold": "85", + "ipv6_nexthop_threshold_type": "percentage", + "polling_interval": "300", + "ipv4_nexthop_threshold_type": "percentage", + "acl_group_low_threshold": "70", + "acl_entry_low_threshold": "70", + "nexthop_group_member_threshold_type": "percentage", + "ipv4_nexthop_low_threshold": "70", + "acl_counter_threshold_type": "percentage", + "ipv6_neighbor_high_threshold": "85", + "nexthop_group_member_high_threshold": "85", + "acl_table_low_threshold": "70", + "fdb_entry_threshold_type": "percentage", + "ipv6_neighbor_threshold_type": "percentage", + "acl_table_high_threshold": "85", + "ipv6_nexthop_low_threshold": "70", + "acl_counter_low_threshold": "70", + "ipv4_neighbor_threshold_type": "percentage", + "nexthop_group_high_threshold": "85", + "ipv6_route_low_threshold": "70", + "acl_entry_high_threshold": "85", + "fdb_entry_low_threshold": "70", + "ipv6_nexthop_high_threshold": "85" + } + } +} diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/Makefile b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/Makefile new file mode 100644 index 000000000000..d1ca9824aa9e --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := centec_e582_48x2q4z_platform.o dal.o centec_at24c64.o +dal-y := dal_kernel.o dal_mpool.o diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/centec_at24c64.c b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/centec_at24c64.c new file mode 100644 index 000000000000..e1835df88625 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/centec_at24c64.c @@ -0,0 +1,602 @@ +/* + * at24.c - handle most I2C EEPROMs + * + * Copyright (C) 2005-2007 David Brownell + * Copyright (C) 2008 Wolfram Sang, Pengutronix + * + * 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 +#include +#include +#include +#include + +/* + * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. + * Differences between different vendor product lines (like Atmel AT24C or + * MicroChip 24LC, etc) won't much matter for typical read/write access. + * There are also I2C RAM chips, likewise interchangeable. One example + * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes). + * + * However, misconfiguration can lose data. "Set 16-bit memory address" + * to a part with 8-bit addressing will overwrite data. Writing with too + * big a page size also loses data. And it's not safe to assume that the + * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC + * uses 0x51, for just one example. + * + * Accordingly, explicit board-specific configuration data should be used + * in almost all cases. (One partial exception is an SMBus used to access + * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.) + * + * So this driver uses "new style" I2C driver binding, expecting to be + * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or + * similar kernel-resident tables; or, configuration data coming from + * a bootloader. + * + * Other than binding model, current differences from "eeprom" driver are + * that this one handles write access and isn't restricted to 24c02 devices. + * It also handles larger devices (32 kbit and up) with two-byte addresses, + * which won't work on pure SMBus systems. + */ + +struct at24_data { + struct at24_platform_data chip; + int use_smbus; + + /* + * Lock protects against activities from other Linux tasks, + * but not from changes by other I2C masters. + */ + struct mutex lock; + struct bin_attribute bin; + + u8 *writebuf; + unsigned write_max; + unsigned num_addresses; + + /* + * Some chips tie up multiple I2C addresses; dummy devices reserve + * them for us, and we'll use them with SMBus calls. + */ + struct i2c_client *client[]; +}; + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = 128; +module_param(io_limit, uint, 0); +MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)"); + +/* + * Specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; +module_param(write_timeout, uint, 0); +MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)"); + +#define AT24_SIZE_BYTELEN 5 +#define AT24_SIZE_FLAGS 8 + +#define AT24_BITMASK(x) (BIT(x) - 1) + +/* create non-zero magic value for given eeprom parameters */ +#define AT24_DEVICE_MAGIC(_len, _flags) \ + ((1 << AT24_SIZE_FLAGS | (_flags)) \ + << AT24_SIZE_BYTELEN | ilog2(_len)) + +static const struct i2c_device_id at24_ctc_ids[] = { + { "24c64-ctc", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16 | AT24_FLAG_READONLY | AT24_FLAG_IRUGO) }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, at24_ctc_ids); + +/*-------------------------------------------------------------------------*/ + +/* + * This routine supports chips which consume multiple I2C addresses. It + * computes the addressing information to be used for a given r/w request. + * Assumes that sanity checks for offset happened at sysfs-layer. + */ +static struct i2c_client *at24_translate_offset(struct at24_data *at24, + unsigned *offset) +{ + unsigned i = 0; + + if (at24->chip.flags & AT24_FLAG_ADDR16) { + i = *offset >> 16; + *offset &= 0xffff; + } else { + i = *offset >> 8; + *offset &= 0xff; + } + + return at24->client[i]; +} + +static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, + unsigned offset, size_t count) +{ + struct i2c_msg msg[2]; + struct i2c_client *client; + unsigned long timeout, read_time; + int status; + + memset(msg, 0, sizeof(msg)); + + /* + * REVISIT some multi-address chips don't rollover page reads to + * the next slave address, so we may need to truncate the count. + * Those chips might need another quirk flag. + * + * If the real hardware used four adjacent 24c02 chips and that + * were misconfigured as one 24c08, that would be a similar effect: + * one "eeprom" file not four, but larger reads would fail when + * they crossed certain pages. + */ + + /* + * Slave address and byte offset derive from the offset. Always + * set the byte address; on a multi-master board, another master + * may have changed the chip's "current" address pointer. + */ + client = at24_translate_offset(at24, &offset); + + if (count > io_limit) + count = io_limit; + + count = 1; + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + read_time = jiffies; + + status = i2c_smbus_write_byte_data(client, (offset >> 8) & 0x0ff, offset & 0x0ff ); + status = i2c_smbus_read_byte(client); + if (status >= 0) { + buf[0] = status; + status = count; + } + + dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", count, offset, status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(read_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t at24_read(struct at24_data *at24, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) + return count; + + memset(buf, 0, count); + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + ssize_t status; + + status = at24_eeprom_read(at24, buf, off, count); + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&at24->lock); + + return retval; +} + +static ssize_t at24_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct at24_data *at24; + + at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return at24_read(at24, buf, off, count); +} + + +/* + * Note that if the hardware write-protect pin is pulled high, the whole + * chip is normally write protected. But there are plenty of product + * variants here, including OTP fuses and partial chip protect. + * + * We only use page mode writes; the alternative is sloooow. This routine + * writes at most one page. + */ +static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + unsigned offset, size_t count) +{ + struct i2c_client *client; + ssize_t status; + unsigned long timeout, write_time; + unsigned next_page; + + /* Get corresponding I2C address and adjust offset */ + client = at24_translate_offset(at24, &offset); + + /* write_max is at most a page */ + if (count > at24->write_max) + count = at24->write_max; + + /* Never roll over backwards, to the start of this page */ + next_page = roundup(offset + 1, at24->chip.page_size); + if (offset + count > next_page) + count = next_page - offset; + + /* + * Writes fail if the previous one didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; + + status = i2c_smbus_write_word_data(client, (offset >> 8) & 0x0ff, (offset & 0xFF) | buf[0]); + if (status == 0) + status = count; + + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", count, offset, status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(write_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off, + size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) + return count; + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + ssize_t status; + + status = at24_eeprom_write(at24, buf, off, 1); /* only one-byte to write; TODO page wirte */ + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&at24->lock); + + return retval; +} + +static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct at24_data *at24; + + if (unlikely(off >= attr->size)) + return -EFBIG; + + at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return at24_write(at24, buf, off, count); +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_OF +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ + const __be32 *val; + struct device_node *node = client->dev.of_node; + + if (node) { + if (of_get_property(node, "read-only", NULL)) + chip->flags |= AT24_FLAG_READONLY; + val = of_get_property(node, "pagesize", NULL); + if (val) + chip->page_size = be32_to_cpup(val); + } +} +#else +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ } +#endif /* CONFIG_OF */ + +static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct at24_platform_data chip; + bool writable; + int use_smbus = 0; + struct at24_data *at24; + int err; + unsigned i, num_addresses; + kernel_ulong_t magic; + + if (client->dev.platform_data) { + chip = *(struct at24_platform_data *)client->dev.platform_data; + } else { + if (!id->driver_data) + return -ENODEV; + + magic = id->driver_data; + chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); + magic >>= AT24_SIZE_BYTELEN; + chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); + + /* + * This is slow, but we can't know all eeproms, so we better + * play safe. Specifying custom eeprom-types via platform_data + * is recommended anyhow. + */ + chip.page_size = 1; + + /* update chipdata if OF is present */ + at24_get_ofdata(client, &chip); + + chip.setup = NULL; + chip.context = NULL; + } + + if (!is_power_of_2(chip.byte_len)) + dev_warn(&client->dev, + "byte_len looks suspicious (no power of 2)!\n"); + if (!chip.page_size) { + dev_err(&client->dev, "page_size must not be 0!\n"); + return -EINVAL; + } + if (!is_power_of_2(chip.page_size)) + dev_warn(&client->dev, + "page_size looks suspicious (no power of 2)!\n"); + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) { + use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + return -EPFNOSUPPORT; + } + use_smbus = I2C_SMBUS_BYTE_DATA; + } + + if (chip.flags & AT24_FLAG_TAKE8ADDR) + num_addresses = 8; + else + num_addresses = DIV_ROUND_UP(chip.byte_len, (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); + + at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) + num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); + if (!at24) + return -ENOMEM; + + mutex_init(&at24->lock); + at24->use_smbus = use_smbus; + at24->chip = chip; + at24->num_addresses = num_addresses; + + printk(KERN_ALERT "at24_probe chip.byte_len = 0x%x\n", chip.byte_len); + printk(KERN_ALERT "at24_probe chip.flags = 0x%x\n", chip.flags); + printk(KERN_ALERT "at24_probe chip.magic = 0x%lx\n", id->driver_data); + printk(KERN_ALERT "at24_probe use_smbus = %d\n", at24->use_smbus); + printk(KERN_ALERT "at24_probe num_addresses = %d\n", at24->num_addresses); + + /* + * Export the EEPROM bytes through sysfs, since that's convenient. + * By default, only root should see the data (maybe passwords etc) + */ + sysfs_bin_attr_init(&at24->bin); + at24->bin.attr.name = "eeprom"; + at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR; + at24->bin.read = at24_bin_read; + at24->bin.size = chip.byte_len; + + writable = !(chip.flags & AT24_FLAG_READONLY); + if (writable) { + if (!use_smbus || i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { + unsigned write_max = chip.page_size; + + at24->bin.write = at24_bin_write; + at24->bin.attr.mode |= S_IWUSR; + + if (write_max > io_limit) + write_max = io_limit; + if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + at24->write_max = write_max; + + /* buffer (data + address at the beginning) */ + at24->writebuf = devm_kzalloc(&client->dev, write_max + 2, GFP_KERNEL); + if (!at24->writebuf) + return -ENOMEM; + } else { + dev_warn(&client->dev, "cannot write due to controller restrictions."); + } + } + + at24->client[0] = client; + + /* use dummy devices for multiple-address chips */ + for (i = 1; i < num_addresses; i++) { + at24->client[i] = i2c_new_dummy(client->adapter, client->addr + i); + if (!at24->client[i]) { + dev_err(&client->dev, "address 0x%02x unavailable\n", client->addr + i); + err = -EADDRINUSE; + goto err_clients; + } + } + + err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin); + if (err) + goto err_clients; + + i2c_set_clientdata(client, at24); + + printk(KERN_ALERT "at24_probe %s done\n", client->name); + + return 0; + +err_clients: + for (i = 1; i < num_addresses; i++) + if (at24->client[i]) + i2c_unregister_device(at24->client[i]); + + return err; +} + +static int at24_remove(struct i2c_client *client) +{ + struct at24_data *at24; + int i; + + at24 = i2c_get_clientdata(client); + sysfs_remove_bin_file(&client->dev.kobj, &at24->bin); + + for (i = 1; i < at24->num_addresses; i++) + i2c_unregister_device(at24->client[i]); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct i2c_board_info i2c_devs = { + I2C_BOARD_INFO("24c64-ctc", 0x57), +}; + +static struct i2c_adapter *adapter = NULL; +static struct i2c_client *client = NULL; + +static int ctc_at24c64_init(void) +{ + printk(KERN_ALERT "ctc_at24c64_init\n"); + + adapter = i2c_get_adapter(0); + if(adapter == NULL){ + printk(KERN_ALERT "i2c_get_adapter == NULL\n"); + return -1; + } + + client = i2c_new_device(adapter, &i2c_devs); + if(client == NULL){ + printk(KERN_ALERT "i2c_new_device == NULL\n"); + i2c_put_adapter(adapter); + adapter = NULL; + return -1; + } + + return 0; +} + +static void ctc_at24c64_exit(void) +{ + printk(KERN_ALERT "ctc_at24c64_exit\n"); + if(client){ + i2c_unregister_device(client); + } + if(adapter){ + i2c_put_adapter(adapter); + } +} + +static struct i2c_driver at24_ctc_driver = { + .driver = { + .name = "at24-ctc", + .owner = THIS_MODULE, + }, + .probe = at24_probe, + .remove = at24_remove, + .id_table = at24_ctc_ids, +}; + +static int __init at24_ctc_init(void) +{ + if (!io_limit) { + pr_err("at24_ctc: io_limit must not be 0!\n"); + return -EINVAL; + } + + io_limit = rounddown_pow_of_two(io_limit); + + ctc_at24c64_init(); + + return i2c_add_driver(&at24_ctc_driver); +} +module_init(at24_ctc_init); + +static void __exit at24_ctc_exit(void) +{ + ctc_at24c64_exit(); + i2c_del_driver(&at24_ctc_driver); +} +module_exit(at24_ctc_exit); + +MODULE_DESCRIPTION("Driver for most I2C EEPROMs"); +MODULE_AUTHOR("David Brownell and Wolfram Sang"); +MODULE_LICENSE("GPL"); +/* XXX */ + diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/centec_e582_48x2q4z_platform.c b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/centec_e582_48x2q4z_platform.c new file mode 100644 index 000000000000..16bed86593b2 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/centec_e582_48x2q4z_platform.c @@ -0,0 +1,1457 @@ +#include +#include +#include +#include +#include +#include +#include + +#define SEP(XXX) 1 +#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) +#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) + +#if SEP("defines") +#define PCA9548_CHANNEL_NUM 8 +#define PCA9548_ADAPT_ID_START 10 +#define SFP_NUM 48 +#define QSFP_NUM 6 +#define PORT_NUM (SFP_NUM+QSFP_NUM) +#endif + +#if SEP("i2c:master") +static struct i2c_adapter *i2c_adp_master = NULL; /* i2c-0-cpu */ + +static int e582_48x2q4z_init_i2c_master(void) +{ + /* find i2c-core master */ + i2c_adp_master = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e582_48x2q4z_init_i2c_master can't find i2c-core bus\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_i2c_master(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_adp_master)) { + i2c_put_adapter(i2c_adp_master); + i2c_adp_master = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:pca9548") +static struct pca954x_platform_mode i2c_dev_pca9548_platform_mode[PCA9548_CHANNEL_NUM] = { + [0] = { + .adap_id = PCA9548_ADAPT_ID_START, + .deselect_on_exit = 1, + .class = 0, + }, + [1] = { + .adap_id = PCA9548_ADAPT_ID_START + 1, + .deselect_on_exit = 1, + .class = 0, + }, + [2] = { + .adap_id = PCA9548_ADAPT_ID_START + 2, + .deselect_on_exit = 1, + .class = 0, + }, + [3] = { + .adap_id = PCA9548_ADAPT_ID_START + 3, + .deselect_on_exit = 1, + .class = 0, + }, + [4] = { + .adap_id = PCA9548_ADAPT_ID_START + 4, + .deselect_on_exit = 1, + .class = 0, + }, + [5] = { + .adap_id = PCA9548_ADAPT_ID_START + 5, + .deselect_on_exit = 1, + .class = 0, + }, + [6] = { + .adap_id = PCA9548_ADAPT_ID_START + 6, + .deselect_on_exit = 1, + .class = 0, + }, + [7] = { + .adap_id = PCA9548_ADAPT_ID_START + 7, + .deselect_on_exit = 1, + .class = 0, + } +}; +static struct pca954x_platform_data i2c_dev_pca9548_platform_data = { + .modes = i2c_dev_pca9548_platform_mode, + .num_modes = PCA9548_CHANNEL_NUM, +}; +static struct i2c_board_info i2c_dev_pca9548 = { + I2C_BOARD_INFO("pca9548", 0x70), + .platform_data = &i2c_dev_pca9548_platform_data, +}; +static struct i2c_client *i2c_client_pca9548x = NULL; + +static int e582_48x2q4z_init_i2c_pca9548(void) +{ + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e582_48x2q4z_init_i2c_pca9548 can't find i2c-core bus\n"); + return -1; + } + + /* install i2c-mux */ + i2c_client_pca9548x = i2c_new_device(i2c_adp_master, &i2c_dev_pca9548); + if(IS_INVALID_PTR(i2c_client_pca9548x)) + { + i2c_client_pca9548x = NULL; + printk(KERN_CRIT "install e582_48x2q4z board pca9548 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_i2c_pca9548(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_client_pca9548x)) { + i2c_unregister_device(i2c_client_pca9548x); + i2c_client_pca9548x = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:adt7470") +static struct i2c_board_info i2c_dev_adt7470 = { + I2C_BOARD_INFO("adt7470", 0x2F), +}; +static struct i2c_adapter *i2c_adp_adt7470 = NULL; /* pca9548x-channel 4 */ +static struct i2c_client *i2c_client_adt7470 = NULL; + +static int e582_48x2q4z_init_i2c_adt7470(void) +{ + i2c_adp_adt7470 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 4); + if(IS_INVALID_PTR(i2c_adp_adt7470)) + { + i2c_adp_adt7470 = NULL; + printk(KERN_CRIT "install e582_48x2q4z board adt7470 failed\n"); + return -1; + } + + i2c_client_adt7470 = i2c_new_device(i2c_adp_adt7470, &i2c_dev_adt7470); + if(IS_INVALID_PTR(i2c_client_adt7470)){ + i2c_client_adt7470 = NULL; + printk(KERN_CRIT "install e582_48x2q4z board adt7470 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_i2c_adt7470(void) +{ + if(IS_VALID_PTR(i2c_client_adt7470)) { + i2c_unregister_device(i2c_client_adt7470); + i2c_client_adt7470 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_adt7470)) { + i2c_put_adapter(i2c_adp_adt7470); + i2c_adp_adt7470 = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:psu") +static struct i2c_adapter *i2c_adp_psu1 = NULL; /* psu1 channel 1 */ +static struct i2c_adapter *i2c_adp_psu2 = NULL; /* psu2 channel 0 */ +static struct i2c_board_info i2c_dev_psu1 = { + I2C_BOARD_INFO("i2c-psu1", 0x38), +}; +static struct i2c_board_info i2c_dev_psu2 = { + I2C_BOARD_INFO("i2c-psu2", 0x38), +}; +static struct i2c_client *i2c_client_psu1 = NULL; +static struct i2c_client *i2c_client_psu2 = NULL; + +static int e582_48x2q4z_init_i2c_psu(void) +{ + i2c_adp_psu1 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 1); + if(IS_INVALID_PTR(i2c_adp_psu1)) + { + i2c_adp_psu1 = NULL; + printk(KERN_CRIT "get e582_48x2q4z psu1 i2c-adp failed\n"); + return -1; + } + + i2c_adp_psu2 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 0); + if(IS_INVALID_PTR(i2c_adp_psu2)) + { + i2c_adp_psu2 = NULL; + printk(KERN_CRIT "get e582_48x2q4z psu2 i2c-adp failed\n"); + return -1; + } + + i2c_client_psu1 = i2c_new_device(i2c_adp_psu1, &i2c_dev_psu1); + if(IS_INVALID_PTR(i2c_client_psu1)){ + i2c_client_psu1 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client psu1 failed\n"); + return -1; + } + + i2c_client_psu2 = i2c_new_device(i2c_adp_psu2, &i2c_dev_psu2); + if(IS_INVALID_PTR(i2c_client_psu2)){ + i2c_client_psu2 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client psu2 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_i2c_psu(void) +{ + if(IS_VALID_PTR(i2c_client_psu1)) { + i2c_unregister_device(i2c_client_psu1); + i2c_client_psu1 = NULL; + } + + if(IS_VALID_PTR(i2c_client_psu2)) { + i2c_unregister_device(i2c_client_psu2); + i2c_client_psu2 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_psu1)) + { + i2c_put_adapter(i2c_adp_psu1); + i2c_adp_psu1 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_psu2)) + { + i2c_put_adapter(i2c_adp_psu2); + i2c_adp_psu2 = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:epld") +static struct i2c_board_info i2c_dev_epld = { + I2C_BOARD_INFO("i2c-epld", 0x58), +}; +static struct i2c_client *i2c_client_epld = NULL; + +static int e582_48x2q4z_init_i2c_epld(void) +{ + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e582_48x2q4z_init_i2c_epld can't find i2c-core bus\n"); + return -1; + } + + i2c_client_epld = i2c_new_device(i2c_adp_master, &i2c_dev_epld); + if(IS_INVALID_PTR(i2c_client_epld)) + { + i2c_client_epld = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client epld failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_i2c_epld(void) +{ + if(IS_VALID_PTR(i2c_client_epld)) { + i2c_unregister_device(i2c_client_epld); + i2c_client_epld = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:gpio") +static struct i2c_adapter *i2c_adp_gpio0 = NULL; /* gpio0 channel 5 */ +static struct i2c_adapter *i2c_adp_gpio1 = NULL; /* gpio1 channel 5 */ +static struct i2c_adapter *i2c_adp_gpio2 = NULL; /* gpio2 channel 5 */ +static struct i2c_adapter *i2c_adp_gpio3 = NULL; /* gpio3 channel 6 */ +static struct i2c_adapter *i2c_adp_gpio4 = NULL; /* gpio4 channel 7 */ +static struct i2c_board_info i2c_dev_gpio0 = { + I2C_BOARD_INFO("i2c-gpio0", 0x21), +}; +static struct i2c_board_info i2c_dev_gpio1 = { + I2C_BOARD_INFO("i2c-gpio1", 0x22), +}; +static struct i2c_board_info i2c_dev_gpio2 = { + I2C_BOARD_INFO("i2c-gpio2", 0x23), +}; +static struct i2c_board_info i2c_dev_gpio3 = { + I2C_BOARD_INFO("i2c-gpio3", 0x21), +}; +static struct i2c_board_info i2c_dev_gpio4 = { + I2C_BOARD_INFO("i2c-gpio4", 0x22), +}; +static struct i2c_client *i2c_client_gpio0 = NULL; +static struct i2c_client *i2c_client_gpio1 = NULL; +static struct i2c_client *i2c_client_gpio2 = NULL; +static struct i2c_client *i2c_client_gpio3 = NULL; +static struct i2c_client *i2c_client_gpio4 = NULL; + +static int e582_48x2q4z_init_i2c_gpio(void) +{ + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e582_48x2q4z_init_i2c_gpio can't find i2c-core bus\n"); + return -1; + } + + i2c_adp_gpio0 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 5); + if(IS_INVALID_PTR(i2c_adp_gpio0)) + { + i2c_adp_gpio0 = NULL; + printk(KERN_CRIT "get e582_48x2q4z gpio0 i2c-adp failed\n"); + return -1; + } + + i2c_adp_gpio1 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 5); + if(IS_INVALID_PTR(i2c_adp_gpio1)) + { + i2c_adp_gpio1 = NULL; + printk(KERN_CRIT "get e582_48x2q4z gpio1 i2c-adp failed\n"); + return -1; + } + + i2c_adp_gpio2 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 5); + if(IS_INVALID_PTR(i2c_adp_gpio2)) + { + i2c_adp_gpio2 = NULL; + printk(KERN_CRIT "get e582_48x2q4z gpio2 i2c-adp failed\n"); + return -1; + } + + i2c_adp_gpio3 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 6); + if(IS_INVALID_PTR(i2c_adp_gpio3)) + { + i2c_adp_gpio3 = NULL; + printk(KERN_CRIT "get e582_48x2q4z gpio3 i2c-adp failed\n"); + return -1; + } + + i2c_adp_gpio4 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 7); + if(IS_INVALID_PTR(i2c_adp_gpio4)) + { + i2c_adp_gpio4 = NULL; + printk(KERN_CRIT "get e582_48x2q4z gpio4 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio0 = i2c_new_device(i2c_adp_gpio0, &i2c_dev_gpio0); + if(IS_INVALID_PTR(i2c_client_gpio0)) + { + i2c_client_gpio0 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client gpio0 failed\n"); + return -1; + } + + i2c_client_gpio1 = i2c_new_device(i2c_adp_gpio1, &i2c_dev_gpio1); + if(IS_INVALID_PTR(i2c_client_gpio1)) + { + i2c_client_gpio1 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client gpio1 failed\n"); + return -1; + } + + i2c_client_gpio2 = i2c_new_device(i2c_adp_gpio2, &i2c_dev_gpio2); + if(IS_INVALID_PTR(i2c_client_gpio2)) + { + i2c_client_gpio2 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client gpio2 failed\n"); + return -1; + } + + i2c_client_gpio3 = i2c_new_device(i2c_adp_gpio3, &i2c_dev_gpio3); + if(IS_INVALID_PTR(i2c_client_gpio3)) + { + i2c_client_gpio3 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client gpio3 failed\n"); + return -1; + } + + i2c_client_gpio4 = i2c_new_device(i2c_adp_gpio4, &i2c_dev_gpio4); + if(IS_INVALID_PTR(i2c_client_gpio4)) + { + i2c_client_gpio4 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client gpio4 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_i2c_gpio(void) +{ + if(IS_VALID_PTR(i2c_client_gpio0)) { + i2c_unregister_device(i2c_client_gpio0); + i2c_client_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio1)) { + i2c_unregister_device(i2c_client_gpio1); + i2c_client_gpio1 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio2)) { + i2c_unregister_device(i2c_client_gpio2); + i2c_client_gpio2 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio3)) { + i2c_unregister_device(i2c_client_gpio3); + i2c_client_gpio3 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio4)) { + i2c_unregister_device(i2c_client_gpio4); + i2c_client_gpio4 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio0)) + { + i2c_put_adapter(i2c_adp_gpio0); + i2c_adp_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio1)) + { + i2c_put_adapter(i2c_adp_gpio1); + i2c_adp_gpio1 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio2)) + { + i2c_put_adapter(i2c_adp_gpio2); + i2c_adp_gpio2 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio3)) + { + i2c_put_adapter(i2c_adp_gpio3); + i2c_adp_gpio3 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio4)) + { + i2c_put_adapter(i2c_adp_gpio4); + i2c_adp_gpio4 = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:smbus") +static int e582_48x2q4z_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret >= 0) { + *value = (unsigned char)ret; + } + else + { + *value = 0; + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} + +static int e582_48x2q4z_smbus_write_reg(struct i2c_client *client, unsigned char reg, unsigned char value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_write_byte_data(client, reg, value); + if (ret != 0) + { + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} +#endif + +#if SEP("drivers:psu") +static struct class* psu_class = NULL; +static struct device* psu_dev_psu1 = NULL; +static struct device* psu_dev_psu2 = NULL; + +static ssize_t e582_48x2q4z_psu_read_presence(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char present_no = 0; + unsigned char present = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio2; + present_no = 30; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio2; + present_no = 29; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e582_48x2q4z_smbus_read_reg(i2c_psu_client, present_no/8, &present); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((present & (1<<(present_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e582_48x2q4z_psu_read_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char workstate_no = 0; + unsigned char workstate = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio2; + workstate_no = 36; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio2; + workstate_no = 35; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e582_48x2q4z_smbus_read_reg(i2c_psu_client, workstate_no/8, &workstate); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((workstate & (1<<(workstate_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static DEVICE_ATTR(psu_presence, S_IRUGO, e582_48x2q4z_psu_read_presence, NULL); +static DEVICE_ATTR(psu_status, S_IRUGO, e582_48x2q4z_psu_read_status, NULL); + +static int e582_48x2q4z_init_psu(void) +{ + int ret = 0; + + psu_class = class_create(THIS_MODULE, "psu"); + if (IS_INVALID_PTR(psu_class)) + { + psu_class = NULL; + printk(KERN_CRIT "create e582_48x2q4z class psu failed\n"); + return -1; + } + + psu_dev_psu1 = device_create(psu_class, NULL, MKDEV(222,0), NULL, "psu1"); + if (IS_INVALID_PTR(psu_dev_psu1)) + { + psu_dev_psu1 = NULL; + printk(KERN_CRIT "create e582_48x2q4z psu1 device failed\n"); + return -1; + } + + psu_dev_psu2 = device_create(psu_class, NULL, MKDEV(222,1), NULL, "psu2"); + if (IS_INVALID_PTR(psu_dev_psu2)) + { + psu_dev_psu2 = NULL; + printk(KERN_CRIT "create e582_48x2q4z psu2 device failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z psu1 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z psu1 device attr:status failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z psu2 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z psu2 device attr:status failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_psu(void) +{ + if (IS_VALID_PTR(psu_dev_psu1)) + { + device_remove_file(psu_dev_psu1, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu1, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,0)); + } + + if (IS_VALID_PTR(psu_dev_psu2)) + { + device_remove_file(psu_dev_psu2, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu2, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,1)); + } + + if (IS_VALID_PTR(psu_class)) + { + class_destroy(psu_class); + psu_class = NULL; + } + + return 0; +} +#endif + +#if SEP("drivers:leds") +extern void e582_48x2q4z_led_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e582_48x2q4z_led_get(struct led_classdev *led_cdev); +extern void e582_48x2q4z_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e582_48x2q4z_led_port_get(struct led_classdev *led_cdev); + +static struct led_classdev led_dev_system = { + .name = "system", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_idn = { + .name = "idn", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_fan1 = { + .name = "fan1", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_fan2 = { + .name = "fan2", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_fan3 = { + .name = "fan3", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_fan4 = { + .name = "fan4", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_psu1 = { + .name = "psu1", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_psu2 = { + .name = "psu2", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_port[PORT_NUM] = { +{ .name = "port1", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port2", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port3", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port4", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port5", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port6", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port7", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port8", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port9", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port10", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port11", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port12", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port13", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port14", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port15", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port16", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port17", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port18", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port19", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port20", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port21", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port22", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port23", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port24", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port25", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port26", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port27", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port28", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port29", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port30", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port31", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port32", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port33", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port34", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port35", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port36", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port37", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port38", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port39", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port40", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port41", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port42", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port43", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port44", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port45", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port46", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port47", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port48", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port49", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port50", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port51", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port52", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port53", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port54", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,} +}; +static unsigned char port_led_mode[PORT_NUM] = {0}; + +void e582_48x2q4z_led_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_epld; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x0F; + shift = 4; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x3; + mask = 0xFE; + shift = 0; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e582_48x2q4z_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return; + } + + led_value = ((led_value & mask) | ((set_value << shift) & (~mask))); + + ret = e582_48x2q4z_smbus_write_reg(i2c_led_client, reg, led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s led attr failed\n", led_cdev->name); + return; + } + + return; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return; +} + +enum led_brightness e582_48x2q4z_led_get(struct led_classdev *led_cdev) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_epld; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0xF0; + shift = 4; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x3; + mask = 0x01; + shift = 0; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e582_48x2q4z_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return 0; + } + + led_value = ((led_value & mask) >> shift); + + return led_value; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return 0; +} + +void e582_48x2q4z_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + port_led_mode[portNum-1] = set_value; + + return; +} + +enum led_brightness e582_48x2q4z_led_port_get(struct led_classdev *led_cdev) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + return port_led_mode[portNum-1]; +} + +static int e582_48x2q4z_init_led(void) +{ + int ret = 0; + int i = 0; + + ret = led_classdev_register(NULL, &led_dev_system); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_system device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_idn); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_idn device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan1); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_fan1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan2); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_fan2 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan3); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_fan3 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan4); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_fan4 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu1); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_psu1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu2); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_psu2 device failed\n"); + return -1; + } + + for (i=0; i PORT_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + value = 0; + } + + if ((portNum >= 1) && (portNum <= 8)) + { + reg_no = portNum + 31;/*32-39*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 9) && (portNum <= 16)) + { + reg_no = portNum - 9;/*0-7*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 17) && (portNum <= 24)) + { + reg_no = portNum - 17;/*0-7*/ + i2c_sfp_client = i2c_client_gpio2; + } + else if ((portNum >= 25) && (portNum <= 32)) + { + reg_no = portNum - 17;/*8-15*/ + i2c_sfp_client = i2c_client_gpio2; + } + else if ((portNum >= 33) && (portNum <= 40)) + { + reg_no = portNum - 1;/*32-39*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 41) && (portNum <= 48)) + { + reg_no = portNum - 41;/*0-7*/ + i2c_sfp_client = i2c_client_gpio4; + } + else if ((portNum >= 49) && (portNum <= 54)) + { + reg_no = portNum - 33;/*16-21*/ + i2c_sfp_client = i2c_client_gpio4; + } + + dir_bank = (reg_no/8) + 0x18; + ret = e582_48x2q4z_smbus_write_reg(i2c_sfp_client, dir_bank, 0xff); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s set dir-ctl failed\n", attr->attr.name); + } + + input_bank = (reg_no/8) + 0x0; + ret = e582_48x2q4z_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 );/*1:PRESENT 0:ABSENT*/ + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e582_48x2q4z_sfp_read_enable(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char value = 0; + unsigned char reg_no = 0; + unsigned char dir_bank = 0; + unsigned char input_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > PORT_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + value = 0; + } + + if ((portNum >= 1) && (portNum <= 8)) + { + reg_no = portNum - 1;/*0-7*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 9) && (portNum <= 16)) + { + reg_no = portNum - 1;/*8-15*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 17) && (portNum <= 24)) + { + reg_no = portNum - 9;/*8-15*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 25) && (portNum <= 32)) + { + reg_no = portNum - 9;/*16-23*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 33) && (portNum <= 40)) + { + reg_no = portNum - 33;/*0-7*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 41) && (portNum <= 48)) + { + reg_no = portNum - 33;/*8-15*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 49) && (portNum <= 54)) + { + printk(KERN_INFO "%s not supported!\n", name); + return sprintf(buf, "%d\n", 0); + } + + dir_bank = (reg_no/8) + 0x18; + ret = e582_48x2q4z_smbus_write_reg(i2c_sfp_client, dir_bank, 0xff); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s set dir-ctl failed\n", attr->attr.name); + } + + input_bank = (reg_no/8) + 0x8; + ret = e582_48x2q4z_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e582_48x2q4z_sfp_write_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + unsigned char value = 0; + unsigned char set_value = simple_strtol(buf, NULL, 10); + unsigned char reg_no = 0; + unsigned char dir_bank = 0; + unsigned char input_bank = 0; + unsigned char output_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > PORT_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + return size; + } + + if ((portNum >= 1) && (portNum <= 8)) + { + reg_no = portNum - 1;/*0-7*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 9) && (portNum <= 16)) + { + reg_no = portNum - 1;/*8-15*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 17) && (portNum <= 24)) + { + reg_no = portNum - 9;/*8-15*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 25) && (portNum <= 32)) + { + reg_no = portNum - 9;/*16-23*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 33) && (portNum <= 40)) + { + reg_no = portNum - 33;/*0-7*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 41) && (portNum <= 48)) + { + reg_no = portNum - 17;/*8-13*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 49) && (portNum <= 54)) + { + printk(KERN_INFO "%s not supported!\n", name); + return size; + } + + set_value = ((set_value > 0) ? 0 : 1 ); + + dir_bank = (reg_no/8) + 0x18; + ret = e582_48x2q4z_smbus_write_reg(i2c_sfp_client, dir_bank, 0x0); + if (ret != 0) + { + printk(KERN_CRIT "Error: read sfp data:%s set dir-ctl failed\n", attr->attr.name); + return size; + } + + input_bank = (reg_no/8) + 0x8; + ret = e582_48x2q4z_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s presence failed\n", name); + return size; + } + + if (set_value) + { + value = (value | (1<<(reg_no % 8))); + } + else + { + value = (value & (~(1<<(reg_no % 8)))); + } + + output_bank = (reg_no/8) + 0x8; + ret = e582_48x2q4z_smbus_write_reg(i2c_sfp_client, output_bank, value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s presence failed\n", name); + return size; + } + + return size; +} + +static DEVICE_ATTR(sfp_presence, S_IRUGO, e582_48x2q4z_sfp_read_presence, NULL); +static DEVICE_ATTR(sfp_enable, S_IRUGO|S_IWUSR, e582_48x2q4z_sfp_read_enable, e582_48x2q4z_sfp_write_enable); +static int e582_48x2q4z_init_sfp(void) +{ + int ret = 0; + int i = 0; + + sfp_class = class_create(THIS_MODULE, "sfp"); + if (IS_INVALID_PTR(sfp_class)) + { + sfp_class = NULL; + printk(KERN_CRIT "create e582_48x2q4z class sfp failed\n"); + return -1; + } + + for (i=1; i<=PORT_NUM; i++) + { + sfp_dev[i] = device_create(sfp_class, NULL, MKDEV(223,i), NULL, "sfp%d", i); + if (IS_INVALID_PTR(sfp_dev[i])) + { + sfp_dev[i] = NULL; + printk(KERN_CRIT "create e582_48x2q4z sfp[%d] device failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z sfp[%d] device attr:presence failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_enable); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z sfp[%d] device attr:enable failed\n", i); + continue; + } + } + + return ret; +} + +static int e582_48x2q4z_exit_sfp(void) +{ + int i = 0; + + for (i=1; i<=PORT_NUM; i++) + { + if (IS_VALID_PTR(sfp_dev[i])) + { + device_remove_file(sfp_dev[i], &dev_attr_sfp_presence); + device_remove_file(sfp_dev[i], &dev_attr_sfp_enable); + device_destroy(sfp_class, MKDEV(223,i)); + sfp_dev[i] = NULL; + } + } + + if (IS_VALID_PTR(sfp_class)) + { + class_destroy(sfp_class); + sfp_class = NULL; + } + + return 0; +} +#endif + +static int e582_48x2q4z_init(void) +{ + int ret = 0; + int failed = 0; + + printk(KERN_ALERT "install e582_48x2q4z board dirver...\n"); + + ret = e582_48x2q4z_init_i2c_master(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_i2c_pca9548(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_i2c_adt7470(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_i2c_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_i2c_epld(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_i2c_gpio(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_led(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_sfp(); + if (ret != 0) + { + failed = 1; + } + + if (failed) + printk(KERN_INFO "install e582_48x2q4z board driver failed\n"); + else + printk(KERN_ALERT "install e582_48x2q4z board dirver...ok\n"); + + return 0; +} + +static void e582_48x2q4z_exit(void) +{ + printk(KERN_INFO "uninstall e582_48x2q4z board dirver...\n"); + + e582_48x2q4z_exit_sfp(); + e582_48x2q4z_exit_led(); + e582_48x2q4z_exit_psu(); + e582_48x2q4z_exit_i2c_gpio(); + e582_48x2q4z_exit_i2c_epld(); + e582_48x2q4z_exit_i2c_psu(); + e582_48x2q4z_exit_i2c_adt7470(); + e582_48x2q4z_exit_i2c_pca9548(); + e582_48x2q4z_exit_i2c_master(); +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("yangbs centecNetworks, Inc"); +MODULE_DESCRIPTION("e582-48x2q4z board driver"); +module_init(e582_48x2q4z_init); +module_exit(e582_48x2q4z_exit); + + diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/dal_kernel.c b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/dal_kernel.c new file mode 100644 index 000000000000..32a38f842cfa --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/dal_kernel.c @@ -0,0 +1,1833 @@ +/** + @file dal_kernal.c + + @date 2012-10-18 + + @version v2.0 + + +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) +#include +#endif +#include "dal_kernel.h" +#include "dal_mpool.h" +#include +MODULE_AUTHOR("Centec Networks Inc."); +MODULE_DESCRIPTION("DAL kernel module"); +MODULE_LICENSE("GPL"); + +/* DMA memory pool size */ +static char* dma_pool_size; +module_param(dma_pool_size, charp, 0); +MODULE_PARM_DESC(dma_pool_size, + "Specify DMA memory pool size (default 4MB)"); + +/***************************************************************************** + * defines + *****************************************************************************/ +#define MB_SIZE 0x100000 +#define CTC_MAX_INTR_NUM 8 + +#define MEM_MAP_RESERVE SetPageReserved +#define MEM_MAP_UNRESERVE ClearPageReserved + +#define CTC_VENDOR_VID 0xc001 +#define CTC_HUMBER_DEVICE_ID 0x6048 +#define CTC_GOLDENGATE_DEVICE_ID 0xc010 +#define CTC_PCIE_VENDOR_ID 0xcb10 +#define CTC_DUET2_DEVICE_ID 0x7148 + +#define MEM_MAP_RESERVE SetPageReserved +#define MEM_MAP_UNRESERVE ClearPageReserved + +#define CTC_GREATBELT_DEVICE_ID 0x03e8 /* TBD */ +#define DAL_MAX_CHIP_NUM 8 /* [GB] used */ +#define VIRT_TO_PAGE(p) virt_to_page((p)) +#define DAL_UNTAG_BLOCK 0 +#define DAL_DISCARD_BLOCK 1 +#define DAL_MATCHED_BLOCK 2 +#define DAL_CUR_MATCH_BLOCk 3 +/***************************************************************************** + * typedef + *****************************************************************************/ +/* Control Data */ +typedef struct dal_isr_s +{ + int irq; + void (* isr)(void*); + void* isr_data; + int trigger; + int count; + wait_queue_head_t wqh; +} dal_isr_t; + +typedef struct dal_kernel_dev_s +{ + struct list_head list; + struct pci_dev* pci_dev; + + /* PCI I/O mapped base address */ + uintptr logic_address; + + /* Physical address */ + unsigned long long phys_address; +} dal_kern_dev_t; + +typedef struct _dma_segment +{ + struct list_head list; + unsigned long req_size; /* Requested DMA segment size */ + unsigned long blk_size; /* DMA block size */ + unsigned long blk_order; /* DMA block size in alternate format */ + unsigned long seg_size; /* Current DMA segment size */ + unsigned long seg_begin; /* Logical address of segment */ + unsigned long seg_end; /* Logical end address of segment */ + unsigned long* blk_ptr; /* Array of logical DMA block addresses */ + int blk_cnt_max; /* Maximum number of block to allocate */ + int blk_cnt; /* Current number of blocks allocated */ +} dma_segment_t; + +typedef irqreturn_t (*p_func) (int irq, void* dev_id); + +/*************************************************************************** + *declared + ***************************************************************************/ +static unsigned int linux_dal_poll0(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll1(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll2(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll3(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll4(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll5(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll6(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll7(struct file* filp, struct poll_table_struct* p); + +/***************************************************************************** + * global variables + *****************************************************************************/ +static dal_kern_dev_t dal_dev[DAL_MAX_CHIP_NUM]; +static dal_isr_t dal_isr[CTC_MAX_INTR_NUM]; +static int dal_chip_num = 0; +static int dal_version = 0; +static int dal_intr_num = 0; +static int use_high_memory = 0; +static unsigned int* dma_virt_base[DAL_MAX_CHIP_NUM]; +#ifndef DMA_MEM_MODE_PLATFORM +static unsigned int* dma_virt_base_tmp[DAL_MAX_CHIP_NUM]; +#endif +static unsigned long long dma_phy_base[DAL_MAX_CHIP_NUM]; +static unsigned int dma_mem_size = 0xc00000; +static unsigned int msi_irq_base[DAL_MAX_CHIP_NUM]; +static unsigned int msi_irq_num[DAL_MAX_CHIP_NUM]; +static unsigned int msi_used = 0; +static struct class *dal_class; + +static LIST_HEAD(_dma_seg); +static int dal_debug = 0; +module_param(dal_debug, int, 0); +MODULE_PARM_DESC(dal_debug, "Set debug level (default 0)"); + +static struct pci_device_id dal_id_table[] = +{ + {PCI_DEVICE(CTC_VENDOR_VID, CTC_GREATBELT_DEVICE_ID)}, + {PCI_DEVICE(CTC_PCIE_VENDOR_ID, CTC_GOLDENGATE_DEVICE_ID)}, + {PCI_DEVICE((CTC_PCIE_VENDOR_ID+1), (CTC_GOLDENGATE_DEVICE_ID+1))}, + {PCI_DEVICE(CTC_PCIE_VENDOR_ID, CTC_DUET2_DEVICE_ID)}, + {0, }, +}; + +static wait_queue_head_t poll_intr[CTC_MAX_INTR_NUM]; + +p_func intr_handler_fun[CTC_MAX_INTR_NUM]; + +static int poll_intr_trigger[CTC_MAX_INTR_NUM]; + +static struct file_operations dal_intr_fops[CTC_MAX_INTR_NUM] = +{ + { + .owner = THIS_MODULE, + .poll = linux_dal_poll0, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll1, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll2, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll3, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll4, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll5, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll6, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll7, + }, +}; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) +#include +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt +#endif +/***************************************************************************** + * macros + *****************************************************************************/ +#define VERIFY_CHIP_INDEX(n) (n < dal_chip_num) + +#define _KERNEL_INTERUPT_PROCESS +static irqreturn_t +intr0_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + + if(poll_intr_trigger[0]) + { + return IRQ_HANDLED; + } + + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[0] = 1; + wake_up(&poll_intr[0]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr1_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[1]) + { + return IRQ_HANDLED; + } + + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[1] = 1; + wake_up(&poll_intr[1]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr2_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[2]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[2] = 1; + wake_up(&poll_intr[2]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr3_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[3]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[3] = 1; + wake_up(&poll_intr[3]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr4_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[4]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[4] = 1; + wake_up(&poll_intr[4]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr5_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[5]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[5] = 1; + wake_up(&poll_intr[5]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr6_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[6]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[6] = 1; + wake_up(&poll_intr[6]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr7_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[7]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[7] = 1; + wake_up(&poll_intr[7]); + } + } + + return IRQ_HANDLED; +} + +int +dal_interrupt_register(unsigned int irq, int prio, void (* isr)(void*), void* data) +{ + int ret; + unsigned char str[16]; + unsigned char* int_name = NULL; + unsigned int intr_num_tmp = 0; + unsigned int intr_num = CTC_MAX_INTR_NUM; + unsigned long irq_flags = 0; + + if (dal_intr_num >= CTC_MAX_INTR_NUM) + { + printk("Interrupt numbers exceeds max.\n"); + return -1; + } + + if (msi_used) + { + int_name = "dal_msi"; + } + else + { + int_name = "dal_intr"; + } + + + for (intr_num_tmp=0;intr_num_tmp < CTC_MAX_INTR_NUM; intr_num_tmp++) + { + if (irq == dal_isr[intr_num_tmp].irq) + { + if (0 == msi_used) + { + dal_isr[intr_num_tmp].count++; + printk("Interrupt irq %d register count %d.\n", irq, dal_isr[intr_num_tmp].count); + } + return 0; + } + if ((0 == dal_isr[intr_num_tmp].irq) && (CTC_MAX_INTR_NUM == intr_num)) + { + intr_num = intr_num_tmp; + dal_isr[intr_num].count = 0; + } + } + dal_isr[intr_num].irq = irq; + dal_isr[intr_num].isr = isr; + dal_isr[intr_num].isr_data = data; + dal_isr[intr_num].count++; + + init_waitqueue_head(&poll_intr[intr_num]); + + /* only user mode */ + if ((NULL == isr) && (NULL == data)) + { + snprintf(str, 16, "%s%d", "dal_intr", intr_num); + ret = register_chrdev(DAL_DEV_INTR_MAJOR_BASE + intr_num, + str, &dal_intr_fops[intr_num]); + if (ret < 0) + { + printk("Register character device for irq %d failed, ret= %d", irq, ret); + return ret; + } + } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) + irq_flags = 0; +#else + irq_flags = IRQF_DISABLED; +#endif + if ((ret = request_irq(irq, + intr_handler_fun[intr_num], + irq_flags, + int_name, + &dal_isr[intr_num])) < 0) + { + printk("Cannot request irq %d, ret %d.\n", irq, ret); + unregister_chrdev(DAL_DEV_INTR_MAJOR_BASE + intr_num, str); + } + + if (0 == ret) + { + dal_intr_num++; + } + + return ret; +} + +int +dal_interrupt_unregister(unsigned int irq) +{ + unsigned char str[16]; + int intr_idx = 0; + int find_flag = 0; + + /* get intr device index */ + for (intr_idx = 0; intr_idx < CTC_MAX_INTR_NUM; intr_idx++) + { + if (dal_isr[intr_idx].irq == irq) + { + find_flag = 1; + break; + } + } + + if (find_flag == 0) + { + printk ("irq%d is not registered! unregister failed \n", irq); + return -1; + } + + dal_isr[intr_idx].count--; + if (0 != dal_isr[intr_idx].count) + { + printk("Interrupt irq %d unregister count %d.\n", irq, dal_isr[intr_idx].count); + return -1; + } + snprintf(str, 16, "%s%d", "dal_intr", intr_idx); + + unregister_chrdev(DAL_DEV_INTR_MAJOR_BASE + intr_idx, str); + + free_irq(irq, &dal_isr[intr_idx]); + + dal_isr[intr_idx].irq = 0; + + dal_intr_num--; + + return 0; +} + +int +dal_interrupt_set_en(unsigned int irq, unsigned int enable) +{ + enable ? enable_irq(irq) : disable_irq_nosync(irq); + return 0; +} + +static int +_dal_set_msi_enabe(unsigned int lchip, unsigned int irq_num) +{ + int ret = 0; + + if (irq_num == 1) + { + ret = pci_enable_msi(dal_dev[lchip].pci_dev); + if (ret) + { + printk ("msi enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); + pci_disable_msi(dal_dev[lchip].pci_dev); + msi_used = 0; + } + + msi_irq_base[lchip] = dal_dev[lchip].pci_dev->irq; + msi_irq_num[lchip] = 1; + } + else + { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 79)) + ret = pci_enable_msi_exact(dal_dev[lchip].pci_dev, irq_num); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 26, 32)) + ret = pci_enable_msi_block(dal_dev[lchip].pci_dev, irq_num); +#else + ret = -1; +#endif + if (ret) + { + printk ("msi enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); + pci_disable_msi(dal_dev[lchip].pci_dev); + msi_used = 0; + } + + msi_irq_base[lchip] = dal_dev[lchip].pci_dev->irq; + msi_irq_num[lchip] = irq_num; + } + + return ret; +} + +static int +_dal_set_msi_disable(unsigned int lchip) +{ + + pci_disable_msi(dal_dev[lchip].pci_dev); + + msi_irq_base[lchip] = 0; + msi_irq_num[lchip] = 0; + + return 0; +} + +int +dal_set_msi_cap(unsigned long arg) +{ + int ret = 0; + int index = 0; + dal_msi_info_t msi_info; + + if (copy_from_user(&msi_info, (void*)arg, sizeof(dal_msi_info_t))) + { + return -EFAULT; + } + + printk("####dal_set_msi_cap lchip %d base %d num:%d\n", msi_info.lchip, msi_info.irq_base, msi_info.irq_num); + if (msi_info.irq_num > 0) + { + if (0 == msi_used) + { + msi_used = 1; + ret = _dal_set_msi_enabe(msi_info.lchip, msi_info.irq_num); + } + else if ((1 == msi_used) && (msi_info.irq_num != msi_irq_num[msi_info.lchip])) + { + for (index = 0; index < msi_irq_num[msi_info.lchip]; index++) + { + dal_interrupt_unregister(msi_irq_base[msi_info.lchip]+index); + } + _dal_set_msi_disable(msi_info.lchip); + msi_used = 1; + ret = _dal_set_msi_enabe(msi_info.lchip, msi_info.irq_num); + } + } + else + { + msi_used = 0; + ret = _dal_set_msi_disable(msi_info.lchip); + } + + return ret; +} + +int +dal_user_interrupt_register(unsigned long arg) +{ + int irq = 0; + if (copy_from_user(&irq, (void*)arg, sizeof(int))) + { + return -EFAULT; + } + printk("####register interrupt irq:%d\n", irq); + return dal_interrupt_register(irq, 0, NULL, NULL); +} + +int +dal_user_interrupt_unregister(unsigned long arg) +{ + int irq = 0; + if (copy_from_user(&irq, (void*)arg, sizeof(int))) + { + return -EFAULT; + } + printk("####unregister interrupt irq:%d\n", irq); + return dal_interrupt_unregister(irq); +} + +int +dal_user_interrupt_set_en(unsigned long arg) +{ + dal_intr_parm_t dal_intr_parm; + + if (copy_from_user(&dal_intr_parm, (void*)arg, sizeof(dal_intr_parm_t))) + { + return -EFAULT; + } + + return dal_interrupt_set_en(dal_intr_parm.irq, dal_intr_parm.enable); +} + +/* + * Function: _dal_dma_segment_free + */ + +/* + * Function: _find_largest_segment + * + * Purpose: + * Find largest contiguous segment from a pool of DMA blocks. + * Parameters: + * dseg - DMA segment descriptor + * Returns: + * 0 on success, < 0 on error. + * Notes: + * Assembly stops if a segment of the requested segment size + * has been obtained. + * + * Lower address bits of the DMA blocks are used as follows: + * 0: Untagged + * 1: Discarded block + * 2: Part of largest contiguous segment + * 3: Part of current contiguous segment + */ +#ifndef DMA_MEM_MODE_PLATFORM +static int +_dal_find_largest_segment(dma_segment_t* dseg) +{ + int i, j, blks, found; + unsigned long seg_begin; + unsigned long seg_end; + unsigned long seg_tmp; + + blks = dseg->blk_cnt; + + /* Clear all block tags */ + for (i = 0; i < blks; i++) + { + dseg->blk_ptr[i] &= ~3; + } + + for (i = 0; i < blks && dseg->seg_size < dseg->req_size; i++) + { + /* First block must be an untagged block */ + if ((dseg->blk_ptr[i] & 3) == DAL_UNTAG_BLOCK) + { + /* Initial segment size is the block size */ + seg_begin = dseg->blk_ptr[i]; + seg_end = seg_begin + dseg->blk_size; + dseg->blk_ptr[i] |= DAL_CUR_MATCH_BLOCk; + + /* Loop looking for adjacent blocks */ + do + { + found = 0; + + for (j = i + 1; j < blks && (seg_end - seg_begin) < dseg->req_size; j++) + { + seg_tmp = dseg->blk_ptr[j]; + /* Check untagged blocks only */ + if ((seg_tmp & 3) == DAL_UNTAG_BLOCK) + { + if (seg_tmp == (seg_begin - dseg->blk_size)) + { + /* Found adjacent block below current segment */ + dseg->blk_ptr[j] |= DAL_CUR_MATCH_BLOCk; + seg_begin = seg_tmp; + found = 1; + } + else if (seg_tmp == seg_end) + { + /* Found adjacent block above current segment */ + dseg->blk_ptr[j] |= DAL_CUR_MATCH_BLOCk; + seg_end += dseg->blk_size; + found = 1; + } + } + } + } + while (found); + + if ((seg_end - seg_begin) > dseg->seg_size) + { + /* The current block is largest so far */ + dseg->seg_begin = seg_begin; + dseg->seg_end = seg_end; + dseg->seg_size = seg_end - seg_begin; + + /* Re-tag current and previous largest segment */ + for (j = 0; j < blks; j++) + { + if ((dseg->blk_ptr[j] & 3) == DAL_CUR_MATCH_BLOCk) + { + /* Tag current segment as the largest */ + dseg->blk_ptr[j] &= ~1; + } + else if ((dseg->blk_ptr[j] & 3) == DAL_MATCHED_BLOCK) + { + /* Discard previous largest segment */ + dseg->blk_ptr[j] ^= 3; + } + } + } + else + { + /* Discard all blocks in current segment */ + for (j = 0; j < blks; j++) + { + if ((dseg->blk_ptr[j] & 3) == DAL_CUR_MATCH_BLOCk) + { + dseg->blk_ptr[j] &= ~2; + } + } + } + } + } + + return 0; +} + +/* + * Function: _alloc_dma_blocks + */ +static int +_dal_alloc_dma_blocks(dma_segment_t* dseg, int blks) +{ + int i, start; + unsigned long addr; + + if (dseg->blk_cnt + blks > dseg->blk_cnt_max) + { + printk("No more DMA blocks\n"); + return -1; + } + + start = dseg->blk_cnt; + dseg->blk_cnt += blks; + + for (i = start; i < dseg->blk_cnt; i++) + { + addr = __get_free_pages(GFP_ATOMIC, dseg->blk_order); + if (addr) + { + dseg->blk_ptr[i] = addr; + } + else + { + printk("DMA allocation failed\n"); + return -1; + } + } + + return 0; +} + +/* + * Function: _dal_dma_segment_alloc + */ +static dma_segment_t* +_dal_dma_segment_alloc(unsigned int size, unsigned int blk_size) +{ + dma_segment_t* dseg; + int i, blk_ptr_size; + unsigned long page_addr; + struct sysinfo si; + + /* Sanity check */ + if (size == 0 || blk_size == 0) + { + return NULL; + } + + /* Allocate an initialize DMA segment descriptor */ + if ((dseg = kmalloc(sizeof(dma_segment_t), GFP_ATOMIC)) == NULL) + { + return NULL; + } + + memset(dseg, 0, sizeof(dma_segment_t)); + dseg->req_size = size; + dseg->blk_size = PAGE_ALIGN(blk_size); + + while ((PAGE_SIZE << dseg->blk_order) < dseg->blk_size) + { + dseg->blk_order++; + } + + si_meminfo(&si); + dseg->blk_cnt_max = (si.totalram << PAGE_SHIFT) / dseg->blk_size; + blk_ptr_size = dseg->blk_cnt_max * sizeof(unsigned long); + /* Allocate an initialize DMA block pool */ + dseg->blk_ptr = kmalloc(blk_ptr_size, GFP_KERNEL); + if (dseg->blk_ptr == NULL) + { + kfree(dseg); + return NULL; + } + + memset(dseg->blk_ptr, 0, blk_ptr_size); + /* Allocate minimum number of blocks */ + _dal_alloc_dma_blocks(dseg, dseg->req_size / dseg->blk_size); + + /* Allocate more blocks until we have a complete segment */ + do + { + _dal_find_largest_segment(dseg); + if (dseg->seg_size >= dseg->req_size) + { + break; + } + } + while (_dal_alloc_dma_blocks(dseg, 8) == 0); + + /* Reserve all pages in the DMA segment and free unused blocks */ + for (i = 0; i < dseg->blk_cnt; i++) + { + if ((dseg->blk_ptr[i] & 3) == 2) + { + dseg->blk_ptr[i] &= ~3; + + for (page_addr = dseg->blk_ptr[i]; + page_addr < dseg->blk_ptr[i] + dseg->blk_size; + page_addr += PAGE_SIZE) + { + MEM_MAP_RESERVE(VIRT_TO_PAGE((void*)page_addr)); + } + } + else if (dseg->blk_ptr[i]) + { + dseg->blk_ptr[i] &= ~3; + free_pages(dseg->blk_ptr[i], dseg->blk_order); + dseg->blk_ptr[i] = 0; + } + } + + return dseg; +} + +/* + * Function: _dal_dma_segment_free + */ +static void +_dal_dma_segment_free(dma_segment_t* dseg) +{ + int i; + unsigned long page_addr; + + if (dseg->blk_ptr) + { + for (i = 0; i < dseg->blk_cnt; i++) + { + if (dseg->blk_ptr[i]) + { + for (page_addr = dseg->blk_ptr[i]; + page_addr < dseg->blk_ptr[i] + dseg->blk_size; + page_addr += PAGE_SIZE) + { + MEM_MAP_UNRESERVE(VIRT_TO_PAGE(page_addr)); + } + + free_pages(dseg->blk_ptr[i], dseg->blk_order); + } + } + + kfree(dseg->blk_ptr); + kfree(dseg); + } +} + +/* + * Function: -dal_pgalloc + */ +static void* +_dal_pgalloc(unsigned int size) +{ + dma_segment_t* dseg; + unsigned int blk_size; + + blk_size = (size < DMA_BLOCK_SIZE) ? size : DMA_BLOCK_SIZE; + if ((dseg = _dal_dma_segment_alloc(size, blk_size)) == NULL) + { + return NULL; + } + + if (dseg->seg_size < size) + { + /* If we didn't get the full size then forget it */ + printk("Notice: Can not get enough memory for requset!!\n"); + printk("actual size:0x%lx, request size:0x%x\n", dseg->seg_size, size); + //-_dal_dma_segment_free(dseg); + //-return NULL; + } + + list_add(&dseg->list, &_dma_seg); + return (void*)dseg->seg_begin; +} + +/* + * Function: _dal_pgfree + */ +static int +_dal_pgfree(void* ptr) +{ + struct list_head* pos; + + list_for_each(pos, &_dma_seg) + { + dma_segment_t* dseg = list_entry(pos, dma_segment_t, list); + if (ptr == (void*)dseg->seg_begin) + { + list_del(&dseg->list); + _dal_dma_segment_free(dseg); + return 0; + } + } + return -1; +} +#endif +static void +dal_alloc_dma_pool(int lchip, int size) +{ + if (use_high_memory) + { + dma_phy_base[lchip] = virt_to_bus(high_memory); + dma_virt_base[lchip] = ioremap_nocache(dma_phy_base[lchip], size); + } + else + { +#ifdef DMA_MEM_MODE_PLATFORM + dma_virt_base[lchip] = dma_alloc_coherent(&(dal_dev[lchip].pci_dev->dev), dma_mem_size, + &dma_phy_base[lchip], GFP_KERNEL); + + printk(KERN_WARNING "########Using DMA_MEM_MODE_PLATFORM \n"); +#endif + +#ifndef DMA_MEM_MODE_PLATFORM + /* Get DMA memory from kernel */ + dma_virt_base_tmp[lchip] = _dal_pgalloc(size); + dma_phy_base[lchip] = virt_to_bus(dma_virt_base_tmp[lchip]); + dma_virt_base [lchip]= ioremap_nocache(dma_phy_base[lchip], size); +#endif + } +} + +static void +dal_free_dma_pool(int lchip) +{ + int ret = 0; + ret = ret; + if (use_high_memory) + { + iounmap(dma_virt_base[lchip]); + } + else + { +#ifdef DMA_MEM_MODE_PLATFORM + dma_free_coherent(&(dal_dev[lchip].pci_dev->dev), dma_mem_size, + dma_virt_base[lchip], dma_phy_base[lchip]); +#endif + +#ifndef DMA_MEM_MODE_PLATFORM + iounmap(dma_virt_base[lchip]); + ret = _dal_pgfree(dma_virt_base_tmp[lchip]); + if(ret<0) + { + printk("Dma free memory fail !!!!!! \n"); + } +#endif + } +} + +#define _KERNEL_DAL_IO +static int +_dal_pci_read(unsigned char lchip, unsigned int offset, unsigned int* value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + *value = *(volatile unsigned int*)(dal_dev[lchip].logic_address + offset); + return 0; +} + +int +dal_create_irq_mapping(unsigned long arg) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) + +#ifndef NO_IRQ +#define NO_IRQ (-1) +#endif + dal_irq_mapping_t irq_map; + + if (copy_from_user(&irq_map, (void*)arg, sizeof(dal_irq_mapping_t))) + { + return -EFAULT; + } + + irq_map.sw_irq = irq_create_mapping(NULL, irq_map.hw_irq); + if (irq_map.sw_irq == NO_IRQ) + { + printk("IRQ mapping fail !!!!!! \n"); + return -1; + } + + if (copy_to_user((dal_irq_mapping_t*)arg, (void*)&irq_map, sizeof(dal_irq_mapping_t))) + { + return -EFAULT; + } +#endif + return 0; +} + +int +dal_pci_read(unsigned long arg) +{ + dal_chip_parm_t cmdpara_chip; + + if (copy_from_user(&cmdpara_chip, (void*)arg, sizeof(dal_chip_parm_t))) + { + return -EFAULT; + } + + _dal_pci_read((unsigned char)cmdpara_chip.lchip, (unsigned int)cmdpara_chip.reg_addr, + (unsigned int*)(&(cmdpara_chip.value))); + + if (copy_to_user((dal_chip_parm_t*)arg, (void*)&cmdpara_chip, sizeof(dal_chip_parm_t))) + { + return -EFAULT; + } + + return 0; +} + +static int +_dal_pci_write(unsigned char lchip, unsigned int offset, unsigned int value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + *(volatile unsigned int*)(dal_dev[lchip].logic_address + offset) = value; + return 0; +} + +int +dal_pci_write(unsigned long arg) +{ + dal_chip_parm_t cmdpara_chip; + + if (copy_from_user(&cmdpara_chip, (void*)arg, sizeof(dal_chip_parm_t))) + { + return -EFAULT; + } + + _dal_pci_write((unsigned char)cmdpara_chip.lchip, (unsigned int)cmdpara_chip.reg_addr, + (unsigned int)cmdpara_chip.value); + + return 0; +} + +int +dal_pci_conf_read(unsigned char lchip, unsigned int offset, unsigned int* value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + pci_read_config_dword(dal_dev[lchip].pci_dev, offset, value); + return 0; +} + +int +dal_pci_conf_write(unsigned char lchip, unsigned int offset, unsigned int value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + pci_write_config_dword(dal_dev[lchip].pci_dev, offset, value); + return 0; +} +int +dal_user_read_pci_conf(unsigned long arg) +{ + dal_pci_cfg_ioctl_t dal_cfg; + + if (copy_from_user(&dal_cfg, (void*)arg, sizeof(dal_pci_cfg_ioctl_t))) + { + return -EFAULT; + } + + if (dal_pci_conf_read(dal_cfg.lchip, dal_cfg.offset, &dal_cfg.value)) + { + printk("dal_pci_conf_read failed.\n"); + return -EFAULT; + } + + if (copy_to_user((dal_pci_cfg_ioctl_t*)arg, (void*)&dal_cfg, sizeof(dal_pci_cfg_ioctl_t))) + { + return -EFAULT; + } + + return 0; +} + +int +dal_user_write_pci_conf(unsigned long arg) +{ + dal_pci_cfg_ioctl_t dal_cfg; + + if (copy_from_user(&dal_cfg, (void*)arg, sizeof(dal_pci_cfg_ioctl_t))) + { + return -EFAULT; + } + + return dal_pci_conf_write(dal_cfg.lchip, dal_cfg.offset, dal_cfg.value); +} + +static int +linux_get_device(unsigned long arg) +{ + dal_user_dev_t user_dev; + int lchip = 0; + + if (copy_from_user(&user_dev, (void*)arg, sizeof(user_dev))) + { + return -EFAULT; + } + + user_dev.chip_num = dal_chip_num; + lchip = user_dev.lchip; + + if (lchip < dal_chip_num) + { + user_dev.phy_base0 = (unsigned int)dal_dev[lchip].phys_address; + user_dev.phy_base1 = (unsigned int)(dal_dev[lchip].phys_address >> 32); + + user_dev.bus_no = dal_dev[lchip].pci_dev->bus->number; + user_dev.dev_no = dal_dev[lchip].pci_dev->device; + user_dev.fun_no = dal_dev[lchip].pci_dev->devfn; + } + + if (copy_to_user((dal_user_dev_t*)arg, (void*)&user_dev, sizeof(user_dev))) + { + return -EFAULT; + } + + return 0; +} + +/* set dal version, copy to user */ +static int +linux_get_dal_version(unsigned long arg) +{ + int dal_ver = VERSION_1DOT2; /* set dal version */ + + if (copy_to_user((int*)arg, (void*)&dal_ver, sizeof(dal_ver))) + { + return -EFAULT; + } + + dal_version = dal_ver; /* up sw */ + + return 0; +} + +static int +linux_get_dma_info(unsigned long arg) +{ + dma_info_t dma_para; + + if (copy_from_user(&dma_para, (void*)arg, sizeof(dma_info_t))) + { + return -EFAULT; + } + + dma_para.phy_base = (unsigned int)dma_phy_base[dma_para.lchip]; + dma_para.phy_base_hi = dma_phy_base[dma_para.lchip] >> 32; + dma_para.size = dma_mem_size; + + if (copy_to_user((dma_info_t*)arg, (void*)&dma_para, sizeof(dma_info_t))) + { + return -EFAULT; + } + + return 0; +} + +static int +dal_get_msi_info(unsigned long arg) +{ + dal_msi_info_t msi_para; + unsigned int lchip = 0; + + /* get lchip form user mode */ + if (copy_from_user(&msi_para, (void*)arg, sizeof(dal_msi_info_t))) + { + return -EFAULT; + } + lchip = msi_para.lchip; + + msi_para.irq_base = msi_irq_base[lchip]; + msi_para.irq_num = msi_irq_num[lchip]; + + /* send msi info to user mode */ + if (copy_to_user((dal_msi_info_t*)arg, (void*)&msi_para, sizeof(dal_msi_info_t))) + { + return -EFAULT; + } + + return 0; +} + + +static int +dal_get_intr_info(unsigned long arg) +{ + dal_intr_info_t intr_para; + unsigned int intr_num = 0; + + /* get lchip form user mode */ + if (copy_from_user(&intr_para, (void*)arg, sizeof(dal_intr_info_t))) + { + return -EFAULT; + } + + intr_para.irq_idx = CTC_MAX_INTR_NUM; + for (intr_num=0; intr_num< CTC_MAX_INTR_NUM; intr_num++) + { + if (intr_para.irq == dal_isr[intr_num].irq) + { + intr_para.irq_idx = intr_num; + break; + } + } + + if (CTC_MAX_INTR_NUM == intr_para.irq_idx) + { + printk("Interrupt %d cann't find.\n", intr_para.irq); + } + /* send msi info to user mode */ + if (copy_to_user((dal_intr_info_t*)arg, (void*)&intr_para, sizeof(dal_intr_info_t))) + { + return -EFAULT; + } + + return 0; +} + +static int +dal_cache_inval(unsigned long arg) +{ + dal_dma_cache_info_t intr_para; + + if (copy_from_user(&intr_para, (void*)arg, sizeof(dal_dma_cache_info_t))) + { + return -EFAULT; + } + +#if 0 + dma_cache_wback_inv((unsigned long)intr_para.ptr, intr_para.length); +#endif + +#if 0 + dma_sync_single_for_cpu(NULL, intr_para.ptr, intr_para.length, DMA_BIDIRECTIONAL); + + + dma_cache_sync(NULL, (void*)intr_para.ptr, intr_para.length, DMA_BIDIRECTIONAL); +#endif + return 0; +} + +static int +dal_cache_flush(unsigned long arg) +{ + dal_dma_cache_info_t intr_para; + + if (copy_from_user(&intr_para, (void*)arg, sizeof(dal_dma_cache_info_t))) + { + return -EFAULT; + } + +#if 0 + dma_cache_wback_inv(intr_para.ptr, intr_para.length); +#endif + +#if 0 + dma_sync_single_for_cpu(NULL, intr_para.ptr, intr_para.length, DMA_BIDIRECTIONAL); + + + dma_cache_sync(NULL, (void*)intr_para.ptr, intr_para.length, DMA_BIDIRECTIONAL); +#endif + return 0; +} + +int +linux_dal_probe(struct pci_dev* pdev, const struct pci_device_id* id) +{ + dal_kern_dev_t* dev = NULL; + int bar = 0; + int ret = 0; + unsigned int temp = 0; + unsigned int lchip = 0; + + printk(KERN_WARNING "********found dal device*****\n"); + + for (lchip = 0; lchip < DAL_MAX_CHIP_NUM; lchip ++) + { + if (NULL == dal_dev[lchip].pci_dev) + { + break; + } + } + + if (lchip >= DAL_MAX_CHIP_NUM) + { + printk("Exceed max local chip num\n"); + return -1; + } + + dev = &dal_dev[lchip]; + if (NULL == dev) + { + printk("Cannot obtain PCI resources\n"); + } + + lchip = lchip; + dal_chip_num += 1; + + dev->pci_dev = pdev; + + if (pci_enable_device(pdev) < 0) + { + printk("Cannot enable PCI device: vendor id = %x, device id = %x\n", + pdev->vendor, pdev->device); + } + + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + if (ret) + { + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) + { + printk("Could not set PCI DMA Mask\n"); + return ret; + } + } + + if (pci_request_regions(pdev, DAL_NAME) < 0) + { + printk("Cannot obtain PCI resources\n"); + } + + dev->phys_address = pci_resource_start(pdev, bar); + dev->logic_address = (uintptr)ioremap_nocache(dev->phys_address, + pci_resource_len(dev->pci_dev, bar)); + + _dal_pci_read(lchip, 0x48, &temp); + if (((temp >> 8) & 0xffff) == 0x3412) + { + printk("Little endian Cpu detected!!! \n"); + _dal_pci_write(lchip, 0x48, 0xFFFFFFFF); + } + + pci_set_master(pdev); + + /* alloc dma_mem_size for every chip */ + if (dma_mem_size) + { + dal_alloc_dma_pool(lchip, dma_mem_size); + + /*add check Dma memory pool cannot cross 4G space*/ + if ((0==(dma_phy_base[lchip]>>32)) && (0!=((dma_phy_base[lchip]+dma_mem_size)>>32))) + { + printk("Dma malloc memory cross 4G space!!!!!! \n"); + return -1; + } + } + + printk(KERN_WARNING "linux_dal_probe end*****\n"); + + return 0; +} + +void +linux_dal_remove(struct pci_dev* pdev) +{ + unsigned int lchip = 0; + unsigned int flag = 0; + + for (lchip = 0; lchip < DAL_MAX_CHIP_NUM; lchip ++) + { + if (pdev == dal_dev[lchip].pci_dev) + { + flag = 1; + break; + } + } + + if (1 == flag) + { + dal_free_dma_pool(lchip); + pci_release_regions(pdev); + pci_disable_device(pdev); + + dal_dev[lchip].pci_dev = NULL; + dal_chip_num--; + } + + +} + +#ifdef CONFIG_COMPAT +static long +linux_dal_ioctl(struct file* file, + unsigned int cmd, unsigned long arg) +#else + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) +static int +linux_dal_ioctl(struct file* file, + unsigned int cmd, unsigned long arg) +#else +static int +linux_dal_ioctl(struct inode* inode, struct file* file, + unsigned int cmd, unsigned long arg) +#endif + +#endif +{ + switch (cmd) + { + + case CMD_READ_CHIP: + return dal_pci_read(arg); + + case CMD_WRITE_CHIP: + return dal_pci_write(arg); + + case CMD_GET_DEVICES: + return linux_get_device(arg); + + case CMD_GET_DAL_VERSION: + return linux_get_dal_version(arg); + + case CMD_GET_DMA_INFO: + return linux_get_dma_info(arg); + + case CMD_PCI_CONFIG_READ: + return dal_user_read_pci_conf(arg); + + case CMD_PCI_CONFIG_WRITE: + return dal_user_write_pci_conf(arg); + + case CMD_REG_INTERRUPTS: + return dal_user_interrupt_register(arg); + + case CMD_UNREG_INTERRUPTS: + return dal_user_interrupt_unregister(arg); + + case CMD_EN_INTERRUPTS: + return dal_user_interrupt_set_en(arg); + + case CMD_SET_MSI_CAP: + return dal_set_msi_cap(arg); + + case CMD_GET_MSI_INFO: + return dal_get_msi_info(arg); + + case CMD_IRQ_MAPPING: + return dal_create_irq_mapping(arg); + + case CMD_GET_INTR_INFO: + return dal_get_intr_info(arg); + + case CMD_CACHE_INVAL: + return dal_cache_inval(arg); + + case CMD_CACHE_FLUSH: + return dal_cache_flush(arg); + + default: + break; + } + + return 0; +} + +static unsigned int +linux_dal_poll0(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[0], p); + local_irq_save(flags); + if (poll_intr_trigger[0]) + { + poll_intr_trigger[0] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll1(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[1], p); + local_irq_save(flags); + if (poll_intr_trigger[1]) + { + poll_intr_trigger[1] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll2(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[2], p); + local_irq_save(flags); + if (poll_intr_trigger[2]) + { + poll_intr_trigger[2] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll3(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[3], p); + local_irq_save(flags); + if (poll_intr_trigger[3]) + { + poll_intr_trigger[3] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll4(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[4], p); + local_irq_save(flags); + if (poll_intr_trigger[4]) + { + poll_intr_trigger[4] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll5(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[5], p); + local_irq_save(flags); + if (poll_intr_trigger[5]) + { + poll_intr_trigger[5] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll6(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[6], p); + local_irq_save(flags); + if (poll_intr_trigger[6]) + { + poll_intr_trigger[6] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll7(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[7], p); + local_irq_save(flags); + if (poll_intr_trigger[7]) + { + poll_intr_trigger[7] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static struct pci_driver linux_dal_driver = +{ + .name = DAL_NAME, + .id_table = dal_id_table, + .probe = linux_dal_probe, + .remove = linux_dal_remove, +}; + +static struct file_operations fops = +{ + .owner = THIS_MODULE, +#ifdef CONFIG_COMPAT + .compat_ioctl = linux_dal_ioctl, + .unlocked_ioctl = linux_dal_ioctl, +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) + .unlocked_ioctl = linux_dal_ioctl, +#else + .ioctl = linux_dal_ioctl, +#endif +#endif +}; + + +static int __init +linux_dal_init(void) +{ + int ret = 0; + + /* Get DMA memory pool size form dal.ok input param, or use default dma_mem_size */ + if (dma_pool_size) + { + if ((dma_pool_size[strlen(dma_pool_size) - 1] & ~0x20) == 'M') + { + dma_mem_size = simple_strtoul(dma_pool_size, NULL, 0); + printk("dma_mem_size: 0x%x \n", dma_mem_size); + + dma_mem_size *= MB_SIZE; + } + else + { + printk("DMA memory pool size must be specified as e.g. dma_pool_size=8M\n"); + } + + if (dma_mem_size & (dma_mem_size - 1)) + { + printk("dma_mem_size must be a power of 2 (1M, 2M, 4M, 8M etc.)\n"); + dma_mem_size = 0; + } + } + + ret = register_chrdev(DAL_DEV_MAJOR, DAL_NAME, &fops); + if (ret < 0) + { + printk(KERN_WARNING "Register linux_dal device, ret %d\n", ret); + return ret; + } + + ret = pci_register_driver(&linux_dal_driver); + if (ret < 0) + { + printk(KERN_WARNING "Register ASIC PCI driver failed, ret %d\n", ret); + return ret; + } + + /* alloc /dev/linux_dal node */ + dal_class = class_create(THIS_MODULE, DAL_NAME); + device_create(dal_class, NULL, MKDEV(DAL_DEV_MAJOR, 0), NULL, DAL_NAME); + + /* init interrupt function */ + intr_handler_fun[0] = intr0_handler; + intr_handler_fun[1] = intr1_handler; + intr_handler_fun[2] = intr2_handler; + intr_handler_fun[3] = intr3_handler; + intr_handler_fun[4] = intr4_handler; + intr_handler_fun[5] = intr5_handler; + intr_handler_fun[6] = intr6_handler; + intr_handler_fun[7] = intr7_handler; + + return ret; +} + +static void __exit +linux_dal_exit(void) +{ + device_destroy(dal_class, MKDEV(DAL_DEV_MAJOR, 0)); + class_destroy(dal_class); + unregister_chrdev(DAL_DEV_MAJOR, "linux_dal"); + pci_unregister_driver(&linux_dal_driver); +} + +module_init(linux_dal_init); +module_exit(linux_dal_exit); + + diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/dal_kernel.h b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/dal_kernel.h new file mode 100644 index 000000000000..850a4cffa731 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/dal_kernel.h @@ -0,0 +1,171 @@ +/** + @file dal_kernel_io.h + + @author Copyright (C) 2012 Centec Networks Inc. All rights reserved. + + @date 2012-4-9 + + @version v2.0 + +*/ +#ifndef _DAL_KERNEL_H_ +#define _DAL_KERNEL_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(CONFIG_RESOURCES_64BIT) || defined(CONFIG_PHYS_ADDR_T_64BIT) +#define PHYS_ADDR_IS_64BIT +#endif + +#ifndef SDK_IN_USERMODE +#ifdef PHYS_ADDR_IS_64BIT +typedef long long intptr; +typedef unsigned long long uintptr; +#else +typedef int intptr; +typedef unsigned int uintptr; +#endif +#endif + +#define DAL_PCI_READ_ADDR 0x0 +#define DAL_PCI_READ_DATA 0xc +#define DAL_PCI_WRITE_ADDR 0x8 +#define DAL_PCI_WRITE_DATA 0x4 +#define DAL_PCI_STATUS 0x10 + +#define DAL_PCI_STATUS_IN_PROCESS 31 +#define DAL_PCI_STATUS_BAD_PARITY 5 +#define DAL_PCI_STATUS_CPU_ACCESS_ERR 4 +#define DAL_PCI_STATUS_READ_CMD 3 +#define DAL_PCI_STATUS_REGISTER_ERR 1 +#define DAL_PCI_STATUS_REGISTER_ACK 0 + +#define DAL_PCI_ACCESS_TIMEOUT 0x64 + +#define DAL_NAME "linux_dal" /* "linux_dal" */ + +#define DAL_DEV_MAJOR 198 + +#define DAL_DEV_INTR_MAJOR_BASE 200 + +#define DAL_DEV_NAME "/dev/" DAL_NAME +#define DAL_ONE_KB 1024 +#define DAL_ONE_MB (1024*1024) +struct dal_chip_parm_s +{ + unsigned int lchip; /*tmp should be uint8*/ + unsigned int fpga_id; /*tmp add*/ + unsigned int reg_addr; + unsigned int value; +}; +typedef struct dal_chip_parm_s dal_chip_parm_t; + +struct dal_intr_parm_s +{ + unsigned int irq; + unsigned int enable; +}; +typedef struct dal_intr_parm_s dal_intr_parm_t; + +struct dal_irq_mapping_s +{ + unsigned int hw_irq; + unsigned int sw_irq; +}; +typedef struct dal_irq_mapping_s dal_irq_mapping_t; + +struct dal_user_dev_s +{ + unsigned int chip_num; /*output: local chip number*/ + unsigned int lchip; /*input: local chip id*/ + unsigned int phy_base0; /* low 32bits physical base address */ + unsigned int phy_base1; /* high 32bits physical base address */ + unsigned int bus_no; + unsigned int dev_no; + unsigned int fun_no; + void* virt_base[2]; /* Virtual base address; this must be last member */ +}; +typedef struct dal_user_dev_s dal_user_dev_t; + +struct dma_info_s +{ + unsigned int lchip; + unsigned int phy_base; + unsigned int phy_base_hi; + unsigned int size; + unsigned int* virt_base; +}; +typedef struct dma_info_s dma_info_t; + +struct dal_pci_cfg_ioctl_s +{ + unsigned int lchip; /* Device ID */ + unsigned int offset; + unsigned int value; +}; +typedef struct dal_pci_cfg_ioctl_s dal_pci_cfg_ioctl_t; + +struct dal_msi_info_s +{ + unsigned int lchip; + unsigned int irq_base; + unsigned int irq_num; +}; +typedef struct dal_msi_info_s dal_msi_info_t; + +struct dal_intr_info_s +{ + unsigned int irq; + unsigned int irq_idx; +}; +typedef struct dal_intr_info_s dal_intr_info_t; + +struct dal_dma_cache_info_s +{ + unsigned long ptr; + unsigned int length; +}; +typedef struct dal_dma_cache_info_s dal_dma_cache_info_t; + +#define CMD_MAGIC 'C' +#define CMD_WRITE_CHIP _IO(CMD_MAGIC, 0) /* for humber ioctrol*/ +#define CMD_READ_CHIP _IO(CMD_MAGIC, 1) /* for humber ioctrol*/ +#define CMD_GET_DEVICES _IO(CMD_MAGIC, 2) +#define CMD_GET_DAL_VERSION _IO(CMD_MAGIC, 3) +#define CMD_PCI_CONFIG_WRITE _IO(CMD_MAGIC, 4) +#define CMD_PCI_CONFIG_READ _IO(CMD_MAGIC, 5) +#define CMD_GET_DMA_INFO _IO(CMD_MAGIC, 6) +#define CMD_REG_INTERRUPTS _IO(CMD_MAGIC, 7) +#define CMD_UNREG_INTERRUPTS _IO(CMD_MAGIC, 8) +#define CMD_EN_INTERRUPTS _IO(CMD_MAGIC, 9) +#define CMD_I2C_READ _IO(CMD_MAGIC, 10) +#define CMD_I2C_WRITE _IO(CMD_MAGIC, 11) +#define CMD_GET_MSI_INFO _IO(CMD_MAGIC, 12) +#define CMD_SET_MSI_CAP _IO(CMD_MAGIC, 13) +#define CMD_IRQ_MAPPING _IO(CMD_MAGIC, 14) +#define CMD_GET_INTR_INFO _IO(CMD_MAGIC, 15) +#define CMD_CACHE_INVAL _IO(CMD_MAGIC, 16) +#define CMD_CACHE_FLUSH _IO(CMD_MAGIC, 17) + +enum dal_version_e +{ + VERSION_MIN, + VERSION_1DOT0, + VERSION_1DOT1, + VERSION_1DOT2, + + VERSION_MAX +}; +typedef enum dal_version_e dal_version_t; + +/* We try to assemble a contiguous segment from chunks of this size */ +#define DMA_BLOCK_SIZE (512 * DAL_ONE_KB) + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/dal_mpool.c b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/dal_mpool.c new file mode 100644 index 000000000000..5aca222a138f --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/dal_mpool.c @@ -0,0 +1,350 @@ +#include "dal_mpool.h" + +#ifdef __KERNEL__ +#include +#include + +#define DAL_MALLOC(x) kmalloc(x, GFP_ATOMIC) +#define DAL_FREE(x) kfree(x) + +static spinlock_t dal_mpool_lock; +#define MPOOL_LOCK_INIT() spin_lock_init(&dal_mpool_lock) +#define MPOOL_LOCK() unsigned long flags; spin_lock_irqsave(&dal_mpool_lock, flags) +#define MPOOL_UNLOCK() spin_unlock_irqrestore(&dal_mpool_lock, flags) +#define DAL_PRINT(fmt,arg...) printk(fmt,##arg) +#else /* !__KERNEL__*/ + +#include +#include "sal.h" +#define DAL_MALLOC(x) malloc(x) +#define DAL_FREE(x) free(x) +static sal_mutex_t* dal_mpool_lock; +#define MPOOL_LOCK_INIT() sal_mutex_create(&dal_mpool_lock) +#define MPOOL_LOCK() sal_mutex_lock(dal_mpool_lock) +#define MPOOL_UNLOCK() sal_mutex_unlock(dal_mpool_lock) +#define DAL_PRINT(fmt,arg...) sal_printf(fmt,##arg) + +#endif /* __KERNEL__ */ + + + +dal_mpool_mem_t* g_free_block_ptr = NULL; + +/* System cache line size */ +#ifndef DAL_CACHE_LINE_BYTES +#define DAL_CACHE_LINE_BYTES 256 +#endif + +#define DAL_MAX_CHIP_NUM 32 +static dal_mpool_mem_t* p_desc_pool[DAL_MAX_CHIP_NUM] = {0}; +static dal_mpool_mem_t* p_data_pool[DAL_MAX_CHIP_NUM] = {0}; + +int +dal_mpool_init(void) +{ + MPOOL_LOCK_INIT(); + return 0; +} + +dal_mpool_mem_t* +_dal_mpool_create(void* base, int size, int type) +{ + dal_mpool_mem_t* head = NULL; + dal_mpool_mem_t* tail = NULL; + + head = (dal_mpool_mem_t*)DAL_MALLOC(sizeof(dal_mpool_mem_t)); + if (head == NULL) + { + return NULL; + } + + tail = (dal_mpool_mem_t*)DAL_MALLOC(sizeof(dal_mpool_mem_t)); + if (tail == NULL) + { + DAL_FREE(head); + return NULL; + } + + head->size = tail->size = 0; + head->type = type; + head->address = base; + tail->address = head->address + size; + head->next = tail; + tail->next = NULL; + + return head; +} + +dal_mpool_mem_t* +dal_mpool_create(unsigned char lchip, void* base, int size) +{ + dal_mpool_mem_t* head = NULL; + int mod = (int)(((unsigned long)base) & (DAL_CACHE_LINE_BYTES - 1)); + + MPOOL_LOCK(); + + if (mod) + { + base = (char*)base + (DAL_CACHE_LINE_BYTES - mod); + size -= (DAL_CACHE_LINE_BYTES - mod); + } + + size &= ~(DAL_CACHE_LINE_BYTES - 1); + + /* init for common linkptr, only used for GB */ + head = _dal_mpool_create(base, size, DAL_MPOOL_TYPE_USELESS); + if (NULL == head) + { + MPOOL_UNLOCK(); + return NULL; + } + + /* init for desc linkptr */ + p_desc_pool[lchip] = _dal_mpool_create(base, DAL_MPOOL_MAX_DESX_SIZE, DAL_MPOOL_TYPE_DESC); + if (NULL == p_desc_pool[lchip]) + { + MPOOL_UNLOCK(); + DAL_FREE(head->next); + DAL_FREE(head); + return NULL; + } + + /* init for data linkptr */ + p_data_pool[lchip] = _dal_mpool_create(((char*)base+DAL_MPOOL_MAX_DESX_SIZE), (size - DAL_MPOOL_MAX_DESX_SIZE), DAL_MPOOL_TYPE_DATA); + if (NULL == p_data_pool[lchip]) + { + MPOOL_UNLOCK(); + DAL_FREE(head->next); + DAL_FREE(head); + DAL_FREE(p_desc_pool[lchip]->next); + DAL_FREE(p_desc_pool[lchip]); + return NULL; + } + + MPOOL_UNLOCK(); + + return head; +} + +dal_mpool_mem_t* +_dal_mpool_alloc_comon(dal_mpool_mem_t* ptr, int size, int type) +{ + dal_mpool_mem_t* new_ptr = NULL; + + while (ptr && ptr->next) + { + if (ptr->next->address - (ptr->address + ptr->size) >= size) + { + break; + } + + ptr = ptr->next; + } + + if (!(ptr && ptr->next)) + { + return NULL; + } + + new_ptr = DAL_MALLOC(sizeof(dal_mpool_mem_t)); + if (!new_ptr) + { + return NULL; + } + + new_ptr->type = type; + new_ptr->address = ptr->address + ptr->size; + new_ptr->size = size; + new_ptr->next = ptr->next; + ptr->next = new_ptr; + + return new_ptr; +} + +void* +dal_mpool_alloc(unsigned char lchip, dal_mpool_mem_t* pool, int size, int type) +{ + dal_mpool_mem_t* ptr = NULL; + dal_mpool_mem_t* new_ptr = NULL; + int mod; + + MPOOL_LOCK(); + + mod = size & (DAL_CACHE_LINE_BYTES - 1); + if (mod != 0) + { + size += (DAL_CACHE_LINE_BYTES - mod); + } + + switch(type) + { + case DAL_MPOOL_TYPE_USELESS: + ptr = pool; + new_ptr = _dal_mpool_alloc_comon(ptr, size, type); + if (NULL == new_ptr) + { + MPOOL_UNLOCK(); + return NULL; + } + break; + case DAL_MPOOL_TYPE_DESC: + ptr = p_desc_pool[lchip]; + new_ptr = _dal_mpool_alloc_comon(ptr, size, type); + if (NULL == new_ptr) + { + MPOOL_UNLOCK(); + return NULL; + } + break; + case DAL_MPOOL_TYPE_DATA: + ptr = p_data_pool[lchip]; + new_ptr = _dal_mpool_alloc_comon(ptr, size, type); + if (NULL == new_ptr) + { + MPOOL_UNLOCK(); + return NULL; + } + break; + default: + MPOOL_UNLOCK(); + return NULL; + break; + } + + MPOOL_UNLOCK(); + if( NULL == new_ptr ) + { + return NULL; + } + + return new_ptr->address; +} + +void +_dal_mpool_free(dal_mpool_mem_t* ptr, void* addr, int type) +{ + unsigned char* address = (unsigned char*)addr; + dal_mpool_mem_t* prev = NULL; + + while (ptr && ptr->next) + { + if (ptr->next->address == address) + { + break; + } + + ptr = ptr->next; + } + + if (ptr && ptr->next) + { + prev = ptr; + ptr = ptr->next; + prev->next = ptr->next; + DAL_FREE(ptr); + } + + return; +} + +void +dal_mpool_free(unsigned char lchip, dal_mpool_mem_t* pool, void* addr) +{ + dal_mpool_mem_t* ptr = pool; + + MPOOL_LOCK(); + + switch(pool->type) + { + case DAL_MPOOL_TYPE_USELESS: + ptr = pool; + _dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_USELESS); + break; + case DAL_MPOOL_TYPE_DESC: + ptr = p_desc_pool[lchip]; + _dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_DESC); + break; + case DAL_MPOOL_TYPE_DATA: + ptr = p_data_pool[lchip]; + _dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_DATA); + break; + default: + break; + } + + MPOOL_UNLOCK(); + return; +} + +int +dal_mpool_destroy(unsigned char lchip, dal_mpool_mem_t* pool) +{ + dal_mpool_mem_t* ptr, * next; + + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = next) + { + next = ptr->next; + DAL_FREE(ptr); + } + + for (ptr = p_desc_pool[lchip]; ptr; ptr = next) + { + next = ptr->next; + DAL_FREE(ptr); + } + + for (ptr = p_data_pool[lchip]; ptr; ptr = next) + { + next = ptr->next; + DAL_FREE(ptr); + } + + MPOOL_UNLOCK(); + + return 0; +} + +int +dal_mpool_usage(dal_mpool_mem_t* pool, int type) +{ + int usage = 0; + dal_mpool_mem_t* ptr; + + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = ptr->next) + { + if (ptr->type == type || ptr->type == -1) + { + usage += ptr->size; + } + } + + MPOOL_UNLOCK(); + + return usage; +} + +int +dal_mpool_debug(dal_mpool_mem_t* pool) +{ + dal_mpool_mem_t* ptr; + int index = 0; + + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = ptr->next) + { +// DAL_PRINT("%2dst mpool block: address=0x%8x, size=0x%x \n", index, (unsigned int)ptr->address, ptr->size); + DAL_PRINT("%2dst mpool block: address=%p, size=0x%x \n", index, ptr->address, ptr->size); // note + index++; + } + + MPOOL_UNLOCK(); + + return 0; +} + + diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/dal_mpool.h b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/dal_mpool.h new file mode 100644 index 000000000000..d93f88868136 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/dal_mpool.h @@ -0,0 +1,72 @@ +/** + @file dal_mpool.h + + @author Copyright (C) 2011 Centec Networks Inc. All rights reserved. + + @date 2012-5-10 + + @version v2.0 + + This file contains the dma memory init, allocation and free APIs +*/ + +#ifndef _DMA_MPOOL_H +#define _DMA_MPOOL_H +#ifdef __cplusplus +extern "C" { +#endif + +#define DAL_MPOOL_MAX_DESX_SIZE (1024*1024) + +enum dal_mpool_type_e +{ + DAL_MPOOL_TYPE_USELESS, /* just compatible with GB */ + DAL_MPOOL_TYPE_DESC, /* dma mpool op for desc */ + DAL_MPOOL_TYPE_DATA /* dma mpool op for data */ +}; +typedef enum dal_mpool_type_e dal_mpool_type_t; + +struct dal_mpool_mem_s +{ + unsigned char* address; + int size; + int type; + struct dal_mpool_mem_s* next; +}; +typedef struct dal_mpool_mem_s dal_mpool_mem_t; + +/** + @brief This function is to alloc dma memory + + @param[in] size size of memory + + @return NULL + +*/ +extern int +dal_mpool_init(void); + +extern dal_mpool_mem_t* +dal_mpool_create(unsigned char lchip, void* base_ptr, int size); + +extern void* +dal_mpool_alloc(unsigned char lchip, dal_mpool_mem_t* pool, int size, int type); + +extern void +dal_mpool_free(unsigned char lchip, dal_mpool_mem_t* pool, void* addr); + +extern int +dal_mpool_destroy(unsigned char lchip, dal_mpool_mem_t* pool); + +extern int +dal_mpool_usage(dal_mpool_mem_t* pool, int type); + +extern int +dal_mpool_debug(dal_mpool_mem_t* pool); +#ifdef __cplusplus +} +#endif + +#endif /* !_DMA_MPOOL_H */ + + diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/scripts/48x2q4z_platform.sh b/platform/centec/sonic-platform-modules-e582/48x2q4z/scripts/48x2q4z_platform.sh new file mode 100755 index 000000000000..2f6583bc487b --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/scripts/48x2q4z_platform.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +#platform init script for centec e582-48x2q4z + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # I801 adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus I801 adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find I801" && exit 1 +} + +init_devnum + +if [ "$1" == "init" ]; then + #install drivers and dependencies + depmod -a + modprobe i2c-i801 + modprobe i2c-dev + modprobe i2c-mux + modprobe i2c-smbus + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + i2cset -y 0 0x58 0x8 0x3f + modprobe lm77 + modprobe tun + modprobe dal + modprobe centec_at24c64 + modprobe centec_e582_48x2q4z_platform + i2cset -y 15 0x21 0x18 0x0 + i2cset -y 15 0x21 0x19 0x0 + i2cset -y 15 0x21 0x1a 0xff + i2cset -y 15 0x21 0x1b 0xff + i2cset -y 15 0x21 0x1c 0xff + i2cset -y 15 0x21 0x8 0x0 + i2cset -y 15 0x21 0x9 0x0 + i2cset -y 15 0x22 0x18 0xff + i2cset -y 15 0x22 0x19 0x0 + i2cset -y 15 0x22 0x1a 0x0 + i2cset -y 15 0x22 0x1b 0xff + i2cset -y 15 0x22 0x1c 0xff + i2cset -y 15 0x22 0x9 0x0 + i2cset -y 15 0x22 0xa 0x0 + i2cset -y 16 0x21 0x18 0x0 + i2cset -y 16 0x21 0x19 0x0 + i2cset -y 16 0x21 0x1a 0xff + i2cset -y 16 0x21 0x1b 0xff + i2cset -y 16 0x21 0x1c 0xff + i2cset -y 16 0x21 0x8 0x0 + i2cset -y 16 0x21 0x9 0x0 + i2cset -y 17 0x22 0x18 0xff + i2cset -y 17 0x22 0x19 0x0 + i2cset -y 17 0x22 0x1a 0xff + i2cset -y 17 0x22 0x1b 0x0 + i2cset -y 17 0x22 0x1c 0xff + i2cset -y 17 0x22 0x9 0x0 + i2cset -y 17 0x22 0xb 0x0c + + #start platform monitor + rm -rf /usr/bin/platform_monitor + ln -s /usr/bin/48x2q4z_platform_monitor.py /usr/bin/platform_monitor + python /usr/bin/platform_monitor & +elif [ "$1" == "deinit" ]; then + kill -9 $(pidof platform_monitor) > /dev/null 2>&1 + rm -rf /usr/bin/platform_monitor + modprobe -r centec_e582_48x2q4z_platform + modprobe -r centec_at24c64 + modprobe -r dal + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev +else + echo "e582-48x2q4z_platform : Invalid option !" +fi diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/scripts/48x2q4z_platform_monitor.py b/platform/centec/sonic-platform-modules-e582/48x2q4z/scripts/48x2q4z_platform_monitor.py new file mode 100644 index 000000000000..2d8d2c440a8f --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/scripts/48x2q4z_platform_monitor.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Module contains an implementation of sfp presence scan logic +# +############################################################################# + +try: + import os + import os.path + import threading + import time + import logging + import struct + import syslog + import swsssdk + from socket import * + from select import * +except ImportError, e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("centec-pmon") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + +PORT_NUMBER = (48+6) + +class PlatformMonitor: + + """init board platform default config""" + def __init__(self): + """[ctlid, slavedevid]""" + self.fiber_mapping = [(0, 0)] # res + self.fiber_mapping.extend([(1, 7), (1, 6), (1, 5), (1, 4), (1, 3), (1, 2), (1, 1), (1, 0)]) # panel port 1~8 + self.fiber_mapping.extend([(1, 15), (1, 14), (1, 13), (1, 12), (1, 11), (1, 10), (1, 9), (1, 8)]) # panel port 9~16 + self.fiber_mapping.extend([(1, 19), (1, 17), (1, 16), (1, 18), (0, 7), (0, 6), (0, 5), (0, 4)]) # panel port 17~24 + self.fiber_mapping.extend([(0, 3), (0, 2), (0, 1), (0, 0), (0, 15), (0, 14), (0, 13), (0, 12)]) # panel port 25~32 + self.fiber_mapping.extend([(0, 11), (0, 10), (0, 9), (0, 8), (0, 23), (0, 22), (0, 21), (0, 20)]) # panel port 33~40 + self.fiber_mapping.extend([(0, 19), (0, 18), (0, 17), (0, 16), (0, 31), (0, 26), (0, 29), (0, 27)]) # panel port 41~48 + self.fiber_mapping.extend([(0, 24), (0, 25), (1, 23), (1, 22), (1, 21), (1, 20)]) # panel port 49~54 + + self.udpClient = socket(AF_INET, SOCK_DGRAM) + self.sfp_present = [0]*(PORT_NUMBER+1) + self.sfp_enable = [0]*(PORT_NUMBER+1) + self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" + self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" + self.sfp_scan_timer = 0 + + def is_qsfp(self, port): + if port <= 48: + return False + else: + return True + + def get_sfp_present(self, port): + with open(self.f_sfp_present.format(port), 'r') as sfp_file: + return int(sfp_file.read()) + + def set_sfp_present(self, port, present): + self.sfp_present[port] = present + + def set_sfp_enable(self, port, enable): + if self.is_qsfp(port): + if enable: + with open(self.f_sfp_enable.format(port), 'w') as sfp_file: + sfp_file.write("1") + self.sfp_enable[port] = 1 + else: + with open(self.f_sfp_enable.format(port), 'w') as sfp_file: + sfp_file.write("0") + self.sfp_enable[port] = 0 + else: + (ctlid, devid) = self.fiber_mapping[port] + req = struct.pack('=HHHBBHIBBBBI', 0, 9, 16, ctlid, devid, 0x50, 0, 0x56, 1, 0xf, 0, 1) + self.udpClient.sendto(req, ('localhost', 8101)) + rsp, addr = self.udpClient.recvfrom(1024) + rsp_data = struct.unpack('=HHHBBHIBBBBIi512B', rsp) + enable_v = rsp_data[13] + if enable: + enable_v &= 0xf0 + else: + enable_v |= 0x0f + data = struct.pack('=HHHBBHBBBB', 0, 11, 8, ctlid, 0x56, 0x50, devid, enable_v, 0xf, 0) + self.udpClient.sendto(data, ('localhost', 8101)) + DBG_PRINT("set sfp{} to {}".format(port, ("enable" if enable else "disable"))) + + def initialize_configdb(self): + try: + f_mac = os.popen('ip link show eth0 | grep ether | awk \'{print $2}\'') + mac_addr = f_mac.read(17) + last_byte = mac_addr[-2:] + aligned_last_byte = format(int(int(str(last_byte), 16) + 1), '02x') + mac_addr = mac_addr[:-2] + aligned_last_byte + DBG_PRINT("start connect swss config-db to set device mac-address") + swss = swsssdk.SonicV2Connector() + swss.connect(swss.CONFIG_DB) + swss.set(swss.CONFIG_DB, "DEVICE_METADATA|localhost", 'mac', mac_addr) + mac_addr = swss.get(swss.CONFIG_DB, "DEVICE_METADATA|localhost", 'mac') + DBG_PRINT("set device mac-address: %s" % mac_addr) + except IOError as e: + DBG_PRINT(str(e)) + + def initialize_rpc(self): + while True: + try: + r_sel = [self.udpClient] + echo_req = struct.pack('=HHH', 0, 1, 0) + self.udpClient.sendto(echo_req, ('localhost', 8101)) + result = select(r_sel, [], [], 1) + if self.udpClient in result[0]: + echo_rsp, srv_addr = self.udpClient.recvfrom(1024) + if echo_rsp: + break + DBG_PRINT("connect to sdk rpc server timeout, try again.") + except IOError as e: + DBG_PRINT(str(e)) + + DBG_PRINT("connect to sdk rpc server success.") + + def initialize_gpio(self): + # set gpio 1,2,3,4,5,6,7,8 output mode + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 1, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 2, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 3, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 4, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 5, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 6, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 7, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 8, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + # set gpio 1,2,3,4,5,6,7,8 output 0 to reset i2c bridge + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 1, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 2, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 3, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 4, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 5, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 6, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 7, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 8, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + # set gpio 1,2,3,4,5,6,7,8 output 1 to release i2c bridge + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 1, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 2, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 3, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 4, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 5, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 6, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 7, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 8, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + DBG_PRINT("config ctc chip gpio done.") + + def initialize_sfp(self): + try: + for port in range(1, PORT_NUMBER+1): + if self.get_sfp_present(port): + self.set_sfp_present(port, 1) + self.set_sfp_enable(port, 1) + else: + self.set_sfp_present(port, 0) + self.set_sfp_enable(port, 0) + except IOError as e: + DBG_PRINT(str(e)) + + def initialize(self): + DBG_PRINT("start connect to sdk rpc server.") + + self.initialize_configdb() + self.initialize_rpc() + self.initialize_gpio() + self.initialize_sfp() + + def sfp_scan(self): + try: + for port in range(1, PORT_NUMBER+1): + cur_present = self.get_sfp_present(port) + if self.sfp_present[port] != cur_present: + self.set_sfp_present(port, cur_present) + self.set_sfp_enable(port, cur_present) + except IOError as e: + DBG_PRINT(str(e)) + + def start(self): + while True: + self.sfp_scan() + time.sleep(1) + +if __name__ == "__main__": + monitor = PlatformMonitor() + monitor.initialize() + monitor.start() + diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/service/48x2q4z_platform.service b/platform/centec/sonic-platform-modules-e582/48x2q4z/service/48x2q4z_platform.service new file mode 100644 index 000000000000..008db145b110 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/service/48x2q4z_platform.service @@ -0,0 +1,13 @@ +[Unit] +Description=Centec e582 48x2q4z platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-e582-48x2q4z start +ExecStop=-/etc/init.d/platform-modules-e582-48x2q4z stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/cfg/48x6q-modules.conf b/platform/centec/sonic-platform-modules-e582/48x6q/cfg/48x6q-modules.conf new file mode 100644 index 000000000000..7a7881c8c0d3 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/cfg/48x6q-modules.conf @@ -0,0 +1,14 @@ +# /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. + +i2c-i801 +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-pca954x +lm77 +adt7470 +tun diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/cfg/config_db.json b/platform/centec/sonic-platform-modules-e582/48x6q/cfg/config_db.json new file mode 100644 index 000000000000..995ac0444b99 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/cfg/config_db.json @@ -0,0 +1,302 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": 65100, + "deployment_id": null, + "hostname": "switch1", + "type": "LeafRouter", + "hwsku": "E582-48x6q" + + } + }, + "BGP_PEER_RANGE": {}, + "VLAN": {}, + "PORT": { + "Ethernet1": { + "alias": "eth-0-1", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet2": { + "alias": "eth-0-2", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet3": { + "alias": "eth-0-3", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet4": { + "alias": "eth-0-4", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet5": { + "alias": "eth-0-5", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet6": { + "alias": "eth-0-6", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet7": { + "alias": "eth-0-7", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet8": { + "alias": "eth-0-8", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet9": { + "alias": "eth-0-9", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet10": { + "alias": "eth-0-10", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet11": { + "alias": "eth-0-11", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet12": { + "alias": "eth-0-12", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet13": { + "alias": "eth-0-13", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet14": { + "alias": "eth-0-14", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet15": { + "alias": "eth-0-15", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet16": { + "alias": "eth-0-16", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet17": { + "alias": "eth-0-17", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet18": { + "alias": "eth-0-18", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet19": { + "alias": "eth-0-19", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet20": { + "alias": "eth-0-20", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet21": { + "alias": "eth-0-21", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet22": { + "alias": "eth-0-22", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet23": { + "alias": "eth-0-23", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet24": { + "alias": "eth-0-24", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet25": { + "alias": "eth-0-25", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet26": { + "alias": "eth-0-26", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet27": { + "alias": "eth-0-27", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet28": { + "alias": "eth-0-28", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet29": { + "alias": "eth-0-29", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet30": { + "alias": "eth-0-30", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet31": { + "alias": "eth-0-31", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet32": { + "alias": "eth-0-32", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet33": { + "alias": "eth-0-33", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet34": { + "alias": "eth-0-34", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet35": { + "alias": "eth-0-35", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet36": { + "alias": "eth-0-36", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet37": { + "alias": "eth-0-37", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet38": { + "alias": "eth-0-38", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet39": { + "alias": "eth-0-39", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet40": { + "alias": "eth-0-40", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet41": { + "alias": "eth-0-41", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet42": { + "alias": "eth-0-42", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet43": { + "alias": "eth-0-43", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet44": { + "alias": "eth-0-44", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet45": { + "alias": "eth-0-45", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet46": { + "alias": "eth-0-46", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet47": { + "alias": "eth-0-47", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet48": { + "alias": "eth-0-48", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet49": { + "alias": "eth-0-49", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet50": { + "alias": "eth-0-50", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet51": { + "alias": "eth-0-51", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet52": { + "alias": "eth-0-52", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet53": { + "alias": "eth-0-53", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet54": { + "alias": "eth-0-54", + "speed": "40000", + "mtu": "9100" + } + }, + "SYSLOG_SERVER": {}, + "VLAN_INTERFACE": {}, + "PORTCHANNEL_INTERFACE": {}, + "PORTCHANNEL": {}, + "MGMT_INTERFACE": {}, + "DHCP_SERVER": {}, + "LOOPBACK_INTERFACE": { + "Loopback0|127.0.0.1/8": {} + }, + "ACL_TABLE": {}, + "INTERFACE": { + "Ethernet1|192.168.1.1/24": {}, + "Ethernet2|192.168.2.1/24": {}, + "Ethernet3|192.168.3.1/24": {}, + "Ethernet4|192.168.4.1/24": {} + } +} diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/cfg/config_db_l2l3.json b/platform/centec/sonic-platform-modules-e582/48x6q/cfg/config_db_l2l3.json new file mode 100644 index 000000000000..ce6909f3a200 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/cfg/config_db_l2l3.json @@ -0,0 +1,610 @@ +{ + "QUEUE": { + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54|0-2": { + "wred_profile": "[WRED_PROFILE|AZURE_LOSSY]" + }, + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54|3-4": { + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]", + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54|5-7": { + "wred_profile": "[WRED_PROFILE|AZURE_LOSSY]" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS": { + "red_max_threshold": "32760", + "yellow_max_threshold": "32760", + "green_min_threshold": "4095", + "red_min_threshold": "4095", + "yellow_min_threshold": "4095", + "green_max_threshold": "32760", + "wred_yellow_enable": "true", + "wred_green_enable": "true" + }, + "AZURE_LOSSY": { + "red_max_threshold": "32760", + "yellow_max_threshold": "32760", + "green_min_threshold": "4095", + "red_min_threshold": "4095", + "yellow_min_threshold": "4095", + "green_max_threshold": "32760", + "wred_yellow_enable": "true", + "wred_green_enable": "true" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "56": "7", + "54": "6", + "28": "3", + "48": "6", + "29": "3", + "60": "7", + "61": "7", + "62": "7", + "63": "7", + "49": "6", + "34": "4", + "24": "3", + "25": "3", + "26": "3", + "27": "3", + "20": "2", + "21": "2", + "22": "2", + "23": "2", + "46": "5", + "47": "5", + "44": "5", + "45": "5", + "42": "5", + "43": "5", + "40": "5", + "41": "5", + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "5": "0", + "4": "0", + "7": "0", + "6": "0", + "9": "1", + "8": "1", + "35": "4", + "13": "1", + "12": "1", + "15": "1", + "58": "7", + "11": "1", + "10": "1", + "39": "4", + "38": "4", + "59": "7", + "14": "1", + "17": "2", + "16": "2", + "19": "2", + "18": "2", + "31": "3", + "30": "3", + "51": "6", + "36": "4", + "53": "6", + "52": "6", + "33": "4", + "55": "6", + "37": "4", + "32": "4", + "57": "7", + "50": "6" + } + }, + "DEVICE_METADATA": { + "localhost": { + "hwsku": "E582-48x6q", + "hostname": "switch1", + "bgp_asn": "None", + "deployment_id": "None", + "type": "LeafRouter" + } + }, + "PORT": { + "Ethernet1": { + "alias": "eth-0-1", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet2": { + "alias": "eth-0-2", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet3": { + "alias": "eth-0-3", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet4": { + "alias": "eth-0-4", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet5": { + "alias": "eth-0-5", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet6": { + "alias": "eth-0-6", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet7": { + "alias": "eth-0-7", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet8": { + "alias": "eth-0-8", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet9": { + "alias": "eth-0-9", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet10": { + "alias": "eth-0-10", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet11": { + "alias": "eth-0-11", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet12": { + "alias": "eth-0-12", + "speed": "1000", + "mtu": "9100" + }, + "Ethernet13": { + "alias": "eth-0-13", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet14": { + "alias": "eth-0-14", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet15": { + "alias": "eth-0-15", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet16": { + "alias": "eth-0-16", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet17": { + "alias": "eth-0-17", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet18": { + "alias": "eth-0-18", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet19": { + "alias": "eth-0-19", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet20": { + "alias": "eth-0-20", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet21": { + "alias": "eth-0-21", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet22": { + "alias": "eth-0-22", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet23": { + "alias": "eth-0-23", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet24": { + "alias": "eth-0-24", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet25": { + "alias": "eth-0-25", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet26": { + "alias": "eth-0-26", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet27": { + "alias": "eth-0-27", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet28": { + "alias": "eth-0-28", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet29": { + "alias": "eth-0-29", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet30": { + "alias": "eth-0-30", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet31": { + "alias": "eth-0-31", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet32": { + "alias": "eth-0-32", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet33": { + "alias": "eth-0-33", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet34": { + "alias": "eth-0-34", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet35": { + "alias": "eth-0-35", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet36": { + "alias": "eth-0-36", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet37": { + "alias": "eth-0-37", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet38": { + "alias": "eth-0-38", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet39": { + "alias": "eth-0-39", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet40": { + "alias": "eth-0-40", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet41": { + "alias": "eth-0-41", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet42": { + "alias": "eth-0-42", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet43": { + "alias": "eth-0-43", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet44": { + "alias": "eth-0-44", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet45": { + "alias": "eth-0-45", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet46": { + "alias": "eth-0-46", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet47": { + "alias": "eth-0-47", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet48": { + "alias": "eth-0-48", + "speed": "10000", + "mtu": "9100" + }, + "Ethernet49": { + "alias": "eth-0-49", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet50": { + "alias": "eth-0-50", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet51": { + "alias": "eth-0-51", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet52": { + "alias": "eth-0-52", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet53": { + "alias": "eth-0-53", + "speed": "40000", + "mtu": "9100" + }, + "Ethernet54": { + "alias": "eth-0-54", + "speed": "40000", + "mtu": "9100" + } + }, + "PORT_QOS_MAP": { + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54": { + "pfc_enable": "3,4", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP|AZURE]" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type": "DWRR", + "weight": "25" + }, + "scheduler.1": { + "type": "DWRR", + "weight": "30" + }, + "scheduler.2": { + "type": "DWRR", + "weight": "20" + } + }, + "VLAN": { + "Vlan500": { + "dhcp_servers": [ + "192.168.5.1", + "192.168.5.2", + "192.168.5.3", + "192.168.5.4" + ], + "members": [ + "Ethernet5", + "Ethernet6", + "Ethernet7", + "Ethernet8" + ], + "vlanid": "500" + }, + "Vlan600": { + "dhcp_servers": [ + "192.168.6.1", + "192.168.6.2", + "192.168.6.3", + "192.168.6.4" + ], + "members": [ + "Ethernet5", + "Ethernet6" + ], + "vlanid": "600" + }, + "Vlan700": { + "dhcp_servers": [ + "192.168.7.1", + "192.168.7.2", + "192.168.7.3", + "192.168.7.4" + ], + "members": [ + "Ethernet5", + "Ethernet7" + ], + "vlanid": "700" + }, + "Vlan800": { + "dhcp_servers": [ + "192.168.8.1", + "192.168.8.2", + "192.168.8.3", + "192.168.8.4" + ], + "members": [ + "Ethernet5", + "Ethernet8" + ], + "vlanid": "800" + } + }, + "VLAN_MEMBER": { + "Vlan500|Ethernet5": { + "tagging_mode": "tagged" + }, + "Vlan500|Ethernet6": { + "tagging_mode": "untagged" + }, + "Vlan500|Ethernet7": { + "tagging_mode": "untagged" + }, + "Vlan500|Ethernet8": { + "tagging_mode": "untagged" + }, + "Vlan600|Ethernet5": { + "tagging_mode": "tagged" + }, + "Vlan600|Ethernet6": { + "tagging_mode": "tagged" + }, + "Vlan700|Ethernet5": { + "tagging_mode": "tagged" + }, + "Vlan700|Ethernet7": { + "tagging_mode": "tagged" + }, + "Vlan800|Ethernet5": { + "tagging_mode": "tagged" + }, + "Vlan800|Ethernet8": { + "tagging_mode": "tagged" + } + }, + "INTERFACE": { + "Ethernet1|192.168.1.1/24": {}, + "Ethernet2|192.168.2.1/24": {}, + "Ethernet3|192.168.3.1/24": {}, + "Ethernet4|192.168.4.1/24": {} + }, + "VLAN_INTERFACE": { + "Vlan500|192.168.5.1/24": {}, + "Vlan600|192.168.6.1/24": {}, + "Vlan700|192.168.7.1/24": {}, + "Vlan800|192.168.8.1/24": {} + }, + "LOOPBACK_INTERFACE": { + "Loopback0|127.0.0.1/8": {} + }, + "CABLE_LENGTH": { + "AZURE": { + "Ethernet8": "40m", + "Ethernet9": "40m", + "Ethernet2": "40m", + "Ethernet3": "40m", + "Ethernet1": "40m", + "Ethernet6": "40m", + "Ethernet7": "40m", + "Ethernet4": "40m", + "Ethernet5": "40m", + "Ethernet22": "40m", + "Ethernet50": "40m", + "Ethernet51": "40m", + "Ethernet52": "40m", + "Ethernet53": "40m", + "Ethernet54": "40m", + "Ethernet38": "40m", + "Ethernet39": "40m", + "Ethernet18": "40m", + "Ethernet19": "40m", + "Ethernet14": "40m", + "Ethernet15": "40m", + "Ethernet16": "40m", + "Ethernet17": "40m", + "Ethernet10": "40m", + "Ethernet11": "40m", + "Ethernet12": "40m", + "Ethernet35": "40m", + "Ethernet37": "40m", + "Ethernet32": "40m", + "Ethernet33": "40m", + "Ethernet30": "40m", + "Ethernet31": "40m", + "Ethernet49": "40m", + "Ethernet48": "40m", + "Ethernet47": "40m", + "Ethernet36": "40m", + "Ethernet45": "40m", + "Ethernet44": "40m", + "Ethernet43": "40m", + "Ethernet42": "40m", + "Ethernet41": "40m", + "Ethernet40": "40m", + "Ethernet29": "40m", + "Ethernet28": "40m", + "Ethernet34": "40m", + "Ethernet46": "40m", + "Ethernet21": "40m", + "Ethernet20": "40m", + "Ethernet23": "40m", + "Ethernet13": "40m", + "Ethernet25": "40m", + "Ethernet24": "40m", + "Ethernet27": "40m", + "Ethernet26": "40m" + } + }, + "CRM": { + "Config": { + "acl_table_threshold_type": "percentage", + "nexthop_group_threshold_type": "percentage", + "fdb_entry_high_threshold": "85", + "acl_entry_threshold_type": "percentage", + "ipv6_neighbor_low_threshold": "70", + "nexthop_group_member_low_threshold": "70", + "acl_group_high_threshold": "85", + "ipv4_route_high_threshold": "85", + "acl_counter_high_threshold": "85", + "ipv4_route_low_threshold": "70", + "ipv4_route_threshold_type": "percentage", + "ipv4_neighbor_low_threshold": "70", + "acl_group_threshold_type": "percentage", + "ipv4_nexthop_high_threshold": "85", + "ipv6_route_threshold_type": "percentage", + "nexthop_group_low_threshold": "70", + "ipv4_neighbor_high_threshold": "85", + "ipv6_route_high_threshold": "85", + "ipv6_nexthop_threshold_type": "percentage", + "polling_interval": "300", + "ipv4_nexthop_threshold_type": "percentage", + "acl_group_low_threshold": "70", + "acl_entry_low_threshold": "70", + "nexthop_group_member_threshold_type": "percentage", + "ipv4_nexthop_low_threshold": "70", + "acl_counter_threshold_type": "percentage", + "ipv6_neighbor_high_threshold": "85", + "nexthop_group_member_high_threshold": "85", + "acl_table_low_threshold": "70", + "fdb_entry_threshold_type": "percentage", + "ipv6_neighbor_threshold_type": "percentage", + "acl_table_high_threshold": "85", + "ipv6_nexthop_low_threshold": "70", + "acl_counter_low_threshold": "70", + "ipv4_neighbor_threshold_type": "percentage", + "nexthop_group_high_threshold": "85", + "ipv6_route_low_threshold": "70", + "acl_entry_high_threshold": "85", + "fdb_entry_low_threshold": "70", + "ipv6_nexthop_high_threshold": "85" + } + } +} diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/modules/Makefile b/platform/centec/sonic-platform-modules-e582/48x6q/modules/Makefile new file mode 100644 index 000000000000..25df81bba426 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := centec_e582_48x6q_platform.o dal.o centec_at24c64.o +dal-y := dal_kernel.o dal_mpool.o diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/modules/centec_at24c64.c b/platform/centec/sonic-platform-modules-e582/48x6q/modules/centec_at24c64.c new file mode 100644 index 000000000000..e1835df88625 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/modules/centec_at24c64.c @@ -0,0 +1,602 @@ +/* + * at24.c - handle most I2C EEPROMs + * + * Copyright (C) 2005-2007 David Brownell + * Copyright (C) 2008 Wolfram Sang, Pengutronix + * + * 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 +#include +#include +#include +#include + +/* + * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. + * Differences between different vendor product lines (like Atmel AT24C or + * MicroChip 24LC, etc) won't much matter for typical read/write access. + * There are also I2C RAM chips, likewise interchangeable. One example + * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes). + * + * However, misconfiguration can lose data. "Set 16-bit memory address" + * to a part with 8-bit addressing will overwrite data. Writing with too + * big a page size also loses data. And it's not safe to assume that the + * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC + * uses 0x51, for just one example. + * + * Accordingly, explicit board-specific configuration data should be used + * in almost all cases. (One partial exception is an SMBus used to access + * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.) + * + * So this driver uses "new style" I2C driver binding, expecting to be + * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or + * similar kernel-resident tables; or, configuration data coming from + * a bootloader. + * + * Other than binding model, current differences from "eeprom" driver are + * that this one handles write access and isn't restricted to 24c02 devices. + * It also handles larger devices (32 kbit and up) with two-byte addresses, + * which won't work on pure SMBus systems. + */ + +struct at24_data { + struct at24_platform_data chip; + int use_smbus; + + /* + * Lock protects against activities from other Linux tasks, + * but not from changes by other I2C masters. + */ + struct mutex lock; + struct bin_attribute bin; + + u8 *writebuf; + unsigned write_max; + unsigned num_addresses; + + /* + * Some chips tie up multiple I2C addresses; dummy devices reserve + * them for us, and we'll use them with SMBus calls. + */ + struct i2c_client *client[]; +}; + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = 128; +module_param(io_limit, uint, 0); +MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)"); + +/* + * Specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; +module_param(write_timeout, uint, 0); +MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)"); + +#define AT24_SIZE_BYTELEN 5 +#define AT24_SIZE_FLAGS 8 + +#define AT24_BITMASK(x) (BIT(x) - 1) + +/* create non-zero magic value for given eeprom parameters */ +#define AT24_DEVICE_MAGIC(_len, _flags) \ + ((1 << AT24_SIZE_FLAGS | (_flags)) \ + << AT24_SIZE_BYTELEN | ilog2(_len)) + +static const struct i2c_device_id at24_ctc_ids[] = { + { "24c64-ctc", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16 | AT24_FLAG_READONLY | AT24_FLAG_IRUGO) }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, at24_ctc_ids); + +/*-------------------------------------------------------------------------*/ + +/* + * This routine supports chips which consume multiple I2C addresses. It + * computes the addressing information to be used for a given r/w request. + * Assumes that sanity checks for offset happened at sysfs-layer. + */ +static struct i2c_client *at24_translate_offset(struct at24_data *at24, + unsigned *offset) +{ + unsigned i = 0; + + if (at24->chip.flags & AT24_FLAG_ADDR16) { + i = *offset >> 16; + *offset &= 0xffff; + } else { + i = *offset >> 8; + *offset &= 0xff; + } + + return at24->client[i]; +} + +static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, + unsigned offset, size_t count) +{ + struct i2c_msg msg[2]; + struct i2c_client *client; + unsigned long timeout, read_time; + int status; + + memset(msg, 0, sizeof(msg)); + + /* + * REVISIT some multi-address chips don't rollover page reads to + * the next slave address, so we may need to truncate the count. + * Those chips might need another quirk flag. + * + * If the real hardware used four adjacent 24c02 chips and that + * were misconfigured as one 24c08, that would be a similar effect: + * one "eeprom" file not four, but larger reads would fail when + * they crossed certain pages. + */ + + /* + * Slave address and byte offset derive from the offset. Always + * set the byte address; on a multi-master board, another master + * may have changed the chip's "current" address pointer. + */ + client = at24_translate_offset(at24, &offset); + + if (count > io_limit) + count = io_limit; + + count = 1; + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + read_time = jiffies; + + status = i2c_smbus_write_byte_data(client, (offset >> 8) & 0x0ff, offset & 0x0ff ); + status = i2c_smbus_read_byte(client); + if (status >= 0) { + buf[0] = status; + status = count; + } + + dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", count, offset, status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(read_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t at24_read(struct at24_data *at24, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) + return count; + + memset(buf, 0, count); + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + ssize_t status; + + status = at24_eeprom_read(at24, buf, off, count); + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&at24->lock); + + return retval; +} + +static ssize_t at24_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct at24_data *at24; + + at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return at24_read(at24, buf, off, count); +} + + +/* + * Note that if the hardware write-protect pin is pulled high, the whole + * chip is normally write protected. But there are plenty of product + * variants here, including OTP fuses and partial chip protect. + * + * We only use page mode writes; the alternative is sloooow. This routine + * writes at most one page. + */ +static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + unsigned offset, size_t count) +{ + struct i2c_client *client; + ssize_t status; + unsigned long timeout, write_time; + unsigned next_page; + + /* Get corresponding I2C address and adjust offset */ + client = at24_translate_offset(at24, &offset); + + /* write_max is at most a page */ + if (count > at24->write_max) + count = at24->write_max; + + /* Never roll over backwards, to the start of this page */ + next_page = roundup(offset + 1, at24->chip.page_size); + if (offset + count > next_page) + count = next_page - offset; + + /* + * Writes fail if the previous one didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; + + status = i2c_smbus_write_word_data(client, (offset >> 8) & 0x0ff, (offset & 0xFF) | buf[0]); + if (status == 0) + status = count; + + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", count, offset, status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(write_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off, + size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) + return count; + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + ssize_t status; + + status = at24_eeprom_write(at24, buf, off, 1); /* only one-byte to write; TODO page wirte */ + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&at24->lock); + + return retval; +} + +static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct at24_data *at24; + + if (unlikely(off >= attr->size)) + return -EFBIG; + + at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return at24_write(at24, buf, off, count); +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_OF +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ + const __be32 *val; + struct device_node *node = client->dev.of_node; + + if (node) { + if (of_get_property(node, "read-only", NULL)) + chip->flags |= AT24_FLAG_READONLY; + val = of_get_property(node, "pagesize", NULL); + if (val) + chip->page_size = be32_to_cpup(val); + } +} +#else +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ } +#endif /* CONFIG_OF */ + +static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct at24_platform_data chip; + bool writable; + int use_smbus = 0; + struct at24_data *at24; + int err; + unsigned i, num_addresses; + kernel_ulong_t magic; + + if (client->dev.platform_data) { + chip = *(struct at24_platform_data *)client->dev.platform_data; + } else { + if (!id->driver_data) + return -ENODEV; + + magic = id->driver_data; + chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); + magic >>= AT24_SIZE_BYTELEN; + chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); + + /* + * This is slow, but we can't know all eeproms, so we better + * play safe. Specifying custom eeprom-types via platform_data + * is recommended anyhow. + */ + chip.page_size = 1; + + /* update chipdata if OF is present */ + at24_get_ofdata(client, &chip); + + chip.setup = NULL; + chip.context = NULL; + } + + if (!is_power_of_2(chip.byte_len)) + dev_warn(&client->dev, + "byte_len looks suspicious (no power of 2)!\n"); + if (!chip.page_size) { + dev_err(&client->dev, "page_size must not be 0!\n"); + return -EINVAL; + } + if (!is_power_of_2(chip.page_size)) + dev_warn(&client->dev, + "page_size looks suspicious (no power of 2)!\n"); + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) { + use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + return -EPFNOSUPPORT; + } + use_smbus = I2C_SMBUS_BYTE_DATA; + } + + if (chip.flags & AT24_FLAG_TAKE8ADDR) + num_addresses = 8; + else + num_addresses = DIV_ROUND_UP(chip.byte_len, (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); + + at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) + num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); + if (!at24) + return -ENOMEM; + + mutex_init(&at24->lock); + at24->use_smbus = use_smbus; + at24->chip = chip; + at24->num_addresses = num_addresses; + + printk(KERN_ALERT "at24_probe chip.byte_len = 0x%x\n", chip.byte_len); + printk(KERN_ALERT "at24_probe chip.flags = 0x%x\n", chip.flags); + printk(KERN_ALERT "at24_probe chip.magic = 0x%lx\n", id->driver_data); + printk(KERN_ALERT "at24_probe use_smbus = %d\n", at24->use_smbus); + printk(KERN_ALERT "at24_probe num_addresses = %d\n", at24->num_addresses); + + /* + * Export the EEPROM bytes through sysfs, since that's convenient. + * By default, only root should see the data (maybe passwords etc) + */ + sysfs_bin_attr_init(&at24->bin); + at24->bin.attr.name = "eeprom"; + at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR; + at24->bin.read = at24_bin_read; + at24->bin.size = chip.byte_len; + + writable = !(chip.flags & AT24_FLAG_READONLY); + if (writable) { + if (!use_smbus || i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { + unsigned write_max = chip.page_size; + + at24->bin.write = at24_bin_write; + at24->bin.attr.mode |= S_IWUSR; + + if (write_max > io_limit) + write_max = io_limit; + if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + at24->write_max = write_max; + + /* buffer (data + address at the beginning) */ + at24->writebuf = devm_kzalloc(&client->dev, write_max + 2, GFP_KERNEL); + if (!at24->writebuf) + return -ENOMEM; + } else { + dev_warn(&client->dev, "cannot write due to controller restrictions."); + } + } + + at24->client[0] = client; + + /* use dummy devices for multiple-address chips */ + for (i = 1; i < num_addresses; i++) { + at24->client[i] = i2c_new_dummy(client->adapter, client->addr + i); + if (!at24->client[i]) { + dev_err(&client->dev, "address 0x%02x unavailable\n", client->addr + i); + err = -EADDRINUSE; + goto err_clients; + } + } + + err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin); + if (err) + goto err_clients; + + i2c_set_clientdata(client, at24); + + printk(KERN_ALERT "at24_probe %s done\n", client->name); + + return 0; + +err_clients: + for (i = 1; i < num_addresses; i++) + if (at24->client[i]) + i2c_unregister_device(at24->client[i]); + + return err; +} + +static int at24_remove(struct i2c_client *client) +{ + struct at24_data *at24; + int i; + + at24 = i2c_get_clientdata(client); + sysfs_remove_bin_file(&client->dev.kobj, &at24->bin); + + for (i = 1; i < at24->num_addresses; i++) + i2c_unregister_device(at24->client[i]); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct i2c_board_info i2c_devs = { + I2C_BOARD_INFO("24c64-ctc", 0x57), +}; + +static struct i2c_adapter *adapter = NULL; +static struct i2c_client *client = NULL; + +static int ctc_at24c64_init(void) +{ + printk(KERN_ALERT "ctc_at24c64_init\n"); + + adapter = i2c_get_adapter(0); + if(adapter == NULL){ + printk(KERN_ALERT "i2c_get_adapter == NULL\n"); + return -1; + } + + client = i2c_new_device(adapter, &i2c_devs); + if(client == NULL){ + printk(KERN_ALERT "i2c_new_device == NULL\n"); + i2c_put_adapter(adapter); + adapter = NULL; + return -1; + } + + return 0; +} + +static void ctc_at24c64_exit(void) +{ + printk(KERN_ALERT "ctc_at24c64_exit\n"); + if(client){ + i2c_unregister_device(client); + } + if(adapter){ + i2c_put_adapter(adapter); + } +} + +static struct i2c_driver at24_ctc_driver = { + .driver = { + .name = "at24-ctc", + .owner = THIS_MODULE, + }, + .probe = at24_probe, + .remove = at24_remove, + .id_table = at24_ctc_ids, +}; + +static int __init at24_ctc_init(void) +{ + if (!io_limit) { + pr_err("at24_ctc: io_limit must not be 0!\n"); + return -EINVAL; + } + + io_limit = rounddown_pow_of_two(io_limit); + + ctc_at24c64_init(); + + return i2c_add_driver(&at24_ctc_driver); +} +module_init(at24_ctc_init); + +static void __exit at24_ctc_exit(void) +{ + ctc_at24c64_exit(); + i2c_del_driver(&at24_ctc_driver); +} +module_exit(at24_ctc_exit); + +MODULE_DESCRIPTION("Driver for most I2C EEPROMs"); +MODULE_AUTHOR("David Brownell and Wolfram Sang"); +MODULE_LICENSE("GPL"); +/* XXX */ + diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/modules/centec_e582_48x6q_platform.c b/platform/centec/sonic-platform-modules-e582/48x6q/modules/centec_e582_48x6q_platform.c new file mode 100644 index 000000000000..6ef18ca62f41 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/modules/centec_e582_48x6q_platform.c @@ -0,0 +1,1381 @@ +#include +#include +#include +#include +#include +#include +#include + +#define SEP(XXX) 1 +#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) +#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) + +#if SEP("defines") +#define PCA9548_CHANNEL_NUM 8 +#define PCA9548_ADAPT_ID_START 10 +#define SFP_NUM 48 +#define QSFP_NUM 6 +#define PORT_NUM (SFP_NUM+QSFP_NUM) +#endif + +#if SEP("i2c:master") +static struct i2c_adapter *i2c_adp_master = NULL; /* i2c-0-cpu */ + +static int e582_48x6q_init_i2c_master(void) +{ + /* find i2c-core master */ + i2c_adp_master = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e582_48x6q_init_i2c_master can't find i2c-core bus\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_i2c_master(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_adp_master)) { + i2c_put_adapter(i2c_adp_master); + i2c_adp_master = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:pca9548") +static struct pca954x_platform_mode i2c_dev_pca9548_platform_mode[PCA9548_CHANNEL_NUM] = { + [0] = { + .adap_id = PCA9548_ADAPT_ID_START, + .deselect_on_exit = 1, + .class = 0, + }, + [1] = { + .adap_id = PCA9548_ADAPT_ID_START + 1, + .deselect_on_exit = 1, + .class = 0, + }, + [2] = { + .adap_id = PCA9548_ADAPT_ID_START + 2, + .deselect_on_exit = 1, + .class = 0, + }, + [3] = { + .adap_id = PCA9548_ADAPT_ID_START + 3, + .deselect_on_exit = 1, + .class = 0, + }, + [4] = { + .adap_id = PCA9548_ADAPT_ID_START + 4, + .deselect_on_exit = 1, + .class = 0, + }, + [5] = { + .adap_id = PCA9548_ADAPT_ID_START + 5, + .deselect_on_exit = 1, + .class = 0, + }, + [6] = { + .adap_id = PCA9548_ADAPT_ID_START + 6, + .deselect_on_exit = 1, + .class = 0, + }, + [7] = { + .adap_id = PCA9548_ADAPT_ID_START + 7, + .deselect_on_exit = 1, + .class = 0, + } +}; +static struct pca954x_platform_data i2c_dev_pca9548_platform_data = { + .modes = i2c_dev_pca9548_platform_mode, + .num_modes = PCA9548_CHANNEL_NUM, +}; +static struct i2c_board_info i2c_dev_pca9548 = { + I2C_BOARD_INFO("pca9548", 0x70), + .platform_data = &i2c_dev_pca9548_platform_data, +}; +static struct i2c_client *i2c_client_pca9548x = NULL; + +static int e582_48x6q_init_i2c_pca9548(void) +{ + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e582_48x6q_init_i2c_pca9548 can't find i2c-core bus\n"); + return -1; + } + + /* install i2c-mux */ + i2c_client_pca9548x = i2c_new_device(i2c_adp_master, &i2c_dev_pca9548); + if(IS_INVALID_PTR(i2c_client_pca9548x)) + { + i2c_client_pca9548x = NULL; + printk(KERN_CRIT "install e582_48x6q board pca9548 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_i2c_pca9548(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_client_pca9548x)) { + i2c_unregister_device(i2c_client_pca9548x); + i2c_client_pca9548x = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:adt7470") +static struct i2c_board_info i2c_dev_adt7470 = { + I2C_BOARD_INFO("adt7470", 0x2F), +}; +static struct i2c_adapter *i2c_adp_adt7470 = NULL; /* pca9548x-channel 5 */ +static struct i2c_client *i2c_client_adt7470 = NULL; + +static int e582_48x6q_init_i2c_adt7470(void) +{ + i2c_adp_adt7470 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 5); + if(IS_INVALID_PTR(i2c_adp_adt7470)) + { + i2c_adp_adt7470 = NULL; + printk(KERN_CRIT "install e582_48x6q board adt7470 failed\n"); + return -1; + } + + i2c_client_adt7470 = i2c_new_device(i2c_adp_adt7470, &i2c_dev_adt7470); + if(IS_INVALID_PTR(i2c_client_adt7470)){ + i2c_client_adt7470 = NULL; + printk(KERN_CRIT "install e582_48x6q board adt7470 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_i2c_adt7470(void) +{ + if(IS_VALID_PTR(i2c_client_adt7470)) { + i2c_unregister_device(i2c_client_adt7470); + i2c_client_adt7470 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_adt7470)) { + i2c_put_adapter(i2c_adp_adt7470); + i2c_adp_adt7470 = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:psu") +static struct i2c_adapter *i2c_adp_psu1 = NULL; /* psu1 channel 3 */ +static struct i2c_adapter *i2c_adp_psu2 = NULL; /* psu2 channel 1 */ +static struct i2c_board_info i2c_dev_psu1 = { + I2C_BOARD_INFO("i2c-psu1", 0x38), +}; +static struct i2c_board_info i2c_dev_psu2 = { + I2C_BOARD_INFO("i2c-psu2", 0x38), +}; +static struct i2c_client *i2c_client_psu1 = NULL; +static struct i2c_client *i2c_client_psu2 = NULL; + +static int e582_48x6q_init_i2c_psu(void) +{ + i2c_adp_psu1 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 3); + if(IS_INVALID_PTR(i2c_adp_psu1)) + { + i2c_adp_psu1 = NULL; + printk(KERN_CRIT "get e582_48x6q psu1 i2c-adp failed\n"); + return -1; + } + + i2c_adp_psu2 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 1); + if(IS_INVALID_PTR(i2c_adp_psu2)) + { + i2c_adp_psu2 = NULL; + printk(KERN_CRIT "get e582_48x6q psu2 i2c-adp failed\n"); + return -1; + } + + i2c_client_psu1 = i2c_new_device(i2c_adp_psu1, &i2c_dev_psu1); + if(IS_INVALID_PTR(i2c_client_psu1)){ + i2c_client_psu1 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client psu1 failed\n"); + return -1; + } + + i2c_client_psu2 = i2c_new_device(i2c_adp_psu2, &i2c_dev_psu2); + if(IS_INVALID_PTR(i2c_client_psu2)){ + i2c_client_psu2 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client psu2 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_i2c_psu(void) +{ + if(IS_VALID_PTR(i2c_client_psu1)) { + i2c_unregister_device(i2c_client_psu1); + i2c_client_psu1 = NULL; + } + + if(IS_VALID_PTR(i2c_client_psu2)) { + i2c_unregister_device(i2c_client_psu2); + i2c_client_psu2 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_psu1)) + { + i2c_put_adapter(i2c_adp_psu1); + i2c_adp_psu1 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_psu2)) + { + i2c_put_adapter(i2c_adp_psu2); + i2c_adp_psu2 = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:epld") +static struct i2c_board_info i2c_dev_epld = { + I2C_BOARD_INFO("i2c-epld", 0x58), +}; +static struct i2c_client *i2c_client_epld = NULL; + +static int e582_48x6q_init_i2c_epld(void) +{ + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e582_48x6q_init_i2c_epld can't find i2c-core bus\n"); + return -1; + } + + i2c_client_epld = i2c_new_device(i2c_adp_master, &i2c_dev_epld); + if(IS_INVALID_PTR(i2c_client_epld)) + { + i2c_client_epld = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client epld failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_i2c_epld(void) +{ + if(IS_VALID_PTR(i2c_client_epld)) { + i2c_unregister_device(i2c_client_epld); + i2c_client_epld = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:gpio") +static struct i2c_board_info i2c_dev_gpio0 = { + I2C_BOARD_INFO("i2c-gpio0", 0x20), +}; +static struct i2c_board_info i2c_dev_gpio1 = { + I2C_BOARD_INFO("i2c-gpio1", 0x21), +}; +static struct i2c_board_info i2c_dev_gpio2 = { + I2C_BOARD_INFO("i2c-gpio2", 0x22), +}; +static struct i2c_board_info i2c_dev_gpio3 = { + I2C_BOARD_INFO("i2c-gpio3", 0x23), +}; +static struct i2c_board_info i2c_dev_gpio4 = { + I2C_BOARD_INFO("i2c-gpio4", 0x24), +}; +static struct i2c_client *i2c_client_gpio0 = NULL; +static struct i2c_client *i2c_client_gpio1 = NULL; +static struct i2c_client *i2c_client_gpio2 = NULL; +static struct i2c_client *i2c_client_gpio3 = NULL; +static struct i2c_client *i2c_client_gpio4 = NULL; + +static int e582_48x6q_init_i2c_gpio(void) +{ + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e582_48x6q_init_i2c_gpio can't find i2c-core bus\n"); + return -1; + } + + i2c_client_gpio0 = i2c_new_device(i2c_adp_master, &i2c_dev_gpio0); + if(IS_INVALID_PTR(i2c_client_gpio0)) + { + i2c_client_gpio0 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client gpio0 failed\n"); + return -1; + } + + i2c_client_gpio1 = i2c_new_device(i2c_adp_master, &i2c_dev_gpio1); + if(IS_INVALID_PTR(i2c_client_gpio1)) + { + i2c_client_gpio1 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client gpio1 failed\n"); + return -1; + } + + i2c_client_gpio2 = i2c_new_device(i2c_adp_master, &i2c_dev_gpio2); + if(IS_INVALID_PTR(i2c_client_gpio2)) + { + i2c_client_gpio2 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client gpio2 failed\n"); + return -1; + } + + i2c_client_gpio3 = i2c_new_device(i2c_adp_master, &i2c_dev_gpio3); + if(IS_INVALID_PTR(i2c_client_gpio3)) + { + i2c_client_gpio3 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client gpio3 failed\n"); + return -1; + } + + i2c_client_gpio4 = i2c_new_device(i2c_adp_master, &i2c_dev_gpio4); + if(IS_INVALID_PTR(i2c_client_gpio4)) + { + i2c_client_gpio4 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client gpio4 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_i2c_gpio(void) +{ + if(IS_VALID_PTR(i2c_client_gpio0)) { + i2c_unregister_device(i2c_client_gpio0); + i2c_client_gpio0 = NULL; + } + + if((i2c_client_gpio1)) { + i2c_unregister_device(i2c_client_gpio1); + i2c_client_gpio1 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio2)) { + i2c_unregister_device(i2c_client_gpio2); + i2c_client_gpio2 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio3)) { + i2c_unregister_device(i2c_client_gpio3); + i2c_client_gpio3 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio4)) { + i2c_unregister_device(i2c_client_gpio4); + i2c_client_gpio4 = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:smbus") +static int e582_48x6q_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret >= 0) { + *value = (unsigned char)ret; + } + else + { + *value = 0; + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} + +static int e582_48x6q_smbus_write_reg(struct i2c_client *client, unsigned char reg, unsigned char value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_write_byte_data(client, reg, value); + if (ret != 0) + { + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} +#endif + +#if SEP("drivers:psu") +static struct class* psu_class = NULL; +static struct device* psu_dev_psu1 = NULL; +static struct device* psu_dev_psu2 = NULL; + +static ssize_t e582_48x6q_psu_read_presence(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char present_no = 0; + unsigned char present = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio0; + present_no = 17; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio0; + present_no = 9; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e582_48x6q_smbus_read_reg(i2c_psu_client, present_no/8, &present); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((present & (1<<(present_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e582_48x6q_psu_read_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char workstate_no = 0; + unsigned char workstate = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio0; + workstate_no = 21; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio0; + workstate_no = 13; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e582_48x6q_smbus_read_reg(i2c_psu_client, workstate_no/8, &workstate); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((workstate & (1<<(workstate_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static DEVICE_ATTR(psu_presence, S_IRUGO, e582_48x6q_psu_read_presence, NULL); +static DEVICE_ATTR(psu_status, S_IRUGO, e582_48x6q_psu_read_status, NULL); + +static int e582_48x6q_init_psu(void) +{ + int ret = 0; + + psu_class = class_create(THIS_MODULE, "psu"); + if (IS_INVALID_PTR(psu_class)) + { + psu_class = NULL; + printk(KERN_CRIT "create e582_48x6q class psu failed\n"); + return -1; + } + + psu_dev_psu1 = device_create(psu_class, NULL, MKDEV(222,0), NULL, "psu1"); + if (IS_INVALID_PTR(psu_dev_psu1)) + { + psu_dev_psu1 = NULL; + printk(KERN_CRIT "create e582_48x6q psu1 device failed\n"); + return -1; + } + + psu_dev_psu2 = device_create(psu_class, NULL, MKDEV(222,1), NULL, "psu2"); + if (IS_INVALID_PTR(psu_dev_psu2)) + { + psu_dev_psu2 = NULL; + printk(KERN_CRIT "create e582_48x6q psu2 device failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q psu1 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q psu1 device attr:status failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q psu2 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q psu2 device attr:status failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_psu(void) +{ + if (IS_VALID_PTR(psu_dev_psu1)) + { + device_remove_file(psu_dev_psu1, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu1, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,0)); + } + + if (IS_VALID_PTR(psu_dev_psu2)) + { + device_remove_file(psu_dev_psu2, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu2, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,1)); + } + + if (IS_VALID_PTR(psu_class)) + { + class_destroy(psu_class); + psu_class = NULL; + } + + return 0; +} +#endif + +#if SEP("drivers:leds") +extern void e582_48x6q_led_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e582_48x6q_led_get(struct led_classdev *led_cdev); +extern void e582_48x6q_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e582_48x6q_led_port_get(struct led_classdev *led_cdev); + +static struct led_classdev led_dev_system = { + .name = "system", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_idn = { + .name = "idn", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_fan1 = { + .name = "fan1", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_fan2 = { + .name = "fan2", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_fan3 = { + .name = "fan3", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_fan4 = { + .name = "fan4", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_psu1 = { + .name = "psu1", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_psu2 = { + .name = "psu2", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_port[PORT_NUM] = { +{ .name = "port1", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port2", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port3", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port4", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port5", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port6", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port7", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port8", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port9", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port10", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port11", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port12", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port13", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port14", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port15", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port16", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port17", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port18", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port19", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port20", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port21", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port22", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port23", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port24", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port25", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port26", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port27", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port28", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port29", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port30", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port31", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port32", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port33", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port34", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port35", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port36", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port37", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port38", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port39", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port40", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port41", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port42", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port43", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port44", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port45", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port46", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port47", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port48", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port49", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port50", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port51", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port52", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port53", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port54", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,} +}; +static unsigned char port_led_mode[PORT_NUM] = {0}; + +void e582_48x6q_led_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_epld; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x0F; + shift = 4; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x3; + mask = 0xFE; + shift = 0; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e582_48x6q_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return; + } + + led_value = ((led_value & mask) | ((set_value << shift) & (~mask))); + + ret = e582_48x6q_smbus_write_reg(i2c_led_client, reg, led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s led attr failed\n", led_cdev->name); + return; + } + + return; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return; +} + +enum led_brightness e582_48x6q_led_get(struct led_classdev *led_cdev) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_epld; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0xF0; + shift = 4; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x3; + mask = 0x01; + shift = 0; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e582_48x6q_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return 0; + } + + led_value = ((led_value & mask) >> shift); + + return led_value; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return 0; +} + +void e582_48x6q_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + port_led_mode[portNum-1] = set_value; + + return; +} + +enum led_brightness e582_48x6q_led_port_get(struct led_classdev *led_cdev) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + return port_led_mode[portNum-1]; +} + +static int e582_48x6q_init_led(void) +{ + int ret = 0; + int i = 0; + + ret = led_classdev_register(NULL, &led_dev_system); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_system device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_idn); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_idn device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan1); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_fan1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan2); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_fan2 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan3); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_fan3 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan4); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_fan4 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu1); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_psu1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu2); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_psu2 device failed\n"); + return -1; + } + + for (i=0; i PORT_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + value = 0; + } + + if ((portNum >= 1) && (portNum <= 8)) + { + reg_no = portNum + 31;/*32-39*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 9) && (portNum <= 16)) + { + reg_no = portNum + 7;/*16-23*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 17) && (portNum <= 24)) + { + reg_no = portNum - 17;/*0-7*/ + i2c_sfp_client = i2c_client_gpio2; + } + else if ((portNum >= 25) && (portNum <= 32)) + { + reg_no = portNum - 1;/*24-31*/ + i2c_sfp_client = i2c_client_gpio2; + } + else if ((portNum >= 33) && (portNum <= 40)) + { + reg_no = portNum - 25;/*8-15*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 41) && (portNum <= 48)) + { + reg_no = portNum - 9;/*32-39*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 49) && (portNum <= 54)) + { + reg_no = portNum - 25;/*24-29*/ + i2c_sfp_client = i2c_client_gpio4; + } + + dir_bank = (reg_no/8) + 0x18; + ret = e582_48x6q_smbus_write_reg(i2c_sfp_client, dir_bank, 0xff); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s set dir-ctl failed\n", attr->attr.name); + } + + input_bank = (reg_no/8) + 0x0; + ret = e582_48x6q_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 );/*1:PRESENT 0:ABSENT*/ + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e582_48x6q_sfp_read_enable(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char value = 0; + unsigned char reg_no = 0; + unsigned char dir_bank = 0; + unsigned char input_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > PORT_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + value = 0; + } + + if ((portNum >= 1) && (portNum <= 8)) + { + reg_no = portNum + 23;/*24-31*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 9) && (portNum <= 16)) + { + reg_no = portNum - 1;/*8-15*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 17) && (portNum <= 24)) + { + reg_no = portNum + 15;/*32-39*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 25) && (portNum <= 32)) + { + reg_no = portNum - 9;/*16-23*/ + i2c_sfp_client = i2c_client_gpio2; + } + else if ((portNum >= 33) && (portNum <= 40)) + { + reg_no = portNum - 33;/*0-7*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 41) && (portNum <= 48)) + { + reg_no = portNum - 17;/*24-31*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 49) && (portNum <= 54)) + { + printk(KERN_INFO "%s not supported!\n", name); + return sprintf(buf, "%d\n", 0); + } + + dir_bank = (reg_no/8) + 0x18; + ret = e582_48x6q_smbus_write_reg(i2c_sfp_client, dir_bank, 0xff); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s set dir-ctl failed\n", attr->attr.name); + } + + input_bank = (reg_no/8) + 0x8; + ret = e582_48x6q_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e582_48x6q_sfp_write_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + unsigned char value = 0; + unsigned char set_value = simple_strtol(buf, NULL, 10); + unsigned char reg_no = 0; + unsigned char dir_bank = 0; + unsigned char input_bank = 0; + unsigned char output_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > PORT_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + return size; + } + + if ((portNum >= 1) && (portNum <= 8)) + { + reg_no = portNum + 23;/*24-31*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 9) && (portNum <= 16)) + { + reg_no = portNum - 1;/*8-15*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 17) && (portNum <= 24)) + { + reg_no = portNum + 15;/*32-39*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 25) && (portNum <= 32)) + { + reg_no = portNum - 9;/*16-23*/ + i2c_sfp_client = i2c_client_gpio2; + } + else if ((portNum >= 33) && (portNum <= 40)) + { + reg_no = portNum - 33;/*0-7*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 41) && (portNum <= 48)) + { + reg_no = portNum - 17;/*24-31*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 49) && (portNum <= 54)) + { + printk(KERN_INFO "%s not supported!\n", name); + return size; + } + + set_value = ((set_value > 0) ? 0 : 1 ); + + dir_bank = (reg_no/8) + 0x18; + ret = e582_48x6q_smbus_write_reg(i2c_sfp_client, dir_bank, 0x0); + if (ret != 0) + { + printk(KERN_CRIT "Error: read sfp data:%s set dir-ctl failed\n", attr->attr.name); + return size; + } + + input_bank = (reg_no/8) + 0x8; + ret = e582_48x6q_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s presence failed\n", name); + return size; + } + + if (set_value) + { + value = (value | (1<<(reg_no % 8))); + } + else + { + value = (value & (~(1<<(reg_no % 8)))); + } + + output_bank = (reg_no/8) + 0x8; + ret = e582_48x6q_smbus_write_reg(i2c_sfp_client, output_bank, value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s presence failed\n", name); + return size; + } + + return size; +} + +static DEVICE_ATTR(sfp_presence, S_IRUGO, e582_48x6q_sfp_read_presence, NULL); +static DEVICE_ATTR(sfp_enable, S_IRUGO|S_IWUSR, e582_48x6q_sfp_read_enable, e582_48x6q_sfp_write_enable); +static int e582_48x6q_init_sfp(void) +{ + int ret = 0; + int i = 0; + + sfp_class = class_create(THIS_MODULE, "sfp"); + if (IS_INVALID_PTR(sfp_class)) + { + sfp_class = NULL; + printk(KERN_CRIT "create e582_48x6q class sfp failed\n"); + return -1; + } + + for (i=1; i<=PORT_NUM; i++) + { + sfp_dev[i] = device_create(sfp_class, NULL, MKDEV(223,i), NULL, "sfp%d", i); + if (IS_INVALID_PTR(sfp_dev[i])) + { + sfp_dev[i] = NULL; + printk(KERN_CRIT "create e582_48x6q sfp[%d] device failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q sfp[%d] device attr:presence failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_enable); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q sfp[%d] device attr:enable failed\n", i); + continue; + } + } + + return ret; +} + +static int e582_48x6q_exit_sfp(void) +{ + int i = 0; + + for (i=1; i<=PORT_NUM; i++) + { + if (IS_VALID_PTR(sfp_dev[i])) + { + device_remove_file(sfp_dev[i], &dev_attr_sfp_presence); + device_remove_file(sfp_dev[i], &dev_attr_sfp_enable); + device_destroy(sfp_class, MKDEV(223,i)); + sfp_dev[i] = NULL; + } + } + + if (IS_VALID_PTR(sfp_class)) + { + class_destroy(sfp_class); + sfp_class = NULL; + } + + return 0; +} +#endif + +static int e582_48x6q_init(void) +{ + int ret = 0; + int failed = 0; + + printk(KERN_ALERT "install e582_48x6q board dirver...\n"); + + ret = e582_48x6q_init_i2c_master(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_i2c_pca9548(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_i2c_adt7470(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_i2c_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_i2c_epld(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_i2c_gpio(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_led(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_sfp(); + if (ret != 0) + { + failed = 1; + } + + if (failed) + printk(KERN_INFO "install e582_48x6q board driver failed\n"); + else + printk(KERN_ALERT "install e582_48x6q board dirver...ok\n"); + + return 0; +} + +static void e582_48x6q_exit(void) +{ + printk(KERN_INFO "uninstall e582_48x6q board dirver...\n"); + + e582_48x6q_exit_sfp(); + e582_48x6q_exit_led(); + e582_48x6q_exit_psu(); + e582_48x6q_exit_i2c_gpio(); + e582_48x6q_exit_i2c_epld(); + e582_48x6q_exit_i2c_psu(); + e582_48x6q_exit_i2c_adt7470(); + e582_48x6q_exit_i2c_pca9548(); + e582_48x6q_exit_i2c_master(); +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("yangbs centecNetworks, Inc"); +MODULE_DESCRIPTION("e582-48x6q board driver"); +module_init(e582_48x6q_init); +module_exit(e582_48x6q_exit); + diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/modules/dal_kernel.c b/platform/centec/sonic-platform-modules-e582/48x6q/modules/dal_kernel.c new file mode 100644 index 000000000000..32a38f842cfa --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/modules/dal_kernel.c @@ -0,0 +1,1833 @@ +/** + @file dal_kernal.c + + @date 2012-10-18 + + @version v2.0 + + +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) +#include +#endif +#include "dal_kernel.h" +#include "dal_mpool.h" +#include +MODULE_AUTHOR("Centec Networks Inc."); +MODULE_DESCRIPTION("DAL kernel module"); +MODULE_LICENSE("GPL"); + +/* DMA memory pool size */ +static char* dma_pool_size; +module_param(dma_pool_size, charp, 0); +MODULE_PARM_DESC(dma_pool_size, + "Specify DMA memory pool size (default 4MB)"); + +/***************************************************************************** + * defines + *****************************************************************************/ +#define MB_SIZE 0x100000 +#define CTC_MAX_INTR_NUM 8 + +#define MEM_MAP_RESERVE SetPageReserved +#define MEM_MAP_UNRESERVE ClearPageReserved + +#define CTC_VENDOR_VID 0xc001 +#define CTC_HUMBER_DEVICE_ID 0x6048 +#define CTC_GOLDENGATE_DEVICE_ID 0xc010 +#define CTC_PCIE_VENDOR_ID 0xcb10 +#define CTC_DUET2_DEVICE_ID 0x7148 + +#define MEM_MAP_RESERVE SetPageReserved +#define MEM_MAP_UNRESERVE ClearPageReserved + +#define CTC_GREATBELT_DEVICE_ID 0x03e8 /* TBD */ +#define DAL_MAX_CHIP_NUM 8 /* [GB] used */ +#define VIRT_TO_PAGE(p) virt_to_page((p)) +#define DAL_UNTAG_BLOCK 0 +#define DAL_DISCARD_BLOCK 1 +#define DAL_MATCHED_BLOCK 2 +#define DAL_CUR_MATCH_BLOCk 3 +/***************************************************************************** + * typedef + *****************************************************************************/ +/* Control Data */ +typedef struct dal_isr_s +{ + int irq; + void (* isr)(void*); + void* isr_data; + int trigger; + int count; + wait_queue_head_t wqh; +} dal_isr_t; + +typedef struct dal_kernel_dev_s +{ + struct list_head list; + struct pci_dev* pci_dev; + + /* PCI I/O mapped base address */ + uintptr logic_address; + + /* Physical address */ + unsigned long long phys_address; +} dal_kern_dev_t; + +typedef struct _dma_segment +{ + struct list_head list; + unsigned long req_size; /* Requested DMA segment size */ + unsigned long blk_size; /* DMA block size */ + unsigned long blk_order; /* DMA block size in alternate format */ + unsigned long seg_size; /* Current DMA segment size */ + unsigned long seg_begin; /* Logical address of segment */ + unsigned long seg_end; /* Logical end address of segment */ + unsigned long* blk_ptr; /* Array of logical DMA block addresses */ + int blk_cnt_max; /* Maximum number of block to allocate */ + int blk_cnt; /* Current number of blocks allocated */ +} dma_segment_t; + +typedef irqreturn_t (*p_func) (int irq, void* dev_id); + +/*************************************************************************** + *declared + ***************************************************************************/ +static unsigned int linux_dal_poll0(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll1(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll2(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll3(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll4(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll5(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll6(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll7(struct file* filp, struct poll_table_struct* p); + +/***************************************************************************** + * global variables + *****************************************************************************/ +static dal_kern_dev_t dal_dev[DAL_MAX_CHIP_NUM]; +static dal_isr_t dal_isr[CTC_MAX_INTR_NUM]; +static int dal_chip_num = 0; +static int dal_version = 0; +static int dal_intr_num = 0; +static int use_high_memory = 0; +static unsigned int* dma_virt_base[DAL_MAX_CHIP_NUM]; +#ifndef DMA_MEM_MODE_PLATFORM +static unsigned int* dma_virt_base_tmp[DAL_MAX_CHIP_NUM]; +#endif +static unsigned long long dma_phy_base[DAL_MAX_CHIP_NUM]; +static unsigned int dma_mem_size = 0xc00000; +static unsigned int msi_irq_base[DAL_MAX_CHIP_NUM]; +static unsigned int msi_irq_num[DAL_MAX_CHIP_NUM]; +static unsigned int msi_used = 0; +static struct class *dal_class; + +static LIST_HEAD(_dma_seg); +static int dal_debug = 0; +module_param(dal_debug, int, 0); +MODULE_PARM_DESC(dal_debug, "Set debug level (default 0)"); + +static struct pci_device_id dal_id_table[] = +{ + {PCI_DEVICE(CTC_VENDOR_VID, CTC_GREATBELT_DEVICE_ID)}, + {PCI_DEVICE(CTC_PCIE_VENDOR_ID, CTC_GOLDENGATE_DEVICE_ID)}, + {PCI_DEVICE((CTC_PCIE_VENDOR_ID+1), (CTC_GOLDENGATE_DEVICE_ID+1))}, + {PCI_DEVICE(CTC_PCIE_VENDOR_ID, CTC_DUET2_DEVICE_ID)}, + {0, }, +}; + +static wait_queue_head_t poll_intr[CTC_MAX_INTR_NUM]; + +p_func intr_handler_fun[CTC_MAX_INTR_NUM]; + +static int poll_intr_trigger[CTC_MAX_INTR_NUM]; + +static struct file_operations dal_intr_fops[CTC_MAX_INTR_NUM] = +{ + { + .owner = THIS_MODULE, + .poll = linux_dal_poll0, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll1, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll2, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll3, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll4, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll5, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll6, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll7, + }, +}; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) +#include +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt +#endif +/***************************************************************************** + * macros + *****************************************************************************/ +#define VERIFY_CHIP_INDEX(n) (n < dal_chip_num) + +#define _KERNEL_INTERUPT_PROCESS +static irqreturn_t +intr0_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + + if(poll_intr_trigger[0]) + { + return IRQ_HANDLED; + } + + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[0] = 1; + wake_up(&poll_intr[0]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr1_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[1]) + { + return IRQ_HANDLED; + } + + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[1] = 1; + wake_up(&poll_intr[1]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr2_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[2]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[2] = 1; + wake_up(&poll_intr[2]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr3_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[3]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[3] = 1; + wake_up(&poll_intr[3]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr4_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[4]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[4] = 1; + wake_up(&poll_intr[4]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr5_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[5]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[5] = 1; + wake_up(&poll_intr[5]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr6_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[6]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[6] = 1; + wake_up(&poll_intr[6]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr7_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[7]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[7] = 1; + wake_up(&poll_intr[7]); + } + } + + return IRQ_HANDLED; +} + +int +dal_interrupt_register(unsigned int irq, int prio, void (* isr)(void*), void* data) +{ + int ret; + unsigned char str[16]; + unsigned char* int_name = NULL; + unsigned int intr_num_tmp = 0; + unsigned int intr_num = CTC_MAX_INTR_NUM; + unsigned long irq_flags = 0; + + if (dal_intr_num >= CTC_MAX_INTR_NUM) + { + printk("Interrupt numbers exceeds max.\n"); + return -1; + } + + if (msi_used) + { + int_name = "dal_msi"; + } + else + { + int_name = "dal_intr"; + } + + + for (intr_num_tmp=0;intr_num_tmp < CTC_MAX_INTR_NUM; intr_num_tmp++) + { + if (irq == dal_isr[intr_num_tmp].irq) + { + if (0 == msi_used) + { + dal_isr[intr_num_tmp].count++; + printk("Interrupt irq %d register count %d.\n", irq, dal_isr[intr_num_tmp].count); + } + return 0; + } + if ((0 == dal_isr[intr_num_tmp].irq) && (CTC_MAX_INTR_NUM == intr_num)) + { + intr_num = intr_num_tmp; + dal_isr[intr_num].count = 0; + } + } + dal_isr[intr_num].irq = irq; + dal_isr[intr_num].isr = isr; + dal_isr[intr_num].isr_data = data; + dal_isr[intr_num].count++; + + init_waitqueue_head(&poll_intr[intr_num]); + + /* only user mode */ + if ((NULL == isr) && (NULL == data)) + { + snprintf(str, 16, "%s%d", "dal_intr", intr_num); + ret = register_chrdev(DAL_DEV_INTR_MAJOR_BASE + intr_num, + str, &dal_intr_fops[intr_num]); + if (ret < 0) + { + printk("Register character device for irq %d failed, ret= %d", irq, ret); + return ret; + } + } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) + irq_flags = 0; +#else + irq_flags = IRQF_DISABLED; +#endif + if ((ret = request_irq(irq, + intr_handler_fun[intr_num], + irq_flags, + int_name, + &dal_isr[intr_num])) < 0) + { + printk("Cannot request irq %d, ret %d.\n", irq, ret); + unregister_chrdev(DAL_DEV_INTR_MAJOR_BASE + intr_num, str); + } + + if (0 == ret) + { + dal_intr_num++; + } + + return ret; +} + +int +dal_interrupt_unregister(unsigned int irq) +{ + unsigned char str[16]; + int intr_idx = 0; + int find_flag = 0; + + /* get intr device index */ + for (intr_idx = 0; intr_idx < CTC_MAX_INTR_NUM; intr_idx++) + { + if (dal_isr[intr_idx].irq == irq) + { + find_flag = 1; + break; + } + } + + if (find_flag == 0) + { + printk ("irq%d is not registered! unregister failed \n", irq); + return -1; + } + + dal_isr[intr_idx].count--; + if (0 != dal_isr[intr_idx].count) + { + printk("Interrupt irq %d unregister count %d.\n", irq, dal_isr[intr_idx].count); + return -1; + } + snprintf(str, 16, "%s%d", "dal_intr", intr_idx); + + unregister_chrdev(DAL_DEV_INTR_MAJOR_BASE + intr_idx, str); + + free_irq(irq, &dal_isr[intr_idx]); + + dal_isr[intr_idx].irq = 0; + + dal_intr_num--; + + return 0; +} + +int +dal_interrupt_set_en(unsigned int irq, unsigned int enable) +{ + enable ? enable_irq(irq) : disable_irq_nosync(irq); + return 0; +} + +static int +_dal_set_msi_enabe(unsigned int lchip, unsigned int irq_num) +{ + int ret = 0; + + if (irq_num == 1) + { + ret = pci_enable_msi(dal_dev[lchip].pci_dev); + if (ret) + { + printk ("msi enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); + pci_disable_msi(dal_dev[lchip].pci_dev); + msi_used = 0; + } + + msi_irq_base[lchip] = dal_dev[lchip].pci_dev->irq; + msi_irq_num[lchip] = 1; + } + else + { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 79)) + ret = pci_enable_msi_exact(dal_dev[lchip].pci_dev, irq_num); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 26, 32)) + ret = pci_enable_msi_block(dal_dev[lchip].pci_dev, irq_num); +#else + ret = -1; +#endif + if (ret) + { + printk ("msi enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); + pci_disable_msi(dal_dev[lchip].pci_dev); + msi_used = 0; + } + + msi_irq_base[lchip] = dal_dev[lchip].pci_dev->irq; + msi_irq_num[lchip] = irq_num; + } + + return ret; +} + +static int +_dal_set_msi_disable(unsigned int lchip) +{ + + pci_disable_msi(dal_dev[lchip].pci_dev); + + msi_irq_base[lchip] = 0; + msi_irq_num[lchip] = 0; + + return 0; +} + +int +dal_set_msi_cap(unsigned long arg) +{ + int ret = 0; + int index = 0; + dal_msi_info_t msi_info; + + if (copy_from_user(&msi_info, (void*)arg, sizeof(dal_msi_info_t))) + { + return -EFAULT; + } + + printk("####dal_set_msi_cap lchip %d base %d num:%d\n", msi_info.lchip, msi_info.irq_base, msi_info.irq_num); + if (msi_info.irq_num > 0) + { + if (0 == msi_used) + { + msi_used = 1; + ret = _dal_set_msi_enabe(msi_info.lchip, msi_info.irq_num); + } + else if ((1 == msi_used) && (msi_info.irq_num != msi_irq_num[msi_info.lchip])) + { + for (index = 0; index < msi_irq_num[msi_info.lchip]; index++) + { + dal_interrupt_unregister(msi_irq_base[msi_info.lchip]+index); + } + _dal_set_msi_disable(msi_info.lchip); + msi_used = 1; + ret = _dal_set_msi_enabe(msi_info.lchip, msi_info.irq_num); + } + } + else + { + msi_used = 0; + ret = _dal_set_msi_disable(msi_info.lchip); + } + + return ret; +} + +int +dal_user_interrupt_register(unsigned long arg) +{ + int irq = 0; + if (copy_from_user(&irq, (void*)arg, sizeof(int))) + { + return -EFAULT; + } + printk("####register interrupt irq:%d\n", irq); + return dal_interrupt_register(irq, 0, NULL, NULL); +} + +int +dal_user_interrupt_unregister(unsigned long arg) +{ + int irq = 0; + if (copy_from_user(&irq, (void*)arg, sizeof(int))) + { + return -EFAULT; + } + printk("####unregister interrupt irq:%d\n", irq); + return dal_interrupt_unregister(irq); +} + +int +dal_user_interrupt_set_en(unsigned long arg) +{ + dal_intr_parm_t dal_intr_parm; + + if (copy_from_user(&dal_intr_parm, (void*)arg, sizeof(dal_intr_parm_t))) + { + return -EFAULT; + } + + return dal_interrupt_set_en(dal_intr_parm.irq, dal_intr_parm.enable); +} + +/* + * Function: _dal_dma_segment_free + */ + +/* + * Function: _find_largest_segment + * + * Purpose: + * Find largest contiguous segment from a pool of DMA blocks. + * Parameters: + * dseg - DMA segment descriptor + * Returns: + * 0 on success, < 0 on error. + * Notes: + * Assembly stops if a segment of the requested segment size + * has been obtained. + * + * Lower address bits of the DMA blocks are used as follows: + * 0: Untagged + * 1: Discarded block + * 2: Part of largest contiguous segment + * 3: Part of current contiguous segment + */ +#ifndef DMA_MEM_MODE_PLATFORM +static int +_dal_find_largest_segment(dma_segment_t* dseg) +{ + int i, j, blks, found; + unsigned long seg_begin; + unsigned long seg_end; + unsigned long seg_tmp; + + blks = dseg->blk_cnt; + + /* Clear all block tags */ + for (i = 0; i < blks; i++) + { + dseg->blk_ptr[i] &= ~3; + } + + for (i = 0; i < blks && dseg->seg_size < dseg->req_size; i++) + { + /* First block must be an untagged block */ + if ((dseg->blk_ptr[i] & 3) == DAL_UNTAG_BLOCK) + { + /* Initial segment size is the block size */ + seg_begin = dseg->blk_ptr[i]; + seg_end = seg_begin + dseg->blk_size; + dseg->blk_ptr[i] |= DAL_CUR_MATCH_BLOCk; + + /* Loop looking for adjacent blocks */ + do + { + found = 0; + + for (j = i + 1; j < blks && (seg_end - seg_begin) < dseg->req_size; j++) + { + seg_tmp = dseg->blk_ptr[j]; + /* Check untagged blocks only */ + if ((seg_tmp & 3) == DAL_UNTAG_BLOCK) + { + if (seg_tmp == (seg_begin - dseg->blk_size)) + { + /* Found adjacent block below current segment */ + dseg->blk_ptr[j] |= DAL_CUR_MATCH_BLOCk; + seg_begin = seg_tmp; + found = 1; + } + else if (seg_tmp == seg_end) + { + /* Found adjacent block above current segment */ + dseg->blk_ptr[j] |= DAL_CUR_MATCH_BLOCk; + seg_end += dseg->blk_size; + found = 1; + } + } + } + } + while (found); + + if ((seg_end - seg_begin) > dseg->seg_size) + { + /* The current block is largest so far */ + dseg->seg_begin = seg_begin; + dseg->seg_end = seg_end; + dseg->seg_size = seg_end - seg_begin; + + /* Re-tag current and previous largest segment */ + for (j = 0; j < blks; j++) + { + if ((dseg->blk_ptr[j] & 3) == DAL_CUR_MATCH_BLOCk) + { + /* Tag current segment as the largest */ + dseg->blk_ptr[j] &= ~1; + } + else if ((dseg->blk_ptr[j] & 3) == DAL_MATCHED_BLOCK) + { + /* Discard previous largest segment */ + dseg->blk_ptr[j] ^= 3; + } + } + } + else + { + /* Discard all blocks in current segment */ + for (j = 0; j < blks; j++) + { + if ((dseg->blk_ptr[j] & 3) == DAL_CUR_MATCH_BLOCk) + { + dseg->blk_ptr[j] &= ~2; + } + } + } + } + } + + return 0; +} + +/* + * Function: _alloc_dma_blocks + */ +static int +_dal_alloc_dma_blocks(dma_segment_t* dseg, int blks) +{ + int i, start; + unsigned long addr; + + if (dseg->blk_cnt + blks > dseg->blk_cnt_max) + { + printk("No more DMA blocks\n"); + return -1; + } + + start = dseg->blk_cnt; + dseg->blk_cnt += blks; + + for (i = start; i < dseg->blk_cnt; i++) + { + addr = __get_free_pages(GFP_ATOMIC, dseg->blk_order); + if (addr) + { + dseg->blk_ptr[i] = addr; + } + else + { + printk("DMA allocation failed\n"); + return -1; + } + } + + return 0; +} + +/* + * Function: _dal_dma_segment_alloc + */ +static dma_segment_t* +_dal_dma_segment_alloc(unsigned int size, unsigned int blk_size) +{ + dma_segment_t* dseg; + int i, blk_ptr_size; + unsigned long page_addr; + struct sysinfo si; + + /* Sanity check */ + if (size == 0 || blk_size == 0) + { + return NULL; + } + + /* Allocate an initialize DMA segment descriptor */ + if ((dseg = kmalloc(sizeof(dma_segment_t), GFP_ATOMIC)) == NULL) + { + return NULL; + } + + memset(dseg, 0, sizeof(dma_segment_t)); + dseg->req_size = size; + dseg->blk_size = PAGE_ALIGN(blk_size); + + while ((PAGE_SIZE << dseg->blk_order) < dseg->blk_size) + { + dseg->blk_order++; + } + + si_meminfo(&si); + dseg->blk_cnt_max = (si.totalram << PAGE_SHIFT) / dseg->blk_size; + blk_ptr_size = dseg->blk_cnt_max * sizeof(unsigned long); + /* Allocate an initialize DMA block pool */ + dseg->blk_ptr = kmalloc(blk_ptr_size, GFP_KERNEL); + if (dseg->blk_ptr == NULL) + { + kfree(dseg); + return NULL; + } + + memset(dseg->blk_ptr, 0, blk_ptr_size); + /* Allocate minimum number of blocks */ + _dal_alloc_dma_blocks(dseg, dseg->req_size / dseg->blk_size); + + /* Allocate more blocks until we have a complete segment */ + do + { + _dal_find_largest_segment(dseg); + if (dseg->seg_size >= dseg->req_size) + { + break; + } + } + while (_dal_alloc_dma_blocks(dseg, 8) == 0); + + /* Reserve all pages in the DMA segment and free unused blocks */ + for (i = 0; i < dseg->blk_cnt; i++) + { + if ((dseg->blk_ptr[i] & 3) == 2) + { + dseg->blk_ptr[i] &= ~3; + + for (page_addr = dseg->blk_ptr[i]; + page_addr < dseg->blk_ptr[i] + dseg->blk_size; + page_addr += PAGE_SIZE) + { + MEM_MAP_RESERVE(VIRT_TO_PAGE((void*)page_addr)); + } + } + else if (dseg->blk_ptr[i]) + { + dseg->blk_ptr[i] &= ~3; + free_pages(dseg->blk_ptr[i], dseg->blk_order); + dseg->blk_ptr[i] = 0; + } + } + + return dseg; +} + +/* + * Function: _dal_dma_segment_free + */ +static void +_dal_dma_segment_free(dma_segment_t* dseg) +{ + int i; + unsigned long page_addr; + + if (dseg->blk_ptr) + { + for (i = 0; i < dseg->blk_cnt; i++) + { + if (dseg->blk_ptr[i]) + { + for (page_addr = dseg->blk_ptr[i]; + page_addr < dseg->blk_ptr[i] + dseg->blk_size; + page_addr += PAGE_SIZE) + { + MEM_MAP_UNRESERVE(VIRT_TO_PAGE(page_addr)); + } + + free_pages(dseg->blk_ptr[i], dseg->blk_order); + } + } + + kfree(dseg->blk_ptr); + kfree(dseg); + } +} + +/* + * Function: -dal_pgalloc + */ +static void* +_dal_pgalloc(unsigned int size) +{ + dma_segment_t* dseg; + unsigned int blk_size; + + blk_size = (size < DMA_BLOCK_SIZE) ? size : DMA_BLOCK_SIZE; + if ((dseg = _dal_dma_segment_alloc(size, blk_size)) == NULL) + { + return NULL; + } + + if (dseg->seg_size < size) + { + /* If we didn't get the full size then forget it */ + printk("Notice: Can not get enough memory for requset!!\n"); + printk("actual size:0x%lx, request size:0x%x\n", dseg->seg_size, size); + //-_dal_dma_segment_free(dseg); + //-return NULL; + } + + list_add(&dseg->list, &_dma_seg); + return (void*)dseg->seg_begin; +} + +/* + * Function: _dal_pgfree + */ +static int +_dal_pgfree(void* ptr) +{ + struct list_head* pos; + + list_for_each(pos, &_dma_seg) + { + dma_segment_t* dseg = list_entry(pos, dma_segment_t, list); + if (ptr == (void*)dseg->seg_begin) + { + list_del(&dseg->list); + _dal_dma_segment_free(dseg); + return 0; + } + } + return -1; +} +#endif +static void +dal_alloc_dma_pool(int lchip, int size) +{ + if (use_high_memory) + { + dma_phy_base[lchip] = virt_to_bus(high_memory); + dma_virt_base[lchip] = ioremap_nocache(dma_phy_base[lchip], size); + } + else + { +#ifdef DMA_MEM_MODE_PLATFORM + dma_virt_base[lchip] = dma_alloc_coherent(&(dal_dev[lchip].pci_dev->dev), dma_mem_size, + &dma_phy_base[lchip], GFP_KERNEL); + + printk(KERN_WARNING "########Using DMA_MEM_MODE_PLATFORM \n"); +#endif + +#ifndef DMA_MEM_MODE_PLATFORM + /* Get DMA memory from kernel */ + dma_virt_base_tmp[lchip] = _dal_pgalloc(size); + dma_phy_base[lchip] = virt_to_bus(dma_virt_base_tmp[lchip]); + dma_virt_base [lchip]= ioremap_nocache(dma_phy_base[lchip], size); +#endif + } +} + +static void +dal_free_dma_pool(int lchip) +{ + int ret = 0; + ret = ret; + if (use_high_memory) + { + iounmap(dma_virt_base[lchip]); + } + else + { +#ifdef DMA_MEM_MODE_PLATFORM + dma_free_coherent(&(dal_dev[lchip].pci_dev->dev), dma_mem_size, + dma_virt_base[lchip], dma_phy_base[lchip]); +#endif + +#ifndef DMA_MEM_MODE_PLATFORM + iounmap(dma_virt_base[lchip]); + ret = _dal_pgfree(dma_virt_base_tmp[lchip]); + if(ret<0) + { + printk("Dma free memory fail !!!!!! \n"); + } +#endif + } +} + +#define _KERNEL_DAL_IO +static int +_dal_pci_read(unsigned char lchip, unsigned int offset, unsigned int* value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + *value = *(volatile unsigned int*)(dal_dev[lchip].logic_address + offset); + return 0; +} + +int +dal_create_irq_mapping(unsigned long arg) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) + +#ifndef NO_IRQ +#define NO_IRQ (-1) +#endif + dal_irq_mapping_t irq_map; + + if (copy_from_user(&irq_map, (void*)arg, sizeof(dal_irq_mapping_t))) + { + return -EFAULT; + } + + irq_map.sw_irq = irq_create_mapping(NULL, irq_map.hw_irq); + if (irq_map.sw_irq == NO_IRQ) + { + printk("IRQ mapping fail !!!!!! \n"); + return -1; + } + + if (copy_to_user((dal_irq_mapping_t*)arg, (void*)&irq_map, sizeof(dal_irq_mapping_t))) + { + return -EFAULT; + } +#endif + return 0; +} + +int +dal_pci_read(unsigned long arg) +{ + dal_chip_parm_t cmdpara_chip; + + if (copy_from_user(&cmdpara_chip, (void*)arg, sizeof(dal_chip_parm_t))) + { + return -EFAULT; + } + + _dal_pci_read((unsigned char)cmdpara_chip.lchip, (unsigned int)cmdpara_chip.reg_addr, + (unsigned int*)(&(cmdpara_chip.value))); + + if (copy_to_user((dal_chip_parm_t*)arg, (void*)&cmdpara_chip, sizeof(dal_chip_parm_t))) + { + return -EFAULT; + } + + return 0; +} + +static int +_dal_pci_write(unsigned char lchip, unsigned int offset, unsigned int value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + *(volatile unsigned int*)(dal_dev[lchip].logic_address + offset) = value; + return 0; +} + +int +dal_pci_write(unsigned long arg) +{ + dal_chip_parm_t cmdpara_chip; + + if (copy_from_user(&cmdpara_chip, (void*)arg, sizeof(dal_chip_parm_t))) + { + return -EFAULT; + } + + _dal_pci_write((unsigned char)cmdpara_chip.lchip, (unsigned int)cmdpara_chip.reg_addr, + (unsigned int)cmdpara_chip.value); + + return 0; +} + +int +dal_pci_conf_read(unsigned char lchip, unsigned int offset, unsigned int* value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + pci_read_config_dword(dal_dev[lchip].pci_dev, offset, value); + return 0; +} + +int +dal_pci_conf_write(unsigned char lchip, unsigned int offset, unsigned int value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + pci_write_config_dword(dal_dev[lchip].pci_dev, offset, value); + return 0; +} +int +dal_user_read_pci_conf(unsigned long arg) +{ + dal_pci_cfg_ioctl_t dal_cfg; + + if (copy_from_user(&dal_cfg, (void*)arg, sizeof(dal_pci_cfg_ioctl_t))) + { + return -EFAULT; + } + + if (dal_pci_conf_read(dal_cfg.lchip, dal_cfg.offset, &dal_cfg.value)) + { + printk("dal_pci_conf_read failed.\n"); + return -EFAULT; + } + + if (copy_to_user((dal_pci_cfg_ioctl_t*)arg, (void*)&dal_cfg, sizeof(dal_pci_cfg_ioctl_t))) + { + return -EFAULT; + } + + return 0; +} + +int +dal_user_write_pci_conf(unsigned long arg) +{ + dal_pci_cfg_ioctl_t dal_cfg; + + if (copy_from_user(&dal_cfg, (void*)arg, sizeof(dal_pci_cfg_ioctl_t))) + { + return -EFAULT; + } + + return dal_pci_conf_write(dal_cfg.lchip, dal_cfg.offset, dal_cfg.value); +} + +static int +linux_get_device(unsigned long arg) +{ + dal_user_dev_t user_dev; + int lchip = 0; + + if (copy_from_user(&user_dev, (void*)arg, sizeof(user_dev))) + { + return -EFAULT; + } + + user_dev.chip_num = dal_chip_num; + lchip = user_dev.lchip; + + if (lchip < dal_chip_num) + { + user_dev.phy_base0 = (unsigned int)dal_dev[lchip].phys_address; + user_dev.phy_base1 = (unsigned int)(dal_dev[lchip].phys_address >> 32); + + user_dev.bus_no = dal_dev[lchip].pci_dev->bus->number; + user_dev.dev_no = dal_dev[lchip].pci_dev->device; + user_dev.fun_no = dal_dev[lchip].pci_dev->devfn; + } + + if (copy_to_user((dal_user_dev_t*)arg, (void*)&user_dev, sizeof(user_dev))) + { + return -EFAULT; + } + + return 0; +} + +/* set dal version, copy to user */ +static int +linux_get_dal_version(unsigned long arg) +{ + int dal_ver = VERSION_1DOT2; /* set dal version */ + + if (copy_to_user((int*)arg, (void*)&dal_ver, sizeof(dal_ver))) + { + return -EFAULT; + } + + dal_version = dal_ver; /* up sw */ + + return 0; +} + +static int +linux_get_dma_info(unsigned long arg) +{ + dma_info_t dma_para; + + if (copy_from_user(&dma_para, (void*)arg, sizeof(dma_info_t))) + { + return -EFAULT; + } + + dma_para.phy_base = (unsigned int)dma_phy_base[dma_para.lchip]; + dma_para.phy_base_hi = dma_phy_base[dma_para.lchip] >> 32; + dma_para.size = dma_mem_size; + + if (copy_to_user((dma_info_t*)arg, (void*)&dma_para, sizeof(dma_info_t))) + { + return -EFAULT; + } + + return 0; +} + +static int +dal_get_msi_info(unsigned long arg) +{ + dal_msi_info_t msi_para; + unsigned int lchip = 0; + + /* get lchip form user mode */ + if (copy_from_user(&msi_para, (void*)arg, sizeof(dal_msi_info_t))) + { + return -EFAULT; + } + lchip = msi_para.lchip; + + msi_para.irq_base = msi_irq_base[lchip]; + msi_para.irq_num = msi_irq_num[lchip]; + + /* send msi info to user mode */ + if (copy_to_user((dal_msi_info_t*)arg, (void*)&msi_para, sizeof(dal_msi_info_t))) + { + return -EFAULT; + } + + return 0; +} + + +static int +dal_get_intr_info(unsigned long arg) +{ + dal_intr_info_t intr_para; + unsigned int intr_num = 0; + + /* get lchip form user mode */ + if (copy_from_user(&intr_para, (void*)arg, sizeof(dal_intr_info_t))) + { + return -EFAULT; + } + + intr_para.irq_idx = CTC_MAX_INTR_NUM; + for (intr_num=0; intr_num< CTC_MAX_INTR_NUM; intr_num++) + { + if (intr_para.irq == dal_isr[intr_num].irq) + { + intr_para.irq_idx = intr_num; + break; + } + } + + if (CTC_MAX_INTR_NUM == intr_para.irq_idx) + { + printk("Interrupt %d cann't find.\n", intr_para.irq); + } + /* send msi info to user mode */ + if (copy_to_user((dal_intr_info_t*)arg, (void*)&intr_para, sizeof(dal_intr_info_t))) + { + return -EFAULT; + } + + return 0; +} + +static int +dal_cache_inval(unsigned long arg) +{ + dal_dma_cache_info_t intr_para; + + if (copy_from_user(&intr_para, (void*)arg, sizeof(dal_dma_cache_info_t))) + { + return -EFAULT; + } + +#if 0 + dma_cache_wback_inv((unsigned long)intr_para.ptr, intr_para.length); +#endif + +#if 0 + dma_sync_single_for_cpu(NULL, intr_para.ptr, intr_para.length, DMA_BIDIRECTIONAL); + + + dma_cache_sync(NULL, (void*)intr_para.ptr, intr_para.length, DMA_BIDIRECTIONAL); +#endif + return 0; +} + +static int +dal_cache_flush(unsigned long arg) +{ + dal_dma_cache_info_t intr_para; + + if (copy_from_user(&intr_para, (void*)arg, sizeof(dal_dma_cache_info_t))) + { + return -EFAULT; + } + +#if 0 + dma_cache_wback_inv(intr_para.ptr, intr_para.length); +#endif + +#if 0 + dma_sync_single_for_cpu(NULL, intr_para.ptr, intr_para.length, DMA_BIDIRECTIONAL); + + + dma_cache_sync(NULL, (void*)intr_para.ptr, intr_para.length, DMA_BIDIRECTIONAL); +#endif + return 0; +} + +int +linux_dal_probe(struct pci_dev* pdev, const struct pci_device_id* id) +{ + dal_kern_dev_t* dev = NULL; + int bar = 0; + int ret = 0; + unsigned int temp = 0; + unsigned int lchip = 0; + + printk(KERN_WARNING "********found dal device*****\n"); + + for (lchip = 0; lchip < DAL_MAX_CHIP_NUM; lchip ++) + { + if (NULL == dal_dev[lchip].pci_dev) + { + break; + } + } + + if (lchip >= DAL_MAX_CHIP_NUM) + { + printk("Exceed max local chip num\n"); + return -1; + } + + dev = &dal_dev[lchip]; + if (NULL == dev) + { + printk("Cannot obtain PCI resources\n"); + } + + lchip = lchip; + dal_chip_num += 1; + + dev->pci_dev = pdev; + + if (pci_enable_device(pdev) < 0) + { + printk("Cannot enable PCI device: vendor id = %x, device id = %x\n", + pdev->vendor, pdev->device); + } + + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + if (ret) + { + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) + { + printk("Could not set PCI DMA Mask\n"); + return ret; + } + } + + if (pci_request_regions(pdev, DAL_NAME) < 0) + { + printk("Cannot obtain PCI resources\n"); + } + + dev->phys_address = pci_resource_start(pdev, bar); + dev->logic_address = (uintptr)ioremap_nocache(dev->phys_address, + pci_resource_len(dev->pci_dev, bar)); + + _dal_pci_read(lchip, 0x48, &temp); + if (((temp >> 8) & 0xffff) == 0x3412) + { + printk("Little endian Cpu detected!!! \n"); + _dal_pci_write(lchip, 0x48, 0xFFFFFFFF); + } + + pci_set_master(pdev); + + /* alloc dma_mem_size for every chip */ + if (dma_mem_size) + { + dal_alloc_dma_pool(lchip, dma_mem_size); + + /*add check Dma memory pool cannot cross 4G space*/ + if ((0==(dma_phy_base[lchip]>>32)) && (0!=((dma_phy_base[lchip]+dma_mem_size)>>32))) + { + printk("Dma malloc memory cross 4G space!!!!!! \n"); + return -1; + } + } + + printk(KERN_WARNING "linux_dal_probe end*****\n"); + + return 0; +} + +void +linux_dal_remove(struct pci_dev* pdev) +{ + unsigned int lchip = 0; + unsigned int flag = 0; + + for (lchip = 0; lchip < DAL_MAX_CHIP_NUM; lchip ++) + { + if (pdev == dal_dev[lchip].pci_dev) + { + flag = 1; + break; + } + } + + if (1 == flag) + { + dal_free_dma_pool(lchip); + pci_release_regions(pdev); + pci_disable_device(pdev); + + dal_dev[lchip].pci_dev = NULL; + dal_chip_num--; + } + + +} + +#ifdef CONFIG_COMPAT +static long +linux_dal_ioctl(struct file* file, + unsigned int cmd, unsigned long arg) +#else + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) +static int +linux_dal_ioctl(struct file* file, + unsigned int cmd, unsigned long arg) +#else +static int +linux_dal_ioctl(struct inode* inode, struct file* file, + unsigned int cmd, unsigned long arg) +#endif + +#endif +{ + switch (cmd) + { + + case CMD_READ_CHIP: + return dal_pci_read(arg); + + case CMD_WRITE_CHIP: + return dal_pci_write(arg); + + case CMD_GET_DEVICES: + return linux_get_device(arg); + + case CMD_GET_DAL_VERSION: + return linux_get_dal_version(arg); + + case CMD_GET_DMA_INFO: + return linux_get_dma_info(arg); + + case CMD_PCI_CONFIG_READ: + return dal_user_read_pci_conf(arg); + + case CMD_PCI_CONFIG_WRITE: + return dal_user_write_pci_conf(arg); + + case CMD_REG_INTERRUPTS: + return dal_user_interrupt_register(arg); + + case CMD_UNREG_INTERRUPTS: + return dal_user_interrupt_unregister(arg); + + case CMD_EN_INTERRUPTS: + return dal_user_interrupt_set_en(arg); + + case CMD_SET_MSI_CAP: + return dal_set_msi_cap(arg); + + case CMD_GET_MSI_INFO: + return dal_get_msi_info(arg); + + case CMD_IRQ_MAPPING: + return dal_create_irq_mapping(arg); + + case CMD_GET_INTR_INFO: + return dal_get_intr_info(arg); + + case CMD_CACHE_INVAL: + return dal_cache_inval(arg); + + case CMD_CACHE_FLUSH: + return dal_cache_flush(arg); + + default: + break; + } + + return 0; +} + +static unsigned int +linux_dal_poll0(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[0], p); + local_irq_save(flags); + if (poll_intr_trigger[0]) + { + poll_intr_trigger[0] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll1(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[1], p); + local_irq_save(flags); + if (poll_intr_trigger[1]) + { + poll_intr_trigger[1] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll2(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[2], p); + local_irq_save(flags); + if (poll_intr_trigger[2]) + { + poll_intr_trigger[2] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll3(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[3], p); + local_irq_save(flags); + if (poll_intr_trigger[3]) + { + poll_intr_trigger[3] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll4(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[4], p); + local_irq_save(flags); + if (poll_intr_trigger[4]) + { + poll_intr_trigger[4] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll5(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[5], p); + local_irq_save(flags); + if (poll_intr_trigger[5]) + { + poll_intr_trigger[5] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll6(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[6], p); + local_irq_save(flags); + if (poll_intr_trigger[6]) + { + poll_intr_trigger[6] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll7(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[7], p); + local_irq_save(flags); + if (poll_intr_trigger[7]) + { + poll_intr_trigger[7] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static struct pci_driver linux_dal_driver = +{ + .name = DAL_NAME, + .id_table = dal_id_table, + .probe = linux_dal_probe, + .remove = linux_dal_remove, +}; + +static struct file_operations fops = +{ + .owner = THIS_MODULE, +#ifdef CONFIG_COMPAT + .compat_ioctl = linux_dal_ioctl, + .unlocked_ioctl = linux_dal_ioctl, +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) + .unlocked_ioctl = linux_dal_ioctl, +#else + .ioctl = linux_dal_ioctl, +#endif +#endif +}; + + +static int __init +linux_dal_init(void) +{ + int ret = 0; + + /* Get DMA memory pool size form dal.ok input param, or use default dma_mem_size */ + if (dma_pool_size) + { + if ((dma_pool_size[strlen(dma_pool_size) - 1] & ~0x20) == 'M') + { + dma_mem_size = simple_strtoul(dma_pool_size, NULL, 0); + printk("dma_mem_size: 0x%x \n", dma_mem_size); + + dma_mem_size *= MB_SIZE; + } + else + { + printk("DMA memory pool size must be specified as e.g. dma_pool_size=8M\n"); + } + + if (dma_mem_size & (dma_mem_size - 1)) + { + printk("dma_mem_size must be a power of 2 (1M, 2M, 4M, 8M etc.)\n"); + dma_mem_size = 0; + } + } + + ret = register_chrdev(DAL_DEV_MAJOR, DAL_NAME, &fops); + if (ret < 0) + { + printk(KERN_WARNING "Register linux_dal device, ret %d\n", ret); + return ret; + } + + ret = pci_register_driver(&linux_dal_driver); + if (ret < 0) + { + printk(KERN_WARNING "Register ASIC PCI driver failed, ret %d\n", ret); + return ret; + } + + /* alloc /dev/linux_dal node */ + dal_class = class_create(THIS_MODULE, DAL_NAME); + device_create(dal_class, NULL, MKDEV(DAL_DEV_MAJOR, 0), NULL, DAL_NAME); + + /* init interrupt function */ + intr_handler_fun[0] = intr0_handler; + intr_handler_fun[1] = intr1_handler; + intr_handler_fun[2] = intr2_handler; + intr_handler_fun[3] = intr3_handler; + intr_handler_fun[4] = intr4_handler; + intr_handler_fun[5] = intr5_handler; + intr_handler_fun[6] = intr6_handler; + intr_handler_fun[7] = intr7_handler; + + return ret; +} + +static void __exit +linux_dal_exit(void) +{ + device_destroy(dal_class, MKDEV(DAL_DEV_MAJOR, 0)); + class_destroy(dal_class); + unregister_chrdev(DAL_DEV_MAJOR, "linux_dal"); + pci_unregister_driver(&linux_dal_driver); +} + +module_init(linux_dal_init); +module_exit(linux_dal_exit); + + diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/modules/dal_kernel.h b/platform/centec/sonic-platform-modules-e582/48x6q/modules/dal_kernel.h new file mode 100644 index 000000000000..850a4cffa731 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/modules/dal_kernel.h @@ -0,0 +1,171 @@ +/** + @file dal_kernel_io.h + + @author Copyright (C) 2012 Centec Networks Inc. All rights reserved. + + @date 2012-4-9 + + @version v2.0 + +*/ +#ifndef _DAL_KERNEL_H_ +#define _DAL_KERNEL_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(CONFIG_RESOURCES_64BIT) || defined(CONFIG_PHYS_ADDR_T_64BIT) +#define PHYS_ADDR_IS_64BIT +#endif + +#ifndef SDK_IN_USERMODE +#ifdef PHYS_ADDR_IS_64BIT +typedef long long intptr; +typedef unsigned long long uintptr; +#else +typedef int intptr; +typedef unsigned int uintptr; +#endif +#endif + +#define DAL_PCI_READ_ADDR 0x0 +#define DAL_PCI_READ_DATA 0xc +#define DAL_PCI_WRITE_ADDR 0x8 +#define DAL_PCI_WRITE_DATA 0x4 +#define DAL_PCI_STATUS 0x10 + +#define DAL_PCI_STATUS_IN_PROCESS 31 +#define DAL_PCI_STATUS_BAD_PARITY 5 +#define DAL_PCI_STATUS_CPU_ACCESS_ERR 4 +#define DAL_PCI_STATUS_READ_CMD 3 +#define DAL_PCI_STATUS_REGISTER_ERR 1 +#define DAL_PCI_STATUS_REGISTER_ACK 0 + +#define DAL_PCI_ACCESS_TIMEOUT 0x64 + +#define DAL_NAME "linux_dal" /* "linux_dal" */ + +#define DAL_DEV_MAJOR 198 + +#define DAL_DEV_INTR_MAJOR_BASE 200 + +#define DAL_DEV_NAME "/dev/" DAL_NAME +#define DAL_ONE_KB 1024 +#define DAL_ONE_MB (1024*1024) +struct dal_chip_parm_s +{ + unsigned int lchip; /*tmp should be uint8*/ + unsigned int fpga_id; /*tmp add*/ + unsigned int reg_addr; + unsigned int value; +}; +typedef struct dal_chip_parm_s dal_chip_parm_t; + +struct dal_intr_parm_s +{ + unsigned int irq; + unsigned int enable; +}; +typedef struct dal_intr_parm_s dal_intr_parm_t; + +struct dal_irq_mapping_s +{ + unsigned int hw_irq; + unsigned int sw_irq; +}; +typedef struct dal_irq_mapping_s dal_irq_mapping_t; + +struct dal_user_dev_s +{ + unsigned int chip_num; /*output: local chip number*/ + unsigned int lchip; /*input: local chip id*/ + unsigned int phy_base0; /* low 32bits physical base address */ + unsigned int phy_base1; /* high 32bits physical base address */ + unsigned int bus_no; + unsigned int dev_no; + unsigned int fun_no; + void* virt_base[2]; /* Virtual base address; this must be last member */ +}; +typedef struct dal_user_dev_s dal_user_dev_t; + +struct dma_info_s +{ + unsigned int lchip; + unsigned int phy_base; + unsigned int phy_base_hi; + unsigned int size; + unsigned int* virt_base; +}; +typedef struct dma_info_s dma_info_t; + +struct dal_pci_cfg_ioctl_s +{ + unsigned int lchip; /* Device ID */ + unsigned int offset; + unsigned int value; +}; +typedef struct dal_pci_cfg_ioctl_s dal_pci_cfg_ioctl_t; + +struct dal_msi_info_s +{ + unsigned int lchip; + unsigned int irq_base; + unsigned int irq_num; +}; +typedef struct dal_msi_info_s dal_msi_info_t; + +struct dal_intr_info_s +{ + unsigned int irq; + unsigned int irq_idx; +}; +typedef struct dal_intr_info_s dal_intr_info_t; + +struct dal_dma_cache_info_s +{ + unsigned long ptr; + unsigned int length; +}; +typedef struct dal_dma_cache_info_s dal_dma_cache_info_t; + +#define CMD_MAGIC 'C' +#define CMD_WRITE_CHIP _IO(CMD_MAGIC, 0) /* for humber ioctrol*/ +#define CMD_READ_CHIP _IO(CMD_MAGIC, 1) /* for humber ioctrol*/ +#define CMD_GET_DEVICES _IO(CMD_MAGIC, 2) +#define CMD_GET_DAL_VERSION _IO(CMD_MAGIC, 3) +#define CMD_PCI_CONFIG_WRITE _IO(CMD_MAGIC, 4) +#define CMD_PCI_CONFIG_READ _IO(CMD_MAGIC, 5) +#define CMD_GET_DMA_INFO _IO(CMD_MAGIC, 6) +#define CMD_REG_INTERRUPTS _IO(CMD_MAGIC, 7) +#define CMD_UNREG_INTERRUPTS _IO(CMD_MAGIC, 8) +#define CMD_EN_INTERRUPTS _IO(CMD_MAGIC, 9) +#define CMD_I2C_READ _IO(CMD_MAGIC, 10) +#define CMD_I2C_WRITE _IO(CMD_MAGIC, 11) +#define CMD_GET_MSI_INFO _IO(CMD_MAGIC, 12) +#define CMD_SET_MSI_CAP _IO(CMD_MAGIC, 13) +#define CMD_IRQ_MAPPING _IO(CMD_MAGIC, 14) +#define CMD_GET_INTR_INFO _IO(CMD_MAGIC, 15) +#define CMD_CACHE_INVAL _IO(CMD_MAGIC, 16) +#define CMD_CACHE_FLUSH _IO(CMD_MAGIC, 17) + +enum dal_version_e +{ + VERSION_MIN, + VERSION_1DOT0, + VERSION_1DOT1, + VERSION_1DOT2, + + VERSION_MAX +}; +typedef enum dal_version_e dal_version_t; + +/* We try to assemble a contiguous segment from chunks of this size */ +#define DMA_BLOCK_SIZE (512 * DAL_ONE_KB) + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/modules/dal_mpool.c b/platform/centec/sonic-platform-modules-e582/48x6q/modules/dal_mpool.c new file mode 100644 index 000000000000..5aca222a138f --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/modules/dal_mpool.c @@ -0,0 +1,350 @@ +#include "dal_mpool.h" + +#ifdef __KERNEL__ +#include +#include + +#define DAL_MALLOC(x) kmalloc(x, GFP_ATOMIC) +#define DAL_FREE(x) kfree(x) + +static spinlock_t dal_mpool_lock; +#define MPOOL_LOCK_INIT() spin_lock_init(&dal_mpool_lock) +#define MPOOL_LOCK() unsigned long flags; spin_lock_irqsave(&dal_mpool_lock, flags) +#define MPOOL_UNLOCK() spin_unlock_irqrestore(&dal_mpool_lock, flags) +#define DAL_PRINT(fmt,arg...) printk(fmt,##arg) +#else /* !__KERNEL__*/ + +#include +#include "sal.h" +#define DAL_MALLOC(x) malloc(x) +#define DAL_FREE(x) free(x) +static sal_mutex_t* dal_mpool_lock; +#define MPOOL_LOCK_INIT() sal_mutex_create(&dal_mpool_lock) +#define MPOOL_LOCK() sal_mutex_lock(dal_mpool_lock) +#define MPOOL_UNLOCK() sal_mutex_unlock(dal_mpool_lock) +#define DAL_PRINT(fmt,arg...) sal_printf(fmt,##arg) + +#endif /* __KERNEL__ */ + + + +dal_mpool_mem_t* g_free_block_ptr = NULL; + +/* System cache line size */ +#ifndef DAL_CACHE_LINE_BYTES +#define DAL_CACHE_LINE_BYTES 256 +#endif + +#define DAL_MAX_CHIP_NUM 32 +static dal_mpool_mem_t* p_desc_pool[DAL_MAX_CHIP_NUM] = {0}; +static dal_mpool_mem_t* p_data_pool[DAL_MAX_CHIP_NUM] = {0}; + +int +dal_mpool_init(void) +{ + MPOOL_LOCK_INIT(); + return 0; +} + +dal_mpool_mem_t* +_dal_mpool_create(void* base, int size, int type) +{ + dal_mpool_mem_t* head = NULL; + dal_mpool_mem_t* tail = NULL; + + head = (dal_mpool_mem_t*)DAL_MALLOC(sizeof(dal_mpool_mem_t)); + if (head == NULL) + { + return NULL; + } + + tail = (dal_mpool_mem_t*)DAL_MALLOC(sizeof(dal_mpool_mem_t)); + if (tail == NULL) + { + DAL_FREE(head); + return NULL; + } + + head->size = tail->size = 0; + head->type = type; + head->address = base; + tail->address = head->address + size; + head->next = tail; + tail->next = NULL; + + return head; +} + +dal_mpool_mem_t* +dal_mpool_create(unsigned char lchip, void* base, int size) +{ + dal_mpool_mem_t* head = NULL; + int mod = (int)(((unsigned long)base) & (DAL_CACHE_LINE_BYTES - 1)); + + MPOOL_LOCK(); + + if (mod) + { + base = (char*)base + (DAL_CACHE_LINE_BYTES - mod); + size -= (DAL_CACHE_LINE_BYTES - mod); + } + + size &= ~(DAL_CACHE_LINE_BYTES - 1); + + /* init for common linkptr, only used for GB */ + head = _dal_mpool_create(base, size, DAL_MPOOL_TYPE_USELESS); + if (NULL == head) + { + MPOOL_UNLOCK(); + return NULL; + } + + /* init for desc linkptr */ + p_desc_pool[lchip] = _dal_mpool_create(base, DAL_MPOOL_MAX_DESX_SIZE, DAL_MPOOL_TYPE_DESC); + if (NULL == p_desc_pool[lchip]) + { + MPOOL_UNLOCK(); + DAL_FREE(head->next); + DAL_FREE(head); + return NULL; + } + + /* init for data linkptr */ + p_data_pool[lchip] = _dal_mpool_create(((char*)base+DAL_MPOOL_MAX_DESX_SIZE), (size - DAL_MPOOL_MAX_DESX_SIZE), DAL_MPOOL_TYPE_DATA); + if (NULL == p_data_pool[lchip]) + { + MPOOL_UNLOCK(); + DAL_FREE(head->next); + DAL_FREE(head); + DAL_FREE(p_desc_pool[lchip]->next); + DAL_FREE(p_desc_pool[lchip]); + return NULL; + } + + MPOOL_UNLOCK(); + + return head; +} + +dal_mpool_mem_t* +_dal_mpool_alloc_comon(dal_mpool_mem_t* ptr, int size, int type) +{ + dal_mpool_mem_t* new_ptr = NULL; + + while (ptr && ptr->next) + { + if (ptr->next->address - (ptr->address + ptr->size) >= size) + { + break; + } + + ptr = ptr->next; + } + + if (!(ptr && ptr->next)) + { + return NULL; + } + + new_ptr = DAL_MALLOC(sizeof(dal_mpool_mem_t)); + if (!new_ptr) + { + return NULL; + } + + new_ptr->type = type; + new_ptr->address = ptr->address + ptr->size; + new_ptr->size = size; + new_ptr->next = ptr->next; + ptr->next = new_ptr; + + return new_ptr; +} + +void* +dal_mpool_alloc(unsigned char lchip, dal_mpool_mem_t* pool, int size, int type) +{ + dal_mpool_mem_t* ptr = NULL; + dal_mpool_mem_t* new_ptr = NULL; + int mod; + + MPOOL_LOCK(); + + mod = size & (DAL_CACHE_LINE_BYTES - 1); + if (mod != 0) + { + size += (DAL_CACHE_LINE_BYTES - mod); + } + + switch(type) + { + case DAL_MPOOL_TYPE_USELESS: + ptr = pool; + new_ptr = _dal_mpool_alloc_comon(ptr, size, type); + if (NULL == new_ptr) + { + MPOOL_UNLOCK(); + return NULL; + } + break; + case DAL_MPOOL_TYPE_DESC: + ptr = p_desc_pool[lchip]; + new_ptr = _dal_mpool_alloc_comon(ptr, size, type); + if (NULL == new_ptr) + { + MPOOL_UNLOCK(); + return NULL; + } + break; + case DAL_MPOOL_TYPE_DATA: + ptr = p_data_pool[lchip]; + new_ptr = _dal_mpool_alloc_comon(ptr, size, type); + if (NULL == new_ptr) + { + MPOOL_UNLOCK(); + return NULL; + } + break; + default: + MPOOL_UNLOCK(); + return NULL; + break; + } + + MPOOL_UNLOCK(); + if( NULL == new_ptr ) + { + return NULL; + } + + return new_ptr->address; +} + +void +_dal_mpool_free(dal_mpool_mem_t* ptr, void* addr, int type) +{ + unsigned char* address = (unsigned char*)addr; + dal_mpool_mem_t* prev = NULL; + + while (ptr && ptr->next) + { + if (ptr->next->address == address) + { + break; + } + + ptr = ptr->next; + } + + if (ptr && ptr->next) + { + prev = ptr; + ptr = ptr->next; + prev->next = ptr->next; + DAL_FREE(ptr); + } + + return; +} + +void +dal_mpool_free(unsigned char lchip, dal_mpool_mem_t* pool, void* addr) +{ + dal_mpool_mem_t* ptr = pool; + + MPOOL_LOCK(); + + switch(pool->type) + { + case DAL_MPOOL_TYPE_USELESS: + ptr = pool; + _dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_USELESS); + break; + case DAL_MPOOL_TYPE_DESC: + ptr = p_desc_pool[lchip]; + _dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_DESC); + break; + case DAL_MPOOL_TYPE_DATA: + ptr = p_data_pool[lchip]; + _dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_DATA); + break; + default: + break; + } + + MPOOL_UNLOCK(); + return; +} + +int +dal_mpool_destroy(unsigned char lchip, dal_mpool_mem_t* pool) +{ + dal_mpool_mem_t* ptr, * next; + + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = next) + { + next = ptr->next; + DAL_FREE(ptr); + } + + for (ptr = p_desc_pool[lchip]; ptr; ptr = next) + { + next = ptr->next; + DAL_FREE(ptr); + } + + for (ptr = p_data_pool[lchip]; ptr; ptr = next) + { + next = ptr->next; + DAL_FREE(ptr); + } + + MPOOL_UNLOCK(); + + return 0; +} + +int +dal_mpool_usage(dal_mpool_mem_t* pool, int type) +{ + int usage = 0; + dal_mpool_mem_t* ptr; + + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = ptr->next) + { + if (ptr->type == type || ptr->type == -1) + { + usage += ptr->size; + } + } + + MPOOL_UNLOCK(); + + return usage; +} + +int +dal_mpool_debug(dal_mpool_mem_t* pool) +{ + dal_mpool_mem_t* ptr; + int index = 0; + + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = ptr->next) + { +// DAL_PRINT("%2dst mpool block: address=0x%8x, size=0x%x \n", index, (unsigned int)ptr->address, ptr->size); + DAL_PRINT("%2dst mpool block: address=%p, size=0x%x \n", index, ptr->address, ptr->size); // note + index++; + } + + MPOOL_UNLOCK(); + + return 0; +} + + diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/modules/dal_mpool.h b/platform/centec/sonic-platform-modules-e582/48x6q/modules/dal_mpool.h new file mode 100644 index 000000000000..d93f88868136 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/modules/dal_mpool.h @@ -0,0 +1,72 @@ +/** + @file dal_mpool.h + + @author Copyright (C) 2011 Centec Networks Inc. All rights reserved. + + @date 2012-5-10 + + @version v2.0 + + This file contains the dma memory init, allocation and free APIs +*/ + +#ifndef _DMA_MPOOL_H +#define _DMA_MPOOL_H +#ifdef __cplusplus +extern "C" { +#endif + +#define DAL_MPOOL_MAX_DESX_SIZE (1024*1024) + +enum dal_mpool_type_e +{ + DAL_MPOOL_TYPE_USELESS, /* just compatible with GB */ + DAL_MPOOL_TYPE_DESC, /* dma mpool op for desc */ + DAL_MPOOL_TYPE_DATA /* dma mpool op for data */ +}; +typedef enum dal_mpool_type_e dal_mpool_type_t; + +struct dal_mpool_mem_s +{ + unsigned char* address; + int size; + int type; + struct dal_mpool_mem_s* next; +}; +typedef struct dal_mpool_mem_s dal_mpool_mem_t; + +/** + @brief This function is to alloc dma memory + + @param[in] size size of memory + + @return NULL + +*/ +extern int +dal_mpool_init(void); + +extern dal_mpool_mem_t* +dal_mpool_create(unsigned char lchip, void* base_ptr, int size); + +extern void* +dal_mpool_alloc(unsigned char lchip, dal_mpool_mem_t* pool, int size, int type); + +extern void +dal_mpool_free(unsigned char lchip, dal_mpool_mem_t* pool, void* addr); + +extern int +dal_mpool_destroy(unsigned char lchip, dal_mpool_mem_t* pool); + +extern int +dal_mpool_usage(dal_mpool_mem_t* pool, int type); + +extern int +dal_mpool_debug(dal_mpool_mem_t* pool); +#ifdef __cplusplus +} +#endif + +#endif /* !_DMA_MPOOL_H */ + + diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/scripts/48x6q_platform.sh b/platform/centec/sonic-platform-modules-e582/48x6q/scripts/48x6q_platform.sh new file mode 100755 index 000000000000..e8f81a20d9d1 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/scripts/48x6q_platform.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +#platform init script for centec e582-48x6q + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # I801 adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus I801 adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find I801" && exit 1 +} + +init_devnum + +if [ "$1" == "init" ]; then + #install drivers and dependencies + depmod -a + modprobe i2c-i801 + modprobe i2c-dev + modprobe i2c-mux + modprobe i2c-smbus + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + i2cset -y 0 0x58 0x8 0x3f + i2cset -y 0 0x20 0x1b 0x0 + i2cset -y 0 0x20 0xb 0x0 + i2cset -y 0 0x21 0x19 0x0 + i2cset -y 0 0x21 0x9 0x0 + i2cset -y 0 0x21 0x1c 0x0 + i2cset -y 0 0x21 0xc 0x0 + i2cset -y 0 0x22 0x1a 0x0 + i2cset -y 0 0x22 0xa 0x0 + i2cset -y 0 0x23 0x18 0x0 + i2cset -y 0 0x23 0x8 0x0 + i2cset -y 0 0x23 0x1b 0x0 + i2cset -y 0 0x23 0xb 0x0 + modprobe lm77 + modprobe tun + modprobe dal + modprobe centec_at24c64 + modprobe centec_e582_48x6q_platform + + #start platform monitor + rm -rf /usr/bin/platform_monitor + ln -s /usr/bin/48x6q_platform_monitor.py /usr/bin/platform_monitor + python /usr/bin/platform_monitor & +elif [ "$1" == "deinit" ]; then + kill -9 $(pidof platform_monitor) > /dev/null 2>&1 + rm -rf /usr/bin/platform_monitor + modprobe -r centec_e582_48x6q_platform + modprobe -r centec_at24c64 + modprobe -r dal + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev +else + echo "e582-48x6q_platform : Invalid option !" +fi diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/scripts/48x6q_platform_monitor.py b/platform/centec/sonic-platform-modules-e582/48x6q/scripts/48x6q_platform_monitor.py new file mode 100644 index 000000000000..d08802a35f3b --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/scripts/48x6q_platform_monitor.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Module contains an implementation of sfp presence scan logic +# +############################################################################# + +try: + import os + import os.path + import threading + import time + import logging + import struct + import syslog + import swsssdk + from socket import * + from select import * +except ImportError, e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("centec-pmon") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + +PORT_NUMBER = (48+6) + +class PlatformMonitor: + + """init board platform default config""" + def __init__(self): + """[ctlid, slavedevid]""" + self.fiber_mapping = [(0, 0)] # res + self.fiber_mapping.extend([(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7)]) # panel port 1~8 + self.fiber_mapping.extend([(0, 14), (0, 13), (0, 15), (0, 12), (0, 8), (0, 11), (0, 9), (0, 10)]) # panel port 9~16 + self.fiber_mapping.extend([(0, 22), (0, 21), (0, 23), (0, 20), (0, 16), (0, 19), (0, 17), (0, 18)]) # panel port 17~24 + self.fiber_mapping.extend([(1, 4), (1, 3), (1, 5), (1, 2), (1, 6), (1, 1), (1, 7), (1, 0)]) # panel port 25~32 + self.fiber_mapping.extend([(1, 8), (1, 15), (1, 9), (1, 14), (1, 10), (1, 13), (1, 11), (1, 12)]) # panel port 33~40 + self.fiber_mapping.extend([(1, 22), (1, 21), (1, 23), (1, 20), (1, 16), (1, 19), (1, 17), (1, 18)]) # panel port 41~48 + self.fiber_mapping.extend([(1, 28), (1, 29), (1, 26), (1, 27), (1, 24), (1, 25)]) # panel port 49~54 + + self.udpClient = socket(AF_INET, SOCK_DGRAM) + self.sfp_present = [0]*(PORT_NUMBER+1) + self.sfp_enable = [0]*(PORT_NUMBER+1) + self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" + self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" + self.sfp_scan_timer = 0 + + def is_qsfp(self, port): + if port <= 48: + return False + else: + return True + + def get_sfp_present(self, port): + with open(self.f_sfp_present.format(port), 'r') as sfp_file: + return int(sfp_file.read()) + + def set_sfp_present(self, port, present): + self.sfp_present[port] = present + + def set_sfp_enable(self, port, enable): + if self.is_qsfp(port): + if enable: + with open(self.f_sfp_enable.format(port), 'w') as sfp_file: + sfp_file.write("1") + self.sfp_enable[port] = 1 + else: + with open(self.f_sfp_enable.format(port), 'w') as sfp_file: + sfp_file.write("0") + self.sfp_enable[port] = 0 + else: + (ctlid, devid) = self.fiber_mapping[port] + req = struct.pack('=HHHBBHIBBBBI', 0, 9, 16, ctlid, devid, 0x50, 0, 0x56, 1, 0xf, 0, 1) + self.udpClient.sendto(req, ('localhost', 8101)) + rsp, addr = self.udpClient.recvfrom(1024) + rsp_data = struct.unpack('=HHHBBHIBBBBIi512B', rsp) + enable_v = rsp_data[13] + if enable: + enable_v &= 0xf0 + else: + enable_v |= 0x0f + data = struct.pack('=HHHBBHBBBB', 0, 11, 8, ctlid, 0x56, 0x50, devid, enable_v, 0xf, 0) + self.udpClient.sendto(data, ('localhost', 8101)) + DBG_PRINT("set sfp{} to {}".format(port, ("enable" if enable else "disable"))) + + def initialize_configdb(self): + try: + f_mac = os.popen('ip link show eth0 | grep ether | awk \'{print $2}\'') + mac_addr = f_mac.read(17) + last_byte = mac_addr[-2:] + aligned_last_byte = format(int(int(str(last_byte), 16) + 1), '02x') + mac_addr = mac_addr[:-2] + aligned_last_byte + DBG_PRINT("start connect swss config-db to set device mac-address") + swss = swsssdk.SonicV2Connector() + swss.connect(swss.CONFIG_DB) + swss.set(swss.CONFIG_DB, "DEVICE_METADATA|localhost", 'mac', mac_addr) + mac_addr = swss.get(swss.CONFIG_DB, "DEVICE_METADATA|localhost", 'mac') + DBG_PRINT("set device mac-address: %s" % mac_addr) + except IOError as e: + DBG_PRINT(str(e)) + + def initialize_rpc(self): + while True: + try: + r_sel = [self.udpClient] + echo_req = struct.pack('=HHH', 0, 1, 0) + self.udpClient.sendto(echo_req, ('localhost', 8101)) + result = select(r_sel, [], [], 1) + if self.udpClient in result[0]: + echo_rsp, srv_addr = self.udpClient.recvfrom(1024) + if echo_rsp: + break + DBG_PRINT("connect to sdk rpc server timeout, try again.") + except IOError as e: + DBG_PRINT(str(e)) + + DBG_PRINT("connect to sdk rpc server success.") + + def initialize_gpio(self): + # set gpio 1,2,3,4,5,6,7,8 output mode + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 1, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 2, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 3, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 4, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 5, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 6, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 7, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 8, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + # set gpio 1,2,3,4,5,6,7,8 output 0 to reset i2c bridge + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 1, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 2, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 3, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 4, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 5, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 6, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 7, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 8, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + # set gpio 1,2,3,4,5,6,7,8 output 1 to release i2c bridge + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 1, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 2, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 3, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 4, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 5, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 6, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 7, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 8, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + DBG_PRINT("config ctc chip gpio done.") + + def initialize_sfp(self): + try: + for port in range(1, PORT_NUMBER+1): + if self.get_sfp_present(port): + self.set_sfp_present(port, 1) + self.set_sfp_enable(port, 1) + else: + self.set_sfp_present(port, 0) + self.set_sfp_enable(port, 0) + except IOError as e: + DBG_PRINT(str(e)) + + def initialize(self): + DBG_PRINT("start connect to sdk rpc server.") + + self.initialize_configdb() + self.initialize_rpc() + self.initialize_gpio() + self.initialize_sfp() + + def sfp_scan(self): + try: + for port in range(1, PORT_NUMBER+1): + cur_present = self.get_sfp_present(port) + if self.sfp_present[port] != cur_present: + self.set_sfp_present(port, cur_present) + self.set_sfp_enable(port, cur_present) + except IOError as e: + DBG_PRINT(str(e)) + + def start(self): + while True: + self.sfp_scan() + time.sleep(1) + +if __name__ == "__main__": + monitor = PlatformMonitor() + monitor.initialize() + monitor.start() + diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/service/48x6q_platform.service b/platform/centec/sonic-platform-modules-e582/48x6q/service/48x6q_platform.service new file mode 100644 index 000000000000..ad9b1fb1b3a7 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/service/48x6q_platform.service @@ -0,0 +1,13 @@ +[Unit] +Description=Centec e582 48x6q platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-e582-48x6q start +ExecStop=-/etc/init.d/platform-modules-e582-48x6q stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec/sonic-platform-modules-e582/LICENSE b/platform/centec/sonic-platform-modules-e582/LICENSE new file mode 100644 index 000000000000..99228517bae7 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2017 Centec, 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 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/centec/sonic-platform-modules-e582/README.md b/platform/centec/sonic-platform-modules-e582/README.md new file mode 100644 index 000000000000..61b3ef6c87f4 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/README.md @@ -0,0 +1 @@ +platform drivers for Centec E582 for the SONiC project diff --git a/platform/centec/sonic-platform-modules-e582/debian/changelog b/platform/centec/sonic-platform-modules-e582/debian/changelog new file mode 100644 index 000000000000..3f4ff89c1bee --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/changelog @@ -0,0 +1,11 @@ +sonic-centec-platform-modules (1.1) unstable; urgency=low + + * Add support for centec e582-48x2q4z + + -- yangbs Thu, 25 Jan 2018 13:43:40 +0800 + +sonic-centec-platform-modules (1.0) unstable; urgency=low + + * Initial release + + -- yangbs Mon, 22 Jan 2018 13:43:40 +0800 diff --git a/platform/centec/sonic-platform-modules-e582/debian/compat b/platform/centec/sonic-platform-modules-e582/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/centec/sonic-platform-modules-e582/debian/control b/platform/centec/sonic-platform-modules-e582/debian/control new file mode 100644 index 000000000000..93939f7dad73 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/control @@ -0,0 +1,17 @@ +Source: sonic-centec-platform-modules +Section: main +Priority: extra +Maintainer: yangbs +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-e582-48x2q4z +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-e582-48x6q +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.init b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.init new file mode 100755 index 000000000000..3ef5e7e30b6d --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.init @@ -0,0 +1,38 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup e582-48x2q4z board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + /usr/bin/48x2q4z_platform.sh init + + echo "done." + ;; + +stop) + /usr/bin/48x2q4z_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: service platform-modules-e582-48x2q4z {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.install b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.install new file mode 100644 index 000000000000..9bd1181e860f --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.install @@ -0,0 +1,6 @@ +48x2q4z/cfg/48x2q4z-modules.conf etc/modules-load.d +48x2q4z/cfg/config_db.json etc/sonic +48x2q4z/cfg/config_db_l2l3.json etc/sonic +48x2q4z/scripts/48x2q4z_platform.sh usr/bin +48x2q4z/scripts/48x2q4z_platform_monitor.py usr/bin +48x2q4z/service/48x2q4z_platform.service lib/systemd/system diff --git a/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.postinst b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.postinst new file mode 100644 index 000000000000..b4a1fcbe4e6c --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.postinst @@ -0,0 +1,3 @@ +depmod -a +systemctl enable 48x2q4z_platform.service +systemctl start 48x2q4z_platform.service diff --git a/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.init b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.init new file mode 100755 index 000000000000..1c5b0c1c4978 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.init @@ -0,0 +1,38 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup e582-48x6q board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + /usr/bin/48x6q_platform.sh init + + echo "done." + ;; + +stop) + /usr/bin/48x6q_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: service platform-modules-e582-48x6q {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.install b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.install new file mode 100644 index 000000000000..a6d26ce329bc --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.install @@ -0,0 +1,6 @@ +48x6q/cfg/48x6q-modules.conf etc/modules-load.d +48x6q/cfg/config_db.json etc/sonic +48x6q/cfg/config_db_l2l3.json etc/sonic +48x6q/scripts/48x6q_platform.sh usr/bin +48x6q/scripts/48x6q_platform_monitor.py usr/bin +48x6q/service/48x6q_platform.service lib/systemd/system diff --git a/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.postinst b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.postinst new file mode 100644 index 000000000000..fea0c4eebda8 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.postinst @@ -0,0 +1,3 @@ +depmod -a +systemctl enable 48x6q_platform.service +systemctl start 48x6q_platform.service diff --git a/platform/centec/sonic-platform-modules-e582/debian/rules b/platform/centec/sonic-platform-modules-e582/debian/rules new file mode 100755 index 000000000000..9f5d67b1af5c --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/rules @@ -0,0 +1,35 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= 48x6q 48x2q4z + +%: + dh $@ + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -pplatform-modules-e582-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp -f $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/platform-modules-e582-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/modules/*.ko; \ + rm -rf debian/platform-modules-e582-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR)/*.ko; \ + done) + diff --git a/platform/generic/aboot-image.mk b/platform/generic/aboot-image.mk new file mode 100644 index 000000000000..ecc91bba54c0 --- /dev/null +++ b/platform/generic/aboot-image.mk @@ -0,0 +1,8 @@ +# sonic aboot installer + +SONIC_GENERIC_ABOOT_IMAGE = sonic-aboot-generic.swi +$(SONIC_GENERIC_ABOOT_IMAGE)_MACHINE = generic +$(SONIC_GENERIC_ABOOT_IMAGE)_IMAGE_TYPE = aboot +$(SONIC_GENERIC_ABOOT_IMAGE)_INSTALLS = +$(SONIC_GENERIC_ABOOT_IMAGE)_DOCKERS = +SONIC_INSTALLERS += $(SONIC_GENERIC_ABOOT_IMAGE) diff --git a/platform/generic/onie-image.mk b/platform/generic/onie-image.mk new file mode 100644 index 000000000000..1a2ddb143505 --- /dev/null +++ b/platform/generic/onie-image.mk @@ -0,0 +1,8 @@ +# sonic generic ONIE image installer + +SONIC_GENERIC_ONIE_IMAGE = sonic-generic.bin +$(SONIC_GENERIC_ONIE_IMAGE)_MACHINE = generic +$(SONIC_GENERIC_ONIE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_GENERIC_ONIE_IMAGE)_INSTALLS = +$(SONIC_GENERIC_ONIE_IMAGE)_DOCKERS = +SONIC_INSTALLERS += $(SONIC_GENERIC_ONIE_IMAGE) diff --git a/platform/generic/platform.conf b/platform/generic/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/generic/rules.mk b/platform/generic/rules.mk new file mode 100644 index 000000000000..bc2507740277 --- /dev/null +++ b/platform/generic/rules.mk @@ -0,0 +1,10 @@ +include $(PLATFORM_PATH)/aboot-image.mk +include $(PLATFORM_PATH)/onie-image.mk + +SONIC_ALL += $(DOCKER_DATABASE) \ + $(DOCKER_LLDP_SV2) \ + $(DOCKER_SNMP_SV2) \ + $(DOCKER_PLATFORM_MONITOR) \ + $(DOCKER_DHCP_RELAY) \ + $(DOCKER_PTF) \ + $(SONIC_GENERIC_ONIE_IMAGE) diff --git a/platform/marvell/docker-orchagent-mrvl.mk b/platform/marvell/docker-orchagent-mrvl.mk new file mode 100644 index 000000000000..9c3c4c13a8f9 --- /dev/null +++ b/platform/marvell/docker-orchagent-mrvl.mk @@ -0,0 +1,23 @@ +# docker image for orchagent + +DOCKER_ORCHAGENT_MRVL = docker-orchagent-mrvl.gz +$(DOCKER_ORCHAGENT_MRVL)_PATH = $(DOCKERS_PATH)/docker-orchagent +$(DOCKER_ORCHAGENT_MRVL)_DEPENDS += $(SWSS) $(REDIS_TOOLS) $(IPROUTE2) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_ORCHAGENT_MRVL)_DEPENDS += $(SWSS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_ORCHAGENT_MRVL)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_MRVL) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_MRVL) + +$(DOCKER_ORCHAGENT_MRVL)_CONTAINER_NAME = swss +$(DOCKER_ORCHAGENT_MRVL)_RUN_OPT += --net=host --privileged -t +$(DOCKER_ORCHAGENT_MRVL)_RUN_OPT += -v /etc/network/interfaces:/etc/network/interfaces:ro +$(DOCKER_ORCHAGENT_MRVL)_RUN_OPT += -v /etc/network/interfaces.d/:/etc/network/interfaces.d/:ro +$(DOCKER_ORCHAGENT_MRVL)_RUN_OPT += -v /host/machine.conf:/host/machine.conf +$(DOCKER_ORCHAGENT_MRVL)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + +$(DOCKER_ORCHAGENT_MRVL)_BASE_IMAGE_FILES += swssloglevel:/usr/bin/swssloglevel +$(DOCKER_ORCHAGENT_MRVL)_FILES += $(ARP_UPDATE_SCRIPT) diff --git a/platform/marvell/docker-syncd-mrvl-rpc.mk b/platform/marvell/docker-syncd-mrvl-rpc.mk new file mode 100644 index 000000000000..d4002a3d645f --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl-rpc.mk @@ -0,0 +1,15 @@ +# docker image for mrvl syncd with rpc + +DOCKER_SYNCD_MRVL_RPC = docker-syncd-mrvl-rpc.gz +$(DOCKER_SYNCD_MRVL_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-mrvl-rpc +$(DOCKER_SYNCD_MRVL_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) +$(DOCKER_SYNCD_MRVL_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_MRVL) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_MRVL_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_MRVL_RPC) +endif + +$(DOCKER_SYNCD_MRVL_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/marvell/docker-syncd-mrvl-rpc/99-syncd.conf b/platform/marvell/docker-syncd-mrvl-rpc/99-syncd.conf new file mode 100644 index 000000000000..f3b57e3b1964 --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl-rpc/99-syncd.conf @@ -0,0 +1,2 @@ +sysctl -w net.core.rmem_max=509430500 + diff --git a/platform/marvell/docker-syncd-mrvl-rpc/Dockerfile.j2 b/platform/marvell/docker-syncd-mrvl-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..14a4698702f5 --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl-rpc/Dockerfile.j2 @@ -0,0 +1,51 @@ +FROM docker-syncd-mrvl + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_mrvl_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -P syncd + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_mrvl_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + && wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/marvell/docker-syncd-mrvl-rpc/ptf_nn_agent.conf b/platform/marvell/docker-syncd-mrvl-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/marvell/docker-syncd-mrvl.mk b/platform/marvell/docker-syncd-mrvl.mk new file mode 100644 index 000000000000..4ee42e9cb904 --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl.mk @@ -0,0 +1,15 @@ +# docker image for mrvl syncd + +DOCKER_SYNCD_MRVL = docker-syncd-mrvl.gz +$(DOCKER_SYNCD_MRVL)_PATH = $(PLATFORM_PATH)/docker-syncd-mrvl +$(DOCKER_SYNCD_MRVL)_DEPENDS += $(SYNCD) $(MRVL_FPA) $(REDIS_TOOLS) +$(DOCKER_SYNCD_MRVL)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_MRVL) +ifneq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_MRVL) +endif + +$(DOCKER_SYNCD_MRVL)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_MRVL)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_MRVL)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_MRVL)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/marvell/docker-syncd-mrvl/Dockerfile.j2 b/platform/marvell/docker-syncd-mrvl/Dockerfile.j2 new file mode 100755 index 000000000000..ca48db80879e --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl/Dockerfile.j2 @@ -0,0 +1,32 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_syncd_mrvl_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get -y install libpcap-dev libxml2-dev python-dev swig libsensors4-dev libjemalloc1 nfs-common + +RUN dpkg -i \ +{% for deb in docker_syncd_mrvl_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "syncd.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] + diff --git a/platform/marvell/docker-syncd-mrvl/start.sh b/platform/marvell/docker-syncd-mrvl/start.sh new file mode 100755 index 000000000000..96e2a9128081 --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl/start.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start syncd + diff --git a/platform/marvell/docker-syncd-mrvl/supervisord.conf b/platform/marvell/docker-syncd-mrvl/supervisord.conf new file mode 100644 index 000000000000..1e015fef931f --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl/supervisord.conf @@ -0,0 +1,29 @@ +[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:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + diff --git a/platform/marvell/docker-syncd-mrvl/syncd.sh b/platform/marvell/docker-syncd-mrvl/syncd.sh new file mode 100755 index 000000000000..993cf100f2f0 --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl/syncd.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +function clean_up { + service syncd stop + exit +} + +trap clean_up SIGTERM SIGKILL + +service syncd start + +read diff --git a/platform/marvell/libsaithrift-dev.mk b/platform/marvell/libsaithrift-dev.mk new file mode 100644 index 000000000000..270bf25b873f --- /dev/null +++ b/platform/marvell/libsaithrift-dev.mk @@ -0,0 +1,7 @@ +# libsaithrift-dev package + +LIBSAITHRIFT_DEV_MRVL = libsaithrift-dev_1.2.1_amd64.deb +$(LIBSAITHRIFT_DEV_MRVL)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV_MRVL)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(THRIFT_COMPILER) $(MRVL_FPA) $(MRVL_SAI) +$(LIBSAITHRIFT_DEV_MRVL)_RDEPENDS += $(LIBTHRIFT) $(MRVL_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV_MRVL) diff --git a/platform/marvell/one-image.mk b/platform/marvell/one-image.mk new file mode 100644 index 000000000000..ad8cd522f998 --- /dev/null +++ b/platform/marvell/one-image.mk @@ -0,0 +1,7 @@ +# sonic marvell one image installer + +SONIC_ONE_IMAGE = sonic-marvell.bin +$(SONIC_ONE_IMAGE)_MACHINE = marvell +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/marvell/platform.conf b/platform/marvell/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/marvell/python-saithrift.mk b/platform/marvell/python-saithrift.mk new file mode 100644 index 000000000000..f7bea43589ad --- /dev/null +++ b/platform/marvell/python-saithrift.mk @@ -0,0 +1,6 @@ +# python-saithrift package + +PYTHON_SAITHRIFT_MRVL = python-saithrift_1.2.1_amd64.deb +$(PYTHON_SAITHRIFT_MRVL)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(PYTHON_SAITHRIFT_MRVL)_DEPENDS += $(MRVL_FPA) $(MRVL_SAI) $(THRIFT_COMPILER) $(PYTHON_THRIFT) $(LIBTHRIFT_DEV) +SONIC_DPKG_DEBS += $(PYTHON_SAITHRIFT_MRVL) diff --git a/platform/marvell/rules.mk b/platform/marvell/rules.mk new file mode 100644 index 000000000000..c5df6bab194e --- /dev/null +++ b/platform/marvell/rules.mk @@ -0,0 +1,18 @@ +include $(PLATFORM_PATH)/sdk.mk +include $(PLATFORM_PATH)/sai.mk +include $(PLATFORM_PATH)/docker-syncd-mrvl.mk +include $(PLATFORM_PATH)/docker-syncd-mrvl-rpc.mk +include $(PLATFORM_PATH)/docker-orchagent-mrvl.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/python-saithrift.mk +include $(PLATFORM_PATH)/one-image.mk + +SONIC_ALL += $(SONIC_ONE_IMAGE) \ + $(DOCKER_FPM) \ + $(DOCKER_SYNCD_MRVL_RPC) + +# Inject mrvl sai into sairedis +$(LIBSAIREDIS)_DEPENDS += $(MRVL_FPA) $(MRVL_SAI) $(LIBSAITHRIFT_DEV_MRVL) + +# Runtime dependency on mrvl sai is set only for syncd +$(SYNCD)_RDEPENDS += $(MRVL_SAI) diff --git a/platform/marvell/sai.mk b/platform/marvell/sai.mk new file mode 100644 index 000000000000..5016b47f19a9 --- /dev/null +++ b/platform/marvell/sai.mk @@ -0,0 +1,9 @@ +# Marvell SAI + +export MRVL_SAI_VERSION = 1.2.1 +export MRVL_SAI_TAG = SONiC.201803 +export MRVL_SAI = mrvllibsai_$(MRVL_SAI_VERSION).deb + +$(MRVL_SAI)_SRC_PATH = $(PLATFORM_PATH)/sai +$(MRVL_SAI)_DEPENDS += $(MRVL_FPA) +SONIC_MAKE_DEBS += $(MRVL_SAI) diff --git a/platform/marvell/sai/Makefile b/platform/marvell/sai/Makefile new file mode 100644 index 000000000000..1fad592a79ee --- /dev/null +++ b/platform/marvell/sai/Makefile @@ -0,0 +1,9 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MRVL_SAI_URL = https://github.com/Marvell-switching/SAI-plugin/raw/$(MRVL_SAI_TAG)/sai_deb/$(MRVL_SAI) + +$(addprefix $(DEST)/, $(MRVL_SAI)): $(DEST)/% : + # get deb package + wget -O $(DEST)/$(MRVL_SAI) $(MRVL_SAI_URL) diff --git a/platform/marvell/sdk.mk b/platform/marvell/sdk.mk new file mode 100644 index 000000000000..3d1ce8e04c88 --- /dev/null +++ b/platform/marvell/sdk.mk @@ -0,0 +1,8 @@ +# Marvell FPA + +export MRVL_FPA_VERSION = 1.2.1 +export MRVL_FPA_TAG = SONiC.201803 +export MRVL_FPA = mrvllibfpa_$(MRVL_FPA_VERSION).deb + +$(MRVL_FPA)_SRC_PATH = $(PLATFORM_PATH)/sdk +SONIC_MAKE_DEBS += $(MRVL_FPA) diff --git a/platform/marvell/sdk/Makefile b/platform/marvell/sdk/Makefile new file mode 100644 index 000000000000..6822c7d7d274 --- /dev/null +++ b/platform/marvell/sdk/Makefile @@ -0,0 +1,9 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MRVL_FPA_URL = https://github.com/Marvell-switching/SAI-plugin/raw/$(MRVL_FPA_TAG)/sdk_deb/$(MRVL_FPA) + +$(addprefix $(DEST)/, $(MRVL_FPA)): $(DEST)/% : + # get deb package + wget -O $(DEST)/$(MRVL_FPA) $(MRVL_FPA_URL) diff --git a/platform/mellanox/.gitignore b/platform/mellanox/.gitignore new file mode 100644 index 000000000000..ac1ce990d56d --- /dev/null +++ b/platform/mellanox/.gitignore @@ -0,0 +1,11 @@ +# Subdirectories +mlnx-sai/* +!mlnx-sai/Makefile +hw-management/* +!hw-management/Makefile +!hw-management/*.patch +mft/* +!mft/Makefile + +# Autogenerated Dockerfiles +docker-syncd-mlnx/Dockerfile diff --git a/platform/mellanox/criu.mk b/platform/mellanox/criu.mk new file mode 100644 index 000000000000..01a425bb2a8a --- /dev/null +++ b/platform/mellanox/criu.mk @@ -0,0 +1,8 @@ +CRIU_VERSION = 3.10 + +export CRIU_VERSION + +CRIU = criu_$(CRIU_VERSION)-1_amd64.deb +$(CRIU)_SRC_PATH = $(PLATFORM_PATH)/criu +$(CRIU)_DEPENDS += $(LIBNL3_DEV) +SONIC_MAKE_DEBS += $(CRIU) diff --git a/platform/mellanox/criu/Makefile b/platform/mellanox/criu/Makefile new file mode 100644 index 000000000000..e9d49b569042 --- /dev/null +++ b/platform/mellanox/criu/Makefile @@ -0,0 +1,14 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = criu_$(CRIU_VERSION)-1_amd64.deb + +CRIU_DEPS = iptables,protobuf-c-compiler,protobuf-compiler,python-protobuf,libprotobuf-c1,python-future,python-ipaddr,libnet1,pkg-config,asciidoc,xmlto + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf criu + git clone -b v$(CRIU_VERSION) https://github.com/checkpoint-restore/criu.git + pushd criu + RUNDIR=/run/criu make + sudo checkinstall --default --install=no --fstrans=no --pkgversion=$(CRIU_VERSION) --maintainer='@' --requires=$(CRIU_DEPS) --pakdir=$(DEST) diff --git a/platform/mellanox/docker-orchagent-mlnx.mk b/platform/mellanox/docker-orchagent-mlnx.mk new file mode 100644 index 000000000000..5e72beb4c300 --- /dev/null +++ b/platform/mellanox/docker-orchagent-mlnx.mk @@ -0,0 +1,24 @@ +# docker image for orchagent + +DOCKER_ORCHAGENT_MLNX = docker-orchagent-mlnx.gz +$(DOCKER_ORCHAGENT_MLNX)_PATH = $(DOCKERS_PATH)/docker-orchagent +$(DOCKER_ORCHAGENT_MLNX)_DEPENDS += $(SWSS) $(REDIS_TOOLS) $(IPROUTE2) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_ORCHAGENT_MLNX)_DEPENDS += $(SWSS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_ORCHAGENT_MLNX)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_MLNX) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_MLNX) + +$(DOCKER_ORCHAGENT_MLNX)_CONTAINER_NAME = swss +$(DOCKER_ORCHAGENT_MLNX)_RUN_OPT += --net=host --privileged -t +$(DOCKER_ORCHAGENT_MLNX)_RUN_OPT += -v /etc/network/interfaces:/etc/network/interfaces:ro +$(DOCKER_ORCHAGENT_MLNX)_RUN_OPT += -v /etc/network/interfaces.d/:/etc/network/interfaces.d/:ro +$(DOCKER_ORCHAGENT_MLNX)_RUN_OPT += -v /host/machine.conf:/host/machine.conf:ro +$(DOCKER_ORCHAGENT_MLNX)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_ORCHAGENT_MLNX)_RUN_OPT += -v /var/log/swss:/var/log/swss:rw + +$(DOCKER_ORCHAGENT_MLNX)_BASE_IMAGE_FILES += swssloglevel:/usr/bin/swssloglevel +$(DOCKER_ORCHAGENT_MLNX)_FILES += $(ARP_UPDATE_SCRIPT) diff --git a/platform/mellanox/docker-ptf-mlnx.mk b/platform/mellanox/docker-ptf-mlnx.mk new file mode 100644 index 000000000000..f6d17e72fcfe --- /dev/null +++ b/platform/mellanox/docker-ptf-mlnx.mk @@ -0,0 +1,7 @@ +# docker image for docker-ptf-mlnx + +DOCKER_PTF_MLNX = docker-ptf-mlnx.gz +$(DOCKER_PTF_MLNX)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift +$(DOCKER_PTF_MLNX)_DEPENDS += $(PYTHON_SAITHRIFT) +$(DOCKER_PTF_MLNX)_LOAD_DOCKERS += $(DOCKER_PTF) +SONIC_DOCKER_IMAGES += $(DOCKER_PTF_MLNX) diff --git a/platform/mellanox/docker-saiserver-mlnx.mk b/platform/mellanox/docker-saiserver-mlnx.mk new file mode 100644 index 000000000000..22f87327554e --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx.mk @@ -0,0 +1,13 @@ +# docker image for mlnx saiserver + +DOCKER_SAISERVER_MLNX = docker-saiserver-mlnx.gz +$(DOCKER_SAISERVER_MLNX)_PATH = $(PLATFORM_PATH)/docker-saiserver-mlnx +$(DOCKER_SAISERVER_MLNX)_DEPENDS += $(SAISERVER) $(PYTHON_SDK_API) $(MLNX_SFPD) $(CRIU) +$(DOCKER_SAISERVER_MLNX)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SAISERVER_MLNX) + +$(DOCKER_SAISERVER_MLNX)_CONTAINER_NAME = saiserver +$(DOCKER_SAISERVER_MLNX)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SAISERVER_MLNX)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SAISERVER_MLNX)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SYNCD_MLNX)_RUN_OPT += --tmpfs /run/criu diff --git a/platform/mellanox/docker-saiserver-mlnx/Dockerfile.j2 b/platform/mellanox/docker-saiserver-mlnx/Dockerfile.j2 new file mode 100644 index 000000000000..0ada859e6450 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx/Dockerfile.j2 @@ -0,0 +1,36 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_saiserver_mlnx_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get install -y --no-install-recommends libxml2 iptables libbsd0 protobuf-c-compiler protobuf-compiler python-protobuf libprotobuf-c1 python-future python-ipaddr libnet1 pkg-config asciidoc xmlto + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_saiserver_mlnx_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +COPY ["start.sh", "/usr/bin/"] + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +COPY ["profile.ini", "portmap.ini", "/etc/sai/"] + +COPY ["sai_2700.xml", "/usr/share/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/mellanox/docker-saiserver-mlnx/portmap.ini b/platform/mellanox/docker-saiserver-mlnx/portmap.ini new file mode 100644 index 000000000000..4d3be08ce5f8 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx/portmap.ini @@ -0,0 +1,33 @@ +# alias lanes +Ethernet1 0,1,2,3 +Ethernet2 4,5,6,7 +Ethernet3 8,9,10,11 +Ethernet4 12,13,14,15 +Ethernet5 16,17,18,19 +Ethernet6 20,21,22,23 +Ethernet7 24,25,26,27 +Ethernet8 28,29,30,31 +Ethernet9 32,33,34,35 +Ethernet10 36,37,38,39 +Ethernet11 40,41,42,43 +Ethernet12 44,45,46,47 +Ethernet13 48,49,50,51 +Ethernet14 52,53,54,55 +Ethernet15 56,57,58,59 +Ethernet16 60,61,62,63 +Ethernet17 64,65,66,67 +Ethernet18 68,69,70,71 +Ethernet19 72,73,74,75 +Ethernet20 76,77,78,79 +Ethernet21 80,81,82,83 +Ethernet22 84,85,86,87 +Ethernet23 88,89,90,91 +Ethernet24 92,93,94,95 +Ethernet25 96,97,98,99 +Ethernet26 100,101,102,103 +Ethernet27 104,105,106,107 +Ethernet28 108,109,110,111 +Ethernet29 112,113,114,115 +Ethernet30 116,117,118,119 +Ethernet31 120,121,122,123 +Ethernet32 124,125,126,127 \ No newline at end of file diff --git a/platform/mellanox/docker-saiserver-mlnx/profile.ini b/platform/mellanox/docker-saiserver-mlnx/profile.ini new file mode 100644 index 000000000000..c67be49f3c45 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx/profile.ini @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sai_2700.xml \ No newline at end of file diff --git a/platform/mellanox/docker-saiserver-mlnx/sai_2700.xml b/platform/mellanox/docker-saiserver-mlnx/sai_2700.xml new file mode 100644 index 000000000000..42b576311453 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx/sai_2700.xml @@ -0,0 +1,243 @@ + + + + + + 00:77:66:55:44:00 + + + 32 + + + + + 1 + 4 + 16 + + + 3 + + + 98368 + + + 3 + 4 + 17 + 1 + 98368 + + + 5 + 4 + 18 + 3 + 98368 + + + 7 + 4 + 19 + 1 + 98368 + + + 9 + 4 + 20 + 3 + 98368 + + + 11 + 4 + 21 + 1 + 98368 + + + 13 + 4 + 22 + 3 + 98368 + + + 15 + 4 + 23 + 1 + 98368 + + + 17 + 4 + 24 + 3 + 98368 + + + 19 + 4 + 25 + 1 + 98368 + + + 21 + 4 + 26 + 3 + 98368 + + + 23 + 4 + 27 + 1 + 98368 + + + 25 + 4 + 28 + 3 + 98368 + + + 27 + 4 + 29 + 1 + 98368 + + + 29 + 4 + 30 + 3 + 98368 + + + 31 + 4 + 31 + 1 + 98368 + + + 33 + 4 + 14 + 3 + 98368 + + + 35 + 4 + 15 + 1 + 98368 + + + 37 + 4 + 12 + 3 + 98368 + + + 39 + 4 + 13 + 1 + 98368 + + + 41 + 4 + 10 + 3 + 98368 + + + 43 + 4 + 11 + 1 + 98368 + + + 45 + 4 + 8 + 3 + 98368 + + + 47 + 4 + 9 + 1 + 98368 + + + 49 + 4 + 6 + 3 + 98368 + + + 51 + 4 + 7 + 1 + 98368 + + + 53 + 4 + 4 + 3 + 98368 + + + 55 + 4 + 5 + 1 + 98368 + + + 57 + 4 + 2 + 3 + 98368 + + + 59 + 4 + 3 + 1 + 98368 + + + 61 + 4 + 0 + 3 + 98368 + + + 63 + 4 + 1 + 1 + 98368 + + + + diff --git a/platform/mellanox/docker-saiserver-mlnx/start.sh b/platform/mellanox/docker-saiserver-mlnx/start.sh new file mode 100755 index 000000000000..58a0c316add3 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx/start.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +start_mlnx() +{ + [ -e /dev/sxdevs/sxcdev ] || ( mkdir -p /dev/sxdevs && mknod /dev/sxdevs/sxcdev c 231 193 ) +} + + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +start_mlnx + +supervisorctl start saiserver diff --git a/platform/mellanox/docker-saiserver-mlnx/supervisord.conf b/platform/mellanox/docker-saiserver-mlnx/supervisord.conf new file mode 100644 index 000000000000..cb67a0fc9a47 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx/supervisord.conf @@ -0,0 +1,28 @@ +[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:saiserver] +command=/usr/bin/saiserver -p /etc/sai/profile.ini -f /etc/sai/portmap.ini +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/mellanox/docker-syncd-mlnx-rpc.mk b/platform/mellanox/docker-syncd-mlnx-rpc.mk new file mode 100644 index 000000000000..b11c5a8c0d51 --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx-rpc.mk @@ -0,0 +1,16 @@ +# docker image for mlnx syncd with rpc + +DOCKER_SYNCD_MLNX_RPC = docker-syncd-mlnx-rpc.gz +$(DOCKER_SYNCD_MLNX_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-mlnx-rpc +$(DOCKER_SYNCD_MLNX_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(MLNX_SFPD) $(MLNX_ISSU) +$(DOCKER_SYNCD_MLNX_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_MLNX) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_MLNX_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_MLNX_RPC) +endif + +$(DOCKER_SYNCD_MLNX_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_MLNX_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_MLNX_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_MLNX_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SYNCD_MLNX_RPC)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/mellanox/docker-syncd-mlnx-rpc/Dockerfile.j2 b/platform/mellanox/docker-syncd-mlnx-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..0a2010dcbbc1 --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx-rpc/Dockerfile.j2 @@ -0,0 +1,51 @@ +FROM docker-syncd-mlnx + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_mlnx_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -P syncd + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_mlnx_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + && wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/mellanox/docker-syncd-mlnx-rpc/ptf_nn_agent.conf b/platform/mellanox/docker-syncd-mlnx-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..cd6a7d4db75d --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-nn-rcv-buffer=109430400 --set-iface-rcv-buffer=109430400 --set-nn-snd-buffer=109430400 --set-iface-snd-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/mellanox/docker-syncd-mlnx.mk b/platform/mellanox/docker-syncd-mlnx.mk new file mode 100644 index 000000000000..dd11f32f7122 --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx.mk @@ -0,0 +1,17 @@ +# docker image for mlnx syncd + +DOCKER_SYNCD_MLNX = docker-syncd-mlnx.gz +$(DOCKER_SYNCD_MLNX)_PATH = $(PLATFORM_PATH)/docker-syncd-mlnx +$(DOCKER_SYNCD_MLNX)_DEPENDS += $(SYNCD) $(PYTHON_SDK_API) $(MLNX_SFPD) $(CRIU) $(MLNX_ISSU) +$(DOCKER_SYNCD_MLNX)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_MLNX) +ifneq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_MLNX) +endif + +$(DOCKER_SYNCD_MLNX)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_MLNX)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_MLNX)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_MLNX)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SYNCD_MLNX)_RUN_OPT += -v /host/warmboot:/var/warmboot +$(DOCKER_SYNCD_MLNX)_RUN_OPT += --tmpfs /run/criu diff --git a/platform/mellanox/docker-syncd-mlnx/Dockerfile.j2 b/platform/mellanox/docker-syncd-mlnx/Dockerfile.j2 new file mode 100755 index 000000000000..bf301f179a42 --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx/Dockerfile.j2 @@ -0,0 +1,31 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_syncd_mlnx_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get install -y --no-install-recommends libxml2 iptables libbsd0 protobuf-c-compiler protobuf-compiler python-protobuf libprotobuf-c1 python-future python-ipaddr libnet1 pkg-config asciidoc xmlto + +RUN dpkg -i \ +{% for deb in docker_syncd_mlnx_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/mellanox/docker-syncd-mlnx/start.sh b/platform/mellanox/docker-syncd-mlnx/start.sh new file mode 100755 index 000000000000..7753b134f7ce --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx/start.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start syncd + +supervisorctl start mlnx-sfpd + +BOOT_TYPE="$(cat /proc/cmdline | grep -o 'SONIC_BOOT_TYPE=\S*' | cut -d'=' -f2)" +if [[ x"$BOOT_TYPE" == x"fastfast" ]] && [[ -f /var/warmboot/issu_started ]]; then + rm -f /var/warmboot/issu_started + /usr/bin/ffb &>/dev/null & +fi diff --git a/platform/mellanox/docker-syncd-mlnx/supervisord.conf b/platform/mellanox/docker-syncd-mlnx/supervisord.conf new file mode 100644 index 000000000000..8860bd6c0205 --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx/supervisord.conf @@ -0,0 +1,36 @@ +[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:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:mlnx-sfpd] +command=/usr/bin/mlnx-sfpd +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/mellanox/fw.mk b/platform/mellanox/fw.mk new file mode 100644 index 000000000000..8ec35a22cfe3 --- /dev/null +++ b/platform/mellanox/fw.mk @@ -0,0 +1,9 @@ +# mellanox firmware + +MLNX_FW_VERSION = 13.1910.0608 +MLNX_FW_FILE = fw-SPC-rel-$(subst .,_,$(MLNX_FW_VERSION))-EVB.mfa +$(MLNX_FW_FILE)_URL = $(MLNX_SDK_BASE_URL)/$(MLNX_FW_FILE) +SONIC_ONLINE_FILES += $(MLNX_FW_FILE) + +export MLNX_FW_VERSION +export MLNX_FW_FILE diff --git a/platform/mellanox/hw-management.mk b/platform/mellanox/hw-management.mk new file mode 100644 index 000000000000..10e6bcd76652 --- /dev/null +++ b/platform/mellanox/hw-management.mk @@ -0,0 +1,12 @@ +# Mellanox HW Management + +MLNX_HW_MANAGEMENT_VERSION = 27.09.2018 + +export MLNX_HW_MANAGEMENT_VERSION + +MLNX_HW_MANAGEMENT = hw-management_1.mlnx.$(MLNX_HW_MANAGEMENT_VERSION)_amd64.deb +$(MLNX_HW_MANAGEMENT)_SRC_PATH = $(PLATFORM_PATH)/hw-management +$(MLNX_HW_MANAGEMENT)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_MAKE_DEBS += $(MLNX_HW_MANAGEMENT) + +SONIC_STRETCH_DEBS += $(MLNX_HW_MANAGEMENT) diff --git a/platform/mellanox/hw-management/Makefile b/platform/mellanox/hw-management/Makefile new file mode 100644 index 000000000000..608c94e6b02a --- /dev/null +++ b/platform/mellanox/hw-management/Makefile @@ -0,0 +1,14 @@ +.ONESHELL: +SHELL = /bin/bash + +MAIN_TARGET = hw-management_1.mlnx.$(MLNX_HW_MANAGEMENT_VERSION)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + + pushd hw-mgmt + git am ../*.patch + chmod +x ./debian/rules + sudo ./debian/rules binary KVERSION=$(KVERSION) + popd + + mv $* $(DEST)/ diff --git a/platform/mellanox/hw-management/hw-mgmt b/platform/mellanox/hw-management/hw-mgmt new file mode 160000 index 000000000000..344e81942c02 --- /dev/null +++ b/platform/mellanox/hw-management/hw-mgmt @@ -0,0 +1 @@ +Subproject commit 344e81942c02c279db03c3aba40db4142dc6817d diff --git a/platform/mellanox/libsaithrift-dev.mk b/platform/mellanox/libsaithrift-dev.mk new file mode 100644 index 000000000000..6d67ef15411e --- /dev/null +++ b/platform/mellanox/libsaithrift-dev.mk @@ -0,0 +1,20 @@ +# libsaithrift-dev package + +SAI_VER = 1.3.5 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_amd64.deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(MLNX_SAI) $(MLNX_SAI_DEV) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(MLNX_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_amd64.deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_amd64.deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(MLNX_SAI) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_amd64.deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/mellanox/mft.mk b/platform/mellanox/mft.mk new file mode 100644 index 000000000000..5191fa41bcf5 --- /dev/null +++ b/platform/mellanox/mft.mk @@ -0,0 +1,19 @@ +# Mellanox SAI + +MFT_VERSION = 4.9.0 +MFT_REVISION = 38 + +export MFT_VERSION MFT_REVISION + +MFT = mft-$(MFT_VERSION)-$(MFT_REVISION).amd64.deb +$(MFT)_SRC_PATH = $(PLATFORM_PATH)/mft +$(MFT)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_MAKE_DEBS += $(MFT) + +KERNEL_MFT = kernel-mft-dkms_$(MFT_VERSION)-$(KVERSION)_all.deb +$(eval $(call add_derived_package,$(MFT),$(KERNEL_MFT))) + +MFT_OEM = mft-oem-$(MFT_VERSION)-$(MFT_REVISION).amd64.deb +$(eval $(call add_derived_package,$(MFT),$(MFT_OEM))) + +SONIC_STRETCH_DEBS += $(KERNEL_MFT) diff --git a/platform/mellanox/mft/Makefile b/platform/mellanox/mft/Makefile new file mode 100644 index 000000000000..15a12decb4e8 --- /dev/null +++ b/platform/mellanox/mft/Makefile @@ -0,0 +1,32 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MFT_NAME = mft-$(MFT_VERSION)-$(MFT_REVISION)-x86_64-deb +MFT_TGZ = $(MFT_NAME).tgz +SRC_DEB = kernel-mft-dkms_$(MFT_VERSION)-$(MFT_REVISION)_all.deb + +MAIN_TARGET = mft-$(MFT_VERSION)-$(MFT_REVISION).amd64.deb +DERIVED_TARGETS = kernel-mft-dkms_$(MFT_VERSION)-$(KVERSION)_all.deb mft-oem-$(MFT_VERSION)-$(MFT_REVISION).amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf $(MFT_NAME) + wget -O $(MFT_TGZ) http://www.mellanox.com/downloads/MFT/$(MFT_TGZ) + tar xzf $(MFT_TGZ) + pushd $(MFT_NAME)/SDEBS + + # put a lock here because dpkg does not allow installing packages in parallel + while true; do + if mkdir $(DEST)/dpkg_lock &> /dev/null; then + { sudo dpkg -i $(SRC_DEB) && rm -d $(DEST)/dpkg_lock && break; } || { rm -d $(DEST)/dpkg_lock && exit 1 ; } + fi + done + + tar xvf `sudo dkms mkdriverdisk kernel-mft-dkms/$(MFT_VERSION) -a all -d ubuntu -k $(KVERSION) --media tar | grep "Disk image location" | cut -d':' -f2` + popd + + # fix timestamp because we do not actually build tools, only kernel + touch $(MFT_NAME)/DEBS/* + mv $(MFT_NAME)/SDEBS/ubuntu-drivers/4.9.0/kernel-mft-dkms_$(MFT_VERSION)-$(KVERSION)_all.deb $(MFT_NAME)/DEBS/* $(DEST) + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/mellanox/mlnx-ffb.mk b/platform/mellanox/mlnx-ffb.mk new file mode 100755 index 000000000000..dabb995a3658 --- /dev/null +++ b/platform/mellanox/mlnx-ffb.mk @@ -0,0 +1,7 @@ +# mellanox fast fast boot script + +MLNX_FFB_SCRIPT = mlnx-ffb.sh +$(MLNX_FFB_SCRIPT)_PATH = platform/mellanox/ +SONIC_COPY_FILES += $(MLNX_FFB_SCRIPT) + +export MLNX_FFB_SCRIPT diff --git a/platform/mellanox/mlnx-ffb.sh b/platform/mellanox/mlnx-ffb.sh new file mode 100755 index 000000000000..d06721081a5d --- /dev/null +++ b/platform/mellanox/mlnx-ffb.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +FFB_SUCCESS=0 +FFB_FAILURE=1 + +# Check if ISSU is enabled on this device +check_issu_enabled() +{ + CHECK_RESULT="${FFB_FAILURE}" + ISSU_CHECK_CMD="show platform mlnx issu" + + # Check whether show ISSU status outputs ENABLED + if [[ `$ISSU_CHECK_CMD` =~ "enabled" ]]; then + # ISSU enabled, return success + CHECK_RESULT="${FFB_SUCCESS}" + fi + + return "${CHECK_RESULT}" +} + +# Check if ISSU upgrade from current SDK to next image SDK is supported +check_sdk_upgrade() +{ + CHECK_RESULT="${FFB_FAILURE}" + + NEXT_SONIC_IMAGE="$(sonic_installer list | grep "Next: " | cut -f2 -d' ')" + CURRENT_SONIC_IMAGE="$(sonic_installer list | grep "Current: " | cut -f2 -d' ')" + + FS_PATH="/host/image-${NEXT_SONIC_IMAGE#SONiC-OS-}/fs.squashfs" + FS_MOUNTPOINT="/tmp/image-${NEXT_SONIC_IMAGE#SONiC-OS-}-fs" + + if [[ "${CURRENT_SONIC_IMAGE}" == "${NEXT_SONIC_IMAGE}" ]]; then + return "${FFB_SUCCESS}" + fi + + while :; do + mkdir -p "${FS_MOUNTPOINT}" + mount -t squashfs "${FS_PATH}" "${FS_MOUNTPOINT}" || { + >&2 echo "Failed to mount next SONiC image" + break; + } + + SDK_VERSION_FILE_PATH="${FS_MOUNTPOINT}/etc/mlnx/sdk-version" + + [ -f "${SDK_VERSION_FILE_PATH}" ] && { + NEXT_SDK_VERSION="$(cat ${FS_MOUNTPOINT}/etc/mlnx/sdk-version)" + } || { + >&2 echo "No SDK version file ${SDK_VERSION_FILE_PATH}" + break; + } + + ISSU_CHECK_CMD="docker exec -t syncd issu --check ${NEXT_SDK_VERSION}" + + ${ISS_CHECK_CMD} > /dev/null && CHECK_RESULT="${FFB_SUCCESS}" + + break + done + + umount -rf "${FS_MOUNTPOINT}" 2> /dev/null || true + rm -rf "${FS_MOUNTPOINT}" 2> /dev/null || true + + return "${CHECK_RESULT}" +} + +# Perform ISSU start +issu_start() +{ + ISSU_START_CMD="docker exec -t syncd issu --start" + ${ISSU_START_CMD} > /dev/null + + EXIT_CODE=$? + + touch /host/warmboot/issu_started + + return $EXIT_CODE +} + +# Perform ISSU end +issu_end() +{ + ISSU_END_CMD="docker exec -t syncd issu --end" + ${ISSU_END_CMD} > /dev/null + + EXIT_CODE=$? + + return $EXIT_CODE +} diff --git a/platform/mellanox/mlnx-fw-upgrade.j2 b/platform/mellanox/mlnx-fw-upgrade.j2 new file mode 100755 index 000000000000..28df25f43ec0 --- /dev/null +++ b/platform/mellanox/mlnx-fw-upgrade.j2 @@ -0,0 +1,143 @@ +#!/bin/bash + +declare -r SCRIPT_NAME="$(basename "$0")" +declare -r SCRIPT_PATH="$(readlink -f "$0")" +declare -r SCRIPT_DIR="$(dirname "$SCRIPT_PATH")" + +declare -r EXIT_SUCCESS="0" +declare -r EXIT_ERROR="1" + +declare -r QUERY_CMD="mlxfwmanager --query" +declare -r BURN_CMD="mlxfwmanager -u -f -y" + +declare -r FW_FILE="/etc/mlnx/fw-SPC.mfa" +declare -r QUERY_FILE="/tmp/mlnxfwmanager-query.txt" + +declare -r FW_REQUIRED="{{ MLNX_FW_VERSION }}" + +IMAGE_UPGRADE="no" + +function PrintHelp() { + echo + echo "Usage: ./${SCRIPT_NAME} [OPTIONS]" + echo + echo "OPTIONS:" + echo " -u, --upgrade Upgrade MLNX ASIC firmware using next boot image (useful after SONiC-To-SONiC update)" + echo " -h, --help Print help" + echo + echo "Examples:" + echo " ./${SCRIPT_NAME}" + echo " ./${SCRIPT_NAME} --upgrade" + echo " ./${SCRIPT_NAME} --help" + echo +} + +function ParseArguments() { + while [ $# -ge 1 ]; do + case "$1" in + -u|--upgrade) + IMAGE_UPGRADE="yes" + ;; + -h|--help) + PrintHelp + exit "${EXIT_SUCCESS}" + ;; + esac + shift + done +} + +function WaitForDevice() { + local -i QUERY_RETRY_COUNT_MAX="10" + local -i QUERY_RETRY_COUNT="0" + + ${QUERY_CMD} > /dev/null + + while [[ ("${QUERY_RETRY_COUNT}" -lt "${QUERY_RETRY_COUNT_MAX}") && ("$?" -ne "0") ]]; do + sleep 1s + ((QUERY_RETRY_COUNT++)) + ${QUERY_CMD} > /dev/null + done +} + +function RunCmd() { + $1 + if [[ $? != 0 ]]; then + echo "Command failed: cmd=$1, errno=$?" + exit "${EXIT_ERROR}" + fi +} + +function UpgradeFW() { + local _FW_FILE="$1" + + if [ ! -z "${_FW_FILE}" ]; then + if [ ! -f "${_FW_FILE}" ]; then + echo "No such file: ${_FW_FILE}" + exit "${EXIT_ERROR}" + fi + + RunCmd "${QUERY_CMD} -i ${_FW_FILE}" > "${QUERY_FILE}" + + local -r _FW_INFO="$(grep FW ${QUERY_FILE})" + local -r _FW_CURRENT="$(echo ${_FW_INFO} | cut -f2 -d' ')" + local -r _FW_AVAILABLE="$(echo ${_FW_INFO} | cut -f3 -d' ')" + else + RunCmd "${QUERY_CMD}" > "${QUERY_FILE}" + + local -r _FW_INFO="$(grep FW ${QUERY_FILE})" + local -r _FW_CURRENT="$(echo ${_FW_INFO} | cut -f2 -d' ')" + local -r _FW_AVAILABLE="${FW_REQUIRED}" + + _FW_FILE="${FW_FILE}" + fi + + if [[ -z "${_FW_CURRENT}" ]]; then + echo "Could not retreive current FW version" + exit "${EXIT_ERROR}" + fi + + if [[ -z "${_FW_AVAILABLE}" ]]; then + echo "Could not retreive available FW version" + exit "${EXIT_ERROR}" + fi + + if [[ "${_FW_CURRENT}" == "${_FW_AVAILABLE}" ]]; then + echo "Mellanox firmware is up to date" + else + echo "Mellanox firmware upgrade is required. Installing compatible version..." + RunCmd "${BURN_CMD} -i ${_FW_FILE}" + fi +} + +function UpgradeFWFromImage() { + local -r _NEXT_SONIC_IMAGE="$(sonic_installer list | grep "Next: " | cut -f2 -d' ')" + local -r _CURRENT_SONIC_IMAGE="$(sonic_installer list | grep "Current: " | cut -f2 -d' ')" + + local -r _FS_PATH="/host/image-${_NEXT_SONIC_IMAGE#SONiC-OS-}/fs.squashfs" + local -r _FS_MOUNTPOINT="/tmp/image-${_NEXT_SONIC_IMAGE#SONiC-OS-}-fs" + + if [[ "${_CURRENT_SONIC_IMAGE}" == "${_NEXT_SONIC_IMAGE}" ]]; then + echo "Mellanox firmware is up to date" + else + mkdir -p "${_FS_MOUNTPOINT}" + mount -t squashfs "${_FS_PATH}" "${_FS_MOUNTPOINT}" + + UpgradeFW "${_FS_MOUNTPOINT}/etc/mlnx/fw-SPC.mfa" + + umount -rf "${_FS_MOUNTPOINT}" + rm -rf "${_FS_MOUNTPOINT}" + fi +} + +ParseArguments "$@" + +WaitForDevice + +if [ "${IMAGE_UPGRADE}" != "yes" ]; then + UpgradeFW +else + UpgradeFWFromImage +fi + +exit "${EXIT_SUCCESS}" diff --git a/platform/mellanox/mlnx-issu.mk b/platform/mellanox/mlnx-issu.mk new file mode 100755 index 000000000000..f0e3b47050ac --- /dev/null +++ b/platform/mellanox/mlnx-issu.mk @@ -0,0 +1,5 @@ +# issu (SONiC MLNX platform ISSU tool) Debian package + +MLNX_ISSU = python-mlnx-issu_1.0-1_all.deb +$(MLNX_ISSU)_SRC_PATH = $(PLATFORM_PATH)/mlnx-issu +SONIC_PYTHON_STDEB_DEBS += $(MLNX_ISSU) diff --git a/platform/mellanox/mlnx-issu/scripts/ffb b/platform/mellanox/mlnx-issu/scripts/ffb new file mode 100755 index 000000000000..e862083d2942 --- /dev/null +++ b/platform/mellanox/mlnx-issu/scripts/ffb @@ -0,0 +1,69 @@ +#!/usr/bin/env python +""" +Part of Mellanox platform specific fastfast boot implementation for warm-boot. +Notifies SYNCD proccess once boot is finished after warm-reboot. +Once SYNCD received such notification it should set appropriate SAI attribute. +Then SAI will notify SDK to end ISSU mode for the FFB. +""" + + +import time +import swsssdk +from threading import Timer + + +class FFB(object): + """Provides implementation for Mellanox fastfast boot""" + DB_WARM_TABLE_KEY = 'WARM_RESTART_TABLE|bgp' + DB_STATE_ENTRY_NAME = 'state' + DB_STATE_TYPE_RECONCILED = 'reconciled' + DB_CHANNEL_NAME = 'MLNX_FFB' + DB_CHANNEL_MSG = '["SET","ISSU_END"]' # message should be in the following format: ["",""] + SUB_THREAD_TIMEOUT = 1 + STOP_TIMER_TIMEOUT = 180 + + def __init__(self): + self.state_db = swsssdk.SonicV2Connector() + self.state_db.connect(self.state_db.STATE_DB) + + self.prevState = self.state_db.get(self.state_db.STATE_DB, self.DB_WARM_TABLE_KEY, self.DB_STATE_ENTRY_NAME) + + self.pubSub = self.state_db.redis_clients[self.state_db.STATE_DB].pubsub() + self.pubSub.psubscribe(**{'__key*@6__:{}'.format(self.DB_WARM_TABLE_KEY): self.eventHandler}) + + self.timeoutTimer = Timer(self.STOP_TIMER_TIMEOUT, self.finish) + + def run(self): + # Start event thread in order to get required events + self.eventThread = self.pubSub.run_in_thread(sleep_time=self.SUB_THREAD_TIMEOUT) + # Start oneshot timer in order to exit in case required event is not received during defined timeout + self.timeoutTimer.start() + + def finish(self): + # Stop event thread and timeout timer + self.eventThread.stop() + self.timeoutTimer.cancel() + + # Publish "FFB END" event to SYNCD process + time.sleep(60) # W/A: Wait until configuration is applied to HW since it takes some time + self.state_db.publish(self.state_db.STATE_DB, self.DB_CHANNEL_NAME, self.DB_CHANNEL_MSG) + + def eventHandler(self, msg): + # Only "set" operations are needed so just skip all others + if msg['data'] != 'hset': + return + + state = self.state_db.get(self.state_db.STATE_DB, self.DB_WARM_TABLE_KEY, self.DB_STATE_ENTRY_NAME) + + if (state != self.prevState) and (state == self.DB_STATE_TYPE_RECONCILED): + self.finish() + else: + self.prevState = state + + +def main(): + FFB().run() + + +if __name__ == '__main__': + main() diff --git a/platform/mellanox/mlnx-issu/scripts/issu b/platform/mellanox/mlnx-issu/scripts/issu new file mode 100755 index 000000000000..45c0f50436c7 --- /dev/null +++ b/platform/mellanox/mlnx-issu/scripts/issu @@ -0,0 +1,176 @@ +#!/usr/bin/env python +''' +This code is for a mlnx platform specific tool, issu. +This tool provides an CLI interface to interact with SDK ISSU module +''' + +from __future__ import print_function + +import sys +import os +import re +import errno +import syslog +import argparse + +from functools import wraps + +from python_sdk_api import sx_api + +# ========================== Constants =============================== +SDK_VERSION_PATTERN = r'(\d+)\.(\d+)\.(.*)' +SYSLOG_IDENTIFIER = "ISSU" + + +# Flag that indicates whether to print logs to stdout +verbose = False + + +# ========================== Syslog wrappers ========================== +def log_info(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + + if verbose: + print(msg) + +def log_warning(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_WARNING, msg) + syslog.closelog() + + if verbose: + print(msg) + +def log_error(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + print(msg, file=sys.stderr) + + +# ========================== Global functions ========================= +def with_sdk_handle(func): + """ A decorator for @func that use sx api + that gets a SDK handler, calls func(handler, *args, **kwargs) + and then closes the handler regardless of func failure""" + + @wraps(func) + def wrapped(*args, **kwargs): + log_info("opening sdk") + rc, handle = sx_api.sx_api_open(None) + log_info("sx_api_open handle: 0x%x , rc %d " % ( handle, rc) ) + + if rc != sx_api.SX_STATUS_SUCCESS: + log_error("failed to open api handle. Please check that SDK is running") + sys.exit(errno.EACCES) + + try: + res = func(handle, *args, **kwargs) + finally: + log_info("closing sdk handle") + rc = sx_api.sx_api_close(handle) + + if rc != sx_api.SX_STATUS_SUCCESS: + log_error("failed to close api handle") + + return res + + return wrapped + + +def check_sdk_version_pattern(sdk_version): + """Checker for @sdk_version""" + + if not re.match(SDK_VERSION_PATTERN, sdk_version): + raise argparse.ArgumentTypeError("{} is an invalid SDK version string".format(sdk_version)) + + return sdk_version + + +@with_sdk_handle +def check_issu_upgrade_to_sdk_version(handle, new_sdk): + """This function checks whether ISSU upgrade to @new_sdk version is posible""" + + version = sx_api.new_sx_api_sx_sdk_versions_t_p() + rc = sx_api.sx_api_sx_sdk_version_get(handle, version) + + if rc != sx_api.SX_STATUS_SUCCESS: + log_error("failed to get current SDK version") + sys.exit(errno.EACCES) + + current_sdk = version.sx_sdk + + succeed = True + + log_info('check ISSU upgrade: current SDK: {}, new SDK: {}, check succeed: {}'.format(current_sdk, new_sdk, succeed)) + + return succeed + + +@with_sdk_handle +def issu_start(handle): + """This function calls ISSU start API""" + + log_info("call ISSU start") + rc = sx_api.sx_api_issu_start_set(handle) + + if rc != sx_api.SX_STATUS_SUCCESS: + log_error("failed to execute ISSU start API") + sys.exit(errno.EACCES) + +@with_sdk_handle +def issu_end(handle): + """This function calls ISSU end API""" + + log_info("call ISSU end") + rc = sx_api.sx_api_issu_end_set(handle) + + if rc != sx_api.SX_STATUS_SUCCESS: + log_error("failed to execute ISSU end API") + sys.exit(errno.EACCES) + + +def get_parser(): + """This function creates an argument parser""" + + parser = argparse.ArgumentParser() + parser.add_argument('-c', '--check', nargs=1, action='store', default=None, type=check_sdk_version_pattern, + help='Check if ISSU upgrade is supported to new SDK version') + parser.add_argument('-s', '--start', action='store_true', help='Call ISSU start API') + parser.add_argument('-e', '--end', action='store_true', help='Call ISSU end API') + parser.add_argument('-v', '--verbose', action='store_true', default=False) + + return parser + + +def main(): + + global verbose + + parser = get_parser() + args = parser.parse_args() + + verbose = args.verbose + + if args.check is not None: + new_sdk = args.check[0] + is_supported = check_issu_upgrade_to_sdk_version(new_sdk) + + if verbose: + print('SDK upgrade is{}supported'.format(' ' if is_supported else ' not ')) + + if not is_supported: + sys.exit(1) + elif args.start: + issu_start() + elif args.end: + issu_end() + else: + parser.parse_args(['-h']) + + +if __name__ == '__main__': + main() diff --git a/platform/mellanox/mlnx-issu/setup.py b/platform/mellanox/mlnx-issu/setup.py new file mode 100755 index 000000000000..d1a733d6dce8 --- /dev/null +++ b/platform/mellanox/mlnx-issu/setup.py @@ -0,0 +1,15 @@ +from setuptools import setup + +setup( + name='mlnx-issu', + version='1.0', + description='MLNX ISSU tool for SONiC on mellanox platform', + author='SONiC Community', + url='https://github.com/Azure/sonic-buildimage/', + maintainer='Stepan Blyschak', + maintainer_email='stepanb@mellanox.com', + scripts=[ + 'scripts/issu', + 'scripts/ffb', + ] +) diff --git a/platform/mellanox/mlnx-sai.mk b/platform/mellanox/mlnx-sai.mk new file mode 100644 index 000000000000..4d422cfedfa8 --- /dev/null +++ b/platform/mellanox/mlnx-sai.mk @@ -0,0 +1,12 @@ +# Mellanox SAI + +MLNX_SAI_VERSION = SAIRel1.13.1-master +MLNX_SAI_REVISION = 673e8fbb10d5cba194daf237ffdc5edd974fc1b0 + +export MLNX_SAI_VERSION MLNX_SAI_REVISION + +MLNX_SAI = mlnx-sai_1.mlnx.$(MLNX_SAI_VERSION)_amd64.deb +$(MLNX_SAI)_SRC_PATH = $(PLATFORM_PATH)/mlnx-sai +$(MLNX_SAI)_DEPENDS += $(MLNX_SDK_DEBS) +$(MLNX_SAI)_RDEPENDS += $(MLNX_SDK_RDEBS) $(MLNX_SDK_DEBS) +SONIC_MAKE_DEBS += $(MLNX_SAI) diff --git a/platform/mellanox/mlnx-sai/Makefile b/platform/mellanox/mlnx-sai/Makefile new file mode 100644 index 000000000000..9a8005e5461f --- /dev/null +++ b/platform/mellanox/mlnx-sai/Makefile @@ -0,0 +1,21 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = mlnx-sai_1.mlnx.$(MLNX_SAI_VERSION)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + rm -rf SAI-Implementation + git clone https://github.com/Mellanox/SAI-Implementation.git + + # build + pushd SAI-Implementation + git checkout $(MLNX_SAI_REVISION) + pushd mlnx_sai + chmod a+x autogen.sh + debuild -e 'make_extra_flags="DEFS=-DACS_OS"' -us -uc -d -b + popd + + mv $* $(DEST)/ + popd diff --git a/platform/mellanox/mlnx-sfpd.mk b/platform/mellanox/mlnx-sfpd.mk new file mode 100644 index 000000000000..416dd7d0f2cd --- /dev/null +++ b/platform/mellanox/mlnx-sfpd.mk @@ -0,0 +1,5 @@ +# mlnx-sfpd (SONiC MLNX platform sfp event monitoring daemon) Debian package + +MLNX_SFPD = python-mlnx-sfpd_1.0-1_all.deb +$(MLNX_SFPD)_SRC_PATH = $(PLATFORM_PATH)/mlnx-sfpd +SONIC_PYTHON_STDEB_DEBS += $(MLNX_SFPD) diff --git a/platform/mellanox/mlnx-sfpd/scripts/mlnx-sfpd b/platform/mellanox/mlnx-sfpd/scripts/mlnx-sfpd new file mode 100644 index 000000000000..a1d2e6d9c3b5 --- /dev/null +++ b/platform/mellanox/mlnx-sfpd/scripts/mlnx-sfpd @@ -0,0 +1,244 @@ +#!/usr/bin/env python +''' +This code is for a mlnx platform specific daemon, mlnx-sfpd. +Which listen to the SDK for the SFP change event and post the event to DB. +''' + +from __future__ import print_function +import sys, errno +import os +import time +import syslog +import signal +import json +import threading +from python_sdk_api.sx_api import * +from swsssdk import SonicV2Connector + +VERSION = '1.0' + +SYSLOG_IDENTIFIER = "mlnx-sfpd" + +REDIS_HOSTIP = "127.0.0.1" + +SDK_SFP_STATE_IN = 0x1 +SDK_SFP_STATE_OUT = 0x2 +STATUS_PLUGIN = '1' +STATUS_PLUGOUT = '0' +STATUS_UNKNOWN = '2' + +SFPD_LIVENESS_UPDATE_INTERVAL_SECS = 30 + +sfp_value_status_dict = {SDK_SFP_STATE_IN:STATUS_PLUGIN, SDK_SFP_STATE_OUT:STATUS_PLUGOUT} + +# ========================== Syslog wrappers ========================== +def log_info(msg, also_print_to_console=False): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + + if also_print_to_console: + print(msg) + +def log_warning(msg, also_print_to_console=False): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_WARNING, msg) + syslog.closelog() + + if also_print_to_console: + print(msg) + +def log_error(msg, also_print_to_console=False): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + if also_print_to_console: + print(msg) + +# ========================== Signal Handling ========================== +def signal_handler(sig, frame): + if sig == signal.SIGHUP: + log_info("Caught SIGHUP - ignoring...") + return + elif sig == signal.SIGINT: + log_info("Caught SIGINT - exiting...") + sys.exit(128 + sig) + elif sig == signal.SIGTERM: + log_info("Caught SIGTERM - exiting...") + sys.exit(128 + sig) + else: + log_warning("Caught unhandled signal '" + sig + "'") + + +def sx_recv(fd_p, handle): + # recv parameters + pkt_size = 2000 + pkt_size_p = new_uint32_t_p() + uint32_t_p_assign(pkt_size_p, pkt_size) + pkt = new_uint8_t_arr(pkt_size) + recv_info_p = new_sx_receive_info_t_p() + pmpe_t = sx_event_pmpe_t() + logical_port_list = new_sx_port_log_id_t_arr(4) + port_attributes_list = new_sx_port_attributes_t_arr(64) + port_cnt_p = new_uint32_t_p() + uint32_t_p_assign(port_cnt_p,64) + label_port_list = [] + status = True + module_state = 0 + + rc = sx_lib_host_ifc_recv(fd_p, pkt, pkt_size_p, recv_info_p) + if rc != 0: + log_error("event receive exit with error, rc %d" % rc) + status = False + return status, label_port_list, module_state + + pmpe_t = recv_info_p.event_info.pmpe + port_list_size = pmpe_t.list_size + logical_port_list = pmpe_t.log_port_list + module_state = pmpe_t.module_state + + for i in range(0, port_list_size): + logical_port = sx_port_log_id_t_arr_getitem(logical_port_list, i) + rc = sx_api_port_device_get(handle, 1 , 0, port_attributes_list, port_cnt_p) + port_cnt = uint32_t_p_value(port_cnt_p) + + for i in range(0, port_cnt): + port_attributes = sx_port_attributes_t_arr_getitem(port_attributes_list,i) + if port_attributes.log_port == logical_port: + lable_port = port_attributes.port_mapping.module_port + break + label_port_list.append(lable_port) + + return status, label_port_list, module_state, + +def send_sfp_notification(db, interface, state): + sfp_notify = [interface, state] + msg = json.dumps(sfp_notify, separators=(',', ':')) + db.publish('STATE_DB', 'TRANSCEIVER_NOTIFY', msg) + return + +def update_sfpd_liveness_key(db, timeout_secs): + if db.exists('STATE_DB', 'MLNX_SFPD_TASK|LIVENESS'): + db.expire('STATE_DB', 'MLNX_SFPD_TASK|LIVENESS', timeout_secs) + else: + db.set('STATE_DB', 'MLNX_SFPD_TASK|LIVENESS', 'value', 'ok') + db.expire('STATE_DB', 'MLNX_SFPD_TASK|LIVENESS', timeout_secs) + +# Timer thread wrapper class to update mlnx-sfpd liveness info to DB periodically +class sfpd_liveness_update_task: + def __init__(self, db): + self.task_stopping_event = threading.Event() + self.task_timer = None + self.state_db = db + + def task_run(self): + if self.task_stopping_event.isSet(): + log_error("Error: sfpd liveness update thread received stop event, exiting...") + return + + update_sfpd_liveness_key(self.state_db, 2*SFPD_LIVENESS_UPDATE_INTERVAL_SECS) + + self.task_timer = threading.Timer(SFPD_LIVENESS_UPDATE_INTERVAL_SECS, self.task_run) + self.task_timer.start() + + def task_stop(self): + self.task_stopping_event.set() + self.task_timer.join() + + +# main start +def main(): + # Register our signal handlers + signal.signal(signal.SIGHUP, signal_handler) + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + # Connect to state db for notification sending + state_db = SonicV2Connector(host=REDIS_HOSTIP) + state_db.connect(state_db.STATE_DB) + + # Open SDK handler + log_info("starting mlnx-sfpd...") + rc, handle = sx_api_open(None) + retry_time = 1 + while rc != SX_STATUS_SUCCESS: + time.sleep(2**retry_time) + retry_time += 1 + rc, handle = sx_api_open(None) + if retry_time > 20: + log_error("Failed to open api handle. Please check that SDK is running.") + sys.exit(errno.EACCES) + + # Open recv fd + rx_fd_p = new_sx_fd_t_p() + rc = sx_api_host_ifc_open(handle, rx_fd_p) + if rc != 0: + log_error("sx_api_host_ifc_open exit with error, rc %d" % rc) + exit(rc) + + # Set up general host ifc parameters + swid = 0 + cmd = SX_ACCESS_CMD_REGISTER + uc_p = new_sx_user_channel_t_p() + uc_p.type = SX_USER_CHANNEL_TYPE_FD + uc_p.channel.fd = rx_fd_p + trap_id = SX_TRAP_ID_PMPE + + rc = sx_api_host_ifc_trap_id_register_set(handle, cmd, swid, trap_id, uc_p) + if rc != 0: + log_error("sx_api_host_ifc_trap_id_register_set exit with error, rc %d" % rc) + exit(rc) + + liveness_info_update = sfpd_liveness_update_task(state_db) + liveness_info_update.task_run() + + # Main loop for sfp event listening + log_info("mlnx-sfpd started") + while True: + sfp_state = STATUS_UNKNOWN + rc, port_list, module_state = sx_recv(rx_fd_p, handle) + if not rc: + log_error("Failed to recv event from SDK, please check that SDK is running.") + break + + if module_state in sfp_value_status_dict: sfp_state = sfp_value_status_dict[module_state] + + if sfp_state != STATUS_UNKNOWN: + for port in port_list: + log_info("SFP on port %d state %s" % (port, sfp_state)) + send_sfp_notification(state_db, str(port), sfp_state) + + log_info("sfp change event handling done") + + # Stop liveness update task + liveness_info_update.task_stop() + + # Remove mlnx-sfpd liveness key in DB if not expired yet. + if state_db.exists('STATE_DB', 'MLNX_SFPD_TASK|LIVENESS'): + state_db.delete(state_db, 'MLNX_SFPD_TASK|LIVENESS') + + # unregister trap id + cmd = SX_ACCESS_CMD_DEREGISTER + rc = sx_api_host_ifc_trap_id_register_set(handle, cmd, swid, trap_id, uc_p) + if rc != 0: + log_error("sx_api_host_ifc_trap_id_register_set exit with error, rc %d" % rc) + exit(rc) + + # Close read fp + rc = sx_api_host_ifc_close(handle, rx_fd_p) + if rc != 0: + log_error("sx_api_host_ifc_close exit with error, rc %d" % rc) + exit(rc) + + # Close sdk handler + rc = sx_api_close(handle) + if rc != 0: + log_error("sx_api_close exit with error, rc %d" % rc) + exit(rc) + + log_info("mlnx-sfpd exited") + + +if __name__ == '__main__': + main() diff --git a/platform/mellanox/mlnx-sfpd/setup.py b/platform/mellanox/mlnx-sfpd/setup.py new file mode 100644 index 000000000000..ea9b895cb1f4 --- /dev/null +++ b/platform/mellanox/mlnx-sfpd/setup.py @@ -0,0 +1,28 @@ +from setuptools import setup + +setup( + name='mlnx-sfpd', + version='1.0', + description='SFP event mmonitoring daemon for SONiC on mellanox platform', + license='Apache 2.0', + author='SONiC Community', + url='https://github.com/Azure/sonic-buildimage/', + maintainer='Kebo Liu', + maintainer_email='kebol@mellanox.com', + scripts=[ + 'scripts/mlnx-sfpd', + ], + classifiers=[ + 'Development Status :: 4 - Beta', + 'Environment :: No Input/Output (Daemon)', + 'Intended Audience :: Developers', + 'Intended Audience :: Information Technology', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: Apache Software License', + 'Natural Language :: English', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: Python :: 2.7', + 'Topic :: System :: Hardware', + ], + keywords='sonic SONiC SFP sfp MELLANOX mellanox daemon SFPD sfpd', +) diff --git a/platform/mellanox/one-image.mk b/platform/mellanox/one-image.mk new file mode 100644 index 000000000000..3a99f1c66c80 --- /dev/null +++ b/platform/mellanox/one-image.mk @@ -0,0 +1,9 @@ +# sonic mellanox one image installer + +SONIC_ONE_IMAGE = sonic-mellanox.bin +$(SONIC_ONE_IMAGE)_MACHINE = mellanox +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(SX_KERNEL) $(KERNEL_MFT) $(MFT_OEM) $(MFT) $(MLNX_HW_MANAGEMENT) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +$(SONIC_ONE_IMAGE)_FILES += $(MLNX_FW_FILE) $(MLNX_FFB_SCRIPT) +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/mellanox/platform.conf b/platform/mellanox/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/mellanox/rules.mk b/platform/mellanox/rules.mk new file mode 100644 index 000000000000..28414b7f9d9f --- /dev/null +++ b/platform/mellanox/rules.mk @@ -0,0 +1,24 @@ +include $(PLATFORM_PATH)/sdk.mk +include $(PLATFORM_PATH)/fw.mk +include $(PLATFORM_PATH)/mft.mk +include $(PLATFORM_PATH)/mlnx-sai.mk +include $(PLATFORM_PATH)/hw-management.mk +include $(PLATFORM_PATH)/docker-syncd-mlnx.mk +include $(PLATFORM_PATH)/docker-syncd-mlnx-rpc.mk +include $(PLATFORM_PATH)/docker-orchagent-mlnx.mk +include $(PLATFORM_PATH)/docker-saiserver-mlnx.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/docker-ptf-mlnx.mk +include $(PLATFORM_PATH)/mlnx-sfpd.mk +include $(PLATFORM_PATH)/mlnx-ffb.mk +include $(PLATFORM_PATH)/mlnx-issu.mk + +SONIC_ALL += $(SONIC_ONE_IMAGE) \ + $(DOCKER_FPM) + +# Inject mlnx sai into sairedis +$(LIBSAIREDIS)_DEPENDS += $(MLNX_SAI) $(LIBSAITHRIFT_DEV) + +# Runtime dependency on mlnx sai is set only for syncd +$(SYNCD)_RDEPENDS += $(MLNX_SAI) diff --git a/platform/mellanox/sdk-version.j2 b/platform/mellanox/sdk-version.j2 new file mode 100755 index 000000000000..5bba188430d6 --- /dev/null +++ b/platform/mellanox/sdk-version.j2 @@ -0,0 +1 @@ +{{ MLNX_SDK_VERSION }} \ No newline at end of file diff --git a/platform/mellanox/sdk.mk b/platform/mellanox/sdk.mk new file mode 100644 index 000000000000..42587249cb61 --- /dev/null +++ b/platform/mellanox/sdk.mk @@ -0,0 +1,59 @@ +MLNX_SDK_BASE_URL = https://github.com/Mellanox/SAI-Implementation/raw/673e8fbb10d5cba194daf237ffdc5edd974fc1b0/sdk +MLNX_SDK_VERSION = 4.2.9108 +MLNX_SDK_RDEBS += $(APPLIBS) $(IPROUTE2_MLNX) $(SX_ACL_RM) $(SX_COMPLIB) \ + $(SX_EXAMPLES) $(SX_GEN_UTILS) $(SX_SCEW) $(SX_SDN_HAL) \ + $(SXD_LIBS) $(TESTX) + +MLNX_SDK_DEBS += $(APPLIBS_DEV) $(IPROUTE2_MLNX_DEV) $(SX_ACL_RM_DEV) \ + $(SX_COMPLIB_DEV) $(SX_COMPLIB_DEV_STATIC) $(SX_EXAMPLES_DEV) \ + $(SX_GEN_UTILS_DEV) $(SX_SCEW_DEV) $(SX_SCEW_DEV_STATIC) \ + $(SX_SDN_HAL_DEV) $(SX_SDN_HAL_DEV_STATIC) $(SXD_LIBS_DEV) \ + $(SXD_LIBS_DEV_STATIC) $(TESTX_DEV) + +APPLIBS = applibs_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +$(APPLIBS)_DEPENDS += $(SX_COMPLIB) $(SX_GEN_UTILS) $(SXD_LIBS) $(LIBNL3) $(LIBNL_GENL3) +$(APPLIBS)_RDEPENDS += $(SX_COMPLIB) $(SX_GEN_UTILS) $(SXD_LIBS) $(LIBNL3) $(LIBNL_GENL3) +APPLIBS_DEV = applibs-dev_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(APPLIBS),$(APPLIBS_DEV))) +IPROUTE2_MLNX = iproute2_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +IPROUTE2_MLNX_DEV = iproute2-dev_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(IPROUTE2_MLNX),$(IPROUTE2_MLNX_DEV))) +SX_COMPLIB = sx-complib_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +SX_COMPLIB_DEV = sx-complib-dev_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(SX_COMPLIB),$(SX_COMPLIB_DEV))) +SX_EXAMPLES = sx-examples_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +$(SX_EXAMPLES)_DEPENDS += $(APPLIBS) $(SX_SCEW) $(SXD_LIBS) +$(SX_EXAMPLES)_RDEPENDS += $(APPLIBS) $(SX_SCEW) $(SXD_LIBS) +SX_EXAMPLES_DEV = sx-examples-dev_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(SX_EXAMPLES),$(SX_EXAMPLES_DEV))) +SX_GEN_UTILS = sx-gen-utils_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +$(SX_GEN_UTILS)_DEPENDS += $(SX_COMPLIB) +$(SX_GEN_UTILS)_RDEPENDS += $(SX_COMPLIB) +SX_GEN_UTILS_DEV = sx-gen-utils-dev_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(SX_GEN_UTILS),$(SX_GEN_UTILS_DEV))) +SX_SCEW = sx-scew_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +SX_SCEW_DEV = sx-scew-dev_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(SX_SCEW),$(SX_SCEW_DEV))) +SXD_LIBS = sxd-libs_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +SXD_LIBS_DEV = sxd-libs-dev_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(SXD_LIBS),$(SXD_LIBS_DEV))) +#packages that are required for runtime only +PYTHON_SDK_API = python-sdk-api_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +$(PYTHON_SDK_API)_DEPENDS += $(APPLIBS) $(SXD_LIBS) +$(PYTHON_SDK_API)_RDEPENDS += $(APPLIBS) $(SXD_LIBS) +SX_KERNEL = sx-kernel_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +SX_KERNEL_DEV = sx-kernel-dev_1.mlnx.$(MLNX_SDK_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(SX_KERNEL),$(SX_KERNEL_DEV))) + +define make_url + $(1)_URL = $(MLNX_SDK_BASE_URL)/$(1) + +endef + +$(eval $(foreach deb,$(MLNX_SDK_DEBS),$(call make_url,$(deb)))) +$(eval $(foreach deb,$(MLNX_SDK_RDEBS),$(call make_url,$(deb)))) +$(eval $(foreach deb,$(PYTHON_SDK_API) $(SX_KERNEL) $(SX_KERNEL_DEV),$(call make_url,$(deb)))) + +SONIC_ONLINE_DEBS += $(MLNX_SDK_RDEBS) $(PYTHON_SDK_API) $(SX_KERNEL) + +export MLNX_SDK_VERSION diff --git a/platform/nephos/docker-orchagent-nephos.mk b/platform/nephos/docker-orchagent-nephos.mk new file mode 100644 index 000000000000..f7719b3df5dd --- /dev/null +++ b/platform/nephos/docker-orchagent-nephos.mk @@ -0,0 +1,24 @@ +# docker image for orchagent + +DOCKER_ORCHAGENT_NEPHOS = docker-orchagent-nephos.gz +$(DOCKER_ORCHAGENT_NEPHOS)_PATH = $(DOCKERS_PATH)/docker-orchagent +$(DOCKER_ORCHAGENT_NEPHOS)_DEPENDS += $(SWSS) $(REDIS_TOOLS) $(IPROUTE2) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_ORCHAGENT_NEPHOS)_DEPENDS += $(SWSS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_ORCHAGENT_NEPHOS)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_NEPHOS) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_NEPHOS) + +$(DOCKER_ORCHAGENT_NEPHOS)_CONTAINER_NAME = swss +$(DOCKER_ORCHAGENT_NEPHOS)_RUN_OPT += --net=host --privileged -t +$(DOCKER_ORCHAGENT_NEPHOS)_RUN_OPT += -v /etc/network/interfaces:/etc/network/interfaces:ro +$(DOCKER_ORCHAGENT_NEPHOS)_RUN_OPT += -v /etc/network/interfaces.d/:/etc/network/interfaces.d/:ro +$(DOCKER_ORCHAGENT_NEPHOS)_RUN_OPT += -v /host/machine.conf:/host/machine.conf:ro +$(DOCKER_ORCHAGENT_NEPHOS)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_ORCHAGENT_NEPHOS)_RUN_OPT += -v /var/log/swss:/var/log/swss:rw + +$(DOCKER_ORCHAGENT_NEPHOS)_BASE_IMAGE_FILES += swssloglevel:/usr/bin/swssloglevel +$(DOCKER_ORCHAGENT_NEPHOS)_FILES += $(ARP_UPDATE_SCRIPT) diff --git a/platform/nephos/docker-ptf-nephos.mk b/platform/nephos/docker-ptf-nephos.mk new file mode 100644 index 000000000000..7fbbd271cf65 --- /dev/null +++ b/platform/nephos/docker-ptf-nephos.mk @@ -0,0 +1,7 @@ +# docker image for docker-ptf-nephos + +DOCKER_PTF_NEPHOS = docker-ptf-nephos.gz +$(DOCKER_PTF_NEPHOS)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift +$(DOCKER_PTF_NEPHOS)_DEPENDS += $(PYTHON_SAITHRIFT_NEPHOS) +$(DOCKER_PTF_NEPHOS)_LOAD_DOCKERS += $(DOCKER_PTF) +SONIC_DOCKER_IMAGES += $(DOCKER_PTF_NEPHOS) diff --git a/platform/nephos/docker-syncd-nephos-rpc.mk b/platform/nephos/docker-syncd-nephos-rpc.mk new file mode 100644 index 000000000000..e891d0b1a68d --- /dev/null +++ b/platform/nephos/docker-syncd-nephos-rpc.mk @@ -0,0 +1,17 @@ +# docker image for nephos syncd with rpc + +DOCKER_SYNCD_NEPHOS_RPC = docker-syncd-nephos-rpc.gz +$(DOCKER_SYNCD_NEPHOS_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-nephos-rpc +$(DOCKER_SYNCD_NEPHOS_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) +$(DOCKER_SYNCD_NEPHOS_RPC)_FILES += $(DSSERVE) $(NPX_DIAG) +$(DOCKER_SYNCD_NEPHOS_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_NEPHOS) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_NEPHOS_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_NEPHOS_RPC) +endif + +$(DOCKER_SYNCD_NEPHOS_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_NEPHOS_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_NEPHOS_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_NEPHOS_RPC)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd +$(DOCKER_SYNCD_NEPHOS_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/nephos/docker-syncd-nephos-rpc/Dockerfile.j2 b/platform/nephos/docker-syncd-nephos-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..9a01d4e1e001 --- /dev/null +++ b/platform/nephos/docker-syncd-nephos-rpc/Dockerfile.j2 @@ -0,0 +1,51 @@ +FROM docker-syncd-nephos + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_nephos_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -P syncd + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_nephos_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + && wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/nephos/docker-syncd-nephos-rpc/ptf_nn_agent.conf b/platform/nephos/docker-syncd-nephos-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/nephos/docker-syncd-nephos-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/nephos/docker-syncd-nephos.mk b/platform/nephos/docker-syncd-nephos.mk new file mode 100644 index 000000000000..a79c8524b890 --- /dev/null +++ b/platform/nephos/docker-syncd-nephos.mk @@ -0,0 +1,19 @@ +# docker image for nephos syncd + +DOCKER_SYNCD_NEPHOS = docker-syncd-nephos.gz +$(DOCKER_SYNCD_NEPHOS)_PATH = $(PLATFORM_PATH)/docker-syncd-nephos +$(DOCKER_SYNCD_NEPHOS)_DEPENDS += $(SYNCD) +$(DOCKER_SYNCD_NEPHOS)_FILES += $(DSSERVE) $(NPX_DIAG) +$(DOCKER_SYNCD_NEPHOS)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_NEPHOS) +ifneq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_NEPHOS) +endif + +$(DOCKER_SYNCD_NEPHOS)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_NEPHOS)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_NEPHOS)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_NEPHOS)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd +$(DOCKER_SYNCD_NEPHOS)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + +$(DOCKER_SYNCD_NEPHOS)_BASE_IMAGE_FILES += npx_diag:/usr/bin/npx_diag diff --git a/platform/nephos/docker-syncd-nephos/Dockerfile.j2 b/platform/nephos/docker-syncd-nephos/Dockerfile.j2 new file mode 100755 index 000000000000..1553e2786cf8 --- /dev/null +++ b/platform/nephos/docker-syncd-nephos/Dockerfile.j2 @@ -0,0 +1,34 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_syncd_nephos_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_syncd_nephos_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +## TODO: add kmod into Depends +RUN apt-get install -f kmod + +COPY ["files/dsserve", "files/npx_diag", "start.sh", "/usr/bin/"] +RUN chmod +x /usr/bin/dsserve /usr/bin/npx_diag + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/nephos/docker-syncd-nephos/base_image_files/npx_diag b/platform/nephos/docker-syncd-nephos/base_image_files/npx_diag new file mode 100755 index 000000000000..876bc1816ecc --- /dev/null +++ b/platform/nephos/docker-syncd-nephos/base_image_files/npx_diag @@ -0,0 +1,3 @@ +#!/bin/bash + +docker exec -i syncd npx_diag "$@" diff --git a/platform/nephos/docker-syncd-nephos/start.sh b/platform/nephos/docker-syncd-nephos/start.sh new file mode 100755 index 000000000000..623316050475 --- /dev/null +++ b/platform/nephos/docker-syncd-nephos/start.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start syncd diff --git a/platform/nephos/docker-syncd-nephos/supervisord.conf b/platform/nephos/docker-syncd-nephos/supervisord.conf new file mode 100644 index 000000000000..1af5d70a1d0c --- /dev/null +++ b/platform/nephos/docker-syncd-nephos/supervisord.conf @@ -0,0 +1,28 @@ +[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:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/nephos/libsaithrift-dev.mk b/platform/nephos/libsaithrift-dev.mk new file mode 100644 index 000000000000..e3828eeb0f2b --- /dev/null +++ b/platform/nephos/libsaithrift-dev.mk @@ -0,0 +1,7 @@ +# libsaithrift-dev package + +LIBSAITHRIFT_DEV_NEPHOS = libsaithrift-dev_1.3.5_amd64.deb +$(LIBSAITHRIFT_DEV_NEPHOS)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV_NEPHOS)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(THRIFT_COMPILER) $(NEPHOS_SAI) $(NEPHOS_SAI_DEV) +$(LIBSAITHRIFT_DEV_NEPHOS)_RDEPENDS += $(LIBTHRIFT) $(NEPHOS_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV_NEPHOS) diff --git a/platform/nephos/one-image.mk b/platform/nephos/one-image.mk new file mode 100644 index 000000000000..ace042d5ce4f --- /dev/null +++ b/platform/nephos/one-image.mk @@ -0,0 +1,11 @@ +# sonic nephos one image installer + +SONIC_ONE_IMAGE = sonic-nephos.bin +$(SONIC_ONE_IMAGE)_MACHINE = nephos +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(NEPHOS_NPS_KERNEL) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(INGRASYS_S9130_32X_PLATFORM_MODULE) \ + $(INGRASYS_S9230_64X_PLATFORM_MODULE) \ + $(ACCTON_AS7116_54X_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/nephos/platform-modules-accton.mk b/platform/nephos/platform-modules-accton.mk new file mode 100644 index 000000000000..1d4788bc9a27 --- /dev/null +++ b/platform/nephos/platform-modules-accton.mk @@ -0,0 +1,13 @@ +# Accton AS7116 54X Platform modules + +ACCTON_AS7116_54X_PLATFORM_MODULE_VERSION = 1.0.0 + +export ACCTON_AS7116_54X_PLATFORM_MODULE_VERSION + +ACCTON_AS7116_54X_PLATFORM_MODULE = sonic-platform-accton-as7116-54x_$(ACCTON_AS7116_54X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7116_54X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton +$(ACCTON_AS7116_54X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(ACCTON_AS7116_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7116_54x-r0 +SONIC_DPKG_DEBS += $(ACCTON_AS7116_54X_PLATFORM_MODULE) + +SONIC_STRETCH_DEBS += $(ACCTON_AS7116_54X_PLATFORM_MODULE) diff --git a/platform/nephos/platform-modules-ingrasys.mk b/platform/nephos/platform-modules-ingrasys.mk new file mode 100644 index 000000000000..94b8315cd70c --- /dev/null +++ b/platform/nephos/platform-modules-ingrasys.mk @@ -0,0 +1,21 @@ +# Ingrasys S9130-32X and S9230-64X Platform modules + +INGRASYS_S9130_32X_PLATFORM_MODULE_VERSION = 1.0.0 +INGRASYS_S9230_64X_PLATFORM_MODULE_VERSION = 1.0.0 + +export INGRASYS_S9130_32X_PLATFORM_MODULE_VERSION +export INGRASYS_S9230_64X_PLATFORM_MODULE_VERSION + +INGRASYS_S9130_32X_PLATFORM_MODULE = sonic-platform-ingrasys-s9130-32x_$(INGRASYS_S9130_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S9130_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-ingrasys +$(INGRASYS_S9130_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(INGRASYS_S9130_32X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9130_32x-r0 +SONIC_DPKG_DEBS += $(INGRASYS_S9130_32X_PLATFORM_MODULE) + +INGRASYS_S9230_64X_PLATFORM_MODULE = sonic-platform-ingrasys-s9230-64x_$(INGRASYS_S9230_64X_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S9230_64X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9230_64x-r0 + +$(eval $(call add_extra_package,$(INGRASYS_S9130_32X_PLATFORM_MODULE),$(INGRASYS_S9230_64X_PLATFORM_MODULE))) + +SONIC_STRETCH_DEBS += $(INGRASYS_S9130_32X_PLATFORM_MODULE) +SONIC_STRETCH_DEBS += $(INGRASYS_S9230_64X_PLATFORM_MODULE) diff --git a/platform/nephos/platform-modules-pegatron.mk b/platform/nephos/platform-modules-pegatron.mk new file mode 100755 index 000000000000..9a411763cec2 --- /dev/null +++ b/platform/nephos/platform-modules-pegatron.mk @@ -0,0 +1,13 @@ +# Pegatron Platform modules + +PEGATRON_PORSCHE_PLATFORM_MODULE_VERSION = 0.1 + +export PEGATRON_PORSCHE_PLATFORM_MODULE_VERSION + +PEGATRON_PORSCHE_PLATFORM_MODULE = sonic-platform-pegatron-porsche_$(PEGATRON_PORSCHE_PLATFORM_MODULE_VERSION)_amd64.deb +$(PEGATRON_PORSCHE_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-pegatron +$(PEGATRON_PORSCHE_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(PEGATRON_PORSCHE_PLATFORM_MODULE)_PLATFORM = x86_64-pegatron_porsche-r0 +SONIC_DPKG_DEBS += $(PEGATRON_PORSCHE_PLATFORM_MODULE) + +$(eval $(call add_extra_package,$(PEGATRON_PORSCHE_PLATFORM_MODULE))) diff --git a/platform/nephos/platform.conf b/platform/nephos/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/python-saithrift.mk b/platform/nephos/python-saithrift.mk new file mode 100644 index 000000000000..9305b0628a96 --- /dev/null +++ b/platform/nephos/python-saithrift.mk @@ -0,0 +1,6 @@ +# python-saithrift package + +PYTHON_SAITHRIFT_NEPHOS = python-saithrift_1.3.5_amd64.deb +$(PYTHON_SAITHRIFT_NEPHOS)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(PYTHON_SAITHRIFT_NEPHOS)_DEPENDS += $(NEPHOS_SAI_DEV) $(THRIFT_COMPILER) $(PYTHON_THRIFT) $(LIBTHRIFT_DEV) +SONIC_DPKG_DEBS += $(PYTHON_SAITHRIFT_NEPHOS) diff --git a/platform/nephos/rules.mk b/platform/nephos/rules.mk new file mode 100644 index 000000000000..bf77ad0e6edf --- /dev/null +++ b/platform/nephos/rules.mk @@ -0,0 +1,27 @@ +include $(PLATFORM_PATH)/sdk.mk +include $(PLATFORM_PATH)/sai.mk +include $(PLATFORM_PATH)/platform-modules-ingrasys.mk +include $(PLATFORM_PATH)/platform-modules-accton.mk +include $(PLATFORM_PATH)/docker-orchagent-nephos.mk +include $(PLATFORM_PATH)/docker-syncd-nephos.mk +include $(PLATFORM_PATH)/docker-syncd-nephos-rpc.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/python-saithrift.mk +include $(PLATFORM_PATH)/docker-ptf-nephos.mk + +NPX_DIAG = npx_diag +$(NPX_DIAG)_URL = "https://github.com/NephosInc/SONiC/raw/master/sdk/npx_diag" + +DSSERVE = dsserve +$(DSSERVE)_URL = "https://sonicstorage.blob.core.windows.net/packages/20170518/dsserve?sv=2015-04-05&sr=b&sig=gyNbgSL%2FvpMXDdpboVkIJcTKMRdGgEaOR9OukHhEsu8%3D&se=2030-03-31T23%3A06%3A35Z&sp=r" + +SONIC_ONLINE_FILES += $(NPX_DIAG) $(DSSERVE) + +SONIC_ALL += $(SONIC_ONE_IMAGE) $(DOCKER_FPM) + +# Inject nephos sai into sairedis +$(LIBSAIREDIS)_DEPENDS += $(NEPHOS_SAI) $(NEPHOS_SAI_DEV) $(LIBSAITHRIFT_DEV_NEPHOS) + +# Runtime dependency on nephos sai is set only for syncd +$(SYNCD)_RDEPENDS += $(NEPHOS_SAI) diff --git a/platform/nephos/sai.mk b/platform/nephos/sai.mk new file mode 100644 index 000000000000..4bfa27999259 --- /dev/null +++ b/platform/nephos/sai.mk @@ -0,0 +1,12 @@ +SDK_VERSION = 2.0.5 +SAI_VERSION = 1.3.5 +SAI_COMMIT_ID = 575f90 +NEPHOS_SAI = libsainps_$(SDK_VERSION)_sai_$(SAI_VERSION)_$(SAI_COMMIT_ID)_amd64.deb +$(NEPHOS_SAI)_URL = "https://github.com/NephosInc/SONiC/raw/master/sai/libsainps_$(SDK_VERSION)_sai_$(SAI_VERSION)_$(SAI_COMMIT_ID)_amd64.deb" + +NEPHOS_SAI_DEV = libsainps-dev_$(SDK_VERSION)_sai_$(SAI_VERSION)_$(SAI_COMMIT_ID)_amd64.deb +$(eval $(call add_derived_package,$(NEPHOS_SAI),$(NEPHOS_SAI_DEV))) +$(NEPHOS_SAI_DEV)_URL = "https://github.com/NephosInc/SONiC/raw/master/sai/libsainps-dev_$(SDK_VERSION)_sai_$(SAI_VERSION)_$(SAI_COMMIT_ID)_amd64.deb" + +SONIC_ONLINE_DEBS += $(NEPHOS_SAI) $(NEPHOS_SAI_DEV) +$(NEPHOS_SAI_DEV)_DEPENDS += $(NEPHOS_SAI) diff --git a/platform/nephos/sdk.mk b/platform/nephos/sdk.mk new file mode 100644 index 000000000000..037094041c76 --- /dev/null +++ b/platform/nephos/sdk.mk @@ -0,0 +1,7 @@ +SDK_VERSION = 2.0.5 +LINUX_VER = 4.9.0-7 +SDK_COMMIT_ID = f2e56f +NEPHOS_NPS_KERNEL = nps-modules-$(LINUX_VER)_$(SDK_VERSION)_$(SDK_COMMIT_ID)_amd64.deb +$(NEPHOS_NPS_KERNEL)_URL = "https://github.com/NephosInc/SONiC/raw/master/sdk/nps-modules-$(LINUX_VER)_$(SDK_VERSION)_$(SDK_COMMIT_ID)_amd64.deb" + +SONIC_ONLINE_DEBS += $(NEPHOS_NPS_KERNEL) diff --git a/platform/nephos/sonic-platform-modules-accton/LICENSE b/platform/nephos/sonic-platform-modules-accton/LICENSE new file mode 100644 index 000000000000..bc693f7a4c40 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2017 Accton Technology Corporation + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/nephos/sonic-platform-modules-accton/README.md b/platform/nephos/sonic-platform-modules-accton/README.md new file mode 100644 index 000000000000..0ff20bb2d21b --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/README.md @@ -0,0 +1 @@ +platform drivers of Accton products for the SONiC project diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/__init__.py b/platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/fanutil.py b/platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/fanutil.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/thermalutil.py b/platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/thermalutil.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/Makefile b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/Makefile new file mode 100644 index 000000000000..19c7029f14a2 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := x86-64-accton-as7116-54x-cpld.o x86-64-accton-as7116-54x-fan.o \ + x86-64-accton-as7116-54x-led.o x86-64-accton-as7116-54x-psu.o x86-64-accton-as7116-54x-sfp.o diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-cpld.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-cpld.c new file mode 100644 index 000000000000..eb52512343a8 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-cpld.c @@ -0,0 +1,242 @@ +/* + * A hwmon driver for the as7116_54x_cpld + * + * Copyright (C) 2017 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for as7116_54x_cpld + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static ssize_t show_cpld_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +static struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, NULL); + +static void as7116_54x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as7116_54x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int as7116_54x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + status = sysfs_create_file(&client->dev.kobj, &ver.attr); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + as7116_54x_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int as7116_54x_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_file(&client->dev.kobj, &ver.attr); + as7116_54x_cpld_remove_client(client); + + return 0; +} + +enum cpld_chips +{ + as7116_54x_cpld1, + as7116_54x_cpld2, + as7116_54x_cpld3 +}; + +static const struct i2c_device_id as7116_54x_cpld_id[] = { + { "as7116_54x_cpld1", as7116_54x_cpld1 }, + { "as7116_54x_cpld2", as7116_54x_cpld2 }, + { "as7116_54x_cpld3", as7116_54x_cpld3 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7116_54x_cpld_id); + +static struct i2c_driver as7116_54x_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7116_54x_cpld", + }, + .probe = as7116_54x_cpld_probe, + .remove = as7116_54x_cpld_remove, + .id_table = as7116_54x_cpld_id, + .address_list = normal_i2c, +}; + +int as7116_54x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7116_54x_cpld_read); + +int as7116_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7116_54x_cpld_write); + +static int __init as7116_54x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7116_54x_cpld_driver); +} + +static void __exit as7116_54x_cpld_exit(void) +{ + i2c_del_driver(&as7116_54x_cpld_driver); +} + +static struct dmi_system_id as7116_54x_dmi_table[] = { + { + .ident = "Accton AS7716", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS7116"), + }, + } +}; + +int platform_accton_as7116_54x(void) +{ + //return dmi_check_system(as7116_54x_dmi_table); + return 1; +} +EXPORT_SYMBOL(platform_accton_as7116_54x); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7116_54x driver"); +MODULE_LICENSE("GPL"); + +module_init(as7116_54x_cpld_init); +module_exit(as7116_54x_cpld_exit); + diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-fan.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-fan.c new file mode 100644 index 000000000000..f5159c8f166e --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-fan.c @@ -0,0 +1,544 @@ +/* + * A hwmon driver for the Accton as7716 32x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7116_54x_fan" + +static struct as7116_54x_fan_data *as7116_54x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x02, /* fan 1-6 present status */ + 0x03, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x06, /* fan PWM(for all fan) */ + 0x04, /* front fan fault */ + 0x05, /* rear fan fault */ + 0x07, /* front fan 1 speed(rpm) */ + 0x08, /* front fan 2 speed(rpm) */ + 0x09, /* front fan 3 speed(rpm) */ + 0x0A, /* front fan 4 speed(rpm) */ + 0x0B, /* front fan 5 speed(rpm) */ + 0x0C, /* rear fan 1 speed(rpm) */ + 0x0D, /* rear fan 2 speed(rpm) */ + 0x0E, /* rear fan 3 speed(rpm) */ + 0x0f, /* rear fan 4 speed(rpm) */ + 0x10, /* rear fan 5 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7116_54x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN_FRONT_FAULT_REG, + FAN_REAR_FAULT_REG, + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN1_FRONT_FAULT, + FAN2_FRONT_FAULT, + FAN3_FRONT_FAULT, + FAN4_FRONT_FAULT, + FAN5_FRONT_FAULT, + FAN1_REAR_FAULT, + FAN2_REAR_FAULT, + FAN3_REAR_FAULT, + FAN4_REAR_FAULT, + FAN5_REAR_FAULT, + FAN1_INPUT, /* FAN1_FRONT_SPEED_RPM, */ + FAN2_INPUT, /* FAN2_FRONT_SPEED_RPM, */ + FAN3_INPUT, /* FAN3_FRONT_SPEED_RPM, */ + FAN4_INPUT, /* FAN4_FRONT_SPEED_RPM, */ + FAN5_INPUT, /* FAN5_FRONT_SPEED_RPM, */ + FAN6_INPUT, /* FAN1_REAR_SPEED_RPM, */ + FAN7_INPUT, /* FAN2_REAR_SPEED_RPM, */ + FAN8_INPUT, /* FAN3_REAR_SPEED_RPM, */ + FAN9_INPUT, /* FAN4_REAR_SPEED_RPM, */ + FAN10_INPUT, /* FAN5_REAR_SPEED_RPM */ +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_front_fault.dev_attr.attr,\ + &sensor_dev_attr_fan##index##_rear_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr + +#define DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_INPUT) +#define DECLARE_FAN_INPUT_ATTR(index) &sensor_dev_attr_fan##index##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); + +/* fan input attributes in this platform */ +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(5); + +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(6); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(7); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(8); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(9); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(10); + +static struct attribute *as7116_54x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1), + DECLARE_FAN_FAULT_ATTR(2), + DECLARE_FAN_FAULT_ATTR(3), + DECLARE_FAN_FAULT_ATTR(4), + DECLARE_FAN_FAULT_ATTR(5), + DECLARE_FAN_SPEED_RPM_ATTR(1), + DECLARE_FAN_SPEED_RPM_ATTR(2), + DECLARE_FAN_SPEED_RPM_ATTR(3), + DECLARE_FAN_SPEED_RPM_ATTR(4), + DECLARE_FAN_SPEED_RPM_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + DECLARE_FAN_INPUT_ATTR(1), + DECLARE_FAN_INPUT_ATTR(2), + DECLARE_FAN_INPUT_ATTR(3), + DECLARE_FAN_INPUT_ATTR(4), + DECLARE_FAN_INPUT_ATTR(5), + DECLARE_FAN_INPUT_ATTR(6), + DECLARE_FAN_INPUT_ATTR(7), + DECLARE_FAN_INPUT_ATTR(8), + DECLARE_FAN_INPUT_ATTR(9), + DECLARE_FAN_INPUT_ATTR(10), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0x1F +#define FAN_MIN_DUTY_CYCLE 20 +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 150 + +static int as7116_54x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7116_54x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + return (reg_val & FAN_DUTY_CYCLE_REG_MASK) * 5; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return (duty_cycle / 5); +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + return !!(reg_val & (1 << id)); +} + +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + return !(reg_val & (1 << id)); +} + +static u8 is_fan_fault(u8 reg_val, enum fan_id id) +{ + return !!(reg_val & (1 << id)); +} +#if 0 +static u8 is_fan_fault(struct as7116_54x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} +#endif + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < FAN_MIN_DUTY_CYCLE) { + value = FAN_MIN_DUTY_CYCLE; + } + + if (value > FAN_MAX_DUTY_CYCLE) { + value = FAN_MAX_DUTY_CYCLE; + } + + as7116_54x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7116_54x_fan_data *data = as7116_54x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FRONT_FAULT: + case FAN2_FRONT_FAULT: + case FAN3_FRONT_FAULT: + case FAN4_FRONT_FAULT: + case FAN5_FRONT_FAULT: + ret = sprintf(buf, "%d\n", + is_fan_fault(data->reg_val[FAN_FRONT_FAULT_REG], + attr->index - FAN1_FRONT_FAULT)); + break; + case FAN1_REAR_FAULT: + case FAN2_REAR_FAULT: + case FAN3_REAR_FAULT: + case FAN4_REAR_FAULT: + case FAN5_REAR_FAULT: + ret = sprintf(buf, "%d\n", + is_fan_fault(data->reg_val[FAN_REAR_FAULT_REG], + attr->index - FAN1_REAR_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + case FAN1_INPUT: + case FAN2_INPUT: + case FAN3_INPUT: + case FAN4_INPUT: + case FAN5_INPUT: + case FAN6_INPUT: + case FAN7_INPUT: + case FAN8_INPUT: + case FAN9_INPUT: + case FAN10_INPUT: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index + - FAN1_INPUT + FAN1_FRONT_SPEED_RPM])); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7116_54x_fan_group = { + .attrs = as7116_54x_fan_attributes, +}; + +static struct as7116_54x_fan_data *as7116_54x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7116_54x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7116_54x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7116_54x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7116_54x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7116_54x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7116_54x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7116_54x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7116_54x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7116_54x_fan_remove(struct i2c_client *client) +{ + struct as7116_54x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7116_54x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7116_54x_fan_id[] = { + { "as7116_54x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7116_54x_fan_id); + +static struct i2c_driver as7116_54x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7116_54x_fan_probe, + .remove = as7116_54x_fan_remove, + .id_table = as7116_54x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7116_54x_fan_init(void) +{ +#if 0 + extern int platform_accton_as7116_54x(void); + if (!platform_accton_as7116_54x()) { + return -ENODEV; + } +#endif + return i2c_add_driver(&as7116_54x_fan_driver); +} + +static void __exit as7116_54x_fan_exit(void) +{ + i2c_del_driver(&as7116_54x_fan_driver); +} + +module_init(as7116_54x_fan_init); +module_exit(as7116_54x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7116_54x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-led.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-led.c new file mode 100644 index 000000000000..cd69f711c826 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-led.c @@ -0,0 +1,448 @@ +/* + * A LED driver for the accton_as7116_54x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7116_54x_fan" + +#define DEBUG_MODE 0 +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +extern int as7116_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as7116_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +struct as7116_54x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* LOC/DIAG LED */ +}; + +static struct as7116_54x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x0C) +#define LED_MODE_DIAG_GREEN_VALUE (0x08) +#define LED_MODE_DIAG_AMBER_VALUE (0x04) +#define LED_MODE_DIAG_YELLOW_VALUE (0x00) +#define LED_MODE_DIAG_OFF_VALUE (0x0C) + +#define LED_TYPE_FAN_REG_MASK (0x03) +#define LED_MODE_FAN_GREEN_VALUE (0x02) +#define LED_MODE_FAN_AMBER_VALUE (0x01) +#define LED_MODE_FAN_OFF_VALUE (0x03) +#define LED_MODE_FAN_AUTO_VALUE (0x00) + +#define LED_TYPE_PSU1_REG_MASK (0x03) +#define LED_MODE_PSU1_GREEN_VALUE (0x02) +#define LED_MODE_PSU1_AMBER_VALUE (0x01) +#define LED_MODE_PSU1_OFF_VALUE (0x03) +#define LED_MODE_PSU1_AUTO_VALUE (0x00) + +#define LED_TYPE_PSU2_REG_MASK (0x0C) +#define LED_MODE_PSU2_GREEN_VALUE (0x08) +#define LED_MODE_PSU2_AMBER_VALUE (0x04) +#define LED_MODE_PSU2_OFF_VALUE (0x0C) +#define LED_MODE_PSU2_AUTO_VALUE (0x00) + +#define LED_TYPE_LOC_REG_MASK (0x30) +#define LED_MODE_LOC_AMBER_VALUE (0x00) +#define LED_MODE_LOC_AMBER_BLINKING_VALUE1 (0x20) +#define LED_MODE_LOC_AMBER_BLINKING_VALUE2 (0x30) +#define LED_MODE_LOC_OFF_VALUE (0x10) + +static const u8 led_reg[] = { + 0x0A, /* LOC/DIAG/FAN LED */ + 0x0B, /* PSU1/PSU2 LED */ +}; + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER, + LED_MODE_AMBER_BLINK, + LED_MODE_YELLOW, + LED_MODE_YELLOW_BLINK, + LED_MODE_BLUE, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +struct led_type_mode { + enum led_type type; + enum led_light_mode mode; + int type_mask; + int mode_value; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_FAN, LED_MODE_OFF, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_OFF_VALUE}, +{LED_TYPE_FAN, LED_MODE_GREEN, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_GREEN_VALUE}, +{LED_TYPE_FAN, LED_MODE_AMBER, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_AMBER_VALUE}, +{LED_TYPE_FAN, LED_MODE_AUTO, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_AUTO_VALUE}, +{LED_TYPE_PSU1, LED_MODE_OFF, LED_TYPE_PSU1_REG_MASK, LED_MODE_PSU1_OFF_VALUE}, +{LED_TYPE_PSU1, LED_MODE_GREEN, LED_TYPE_PSU1_REG_MASK, LED_MODE_PSU1_GREEN_VALUE}, +{LED_TYPE_PSU1, LED_MODE_AMBER, LED_TYPE_PSU1_REG_MASK, LED_MODE_PSU1_AMBER_VALUE}, +{LED_TYPE_PSU1, LED_MODE_AUTO, LED_TYPE_PSU1_REG_MASK, LED_MODE_PSU1_AUTO_VALUE}, +{LED_TYPE_PSU2, LED_MODE_OFF, LED_TYPE_PSU2_REG_MASK, LED_MODE_PSU2_OFF_VALUE}, +{LED_TYPE_PSU2, LED_MODE_GREEN, LED_TYPE_PSU2_REG_MASK, LED_MODE_PSU2_GREEN_VALUE}, +{LED_TYPE_PSU2, LED_MODE_AMBER, LED_TYPE_PSU2_REG_MASK, LED_MODE_PSU2_AMBER_VALUE}, +{LED_TYPE_PSU2, LED_MODE_AUTO, LED_TYPE_PSU2_REG_MASK, LED_MODE_PSU2_AUTO_VALUE}, +{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE}, +{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE}, +{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE}, +{LED_TYPE_DIAG, LED_MODE_YELLOW, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_YELLOW_VALUE}, +{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE}, +{LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_VALUE}, +{LED_TYPE_LOC, LED_MODE_AMBER_BLINK, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_BLINKING_VALUE1}, +{LED_TYPE_LOC, LED_MODE_AMBER_BLINK, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_BLINKING_VALUE2} +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) { + continue; + } + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_value) { + return led_type_mode_data[i].mode; + } + } + + return LED_MODE_UNKNOWN; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + int type_mask, mode_value; + + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + type_mask = led_type_mode_data[i].type_mask; + mode_value = led_type_mode_data[i].mode_value; + reg_val = (reg_val & ~type_mask) | mode_value; + } + + return reg_val; +} + +static int as7116_54x_led_read_value(u8 reg) +{ + return as7116_54x_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); +} + +static int as7116_54x_led_write_value(u8 reg, u8 value) +{ + return as7116_54x_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); +} + +static void as7116_54x_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as7116_54x_led update\n"); + ledctl->valid = 0; + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = as7116_54x_led_read_value(led_reg[i]); + + if (status < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void as7116_54x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + + reg_val = as7116_54x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + as7116_54x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void as7116_54x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7116_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} + +static enum led_brightness as7116_54x_led_diag_get(struct led_classdev *cdev) +{ + as7116_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void as7116_54x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7116_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static enum led_brightness as7116_54x_led_loc_get(struct led_classdev *cdev) +{ + as7116_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void as7116_54x_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7116_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_FAN); +} + +static enum led_brightness as7116_54x_led_fan_get(struct led_classdev *cdev) +{ + as7116_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + +static void as7116_54x_led_psu1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7116_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1); +} + +static enum led_brightness as7116_54x_led_psu1_get(struct led_classdev *cdev) +{ + as7116_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void as7116_54x_led_psu2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7116_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2); +} + +static enum led_brightness as7116_54x_led_psu2_get(struct led_classdev *cdev) +{ + as7116_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static struct led_classdev as7116_54x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "as7116_54x_led::diag", + .default_trigger = "unused", + .brightness_set = as7116_54x_led_diag_set, + .brightness_get = as7116_54x_led_diag_get, + .max_brightness = LED_MODE_YELLOW, + }, + [LED_TYPE_LOC] = { + .name = "as7116_54x_led::loc", + .default_trigger = "unused", + .brightness_set = as7116_54x_led_loc_set, + .brightness_get = as7116_54x_led_loc_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, + [LED_TYPE_FAN] = { + .name = "as7116_54x_led::fan", + .default_trigger = "unused", + .brightness_set = as7116_54x_led_fan_set, + .brightness_get = as7116_54x_led_fan_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "as7116_54x_led::psu1", + .default_trigger = "unused", + .brightness_set = as7116_54x_led_psu1_set, + .brightness_get = as7116_54x_led_psu1_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as7116_54x_led::psu2", + .default_trigger = "unused", + .brightness_set = as7116_54x_led_psu2_set, + .brightness_get = as7116_54x_led_psu2_get, + .max_brightness = LED_MODE_AUTO, + }, +}; + + +static int as7116_54x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(as7116_54x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &as7116_54x_leds[i]); + + if (ret < 0) { + break; + } + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(as7116_54x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&as7116_54x_leds[i]); + } + } + + return ret; +} + +static int as7116_54x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(as7116_54x_leds); i++) { + led_classdev_unregister(&as7116_54x_leds[i]); + } + + return 0; +} + +static struct platform_driver as7116_54x_led_driver = { + .probe = as7116_54x_led_probe, + .remove = as7116_54x_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init as7116_54x_led_init(void) +{ + int ret; + +#if 0 + extern int platform_accton_as7116_54x(void); + if (!platform_accton_as7116_54x()) { + return -ENODEV; + } +#endif + + ret = platform_driver_register(&as7116_54x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct as7116_54x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + goto exit_driver; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + goto exit_free; + } + + return 0; + +exit_free: + kfree(ledctl); +exit_driver: + platform_driver_unregister(&as7116_54x_led_driver); +exit: + return ret; +} + +static void __exit as7116_54x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&as7116_54x_led_driver); + kfree(ledctl); +} + +module_init(as7116_54x_led_init); +module_exit(as7116_54x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7116_54x_led driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-psu.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-psu.c new file mode 100644 index 000000000000..b4e14297f414 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-psu.c @@ -0,0 +1,349 @@ +/* + * An hwmon driver for accton as7116_54x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 + +#define MODEL_NAME_LEN 11 +#define MODEL_NAME_REG_OFFSET 0x20 + +#define SERIAL_NUM_LEN 18 +#define SERIAL_NUM_REG_OFFSET 0x35 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +static int as7116_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7116_54x_cpld_read(unsigned short cpld_addr, u8 reg); +static struct as7116_54x_psu_data *as7116_54x_psu_update_device(struct device *dev, u8 update_eeprom); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7116_54x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MODEL_NAME_LEN+1]; /* Model name, read from eeprom */ + char serial[SERIAL_NUM_LEN+1]; /* Serial number, read from eeprom*/ +}; + +enum as7116_54x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_serial_numer, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); + +static struct attribute *as7116_54x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_serial_numer.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7116_54x_psu_data *data = as7116_54x_psu_update_device(dev, 0); + u8 status = 0; + + if (!data->valid) { + return -EIO; + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7116_54x_psu_data *data = as7116_54x_psu_update_device(dev, 1); + char *ptr = NULL; + + if (!data->valid) { + return -EIO; + } + + if (!IS_PRESENT(data->index, data->status)) { + return -ENXIO; + } + + if (attr->index == PSU_MODEL_NAME) { + ptr = data->model_name; + } + else { /* PSU_SERIAL_NUBMER */ + ptr = data->serial; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group as7116_54x_psu_group = { + .attrs = as7116_54x_psu_attributes, +}; + +static int as7116_54x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7116_54x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7116_54x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7116_54x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7116_54x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7116_54x_psu_remove(struct i2c_client *client) +{ + struct as7116_54x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7116_54x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7116_54x_psu1, + as7116_54x_psu2 +}; + +static const struct i2c_device_id as7116_54x_psu_id[] = { + { "as7116_54x_psu1", as7116_54x_psu1 }, + { "as7116_54x_psu2", as7116_54x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7116_54x_psu_id); + +static struct i2c_driver as7116_54x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7116_54x_psu", + }, + .probe = as7116_54x_psu_probe, + .remove = as7116_54x_psu_remove, + .id_table = as7116_54x_psu_id, + .address_list = normal_i2c, +}; + +static int as7116_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as7116_54x_psu_data *as7116_54x_psu_update_device(struct device *dev, u8 update_eeprom) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7116_54x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + + data->valid = 0; + dev_dbg(&client->dev, "Starting as7116_54x update\n"); + + /* Read psu status */ + status = as7116_54x_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial, 0, sizeof(data->serial)); + + if (update_eeprom && IS_PRESENT(data->index, data->status)) { + /* Read model name */ + status = as7116_54x_psu_read_block(client, MODEL_NAME_REG_OFFSET, data->model_name, + ARRAY_SIZE(data->model_name)-1); + + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + goto exit; + } + else { + /* Skip the meaningless data byte 8*/ + data->model_name[8] = data->model_name[9]; + data->model_name[9] = data->model_name[10]; + data->model_name[10] = '\0'; + } + + /* Read serial number */ + status = as7116_54x_psu_read_block(client, SERIAL_NUM_REG_OFFSET, data->serial, + ARRAY_SIZE(data->serial)-1); + + if (status < 0) { + data->serial[0] = '\0'; + dev_dbg(&client->dev, "unable to read serial number from (0x%x)\n", client->addr); + goto exit; + } + else { + data->serial[SERIAL_NUM_LEN] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as7116_54x_psu_init(void) +{ + //extern int platform_accton_as7116_54x(void); + //if (!platform_accton_as7116_54x()) { + // return -ENODEV; + //} + + return i2c_add_driver(&as7116_54x_psu_driver); +} + +static void __exit as7116_54x_psu_exit(void) +{ + i2c_del_driver(&as7116_54x_psu_driver); +} + +module_init(as7116_54x_psu_init); +module_exit(as7116_54x_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7116_54x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-sfp.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-sfp.c new file mode 100644 index 000000000000..540ceb21722f --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-sfp.c @@ -0,0 +1,1384 @@ +/* + * SFP driver for accton as7116_54x sfp + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "as7116_54x_sfp" /* Platform dependent */ + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) +#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1) + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 +#define SFF8472_10G_BASE_MASK 0xF0 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +extern int as7116_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as7116_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL +}; + +/* SFP/QSFP common attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); + +/* QSFP attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); +static struct attribute *qsfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, + NULL +}; + +/* SFP msa attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED); +static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); +static struct attribute *sfp_msa_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + NULL +}; + +/* SFP ddm attributes for sysfs */ +static struct attribute *sfp_ddm_attributes[] = { + NULL +}; + +/* Platform dependent +++ */ +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +as7116_54x_sfp1, as7116_54x_sfp2, as7116_54x_sfp3, as7116_54x_sfp4, +as7116_54x_sfp5, as7116_54x_sfp6, as7116_54x_sfp7, as7116_54x_sfp8, +as7116_54x_sfp9, as7116_54x_sfp10, as7116_54x_sfp11, as7116_54x_sfp12, +as7116_54x_sfp13, as7116_54x_sfp14, as7116_54x_sfp15, as7116_54x_sfp16, +as7116_54x_sfp17, as7116_54x_sfp18, as7116_54x_sfp19, as7116_54x_sfp20, +as7116_54x_sfp21, as7116_54x_sfp22, as7116_54x_sfp23, as7116_54x_sfp24, +as7116_54x_sfp25, as7116_54x_sfp26, as7116_54x_sfp27, as7116_54x_sfp28, +as7116_54x_sfp29, as7116_54x_sfp30, as7116_54x_sfp31, as7116_54x_sfp32, +as7116_54x_sfp33, as7116_54x_sfp34, as7116_54x_sfp35, as7116_54x_sfp36, +as7116_54x_sfp37, as7116_54x_sfp38, as7116_54x_sfp39, as7116_54x_sfp40, +as7116_54x_sfp41, as7116_54x_sfp42, as7116_54x_sfp43, as7116_54x_sfp44, +as7116_54x_sfp45, as7116_54x_sfp46, as7116_54x_sfp47, as7116_54x_sfp48, +as7116_54x_sfp49, as7116_54x_sfp50, as7116_54x_sfp51, as7116_54x_sfp52, +as7116_54x_sfp53, as7116_54x_sfp54 +}; + +#define I2C_DEV_ID(x) { #x, x} + +static const struct i2c_device_id sfp_device_id[] = { +I2C_DEV_ID(as7116_54x_sfp1), +I2C_DEV_ID(as7116_54x_sfp2), +I2C_DEV_ID(as7116_54x_sfp3), +I2C_DEV_ID(as7116_54x_sfp4), +I2C_DEV_ID(as7116_54x_sfp5), +I2C_DEV_ID(as7116_54x_sfp6), +I2C_DEV_ID(as7116_54x_sfp7), +I2C_DEV_ID(as7116_54x_sfp8), +I2C_DEV_ID(as7116_54x_sfp9), +I2C_DEV_ID(as7116_54x_sfp10), +I2C_DEV_ID(as7116_54x_sfp11), +I2C_DEV_ID(as7116_54x_sfp12), +I2C_DEV_ID(as7116_54x_sfp13), +I2C_DEV_ID(as7116_54x_sfp14), +I2C_DEV_ID(as7116_54x_sfp15), +I2C_DEV_ID(as7116_54x_sfp16), +I2C_DEV_ID(as7116_54x_sfp17), +I2C_DEV_ID(as7116_54x_sfp18), +I2C_DEV_ID(as7116_54x_sfp19), +I2C_DEV_ID(as7116_54x_sfp20), +I2C_DEV_ID(as7116_54x_sfp21), +I2C_DEV_ID(as7116_54x_sfp22), +I2C_DEV_ID(as7116_54x_sfp23), +I2C_DEV_ID(as7116_54x_sfp24), +I2C_DEV_ID(as7116_54x_sfp25), +I2C_DEV_ID(as7116_54x_sfp26), +I2C_DEV_ID(as7116_54x_sfp27), +I2C_DEV_ID(as7116_54x_sfp28), +I2C_DEV_ID(as7116_54x_sfp29), +I2C_DEV_ID(as7116_54x_sfp30), +I2C_DEV_ID(as7116_54x_sfp31), +I2C_DEV_ID(as7116_54x_sfp32), +I2C_DEV_ID(as7116_54x_sfp33), +I2C_DEV_ID(as7116_54x_sfp34), +I2C_DEV_ID(as7116_54x_sfp35), +I2C_DEV_ID(as7116_54x_sfp36), +I2C_DEV_ID(as7116_54x_sfp37), +I2C_DEV_ID(as7116_54x_sfp38), +I2C_DEV_ID(as7116_54x_sfp39), +I2C_DEV_ID(as7116_54x_sfp40), +I2C_DEV_ID(as7116_54x_sfp41), +I2C_DEV_ID(as7116_54x_sfp42), +I2C_DEV_ID(as7116_54x_sfp43), +I2C_DEV_ID(as7116_54x_sfp44), +I2C_DEV_ID(as7116_54x_sfp45), +I2C_DEV_ID(as7116_54x_sfp46), +I2C_DEV_ID(as7116_54x_sfp47), +I2C_DEV_ID(as7116_54x_sfp48), +I2C_DEV_ID(as7116_54x_sfp49), +I2C_DEV_ID(as7116_54x_sfp50), +I2C_DEV_ID(as7116_54x_sfp51), +I2C_DEV_ID(as7116_54x_sfp52), +I2C_DEV_ID(as7116_54x_sfp53), +I2C_DEV_ID(as7116_54x_sfp54), +{ /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28 +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[6]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss + 3 => device id + 4 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 5 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +}; + +struct sfp_ddm_data { + struct eeprom_data eeprom; +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct sfp_ddm_data *ddm; + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + +/* Platform dependent +++ */ +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + int i = 0, j = 0, status = -1; + u8 reg; + unsigned short cpld_addr; + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + data->present = 0; + + /* Read present status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + cpld_addr = 0x61+i; + reg = 0x6+j; + status = as7116_54x_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%lx\r\n", data->present); + data->present |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* Read present status of port 49-54(QSFP port) */ + cpld_addr = 0x62; + reg = 0x14; + status = as7116_54x_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + else { + data->present |= (u64)status << 48; + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0, j = 0; + int status = -1; + + if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { + return data; + } + + DEBUG_PRINT("Starting as7116_54x sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->msa->valid = 0; + memset(data->msa->status, 0, sizeof(data->msa->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 9; j++) { + u8 reg; + unsigned short cpld_addr; + reg = 0x9+j; + cpld_addr = 0x61+i; + + status = as7116_54x_cpld_read(cpld_addr, reg); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + + data->msa->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + data->msa->valid = 1; + data->msa->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + unsigned short cpld_addr = 0; + u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; + long disable; + int error; + + if (data->driver_type == DRIVER_TYPE_QSFP) { + return qsfp_set_tx_disable(dev, da, buf, count); + } + + error = kstrtol(buf, 10, &disable); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + if(data->port < 24) { + cpld_addr = 0x61; + cpld_reg = 0xC + data->port / 8; + cpld_bit = 1 << (data->port % 8); + } + else { /* port 24 ~ 48 */ + cpld_addr = 0x62; + cpld_reg = 0xC + (data->port - 24) / 8; + cpld_bit = 1 << (data->port % 8); + } + + /* Read current status */ + cpld_val = as7116_54x_cpld_read(cpld_addr, cpld_reg); + + /* Update tx_disable status */ + if (disable) { + data->msa->status[1] |= BIT_INDEX(data->port); + cpld_val |= cpld_bit; + } + else { + data->msa->status[1] &= ~BIT_INDEX(data->port); + cpld_val &= ~cpld_bit; + } + + as7116_54x_cpld_write(cpld_addr, cpld_reg, cpld_val); + mutex_unlock(&data->update_lock); + return count; +} +/* Platform dependent --- */ + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + data = sfp_update_present(client); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + return !(data->present & BIT_INDEX(data->port)); /* Platform dependent */ +} + +/* Platform dependent +++ */ +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if (PRESENT_ALL == attr->index) { + int i; + u8 values[7] = {0}; + struct sfp_port_data *data = sfp_update_present(client); + + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = ~(u8)(data->present >> (i * 8)); + } + + /* Return values 1 -> 54 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5], + values[6] & 0x3F); + } + else { + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + /* PRESENT */ + return sprintf(buf, "%d\n", present); + } +} +/* Platform dependent --- */ + +static struct sfp_port_data *sfp_update_port_type(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 buf = 0; + int status; + + mutex_lock(&data->update_lock); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + { + status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + if (buf != SFF8024_DEVICE_ID_SFP) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + status = sfp_eeprom_read(client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); + data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; + break; + } + case DRIVER_TYPE_QSFP: + { + status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); + switch (buf) { + case SFF8024_DEVICE_ID_QSFP: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; + break; + case SFF8024_DEVICE_ID_QSFP_PLUS: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + case SFF8024_DEVICE_ID_QSFP28: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + default: + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + break; + } + default: + break; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + if (!present) { + /* port is not present */ + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_type(dev); + return sprintf(buf, "%d\n", data->port_type); +} + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + DEBUG_PRINT(""); + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + DEBUG_PRINT("Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + DEBUG_PRINT(""); + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + DEBUG_PRINT(""); + goto exit; + } + } + msleep(200); + DEBUG_PRINT(""); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + DEBUG_PRINT(""); + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + DEBUG_PRINT(""); + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + +exit: + DEBUG_PRINT(""); + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + int present; + u8 val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT(""); + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + DEBUG_PRINT(""); + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + DEBUG_PRINT(""); + data = qsfp_update_tx_rx_status(dev); + DEBUG_PRINT(""); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + DEBUG_PRINT(""); + switch (attr->index) { + case TX_FAULT: + val = !!(data->qsfp->status[2] & 0xF); + break; + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); + break; + case TX_DISABLE: + val = data->qsfp->status[1] & 0xF; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); + break; + case RX_LOS: + val = !!(data->qsfp->status[0] & 0xF); + break; + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); + break; + default: + break; + } + + DEBUG_PRINT(""); + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (!status) { + /* port is not present */ + return -ENXIO; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + mutex_lock(&data->update_lock); + + if (attr->index == TX_DISABLE) { + data->qsfp->status[1] = disable & 0xF; + } + else {/* TX_DISABLE1 ~ TX_DISABLE4*/ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + if (unlikely(status < 0)) { + count = status; + } + + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + char ddm; + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (status == 0) { + /* port is not present */ + return -ENODEV; + } + + status = sfp_eeprom_read(client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); + if (unlikely(status < 0)) { + return status; + } + + return sprintf(buf, "%d\n", !!(ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK)); +} + +/* Platform dependent +++ */ +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT("driver type = (%d)", data->driver_type); + if (data->driver_type == DRIVER_TYPE_QSFP) { + DEBUG_PRINT(""); + return qsfp_show_tx_rx_status(dev, da, buf); + } + + DEBUG_PRINT(""); + data = sfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + if(attr->index == RX_LOS_ALL) { + int i = 0; + u8 values[6] = {0}; + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = (u8)(data->msa->status[2] >> (i * 8)); + } + + /** Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5]); + } + + switch (attr->index) { + case TX_FAULT: + index = 0; + break; + case TX_DISABLE: + index = 1; + break; + case RX_LOS: + index = 2; + break; + default: + break; + } + + val = !!(data->msa->status[index] & BIT_INDEX(data->port)); + return sprintf(buf, "%d\n", val); +} +/* Platform dependent --- */ +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return data_len; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, command, *data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return 1; +#endif + + +} + +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + return sfp_port_write(data, buf, off, count); +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + goto abort; + } + if (unlikely(status != data_len)) { + status = -EIO; + goto abort; + } + + //result = data_len; + +abort: + return status; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); + goto abort; + } + + *data = (u8)status; + status = 1; + +abort: + return status; +#endif +} + +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + return sfp_port_read(data, buf, off, count); +} + +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group sfp_ddm_group = { + .attrs = sfp_ddm_attributes, +}; + +static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_ddm_data **data) +{ + int status; + struct sfp_ddm_data *ddm; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); + if (!ddm) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = ddm; + dev_info(&client->dev, "sfp ddm '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); +exit_free: + kfree(ddm); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); + if (status) { + goto exit_remove; + } + + /* Bring QSFPs out of reset */ + as7116_54x_cpld_write(0x62, 0x15, 0x3F); + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +/* Platform dependent +++ */ +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct sfp_port_data *data = NULL; + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + if (dev_id->driver_data >= as7116_54x_sfp1 && dev_id->driver_data <= as7116_54x_sfp48) { + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_SFP_MSA; + return sfp_msa_probe(client, dev_id, &data->msa); + } + else if (client->addr == SFP_EEPROM_A2_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_SFP_DDM; + return sfp_ddm_probe(client, dev_id, &data->ddm); + } + } + else { /* as7116_54x_sfp49 ~ as7116_54x_sfp54 */ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_QSFP; + return qsfp_probe(client, dev_id, &data->qsfp); + } + } + + return -ENODEV; +} +/* Platform dependent --- */ + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_SFP_DDM: + return sfp_ddm_remove(client, data->ddm); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + + return 0; +} + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + //extern int platform_accton_as7116_54x(void); + //if (!platform_accton_as7116_54x()) { + // return -ENODEV; + //} + + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7116_54x_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/service/as7116-platform-init.service b/platform/nephos/sonic-platform-modules-accton/as7116-54x/service/as7116-platform-init.service new file mode 100755 index 000000000000..be8688d2c2d2 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/service/as7116-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Accton AS7116-54X Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/accton_as7116_util.py install +ExecStop=/usr/local/bin/accton_as7116_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/setup.py b/platform/nephos/sonic-platform-modules-accton/as7116-54x/setup.py new file mode 100644 index 000000000000..bb740409e310 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7116-54x', + version='1.0.0', + description='Module to initialize Accton AS7116-54X platforms', + + packages=['as7116-54x'], + package_dir={'as7116-54x': 'as7116-54x/classes'}, + ) diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/README b/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/README new file mode 100755 index 000000000000..0b9fc1633999 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/README @@ -0,0 +1,60 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program is free software: you can redistribute it and/or modify +It under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +To initialize the system, run "accton_as7712_util.py install". +To clean up the drivers & devices, run "accton_as7712_util.py clean". +To dump information of sensors, run "accton_as7712_util.py show". +To dump SFP EEPROM, run "accton_as7712_util.py sff". +To set fan speed, run "accton_as7712_util.py set fan". +To enable/disable SFP emission, run "accton_as7712_util.py set sfp". +To set system LEDs' color, run "accton_as7712_util.py set led" +For more information, run "accton_as7712_util.py --help". + +==================================================================== +Besides applying accton_as7712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +LED controls can be found under /sys/class/leds. The sysfs interface +color mappings are as follows: +Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + +There are 5 system LEDs, loc, diag, fan, ps1, and ps2. +They are lit automatically by CPLD, but the loc and diag. +The loc led has only 1 color, blue. +The diag one has 3 colors: red, amber, and green. + +Fan controls can be found in /sys/bus/i2c/devices/2-0066. +There are 12 fans inside 6 fan modules. +All fans share 1 duty setting, ranged from 0~100. + +Three temperature sensors are controlled by the lm75 kernel modules. +They should already be visible under /sys/bus/i2c/drivers/lm75/. + +Two power supplies are controlled by the CPLD. +Here provide their status under +/sys/bus/i2c/devices/10-0050 and /sys/bus/i2c/devices/11-0053. + +There are 32 QSFP+ modules are equipped. +Apply "accton_as7712_util.py show" to get their status. +Apply "accton_as7712_util.py set sfp" to turn on/off light transmission. +Apply "accton_as7712_util.py sff" to dump EEPROM information. +Before operating on that QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/accton_as7116_util.py b/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/accton_as7116_util.py new file mode 100755 index 000000000000..26a8a3cc8f84 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/accton_as7116_util.py @@ -0,0 +1,526 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'as7116_54x' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':1, 'thermal':3, 'psu':2, 'sfp':54} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-54 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ + 'depmod', + 'modprobe i2c_dev', + 'modprobe i2c_mux_pca954x force_deselect_on_exit=1', + 'modprobe x86-64-accton-as7116-54x-cpld' , + 'modprobe x86-64-accton-as7116-54x-fan' , + 'modprobe x86-64-accton-as7116-54x-psu' , + 'modprobe x86-64-accton-as7116-54x-sfp' , + 'modprobe x86-64-accton-as7116-54x-led' ] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['1-0063'] , + 'thermal': ['17-004b','19-0049', '20-004a'] , + 'psu': ['10-0050','11-0058'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable_all']} + +sfp_map = [37,38,39,40, + 41,42,43,44,45,46,47,48,49,50, + 51,52,53,54,55,56,57,58,59,60, + 61,62,63,64,65,66,67,68,69,70, + 71,72,73,74,75,76,77,78,79,80, + 81,82,83,84, + 21,22,23,24,25,26] + +mknod =[ + 'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', + 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo as7116_54x_fan 0x63 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-17/new_device', + 'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-19/new_device', + 'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-20/new_device', + 'echo as7116_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo as7116_54x_cpld2 0x61 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo as7116_54x_cpld3 0x62 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo as7116_54x_psu1 0x50 > /sys/bus/i2c/devices/i2c-10/new_device', + 'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-10/new_device', + 'echo as7116_54x_psu2 0x53 > /sys/bus/i2c/devices/i2c-11/new_device', + 'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-11/new_device', + 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-29/new_device', + 'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-30/new_device', + 'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-31/new_device', + 'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-32/new_device', + 'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-33/new_device', + 'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-34/new_device', + 'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device'] + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo as7116_54x_sfp"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + if i <= 47: + status, output =log_os_system("echo as7116_54x_sfp"+str(i+1)+" 0x51 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0077", 0) + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/nephos/sonic-platform-modules-accton/debian/changelog b/platform/nephos/sonic-platform-modules-accton/debian/changelog new file mode 100755 index 000000000000..49f8f44bca48 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/debian/changelog @@ -0,0 +1,6 @@ +sonic-accton-platform-modules (1.0.0) unstable; urgency=low + + * Add support for AS7116-54X series + + -- developer Wed, 29 Mar 2017 11:00:00 +0800 + diff --git a/platform/nephos/sonic-platform-modules-accton/debian/compat b/platform/nephos/sonic-platform-modules-accton/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/nephos/sonic-platform-modules-accton/debian/control b/platform/nephos/sonic-platform-modules-accton/debian/control new file mode 100755 index 000000000000..cd70a20b2561 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/debian/control @@ -0,0 +1,11 @@ +Source: sonic-accton-platform-modules +Section: main +Priority: extra +Maintainer: simon.ji@nephosinc.com +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-accton-as7116-54x +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/nephos/sonic-platform-modules-accton/debian/rules b/platform/nephos/sonic-platform-modules-accton/debian/rules new file mode 100755 index 000000000000..cb232bd42425 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/debian/rules @@ -0,0 +1,86 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-accton +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= as7116-54x +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CLASSES_DIR := classes +CONF_DIR := conf + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + $(PYTHON) $${mod}/setup.py build; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/nephos/sonic-platform-modules-ingrasys/.gitignore b/platform/nephos/sonic-platform-modules-ingrasys/.gitignore new file mode 100644 index 000000000000..c6127b38c1aa --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/.gitignore @@ -0,0 +1,52 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf diff --git a/platform/nephos/sonic-platform-modules-ingrasys/LICENSE b/platform/nephos/sonic-platform-modules-ingrasys/LICENSE new file mode 100644 index 000000000000..9cecc1d4669e --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/platform/nephos/sonic-platform-modules-ingrasys/debian/changelog b/platform/nephos/sonic-platform-modules-ingrasys/debian/changelog new file mode 100644 index 000000000000..a3e3f92cc731 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/debian/changelog @@ -0,0 +1,11 @@ +platform-driver (1.0.0) unstable; urgency=low + + * Add support for S9130-32X, S9230-64X series + + -- developer Wed, 29 Mar 2017 11:00:00 +0800 + +platform-driver (1.0.0) unstable; urgency=low + + * Initial release (Closes: #nnnn) + + -- developer Wed, 05 Oct 2016 16:30:45 +0800 diff --git a/platform/nephos/sonic-platform-modules-ingrasys/debian/compat b/platform/nephos/sonic-platform-modules-ingrasys/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/nephos/sonic-platform-modules-ingrasys/debian/control b/platform/nephos/sonic-platform-modules-ingrasys/debian/control new file mode 100755 index 000000000000..3db0b5f3505f --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/debian/control @@ -0,0 +1,15 @@ +Source: platform-driver +Section: unknown +Priority: optional +Maintainer: Wade He +Build-Depends: debhelper (>= 9), dh-systemd +Standards-Version: 1.0.0 + +Package: sonic-platform-ingrasys-s9130-32x +Architecture: amd64 +Description: This package contains S9130-32X platform driver utility for SONiC project. + +Package: sonic-platform-ingrasys-s9230-64x +Architecture: amd64 +Description: This package contains S9230-64X platform driver utility for SONiC project. + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/debian/rules b/platform/nephos/sonic-platform-modules-ingrasys/debian/rules new file mode 100755 index 000000000000..f03e1de42c1d --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/debian/rules @@ -0,0 +1,42 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_PRE_NAME := sonic-platform-ingrasys +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= s9130-32x s9230-64x +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CONF_DIR := conf + +%: + dh $@ --with systemd + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/sbin; \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/*.sh \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/sbin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + done) + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9130-32x.init b/platform/nephos/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9130-32x.init new file mode 100644 index 000000000000..a925faf45fa8 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9130-32x.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S9130-32X board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9130-32x.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/nephos/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9230-64x.init b/platform/nephos/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9230-64x.init new file mode 100644 index 000000000000..4389aee5f77c --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9230-64x.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S9230-64X board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9230-64x.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/README.md b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/README.md new file mode 100644 index 000000000000..1b3b14db343b --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/README.md @@ -0,0 +1,167 @@ +# Ingrasys S9130-32X Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, 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 . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S9130-32X is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S9130-32X platform. + +### I2C i801 + +The I2C i801 on Ingrasys S9130-32X can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for power monitor, FAN controller, HWM and thermal sensors. + +### I2C PCA9548 +The PCA9548 module on S9130-32X can be found in +`/sys/bus/i2c/devices/i2c-1/` , `/sys/bus/i2c/devices/i2c-2/`, +`/sys/bus/i2c/devices/i2c-3/`, `/sys/bus/i2c/devices/i2c-4/`, +`/sys/bus/i2c/devices/i2c-5/`, `/sys/bus/i2c/devices/i2c-6/`, +`/sys/bus/i2c/devices/i2c-7/`, `/sys/bus/i2c/devices/i2c-8/` + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S9130-32X. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S9130-32X platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s9130-32x package is installed on the S9130-32X, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x51" > /sys/bus/i2c/devices/i2c-0/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/0-0051/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon5/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/Makefile b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/Makefile new file mode 100755 index 000000000000..688bb4666444 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := eeprom_mb.o +obj-m += ingrasys_s9130_32x_psu.o diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/eeprom_mb.c b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/eeprom_mb.c new file mode 100755 index 000000000000..528864d93382 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/eeprom_mb.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +/* enable dev_dbg print out */ +//#define DEBUG + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { /*0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57,*/ I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 512 + +#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 mb_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 mb_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++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static ssize_t mb_eeprom_write(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); + int ret; + int i; + u8 cmd; + u16 value16; + + dev_dbg(&client->dev, "mb_eeprom_write off=%d, count=%d\n", (int)off, (int)count); + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + mutex_lock(&data->update_lock); + + for(i=0; i < count; i++) { + /* write command */ + cmd = (off >> 8) & 0xff; + value16 = off & 0xff; + value16 |= buf[i] << 8; + ret = i2c_smbus_write_word_data(client, cmd, value16); + + if (ret < 0) { + dev_err(&client->dev, "write address failed at %d \n", (int)off); + goto exit; + } + + off++; + + /* need to wait for write complete */ + udelay(10000); + } +exit: + mutex_unlock(&data->update_lock); + /* force to update client when reading */ + for(i=0; i < SLICE_NUM; i++) { + data->last_updated[i] = 0; + } + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO | S_IWUSR, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, + .write = mb_eeprom_write, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x51 and 0x55. So decline + attaching to addresses >= 0x56 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x56) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_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, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/ingrasys_s9130_32x_platform.h b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/ingrasys_s9130_32x_platform.h new file mode 100644 index 000000000000..23dcf17a855b --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/ingrasys_s9130_32x_platform.h @@ -0,0 +1,148 @@ +#ifndef _S9130_32X_PLATFORM_H +#define _S9130_32X_PLATFORM_H + +#include + +// remove debug before release +#define DEBUG + +enum bus_order { + I2C_BUS_MAIN, + MUX_9548_0_CH0, + MUX_9548_0_CH1, + MUX_9548_0_CH2, + MUX_9548_0_CH3, + MUX_9548_0_CH4, + MUX_9548_0_CH5, + MUX_9548_0_CH6, + MUX_9548_0_CH7, + MUX_9548_1_CH0, + MUX_9548_1_CH1, + MUX_9548_1_CH2, + MUX_9548_1_CH3, + MUX_9548_1_CH4, + MUX_9548_1_CH5, + MUX_9548_1_CH6, + MUX_9548_1_CH7, + MUX_9546_0_CH0, + MUX_9546_0_CH1, + MUX_9546_0_CH2, + MUX_9546_0_CH3, + MUX_9546_1_CH0, + MUX_9546_1_CH1, + MUX_9546_1_CH2, + MUX_9546_1_CH3, + MUX_9548_2_CH0, + MUX_9548_2_CH1, + MUX_9548_2_CH2, + MUX_9548_2_CH3, + MUX_9548_2_CH4, + MUX_9548_2_CH5, + MUX_9548_2_CH6, + MUX_9548_2_CH7, + MUX_9548_3_CH0, + MUX_9548_3_CH1, + MUX_9548_3_CH2, + MUX_9548_3_CH3, + MUX_9548_3_CH4, + MUX_9548_3_CH5, + MUX_9548_3_CH6, + MUX_9548_3_CH7, + MUX_9548_4_CH0, + MUX_9548_4_CH1, + MUX_9548_4_CH2, + MUX_9548_4_CH3, + MUX_9548_4_CH4, + MUX_9548_4_CH5, + MUX_9548_4_CH6, + MUX_9548_4_CH7, + MUX_9548_5_CH0, + MUX_9548_5_CH1, + MUX_9548_5_CH2, + MUX_9548_5_CH3, + MUX_9548_5_CH4, + MUX_9548_5_CH5, + MUX_9548_5_CH6, + MUX_9548_5_CH7, + MUX_9548_6_CH0, + MUX_9548_6_CH1, + MUX_9548_6_CH2, + MUX_9548_6_CH3, + MUX_9548_6_CH4, + MUX_9548_6_CH5, + MUX_9548_6_CH6, + MUX_9548_6_CH7, + MUX_9548_7_CH0, + MUX_9548_7_CH1, + MUX_9548_7_CH2, + MUX_9548_7_CH3, + MUX_9548_7_CH4, + MUX_9548_7_CH5, + MUX_9548_7_CH6, + MUX_9548_7_CH7, + MUX_9548_8_CH0, + MUX_9548_8_CH1, + MUX_9548_8_CH2, + MUX_9548_8_CH3, + MUX_9548_8_CH4, + MUX_9548_8_CH5, + MUX_9548_8_CH6, + MUX_9548_8_CH7, + MUX_9548_9_CH0, + MUX_9548_9_CH1, + MUX_9548_9_CH2, + MUX_9548_9_CH3, + MUX_9548_9_CH4, + MUX_9548_9_CH5, + MUX_9548_9_CH6, + MUX_9548_9_CH7, + MUX_9548_10_CH0, + MUX_9548_10_CH1, + MUX_9548_10_CH2, + MUX_9548_10_CH3, + MUX_9548_10_CH4, + MUX_9548_10_CH5, + MUX_9548_10_CH6, + MUX_9548_10_CH7, +}; + +#define I2C_ADDR_MUX_9555_0 (0x20) +#define I2C_ADDR_MUX_9555_1 (0x24) +#define I2C_ADDR_MUX_9555_2 (0x25) +#define I2C_ADDR_MUX_9555_3 (0x26) +#define I2C_ADDR_MUX_9539_0 (0x76) +#define I2C_ADDR_MUX_9539_1 (0x76) +#define I2C_BUS_FAN_STATUS (I2C_BUS_MAIN) +#define I2C_BUS_SYS_LED (MUX_9548_1_CH1) + +#define NUM_OF_I2C_MUX (11) +#define NUM_OF_CPLD (5) +#define NUM_OF_QSFP_PORT (64) +#define NUM_OF_SFP_PORT (2) +#define QSFP_EEPROM_I2C_ADDR (0x50) + +enum gpio_reg { + REG_PORT0_IN, + REG_PORT1_IN, + REG_PORT0_OUT, + REG_PORT1_OUT, + REG_PORT0_POL, + REG_PORT1_POL, + REG_PORT0_DIR, + REG_PORT1_DIR, +}; + +struct ing_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +struct i2c_init_data { + __u16 ch; + __u16 addr; + __u8 reg; + __u8 value; +}; + +#endif diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/ingrasys_s9130_32x_psu.c b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/ingrasys_s9130_32x_psu.c new file mode 100644 index 000000000000..edf92b67241b --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/ingrasys_s9130_32x_psu.c @@ -0,0 +1,388 @@ +/* + * S9130-32x PSU driver + * + * Copyright (C) 2017 Ingrasys, 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 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s9130_32x_platform.h" + +static ssize_t show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf); +static struct s9130_psu_data *s9130_psu_update_status(struct device *dev); +static struct s9130_psu_data *s9130_psu_update_eeprom(struct device *dev); +static int s9130_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len); + + +#define DRIVER_NAME "psu" + +// Addresses scanned +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* PSU EEPROM SIZE */ +#define EEPROM_SZ 256 +#define READ_EEPROM 1 +#define NREAD_EEPROM 0 + +static struct i2c_client pca9555_client; + +/* pca9555 gpio pin mapping */ +#define PSU2_PWROK 0 +#define PSU2_PRSNT_L 1 +#define PSU2_PWRON_L 2 +#define PSU1_PWROK 3 +#define PSU1_PRSNT_L 4 +#define PSU1_PWRON_L 5 +#define TMP_75_INT_L 6 + +/* Driver Private Data */ +struct s9130_psu_data { + struct mutex lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + s32 status; /* IO expander value */ + char eeprom[EEPROM_SZ]; /* psu eeprom data */ + char psuABS; /* PSU absent */ + char psuPG; /* PSU power good */ +}; + +enum psu_index +{ + s9130_psu1, + s9130_psu2 +}; + +/* + * display power good attribute + */ +static ssize_t +show_psu_pg(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9130_psu_data *data = s9130_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuPG; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + +/* + * display power absent attribute + */ +static ssize_t +show_psu_abs(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9130_psu_data *data = s9130_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuABS; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + + +/* + * sysfs attributes for psu + */ +static DEVICE_ATTR(psu_pg, S_IRUGO, show_psu_pg, NULL); +static DEVICE_ATTR(psu_abs, S_IRUGO, show_psu_abs, NULL); +static DEVICE_ATTR(psu_eeprom, S_IRUGO, show_psu_eeprom, NULL); + +static struct attribute *s9130_psu_attributes[] = { + &dev_attr_psu_pg.attr, + &dev_attr_psu_abs.attr, + &dev_attr_psu_eeprom.attr, + NULL +}; + +/* + * display psu eeprom content + */ +static ssize_t +show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct s9130_psu_data *data = s9130_psu_update_eeprom(dev); + + memcpy(buf, (char *)data->eeprom, EEPROM_SZ); + return EEPROM_SZ; +} + +static const struct attribute_group s9130_psu_group = { + .attrs = s9130_psu_attributes, +}; + +/* + * check gpio expander is accessible + */ +static int +pca9555_detect(struct i2c_client *client) +{ + if (i2c_smbus_read_byte_data(client, REG_PORT0_DIR) < 0) { + return -ENODEV; + } + + return 0; +} + +/* + * client address init + */ +static void +i2c_devices_client_address_init(struct i2c_client *client) +{ + pca9555_client = *client; + pca9555_client.addr = 0x25; +} + +static int +s9130_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct s9130_psu_data *data; + int status, err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct s9130_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct s9130_psu_data)); + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + i2c_devices_client_address_init(client); + + err = pca9555_detect(&pca9555_client); + if (err) { + return err; + } + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &s9130_psu_group); + if (status) { + goto exit_free; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &s9130_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int +s9130_psu_remove(struct i2c_client *client) +{ + struct s9130_psu_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &s9130_psu_group); + kfree(data); + + return 0; +} + + +/* + * psu eeprom read utility + */ +static int +s9130_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len) +{ + int i=0, ret=0; + int blk_max = 32; //max block read size + + /* read eeprom, 32 * 8 = 256 bytes */ + for (i=0; i < EEPROM_SZ/blk_max; i++) { + ret = i2c_smbus_read_i2c_block_data(client, (i*blk_max), blk_max, + data + (i*blk_max)); + if (ret < 0) { + return ret; + } + } + return ret; +} + +/* + * update eeprom content + */ +static struct s9130_psu_data +*s9130_psu_update_eeprom(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9130_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + if (time_after(jiffies, data->last_updated + 300 * HZ) + || !data->valid) { + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9130_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + /* Read eeprom */ + if (!data->psuABS) { + //clear local eeprom data + memset(data->eeprom, 0, EEPROM_SZ); + + //read eeprom + status = s9130_psu_read_block(client, 0, data->eeprom, + ARRAY_SIZE(data->eeprom)); + + if (status < 0) { + memset(data->eeprom, 0, EEPROM_SZ); + dev_err(&client->dev, "Read eeprom failed, status=(%d)\n", status); + } else { + data->valid = 1; + } + } else { + memset(data->eeprom, 0, EEPROM_SZ); + } + data->last_updated = jiffies; + } + + mutex_unlock(&data->lock); + + return data; +} + +/* + * update psu status + */ +static struct s9130_psu_data +*s9130_psu_update_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9130_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9130_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + mutex_unlock(&data->lock); + + return data; +} + +static const struct i2c_device_id s9130_psu_id[] = { + { "psu1", s9130_psu1 }, + { "psu2", s9130_psu2 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, s9130_psu_id); + +static struct i2c_driver s9130_psu_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = s9130_psu_probe, + .remove = s9130_psu_remove, + .id_table = s9130_psu_id, + .address_list = normal_i2c, +}; + +static int __init s9130_psu_init(void) +{ + return i2c_add_driver(&s9130_psu_driver); +} + +static void __exit s9130_psu_exit(void) +{ + i2c_del_driver(&s9130_psu_driver); +} + +module_init(s9130_psu_init); +module_exit(s9130_psu_exit); + +MODULE_AUTHOR("Jason Tsai "); +MODULE_DESCRIPTION("S9130-32X psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/service/qsfp-monitor.service b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/service/qsfp-monitor.service new file mode 100644 index 000000000000..10b48f648b98 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s9130-32x-monitor.service +After=s9130-32x-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/service/s9130-32x-monitor.service b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/service/s9130-32x-monitor.service new file mode 100644 index 000000000000..3163b0af6f12 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/service/s9130-32x-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s9130_32x_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/i2c_utils.sh b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/i2c_utils.sh new file mode 100755 index 000000000000..ea238e01729a --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/i2c_utils.sh @@ -0,0 +1,1720 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, 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 . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.1.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +QSFP_ACTION=${2} +MB_EEPROM_ACTION=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_I801_DEVICE=0 + +# MAIN MUX PCA9548#0 0x73 +NUM_MUX_9548_0_CH0=$(( ${NUM_I801_DEVICE} + 1 )) # ucd9090 0x34 +NUM_MUX_9548_0_CH1=$(( ${NUM_I801_DEVICE} + 2 )) # PCA9539 0x76 for fp LED & HW ID +NUM_MUX_9548_0_CH7=$(( ${NUM_I801_DEVICE} + 8 )) # W83795 0x2F + +# FRU MUX PCA9545#1 0x72 +NUM_MUX_9545_1_CH0=$(( ${NUM_I801_DEVICE} + 9 )) # PSU2 0x50 +NUM_MUX_9545_1_CH1=$(( ${NUM_I801_DEVICE} + 10 )) # PSU1 0x50 +NUM_MUX_9545_1_CH2=$(( ${NUM_I801_DEVICE} + 11 )) # FAN board IO exander 0x20 +NUM_MUX_9545_1_CH3=$(( ${NUM_I801_DEVICE} + 12 )) # TMP75#0 0x4C TMP75#1 0x49 + +# HOST MUX PCA9548#2 0X70 +NUM_MUX_9548_2_CH0=$(( ${NUM_I801_DEVICE} + 13 )) # PCA9548#3 0x71 +NUM_MUX_9548_2_CH1=$(( ${NUM_I801_DEVICE} + 14 )) # PCA9548#4 0x71 +NUM_MUX_9548_2_CH2=$(( ${NUM_I801_DEVICE} + 15 )) # PCA9548#5 0x71 +NUM_MUX_9548_2_CH3=$(( ${NUM_I801_DEVICE} + 16 )) # PCA9548#6 0x71 +NUM_MUX_9548_2_CH4=$(( ${NUM_I801_DEVICE} + 17 )) # PCA9535#3~6 0x20~0x23 ZQSFP ABS/INT +NUM_MUX_9548_2_CH5=$(( ${NUM_I801_DEVICE} + 18 )) # PCA9535#7~10 0x20~0x23 ZQSFP LPMODE/RST +NUM_MUX_9548_3_CH0=$(( ${NUM_I801_DEVICE} + 21 )) # QSFP 0 EEPROM +NUM_MUX_9548_4_CH0=$(( ${NUM_I801_DEVICE} + 29 )) # QSFP 8 EEPROM +NUM_MUX_9548_5_CH0=$(( ${NUM_I801_DEVICE} + 37 )) # QSFP 16 EEPROM +NUM_MUX_9548_6_CH0=$(( ${NUM_I801_DEVICE} + 45 )) # QSFP 24 EEPROM + +# MUX Alias +I2C_BUS_MAIN=${NUM_I801_DEVICE} +I2C_BUS_HWM=${NUM_MUX_9548_0_CH7} +I2C_BUS_FAN_STATUS=${NUM_MUX_9545_1_CH2} +I2C_BUS_SYS_LED=${NUM_MUX_9548_0_CH1} +I2C_BUS_HW_ID=${NUM_MUX_9548_0_CH1} +I2C_BUS_BMC_HW_ID=${I2C_BUS_MAIN} +I2C_BUS_PSU_STAT=${I2C_BUS_MAIN} +I2C_BUS_FANTRAY_LED=${NUM_MUX_9545_1_CH2} +I2C_BUS_MB_EEPROM=${I2C_BUS_MAIN} +I2C_BUS_CB_EEPROM=${I2C_BUS_MAIN} +I2C_BUS_PSU1_EEPROM=${NUM_MUX_9545_1_CH1} +I2C_BUS_PSU2_EEPROM=${NUM_MUX_9545_1_CH0} + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_SYS_GPIO="/sys/class/gpio" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon5" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_MUX_9548_0_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH0}" +PATH_MUX_9548_0_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH1}" +PATH_MUX_9548_0_CH7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH7}" +PATH_MUX_9545_1_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_1_CH0}" +PATH_MUX_9545_1_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_1_CH1}" +PATH_MUX_9545_1_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_1_CH2}" +PATH_MUX_9545_1_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_1_CH3}" +PATH_MUX_9548_2_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH0}" +PATH_MUX_9548_2_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH1}" +PATH_MUX_9548_2_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH2}" +PATH_MUX_9548_2_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH3}" +PATH_MUX_9548_2_CH4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH4}" +PATH_MUX_9548_2_CH5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH5}" +PATH_MUX_9548_3_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_3_CH0}" +PATH_MUX_9548_4_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_4_CH0}" +PATH_MUX_9548_5_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_5_CH0}" +PATH_MUX_9548_6_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_6_CH0}" + +# I2C Address +### I2C MUX +I2C_ADDR_MUX_9548_0=0x73 # MAIN MUX +I2C_ADDR_MUX_9545_1=0x72 # FRU MUX +I2C_ADDR_MUX_9548_2=0x70 # HOST MUX +I2C_ADDR_MUX_9548_3=0x71 # ZQSFP MUX #1 EEPROM +I2C_ADDR_MUX_9548_4=0x71 # ZQSFP MUX #2 EEPROM +I2C_ADDR_MUX_9548_5=0x71 # ZQSFP MUX #3 EEPROM +I2C_ADDR_MUX_9548_6=0x71 # ZQSFP MUX #4 EEPROM +### GPIO Expander +I2C_ADDR_MUX_9539_0=0x76 # LED & HW ID +I2C_ADDR_MUX_9539_1=0x75 # BMC PRSNT & HWM reset +I2C_ADDR_MUX_9539_2=0x74 # SYS SEL & RST +I2C_ADDR_MUX_9535_3=0x20 # ZQSFP0~15 ABS +I2C_ADDR_MUX_9535_4=0x21 # ZQSFP16~31 ABS +I2C_ADDR_MUX_9535_5=0x22 # ZQSFP0~15 INT +I2C_ADDR_MUX_9535_6=0x23 # ZQSFP16~31 INT +I2C_ADDR_MUX_9535_7=0x20 # ZQSFP0~15 LPMODE +I2C_ADDR_MUX_9535_8=0x21 # ZQSFP16~31 LPMODE +I2C_ADDR_MUX_9535_9=0x22 # ZQSFP0~15 RST +I2C_ADDR_MUX_9535_10=0x23 # ZQSFP16~31 RST +I2C_ADDR_MUX_9535_11=0x20 # on FAN board, fan status and led config +I2C_ADDR_MUX_9555_12=0x24 # on BMC board, INT and HW ID +I2C_ADDR_MUX_9555_13=0x25 # on BMC board, PSU status +I2C_ADDR_MUX_9555_14=0x26 # on BMC board, RST and SEL +I2C_ADDR_MUX_9539_15=0x77 # on CPU board, STATUS and ERR from CPLD +### peripheral +I2C_ADDR_MB_EEPROM=0x55 # on main board +I2C_ADDR_CB_EEPROM=0x51 # on cpu board +I2C_ADDR_UCD9090=0x34 +I2C_ADDR_W83795=0x2F +I2C_ADDR_PSU1_EEPROM=0x50 +I2C_ADDR_PSU2_EEPROM=0x50 +I2C_ADDR_TMP75_REAR=0x4C +I2C_ADDR_TMP75_FRONT=0x49 +I2C_ADDR_TMP75_CB=0x4F # on cpu board +I2C_ADDR_TMP75_BB=0x4A # on bmc board +I2C_ADDR_QSFP_EEPROM=0x50 + +#sysfs +PATH_SYSFS_PSU1="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU1_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU1_EEPROM)" +PATH_SYSFS_PSU2="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU2_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU2_EEPROM)" + +#ACTIVE LOW enable flag +ACTIVE_LOW_EN=1 +ACTIVE_HIGH_EN=0 +#GPIO Direction In/Out +DIR_IN=in +DIR_OUT=out + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +# IO expander register +# direction +REG_PORT0_DIR=6 +REG_PORT1_DIR=7 +# polarity +REG_PORT0_POL=4 +REG_PORT1_POL=5 +# output +REG_PORT0_OUT=2 +REG_PORT1_OUT=3 +# input +REG_PORT0_IN=0 +REG_PORT1_IN=1 + +#ZQSFP GPIO sysfs index +ZQSFP_PORT0_ABS_GPIO_IDX=240 # 240~255 +ZQSFP_PORT16_ABS_GPIO_IDX=224 # 224~239 + +# switch port number range +MIN_PORT_NUM=1 +MAX_PORT_NUM=32 + +#GPIO Offset +GPIO_OFFSET=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "# Version : ${VERSION}" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_fan_speed_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_gpio_init" + echo " : ${0} i2c_gpio_deinit" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_cb_eeprom_get" + echo " : ${0} i2c_eeprom_sync" + echo " : ${0} i2c_qsfp_eeprom_get [1-32]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_cb_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [1-32]" + echo " : ${0} i2c_qsfp_type_get [1-32]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_bmc_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber" + echo " : ${0} i2c_fan_led green|amber on|off" + echo " : ${0} i2c_psu1_led green|amber on|off" + echo " : ${0} i2c_psu2_led green|amber on|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + #rmmod i2c_ismt + _util_rmmod i2c_i801 + modprobe i2c_i801 disable_features=0x10 + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + # add MUX PCA9548#0 on I801, assume to be i2c-1~8 + if [ ! -e ${PATH_MUX_9548_0_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_0}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_0} already init." + fi + # add MUX PCA9545#1 on I801, assume to be i2c-9~12 + if [ ! -e ${PATH_MUX_9545_1_CH0} ]; then + _retry "echo 'pca9545 ${I2C_ADDR_MUX_9545_1}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9545 ${I2C_ADDR_MUX_9545_1} already init." + fi + # add MUX PCA9548#2 on I801, assume to be i2c-13~20 + if [ ! -e ${PATH_MUX_9548_2_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_2}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_2} already init." + fi + # add MUX PCA9548#3 on PCA9548#2 CH0, assume to be i2c-21~28 + if [ ! -e ${PATH_MUX_9548_3_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_3}' > ${PATH_MUX_9548_2_CH0}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_3} already init." + fi + # add MUX PCA9548#4 on PCA9548#2 CH1, assume to be i2c-29~36 + if [ ! -e ${PATH_MUX_9548_4_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_4}' > ${PATH_MUX_9548_2_CH1}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_4} already init." + fi + # add MUX PCA9548#5 on PCA9548#2 CH2, assume to be i2c-37~44 + if [ ! -e ${PATH_MUX_9548_5_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_5}' > ${PATH_MUX_9548_2_CH2}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_5} already init." + fi + # add MUX PCA9548#6 on PCA9548#2 CH3, assume to be i2c-45~52 + if [ ! -e ${PATH_MUX_9548_6_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_6}' > ${PATH_MUX_9548_2_CH3}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_6} already init." + fi + + _i2c_hwm_init + _util_rmmod eeprom + modprobe eeprom_mb + modprobe gpio-pca953x + _i2c_io_exp_init + rmmod gpio_ich + _i2c_gpio_init + modprobe gpio_ich + _i2c_sensors_init + _i2c_psu_init + + # Init LED_CLR register (pull shift register out of reset), should be after io exp init + _port_led_clr_init + _i2c_qsfp_eeprom_init "new" + _i2c_mb_eeprom_init "new" + _i2c_cb_eeprom_init "new" + _i2c_fan_speed_init + _i2c_led_psu_status_set + _i2c_led_fan_status_set + + # sync eeprom content + _i2c_eeprom_sync + + # trun on sys led + echo "led_sys setup..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + echo "i2c deinit..." + _i2c_gpio_deinit + for mod in coretemp jc42 w83795 eeprom eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_i801 ingrasys_s9130_32x_psu; + do + _util_rmmod $mod + done + echo "Done" +} + +function _i2c_sensors_init { + echo "SENSORS init..." + local dev_path + # to make sure hwmon index in sysfs as expected, + # need to remove kernel module and then probe them in expected order + # remove all sensors kernel module + _util_rmmod coretemp + _util_rmmod jc42 + _util_rmmod w83795 + # probe coretemp kernel module + modprobe coretemp + # probe hwmon kernel module + modprobe w83795 + # add tmp75 to sysfs + ####Main board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9545_1_CH3}-$(printf "%04x" ${I2C_ADDR_TMP75_REAR})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_REAR}" > ${PATH_MUX_9545_1_CH3}/new_device # hwmon1 + else + echo "${dev_path} already exist" + fi + sleep 0.5 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9545_1_CH3}-$(printf "%04x" ${I2C_ADDR_TMP75_FRONT})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_FRONT}" > ${PATH_MUX_9545_1_CH3}/new_device #hwmon2 + else + echo "${dev_path} already exist" + fi + sleep 0.5 + ####BMC board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH7}-$(printf "%04x" ${I2C_ADDR_TMP75_BB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_BB}" > ${PATH_MUX_9548_0_CH7}/new_device #hwmon3 + else + echo "${dev_path} already exist" + fi + sleep 0.5 + ####CPU board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MAIN}-$(printf "%04x" ${I2C_ADDR_TMP75_CB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_CB}" > ${PATH_I801_DEVICE}/new_device #hwmon4 + else + echo "${dev_path} already exist" + fi + sleep 0.5 + # add w83795 to sysfs + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH7}-$(printf "%04x" ${I2C_ADDR_W83795})" + if ! [ -L ${dev_path} ]; then + echo "w83795adg ${I2C_ADDR_W83795}" > ${PATH_MUX_9548_0_CH7}/new_device #hwmon5 + else + echo "${dev_path} already exist" + fi + sleep 0.5 + + # probe jc42 kernel module + modprobe jc42 + + echo "Done" +} + +function _port_led_clr_init { + echo "port led init..." + # gpio pin on GPIO MUX PCA9539#2 I/O 0.2 + # pull high to out of reset + output_reg=${REG_PORT0_OUT} + mask=0x04 + value=0x04 + _util_i2cset -m ${mask} -y ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${output_reg} ${value} + echo "Done" +} + +#FAN Speed Init +function _i2c_fan_speed_init { + echo -n "FAN SPEED INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + # init fan speed + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi +} + +# HWM init +function _i2c_hwm_init { + echo "HWM INIT..." + # select bank0 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x80 + # SW reset, Disable monitor + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x01 0x9C + # disable TR5/TR6 DTS + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x04 0x0 + # enable FANIN1~8 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x06 0xFF + # disable FANIN9~14 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x07 0x00 + # CLKIN clock frequency set as 48Mhz + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x01 0x1C + # select bank 2 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x82 + # set PWM mode in FOMC + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x0F 0x00 + # set 25KHz fan output frequency in F1OPFP&F2OPFP + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x18 0x84 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x19 0x84 +} + +#Temperature sensor Init +function _i2c_temp_init { + echo "TEMP INIT..." + # enable temp monitor on w83795 + # select bank0 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x80 + # enable TR4 temperature monitoring + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x05 0x40 + # disable TR5/TR6 DTS + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x04 0x0 + echo "Done" +} + +#VOLMON Init +function _i2c_volmon_init { + echo "VOLMON INIT..." + # enable voltage monitor on w83795 + # VSEN1 P0V9 + # VSEN2 VDD + # VSEN3 P1V2 + # VSEN4 P1V8 + # select bank0 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x80 + # enable vsen1~4, disable vsen5~8 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x02 0x0F + # enable 3VDD,VBAT + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x03 0x50 + echo "Done" +} + +#FANIN Init +function _i2c_fan_init { + echo "FANIN INIT..." + # enable fan monitor on w83795 + # 4 fantray with 8 FANIN + # select bank0 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x80 + # enable FANIN1~8 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x06 0xFF + # disable FANIN9~14 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x07 0x00 + + # select bank 2 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x82 + # set PWM mode in FOMC + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x0F 0x00 + + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + + # need to init BMC io expander first due to some io expander are reset default + echo "Init BMC INT & HW ID IO Expander" + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_12} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_12} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_12} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_12} ${REG_PORT1_POL} 0x00 + + echo "Init BMC PSU status IO Expander" + # PWRON default 0 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_13} ${REG_PORT0_OUT} 0x00 + # default 0 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_13} ${REG_PORT1_OUT} 0x00 + # I/O 0.2 0.5 output(PWRON), rest input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_13} ${REG_PORT0_DIR} 0xDB + # I/O 1.0~1.1 input, 1.2~1.4 output (1.5~1.7 not enable) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_13} ${REG_PORT1_DIR} 0xE3 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_13} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_13} ${REG_PORT1_POL} 0x00 + + echo "Init BMC RST and SEL IO Expander" + # RST default is 1 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_14} ${REG_PORT0_OUT} 0x3F + # SEL default is 0 (HOST), EN default is 1 (ACTIVE_HIGH) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_14} ${REG_PORT1_OUT} 0x1F + # I/O 0.0~0.5 output, 0.6~0.7 not use + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_14} ${REG_PORT0_DIR} 0xC0 + # all output + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_14} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_14} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_14} ${REG_PORT1_POL} 0x00 + + echo "Init System LED & HW ID IO Expander" + # I/O_0.x for System LED default 0, I/O_1.x for HW ID + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_OUT} 0x00 + # System LED => all output + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_DIR} 0x00 + # HW ID => all input + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT1_POL} 0x00 + + echo "Init System PRSNT and HWM RST IO Expander" + # HWM_RST_L default 1 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_1} ${REG_PORT0_OUT} 0x04 + # all input expect HWM_RST_L (0.2) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_1} ${REG_PORT0_DIR} 0xFB + # port1 not used + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_1} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_1} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_1} ${REG_PORT1_POL} 0x00 + + echo "Init System SEL and RST IO Expander" + # RST 0.0~0.3 default 1 (ACTIVE low), rest default 0 + # SEL set to value 0 (host) + # LED_CLR also do init in _port_led_clr_init + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_OUT} 0x0F + # RST 1.6~1.7 default 1 (ACTIVE low), INT 1.0~1.4 default 1 (ACTIVE low) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_OUT} 0xDF + # all output, but MAC_RST_L 0.0 need to set as input to prevent reboot issue + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_DIR} 0x09 + # RST 1.5 !~ 1.7 output, rest are input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_DIR} 0x1F + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_POL} 0x00 + + echo "Init FAN Board Status IO Expander" + # LED_G_L set to 0, LED_Y_L set to 1 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_11} ${REG_PORT0_OUT} 0x22 + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_11} ${REG_PORT1_OUT} 0x22 + # DIR/ABS is input, LED_Y/LED_G is output + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_11} ${REG_PORT0_DIR} 0xCC + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_11} ${REG_PORT1_DIR} 0xCC + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_11} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_11} ${REG_PORT1_POL} 0x00 + + echo "Init CPU CPLD IO Expander" + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_15} ${REG_PORT0_DIR} 0xFF + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_15} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_15} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_15} ${REG_PORT1_POL} 0x00 + + echo "Init ZQSFP IO Expender" + + echo "set ZQSFP ABS" + #zQSFP 0-15 ABS + # all input + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_3} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_3} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_3} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_3} ${REG_PORT1_POL} 0x00 + #zQSFP 16-31 ABS + # all input + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_4} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_4} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_4} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_4} ${REG_PORT1_POL} 0x00 + + echo "set ZQSFP INT" + #zQSFP 0-15 INT + # all input + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_5} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_5} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_5} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_5} ${REG_PORT1_POL} 0x00 + #zQSFP 16-31 INT + # all input + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_6} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_6} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_6} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_6} ${REG_PORT1_POL} 0x00 + + echo "set ZQSFP LP_MODE = 0" + #ZQSFP 0-15 LP_MODE + # default is 0 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_7} ${REG_PORT0_OUT} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_7} ${REG_PORT1_OUT} 0x00 + # all output + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_7} ${REG_PORT0_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_7} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_7} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_7} ${REG_PORT1_POL} 0x00 + #ZQSFP 16-31 LP_MODE + # default is 0 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_8} ${REG_PORT0_OUT} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_8} ${REG_PORT1_OUT} 0x00 + # all output + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_8} ${REG_PORT0_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_8} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_8} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_8} ${REG_PORT1_POL} 0x00 + + echo "set ZQSFP RST = 1" + #ZQSFP 0-15 RST + # default is 1 (ACTIVE_LOW) + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_9} ${REG_PORT0_OUT} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_9} ${REG_PORT1_OUT} 0xFF + # all output + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_9} ${REG_PORT0_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_9} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_9} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_9} ${REG_PORT1_POL} 0x00 + #ZQSFP 16-31 RST + # default is 1 (ACTIVE_LOW) + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_10} ${REG_PORT0_OUT} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_10} ${REG_PORT1_OUT} 0xFF + # all output + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_10} ${REG_PORT0_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_10} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_10} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_10} ${REG_PORT1_POL} 0x00 + +} + +# To set the global variable GPIO_OFFSET +function _set_gpio_offset { + GPIO_OFFSET=0 + for d in `ls /sys/class/gpio/ | grep gpiochip` + do + gpiochip_no=${d##gpiochip} + if [ $gpiochip_no -gt 255 ]; then + GPIO_OFFSET=256 + break + fi + done + #echo "set GPIO_OFFSET=${GPIO_OFFSET}" +} + +#GPIO Init +function _i2c_gpio_init { + local i=0 + local start=255 + local end=255 + local ch_num=16 + + #ABS Port 0-15 + echo "pca9535 ${I2C_ADDR_MUX_9535_3}" > ${PATH_MUX_9548_2_CH4}/new_device + _set_gpio_offset + start=$[ ${start}+${GPIO_OFFSET} ] + end=$[ ${end}+${GPIO_OFFSET} ] + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + _util_gpio_export ${i} ${DIR_IN} ${ACTIVE_LOW_EN} + done + + #ABS Port 16-31 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_4}" > ${PATH_MUX_9548_2_CH4}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + _util_gpio_export ${i} ${DIR_IN} ${ACTIVE_LOW_EN} + done + + #INT Port 0-15 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_5}" > ${PATH_MUX_9548_2_CH4}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + _util_gpio_export ${i} ${DIR_IN} ${ACTIVE_LOW_EN} + done + + #INT Port 16-31 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_6}" > ${PATH_MUX_9548_2_CH4}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + _util_gpio_export ${i} ${DIR_IN} ${ACTIVE_LOW_EN} + done + + #LP Mode Port 0-15 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_7}" > ${PATH_MUX_9548_2_CH5}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + _util_gpio_export ${i} ${DIR_OUT} ${ACTIVE_HIGH_EN} + done + + #LP Mode Port 16-31 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_8}" > ${PATH_MUX_9548_2_CH5}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + _util_gpio_export ${i} ${DIR_OUT} ${ACTIVE_HIGH_EN} + done + + #RESET Port 0-15 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_9}" > ${PATH_MUX_9548_2_CH5}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + # need to set value to low (became ACTIVE_HIGH) to take port out of reset + _util_gpio_export ${i} ${DIR_OUT} ${ACTIVE_LOW_EN} 0 + done + + #RESET Port 16-31 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_10}" > ${PATH_MUX_9548_2_CH5}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + # need to set value to low (became ACTIVE_HIGH) to take port out of reset + _util_gpio_export ${i} ${DIR_OUT} ${ACTIVE_LOW_EN} 0 + done +} + +#GPIO DeInit +function _i2c_gpio_deinit { + echo ${I2C_ADDR_MUX_9535_3} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH4}/delete_device + echo ${I2C_ADDR_MUX_9535_4} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH4}/delete_device + echo ${I2C_ADDR_MUX_9535_5} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH4}/delete_device + echo ${I2C_ADDR_MUX_9535_6} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH4}/delete_device + echo ${I2C_ADDR_MUX_9535_7} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH5}/delete_device + echo ${I2C_ADDR_MUX_9535_8} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH5}/delete_device + echo ${I2C_ADDR_MUX_9535_9} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH5}/delete_device + echo ${I2C_ADDR_MUX_9535_10} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH5}/delete_device +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + + # check if io expander for fan tray exist + result=`i2cget -y ${I2C_BUS_FANTRAY_LED} ${I2C_ADDR_MUX_9535_11} ${REG_PORT0_IN} 2>/dev/null` + err_code=$? + if [ "$err_code" != "0" ]; then + echo "fan tray not exist!" + return + fi + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ]; then + FAN_TRAY=1 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=1 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ]; then + FAN_TRAY=2 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=2 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ]; then + FAN_TRAY=3 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=3 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + FAN_TRAY=4 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=4 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + echo "led_fan setup..." + # all fan ok + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + # all fan fail + elif [ "${FAN1_ALARM}" == "1" ] && [ "${FAN2_ALARM}" == "1" ] \ + && [ "${FAN3_ALARM}" == "1" ] && [ "${FAN4_ALARM}" == "1" ] \ + && [ "${FAN5_ALARM}" == "1" ] && [ "${FAN6_ALARM}" == "1" ] \ + && [ "${FAN7_ALARM}" == "1" ] && [ "${FAN8_ALARM}" == "1" ]; then + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + # partial fan fail + else + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + fi +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + echo "led_psu1 setup..." + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + else + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + echo "led_psu2 setup..." + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + else + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C SYSTEM LED TEST..." + echo "=========================================================" + local output_reg=${REG_PORT0_OUT} + local mask=0xFF + local value=0xFF + + #sys led (green) + # set sys_led_g (0.7) = 1 + mask=0x80 + value=0x80 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + # set sys_led_g (0.7) = 0 + mask=0x80 + value=0x00 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 0 + mask=0x60 + value=0x40 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 1 + mask=0x60 + value=0x60 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 0 + mask=0x18 + value=0x10 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 1 + mask=0x18 + value=0x18 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 0 + mask=0x06 + value=0x04 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 1 + mask=0x06 + value=0x06 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED (can't trun off system led) + # set set fan_led_en (0.6), psu1_pwr_ok_oe (0.4), psu0_pwr_ok_oe (0.2) = 0 + mask=0x54 + value=0x00 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check turn off all LEDs (exclude SYS LED) and Press [Enter] key to continue...' + + # restore sys led + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + + echo "Done" +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + local port=$1 + case ${port} in + 1|2|3|4|5|6|7|8) + i2cbus=${NUM_MUX_9548_2_CH4} + eeprombusbase=${NUM_MUX_9548_3_CH0} + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT0_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT0_ABS_GPIO_IDX} + ;; + 9|10|11|12|13|14|15|16) + i2cbus=${NUM_MUX_9548_2_CH4} + eeprombusbase=${NUM_MUX_9548_4_CH0} + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT0_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT0_ABS_GPIO_IDX} + ;; + 17|18|19|20|21|22|23|24) + i2cbus=${NUM_MUX_9548_2_CH4} + eeprombusbase=${NUM_MUX_9548_5_CH0} + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT16_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT16_ABS_GPIO_IDX} + ;; + 25|26|27|28|29|30|31|32) + i2cbus=${NUM_MUX_9548_2_CH4} + eeprombusbase=${NUM_MUX_9548_6_CH0} + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT16_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT16_ABS_GPIO_IDX} + ;; + *) + echo "Please input 1~32" + exit + ;; + esac +} + +#Set QSFP Port variable +function _qsfp_eeprom_var_set { + local port=$1 + # port 1 => zqsfp0 + # port 2 => zqsfp1 + # ... + eeprombusidx=$(( (${port} - 1) % 8)) + eeprombus=$(( ${eeprombusbase} + ${eeprombusidx} )) + eepromAddr=${I2C_ADDR_QSFP_EEPROM} +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_PORT_NUM}" "${MAX_PORT_NUM}" + + _util_get_qsfp_abs + + if [ $status = 0 ]; then + exit + fi + + _qsfp_eeprom_var_set ${QSFP_PORT} + + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo "QSFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-32 ports EEPROM + local i + for i in {1..32}; + do + _qsfp_port_i2c_var_set ${i} + + _qsfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/delete_device + fi + done + echo "Done" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + echo -n "Main Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init mb EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_MB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "$I2C_ADDR_MB_EEPROM" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/delete_device + fi + echo "Done" +} + +#Init CPU Board EEPROM +function _i2c_cb_eeprom_init { + echo -n "CPU Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init cpu EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_CB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM) ]; then + echo "$I2C_ADDR_CB_EEPROM" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CB_EEPROM}/delete_device + fi + echo "Done" +} + + +#get QSFP Status +function _i2c_qsfp_status_get { + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_PORT_NUM}" "${MAX_PORT_NUM}" + + local stat + _util_get_qsfp_abs + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_PORT_NUM}" "${MAX_PORT_NUM}" + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + _qsfp_eeprom_var_set ${QSFP_PORT} + + #Get QSFP EEPROM info + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Init PSU Kernel Module +function _i2c_psu_init { + echo "=========================================================" + echo "# Description: I2C PSU Init" + echo "=========================================================" + modprobe ingrasys_s9130_32x_psu + + echo "psu1 ${I2C_ADDR_PSU1_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/new_device + echo "psu2 ${I2C_ADDR_PSU2_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/new_device +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + local eeprom_psu1="" + local eeprom_psu2="" + + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + eeprom_psu1="${PATH_SYSFS_PSU1}/psu_eeprom" + cat ${eeprom_psu1} | hexdump -C + + eeprom_psu2="${PATH_SYSFS_PSU2}/psu_eeprom" + cat ${eeprom_psu2} | hexdump -C +} + +#Get Main Board EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + _i2c_sys_eeprom_get mb +} + +#Get CPU Board EEPROM Information +function _i2c_cb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C CB EEPROM Get..." + echo "=========================================================" + _i2c_sys_eeprom_get cb +} + +#Get system EEPROM Information +##input: "cb" for cpu board, "mb" for main board +function _i2c_sys_eeprom_get { + local eeprom_dev + + if [ "$1" == "cb" ]; then + eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM)/eeprom" + elif [ "$1" == "mb" ]; then + eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom" + else + echo "wrong eeprom type" + return + fi + + # check if eeprom device exist in sysfs + if [ ! -f ${eeprom_dev} ]; then + echo "eeprom device not init" + return + fi + + cat ${eeprom_dev} | hexdump -C + echo "Done" +} + +#sync eeprom content between mb and cb eeprom +function _i2c_eeprom_sync { + echo "=========================================================" + echo "# Description: EEPROM sync..." + echo "=========================================================" + + local mb_eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom" + local cb_eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM)/eeprom" + + # check if eeprom device exist in sysfs + if [[ ! -f ${mb_eeprom_dev} || ! -f ${cb_eeprom_dev} ]]; then + echo "eeprom device not init" + return + fi + + ## check if MB eeprom is empty + if [ ! -z "$(cat ${mb_eeprom_dev} | hexdump -n2 | grep ffff)" ]; then + echo "copy cb eeprom to mb eeprom..." + cat ${cb_eeprom_dev} > ${mb_eeprom_dev} + else + echo "no need to sync" + fi + + echo "Done" +} + +#Set System Status LED +function _i2c_sys_led { + # only green/amber, on/off can't control + if [ "${COLOR_LED}" == "green" ]; then + # set sys_led_g (0.7) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x80 + value=0x80 + elif [ "${COLOR_LED}" == "amber" ]; then + # set sys_led_g (0.7) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x80 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x40 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + # set fan_led_en (0.6) = 0 & fan_led_y (0.5) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x60 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + # set fan_led_en (0.6) = 0 & fan_led_y (0.5) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x20 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set PSU1 LED +function _i2c_psu1_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x10 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + # set psu1_pwr_ok_oe (0.4) = 0 & psu1_led_y (0.3) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x18 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + # set psu1_pwr_ok_oe (0.4) = 0 & psu1_led_y (0.3) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x08 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set PSU2 LED +function _i2c_psu2_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x04 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + # set psu0_pwr_ok_oe (0.2) = 0 & psu0_led_y (0.1) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x06 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + # set psu0_pwr_ok_oe (0.2) = 0 & psu0_led_y (0.1) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x02 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + + i2cAddr=${I2C_ADDR_MUX_9535_11} + output_reg=${REG_PORT0_OUT} + + case ${FAN_TRAY} in + 4) + output_reg=${REG_PORT0_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 3) + output_reg=${REG_PORT0_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 2) + output_reg=${REG_PORT1_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 1) + output_reg=${REG_PORT1_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x33 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x33 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "Done" +} + +#Get Board Version and Type +function _i2c_board_type_get { + # read input port 1 value from io expander + input_reg=${REG_PORT1_IN} + boardType=`i2cget -y ${I2C_BUS_HW_ID} ${I2C_ADDR_MUX_9539_0} ${input_reg}` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "MAIN_BOARD BOARD_ID is 0x%02x, HW Rev %d, Build Rev %d\n" $boardId $boardHwRev $boardBuildRev +} + +#Get BMC Board Version and Type +function _i2c_bmc_board_type_get { + # read input port 1 value from io expander + input_reg=${REG_PORT1_IN} + boardType=`i2cget -y ${I2C_BUS_BMC_HW_ID} ${I2C_ADDR_MUX_9555_12} ${input_reg}` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BMC_BOARD BOARD_ID is 0x%02x, HW Rev %d, Build Rev %d\n" $boardId $boardHwRev $boardBuildRev +} + +#Get PSU Status +function _i2c_psu_status { + local psu_abs="" + + psu1PwGood=`cat ${PATH_SYSFS_PSU1}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU1}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu1Exist=1 + else + psu1Exist=0 + fi + + psu2PwGood=`cat ${PATH_SYSFS_PSU2}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU2}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu2Exist=1 + else + psu2Exist=0 + fi + + printf "PSU1 Exist:%x PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#util functions +function _util_i2cset { + if [ "$DEBUG" == "on" ]; then + i2cset $@ + else + i2cset $@ 1>/dev/null + fi +} + +function _util_rmmod { + local mod=$1 + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod +} + +# get qsfp presence +function _util_get_qsfp_abs { + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up (ACTIVE_LOW_EN) + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) % 16 )) ))/value` +} + +# gpio init util function +function _util_gpio_export { + local gpio_n=$1 + local direction=$2 + local active_low=$3 + local value=$4 + + if [ -z "${gpio_n}" ]; then + echo "[gpio_init] gpio_n(${gpio_n}) is not provided" + return + fi + if [[ ${gpio_n} < 0 || ${gpio_n} > $(( 255+${GPIO_OFFSET} )) ]]; then + echo "[gpio_init] gpio_n(${gpio_n}) is invalid value" + return + fi + + #export gpio + echo ${gpio_n} > /sys/class/gpio/export + #set gpio direction + echo ${direction} > /sys/class/gpio/gpio${gpio_n}/direction + #set gpio active_low + echo ${active_low} > /sys/class/gpio/gpio${gpio_n}/active_low + #set value + if [ ! -z "${value}" ]; then + echo ${value} > /sys/class/gpio/gpio${gpio_n}/value + fi +} + +# valid input number +function _util_input_check { + # input parameter validation + if [[ $1 -lt $2 || $1 -gt $3 ]]; then + echo "Please input number $2~$3" + exit + fi +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Main Function +function _main { + tart_time_str=`date` + start_time_sec=$(date +%s) + + _set_gpio_offset + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_fan_speed_init" ]; then + _i2c_fan_speed_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_init" ]; then + _i2c_gpio_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_deinit" ]; then + _i2c_gpio_deinit + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_cb_eeprom_get" ]; then + _i2c_cb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_eeprom_sync" ]; then + _i2c_eeprom_sync + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_cb_eeprom_init" ]; then + _i2c_cb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_bmc_board_type_get" ]; then + _i2c_bmc_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_cb_eeprom_get + _i2c_board_type_get + _i2c_bmc_board_type_get + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/qsfp_monitor.sh b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/qsfp_monitor.sh new file mode 100755 index 000000000000..249f179216a6 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/qsfp_monitor.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, 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 . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..31}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/s9130_32x_monitor.sh b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/s9130_32x_monitor.sh new file mode 100755 index 000000000000..974da6d5001f --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/s9130_32x_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, 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 . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main \ No newline at end of file diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/README.md b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/README.md new file mode 100644 index 000000000000..d1a2d5464aee --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/README.md @@ -0,0 +1,182 @@ +# Ingrasys S9230-64X Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, 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 . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S9230-64X is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S9230-64X platform. + +### I2C i801 + +The I2C i801 on Ingrasys S9230-64X can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for power monitor, FAN controller, HWM and thermal sensors. + +### I2C PCA9548 +The PCA9548 module on S9230-64X can be found in +`/sys/bus/i2c/devices/i2c-1/` , `/sys/bus/i2c/devices/i2c-2/`, +`/sys/bus/i2c/devices/i2c-3/`, `/sys/bus/i2c/devices/i2c-4/`, +`/sys/bus/i2c/devices/i2c-5/`, `/sys/bus/i2c/devices/i2c-6/`, +`/sys/bus/i2c/devices/i2c-7/`, `/sys/bus/i2c/devices/i2c-8/` + +The pca9548 module for CPLD get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S9230-64X. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S9230-64X platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s9230-64X package is installed on the S9230-64X, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x55" > /sys/bus/i2c/devices/i2c-0/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/0-0055/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon7/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the CPLD 1~5 according to port number. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-64] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_status_get [1-64] + 0 => not insert + 1 => inserted +``` + +### SFP+ +SFP+ modules are managed by the CPLD 1~2 according to port number. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +SFP EEPROM: + i2c_utils.sh i2c_sfp_eeprom_get [1-2] + +SFP Insert Event: + i2c_utils.sh i2c_sfp_status_get [1-2] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/Makefile b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/Makefile new file mode 100755 index 000000000000..3107674e8712 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m := eeprom_mb.o +obj-m += ingrasys_s9230_64x_i2c_cpld.o +obj-m += ingrasys_s9230_64x_psu.o diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/eeprom_mb.c b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/eeprom_mb.c new file mode 100755 index 000000000000..528864d93382 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/eeprom_mb.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +/* enable dev_dbg print out */ +//#define DEBUG + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { /*0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57,*/ I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 512 + +#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 mb_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 mb_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++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static ssize_t mb_eeprom_write(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); + int ret; + int i; + u8 cmd; + u16 value16; + + dev_dbg(&client->dev, "mb_eeprom_write off=%d, count=%d\n", (int)off, (int)count); + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + mutex_lock(&data->update_lock); + + for(i=0; i < count; i++) { + /* write command */ + cmd = (off >> 8) & 0xff; + value16 = off & 0xff; + value16 |= buf[i] << 8; + ret = i2c_smbus_write_word_data(client, cmd, value16); + + if (ret < 0) { + dev_err(&client->dev, "write address failed at %d \n", (int)off); + goto exit; + } + + off++; + + /* need to wait for write complete */ + udelay(10000); + } +exit: + mutex_unlock(&data->update_lock); + /* force to update client when reading */ + for(i=0; i < SLICE_NUM; i++) { + data->last_updated[i] = 0; + } + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO | S_IWUSR, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, + .write = mb_eeprom_write, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x51 and 0x55. So decline + attaching to addresses >= 0x56 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x56) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_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, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_i2c_cpld.c b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_i2c_cpld.c new file mode 100644 index 000000000000..7d832fc0149f --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_i2c_cpld.c @@ -0,0 +1,1259 @@ +/* + * A i2c cpld driver for the ingrasys_s9230_64x + * + * Copyright (C) 2017 Ingrasys Technology Corporation. + * Leo Lin + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s9230_64x_i2c_cpld.h" + +#ifdef DEBUG +#define DEBUG_PRINT(fmt, args...) \ + printk(KERN_INFO "%s:%s[%d]: " fmt "\r\n", \ + __FILE__, __func__, __LINE__, ##args) +#else +#define DEBUG_PRINT(fmt, args...) +#endif + +#define I2C_READ_BYTE_DATA(ret, lock, i2c_client, reg) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_read_byte_data(i2c_client, reg); \ + mutex_unlock(lock); \ +} +#define I2C_WRITE_BYTE_DATA(ret, lock, i2c_client, reg, val) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_write_byte_data(i2c_client, reg, val); \ + mutex_unlock(lock); \ +} + +/* CPLD sysfs attributes index */ +enum s9230_64x_cpld_sysfs_attributes { + CPLD_ACCESS_REG, + CPLD_REGISTER_VAL, + CPLD_PORT_START, + CPLD_PORTS, + CPLD_VERSION, + CPLD_ID, + CPLD_BOARD_TYPE, + CPLD_EXT_BOARD_TYPE, + CPLD_QSFP_PORT_STATUS_1, + CPLD_QSFP_PORT_STATUS_2, + CPLD_QSFP_PORT_STATUS_3, + CPLD_QSFP_PORT_STATUS_4, + CPLD_QSFP_PORT_STATUS_5, + CPLD_QSFP_PORT_STATUS_6, + CPLD_QSFP_PORT_STATUS_7, + CPLD_QSFP_PORT_STATUS_8, + CPLD_QSFP_PORT_STATUS_9, + CPLD_QSFP_PORT_STATUS_10, + CPLD_QSFP_PORT_STATUS_11, + CPLD_QSFP_PORT_STATUS_12, + CPLD_QSFP_PORT_STATUS_13, + CPLD_QSFP_PORT_CONFIG_1, + CPLD_QSFP_PORT_CONFIG_2, + CPLD_QSFP_PORT_CONFIG_3, + CPLD_QSFP_PORT_CONFIG_4, + CPLD_QSFP_PORT_CONFIG_5, + CPLD_QSFP_PORT_CONFIG_6, + CPLD_QSFP_PORT_CONFIG_7, + CPLD_QSFP_PORT_CONFIG_8, + CPLD_QSFP_PORT_CONFIG_9, + CPLD_QSFP_PORT_CONFIG_10, + CPLD_QSFP_PORT_CONFIG_11, + CPLD_QSFP_PORT_CONFIG_12, + CPLD_QSFP_PORT_CONFIG_13, + CPLD_QSFP_PORT_INTERRUPT, + CPLD_SFP_PORT_STATUS, + CPLD_SFP_PORT_CONFIG, + CPLD_10GMUX_CONFIG, + CPLD_BMC_STATUS, + CPLD_BMC_WATCHDOG, + CPLD_USB_STATUS, +}; + +/* CPLD sysfs attributes hook functions */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t get_qsfp_port_start(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t get_qsfp_ports(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_cpld_id(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_qsfp_port_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_qsfp_port_config(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_qsfp_port_config(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_qsfp_port_interrupt(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_sfp_port_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_sfp_port_config(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_sfp_port_config(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_10gmux_config(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_10gmux_config(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_bmc_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_bmc_watchdog(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_bmc_watchdog(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_usb_status(struct device *dev, + struct device_attribute *da, char *buf); + +static LIST_HEAD(cpld_client_list); /* client list for cpld */ +static struct mutex list_lock; /* mutex for client list */ + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +struct cpld_data { + int index; /* CPLD index */ + struct mutex access_lock; /* mutex for cpld access */ + u8 access_reg; /* register to access */ +}; + +/* CPLD device id and data */ +static const struct i2c_device_id ingrasys_i2c_cpld_id[] = { + { "ingrasys_cpld1", cpld1 }, + { "ingrasys_cpld2", cpld2 }, + { "ingrasys_cpld3", cpld3 }, + { "ingrasys_cpld4", cpld4 }, + { "ingrasys_cpld5", cpld5 }, + {} +}; + +/* Addresses scanned for ingrasys_i2c_cpld */ +static const unsigned short cpld_i2c_addr[] = { 0x33, I2C_CLIENT_END }; + +/* define all support register access of cpld in attribute */ +static SENSOR_DEVICE_ATTR(cpld_access_register, S_IWUSR | S_IRUGO, + read_access_register, write_access_register, CPLD_ACCESS_REG); +static SENSOR_DEVICE_ATTR(cpld_register_value, S_IWUSR | S_IRUGO, + read_register_value, write_register_value, CPLD_REGISTER_VAL); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_start, S_IRUGO, + get_qsfp_port_start, NULL, CPLD_PORT_START); +static SENSOR_DEVICE_ATTR(cpld_qsfp_ports, S_IRUGO, + get_qsfp_ports, NULL, CPLD_PORTS); +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, + read_cpld_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(cpld_id, S_IRUGO, read_cpld_id, NULL, CPLD_ID); +static SENSOR_DEVICE_ATTR(cpld_board_type, S_IRUGO, + read_board_type, NULL, CPLD_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_ext_board_type, S_IRUGO, + read_ext_board_type, NULL, CPLD_EXT_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_1, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_1); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_2, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_2); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_3, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_3); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_4, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_4); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_5, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_5); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_6, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_6); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_7, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_7); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_8, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_8); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_9, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_9); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_10, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_10); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_11, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_11); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_12, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_12); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_13, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_13); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_1, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, CPLD_QSFP_PORT_CONFIG_1); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_2, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_2); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_3, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_3); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_4, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_4); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_5, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_5); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_6, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_6); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_7, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_7); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_8, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_8); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_9, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_9); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_10, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_10); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_11, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_11); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_12, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_12); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_13, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_13); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_interrupt, S_IRUGO, + read_qsfp_port_interrupt, NULL, CPLD_QSFP_PORT_INTERRUPT); +static SENSOR_DEVICE_ATTR(cpld_sfp_port_status, S_IRUGO, + read_sfp_port_status, NULL, CPLD_SFP_PORT_STATUS); +static SENSOR_DEVICE_ATTR(cpld_sfp_port_config, S_IWUSR | S_IRUGO, + read_sfp_port_config, write_sfp_port_config, CPLD_SFP_PORT_CONFIG); +static SENSOR_DEVICE_ATTR(cpld_10gmux_config, S_IWUSR | S_IRUGO, + read_10gmux_config, write_10gmux_config, + CPLD_10GMUX_CONFIG); +static SENSOR_DEVICE_ATTR(cpld_bmc_status, S_IRUGO, + read_bmc_status, NULL, CPLD_BMC_STATUS); +static SENSOR_DEVICE_ATTR(cpld_bmc_watchdog, S_IWUSR | S_IRUGO, + read_bmc_watchdog, write_bmc_watchdog, + CPLD_BMC_WATCHDOG); +static SENSOR_DEVICE_ATTR(cpld_usb_status, S_IRUGO, + read_usb_status, NULL, CPLD_USB_STATUS); + + +/* define support attributes of cpldx , total 5 */ +/* cpld 1 */ +static struct attribute *s9230_64x_cpld1_attributes[] = { + &sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_start.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_ports.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_id.dev_attr.attr, + &sensor_dev_attr_cpld_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_ext_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_interrupt.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_port_status.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_port_config.dev_attr.attr, + &sensor_dev_attr_cpld_10gmux_config.dev_attr.attr, + &sensor_dev_attr_cpld_bmc_status.dev_attr.attr, + &sensor_dev_attr_cpld_bmc_watchdog.dev_attr.attr, + &sensor_dev_attr_cpld_usb_status.dev_attr.attr, + NULL +}; +/* cpld 2 */ +static struct attribute *s9230_64x_cpld2_attributes[] = { + &sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_start.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_ports.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_id.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_interrupt.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_port_status.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_port_config.dev_attr.attr, + NULL +}; +/* cpld 3 / cpld 4 / cpld 5 */ +static struct attribute *s9230_64x_cpld345_attributes[] = { +&sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_start.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_ports.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_id.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_interrupt.dev_attr.attr, + NULL +}; + +/* cpld 1 attributes group */ +static const struct attribute_group s9230_64x_cpld1_group = { + .attrs = s9230_64x_cpld1_attributes, +}; +/* cpld 2 attributes group */ +static const struct attribute_group s9230_64x_cpld2_group = { + .attrs = s9230_64x_cpld2_attributes, +}; +/* cpld 3/4/5 attributes group */ +static const struct attribute_group s9230_64x_cpld345_group = { + .attrs = s9230_64x_cpld345_attributes, +}; + +/* read access register from cpld data */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + + return sprintf(buf, "0x%x\n", reg); +} + +/* write access register to cpld data */ +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + + if (kstrtou8(buf, 0, ®) < 0) + return -EINVAL; + + data->access_reg = reg; + return count; +} + +/* read the value of access register in cpld data */ +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + int reg_val; + + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + + if (reg_val < 0) + return -1; + + return sprintf(buf, "0x%x\n", reg_val); +} + +/* wrtie the value to access register in cpld data */ +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ret = -EIO; + u8 reg = data->access_reg; + u8 reg_val; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, client, reg, reg_val); + + return count; +} + +/* get qsfp port start number of the cpld device */ +/* the start number use to tranlate qsfp port to cpld port */ +/* the cpld port use to access the qsfp port register in cpld */ +static ssize_t get_qsfp_port_start(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int port_base_num; + + if (attr->index == CPLD_PORT_START) { + if (data->index == cpld1) { + port_base_num = 1; + } else { + port_base_num = CPLD_1_PORT_NUM + + CPLD_2_PORT_NUM*(data->index - 1) + 1; + } + return sprintf(buf, "%d\n", port_base_num); + } + return -1; +} + +/* get total qsfp port which contain register in the cpld device */ +static ssize_t get_qsfp_ports(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ports; + + if (attr->index == CPLD_PORTS) { + if (data->index == cpld1) + ports = CPLD_1_PORT_NUM; + else + ports = CPLD_2_PORT_NUM; + return sprintf(buf, "%d\n", ports); + } + return -1; +} + +/* get cpdl version register value */ +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_VERSION) { + reg = CPLD_VERSION_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get cpdl id register value */ +static ssize_t read_cpld_id(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_ID) { + reg = CPLD_ID_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get board type register value */ +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BOARD_TYPE) { + reg = CPLD_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_EXT_BOARD_TYPE) { + reg = CPLD_EXT_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get qsfp port status register value */ +static ssize_t read_qsfp_port_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index >= CPLD_QSFP_PORT_STATUS_1 && + attr->index <= CPLD_QSFP_PORT_STATUS_13) { + reg = CPLD_QSFP_PORT_STATUS_BASE_REG + + (attr->index - CPLD_QSFP_PORT_STATUS_1); + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get qsfp port config register value */ +static ssize_t read_qsfp_port_config(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index >= CPLD_QSFP_PORT_CONFIG_1 && + attr->index <= CPLD_QSFP_PORT_CONFIG_13) { + reg = CPLD_QSFP_PORT_CONFIG_BASE_REG + + (attr->index - CPLD_QSFP_PORT_CONFIG_1); + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to qsfp port config register */ +static ssize_t write_qsfp_port_config(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index >= CPLD_QSFP_PORT_CONFIG_1 && + attr->index <= CPLD_QSFP_PORT_CONFIG_13) { + reg = CPLD_QSFP_PORT_CONFIG_BASE_REG + + (attr->index - CPLD_QSFP_PORT_CONFIG_1); + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get qsfp port interrupt register value */ +static ssize_t read_qsfp_port_interrupt(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_QSFP_PORT_INTERRUPT) { + reg = CPLD_QSFP_PORT_INTERRUPT_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get sfp port status register value */ +static ssize_t read_sfp_port_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_SFP_PORT_STATUS) { + reg = CPLD_SFP_PORT_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get sfp port config register value */ +static ssize_t read_sfp_port_config(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_SFP_PORT_CONFIG) { + reg = CPLD_SFP_PORT_CONFIG_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to sfp port config register */ +static ssize_t write_sfp_port_config(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_SFP_PORT_CONFIG) { + reg = CPLD_SFP_PORT_CONFIG_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get 10g mux config register value */ +static ssize_t read_10gmux_config(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_10GMUX_CONFIG) { + reg = CPLD_10GMUX_CONFIG_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to 10g mux config register */ +static ssize_t write_10gmux_config(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_10GMUX_CONFIG) { + reg = CPLD_10GMUX_CONFIG_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get bmc status register value */ +static ssize_t read_bmc_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BMC_STATUS) { + reg = CPLD_BMC_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get bmc watchdog register value */ +static ssize_t read_bmc_watchdog(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BMC_WATCHDOG) { + reg = CPLD_BMC_WATCHDOG_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to bmc watchdog register */ +static ssize_t write_bmc_watchdog(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_BMC_WATCHDOG) { + reg = CPLD_BMC_WATCHDOG_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get usb status register value */ +static ssize_t read_usb_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_USB_STATUS) { + reg = CPLD_USB_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* add valid cpld client to list */ +static void ingrasys_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = NULL; + + node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + if (!node) { + dev_info(&client->dev, + "Can't allocate cpld_client_node for index %d\n", + client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +/* remove exist cpld client in list */ +static void ingrasys_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + mutex_unlock(&list_lock); +} + +/* cpld drvier probe */ +static int ingrasys_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct cpld_data *data = NULL; + int ret = -EPERM; + int err; + int idx; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* init cpld data for client */ + i2c_set_clientdata(client, data); + mutex_init(&data->access_lock); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_info(&client->dev, + "i2c_check_functionality failed (0x%x)\n", + client->addr); + status = -EIO; + goto exit; + } + + /* get cpld id from device */ + ret = i2c_smbus_read_byte_data(client, CPLD_ID_REG); + + if (ret < 0) { + dev_info(&client->dev, + "fail to get cpld id (0x%x) at addr (0x%x)\n", + CPLD_ID_REG, client->addr); + status = -EIO; + goto exit; + } + + CPLD_ID_ID_GET(ret, idx); + + if (INVALID(idx, cpld1, cpld5)) { + dev_info(&client->dev, + "cpld id %d(device) not valid\n", idx); + //status = -EPERM; + //goto exit; + } + +#if 0 + /* change client name for each cpld with index */ + snprintf(client->name, sizeof(client->name), "%s_%d", client->name, + data->index); +#endif + + data->index = dev_id->driver_data; + + /* register sysfs hooks for different cpld group */ + dev_info(&client->dev, "probe cpld with index %d\n", data->index); + switch (data->index) { + case cpld1: + status = sysfs_create_group(&client->dev.kobj, + &s9230_64x_cpld1_group); + break; + case cpld2: + status = sysfs_create_group(&client->dev.kobj, + &s9230_64x_cpld2_group); + break; + case cpld3: + case cpld4: + case cpld5: + status = sysfs_create_group(&client->dev.kobj, + &s9230_64x_cpld345_group); + break; + default: + status = -EINVAL; + } + + if (status) + goto exit; + + dev_info(&client->dev, "chip found\n"); + + /* add probe chip to client list */ + ingrasys_i2c_cpld_add_client(client); + + return 0; +exit: + sysfs_remove_group(&client->dev.kobj, &s9230_64x_cpld345_group); + return status; +} + +/* cpld drvier remove */ +static int ingrasys_i2c_cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + + switch (data->index) { + case cpld1: + sysfs_remove_group(&client->dev.kobj, &s9230_64x_cpld1_group); + break; + case cpld2: + sysfs_remove_group(&client->dev.kobj, &s9230_64x_cpld2_group); + break; + case cpld3: + case cpld4: + case cpld5: + sysfs_remove_group(&client->dev.kobj, + &s9230_64x_cpld345_group); + break; + } + + ingrasys_i2c_cpld_remove_client(client); + return 0; +} + +MODULE_DEVICE_TABLE(i2c, ingrasys_i2c_cpld_id); + +static struct i2c_driver ingrasys_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ingrasys_i2c_cpld", + }, + .probe = ingrasys_i2c_cpld_probe, + .remove = ingrasys_i2c_cpld_remove, + .id_table = ingrasys_i2c_cpld_id, + .address_list = cpld_i2c_addr, +}; + +/* provid cpld register read */ +/* cpld_idx indicate the index of cpld device */ +int ingrasys_i2c_cpld_read(u8 cpld_idx, + u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + struct cpld_data *data; + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + data = i2c_get_clientdata(cpld_node->client); + if (data->index == cpld_idx) { + DEBUG_PRINT("cpld_idx=%d, read reg 0x%02x", + cpld_idx, reg); + I2C_READ_BYTE_DATA(ret, &data->access_lock, + cpld_node->client, reg); + DEBUG_PRINT("cpld_idx=%d, read reg 0x%02x = 0x%02x", + cpld_idx, reg, ret); + break; + } + } + + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_read); + +/* provid cpld register write */ +/* cpld_idx indicate the index of cpld device */ +int ingrasys_i2c_cpld_write(u8 cpld_idx, + u8 reg, + u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + struct cpld_data *data; + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + data = i2c_get_clientdata(cpld_node->client); + + if (data->index == cpld_idx) { + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + cpld_node->client, + reg, value); + DEBUG_PRINT("cpld_idx=%d, write reg 0x%02x val 0x%02x, ret=%d", + cpld_idx, reg, value, ret); + break; + } + } + + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_write); + +/* provid qsfp port status register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_qsfp_port_status_val(u8 port_num) +{ + u8 cpld_idx, cpld_port, reg; + int reg_val; + + if (INVALID(port_num, QSFP_MIN_PORT_NUM, QSFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + QSFP_TO_CPLD_IDX(port_num, cpld_idx, cpld_port); + reg = QSFP_PORT_STATUS_REG(cpld_port); + DEBUG_PRINT("port_num=%d, cpld_idx=%d, cpld_port=%d, reg=0x%x", + port_num, cpld_idx, cpld_port, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_qsfp_port_status_val); + +/* provid qsfp port config register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_qsfp_port_config_val(u8 port_num) +{ + u8 cpld_idx, cpld_port, reg; + int reg_val; + + if (INVALID(port_num, QSFP_MIN_PORT_NUM, QSFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + QSFP_TO_CPLD_IDX(port_num, cpld_idx, cpld_port); + reg = QSFP_PORT_CONFIG_REG(cpld_port); + DEBUG_PRINT("port_num=%d, cpld_idx=%d, cpld_port=%d, reg=0x%x", + port_num, cpld_idx, cpld_port, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_qsfp_port_config_val); + +/* provid qsfp port config register write */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_set_qsfp_port_config_val(u8 port_num, + u8 reg_val) +{ + u8 cpld_idx, cpld_port, reg, ret; + + if (INVALID(port_num, QSFP_MIN_PORT_NUM, QSFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + QSFP_TO_CPLD_IDX(port_num, cpld_idx, cpld_port); + reg = QSFP_PORT_CONFIG_REG(cpld_port); + DEBUG_PRINT("port_num=%d, cpld_idx=%d, cpld_port=%d, reg=0x%x", + port_num, cpld_idx, cpld_port, reg); + ret = ingrasys_i2c_cpld_write(cpld_idx, reg, reg_val); + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_set_qsfp_port_config_val); + +/* provid sfp port status register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_sfp_port_status_val(u8 port_num) +{ + u8 cpld_idx, reg; + int reg_val; + + if (INVALID(port_num, SFP_MIN_PORT_NUM, SFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + SFP_TO_CPLD_IDX(port_num, cpld_idx); + reg = CPLD_SFP_PORT_STATUS_REG; + DEBUG_PRINT("port_num=%d, cpld_idx=%d, reg=0x%x", + port_num, cpld_idx, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_sfp_port_status_val); + +/* provid qsfp port config register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_sfp_port_config_val(u8 port_num) +{ + u8 cpld_idx, reg; + int reg_val; + + if (INVALID(port_num, SFP_MIN_PORT_NUM, SFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + SFP_TO_CPLD_IDX(port_num, cpld_idx); + reg = CPLD_SFP_PORT_CONFIG_REG; + DEBUG_PRINT("port_num=%d, cpld_idx=%d, reg=0x%x", + port_num, cpld_idx, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_sfp_port_config_val); + +/* provid qsfp port config register write */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_set_sfp_port_config_val(u8 port_num, + u8 reg_val) +{ + u8 cpld_idx, reg, ret; + + if (INVALID(port_num, SFP_MIN_PORT_NUM, SFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + SFP_TO_CPLD_IDX(port_num, cpld_idx); + reg = CPLD_SFP_PORT_CONFIG_REG; + DEBUG_PRINT("port_num=%d, cpld_idx=%d, reg=0x%x", + port_num, cpld_idx, reg); + ret = ingrasys_i2c_cpld_write(cpld_idx, reg, reg_val); + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_set_sfp_port_config_val); + +static int __init ingrasys_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&ingrasys_i2c_cpld_driver); +} + +static void __exit ingrasys_i2c_cpld_exit(void) +{ + i2c_del_driver(&ingrasys_i2c_cpld_driver); +} + +MODULE_AUTHOR("Leo Lin "); +MODULE_DESCRIPTION("ingrasys_i2c_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(ingrasys_i2c_cpld_init); +module_exit(ingrasys_i2c_cpld_exit); + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_i2c_cpld.h b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_i2c_cpld.h new file mode 100644 index 000000000000..e0e53174d675 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_i2c_cpld.h @@ -0,0 +1,223 @@ +/* header file for i2c cpld driver of ingrasys_s9230_64x + * + * Copyright (C) 2017 Ingrasys Technology Corporation. + * Leo Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef INGRASYS_S9230_64X_I2C_CPLD_H +#define INGRASYS_S9230_64X_I2C_CPLD_H + +/* CPLD device index value */ +enum cpld_id { + cpld1, + cpld2, + cpld3, + cpld4, + cpld5 +}; + +/* port number on CPLD */ +#define CPLD_1_PORT_NUM 12 +#define CPLD_2_PORT_NUM 13 + +/* QSFP port number */ +#define QSFP_MAX_PORT_NUM 64 +#define QSFP_MIN_PORT_NUM 1 + +/* SFP+ port number */ +#define SFP_MAX_PORT_NUM 2 +#define SFP_MIN_PORT_NUM 1 + + +/* CPLD registers */ +#define CPLD_BOARD_TYPE_REG 0x0 +#define CPLD_EXT_BOARD_TYPE_REG 0x7 +#define CPLD_VERSION_REG 0x1 +#define CPLD_ID_REG 0x2 +#define CPLD_QSFP_PORT_STATUS_BASE_REG 0x20 +#define CPLD_QSFP_PORT_CONFIG_BASE_REG 0x30 +#define CPLD_QSFP_PORT_INTERRUPT_REG 0x40 +#define CPLD_SFP_PORT_STATUS_REG 0x2F +#define CPLD_SFP_PORT_CONFIG_REG 0x3F +#define CPLD_QSFP_PORT_INTERRUPT_REG 0x40 +#define CPLD_10GMUX_CONFIG_REG 0x41 +#define CPLD_BMC_STATUS_REG 0x42 +#define CPLD_BMC_WATCHDOG_REG 0x43 +#define CPLD_USB_STATUS_REG 0x44 +#define CPLD_REST_CONTROL_REG 0x4A + + +/* bit definition for register value */ +enum CPLD_QSFP_PORT_STATUS_BITS { + CPLD_QSFP_PORT_STATUS_INT_BIT, + CPLD_QSFP_PORT_STATUS_ABS_BIT, +}; +enum CPLD_QSFP_PORT_CONFIG_BITS { + CPLD_QSFP_PORT_CONFIG_RESET_BIT, + CPLD_QSFP_PORT_CONFIG_RESERVE_BIT, + CPLD_QSFP_PORT_CONFIG_LPMODE_BIT, +}; +enum CPLD_SFP_PORT_STATUS_BITS { + CPLD_SFP_PORT_STATUS_PRESENT_BIT, + CPLD_SFP_PORT_STATUS_TXFAULT_BIT, + CPLD_SFP_PORT_STATUS_RXLOS_BIT, +}; +enum CPLD_SFP_PORT_CONFIG_BITS { + CPLD_SFP_PORT_CONFIG_TXDIS_BIT, + CPLD_SFP_PORT_CONFIG_RS_BIT, + CPLD_SFP_PORT_CONFIG_TS_BIT, +}; +enum CPLD_10GMUX_CONFIG_BITS { + CPLD_10GMUX_CONFIG_ENSMB_BIT, + CPLD_10GMUX_CONFIG_ENINPUT_BIT, + CPLD_10GMUX_CONFIG_SEL1_BIT, + CPLD_10GMUX_CONFIG_SEL0_BIT, +}; +enum CPLD_BMC_WATCHDOG_BITS { + CPLD_10GMUX_CONFIG_ENTIMER_BIT, + CPLD_10GMUX_CONFIG_TIMEOUT_BIT, +}; +enum CPLD_RESET_CONTROL_BITS { + CPLD_RESET_CONTROL_SWRST_BIT, + CPLD_RESET_CONTROL_CP2104RST_BIT, + CPLD_RESET_CONTROL_82P33814RST_BIT, + CPLD_RESET_CONTROL_BMCRST_BIT, +}; + +/* bit field structure for register value */ +struct cpld_reg_board_type_t { + u8 build_rev:2; + u8 hw_rev:2; + u8 board_id:4; +}; + +struct cpld_reg_version_t { + u8 revision:6; + u8 release:1; + u8 reserve:1; +}; + +struct cpld_reg_id_t { + u8 id:3; + u8 release:5; +}; + +/* common manipulation */ +#define INVALID(i, min, max) ((i < min) || (i > max) ? 1u : 0u) +#define READ_BIT(val, bit) ((0u == (val & (1<bf_name) +#define READ_BF_1(bf_struct, val, bf_name, bf_value) \ + bf_struct bf; \ + bf.data = val; \ + bf_value = bf.bf_name +#define BOARD_TYPE_BUILD_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, build_rev, res) +#define BOARD_TYPE_HW_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, hw_rev, res) +#define BOARD_TYPE_BOARD_ID_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, board_id, res) +#define CPLD_VERSION_REV_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, revision, res) +#define CPLD_VERSION_REL_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, release, res) +#define CPLD_ID_ID_GET(val, res) \ + READ_BF(cpld_reg_id_t, val, id, res) +#define CPLD_ID_REL_GET(val, res) \ + READ_BF(cpld_reg_id_t, val, release, res) +/* QSFP/SFP registers manipulation */ +#define QSFP_TO_CPLD_IDX(qsfp_port, cpld_index, cpld_port) \ +{ \ + if (QSFP_MIN_PORT_NUM <= qsfp_port && qsfp_port <= CPLD_1_PORT_NUM) { \ + cpld_index = cpld1; \ + cpld_port = qsfp_port - 1; \ + } else if (CPLD_1_PORT_NUM < qsfp_port \ + && qsfp_port <= QSFP_MAX_PORT_NUM) { \ + cpld_index = cpld2 + (qsfp_port - 1 - CPLD_1_PORT_NUM) \ + / CPLD_2_PORT_NUM; \ + cpld_port = (qsfp_port - 1 - CPLD_1_PORT_NUM) % \ + CPLD_2_PORT_NUM; \ + } else { \ + cpld_index = 0; \ + cpld_port = 0; \ + } \ +} +#define SFP_TO_CPLD_IDX(sfp_port, cpld_index) \ + (cpld_index = sfp_port - SFP_MIN_PORT_NUM) +#define QSFP_PORT_STATUS_REG(cpld_port) \ + (CPLD_QSFP_PORT_STATUS_BASE_REG + cpld_port) +#define QSFP_PORT_CONFIG_REG(cpld_port) \ + (CPLD_QSFP_PORT_CONFIG_BASE_REG + cpld_port) +#define QSFP_PORT_INT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_INT_BIT) +#define QSFP_PORT_ABS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_ABS_BIT) +#define QSFP_PORT_RESET_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_RESET_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_RESET_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_LPMODE_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define SFP_PORT_PRESENT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_PRESENT_BIT) + +#define SFP_PORT_TXFAULT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_TXFAULT_BIT) +#define SFP_PORT_RXLOS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_RXLOS_BIT) +#define SFP_PORT_TXDIS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TXDIS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_TXDIS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_RS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) + +/* CPLD access functions */ +extern int ingrasys_i2c_cpld_get_qsfp_port_status_val(u8 port_num); +extern int ingrasys_i2c_cpld_get_qsfp_port_config_val(u8 port_num); +extern int ingrasys_i2c_cpld_set_qsfp_port_config_val(u8 port_num, u8 reg_val); +extern int ingrasys_i2c_cpld_get_sfp_port_status_val(u8 port_num); +extern int ingrasys_i2c_cpld_get_sfp_port_config_val(u8 port_num); +extern int ingrasys_i2c_cpld_set_sfp_port_config_val(u8 port_num, u8 reg_val); +extern u8 fp_port_to_phy_port(u8 fp_port); +#endif + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_platform.h b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_platform.h new file mode 100644 index 000000000000..a14853fdae9c --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_platform.h @@ -0,0 +1,148 @@ +#ifndef _S9230_64X_PLATFORM_H +#define _S9230_64X_PLATFORM_H + +#include + +// remove debug before release +#define DEBUG + +enum bus_order { + I2C_BUS_MAIN, + MUX_9548_0_CH0, + MUX_9548_0_CH1, + MUX_9548_0_CH2, + MUX_9548_0_CH3, + MUX_9548_0_CH4, + MUX_9548_0_CH5, + MUX_9548_0_CH6, + MUX_9548_0_CH7, + MUX_9548_1_CH0, + MUX_9548_1_CH1, + MUX_9548_1_CH2, + MUX_9548_1_CH3, + MUX_9548_1_CH4, + MUX_9548_1_CH5, + MUX_9548_1_CH6, + MUX_9548_1_CH7, + MUX_9546_0_CH0, + MUX_9546_0_CH1, + MUX_9546_0_CH2, + MUX_9546_0_CH3, + MUX_9546_1_CH0, + MUX_9546_1_CH1, + MUX_9546_1_CH2, + MUX_9546_1_CH3, + MUX_9548_2_CH0, + MUX_9548_2_CH1, + MUX_9548_2_CH2, + MUX_9548_2_CH3, + MUX_9548_2_CH4, + MUX_9548_2_CH5, + MUX_9548_2_CH6, + MUX_9548_2_CH7, + MUX_9548_3_CH0, + MUX_9548_3_CH1, + MUX_9548_3_CH2, + MUX_9548_3_CH3, + MUX_9548_3_CH4, + MUX_9548_3_CH5, + MUX_9548_3_CH6, + MUX_9548_3_CH7, + MUX_9548_4_CH0, + MUX_9548_4_CH1, + MUX_9548_4_CH2, + MUX_9548_4_CH3, + MUX_9548_4_CH4, + MUX_9548_4_CH5, + MUX_9548_4_CH6, + MUX_9548_4_CH7, + MUX_9548_5_CH0, + MUX_9548_5_CH1, + MUX_9548_5_CH2, + MUX_9548_5_CH3, + MUX_9548_5_CH4, + MUX_9548_5_CH5, + MUX_9548_5_CH6, + MUX_9548_5_CH7, + MUX_9548_6_CH0, + MUX_9548_6_CH1, + MUX_9548_6_CH2, + MUX_9548_6_CH3, + MUX_9548_6_CH4, + MUX_9548_6_CH5, + MUX_9548_6_CH6, + MUX_9548_6_CH7, + MUX_9548_7_CH0, + MUX_9548_7_CH1, + MUX_9548_7_CH2, + MUX_9548_7_CH3, + MUX_9548_7_CH4, + MUX_9548_7_CH5, + MUX_9548_7_CH6, + MUX_9548_7_CH7, + MUX_9548_8_CH0, + MUX_9548_8_CH1, + MUX_9548_8_CH2, + MUX_9548_8_CH3, + MUX_9548_8_CH4, + MUX_9548_8_CH5, + MUX_9548_8_CH6, + MUX_9548_8_CH7, + MUX_9548_9_CH0, + MUX_9548_9_CH1, + MUX_9548_9_CH2, + MUX_9548_9_CH3, + MUX_9548_9_CH4, + MUX_9548_9_CH5, + MUX_9548_9_CH6, + MUX_9548_9_CH7, + MUX_9548_10_CH0, + MUX_9548_10_CH1, + MUX_9548_10_CH2, + MUX_9548_10_CH3, + MUX_9548_10_CH4, + MUX_9548_10_CH5, + MUX_9548_10_CH6, + MUX_9548_10_CH7, +}; + +#define I2C_ADDR_MUX_9555_0 (0x20) +#define I2C_ADDR_MUX_9555_1 (0x24) +#define I2C_ADDR_MUX_9555_2 (0x25) +#define I2C_ADDR_MUX_9555_3 (0x26) +#define I2C_ADDR_MUX_9539_0 (0x76) +#define I2C_ADDR_MUX_9539_1 (0x76) +#define I2C_BUS_FAN_STATUS (I2C_BUS_MAIN) +#define I2C_BUS_SYS_LED (MUX_9548_1_CH1) + +#define NUM_OF_I2C_MUX (11) +#define NUM_OF_CPLD (5) +#define NUM_OF_QSFP_PORT (64) +#define NUM_OF_SFP_PORT (2) +#define QSFP_EEPROM_I2C_ADDR (0x50) + +enum gpio_reg { + REG_PORT0_IN, + REG_PORT1_IN, + REG_PORT0_OUT, + REG_PORT1_OUT, + REG_PORT0_POL, + REG_PORT1_POL, + REG_PORT0_DIR, + REG_PORT1_DIR, +}; + +struct ing_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +struct i2c_init_data { + __u16 ch; + __u16 addr; + __u8 reg; + __u8 value; +}; + +#endif diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_psu.c b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_psu.c new file mode 100644 index 000000000000..694b57bd748d --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_psu.c @@ -0,0 +1,388 @@ +/* + * S9230-64x PSU driver + * + * Copyright (C) 2017 Ingrasys, 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 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s9230_64x_platform.h" + +static ssize_t show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf); +static struct s9230_psu_data *s9230_psu_update_status(struct device *dev); +static struct s9230_psu_data *s9230_psu_update_eeprom(struct device *dev); +static int s9230_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len); + + +#define DRIVER_NAME "psu" + +// Addresses scanned +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* PSU EEPROM SIZE */ +#define EEPROM_SZ 256 +#define READ_EEPROM 1 +#define NREAD_EEPROM 0 + +static struct i2c_client pca9555_client; + +/* pca9555 gpio pin mapping */ +#define PSU2_PWROK 0 +#define PSU2_PRSNT_L 1 +#define PSU2_PWRON_L 2 +#define PSU1_PWROK 3 +#define PSU1_PRSNT_L 4 +#define PSU1_PWRON_L 5 +#define TMP_75_INT_L 6 + +/* Driver Private Data */ +struct s9230_psu_data { + struct mutex lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + s32 status; /* IO expander value */ + char eeprom[EEPROM_SZ]; /* psu eeprom data */ + char psuABS; /* PSU absent */ + char psuPG; /* PSU power good */ +}; + +enum psu_index +{ + s9230_psu1, + s9230_psu2 +}; + +/* + * display power good attribute + */ +static ssize_t +show_psu_pg(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9230_psu_data *data = s9230_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuPG; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + +/* + * display power absent attribute + */ +static ssize_t +show_psu_abs(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9230_psu_data *data = s9230_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuABS; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + + +/* + * sysfs attributes for psu + */ +static DEVICE_ATTR(psu_pg, S_IRUGO, show_psu_pg, NULL); +static DEVICE_ATTR(psu_abs, S_IRUGO, show_psu_abs, NULL); +static DEVICE_ATTR(psu_eeprom, S_IRUGO, show_psu_eeprom, NULL); + +static struct attribute *s9230_psu_attributes[] = { + &dev_attr_psu_pg.attr, + &dev_attr_psu_abs.attr, + &dev_attr_psu_eeprom.attr, + NULL +}; + +/* + * display psu eeprom content + */ +static ssize_t +show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct s9230_psu_data *data = s9230_psu_update_eeprom(dev); + + memcpy(buf, (char *)data->eeprom, EEPROM_SZ); + return EEPROM_SZ; +} + +static const struct attribute_group s9230_psu_group = { + .attrs = s9230_psu_attributes, +}; + +/* + * check gpio expander is accessible + */ +static int +pca9555_detect(struct i2c_client *client) +{ + if (i2c_smbus_read_byte_data(client, REG_PORT0_DIR) < 0) { + return -ENODEV; + } + + return 0; +} + +/* + * client address init + */ +static void +i2c_devices_client_address_init(struct i2c_client *client) +{ + pca9555_client = *client; + pca9555_client.addr = 0x25; +} + +static int +s9230_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct s9230_psu_data *data; + int status, err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct s9230_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct s9230_psu_data)); + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + i2c_devices_client_address_init(client); + + err = pca9555_detect(&pca9555_client); + if (err) { + return err; + } + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &s9230_psu_group); + if (status) { + goto exit_free; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &s9230_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int +s9230_psu_remove(struct i2c_client *client) +{ + struct s9230_psu_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &s9230_psu_group); + kfree(data); + + return 0; +} + + +/* + * psu eeprom read utility + */ +static int +s9230_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len) +{ + int i=0, ret=0; + int blk_max = 32; //max block read size + + /* read eeprom, 32 * 8 = 256 bytes */ + for (i=0; i < EEPROM_SZ/blk_max; i++) { + ret = i2c_smbus_read_i2c_block_data(client, (i*blk_max), blk_max, + data + (i*blk_max)); + if (ret < 0) { + return ret; + } + } + return ret; +} + +/* + * update eeprom content + */ +static struct s9230_psu_data +*s9230_psu_update_eeprom(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9230_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + if (time_after(jiffies, data->last_updated + 300 * HZ) + || !data->valid) { + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9230_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + /* Read eeprom */ + if (!data->psuABS) { + //clear local eeprom data + memset(data->eeprom, 0, EEPROM_SZ); + + //read eeprom + status = s9230_psu_read_block(client, 0, data->eeprom, + ARRAY_SIZE(data->eeprom)); + + if (status < 0) { + memset(data->eeprom, 0, EEPROM_SZ); + dev_err(&client->dev, "Read eeprom failed, status=(%d)\n", status); + } else { + data->valid = 1; + } + } else { + memset(data->eeprom, 0, EEPROM_SZ); + } + data->last_updated = jiffies; + } + + mutex_unlock(&data->lock); + + return data; +} + +/* + * update psu status + */ +static struct s9230_psu_data +*s9230_psu_update_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9230_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9230_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + mutex_unlock(&data->lock); + + return data; +} + +static const struct i2c_device_id s9230_psu_id[] = { + { "psu1", s9230_psu1 }, + { "psu2", s9230_psu2 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, s9230_psu_id); + +static struct i2c_driver s9230_psu_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = s9230_psu_probe, + .remove = s9230_psu_remove, + .id_table = s9230_psu_id, + .address_list = normal_i2c, +}; + +static int __init s9230_psu_init(void) +{ + return i2c_add_driver(&s9230_psu_driver); +} + +static void __exit s9230_psu_exit(void) +{ + i2c_del_driver(&s9230_psu_driver); +} + +module_init(s9230_psu_init); +module_exit(s9230_psu_exit); + +MODULE_AUTHOR("Jason Tsai "); +MODULE_DESCRIPTION("S9230-64X psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/service/qsfp-monitor.service b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/service/qsfp-monitor.service new file mode 100644 index 000000000000..cf4a6a8ad41e --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s9230-64x-monitor.service +After=s9230-64x-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/service/s9230-64x-monitor.service b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/service/s9230-64x-monitor.service new file mode 100644 index 000000000000..5caf968e659a --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/service/s9230-64x-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s9230_64x_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/i2c_utils.sh b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/i2c_utils.sh new file mode 100755 index 000000000000..e899e64a7c3b --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/i2c_utils.sh @@ -0,0 +1,1850 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, 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 . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +SFP_PORT=${2} +QSFP_ACTION=${2} +SFP_ACTION=${2} +MB_EEPROM_ACTION=${2} +TARGET_10G_MUX=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_I801_DEVICE=0 + +# PCA9548#0 0x70 +NUM_MUX_9548_0_CH0=$(( ${NUM_I801_DEVICE} + 1 )) # CPLD1 +NUM_MUX_9548_0_CH1=$(( ${NUM_I801_DEVICE} + 2 )) # CPLD2 +NUM_MUX_9548_0_CH2=$(( ${NUM_I801_DEVICE} + 3 )) # CPLD3 +NUM_MUX_9548_0_CH3=$(( ${NUM_I801_DEVICE} + 4 )) # CPLD4 +NUM_MUX_9548_0_CH4=$(( ${NUM_I801_DEVICE} + 5 )) # CPLD5 +NUM_MUX_9548_0_CH5=$(( ${NUM_I801_DEVICE} + 6 )) # LM75_1 LM75_2 +NUM_MUX_9548_0_CH6=$(( ${NUM_I801_DEVICE} + 7 )) # LM75_3 LM75_4 + +# PCA9548#1 0x73 +NUM_MUX_9548_1_CH0=$(( ${NUM_I801_DEVICE} + 9 )) # UCD9090 +NUM_MUX_9548_1_CH1=$(( ${NUM_I801_DEVICE} + 10 )) # PCA9539 0x76 for FP LED & HW ID +NUM_MUX_9548_1_CH2=$(( ${NUM_I801_DEVICE} + 11 )) # PCA9539 0x76 for SYS control +NUM_MUX_9548_1_CH4=$(( ${NUM_I801_DEVICE} + 13 )) # 10G Mux +NUM_MUX_9548_1_CH7=$(( ${NUM_I801_DEVICE} + 16 )) # HWM & TMP75 on BMC + +# PCA9546#0 0X72 +NUM_MUX_9546_0_CH0=$(( ${NUM_I801_DEVICE} + 17 )) # PSU1 0x58 +NUM_MUX_9546_0_CH1=$(( ${NUM_I801_DEVICE} + 18 )) # PSU2 0x58 +NUM_MUX_9546_0_CH2=$(( ${NUM_I801_DEVICE} + 19 )) # PCA9548#2 0x71 +NUM_MUX_9546_0_CH3=$(( ${NUM_I801_DEVICE} + 20 )) # PCA9546#1 0x71 + +# PCA9546#1 0X71 +NUM_MUX_9546_1_CH0=$(( ${NUM_I801_DEVICE} + 21 )) # SFP0 EEPROM 0x50 +NUM_MUX_9546_1_CH1=$(( ${NUM_I801_DEVICE} + 22 )) # SFP1 EEPROM 0x50 + +# PCA9548#2 0X71 +NUM_MUX_9548_2_CH0=$(( ${NUM_I801_DEVICE} + 25 )) # PCA9548#3 0x74 +NUM_MUX_9548_2_CH1=$(( ${NUM_I801_DEVICE} + 26 )) # PCA9548#4 0x74 +NUM_MUX_9548_2_CH2=$(( ${NUM_I801_DEVICE} + 27 )) # PCA9548#5 0x74 +NUM_MUX_9548_2_CH3=$(( ${NUM_I801_DEVICE} + 28 )) # PCA9548#6 0x74 +NUM_MUX_9548_2_CH4=$(( ${NUM_I801_DEVICE} + 29 )) # PCA9548#7 0x74 +NUM_MUX_9548_2_CH5=$(( ${NUM_I801_DEVICE} + 30 )) # PCA9548#8 0x74 +NUM_MUX_9548_2_CH6=$(( ${NUM_I801_DEVICE} + 31 )) # PCA9548#9 0x74 +NUM_MUX_9548_2_CH7=$(( ${NUM_I801_DEVICE} + 32 )) # PCA9548#10 0x74 + +# PCA9548#3~10 0X74 +NUM_MUX_9548_3_CH0=$(( ${NUM_I801_DEVICE} + 33 )) # QSFP 0 EEPROM +NUM_MUX_9548_4_CH0=$(( ${NUM_I801_DEVICE} + 41 )) # QSFP 8 EEPROM +NUM_MUX_9548_5_CH0=$(( ${NUM_I801_DEVICE} + 49 )) # QSFP 16 EEPROM +NUM_MUX_9548_6_CH0=$(( ${NUM_I801_DEVICE} + 57 )) # QSFP 24 EEPROM +NUM_MUX_9548_7_CH0=$(( ${NUM_I801_DEVICE} + 65 )) # QSFP 32 EEPROM +NUM_MUX_9548_8_CH0=$(( ${NUM_I801_DEVICE} + 73 )) # QSFP 40 EEPROM +NUM_MUX_9548_9_CH0=$(( ${NUM_I801_DEVICE} + 81 )) # QSFP 48 EEPROM +NUM_MUX_9548_10_CH0=$(( ${NUM_I801_DEVICE} + 89 )) # QSFP 56 EEPROM + +# MUX Alias +I2C_BUS_MAIN=${NUM_I801_DEVICE} +I2C_BUS_HWM=${NUM_MUX_9548_1_CH7} +I2C_BUS_FAN_STATUS=${I2C_BUS_MAIN} +I2C_BUS_SYS_LED=${NUM_MUX_9548_1_CH1} +I2C_BUS_HW_ID=${NUM_MUX_9548_1_CH1} +I2C_BUS_BMC_HW_ID=${I2C_BUS_MAIN} +I2C_BUS_PSU_STAT=${I2C_BUS_MAIN} +I2C_BUS_FANTRAY_LED=${I2C_BUS_MAIN} +I2C_BUS_MB_EEPROM=${I2C_BUS_MAIN} +I2C_BUS_CB_EEPROM=${I2C_BUS_MAIN} +I2C_BUS_PSU1_EEPROM=${NUM_MUX_9546_0_CH1} +I2C_BUS_PSU2_EEPROM=${NUM_MUX_9546_0_CH0} +I2C_BUS_CPLD1=${NUM_MUX_9548_0_CH0} +I2C_BUS_CPLD2=${NUM_MUX_9548_0_CH1} +I2C_BUS_CPLD3=${NUM_MUX_9548_0_CH2} +I2C_BUS_CPLD4=${NUM_MUX_9548_0_CH3} +I2C_BUS_CPLD5=${NUM_MUX_9548_0_CH4} +I2C_BUS_10GMUX=${NUM_MUX_9548_1_CH4} + +# I2C BUS path +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +# TODO: need to verify HWM deivce path after board ready +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon7" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_MUX_9548_0_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH0}" +PATH_MUX_9548_0_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH1}" +PATH_MUX_9548_0_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH2}" +PATH_MUX_9548_0_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH3}" +PATH_MUX_9548_0_CH4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH4}" +PATH_MUX_9548_0_CH5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH5}" +PATH_MUX_9548_0_CH6="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH6}" +PATH_MUX_9548_1_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH0}" +PATH_MUX_9548_1_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH1}" +PATH_MUX_9548_1_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH2}" +PATH_MUX_9548_1_CH7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH7}" +PATH_MUX_9546_0_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH0}" +PATH_MUX_9546_0_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH1}" +PATH_MUX_9546_0_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH2}" +PATH_MUX_9546_0_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH3}" +PATH_MUX_9546_1_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_1_CH0}" +PATH_MUX_9546_1_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_1_CH1}" +PATH_MUX_9548_2_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH0}" +PATH_MUX_9548_2_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH1}" +PATH_MUX_9548_2_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH2}" +PATH_MUX_9548_2_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH3}" +PATH_MUX_9548_2_CH4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH4}" +PATH_MUX_9548_2_CH5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH5}" +PATH_MUX_9548_2_CH6="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH6}" +PATH_MUX_9548_2_CH7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH7}" +PATH_MUX_9548_3_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_3_CH0}" +PATH_MUX_9548_4_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_4_CH0}" +PATH_MUX_9548_5_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_5_CH0}" +PATH_MUX_9548_6_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_6_CH0}" +PATH_MUX_9548_7_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_7_CH0}" +PATH_MUX_9548_8_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_8_CH0}" +PATH_MUX_9548_9_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_9_CH0}" +PATH_MUX_9548_10_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_10_CH0}" +PATH_CPLD1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD1}" +PATH_CPLD2_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD2}" +PATH_CPLD3_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD3}" +PATH_CPLD4_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD4}" +PATH_CPLD5_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD5}" +PATH_10GMUX=${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_10GMUX} + + +# I2C Address +### I2C MUX +I2C_ADDR_MUX_9548_0=0x70 +I2C_ADDR_MUX_9548_1=0x73 +I2C_ADDR_MUX_9546_0=0x72 +I2C_ADDR_MUX_9546_1=0x71 +I2C_ADDR_MUX_9548_2=0x71 +I2C_ADDR_MUX_9548_3=0x74 +I2C_ADDR_MUX_9548_4=0x74 +I2C_ADDR_MUX_9548_5=0x74 +I2C_ADDR_MUX_9548_6=0x74 +I2C_ADDR_MUX_9548_7=0x74 +I2C_ADDR_MUX_9548_8=0x74 +I2C_ADDR_MUX_9548_9=0x74 +I2C_ADDR_MUX_9548_10=0x74 + +### GPIO Expander +I2C_ADDR_MUX_9539_0=0x76 # LED & HW ID +I2C_ADDR_MUX_9539_1=0x76 # SYS config +I2C_ADDR_MUX_9539_2=0x77 # on CPU board, STATUS and ERR from CPLD +I2C_ADDR_MUX_9555_0=0x20 # on FAN board, fan status and led config +I2C_ADDR_MUX_9555_1=0x24 # on BMC board, INT and HW ID +I2C_ADDR_MUX_9555_2=0x25 # on BMC board, PSU status +I2C_ADDR_MUX_9555_3=0x26 # on BMC board, RST and SEL +I2C_ADDR_MUX_9555_3=0x26 # on BMC board, RST and SEL + + +### peripheral +I2C_ADDR_MB_EEPROM=0x55 # on main board +I2C_ADDR_CB_EEPROM=0x51 # on cpu board +I2C_ADDR_UCD9090=0x34 +I2C_ADDR_W83795=0x2F +I2C_ADDR_PSU1_EEPROM=0x50 +I2C_ADDR_PSU2_EEPROM=0x50 +I2C_ADDR_LM75_1=0x4D # Rear Panel +I2C_ADDR_LM75_2=0x4E # Rear MAC +I2C_ADDR_LM75_3=0x4D # Front Panel +I2C_ADDR_LM75_4=0x4E # Front MAC +I2C_ADDR_TMP75_CB=0x4F # on cpu board +I2C_ADDR_TMP75_BB=0x4A # on bmc board +I2C_ADDR_QSFP_EEPROM=0x50 +I2C_ADDR_SFP_EEPROM=0x50 +I2C_ADDR_CPLD=0x33 +I2C_ADDR_10GMUX=0x67 + +#sysfs +PATH_SYSFS_PSU1="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU1_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU1_EEPROM)" +PATH_SYSFS_PSU2="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU2_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU2_EEPROM)" + +#ACTIVE LOW enable flag +ACTIVE_LOW_EN=1 +ACTIVE_HIGH_EN=0 +#GPIO Direction In/Out +DIR_IN=in +DIR_OUT=out + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +# IO expander register +# direction +REG_PORT0_DIR=6 +REG_PORT1_DIR=7 +# polarity +REG_PORT0_POL=4 +REG_PORT1_POL=5 +# output +REG_PORT0_OUT=2 +REG_PORT1_OUT=3 +# input +REG_PORT0_IN=0 +REG_PORT1_IN=1 + +# qsfp port number range +MIN_QSFP_PORT_NUM=1 +MAX_QSFP_PORT_NUM=64 + +# sfp+ port number range +MIN_SFP_PORT_NUM=1 +MAX_SFP_PORT_NUM=2 + +# CPLD access +# port status +CPLD_QSFP_STATUS_KEY=cpld_qsfp_port_status +CPLD_SFP_STATUS_KEY=cpld_sfp_port_status +# bit define +CPLD_QSFP_STATUS_ABS_BIT=1 +CPLD_SFP_STATUS_PRES_BIT=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_fan_speed_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_cb_eeprom_get" + #echo " : ${0} i2c_eeprom_sync" + echo " : ${0} i2c_qsfp_eeprom_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_sfp_eeprom_get [${MIN_SFP_PORT_NUM}-${MAX_SFP_PORT_NUM}]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_sfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_cb_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_sfp_status_get [${MIN_SFP_PORT_NUM}-${MAX_SFP_PORT_NUM}]" + echo " : ${0} i2c_qsfp_type_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_sfp_type_get [${MIN_SFP_PORT_NUM}-${MAX_SFP_PORT_NUM}]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_bmc_board_type_get" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber" + echo " : ${0} i2c_fan_led green|amber|off" + echo " : ${0} i2c_psu1_led green|amber|off" + echo " : ${0} i2c_psu2_led green|amber|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo " : ${0} i2c_10g_mux cpu|fp" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +#logical(front panel) to physical (falcon core) port mapping +function _port_logic2phy { + + local logic_port=$1 + local phy_port=0 + + if (( $logic_port >=1 && $logic_port <= 32 )) ; then + phy_port=$(( (logic_port-1)/2*4 + (logic_port-1)%2 + 1)) + elif (( $logic_port >=33 && $logic_port <= 64 )) ; then + phy_port=$(( (((logic_port-1)%32))/2*4 + (logic_port-1)%2 + 3)) + fi + + echo $phy_port +} + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + #rmmod i2c_ismt + _util_rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + # add MUX PCA9548#0 on I801, assume to be i2c-1~8 + if [ ! -e ${PATH_MUX_9548_0_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_0}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_0} already init." + fi + + # add MUX PCA9548#1 on I801, assume to be i2c-9~16 + if [ ! -e ${PATH_MUX_9548_1_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_1}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_1} already init." + fi + + # add MUX PCA9546#0 on I801, assume to be i2c-17~20 + if [ ! -e ${PATH_MUX_9546_0_CH0} ]; then + _retry "echo 'pca9546 ${I2C_ADDR_MUX_9546_0}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9546 ${I2C_ADDR_MUX_9546_0} already init." + fi + + # add MUX PCA9546#1 on PCA9546#0 CH3, assume to be i2c-21~24 + if [ ! -e ${PATH_MUX_9546_1_CH0} ]; then + _retry "echo 'pca9546 ${I2C_ADDR_MUX_9546_1}' > ${PATH_MUX_9546_0_CH3}/new_device" + else + echo "pca9546 ${I2C_ADDR_MUX_9546_1} already init." + fi + + # add MUX PCA9548#2 on PCA9546#0 CH2, assume to be i2c-25~32 + if [ ! -e ${PATH_MUX_9548_2_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_2}' > ${PATH_MUX_9546_0_CH2}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_2} already init." + fi + + # add MUX PCA9548#3 on PCA9548#2 CH0, assume to be i2c-33~40 + if [ ! -e ${PATH_MUX_9548_3_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_3}' > ${PATH_MUX_9548_2_CH0}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_3} already init." + fi + + # add MUX PCA9548#4 on PCA9548#2 CH1, assume to be i2c-41~48 + if [ ! -e ${PATH_MUX_9548_4_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_4}' > ${PATH_MUX_9548_2_CH1}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_4} already init." + fi + + # add MUX PCA9548#5 on PCA9548#2 CH2, assume to be i2c-49~56 + if [ ! -e ${PATH_MUX_9548_5_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_5}' > ${PATH_MUX_9548_2_CH2}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_5} already init." + fi + + # add MUX PCA9548#6 on PCA9548#2 CH3, assume to be i2c-57~64 + if [ ! -e ${PATH_MUX_9548_6_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_6}' > ${PATH_MUX_9548_2_CH3}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_6} already init." + fi + + # add MUX PCA9548#7 on PCA9548#2 CH4, assume to be i2c-65~72 + if [ ! -e ${PATH_MUX_9548_7_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_7}' > ${PATH_MUX_9548_2_CH4}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_7} already init." + fi + + # add MUX PCA9548#8 on PCA9548#2 CH5, assume to be i2c-73~80 + if [ ! -e ${PATH_MUX_9548_8_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_8}' > ${PATH_MUX_9548_2_CH5}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_8} already init." + fi + + # add MUX PCA9548#9 on PCA9548#2 CH6, assume to be i2c-81~88 + if [ ! -e ${PATH_MUX_9548_9_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_9}' > ${PATH_MUX_9548_2_CH6}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_9} already init." + fi + + # add MUX PCA9548#10 on PCA9548#2 CH7, assume to be i2c-89~96 + if [ ! -e ${PATH_MUX_9548_10_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_10}' > ${PATH_MUX_9548_2_CH7}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_10} already init." + fi + + _i2c_hwm_init + _util_rmmod eeprom + modprobe eeprom_mb + modprobe gpio-pca953x + _i2c_io_exp_init + _i2c_sensors_init + _i2c_cpld_init + _i2c_psu_init + + _i2c_qsfp_eeprom_init "new" + _i2c_sfp_eeprom_init "new" + _i2c_mb_eeprom_init "new" + _i2c_cb_eeprom_init "new" + _i2c_fan_speed_init + _i2c_led_psu_status_set + _i2c_led_fan_status_set + + # trun on sys led + echo "led_sys setup..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + echo "i2c deinit..." + for mod in coretemp jc42 w83795 eeprom eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_i801 ingrasys_s9230_64x_psu; + do + _util_rmmod $mod + done + echo "Done" +} + +function _i2c_cpld_init { + echo "CPLD init..." + _util_rmmod ingrasys_s9230_64x_i2c_cpld + modprobe ingrasys_s9230_64x_i2c_cpld + + # add cpld 1~5 to sysfs + for i in {1..5}; + do + local cpld_bus="I2C_BUS_CPLD${i}" + local cpld_path="PATH_CPLD${i}_DEVICE" + dev_path="${PATH_SYS_I2C_DEVICES}/${!cpld_bus}-$(printf "%04x" ${I2C_ADDR_CPLD})" + if ! [ -L ${dev_path} ]; then + echo "ingrasys_cpld${i} ${I2C_ADDR_CPLD}" > ${!cpld_path}/new_device + else + echo "${dev_path} already exist" + fi + done + + echo "Done" +} + +function _i2c_sensors_init { + echo "SENSORS init..." + local dev_path + # to make sure hwmon index in sysfs as expected, + # need to remove kernel module and then probe them in expected order + # remove all sensors kernel module + _util_rmmod coretemp + _util_rmmod jc42 + _util_rmmod w83795 + # probe coretemp kernel module + modprobe coretemp + # probe hwmon kernel module + modprobe w83795 + # add lm75 to sysfs + ####Main board thermal + ####lm75_1 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH5}-$(printf "%04x" ${I2C_ADDR_LM75_1})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_1}" > ${PATH_MUX_9548_0_CH5}/new_device # hwmon1 + else + echo "${dev_path} already exist" + fi + ####lm75_2 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH5}-$(printf "%04x" ${I2C_ADDR_LM75_2})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_2}" > ${PATH_MUX_9548_0_CH5}/new_device #hwmon2 + else + echo "${dev_path} already exist" + fi + ####lm75_3 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH6}-$(printf "%04x" ${I2C_ADDR_LM75_3})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_1}" > ${PATH_MUX_9548_0_CH6}/new_device # hwmon3 + else + echo "${dev_path} already exist" + fi + ####lm75_4 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH6}-$(printf "%04x" ${I2C_ADDR_LM75_4})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_4}" > ${PATH_MUX_9548_0_CH6}/new_device #hwmon4 + else + echo "${dev_path} already exist" + fi + ####BMC board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_1_CH7}-$(printf "%04x" ${I2C_ADDR_TMP75_BB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_BB}" > ${PATH_MUX_9548_1_CH7}/new_device #hwmon5 + else + echo "${dev_path} already exist" + fi + ####CPU board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MAIN}-$(printf "%04x" ${I2C_ADDR_TMP75_CB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_CB}" > ${PATH_I801_DEVICE}/new_device #hwmon6 + else + echo "${dev_path} already exist" + fi + # add w83795 to sysfs + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_1_CH7}-$(printf "%04x" ${I2C_ADDR_W83795})" + if ! [ -L ${dev_path} ]; then + echo "w83795adg ${I2C_ADDR_W83795}" > ${PATH_MUX_9548_1_CH7}/new_device #hwmon7 + else + echo "${dev_path} already exist" + fi + + # probe jc42 kernel module + modprobe jc42 + + echo "Done" +} + +#FAN Speed Init +function _i2c_fan_speed_init { + echo -n "FAN SPEED INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + # init fan speed + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi +} + +# HWM init +function _i2c_hwm_init { + echo "HWM INIT..." + # select bank0 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x80 + # SW reset, Disable monitor + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x01 0x9C + # disable TR5/TR6 DTS + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x04 0x0 + # enable FANIN1~8 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x06 0xFF + # disable FANIN9~14 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x07 0x00 + # CLKIN clock frequency set as 48Mhz + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x01 0x1C + # select bank 2 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x82 + # set PWM mode in FOMC + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x0F 0x00 + # set 25KHz fan output frequency in F1OPFP&F2OPFP + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x18 0x84 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x19 0x84 +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + + # need to init BMC io expander first due to some io expander are reset default + echo "Init BMC INT & HW ID IO Expander" + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT1_POL} 0x00 + + echo "Init BMC PSU status IO Expander" + # PWRON default 0 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT0_OUT} 0x00 + # default 0 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT1_OUT} 0x00 + # I/O 0.2 0.5 output(PWRON), rest input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT0_DIR} 0xDB + # I/O 1.0~1.1 input, 1.2~1.4 output (1.5~1.7 not enable) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT1_DIR} 0xE3 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT1_POL} 0x00 + + echo "Init BMC RST and SEL IO Expander" + # RST default is 1 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT0_OUT} 0x3F + # SEL default is 0 (HOST), EN default is 1 (ACTIVE_HIGH) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT1_OUT} 0x1F + # I/O 0.0~0.5 output, 0.6~0.7 not use + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT0_DIR} 0xC0 + # all output + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT1_POL} 0x00 + + echo "Init System LED & HW ID IO Expander" + # I/O_0.x for System LED default 0, I/O_1.x for HW ID + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_OUT} 0x00 + # System LED => all output + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_DIR} 0x00 + # HW ID => all input + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT1_POL} 0x00 + + echo "Init FAN Board Status IO Expander" + # LED_G_H set to 1, LED_Y_G set to 0 (ACTIVE_HIGH) + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_OUT} 0x11 + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT1_OUT} 0x11 + # DIR/ABS is input, LED_Y/LED_G is output + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_DIR} 0xCC + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT1_DIR} 0xCC + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT1_POL} 0x00 + + echo "Init System SEL and RST IO Expander" + # RST 0.0~0.3 default 1 (ACTIVE low), rest default 0 + # SEL set to value 0 (host) + # LED_CLR set to 0 will clear all switch LED bitmap, set to 1 here + _util_i2cset -y -r ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${REG_PORT0_OUT} 0x0F + # RST 1.6~1.7 default 1 (ACTIVE low), INT 1.0~1.4 default 1 (ACTIVE low) + _util_i2cset -y -r ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${REG_PORT1_OUT} 0xDF + # all output, but MAC_RST_L 0.0 need to set as input to prevent reboot issue + _util_i2cset -y -r ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${REG_PORT0_DIR} 0x09 + # RST 1.5 !~ 1.7 output, rest are input + _util_i2cset -y -r ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${REG_PORT1_DIR} 0x1F + _util_i2cset -y -r ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${REG_PORT1_POL} 0x00 + + echo "Init CPU CPLD IO Expander" + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_DIR} 0xFF + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_POL} 0x00 +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + + # check if io expander for fan tray exist + result=`i2cget -y ${I2C_BUS_FANTRAY_LED} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_IN} 2>/dev/null` + err_code=$? + if [ "$err_code" != "0" ]; then + echo "fan tray not exist!" + return + fi + + for FAN_TRAY in {1..4}; + do + FAN_ALARM="FAN${FAN_TRAY}_ALARM" + if [ "${!FAN_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + + echo "set [FAN TRAY ${FAN_TRAY}] [Green]=on [Amber]=off" + else + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + + echo "set [FAN TRAY ${FAN_TRAY}] [Green]=off [Amber]=on" + fi + done +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + + echo "led_fan setup..." + # all fan ok + if [ "${FAN1_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ]; then + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_fan_led + # all fan fail + elif [ "${FAN1_ALARM}" == "1" ] \ + && [ "${FAN3_ALARM}" == "1" ] \ + && [ "${FAN5_ALARM}" == "1" ] \ + && [ "${FAN7_ALARM}" == "1" ] ; then + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_fan_led + # partial fan fail + else + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_fan_led + fi +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + echo "led_psu1 setup..." + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_psu1_led + else + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="off" + echo "${COLOR_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + echo "led_psu2 setup..." + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_psu2_led + else + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="off" + echo "${COLOR_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C SYSTEM LED TEST..." + echo "=========================================================" + local output_reg=${REG_PORT0_OUT} + local mask=0xFF + local value=0xFF + + #sys led (green) + # set sys_led_g (0.7) = 1 + mask=0x80 + value=0x80 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + # set sys_led_g (0.7) = 0 + mask=0x80 + value=0x00 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 0 + mask=0x60 + value=0x60 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 1 + mask=0x60 + value=0x40 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 0 + mask=0x18 + value=0x18 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 1 + mask=0x18 + value=0x10 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 0 + mask=0x06 + value=0x06 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 1 + mask=0x06 + value=0x04 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED (can't trun off system led) + # set set fan_led_en (0.6), psu1_pwr_ok_oe (0.4), psu0_pwr_ok_oe (0.2) = 0 + mask=0xFF + value=$((2#00000011)) + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check turn off all LEDs (exclude SYS LED) and Press [Enter] key to continue...' + + # restore sys led + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led +} + +#Set QSFP Port cpld variable +function _qsfp_cpld_var_set { + local port=$1 + local reg_port_base + local reg_port_shift + if [[ $1 -le 12 && $1 -ge 1 ]]; then + cpld_index=1 + reg_port_base=0 + elif [[ $1 -le 25 && $1 -ge 13 ]]; then + cpld_index=2 + reg_port_base=12 + elif [[ $1 -le 38 && $1 -ge 26 ]]; then + cpld_index=3 + reg_port_base=25 + elif [[ $1 -le 51 && $1 -ge 39 ]]; then + cpld_index=4 + reg_port_base=38 + elif [[ $1 -le 64 && $1 -ge 52 ]]; then + cpld_index=5 + reg_port_base=51 + else + echo "invalid port number" + fi + + cpld_port_index=$(( $port - $reg_port_base )) +} + +#Set QSFP Port eeporm variable +function _qsfp_eeprom_var_set { + local port=$1 + local eeprombusbase + local eeprombusshift + # port 1 => zqsfp0 + # port 2 => zqsfp1 + # ... + local port_group=$(( ($port - 1) / 8 )) + + case ${port_group} in + 0) + eeprombusbase=${NUM_MUX_9548_3_CH0} + ;; + 1) + eeprombusbase=${NUM_MUX_9548_4_CH0} + ;; + 2) + eeprombusbase=${NUM_MUX_9548_5_CH0} + ;; + 3) + eeprombusbase=${NUM_MUX_9548_6_CH0} + ;; + 4) + eeprombusbase=${NUM_MUX_9548_7_CH0} + ;; + 5) + eeprombusbase=${NUM_MUX_9548_8_CH0} + ;; + 6) + eeprombusbase=${NUM_MUX_9548_9_CH0} + ;; + 7) + eeprombusbase=${NUM_MUX_9548_10_CH0} + ;; + *) + ;; + esac + + eeprombusshift=$(( (${port} - 1) % 8)) + eepromBus=$(( ${eeprombusbase} + ${eeprombusshift} )) + eepromAddr=${I2C_ADDR_QSFP_EEPROM} +} + + +#Set SFP Port cpld variable +function _sfp_cpld_var_set { + local port=$1 + case ${port} in + 1) + cpld_index=1 + ;; + 2) + cpld_index=2 + ;; + *) + ;; + esac +} + +#Set QSFP Port eeporm variable +function _sfp_eeprom_var_set { + local port=$1 + + case ${port} in + 1) + eepromBus=${NUM_MUX_9546_1_CH0} + ;; + 2) + eepromBus=${NUM_MUX_9546_1_CH1} + ;; + *) + ;; + esac + + eepromAddr=${I2C_ADDR_SFP_EEPROM} +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + local phy_port=0 + + #get physical port + phy_port=$(_port_logic2phy $QSFP_PORT) + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + _qsfp_eeprom_var_set ${phy_port} + + _util_get_qsfp_abs + + if [ $status = 0 ]; then + exit + fi + + + cat ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo "QSFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-64 ports EEPROM + local i + for i in {1..64}; + do + _qsfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/delete_device + fi + done + echo "Done" +} + +#Get SFP EEPROM Information +function _i2c_sfp_eeprom_get { + + # input parameter validation + _util_input_check "${SFP_PORT}" "${MIN_SFP_PORT_NUM}" "${MAX_SFP_PORT_NUM}" + _util_get_sfp_pres + + if [ $status = 0 ]; then + exit + fi + + _sfp_eeprom_var_set ${SFP_PORT} + + cat ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init SFP EEPROM +function _i2c_sfp_eeprom_init { + echo "SFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-2 sfp+ EEPROM + local i + for i in {1..2}; + do + _sfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/delete_device + fi + done + echo "Done" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + echo -n "Main Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init mb EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_MB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "$I2C_ADDR_MB_EEPROM" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/delete_device + fi + echo "Done" +} + +#Init CPU Board EEPROM +function _i2c_cb_eeprom_init { + echo -n "CPU Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init cpu EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_CB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM) ]; then + echo "$I2C_ADDR_CB_EEPROM" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CB_EEPROM}/delete_device + fi + echo "Done" +} + +#Init PSU Kernel Module +function _i2c_psu_init { + echo "=========================================================" + echo "# Description: I2C PSU Init" + echo "=========================================================" + modprobe ingrasys_s9230_64x_psu + + echo "psu1 ${I2C_ADDR_PSU1_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/new_device + echo "psu2 ${I2C_ADDR_PSU2_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/new_device +} + +#Deinit PSU Kernel Module +function _i2c_psu_deinit { + echo "${I2C_ADDR_PSU1_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/delete_device + echo "${I2C_ADDR_PSU2_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/delete_device + _util_rmmod ingrasys_s9230_64x_psu +} + +#get QSFP Status +function _i2c_qsfp_status_get { + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + local stat + _util_get_qsfp_abs + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + local phy_port=0 + + phy_port=$(_port_logic2phy ${QSFP_PORT}) + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + #_qsfp_eeprom_var_set ${QSFP_PORT} + _qsfp_eeprom_var_set ${phy_port} + + #Get QSFP EEPROM info + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +function _i2c_sfp_status_get { + + # input parameter validation + _util_input_check "${SFP_PORT}" "${MIN_SFP_PORT_NUM}" "${MAX_SFP_PORT_NUM}" + + local stat + _util_get_sfp_pres + #status: 0 -> Down, 1 -> Up + if [ $status = 0 ]; then + stat="down" + else + stat="up" + fi + echo "status is $stat" +} + +#get SFP Type +function _i2c_sfp_type_get { + + # input parameter validation + _util_input_check "${SFP_PORT}" "${MIN_SFP_PORT_NUM}" "${MAX_SFP_PORT_NUM}" + + _sfp_eeprom_var_set ${SFP_PORT} + + #Get QSFP EEPROM info + sfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $sfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $sfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $sfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + local eeprom_psu1="" + local eeprom_psu2="" + + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + eeprom_psu1="${PATH_SYSFS_PSU1}/psu_eeprom" + cat ${eeprom_psu1} | hexdump -C + + eeprom_psu2="${PATH_SYSFS_PSU2}/psu_eeprom" + cat ${eeprom_psu2} | hexdump -C +} + +#Get Main Board EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + _i2c_sys_eeprom_get mb +} + +#Get CPU Board EEPROM Information +function _i2c_cb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C CB EEPROM Get..." + echo "=========================================================" + _i2c_sys_eeprom_get cb +} + +#Get system EEPROM Information +##input: "cb" for cpu board, "mb" for main board +function _i2c_sys_eeprom_get { + local eeprom_dev + + if [ "$1" == "cb" ]; then + eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM)/eeprom" + elif [ "$1" == "mb" ]; then + eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom" + else + echo "wrong eeprom type" + return + fi + + # check if eeprom device exist in sysfs + if [ ! -f ${eeprom_dev} ]; then + echo "eeprom device not init" + return + fi + + cat ${eeprom_dev} | hexdump -C + echo "Done" +} + +#sync eeprom content between mb and cb eeprom +function _i2c_eeprom_sync { + echo "=========================================================" + echo "# Description: EEPROM sync..." + echo "=========================================================" + + local mb_eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom" + local cb_eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM)/eeprom" + + # check if eeprom device exist in sysfs + if [[ ! -f ${mb_eeprom_dev} || ! -f ${cb_eeprom_dev} ]]; then + echo "eeprom device not init" + return + fi + + ## check if MB eeprom is empty + if [ ! -z "$(cat ${mb_eeprom_dev} | hexdump -n2 | grep ffff)" ]; then + echo "copy cb eeprom to mb eeprom..." + cat ${cb_eeprom_dev} > ${mb_eeprom_dev} + else + echo "no need to sync" + fi + + echo "Done" +} + +#Set System Status LED +function _i2c_sys_led { + # only green/amber, on/off can't control + if [ "${COLOR_LED}" == "green" ]; then + # set sys_led_g (0.7) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x80 + value=0x80 + elif [ "${COLOR_LED}" == "amber" ]; then + # set sys_led_g (0.7) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x80 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_LED}" == "green" ]; then + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x60 + elif [ "${COLOR_LED}" == "amber" ]; then + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x40 + elif [ "${COLOR_LED}" == "off" ]; then + # set fan_led_en (0.6) = 0 & fan_led_y (0.5) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set PSU1 LED +function _i2c_psu1_led { + if [ "${COLOR_LED}" == "green" ]; then + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x18 + elif [ "${COLOR_LED}" == "amber" ]; then + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x10 + elif [ "${COLOR_LED}" == "off" ]; then + # set psu1_pwr_ok_oe (0.4) = 0 & psu1_led_y (0.3) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set PSU2 LED +function _i2c_psu2_led { + if [ "${COLOR_LED}" == "green" ]; then + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x06 + elif [ "${COLOR_LED}" == "amber" ]; then + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x04 + elif [ "${COLOR_LED}" == "off" ]; then + # set psu0_pwr_ok_oe (0.2) = 0 & psu0_led_y (0.1) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + + i2cAddr=${I2C_ADDR_MUX_9555_0} + output_reg=${REG_PORT0_OUT} + + case ${FAN_TRAY} in + 1) + output_reg=${REG_PORT0_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + output_reg=${REG_PORT0_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + output_reg=${REG_PORT1_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + output_reg=${REG_PORT1_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + # LED PIN value is ACTIVE HIGH + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0xff + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0xff + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "Done" +} + +#Get Board Version and Type +function _i2c_board_type_get { + # read input port 1 value from io expander + input_reg=${REG_PORT1_IN} + boardType=`i2cget -y ${I2C_BUS_HW_ID} ${I2C_ADDR_MUX_9539_0} ${input_reg}` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "MAIN_BOARD BOARD_ID is 0x%02x, HW Rev 0x%02x, Build Rev 0x%02x\n" $boardId $boardHwRev $boardBuildRev +} + +#Get BMC Board Version and Type +function _i2c_bmc_board_type_get { + # read input port 1 value from io expander + input_reg=${REG_PORT1_IN} + boardType=`i2cget -y ${I2C_BUS_BMC_HW_ID} ${I2C_ADDR_MUX_9555_1} ${input_reg}` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BMC_BOARD BOARD_ID is 0x%02x, HW Rev 0x%02x, Build Rev 0x%02x\n" $boardId $boardHwRev $boardBuildRev +} + +#Get CPLD Version +function _i2c_cpld_version { + echo "=========================================================" + echo "# Description: CPLD Version" + echo "=========================================================" + + for i in {1..5}; + do + local cpld_bus="I2C_BUS_CPLD${i}" + local cpld_path="PATH_CPLD${i}_DEVICE" + local file_path="${PATH_SYS_I2C_DEVICES}/${!cpld_bus}-$(printf "%04x" ${I2C_ADDR_CPLD})/cpld_version" + printf "[CPLD %d] %s\n" ${i} $(cat ${file_path}) + done +} + +#Get PSU Status +function _i2c_psu_status { + local psu_abs="" + + psu1PwGood=`cat ${PATH_SYSFS_PSU1}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU1}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu1Exist=1 + else + psu1Exist=0 + fi + + psu2PwGood=`cat ${PATH_SYSFS_PSU2}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU2}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu2Exist=1 + else + psu2Exist=0 + fi + + printf "PSU1 Exist:%x PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Get register value from CPLD +function _i2c_cpld_reg_read { + local idx=$1 + local file_name=$2 + local cpld_i2c_addr=${I2C_ADDR_CPLD} + local reg_file_path + + case ${idx} in + 1) + cpld_i2c_bus=${I2C_BUS_CPLD1} + ;; + 2) + cpld_i2c_bus=${I2C_BUS_CPLD2} + ;; + 3) + cpld_i2c_bus=${I2C_BUS_CPLD3} + ;; + 4) + cpld_i2c_bus=${I2C_BUS_CPLD4} + ;; + 5) + cpld_i2c_bus=${I2C_BUS_CPLD5} + ;; + *) + echo "invalid cpld index" + exit + ;; + esac + + reg_file_path="${PATH_SYS_I2C_DEVICES}/${cpld_i2c_bus}-$(printf "%04x" ${cpld_i2c_addr})/${file_name}" + cpld_reg_val=`cat ${reg_file_path}` +} + +#util functions +function _util_i2cset { + if [ "$DEBUG" == "on" ]; then + i2cset $@ + else + i2cset $@ 1>/dev/null + fi +} + +function _i2c_set { + local i2c_bus=$1 + local i2c_addr=$2 + local reg=$3 + local mask=$4 + local value=$5 + + echo `i2cset -m $mask -y -r ${i2c_bus} ${i2c_addr} ${reg} ${value}` +} + +function _util_rmmod { + local mod=$1 + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod +} + +# get qsfp presence +function _util_get_qsfp_abs { + local phy_port=0 + + #get physical port + phy_port=$(_port_logic2phy $QSFP_PORT) + + # read status from cpld + #_qsfp_cpld_var_set ${QSFP_PORT} + _qsfp_cpld_var_set ${phy_port} + cpld_reg_file_name="${CPLD_QSFP_STATUS_KEY}_${cpld_port_index}" + _i2c_cpld_reg_read ${cpld_index} ${cpld_reg_file_name} + #status: 0 -> Down, 1 -> Up (ACTIVE_LOW in ABS_BIT) + status=$(( $(( $((${cpld_reg_val})) & (1 << ($CPLD_QSFP_STATUS_ABS_BIT)) ))?0:1 )) +} + +# get sfp presence +function _util_get_sfp_pres { + + # read status from cpld + _sfp_cpld_var_set ${SFP_PORT} + cpld_reg_file_name="${CPLD_SFP_STATUS_KEY}" + _i2c_cpld_reg_read ${cpld_index} ${cpld_reg_file_name} + #status: 0 -> Down, 1 -> Up (ACTIVE_LOW in PRES_BIT) + status=$(( $(( $((${cpld_reg_val})) & (1 << ($CPLD_SFP_STATUS_PRES_BIT)) ))?0:1 )) +} + +# valid input number +function _util_input_check { + # input parameter validation + if [[ $1 -lt $2 || $1 -gt $3 ]]; then + echo "Please input number $2~$3" + exit + fi +} + +# clear all switch port led bitmap +function _util_port_led_clear { + echo "port led clear..." + # gpio pin on GPIO MUX PCA9539#1 I/O 0.2 + # pull low to reset bitamp + output_reg=${REG_PORT0_OUT} + mask=0x04 + value=0x00 + _util_i2cset -m ${mask} -y ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${output_reg} ${value} + echo "Done" +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Set 10G Mux to CPU or Front Panel +function _i2c_10g_mux { + + echo "=========================================================" + echo "# Description: 10G Mux" + echo "=========================================================" + + local target=${TARGET_10G_MUX} + local i2c_bus=${I2C_BUS_10GMUX} + local i2c_addr=${I2C_ADDR_10GMUX} + local reg=0 + local mask=0xff + local value=0 + local file_10g_mux="${PATH_CPLD1_DEVICE}/${I2C_BUS_CPLD1}-$(printf "%04x" ${I2C_ADDR_CPLD})/cpld_10gmux_config" + + #get current 10g mux register value on CPLD + value=`cat ${file_10g_mux}` + + if [ "${target}" == "cpu" ]; then + #Set XE0: slave address access + _i2c_set $i2c_bus $i2c_addr 0x06 $mask 0x18 + #Set XE0: CH4 D_IN0-S_OUTA0 EQ + _i2c_set $i2c_bus $i2c_addr 0x2c $mask 0x00 + #Set XE0: CH5 NC-S_OUTB0 DEM + _i2c_set $i2c_bus $i2c_addr 0x35 $mask 0x80 + #Set XE0: CH5 NC-S_OUTB0 VOD + _i2c_set $i2c_bus $i2c_addr 0x34 $mask 0xab + #Set XE0: CH1 D_OUT0-S_INB0 EQ + _i2c_set $i2c_bus $i2c_addr 0x16 $mask 0x01 + #Set XE0: CH1 D_OUT0-S_INB0 DEM + _i2c_set $i2c_bus $i2c_addr 0x18 0x1f 0x80 + #Set XE0: CH1 D_OUT0-S_INB0 VOD + _i2c_set $i2c_bus $i2c_addr 0x17 $mask 0xab + #Set XE1: CH6 D_IN1-S_OUTA1 EQ + _i2c_set $i2c_bus $i2c_addr 0x3a $mask 0x00 + #Set XE1: CH7 NC-S_OUTB1 EQ + _i2c_set $i2c_bus $i2c_addr 0x41 $mask 0x00 + #Set XE1: CH7 NC-S_OUTB1 DEM + _i2c_set $i2c_bus $i2c_addr 0x43 $mask 0x80 + #Set XE1: CH7 NC-S_OUTB1 VOD + _i2c_set $i2c_bus $i2c_addr 0x42 $mask 0xab + #Set XE1: CH3 D_OUT1-S_INB1 EQ + _i2c_set $i2c_bus $i2c_addr 0x24 $mask 0x01 + #Set XE1: CH3 D_OUT1-S_INB1 DEM + _i2c_set $i2c_bus $i2c_addr 0x26 $mask 0x80 + #Set XE1: CH3 D_OUT1-S_INB1 VOD + _i2c_set $i2c_bus $i2c_addr 0x25 $mask 0xab + #Enable auto negotiation of XE ports + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x7 addr=0x11 data=0x80'" + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x7 addr=0x10 data=0x01'" + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x7 addr=0x0 data=0x3200'" + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x1 addr=0x96 data=0x2'" + #delay 1 sec + sleep 1 + + #switch 10G MUX to cpu on CPLD + value=$(( value & 0xf3 )) + echo "$(printf 0x"%x" ${value})" > ${file_10g_mux} + + echo "Switch 10G Mux to [CPU]" + + elif [ "${COLOR_LED}" == "fp" ]; then + #Set XE0: slave address access + _i2c_set $i2c_bus $i2c_addr 0x06 $mask 0x18 + #Set XE0: CH4 D_IN0-S_OUTA0 EQ + _i2c_set $i2c_bus $i2c_addr 0x2c $mask 0x00 + #Set XE0: CH4 D_IN0-S_OUTA0 DEM + _i2c_set $i2c_bus $i2c_addr 0x2e $mask 0x80 + #Set XE0: CH4 D_IN0-S_OUTA0 VOD + _i2c_set $i2c_bus $i2c_addr 0x2d $mask 0xab + #Set XE0: CH0 NC-S_INA0 EQ + _i2c_set $i2c_bus $i2c_addr 0x0f $mask 0x00 + #Set XE0: CH1 D_OUT0-S_INB0 DEM + _i2c_set $i2c_bus $i2c_addr 0x18 0x18 0x80 + #Set XE0: CH1 D_OUT0-S_INB0 VOD + _i2c_set $i2c_bus $i2c_addr 0x17 $mask 0xab + #Set XE1: CH6 D_IN1-S_OUTA1 EQ + _i2c_set $i2c_bus $i2c_addr 0x3a $mask 0x00 + #Set XE1: CH6 D_IN1-S_OUTA1 DEM + _i2c_set $i2c_bus $i2c_addr 0x3c $mask 0x80 + #Set XE1: CH6 D_IN1-S_OUTA1 VOD + _i2c_set $i2c_bus $i2c_addr 0x3b $mask 0xab + #Set XE1: CH2 NC-S_INA1 EQ + _i2c_set $i2c_bus $i2c_addr 0x1d $mask 0x00 + #Set XE1: CH3 D_OUT1-S_INB1 DEM + _i2c_set $i2c_bus $i2c_addr 0x26 $mask 0x80 + #Set XE1: CH3 D_OUT1-S_INB1 VOD + _i2c_set $i2c_bus $i2c_addr 0x25 $mask 0xab + #Enable auto negotiation of XE ports + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x7 addr=0x11 data=0x0'" + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x7 addr=0x10 data=0x0'" + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x7 addr=0x0 data=0x2200'" + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x1 addr=0x96 data=0x2200'" + #delay 1 sec + sleep 1 + + #switch 10G MUX to front panel on CPLD + value=$(( value | 0x0c )) + echo "$(printf 0x"%x" ${value})" > ${file_10g_mux} + + echo "Switch 10G Mux to [Front Panel]" + else + echo "invalid target, please set target to cpu/fp" + fi +} + +#Main Function +function _main { + tart_time_str=`date` + start_time_sec=$(date +%s) + + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_fan_speed_init" ]; then + _i2c_fan_speed_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_cb_eeprom_get" ]; then + _i2c_cb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_eeprom_sync" ]; then + _i2c_eeprom_sync + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_sfp_eeprom_get" ]; then + _i2c_sfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_sfp_eeprom_init" ]; then + _i2c_sfp_eeprom_init ${SFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_cb_eeprom_init" ]; then + _i2c_cb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_sfp_status_get" ]; then + _i2c_sfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_sfp_type_get" ]; then + _i2c_sfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_bmc_board_type_get" ]; then + _i2c_bmc_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_cb_eeprom_get + _i2c_board_type_get + _i2c_bmc_board_type_get + _i2c_cpld_version + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_10g_mux" ]; then + _i2c_10g_mux + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/qsfp_monitor.sh b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/qsfp_monitor.sh new file mode 100755 index 000000000000..23a3fd066bee --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/qsfp_monitor.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, 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 . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..63}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/s9230_64x_monitor.sh b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/s9230_64x_monitor.sh new file mode 100755 index 000000000000..8bfb22328003 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/s9230_64x_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, 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 . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main diff --git a/platform/nephos/sonic-platform-modules-pegatron/LICENSE b/platform/nephos/sonic-platform-modules-pegatron/LICENSE new file mode 100644 index 000000000000..a23cc2b232cd --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2018 Pegatron Corporation. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/nephos/sonic-platform-modules-pegatron/README.md b/platform/nephos/sonic-platform-modules-pegatron/README.md new file mode 100644 index 000000000000..32444b4b8916 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/README.md @@ -0,0 +1 @@ +platform drivers of Pegatron products for the SONiC project diff --git a/platform/nephos/sonic-platform-modules-pegatron/common/modules/pegatron_hwmon_mcu.c b/platform/nephos/sonic-platform-modules-pegatron/common/modules/pegatron_hwmon_mcu.c new file mode 100644 index 000000000000..76cbd8844708 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/common/modules/pegatron_hwmon_mcu.c @@ -0,0 +1,1374 @@ +/* + * A MCU driver connect to hwmon + * + * Copyright (C) 2018 Pegatron Corporation. + * Peter5_Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef pega_DEBUG +/*#define pega_DEBUG*/ +#ifdef pega_DEBUG +#define DBG(x) x +#else +#define DBG(x) +#endif /* DEBUG */ + +#define FW_UPGRADE_COMMAND 0xA5 +#define FAN_DISABLE_COMMAND 0x20 +#define FAN_ENABLE_COMMAND 0x21 +#define FAN_LED_SETTO_MANUAL_COMMAND 0x30 +#define FAN_LED_SETTO_AUTO_COMMAND 0x31 +#define FAN_LED_GREENON_COMMAND 0x40 +#define FAN_LED_GREENOFF_COMMAND 0x41 +#define FAN_LED_AMBERON_COMMAND 0x50 +#define FAN_LED_AMBEROFF_COMMAND 0x51 +#define SMART_FAN_ENABLE_BIT 0 +#define SMART_FAN_SETTING_ENABLE_BIT 0 +#define SA56004X_REMOTE_TEMP_ALERT_BIT 4 +#define I2C_FANBOARD_TIMEOUT_BIT 0 +#define ALERT_MODE_BIT 0 +#define GET_BIT(data, bit, value) value = (data >> bit) & 0x1 +#define SET_BIT(data, bit) data |= (1 << bit) +#define CLEAR_BIT(data, bit) data &= ~(1 << bit) + +enum chips +{ + mercedes3 = 0, + cadillac, + porsche, +}; + +enum fan_alert +{ + FAN_OUTER_RPM_OVER_ALERT_BIT = 0, + FAN_OUTER_RPM_UNDER_ALERT_BIT, + FAN_INNER_RPM_OVER_ALERT_BIT, + FAN_INNER_RPM_UNDER_ALERT_BIT, + FAN_CONNECT_ALERT_BIT, + FAN_DISCONNECT_ALERT_BIT, +}; + +enum fan_status +{ + FAN_ALERT_BIT = 2, + FAN_LED_AMBER_BIT, + FAN_LED_GREEN_BIT, + FAN_LED_AUTO_BIT, + FAN_ENABLE_BIT, + FAN_PRESENT_BIT, +}; + +enum hwmon_mcu_register +{ + MB_FW_UG_REG = 0, + FB_FW_UG_REG, + MB_HW_VER_REG, + FB_HW_SKUVER_REG, + MB_FW_VER_REG, + FB_FW_VER_REG, + + FAN_PWM_REG = 16, + + SF_ENABLE_REG, + SF_SETTING_ENABLE_REG, + SF_DEVICE_REG, + SF_UPDATE_REG, + SF_TEMP_MAX_REG, + SF_TEMP_MID_REG, + SF_TEMP_MIN_REG, + SF_PWM_MAX_REG, + SF_PWM_MID_REG, + SF_PWM_MIN_REG, + + FAN1_INNER_RPM_REG = 32, + FAN2_INNER_RPM_REG, + FAN3_INNER_RPM_REG, + FAN4_INNER_RPM_REG, + FAN5_INNER_RPM_REG, + + FAN1_OUTER_RPM_REG = 48, + FAN2_OUTER_RPM_REG, + FAN3_OUTER_RPM_REG, + FAN4_OUTER_RPM_REG, + FAN5_OUTER_RPM_REG, + + FAN1_STATUS_REG = 64, + FAN2_STATUS_REG, + FAN3_STATUS_REG, + FAN4_STATUS_REG, + FAN5_STATUS_REG, + + ADC_UNDER_VOL_ALERT_REG = 80, + ADC_OVER_VOL_ALERT_REG, + TS_OVER_TEMP_ALERT_REG, + + FAN1_ALERT_REG, + FAN2_ALERT_REG, + FAN3_ALERT_REG, + FAN4_ALERT_REG, + FAN5_ALERT_REG, + + I2C_BUS_ALERT_REG, + ALERT_MODE_REG, + + MONITOR_ADC_VOLTAGE_REG = 96, + + LM_0X49_TEMP_REG = 112, + LM_0X48_TEMP_REG, + SA56004X_LOCAL_TEMP_REG, + SA56004X_REMOTE_TEMP_REG, + +}; + +static struct mutex pega_hwmon_mcu_lock; + +static int pega_hwmon_mcu_read(struct i2c_client *client, u8 reg) +{ + int data = -EPERM; + + mutex_lock(&pega_hwmon_mcu_lock); + + data = i2c_smbus_read_word_data(client, reg); + + mutex_unlock(&pega_hwmon_mcu_lock); + + return data; +} + +static int pega_hwmon_mcu_write(struct i2c_client *client, u8 reg, u8 val) +{ + int ret = -EIO; + + mutex_lock(&pega_hwmon_mcu_lock); + + ret = i2c_smbus_write_byte_data(client, reg, val); + + mutex_unlock(&pega_hwmon_mcu_lock); + + return ret; +} + +static ssize_t mainBoardUpgrade(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = MB_FW_UG_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + if(val) + pega_hwmon_mcu_write(client, reg, FW_UPGRADE_COMMAND); + else + pega_hwmon_mcu_write(client, reg, 0xff); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, FW_UPGRADE_COMMAND)); + + return count; +} + +static ssize_t fanBoardUpgrade(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = FB_FW_UG_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + if(val) + pega_hwmon_mcu_write(client, reg, FW_UPGRADE_COMMAND); + else + pega_hwmon_mcu_write(client, reg, 0xff); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, FW_UPGRADE_COMMAND)); + + return count; +} + +static ssize_t get_MB_HW_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = MB_HW_VER_REG; + + data = pega_hwmon_mcu_read(client, reg); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + data &= 0x1f; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t get_FB_HW_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = FB_HW_SKUVER_REG; + + data = pega_hwmon_mcu_read(client, reg); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + data = (data >> 5) & 0x7; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t get_FB_boardId(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = FB_HW_SKUVER_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data &= 0x1f; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t get_MB_FW_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, major_ver = 0, minor_ver = 0; + u8 reg = MB_FW_VER_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + major_ver = (data >> 4) & 0xf; + minor_ver = data & 0xf; + + return sprintf(buf, "%d.%d\n", major_ver, minor_ver); +} + +static ssize_t get_FB_FW_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, major_ver = 0, minor_ver = 0; + u8 reg = FB_FW_VER_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + major_ver = (data >> 4) & 0xf; + minor_ver = data & 0xf; + + return sprintf(buf, "%d.%d\n", major_ver, minor_ver); +} + +static ssize_t get_fan_PWM(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = FAN_PWM_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = FAN_PWM_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = SF_ENABLE_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SMART_FAN_ENABLE_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t set_smartFan_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_ENABLE_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + if(val) + SET_BIT(data, SMART_FAN_ENABLE_BIT); + else + CLEAR_BIT(data, SMART_FAN_ENABLE_BIT); + pega_hwmon_mcu_write(client, reg, data); + + return count; +} + +static ssize_t get_smartFan_setting_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = SF_SETTING_ENABLE_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SMART_FAN_SETTING_ENABLE_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t set_smartFan_setting_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_SETTING_ENABLE_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + if(val) + SET_BIT(data, SMART_FAN_SETTING_ENABLE_BIT); + else + CLEAR_BIT(data, SMART_FAN_SETTING_ENABLE_BIT); + pega_hwmon_mcu_write(client, reg, data); + + return count; +} + +static ssize_t get_smartFan_device(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_DEVICE_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%x\n", data); +} + +static ssize_t set_smartFan_device(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_DEVICE_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_update(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_UPDATE_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_update(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_UPDATE_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_max_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_TEMP_MAX_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_max_temp(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_TEMP_MAX_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_mid_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_TEMP_MID_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_mid_temp(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_TEMP_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_min_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_TEMP_MID_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_min_temp(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_TEMP_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_max_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MAX_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_max_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MAX_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_mid_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MID_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_mid_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_min_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MIN_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_min_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MIN_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_fan_inner_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u16 data = 0; + u8 reg = FAN1_INNER_RPM_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t get_fan_outer_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u16 data = 0; + u8 reg = FAN1_OUTER_RPM_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t get_fan_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_STATUS_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_PRESENT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_STATUS_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_ENABLE_BIT, val); + + return sprintf(buf, "%d\n", val); +} + + +static ssize_t set_fan_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); + + if(val) + pega_hwmon_mcu_write(client, reg, FAN_ENABLE_COMMAND); + else + pega_hwmon_mcu_write(client, reg, FAN_DISABLE_COMMAND); + + return count; +} + +static ssize_t get_fan_led_auto(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_STATUS_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_LED_AUTO_BIT, val); + + return sprintf(buf, "%d\n", val); +} + + +static ssize_t set_fan_led_auto(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); + + if(val) + pega_hwmon_mcu_write(client, reg, FAN_LED_SETTO_AUTO_COMMAND); + else + pega_hwmon_mcu_write(client, reg, FAN_LED_SETTO_MANUAL_COMMAND); + + return count; +} + +static ssize_t get_fan_led_green(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_STATUS_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_LED_GREEN_BIT, val); + + return sprintf(buf, "%d\n", val); +} + + +static ssize_t set_fan_led_green(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); + + if(val) + pega_hwmon_mcu_write(client, reg, FAN_LED_GREENON_COMMAND); + else + pega_hwmon_mcu_write(client, reg, FAN_LED_GREENOFF_COMMAND); + + return count; +} + +static ssize_t get_fan_led_amber(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_STATUS_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_LED_AMBER_BIT, val); + + return sprintf(buf, "%d\n", val); +} + + +static ssize_t set_fan_led_amber(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); + + if(val) + pega_hwmon_mcu_write(client, reg, FAN_LED_AMBERON_COMMAND); + else + pega_hwmon_mcu_write(client, reg, FAN_LED_AMBEROFF_COMMAND); + + return count; +} + +static ssize_t get_fan_status_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_STATUS_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_adc_under_vol_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = ADC_UNDER_VOL_ALERT_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, attr->index, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_adc_over_vol_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = ADC_OVER_VOL_ALERT_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, attr->index, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_temp_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = TS_OVER_TEMP_ALERT_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SA56004X_REMOTE_TEMP_ALERT_BIT + attr->index, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_outerRPMOver_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_ALERT_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_OUTER_RPM_OVER_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_outerRPMUnder_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_ALERT_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_OUTER_RPM_UNDER_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_innerRPMOver_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_ALERT_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_INNER_RPM_OVER_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_innerRPMUnder_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_ALERT_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_INNER_RPM_UNDER_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_connect_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_ALERT_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_CONNECT_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_disconnect_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_ALERT_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_DISCONNECT_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_i2c_timeout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = I2C_BUS_ALERT_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, I2C_FANBOARD_TIMEOUT_BIT + attr->index, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_alert_mode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = ALERT_MODE_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, ALERT_MODE_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t set_alert_mode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = ALERT_MODE_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); + + if(val) + SET_BIT(data, ALERT_MODE_BIT); + else + CLEAR_BIT(data, ALERT_MODE_BIT); + pega_hwmon_mcu_write(client, reg, data); + + return count; +} + +static ssize_t get_adc_vol(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u16 data = 0, reg = MONITOR_ADC_VOLTAGE_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d.%02d\n", data/1000, (data/10)%12); +} + +static ssize_t get_hwmon_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = LM_0X49_TEMP_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} +#define SET_FAN_ATTR(_num) \ + static SENSOR_DEVICE_ATTR(fan##_num##_inner_rpm, S_IRUGO, get_fan_inner_rpm, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_outer_rpm, S_IRUGO, get_fan_outer_rpm, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_present, S_IRUGO, get_fan_present, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_enable, S_IRUGO | S_IWUSR, get_fan_enable, set_fan_enable, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_led_auto, S_IRUGO | S_IWUSR, get_fan_led_auto, set_fan_led_auto, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_led_green, S_IRUGO | S_IWUSR, get_fan_led_green, set_fan_led_green, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_led_amber, S_IRUGO | S_IWUSR, get_fan_led_amber, set_fan_led_amber, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_status_alert, S_IRUGO, get_fan_status_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_outerRPMOver_alert, S_IRUGO, get_fan_outerRPMOver_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_outerRPMUnder_alert, S_IRUGO, get_fan_outerRPMUnder_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_innerRPMOver_alert, S_IRUGO, get_fan_innerRPMOver_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_innerRPMUnder_alert, S_IRUGO, get_fan_innerRPMUnder_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_connect_alert, S_IRUGO, get_fan_connect_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_disconnect_alert, S_IRUGO, get_fan_disconnect_alert, NULL, _num-1) + +SET_FAN_ATTR(1);SET_FAN_ATTR(2);SET_FAN_ATTR(3);SET_FAN_ATTR(4);SET_FAN_ATTR(5); + +#define SET_ADC_ATTR(_num) \ + static SENSOR_DEVICE_ATTR(ADC##_num##_under_alert, S_IRUGO, get_adc_under_vol_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(ADC##_num##_over_alert, S_IRUGO, get_adc_over_vol_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(ADC##_num##_vol, S_IRUGO, get_adc_vol, NULL, 8-_num) + +SET_ADC_ATTR(1);SET_ADC_ATTR(2);SET_ADC_ATTR(3);SET_ADC_ATTR(4);SET_ADC_ATTR(5);SET_ADC_ATTR(6);SET_ADC_ATTR(7);SET_ADC_ATTR(8); + +static SENSOR_DEVICE_ATTR(mb_fw_upgrade, S_IWUSR, NULL, mainBoardUpgrade, 0); +static SENSOR_DEVICE_ATTR(fb_fw_upgrade, S_IWUSR, NULL, fanBoardUpgrade, 0); +static SENSOR_DEVICE_ATTR(mb_hw_version, S_IRUGO, get_MB_HW_version, NULL, 0); +static SENSOR_DEVICE_ATTR(fb_hw_version, S_IRUGO, get_FB_HW_version, NULL, 0); +static SENSOR_DEVICE_ATTR(fb_board_id, S_IRUGO, get_FB_boardId, NULL, 0); +static SENSOR_DEVICE_ATTR(mb_fw_version, S_IRUGO, get_MB_FW_version, NULL, 0); +static SENSOR_DEVICE_ATTR(fb_fw_version, S_IRUGO, get_FB_FW_version, NULL, 0); +static SENSOR_DEVICE_ATTR(fan_pwm, S_IRUGO | S_IWUSR, get_fan_PWM, set_fan_pwm, 0); + +static SENSOR_DEVICE_ATTR(smartFan_enable, S_IRUGO | S_IWUSR, get_smartFan_enable, set_smartFan_enable, 0); +static SENSOR_DEVICE_ATTR(smartFan_setting_enable, S_IRUGO | S_IWUSR, get_smartFan_setting_enable, set_smartFan_setting_enable, 0); +static SENSOR_DEVICE_ATTR(smartFan_device, S_IRUGO | S_IWUSR, get_smartFan_device, set_smartFan_device, 0); +static SENSOR_DEVICE_ATTR(smartFan_update, S_IRUGO | S_IWUSR, get_smartFan_update, set_smartFan_update, 0); +static SENSOR_DEVICE_ATTR(smartFan_max_temp, S_IRUGO | S_IWUSR, get_smartFan_max_temp, set_smartFan_max_temp, 0); +static SENSOR_DEVICE_ATTR(smartFan_mid_temp, S_IRUGO | S_IWUSR, get_smartFan_mid_temp, set_smartFan_mid_temp, 0); +static SENSOR_DEVICE_ATTR(smartFan_min_temp, S_IRUGO | S_IWUSR, get_smartFan_min_temp, set_smartFan_min_temp, 0); +static SENSOR_DEVICE_ATTR(smartFan_max_pwm, S_IRUGO | S_IWUSR, get_smartFan_max_pwm, set_smartFan_max_pwm, 0); +static SENSOR_DEVICE_ATTR(smartFan_mid_pwm, S_IRUGO | S_IWUSR, get_smartFan_mid_pwm, set_smartFan_mid_pwm, 0); +static SENSOR_DEVICE_ATTR(smartFan_min_pwm, S_IRUGO | S_IWUSR, get_smartFan_min_pwm, set_smartFan_min_pwm, 0); + +static SENSOR_DEVICE_ATTR(lm75_49_temp_alert, S_IRUGO, get_temp_alert, NULL, 3); +static SENSOR_DEVICE_ATTR(lm75_48_temp_alert, S_IRUGO, get_temp_alert, NULL, 2); +static SENSOR_DEVICE_ATTR(SA56004X_Ltemp_alert, S_IRUGO, get_temp_alert, NULL, 1); +static SENSOR_DEVICE_ATTR(SA56004X_Rtemp_alert, S_IRUGO, get_temp_alert, NULL, 0); + +static SENSOR_DEVICE_ATTR(i2c_fb_timeout, S_IRUGO, get_i2c_timeout, NULL, 0); +static SENSOR_DEVICE_ATTR(i2c_remote_timeout, S_IRUGO, get_i2c_timeout, NULL, 1); +static SENSOR_DEVICE_ATTR(i2c_local_timeout, S_IRUGO, get_i2c_timeout, NULL, 2); +static SENSOR_DEVICE_ATTR(i2c_lm75_48_timeout, S_IRUGO, get_i2c_timeout, NULL, 3); +static SENSOR_DEVICE_ATTR(i2c_lm75_49_timeout, S_IRUGO, get_i2c_timeout, NULL, 4); +static SENSOR_DEVICE_ATTR(alert_mode, S_IRUGO | S_IWUSR, get_alert_mode, set_alert_mode, 0); + +static SENSOR_DEVICE_ATTR(lm75_49_temp, S_IRUGO, get_hwmon_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(lm75_48_temp, S_IRUGO, get_hwmon_temp, NULL, 1); +static SENSOR_DEVICE_ATTR(SA56004_local_temp, S_IRUGO, get_hwmon_temp, NULL, 2); +static SENSOR_DEVICE_ATTR(SA56004_remote_temp, S_IRUGO, get_hwmon_temp, NULL, 3); + +static struct attribute *pega_hwmon_mcu_attributes[] = { + &sensor_dev_attr_mb_fw_upgrade.dev_attr.attr, + &sensor_dev_attr_fb_fw_upgrade.dev_attr.attr, + &sensor_dev_attr_mb_hw_version.dev_attr.attr, + &sensor_dev_attr_fb_hw_version.dev_attr.attr, + &sensor_dev_attr_fb_board_id.dev_attr.attr, + &sensor_dev_attr_mb_fw_version.dev_attr.attr, + &sensor_dev_attr_fb_fw_version.dev_attr.attr, + &sensor_dev_attr_fan_pwm.dev_attr.attr, + + &sensor_dev_attr_smartFan_enable.dev_attr.attr, + &sensor_dev_attr_smartFan_setting_enable.dev_attr.attr, + &sensor_dev_attr_smartFan_device.dev_attr.attr, + &sensor_dev_attr_smartFan_update.dev_attr.attr, + &sensor_dev_attr_smartFan_max_temp.dev_attr.attr, + &sensor_dev_attr_smartFan_mid_temp.dev_attr.attr, + &sensor_dev_attr_smartFan_min_temp.dev_attr.attr, + &sensor_dev_attr_smartFan_max_pwm.dev_attr.attr, + &sensor_dev_attr_smartFan_mid_pwm.dev_attr.attr, + &sensor_dev_attr_smartFan_min_pwm.dev_attr.attr, + + &sensor_dev_attr_fan1_inner_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_inner_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_inner_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_inner_rpm.dev_attr.attr, + &sensor_dev_attr_fan5_inner_rpm.dev_attr.attr, + + &sensor_dev_attr_fan1_outer_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_outer_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_outer_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_outer_rpm.dev_attr.attr, + &sensor_dev_attr_fan5_outer_rpm.dev_attr.attr, + + &sensor_dev_attr_fan1_present.dev_attr.attr, + &sensor_dev_attr_fan2_present.dev_attr.attr, + &sensor_dev_attr_fan3_present.dev_attr.attr, + &sensor_dev_attr_fan4_present.dev_attr.attr, + &sensor_dev_attr_fan5_present.dev_attr.attr, + + &sensor_dev_attr_fan1_enable.dev_attr.attr, + &sensor_dev_attr_fan2_enable.dev_attr.attr, + &sensor_dev_attr_fan3_enable.dev_attr.attr, + &sensor_dev_attr_fan4_enable.dev_attr.attr, + &sensor_dev_attr_fan5_enable.dev_attr.attr, + + &sensor_dev_attr_fan1_led_auto.dev_attr.attr, + &sensor_dev_attr_fan2_led_auto.dev_attr.attr, + &sensor_dev_attr_fan3_led_auto.dev_attr.attr, + &sensor_dev_attr_fan4_led_auto.dev_attr.attr, + &sensor_dev_attr_fan5_led_auto.dev_attr.attr, + + &sensor_dev_attr_fan1_led_green.dev_attr.attr, + &sensor_dev_attr_fan2_led_green.dev_attr.attr, + &sensor_dev_attr_fan3_led_green.dev_attr.attr, + &sensor_dev_attr_fan4_led_green.dev_attr.attr, + &sensor_dev_attr_fan5_led_green.dev_attr.attr, + + &sensor_dev_attr_fan1_led_amber.dev_attr.attr, + &sensor_dev_attr_fan2_led_amber.dev_attr.attr, + &sensor_dev_attr_fan3_led_amber.dev_attr.attr, + &sensor_dev_attr_fan4_led_amber.dev_attr.attr, + &sensor_dev_attr_fan5_led_amber.dev_attr.attr, + + &sensor_dev_attr_fan1_status_alert.dev_attr.attr, + &sensor_dev_attr_fan2_status_alert.dev_attr.attr, + &sensor_dev_attr_fan3_status_alert.dev_attr.attr, + &sensor_dev_attr_fan4_status_alert.dev_attr.attr, + &sensor_dev_attr_fan5_status_alert.dev_attr.attr, + + &sensor_dev_attr_ADC1_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC2_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC3_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC4_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC5_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC6_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC7_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC8_under_alert.dev_attr.attr, + + &sensor_dev_attr_ADC1_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC2_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC3_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC4_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC5_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC6_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC7_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC8_over_alert.dev_attr.attr, + + &sensor_dev_attr_lm75_48_temp_alert.dev_attr.attr, + &sensor_dev_attr_lm75_49_temp_alert.dev_attr.attr, + &sensor_dev_attr_SA56004X_Ltemp_alert.dev_attr.attr, + &sensor_dev_attr_SA56004X_Rtemp_alert.dev_attr.attr, + + &sensor_dev_attr_fan1_outerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan2_outerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan3_outerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan4_outerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan5_outerRPMOver_alert.dev_attr.attr, + + &sensor_dev_attr_fan1_outerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan2_outerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan3_outerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan4_outerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan5_outerRPMUnder_alert.dev_attr.attr, + + &sensor_dev_attr_fan1_innerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan2_innerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan3_innerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan4_innerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan5_innerRPMOver_alert.dev_attr.attr, + + &sensor_dev_attr_fan1_innerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan2_innerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan3_innerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan4_innerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan5_innerRPMUnder_alert.dev_attr.attr, + + &sensor_dev_attr_fan1_connect_alert.dev_attr.attr, + &sensor_dev_attr_fan2_connect_alert.dev_attr.attr, + &sensor_dev_attr_fan3_connect_alert.dev_attr.attr, + &sensor_dev_attr_fan4_connect_alert.dev_attr.attr, + &sensor_dev_attr_fan5_connect_alert.dev_attr.attr, + + &sensor_dev_attr_fan1_disconnect_alert.dev_attr.attr, + &sensor_dev_attr_fan2_disconnect_alert.dev_attr.attr, + &sensor_dev_attr_fan3_disconnect_alert.dev_attr.attr, + &sensor_dev_attr_fan4_disconnect_alert.dev_attr.attr, + &sensor_dev_attr_fan5_disconnect_alert.dev_attr.attr, + + &sensor_dev_attr_i2c_fb_timeout.dev_attr.attr, + &sensor_dev_attr_i2c_remote_timeout.dev_attr.attr, + &sensor_dev_attr_i2c_local_timeout.dev_attr.attr, + &sensor_dev_attr_i2c_lm75_48_timeout.dev_attr.attr, + &sensor_dev_attr_i2c_lm75_49_timeout.dev_attr.attr, + &sensor_dev_attr_alert_mode.dev_attr.attr, + + &sensor_dev_attr_ADC1_vol.dev_attr.attr, + &sensor_dev_attr_ADC2_vol.dev_attr.attr, + &sensor_dev_attr_ADC3_vol.dev_attr.attr, + &sensor_dev_attr_ADC4_vol.dev_attr.attr, + &sensor_dev_attr_ADC5_vol.dev_attr.attr, + &sensor_dev_attr_ADC6_vol.dev_attr.attr, + &sensor_dev_attr_ADC7_vol.dev_attr.attr, + &sensor_dev_attr_ADC8_vol.dev_attr.attr, + + &sensor_dev_attr_lm75_49_temp.dev_attr.attr, + &sensor_dev_attr_lm75_48_temp.dev_attr.attr, + &sensor_dev_attr_SA56004_local_temp.dev_attr.attr, + &sensor_dev_attr_SA56004_remote_temp.dev_attr.attr, + + NULL +}; + +static const struct attribute_group pega_hwmon_mcu_group = { .attrs = pega_hwmon_mcu_attributes}; + +static int pega_hwmon_mcu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + status = sysfs_create_group(&client->dev.kobj, &pega_hwmon_mcu_group); + + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + + return 0; + +exit: + return status; +} + +static int pega_hwmon_mcu_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &pega_hwmon_mcu_group); + return 0; +} + +static const struct i2c_device_id pega_hwmon_mcu_id[] = { + { "porsche_hwmon_mcu", porsche }, + {} +}; +MODULE_DEVICE_TABLE(i2c, pega_hwmon_mcu_id); + +static struct i2c_driver pega_hwmon_mcu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "pegatron_hwmon_mcu", + }, + .probe = pega_hwmon_mcu_probe, + .remove = pega_hwmon_mcu_remove, + .id_table = pega_hwmon_mcu_id, +}; + +static int __init pega_hwmon_mcu_init(void) +{ + mutex_init(&pega_hwmon_mcu_lock); + + return i2c_add_driver(&pega_hwmon_mcu_driver); +} + +static void __exit pega_hwmon_mcu_exit(void) +{ + i2c_del_driver(&pega_hwmon_mcu_driver); +} + +MODULE_AUTHOR("Peter5 Lin "); +MODULE_DESCRIPTION("pega_hwmon_mcu driver"); +MODULE_LICENSE("GPL"); + +module_init(pega_hwmon_mcu_init); +module_exit(pega_hwmon_mcu_exit); \ No newline at end of file diff --git a/platform/nephos/sonic-platform-modules-pegatron/debian/changelog b/platform/nephos/sonic-platform-modules-pegatron/debian/changelog new file mode 100644 index 000000000000..39ecd34d960c --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/debian/changelog @@ -0,0 +1,5 @@ +sonic-pegatron-platform-modules (0.1) unstable; urgency=low + + * Initial release + + -- Pegatron Mon, 12 Mar 2018 15:22:37 +0800 diff --git a/platform/nephos/sonic-platform-modules-pegatron/debian/compat b/platform/nephos/sonic-platform-modules-pegatron/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/nephos/sonic-platform-modules-pegatron/debian/control b/platform/nephos/sonic-platform-modules-pegatron/debian/control new file mode 100755 index 000000000000..18e74be1455d --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/debian/control @@ -0,0 +1,12 @@ +Source: sonic-pegatron-platform-modules +Section: main +Priority: extra +Maintainer: Pegatron +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-pegatron-porsche +Architecture: amd64 +Depends: linux-image-3.16.0-5-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/nephos/sonic-platform-modules-pegatron/debian/rules b/platform/nephos/sonic-platform-modules-pegatron/debian/rules new file mode 100755 index 000000000000..472ec939a47c --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/debian/rules @@ -0,0 +1,88 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-pegatron +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= porsche +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +SCRIPTS_DIR := scripts +CONF_DIR := conf + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + #$(PYTHON) $${mod}/setup.py build; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SCRIPTS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/bin/; \ + #$(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/Makefile b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/Makefile new file mode 100644 index 000000000000..60e882a586d9 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/Makefile @@ -0,0 +1 @@ +obj-m:=pegatron_porsche_cpld.o pegatron_hwmon_mcu.o pegatron_porsche_sfp.o diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_hwmon_mcu.c b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_hwmon_mcu.c new file mode 120000 index 000000000000..1357104478a3 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_hwmon_mcu.c @@ -0,0 +1 @@ +../../common/modules/pegatron_hwmon_mcu.c \ No newline at end of file diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_porsche_cpld.c b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_porsche_cpld.c new file mode 100644 index 000000000000..154a68dcb836 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_porsche_cpld.c @@ -0,0 +1,1132 @@ +/* + * A CPLD driver for the porsche + * + * Copyright (C) 2018 Pegatron Corporation. + * Peter5_Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef pegatron_porsche_DEBUG +/*#define pegatron_porsche_DEBUG*/ +#ifdef pegatron_porsche_DEBUG +#define DBG(x) x +#else +#define DBG(x) +#endif /* DEBUG */ + +#define CPLD_SFP_MAX_GROUP 3 +#define SFP_PORT_MAX_NUM 54 +#define SFP_EEPROM_SIZE 256 +#define QSFP_FIRST_PORT 48 +#define CPLDA_SFP_NUM 24 +#define CPLDB_SFP_NUM 12 +#define CPLDC_SFP_NUM 18 +#define CPLDA_ADDRESS 0x74 +#define CPLDB_ADDRESS 0x75 +#define CPLDC_ADDRESS 0x76 +#define CPLD_VERSION_REG 0x0 +#define SYNC_CONTROL_REG 0x1 +#define CPLD_SYS_PWR_LED_REG 0xD +#define CPLD_LOC_FAN_LED_REG 0xE +#define CPLD_EEPROM_WRITE_REG 0x12 +#define CPLD_PSU_REG 0x15 +#define SFP_13_36_SCL_BASE 0x4 +#define SFP_1_12_SCL_BASE 0x2 +#define SFP_37_54_SCL_BASE 0x5 +#define SFP_13_36_STATUS_BASE 0x8 +#define SFP_1_12_STATUS_BASE 0x5 +#define SFP_37_54_STATUS_BASE 0x9 +#define QSFP_PRESENT_ADDRESS 0xF +#define QSFP_RESET_ADDRESS_BASE 0x10 +#define QSFP_MODSELN_ADDRESS 0x17 +#define QSFP_LOW_POWER_ADDRESS 0x18 +#define CPLD_SERIAL_LED_BIT 2 +#define CPLD_EEPROM_WRITE_BIT 2 +#define SFP_PRESENT_BASE 0 +#define SFP_RXLOSS_BASE 1 +#define SFP_TXFAULT_BASE 2 +#define SFP_TXDISABLE_BASE 3 +#define CPLD_PSU_PWOK_BASE 0 +#define CPLD_PSU_PRESENT_BASE 2 +#define GET_BIT(data, bit, value) value = (data >> bit) & 0x1 +#define SET_BIT(data, bit) data |= (1 << bit) +#define CLEAR_BIT(data, bit) data &= ~(1 << bit) + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; +/* Addresses scanned for pegatron_porsche_cpld + */ +static const unsigned short normal_i2c[] = { CPLDA_ADDRESS, CPLDB_ADDRESS, CPLDC_ADDRESS, I2C_CLIENT_END }; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +int pegatron_porsche_cpld_read(unsigned short addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int data = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == addr) { + data = i2c_smbus_read_byte_data(cpld_node->client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, addr, reg, data)); + break; + } + } + + mutex_unlock(&list_lock); + + return data; +} +EXPORT_SYMBOL(pegatron_porsche_cpld_read); + +int pegatron_porsche_cpld_write(unsigned short addr, u8 reg, u8 val) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, val); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, addr, reg, val)); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(pegatron_porsche_cpld_write); + +static ssize_t read_cpld_HWversion(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_VERSION_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%02x\n", (data >> 5) & 0x7); +} + +static ssize_t read_cpld_SWversion(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_VERSION_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%02x\n", (data & 0x1f)); +} + +static ssize_t show_allled_ctrl(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = SYNC_CONTROL_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data &= 0x3; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t set_allled_ctrl(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = SYNC_CONTROL_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + data = val | (data & 0xfc); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t show_serial_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0, reg = SYNC_CONTROL_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, CPLD_SERIAL_LED_BIT, val); + + return sprintf(buf, "%02x\n", val); +} + +static ssize_t set_serial_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = SYNC_CONTROL_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + if(val) + SET_BIT(data, CPLD_SERIAL_LED_BIT); + else + CLEAR_BIT(data, CPLD_SERIAL_LED_BIT); + + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t show_sys_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_SYS_PWR_LED_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data = (data >> 5) & 0x7; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t set_sys_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_SYS_PWR_LED_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + data = (val << 5) | (data & 0x1f); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} +static ssize_t show_pwr_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_SYS_PWR_LED_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data = (data >> 2) & 0x7; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t set_pwr_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_SYS_PWR_LED_REG; + long val = 0; + + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + data = (val << 2) | (data & 0xe3); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} +static ssize_t show_loc_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_LOC_FAN_LED_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data = (data>>4) & 0x3; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t set_loc_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_LOC_FAN_LED_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + data = (val << 4) | (data & 0xf); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t show_fan_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_LOC_FAN_LED_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data &= 0x7; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t set_fan_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_LOC_FAN_LED_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + data = val | (data & 0xf8); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t show_eeprom_write_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0, reg = CPLD_EEPROM_WRITE_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, reg, val); + + return sprintf(buf, "%02x\n", val); +} + +static ssize_t set_eeprom_write_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_EEPROM_WRITE_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + if(val) + SET_BIT(data, CPLD_EEPROM_WRITE_BIT); + else + CLEAR_BIT(data, CPLD_EEPROM_WRITE_BIT); + + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t read_psu_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0, reg = CPLD_PSU_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, (CPLD_PSU_PRESENT_BASE + attr->index), val); + + return sprintf(buf, "%02x\n", val); +} + +static ssize_t read_psu_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val=0, reg = CPLD_PSU_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, (CPLD_PSU_PWOK_BASE + attr->index), val); + + return sprintf(buf, "%02x\n", val); +} + +#define GET_SFP_STATUS_ADDRESS(idx, reg) \ + if(idx < CPLDB_SFP_NUM) \ + reg = SFP_1_12_STATUS_BASE + (idx / 2); \ + else if(idx < CPLDA_SFP_NUM + CPLDB_SFP_NUM) \ + reg = SFP_13_36_STATUS_BASE + ((idx-CPLDB_SFP_NUM) / 2); \ + else \ + reg = SFP_37_54_STATUS_BASE + ((idx-CPLDB_SFP_NUM-CPLDA_SFP_NUM) / 2) + +static ssize_t get_sfp_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = 0, data = 0, val = 0; + + GET_SFP_STATUS_ADDRESS(attr->index, reg); + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SFP_PRESENT_BASE + 4*(attr->index % 2), val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_sfp_tx_disable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = 0, data = 0, val = 0; + + GET_SFP_STATUS_ADDRESS(attr->index, reg); + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SFP_TXDISABLE_BASE + 4*(attr->index % 2), val); + + return sprintf(buf, "%d\n", val); +} +static ssize_t set_sfp_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = 0, data = 0; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + GET_SFP_STATUS_ADDRESS(attr->index, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data = pegatron_porsche_cpld_read(client->addr, reg); + + if(val) + SET_BIT(data, SFP_TXDISABLE_BASE + 4*(attr->index % 2)); + else + CLEAR_BIT(data, SFP_TXDISABLE_BASE + 4*(attr->index % 2)); + + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} +static ssize_t get_sfp_rx_loss(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = 0, data = 0, val = 0; + + GET_SFP_STATUS_ADDRESS(attr->index, reg); + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SFP_RXLOSS_BASE + 4*(attr->index % 2), val); + + return sprintf(buf, "%d\n", val); +} +static ssize_t get_sfp_tx_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = 0, data = 0, val = 0; + + GET_SFP_STATUS_ADDRESS(attr->index, reg); + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SFP_TXFAULT_BASE + 4*(attr->index % 2), val); + + return sprintf(buf, "%d\n",val); +} + +static ssize_t get_qsfp_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0, reg = QSFP_PRESENT_ADDRESS; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, (attr->index % QSFP_FIRST_PORT), val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_qsfp_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = (QSFP_RESET_ADDRESS_BASE + attr->index % QSFP_FIRST_PORT / 4), data =0; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data = (data >> ((attr->index % QSFP_FIRST_PORT % 4)*2)) & 0x3; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_qsfp_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = (QSFP_RESET_ADDRESS_BASE + attr->index % QSFP_FIRST_PORT / 4), data = 0; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data = (val & 0x3) << ((attr->index % QSFP_FIRST_PORT % 4)*2); + + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t get_qsfp_lowpower(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0, reg = QSFP_LOW_POWER_ADDRESS; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, (attr->index % QSFP_FIRST_PORT), val); + return sprintf(buf, "%02x\n", val); +} + +static ssize_t set_qsfp_lowpower(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = QSFP_LOW_POWER_ADDRESS; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + if(val) + SET_BIT(data, (attr->index % QSFP_FIRST_PORT)); + else + CLEAR_BIT(data, (attr->index % QSFP_FIRST_PORT)); + + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t get_qsfp_modeseln(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0, reg = QSFP_MODSELN_ADDRESS; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, (attr->index % QSFP_FIRST_PORT), val); + return sprintf(buf, "%02x\n", val); +} + +static ssize_t set_qsfp_modeseln(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = QSFP_MODSELN_ADDRESS; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + if(val) + SET_BIT(data, (attr->index % QSFP_FIRST_PORT)); + else + CLEAR_BIT(data, (attr->index % QSFP_FIRST_PORT)); + + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static SENSOR_DEVICE_ATTR(cpld_hw_version, S_IRUGO, read_cpld_HWversion, NULL, 0); +static SENSOR_DEVICE_ATTR(cpld_sw_version, S_IRUGO, read_cpld_SWversion, NULL, 0); +static SENSOR_DEVICE_ATTR(cpld_allled_ctrl, S_IRUGO | S_IWUSR, show_allled_ctrl, set_allled_ctrl, 0); +static SENSOR_DEVICE_ATTR(serial_led_enable, S_IRUGO | S_IWUSR, show_serial_led, set_serial_led, 0); +static SENSOR_DEVICE_ATTR(sys_led, S_IRUGO | S_IWUSR, show_sys_led, set_sys_led, 0); +static SENSOR_DEVICE_ATTR(pwr_led, S_IRUGO | S_IWUSR, show_pwr_led, set_pwr_led, 0); +static SENSOR_DEVICE_ATTR(loc_led, S_IRUGO | S_IWUSR, show_loc_led, set_loc_led, 0); +static SENSOR_DEVICE_ATTR(fan_led, S_IRUGO | S_IWUSR, show_fan_led, set_fan_led, 0); +static SENSOR_DEVICE_ATTR(eeprom_write_enable, S_IRUGO | S_IWUSR, show_eeprom_write_enable, set_eeprom_write_enable, 0); +static SENSOR_DEVICE_ATTR(psu_1_present, S_IRUGO, read_psu_present, NULL, 1); +static SENSOR_DEVICE_ATTR(psu_2_present, S_IRUGO, read_psu_present, NULL, 0); +static SENSOR_DEVICE_ATTR(psu_1_status, S_IRUGO, read_psu_status, NULL, 1); +static SENSOR_DEVICE_ATTR(psu_2_status, S_IRUGO, read_psu_status, NULL, 0); + +#define SET_SFP_ATTR(_num) \ + static SENSOR_DEVICE_ATTR(sfp##_num##_present, S_IRUGO, get_sfp_present, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(sfp##_num##_tx_disable, S_IRUGO | S_IWUSR, get_sfp_tx_disable, set_sfp_tx_disable, _num-1); \ + static SENSOR_DEVICE_ATTR(sfp##_num##_rx_loss, S_IRUGO, get_sfp_rx_loss, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(sfp##_num##_tx_fault, S_IRUGO, get_sfp_tx_fault, NULL, _num-1) + +#define SET_QSFP_ATTR(_num) \ + static SENSOR_DEVICE_ATTR(sfp##_num##_present, S_IRUGO, get_qsfp_present, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(sfp##_num##_reset, S_IRUGO | S_IWUSR, get_qsfp_reset, set_qsfp_reset, _num-1); \ + static SENSOR_DEVICE_ATTR(sfp##_num##_lowpower, S_IRUGO | S_IWUSR, get_qsfp_lowpower, set_qsfp_lowpower, _num-1); \ + static SENSOR_DEVICE_ATTR(sfp##_num##_modeseln, S_IRUGO | S_IWUSR, get_qsfp_modeseln, set_qsfp_modeseln, _num-1) + +SET_SFP_ATTR(1);SET_SFP_ATTR(2);SET_SFP_ATTR(3);SET_SFP_ATTR(4);SET_SFP_ATTR(5);SET_SFP_ATTR(6);SET_SFP_ATTR(7);SET_SFP_ATTR(8);SET_SFP_ATTR(9); +SET_SFP_ATTR(10);SET_SFP_ATTR(11);SET_SFP_ATTR(12);SET_SFP_ATTR(13);SET_SFP_ATTR(14);SET_SFP_ATTR(15);SET_SFP_ATTR(16);SET_SFP_ATTR(17);SET_SFP_ATTR(18); +SET_SFP_ATTR(19);SET_SFP_ATTR(20);SET_SFP_ATTR(21);SET_SFP_ATTR(22);SET_SFP_ATTR(23);SET_SFP_ATTR(24);SET_SFP_ATTR(25);SET_SFP_ATTR(26);SET_SFP_ATTR(27); +SET_SFP_ATTR(28);SET_SFP_ATTR(29);SET_SFP_ATTR(30);SET_SFP_ATTR(31);SET_SFP_ATTR(32);SET_SFP_ATTR(33);SET_SFP_ATTR(34);SET_SFP_ATTR(35);SET_SFP_ATTR(36); +SET_SFP_ATTR(37);SET_SFP_ATTR(38);SET_SFP_ATTR(39);SET_SFP_ATTR(40);SET_SFP_ATTR(41);SET_SFP_ATTR(42);SET_SFP_ATTR(43);SET_SFP_ATTR(44);SET_SFP_ATTR(45); +SET_SFP_ATTR(46);SET_SFP_ATTR(47);SET_SFP_ATTR(48); +SET_QSFP_ATTR(49);SET_QSFP_ATTR(50);SET_QSFP_ATTR(51);SET_QSFP_ATTR(52);SET_QSFP_ATTR(53);SET_QSFP_ATTR(54); + +static struct attribute *pegatron_porsche_cpldA_attributes[] = { + &sensor_dev_attr_cpld_hw_version.dev_attr.attr, + &sensor_dev_attr_cpld_sw_version.dev_attr.attr, + + &sensor_dev_attr_sfp13_present.dev_attr.attr, + &sensor_dev_attr_sfp13_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp13_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp13_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp14_present.dev_attr.attr, + &sensor_dev_attr_sfp14_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp14_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp14_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp15_present.dev_attr.attr, + &sensor_dev_attr_sfp15_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp15_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp15_tx_fault.dev_attr.attr, + + + &sensor_dev_attr_sfp16_present.dev_attr.attr, + &sensor_dev_attr_sfp16_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp16_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp16_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp17_present.dev_attr.attr, + &sensor_dev_attr_sfp17_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp17_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp17_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp18_present.dev_attr.attr, + &sensor_dev_attr_sfp18_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp18_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp18_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp19_present.dev_attr.attr, + &sensor_dev_attr_sfp19_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp19_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp19_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp20_present.dev_attr.attr, + &sensor_dev_attr_sfp20_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp20_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp20_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp21_present.dev_attr.attr, + &sensor_dev_attr_sfp21_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp21_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp21_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp22_present.dev_attr.attr, + &sensor_dev_attr_sfp22_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp22_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp22_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp23_present.dev_attr.attr, + &sensor_dev_attr_sfp23_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp23_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp23_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp24_present.dev_attr.attr, + &sensor_dev_attr_sfp24_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp24_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp24_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp25_present.dev_attr.attr, + &sensor_dev_attr_sfp25_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp25_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp25_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp26_present.dev_attr.attr, + &sensor_dev_attr_sfp26_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp26_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp26_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp27_present.dev_attr.attr, + &sensor_dev_attr_sfp27_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp27_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp27_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp28_present.dev_attr.attr, + &sensor_dev_attr_sfp28_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp28_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp28_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp29_present.dev_attr.attr, + &sensor_dev_attr_sfp29_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp29_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp29_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp30_present.dev_attr.attr, + &sensor_dev_attr_sfp30_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp30_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp30_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp31_present.dev_attr.attr, + &sensor_dev_attr_sfp31_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp31_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp31_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp32_present.dev_attr.attr, + &sensor_dev_attr_sfp32_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp32_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp32_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp33_present.dev_attr.attr, + &sensor_dev_attr_sfp33_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp33_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp33_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp34_present.dev_attr.attr, + &sensor_dev_attr_sfp34_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp34_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp34_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp35_present.dev_attr.attr, + &sensor_dev_attr_sfp35_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp35_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp35_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp36_present.dev_attr.attr, + &sensor_dev_attr_sfp36_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp36_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp36_tx_fault.dev_attr.attr, + + NULL +}; + +static struct attribute *pegatron_porsche_cpldB_attributes[] = { + &sensor_dev_attr_cpld_hw_version.dev_attr.attr, + &sensor_dev_attr_cpld_sw_version.dev_attr.attr, + &sensor_dev_attr_cpld_allled_ctrl.dev_attr.attr, + &sensor_dev_attr_serial_led_enable.dev_attr.attr, + &sensor_dev_attr_sys_led.dev_attr.attr, + &sensor_dev_attr_pwr_led.dev_attr.attr, + &sensor_dev_attr_loc_led.dev_attr.attr, + &sensor_dev_attr_fan_led.dev_attr.attr, + &sensor_dev_attr_eeprom_write_enable.dev_attr.attr, + &sensor_dev_attr_psu_1_present.dev_attr.attr, + &sensor_dev_attr_psu_2_present.dev_attr.attr, + &sensor_dev_attr_psu_1_status.dev_attr.attr, + &sensor_dev_attr_psu_2_status.dev_attr.attr, + + &sensor_dev_attr_sfp1_present.dev_attr.attr, + &sensor_dev_attr_sfp1_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp1_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp1_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp2_present.dev_attr.attr, + &sensor_dev_attr_sfp2_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp2_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp2_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp3_present.dev_attr.attr, + &sensor_dev_attr_sfp3_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp3_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp3_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp4_present.dev_attr.attr, + &sensor_dev_attr_sfp4_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp4_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp4_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp5_present.dev_attr.attr, + &sensor_dev_attr_sfp5_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp5_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp5_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp6_present.dev_attr.attr, + &sensor_dev_attr_sfp6_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp6_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp6_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp7_present.dev_attr.attr, + &sensor_dev_attr_sfp7_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp7_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp7_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp8_present.dev_attr.attr, + &sensor_dev_attr_sfp8_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp8_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp8_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp9_present.dev_attr.attr, + &sensor_dev_attr_sfp9_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp9_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp9_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp10_present.dev_attr.attr, + &sensor_dev_attr_sfp10_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp10_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp10_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp11_present.dev_attr.attr, + &sensor_dev_attr_sfp11_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp11_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp11_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp12_present.dev_attr.attr, + &sensor_dev_attr_sfp12_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp12_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp12_tx_fault.dev_attr.attr, + NULL +}; + +static struct attribute *pegatron_porsche_cpldC_attributes[] = { + &sensor_dev_attr_cpld_hw_version.dev_attr.attr, + &sensor_dev_attr_cpld_sw_version.dev_attr.attr, + + &sensor_dev_attr_sfp37_present.dev_attr.attr, + &sensor_dev_attr_sfp37_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp37_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp37_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp38_present.dev_attr.attr, + &sensor_dev_attr_sfp38_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp38_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp38_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp39_present.dev_attr.attr, + &sensor_dev_attr_sfp39_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp39_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp39_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp40_present.dev_attr.attr, + &sensor_dev_attr_sfp40_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp40_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp40_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp41_present.dev_attr.attr, + &sensor_dev_attr_sfp41_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp41_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp41_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp42_present.dev_attr.attr, + &sensor_dev_attr_sfp42_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp42_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp42_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp43_present.dev_attr.attr, + &sensor_dev_attr_sfp43_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp43_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp43_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp44_present.dev_attr.attr, + &sensor_dev_attr_sfp44_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp44_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp44_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp45_present.dev_attr.attr, + &sensor_dev_attr_sfp45_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp45_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp45_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp46_present.dev_attr.attr, + &sensor_dev_attr_sfp46_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp46_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp46_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp47_present.dev_attr.attr, + &sensor_dev_attr_sfp47_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp47_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp47_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp48_present.dev_attr.attr, + &sensor_dev_attr_sfp48_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp48_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp48_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp49_present.dev_attr.attr, + &sensor_dev_attr_sfp49_lowpower.dev_attr.attr, + &sensor_dev_attr_sfp49_modeseln.dev_attr.attr, + &sensor_dev_attr_sfp49_reset.dev_attr.attr, + + &sensor_dev_attr_sfp50_present.dev_attr.attr, + &sensor_dev_attr_sfp50_lowpower.dev_attr.attr, + &sensor_dev_attr_sfp50_modeseln.dev_attr.attr, + &sensor_dev_attr_sfp50_reset.dev_attr.attr, + + &sensor_dev_attr_sfp51_present.dev_attr.attr, + &sensor_dev_attr_sfp51_lowpower.dev_attr.attr, + &sensor_dev_attr_sfp51_modeseln.dev_attr.attr, + &sensor_dev_attr_sfp51_reset.dev_attr.attr, + + &sensor_dev_attr_sfp52_present.dev_attr.attr, + &sensor_dev_attr_sfp52_lowpower.dev_attr.attr, + &sensor_dev_attr_sfp52_modeseln.dev_attr.attr, + &sensor_dev_attr_sfp52_reset.dev_attr.attr, + + &sensor_dev_attr_sfp53_present.dev_attr.attr, + &sensor_dev_attr_sfp53_lowpower.dev_attr.attr, + &sensor_dev_attr_sfp53_modeseln.dev_attr.attr, + &sensor_dev_attr_sfp53_reset.dev_attr.attr, + + &sensor_dev_attr_sfp54_present.dev_attr.attr, + &sensor_dev_attr_sfp54_lowpower.dev_attr.attr, + &sensor_dev_attr_sfp54_modeseln.dev_attr.attr, + &sensor_dev_attr_sfp54_reset.dev_attr.attr, + NULL +}; + +static const struct attribute_group pegatron_porsche_cpldA_group = { .attrs = pegatron_porsche_cpldA_attributes}; +static const struct attribute_group pegatron_porsche_cpldB_group = { .attrs = pegatron_porsche_cpldB_attributes}; +static const struct attribute_group pegatron_porsche_cpldC_group = { .attrs = pegatron_porsche_cpldC_attributes}; + +static void pegatron_porsche_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void pegatron_porsche_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int pegatron_porsche_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + /* Register sysfs hooks */ + switch(client->addr) + { + case CPLDA_ADDRESS: + status = sysfs_create_group(&client->dev.kobj, &pegatron_porsche_cpldA_group); + break; + case CPLDB_ADDRESS: + status = sysfs_create_group(&client->dev.kobj, &pegatron_porsche_cpldB_group); + break; + case CPLDC_ADDRESS: + status = sysfs_create_group(&client->dev.kobj, &pegatron_porsche_cpldC_group); + break; + default: + dev_dbg(&client->dev, "i2c_check_CPLD failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + break; + } + + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + pegatron_porsche_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int pegatron_porsche_cpld_remove(struct i2c_client *client) +{ + switch(client->addr) + { + case CPLDA_ADDRESS: + sysfs_remove_group(&client->dev.kobj, &pegatron_porsche_cpldA_group); + break; + case CPLDB_ADDRESS: + sysfs_remove_group(&client->dev.kobj, &pegatron_porsche_cpldB_group); + break; + case CPLDC_ADDRESS: + sysfs_remove_group(&client->dev.kobj, &pegatron_porsche_cpldC_group); + break; + default: + dev_dbg(&client->dev, "i2c_remove_CPLD failed (0x%x)\n", client->addr); + break; + } + + + pegatron_porsche_cpld_remove_client(client); + return 0; +} + +static const struct i2c_device_id pegatron_porsche_cpld_id[] = { + { "porsche_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, pegatron_porsche_cpld_id); + +static struct i2c_driver pegatron_porsche_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "pegatron_porsche_cpld", + }, + .probe = pegatron_porsche_cpld_probe, + .remove = pegatron_porsche_cpld_remove, + .id_table = pegatron_porsche_cpld_id, + .address_list = normal_i2c, +}; + +static int __init pegatron_porsche_cpld_init(void) +{ + mutex_init(&list_lock); + + return i2c_add_driver(&pegatron_porsche_cpld_driver); +} + +static void __exit pegatron_porsche_cpld_exit(void) +{ + i2c_del_driver(&pegatron_porsche_cpld_driver); +} + +MODULE_AUTHOR("Peter5 Lin "); +MODULE_DESCRIPTION("pegatron_porsche_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(pegatron_porsche_cpld_init); +module_exit(pegatron_porsche_cpld_exit); diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_porsche_sfp.c b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_porsche_sfp.c new file mode 100644 index 000000000000..5d5d64b15e1a --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_porsche_sfp.c @@ -0,0 +1,431 @@ +/* + * A SFP driver for the porsche platform + * + * Copyright (C) 2018 Pegatron Corporation. + * Peter5_Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef PEGA_DEBUG +/*#define PEGA_DEBUG*/ +#ifdef PEGA_DEBUG +#define DBG(x) x +#else +#define DBG(x) +#endif /* DEBUG */ + +#define SFP_EEPROM_SIZE 256 +#define SFP_EEPROM_A0_ADDR 0x50 +#define SFP_EEPROM_A2_ADDR 0x51 +#define SFP_EEPROM_BUS_TYPE I2C_SMBUS_I2C_BLOCK_DATA +#define CPLDA_SFP_NUM 24 +#define CPLDB_SFP_NUM 12 +#define CPLDC_SFP_NUM 18 +#define CPLDA_ADDRESS 0x74 +#define CPLDB_ADDRESS 0x75 +#define CPLDC_ADDRESS 0x76 +#define SFP_13_36_SCL_BASE 0x4 +#define SFP_1_12_SCL_BASE 0x2 +#define SFP_37_54_SCL_BASE 0x5 +#define QSFP_I2C_ENABLE_BASE 0x17 +#define GET_BIT(data, bit, value) value = (data >> bit) & 0x1 +#define SET_BIT(data, bit) data |= (1 << bit) +#define CLEAR_BIT(data, bit) data &= ~(1 << bit) + +enum cpld_croups { cpld_group_a, cpld_group_b, cpld_group_c}; + +static const unsigned short normal_i2c[] = { SFP_EEPROM_A0_ADDR, SFP_EEPROM_A2_ADDR, I2C_CLIENT_END }; +static char *SFP_CPLD_GROUPA_MAPPING[CPLDA_SFP_NUM][16]={0}; +static char *SFP_CPLD_GROUPB_MAPPING[CPLDB_SFP_NUM][16]={0}; +static char *SFP_CPLD_GROUPC_MAPPING[CPLDC_SFP_NUM][16]={0}; + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = 128; +module_param(io_limit, uint, 0); +MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)"); + +/* + * Specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; +module_param(write_timeout, uint, 0); +MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)"); + + +struct porsche_sfp_data { + struct mutex lock; + struct bin_attribute bin; + int use_smbus; + kernel_ulong_t driver_data; + + struct i2c_client *client; +}; + +extern int pegatron_porsche_cpld_read(unsigned short cpld_addr, u8 reg); +extern int pegatron_porsche_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +static ssize_t porsche_sfp_eeprom_read(struct porsche_sfp_data *data, char *buf, + unsigned offset, size_t count) +{ + struct i2c_msg msg[2]; + u8 msgbuf[2]; + struct i2c_client *client = data->client; + unsigned long timeout, read_time; + int status; + + memset(msg, 0, sizeof(msg)); + + if (count > io_limit) + count = io_limit; + + /* Smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + read_time = jiffies; + switch (data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_read_i2c_block_data(client, offset, + count, buf); + break; + case I2C_SMBUS_WORD_DATA: + status = i2c_smbus_read_word_data(client, offset); + if (status >= 0) { + buf[0] = status & 0xff; + if (count == 2) + buf[1] = status >> 8; + status = count; + } + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_read_byte_data(client, offset); + if (status >= 0) { + buf[0] = status; + status = count; + } + break; + default: + status = i2c_transfer(client->adapter, msg, 2); + if (status == 2) + status = count; + } + dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(read_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t porsche_sfp_read(struct porsche_sfp_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) + return count; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->lock); + + while (count) { + ssize_t status; + + status = porsche_sfp_eeprom_read(data, buf, off, count); + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->lock); + + return retval; +} + +static ssize_t +porsche_sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int i; + u8 cpldData = 0; + struct porsche_sfp_data *data; + + /*SFP 1-12*/ + for(i=0; iattr.name, SFP_CPLD_GROUPB_MAPPING[i])) + { + pegatron_porsche_cpld_write(CPLDB_ADDRESS, SFP_1_12_SCL_BASE, i+1); + goto check_done; + } + } + /*SFP 13-36*/ + for(i=0; iattr.name, SFP_CPLD_GROUPA_MAPPING[i])) + { + pegatron_porsche_cpld_write(CPLDA_ADDRESS, SFP_13_36_SCL_BASE, i+1); + goto check_done; + } + } + + /*SFP 37-54*/ + for(i=0; iattr.name, SFP_CPLD_GROUPC_MAPPING[i])) + { + /* Enable QSFP i2c function */ + if(i >= 12) + { + cpldData = 0xff; + cpldData = pegatron_porsche_cpld_read(CPLDC_ADDRESS, QSFP_I2C_ENABLE_BASE); + CLEAR_BIT(cpldData, i-12); + pegatron_porsche_cpld_write(CPLDC_ADDRESS, QSFP_I2C_ENABLE_BASE, cpldData); + } + pegatron_porsche_cpld_write(CPLDC_ADDRESS, SFP_37_54_SCL_BASE, i+1); + goto check_done; + } + } + +check_done: + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + return porsche_sfp_read(data, buf, off, count); +} + +#define SFP_EEPROM_ATTR(_num) \ + static struct bin_attribute sfp##_num##_eeprom_attr = { \ + .attr = { \ + .name = __stringify(sfp##_num##_eeprom), \ + .mode = S_IRUGO\ + }, \ + .size = SFP_EEPROM_SIZE, \ + .read = porsche_sfp_bin_read, \ + } + +SFP_EEPROM_ATTR(1);SFP_EEPROM_ATTR(2);SFP_EEPROM_ATTR(3);SFP_EEPROM_ATTR(4);SFP_EEPROM_ATTR(5);SFP_EEPROM_ATTR(6);SFP_EEPROM_ATTR(7);SFP_EEPROM_ATTR(8);SFP_EEPROM_ATTR(9); +SFP_EEPROM_ATTR(10);SFP_EEPROM_ATTR(11);SFP_EEPROM_ATTR(12);SFP_EEPROM_ATTR(13);SFP_EEPROM_ATTR(14);SFP_EEPROM_ATTR(15);SFP_EEPROM_ATTR(16);SFP_EEPROM_ATTR(17);SFP_EEPROM_ATTR(18); +SFP_EEPROM_ATTR(19);SFP_EEPROM_ATTR(20);SFP_EEPROM_ATTR(21);SFP_EEPROM_ATTR(22);SFP_EEPROM_ATTR(23);SFP_EEPROM_ATTR(24);SFP_EEPROM_ATTR(25);SFP_EEPROM_ATTR(26);SFP_EEPROM_ATTR(27); +SFP_EEPROM_ATTR(28);SFP_EEPROM_ATTR(29);SFP_EEPROM_ATTR(30);SFP_EEPROM_ATTR(31);SFP_EEPROM_ATTR(32);SFP_EEPROM_ATTR(33);SFP_EEPROM_ATTR(34);SFP_EEPROM_ATTR(35);SFP_EEPROM_ATTR(36); +SFP_EEPROM_ATTR(37);SFP_EEPROM_ATTR(38);SFP_EEPROM_ATTR(39);SFP_EEPROM_ATTR(40);SFP_EEPROM_ATTR(41);SFP_EEPROM_ATTR(42);SFP_EEPROM_ATTR(43);SFP_EEPROM_ATTR(44);SFP_EEPROM_ATTR(45); +SFP_EEPROM_ATTR(46);SFP_EEPROM_ATTR(47);SFP_EEPROM_ATTR(48);SFP_EEPROM_ATTR(49);SFP_EEPROM_ATTR(50);SFP_EEPROM_ATTR(51);SFP_EEPROM_ATTR(52);SFP_EEPROM_ATTR(53);SFP_EEPROM_ATTR(54); + +static struct bin_attribute *porsche_cpldA_sfp_epprom_attributes[] = { + &sfp13_eeprom_attr, &sfp14_eeprom_attr, &sfp15_eeprom_attr, &sfp16_eeprom_attr, &sfp17_eeprom_attr, &sfp18_eeprom_attr, &sfp19_eeprom_attr, &sfp20_eeprom_attr, + &sfp21_eeprom_attr, &sfp22_eeprom_attr, &sfp23_eeprom_attr, &sfp24_eeprom_attr, &sfp25_eeprom_attr, &sfp26_eeprom_attr, &sfp27_eeprom_attr, &sfp28_eeprom_attr, + &sfp29_eeprom_attr, &sfp30_eeprom_attr, &sfp31_eeprom_attr, &sfp32_eeprom_attr, &sfp33_eeprom_attr, &sfp34_eeprom_attr, &sfp35_eeprom_attr, &sfp36_eeprom_attr, + NULL +}; + +static struct bin_attribute *porsche_cpldB_sfp_epprom_attributes[] = { + &sfp1_eeprom_attr, &sfp2_eeprom_attr, &sfp3_eeprom_attr, &sfp4_eeprom_attr, &sfp5_eeprom_attr, &sfp6_eeprom_attr, &sfp7_eeprom_attr, &sfp8_eeprom_attr, + &sfp9_eeprom_attr, &sfp10_eeprom_attr, &sfp11_eeprom_attr, &sfp12_eeprom_attr, + NULL +}; + +static struct bin_attribute *porsche_cpldC_sfp_epprom_attributes[] = { + &sfp37_eeprom_attr, &sfp38_eeprom_attr, &sfp39_eeprom_attr, &sfp40_eeprom_attr, &sfp41_eeprom_attr, &sfp42_eeprom_attr, &sfp43_eeprom_attr, &sfp44_eeprom_attr, + &sfp45_eeprom_attr, &sfp46_eeprom_attr, &sfp47_eeprom_attr, &sfp48_eeprom_attr, &sfp49_eeprom_attr, &sfp50_eeprom_attr, &sfp51_eeprom_attr, &sfp52_eeprom_attr, + &sfp53_eeprom_attr, &sfp54_eeprom_attr, + NULL +}; + +static const struct attribute_group porsche_sfpA_group = { .bin_attrs = porsche_cpldA_sfp_epprom_attributes}; +static const struct attribute_group porsche_sfpB_group = { .bin_attrs = porsche_cpldB_sfp_epprom_attributes}; +static const struct attribute_group porsche_sfpC_group = { .bin_attrs = porsche_cpldC_sfp_epprom_attributes}; + +static int porsche_sfp_device_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) +{ + int use_smbus = SFP_EEPROM_BUS_TYPE; + struct porsche_sfp_data *data; + int err, i; + unsigned num_addresses; + kernel_ulong_t magic; + + data = kzalloc(sizeof(struct porsche_sfp_data) , GFP_KERNEL); + if (!data) + return -ENOMEM; + + mutex_init(&data->lock); + data->use_smbus = use_smbus; + /* + * Export the EEPROM bytes through sysfs, since that's convenient. + * By default, only root should see the data (maybe passwords etc) + */ + + data->client = client; + data->driver_data = dev_id->driver_data; + + sysfs_bin_attr_init(&data->bin); + + switch(dev_id->driver_data) + { + case cpld_group_a: + err = sysfs_create_group(&client->dev.kobj, &porsche_sfpA_group); + if (err) + goto err_clients; + break; + case cpld_group_b: + err = sysfs_create_group(&client->dev.kobj, &porsche_sfpB_group); + if (err) + goto err_clients; + break; + case cpld_group_c: + err = sysfs_create_group(&client->dev.kobj, &porsche_sfpC_group); + if (err) + goto err_clients; + break; + default: + printk(KERN_ALERT "i2c_check_CPLD failed\n"); + err = -EIO; + break; + } + + i2c_set_clientdata(client, data); + + return 0; + +err_clients: + kfree(data); + return err; +} + +static int porsche_sfp_device_remove(struct i2c_client *client) +{ + struct porsche_sfp_data *data; + int i; + + data = i2c_get_clientdata(client); + + switch(data->driver_data) + { + case cpld_group_a: + sysfs_remove_group(&client->dev.kobj, &porsche_sfpA_group); + break; + case cpld_group_b: + sysfs_remove_group(&client->dev.kobj, &porsche_sfpB_group); + break; + case cpld_group_c: + sysfs_remove_group(&client->dev.kobj, &porsche_sfpC_group); + break; + default: + dev_dbg(&client->dev, "i2c_remove_CPLD failed (0x%x)\n", client->addr); + break; + } + + + return 0; +} + +static const struct i2c_device_id porsche_sfp_id[] = { + { "porsche_sfpA", cpld_group_a }, + { "porsche_sfpB", cpld_group_b }, + { "porsche_sfpC", cpld_group_c }, + {} +}; +MODULE_DEVICE_TABLE(i2c, porsche_sfp_id); + +static struct i2c_driver porsche_sfp_driver = { + .driver = { + .name = "pegatron_porsche_sfp", + }, + .probe = porsche_sfp_device_probe, + .remove = porsche_sfp_device_remove, + .id_table = porsche_sfp_id, + .address_list = normal_i2c, +}; + +static int __init porsche_sfp_init(void) +{ + int i; + + /*SFP 1-12*/ + for(i=0; i"); +MODULE_DESCRIPTION("porsche_cpld_mux driver"); +MODULE_LICENSE("GPL"); + +module_init(porsche_sfp_init); +module_exit(porsche_sfp_exit); + diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/scripts/sensors b/platform/nephos/sonic-platform-modules-pegatron/porsche/scripts/sensors new file mode 100755 index 000000000000..7f9426a0c5ec --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/scripts/sensors @@ -0,0 +1,7 @@ +#!/bin/bash +docker exec -i pmon sensors "$@" + +#To probe sensors not part of lm-sensors +if [ -r /usr/local/bin/porsche_sensors.py ]; then + python /usr/local/bin/porsche_sensors.py get_sensors +fi diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/service/porsche-platform-init.service b/platform/nephos/sonic-platform-modules-pegatron/porsche/service/porsche-platform-init.service new file mode 100644 index 000000000000..8e6f4344715f --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/service/porsche-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Pegastron porsche Platform initialization service +After=local-fs.target +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/pegatron_porsche_util.py install +ExecStop=/usr/local/bin/pegatron_porsche_util.py uninstall +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/utils/pegatron_porsche_util.py b/platform/nephos/sonic-platform-modules-pegatron/porsche/utils/pegatron_porsche_util.py new file mode 100755 index 000000000000..16662081d0cb --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/utils/pegatron_porsche_util.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Pegatron, 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 . + +import sys, getopt +import logging +import os +import commands +import threading + +DEBUG = False + +SFP_MAX_NUM = 48 +CPLDA_SFP_NUM = 24 +CPLDB_SFP_NUM = 12 +CPLDC_SFP_NUM = 18 + +kernel_module = ['i2c_dev', 'i2c-mux-pca954x force_deselect_on_exit=1', 'at24', 'pegatron_porsche_cpld', 'pegatron_hwmon_mcu', 'pegatron_porsche_sfp'] +moduleID = ['pca9544', 'pca9544', '24c02', 'porsche_hwmon_mcu', 'porsche_cpld', 'porsche_cpld', 'porsche_cpld', 'porsche_sfpA', 'porsche_sfpB', 'porsche_sfpC'] +i2c_check_node = ['i2c-0', 'i2c-1'] +device_address = ['0x72', '0x73', '0x54', '0x70', '0x74', '0x75', '0x76', '0x50', '0x50', '0x50'] +device_node= ['i2c-2', 'i2c-6', 'i2c-4', 'i2c-5', 'i2c-6', 'i2c-7', 'i2c-8', 'i2c-6', 'i2c-7', 'i2c-8'] + +i2c_prefix = '/sys/bus/i2c/devices/' +cpld_bus = ['6-0074', '7-0075', '8-0076'] +led_nodes = ['sys_led', 'pwr_led', 'loc_led', 'fan_led', "cpld_allled_ctrl", "serial_led_enable"] + +def dbg_print(string): + if DEBUG == True: + print string + return + +def do_cmd(cmd, show): + logging.info('Run :' + cmd) + status, output = commands.getstatusoutput(cmd) + dbg_print(cmd + "with result:" + str(status)) + dbg_print("output:" + output) + if status: + logging.info('Failed :' + cmd) + if show: + print('Failed :' + cmd) + return status, output + +def check_device_position(num): + for i in range(0, len(i2c_check_node)): + status, output = do_cmd("echo " + moduleID[num] + " " + device_address[num] + " > " + i2c_prefix + i2c_check_node[i] + "/new_device", 0) + status, output = do_cmd("ls " + i2c_prefix + device_node[num], 0) + device_node[num] = i2c_check_node[i] + + if status: + status, output = do_cmd("echo " + device_address[num] + " > " + i2c_prefix + i2c_check_node[i] + "/delete_device", 0) + else: + return + + return + +def install_device(): + for i in range(0, len(moduleID)): + if moduleID[i] == "pca9544": + check_device_position(i) + else: + status, output = do_cmd("echo " + moduleID[i] + " " + device_address[i] + " > " + i2c_prefix + device_node[i] + "/new_device", 1) + + return + +def check_driver(): + for i in range(0, len(kernel_module)): + status, output = do_cmd("lsmod | grep " + kernel_module[i], 0) + if status: + status, output = do_cmd("modprobe " + kernel_module[i], 1) + + return + +def do_install(): + status, output = do_cmd("depmod -a", 1) + + check_driver() + install_device() + + return + +def do_uninstall(): + for i in range(0, len(kernel_module)): + status, output = do_cmd("modprobe -r " + kernel_module[i], 1) + + for i in range(0, len(moduleID)): + status, output = do_cmd("echo " + device_address[i] + " > " + i2c_prefix + i2c_check_node[i] + "/delete_device", 0) + + return + +led_command = {'sys_led': {'green':'0', 'amber':'1', 'off':'2', 'blink_green':'3', 'blink_amber':'4'}, + 'pwr_led': {'green':'0', 'amber':'1', 'off':'2', 'blink_green':'3', 'blink_amber':'4'}, + 'loc_led': {'on':'0', 'off':'1', 'blink':'2'}, + 'fan_led': {'green':'0', 'amber':'1', 'off':'2', 'blink_green':'3', 'blink_amber':'4'}, + 'cpld_allled_ctrl': {'off':'0', 'mix':'1', 'amber':'2', 'normal':'3'}, + 'serial_led_enable': {'disable':'0', 'enable':'1'}} + +def set_led(args): + """ + Usage: %(scriptName)s set led object command + + object: + sys_led : set SYS led [command: off|green|amber|blink_green|blink_amber] + pwr_led : set PWR led [command: off|green|amber|blink_green|blink_amber] + loc_led : set LOCATOR led [command: off|on|blink] + fan_led : set FAN led [command: off|green|amber|blink_green|blink_amber] + """ + if args[0] not in led_command: + print set_led.__doc__ + sys.exit(0) + + for i in range(0,len(led_nodes)): + if args[0] == led_nodes[i]: + node = i2c_prefix + cpld_bus[1] + '/'+ led_nodes[i] + + command = led_command[args[0]] + data = command[args[1]] + + status, output = do_cmd("echo "+ str(data) + " > "+ node, 1) + + return + +def set_device(args): + """ + Usage: %(scriptName)s command object + + command: + led : set status led sys_led|pwr_led|loc_led|mst_led|fan_led|digit_led + """ + + if args[0] == 'led': + set_led(args[1:]) + return + else: + print set_device.__doc__ + + return + +device_init = {'led': [['led', 'sys_led', 'green'], ['led', 'pwr_led', 'green'], ['led', 'fan_led', 'green'], ['led', 'cpld_allled_ctrl', 'normal'], ['led', 'serial_led_enable', 'enable']]} + +def pega_init(): + #set led + for i in range(0,len(device_init['led'])): + set_device(device_init['led'][i]) + + #set tx_disable + for x in range(0, SFP_MAX_NUM-1): + if x < CPLDB_SFP_NUM: + bus = cpld_bus[1] + elif x < CPLDB_SFP_NUM + CPLDA_SFP_NUM: + bus = cpld_bus[0] + else: + bus = cpld_bus[2] + + nodes = i2c_prefix + bus + '/sfp' + str(x+1) + '_tx_disable' + dbg_print("SFP_TX_DISABLE NODES: " + nodes) + status, output = do_cmd("echo 0 > "+ nodes, 1) + + return + +def main(): + """ + Usage: %(scriptName)s command object + + command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + set : change board setting [led] + debug : debug info [on/off] + """ + + if len(sys.argv)<2: + print main.__doc__ + + for arg in sys.argv[1:]: + if arg == 'install': + do_install() + pega_init() + elif arg == 'uninstall': + do_uninstall() + elif arg == 'set': + if len(sys.argv[2:])<1: + print main.__doc__ + else: + set_device(sys.argv[2:]) + return + elif arg == 'debug': + if sys.argv[2] == 'on': + DEBUG = True + else: + DEBUG = False + else: + print main.__doc__ + +if __name__ == "__main__": + main() diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/utils/porsche_sensors.py b/platform/nephos/sonic-platform-modules-pegatron/porsche/utils/porsche_sensors.py new file mode 100755 index 000000000000..40e23ef01b7e --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/utils/porsche_sensors.py @@ -0,0 +1,141 @@ +#!/usr/bin/python + +import os +import sys +import logging + +FAN_NUM = 5 +sensors_path = '/sys/bus/i2c/devices/5-0070/' +sensors_nodes = {'fan_rpm': ['_inner_rpm', '_outer_rpm'], + 'fan_vol': ['ADC8_vol', 'ADC7_vol','ADC6_vol', 'ADC5_vol','ADC4_vol', 'ADC3_vol'], + 'temp':['lm75_49_temp', 'lm75_48_temp', 'SA56004_local_temp','SA56004_remote_temp']} +sensors_type = {'fan_rpm': ['Inner RPM', 'Outer RPM'], + 'fan_vol': ['P0.2', 'P0.6','P0.1', 'P1.5','P0.7', 'P1.6'], + 'temp':['lm75_49_temp', 'lm75_48_temp', 'SA56004_local_temp','SA56004_remote_temp']} + +# Get sysfs attribute +def get_attr_value(attr_path): + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + fd.close() + return retval + +def get_fan_status(number): + attr_value = get_attr_value(sensors_path + "fan" + str(number+1) + "_present") + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + + if(attr_value == 0): + string = "Connect" + else: + string = "Disconnect" + return string + +def get_fan_alert(number): + attr_value = get_attr_value(sensors_path + "fan" + str(number+1) + "_status_alert") + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + + if(attr_value == 0): + string = "Normal" + else: + string = "Abnormal" + return string + +def get_fan_inner_rpm(number): + return get_attr_value(sensors_path + "fan" + str(number+1) + "_inner_rpm") + +def get_fan_outer_rpm(number): + return get_attr_value(sensors_path + "fan" + str(number+1) + "_outer_rpm") + +def get_fan(): + for i in range(0,FAN_NUM): + print " " + #status + string = get_fan_status(i) + print "FAN " + str(i+1) + ":" + ' ' + string + if string=='Disconnect': + continue + + #alert + string = get_fan_alert(i) + print " Status:"+ ' ' + string + + #inner rpm + string = get_fan_inner_rpm(i) + print " Inner RPM:"+ string.rjust(10) + ' RPM' + + #outer rpm + string = get_fan_outer_rpm(i) + print " Outer RPM:"+ string.rjust(10) + ' RPM' + + return + +def get_hwmon(): + print " " + string = get_attr_value(sensors_path + "lm75_48_temp") + print "Sensor A: " + string + " C" + + string = get_attr_value(sensors_path + "lm75_49_temp") + print "Sensor B: " + string + " C" + + return + +def get_voltage(): + print " " + nodes = sensors_nodes['fan_vol'] + types = sensors_type['fan_vol'] + for i in range(0,len(nodes)): + string = get_attr_value(sensors_path + nodes[i]) + print types[i] + ': ' + string + " V" + + return + +def init_fan(): + return + +def main(): + """ + Usage: %(scriptName)s command object + + command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + set : change board setting with fan|led|sfp + """ + + if len(sys.argv)<2: + print main.__doc__ + + for arg in sys.argv[1:]: + if arg == 'fan_init': + init_fan() + elif arg == 'get_sensors': + ver = get_attr_value(sensors_path + "fb_hw_version") + print 'HW Version: ' + ver + ver = get_attr_value(sensors_path + "fb_fw_version") + print 'SW Version: ' + ver + get_fan() + get_hwmon() + get_voltage() + elif arg == 'fan_set': + if len(sys.argv[1:])<1: + print main.__doc__ + else: + set_fan(sys.argv[1:]) + return + else: + print main.__doc__ + +if __name__ == "__main__": + main() diff --git a/platform/p4/SAI-P4-BM b/platform/p4/SAI-P4-BM new file mode 160000 index 000000000000..c763924affd4 --- /dev/null +++ b/platform/p4/SAI-P4-BM @@ -0,0 +1 @@ +Subproject commit c763924affd416df9c4d3e40d4f8ac1cb2be5fff diff --git a/platform/p4/docker-sonic-p4.mk b/platform/p4/docker-sonic-p4.mk new file mode 100644 index 000000000000..534d161631f5 --- /dev/null +++ b/platform/p4/docker-sonic-p4.mk @@ -0,0 +1,29 @@ +# docker image for p4 sonic docker image + +DOCKER_SONIC_P4 = docker-sonic-p4.gz +$(DOCKER_SONIC_P4)_PATH = $(PLATFORM_PATH)/docker-sonic-p4 +$(DOCKER_SONIC_P4)_DEPENDS += $(SWSS) \ + $(SYNCD) \ + $(P4_SWITCH) \ + $(REDIS_TOOLS) \ + $(REDIS_SERVER) \ + $(PYTHON_SWSSCOMMON) \ + $(LIBTEAMDCT) \ + $(LIBTEAM_UTILS) \ + $(SONIC_DEVICE_DATA) \ + $(SONIC_UTILS) \ + $(IPROUTE2) + +# ifeq ($(ROUTING_STACK), quagga) +$(DOCKER_SONIC_P4)_DEPENDS += $(QUAGGA) +# else ifeq ($(ROUTING_STACK), frr) +# $(DOCKER_SONIC_P4)_DEPENDS += $(FRR) +# else +# $(DOCKER_SONIC_P4)_DEPENDS += $(GOBGP) +# endif + +$(DOCKER_SONIC_P4)_FILES += $(CONFIGDB_LOAD_SCRIPT) \ + $(ARP_UPDATE_SCRIPT) + +$(DOCKER_SONIC_P4)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SONIC_P4) diff --git a/platform/p4/docker-sonic-p4/Dockerfile.j2 b/platform/p4/docker-sonic-p4/Dockerfile.j2 new file mode 100644 index 000000000000..09849a7ae143 --- /dev/null +++ b/platform/p4/docker-sonic-p4/Dockerfile.j2 @@ -0,0 +1,82 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY ["sonic-dev.gpg.key", "/etc/apt/"] +RUN apt-key add /etc/apt/sonic-dev.gpg.key +RUN echo "deb http://packages.microsoft.com/repos/sonic-dev/ jessie main" >> /etc/apt/sources.list +RUN apt-get update + +RUN apt-get install -y net-tools \ + arping \ + ethtool \ + tcpdump \ + ifupdown \ + bridge-utils \ + python-ply \ + libqt5core5a \ + libqt5network5 \ + libboost-program-options1.55.0 \ + libboost-system1.55.0 \ + libboost-thread1.55.0 \ + libgmp10 \ + libjudydebian1 \ + libnanomsg0 \ + libdaemon0 \ + libjansson4 \ + libjemalloc1 \ + openssh-client \ + openssh-server \ + libc-ares2 \ + iproute \ + libpython2.7 \ + grub2-common \ + python-click-default-group \ + python-click \ + python-natsort \ + python-tabulate \ + bash-completion \ + libelf1 \ + libmnl0 + +RUN pip install setuptools +RUN pip install py2_ipaddress + +COPY \ +{% for deb in docker_sonic_p4_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_sonic_p4_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +RUN sed -ri 's/^(save .*$)/# \1/g; \ + s/^daemonize yes$/daemonize no/; \ + s/^logfile .*$/logfile ""/; \ + s/^# syslog-enabled no$/syslog-enabled no/; \ + s/^# unixsocket/unixsocket/; \ + s/notify-keyspace-events ""/notify-keyspace-events AKE/; \ + s/^client-output-buffer-limit pubsub [0-9]+mb [0-9]+mb [0-9]+/client-output-buffer-limit pubsub 0 0 0/ \ + ' /etc/redis/redis.conf + +ADD port_config.ini /port_config.ini +ADD rsyslog.conf /etc/rsyslog.conf +COPY ["start.sh", "orchagent.sh", "config_bm.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/configdb-load.sh", "/usr/bin/"] +COPY ["files/arp_update", "/usr/bin"] +RUN echo "docker-sonic-p4" > /etc/hostname +RUN touch /etc/quagga/zebra.conf + +ENTRYPOINT ["/bin/bash"] diff --git a/platform/p4/docker-sonic-p4/config_bm.sh b/platform/p4/docker-sonic-p4/config_bm.sh new file mode 100755 index 000000000000..25de26b4da74 --- /dev/null +++ b/platform/p4/docker-sonic-p4/config_bm.sh @@ -0,0 +1,4 @@ +simple_switch_CLI --pre SimplePreLAG < /usr/share/p4-sai-bm/bridge_default_config.txt +simple_switch_CLI < /usr/share/p4-sai-bm/bridge_default_config_mirror.txt +simple_switch_CLI --pre SimplePreLAG --thrift-port 9091 < /usr/share/p4-sai-bm/router_default_config.txt +simple_switch_CLI --thrift-port 9091 < /usr/share/p4-sai-bm/router_default_config_mirror.txt \ No newline at end of file diff --git a/platform/p4/docker-sonic-p4/orchagent.sh b/platform/p4/docker-sonic-p4/orchagent.sh new file mode 100755 index 000000000000..7e250dfa20e9 --- /dev/null +++ b/platform/p4/docker-sonic-p4/orchagent.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +MAC_ADDRESS=`ip link show eth0 | grep ether | awk '{print $2}'` + +# Create a folder for SsWW record files +mkdir -p /var/log/swss +ORCHAGENT_ARGS="-d /var/log/swss " + +# Set orchagent pop batch size to 8192 +ORCHAGENT_ARGS+="-b 8192 " + +# Set mac address +ORCHAGENT_ARGS+="-m $MAC_ADDRESS" + +exec /usr/bin/orchagent ${ORCHAGENT_ARGS} diff --git a/platform/p4/docker-sonic-p4/port_config.ini b/platform/p4/docker-sonic-p4/port_config.ini new file mode 100644 index 000000000000..2a88c4a7235b --- /dev/null +++ b/platform/p4/docker-sonic-p4/port_config.ini @@ -0,0 +1,33 @@ +# name lanes +Ethernet0 0 +Ethernet1 1 +Ethernet2 2 +Ethernet3 3 +Ethernet4 4 +Ethernet5 5 +Ethernet6 6 +Ethernet7 7 +Ethernet8 8 +Ethernet9 9 +Ethernet10 10 +Ethernet11 11 +Ethernet12 12 +Ethernet13 13 +Ethernet14 14 +Ethernet15 15 +Ethernet16 16 +Ethernet17 17 +Ethernet18 18 +Ethernet19 19 +Ethernet20 20 +Ethernet21 21 +Ethernet22 22 +Ethernet23 23 +Ethernet24 24 +Ethernet25 25 +Ethernet26 26 +Ethernet27 27 +Ethernet28 28 +Ethernet29 29 +Ethernet30 30 +Ethernet31 31 \ No newline at end of file diff --git a/platform/p4/docker-sonic-p4/rsyslog.conf b/platform/p4/docker-sonic-p4/rsyslog.conf new file mode 100644 index 000000000000..79926a8b30c7 --- /dev/null +++ b/platform/p4/docker-sonic-p4/rsyslog.conf @@ -0,0 +1,69 @@ +############################################################################### +# Managed by Ansible +# file: ansible/roles/acs/templates/rsyslog.conf.j2 +############################################################################### +# +# /etc/rsyslog.conf Configuration file for rsyslog. +# +# For more information see +# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html + + +################# +#### MODULES #### +################# + +$ModLoad imuxsock # provides support for local system logging +#$ModLoad imklog # provides kernel logging support +#$ModLoad immark # provides --MARK-- message capability + +# provides UDP syslog reception +#$ModLoad imudp +#$UDPServerRun 514 + +# provides TCP syslog reception +#$ModLoad imtcp +#$InputTCPServerRun 514 + + +########################### +#### GLOBAL DIRECTIVES #### +########################### +#Set remote syslog server +#*.* @172.17.0.1:514 +#Set local syslog +*.* /var/log/messages + +# +# Use traditional timestamp format. +# To enable high precision timestamps, comment out the following line. +# +#$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat + +# Define a custom template +$template SONiCFileFormat,"%TIMESTAMP%.%timestamp:::date-subseconds% %HOSTNAME% %syslogseverity-text:::uppercase% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" +$ActionFileDefaultTemplate SONiCFileFormat + +# +# Set the default permissions for all log files. +# +$FileOwner root +$FileGroup adm +$FileCreateMode 0640 +$DirCreateMode 0755 +$Umask 0022 + +# +# Where to place spool and state files +# +$WorkDirectory /var/spool/rsyslog + +# +# Include all config files in /etc/rsyslog.d/ +# +$IncludeConfig /etc/rsyslog.d/*.conf + + +############### +#### RULES #### +############### diff --git a/platform/p4/docker-sonic-p4/sonic-dev.gpg.key b/platform/p4/docker-sonic-p4/sonic-dev.gpg.key new file mode 100644 index 000000000000..fb9a37901bc7 --- /dev/null +++ b/platform/p4/docker-sonic-p4/sonic-dev.gpg.key @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQENBFQ1bTIBCAC7oGfkv/ck0XsLuG8cdcSB2ISqxFAcBvH9BitEtxmpW2uhykKk +xY4rVD/4Uys1s3PF1/64QfPR+hYcewueOwz0ZAcLyFXXk4McICXaPq3NrLiWYKKX +UZLnrPzcrGZoW/kHDDp4OmBiDmT1PGvZlpuimwkMCusUzIr7Cbbp2dIy8MERL5tA +LcgLu3KL6clJ+aTW2jgepI1D7sTepOeGd7eRSb5njKg2M7k/93v/7MipZxiVtyXH +B74YiK6jSbst5JpuYsLa/Dqryvx7Xq3n53oif892pv3euTduo1fYw8Hgh/OOYdeT +c9WCj03KA1jCSFURjdrug0kR8BPlfjqtRLXFABEBAAG0JE1TIE9wZW4gVGVjaCA8 +aW50ZXJvcEBtaWNyb3NvZnQuY29tPokBOAQTAQIAIgUCVDVtMgIbAwYLCQgHAwIG +FQgCCQoLBBYCAwECHgECF4AACgkQsCxG30F6CJO1uAf/cmL68bM8YgF/61hkaY56 +LqrppUTJH/w4fKq47Pf6KfgSLvxfNU6soi2KHYRjIvTRx3tV4vUM5n2plaQg2s8V +/Epg4FeIRTk75YwiHAzLhLnp5cdUaTvC4j4mwxoB6j9Ty+fXJwQ0MvpDhIZb9vM4 +GXw/fEQHCT4f3gx4nReeqE+FB2wVHleX9+Lpodu98JyJTKJRBRHYLqy6S+/lyp2W +aBlsI1LOqBcx1uRK24U7duIpbYwIyrx0cafSruqR2GjVdu+imkhHyUn52VbzYhq1 +af0rqYiZ1VOamVOG0By8+hVyNa1MLc1K2uWGs0o5fDe9F5/swbvLHVXI+M50Vs+m +J7kBDQRUNW0yAQgAu7DkTVj0ZQC4F7bFivAwrdby8gCakTXOl1kcK622hjRJ8nam +aZeW+eADfLRsTmdUmXgZu1YWS5Gn2ZVngC8SGPUBT071+oRETCz4uNB7IimB9QfP +++orI6o2vmnVVsq5wWCbEdNU+TCVv1zjrYev5lwckkKpjHt6o8MNoX2DFuQymSyR +eZKaqhdKmcji4Ke7OIYqwgPjch3wxzE1b5gNOR/iwxWyjjOffZPLr/VhIfIJRs86 +dSXrwjHtEh810SKDLghHM0VAdY34nyC5ZZ61yhts5HtQDFK+9mNpH1mkc4gDBlgG +266pVvknumK6lPNm/osF/cpjWmEw24ypcQIvOQARAQABiQEfBBgBAgAJBQJUNW0y +AhsMAAoJELAsRt9BegiTMBUH/0sZ6gZy7mCTSAYT+NSXLFtGC2zNUVL80SWvfgYm +k9XPVI22MrefZfQ6M01RylyxtWXjRM8UoN8SDKWPpXumzJf831f/7om5zwutaG7b +tjDPYqRKJSbAIFZu2mN+uLrNQ2SV6XK7FoV0dtcrEX9S7RICb6i19D+70+Oh/qgU +R04H1jqS29XBzqAlIzdBoA+sYAwbOIJsSL3YyNQcUv3B5+5yR/bo/L8pnUJt6iuL +nWW+mi7r8gWPHDSrcdYq1TmmlOM7CwZPgWRZzkQPSeZz52Tt7IP47eyGJ09U4PIf +FtMH1ElL2UgHoA/F9Q88e7LkztaTqE59uXWbIYyuSMJVvRU= +=sb3d +-----END PGP PUBLIC KEY BLOCK----- diff --git a/platform/p4/docker-sonic-p4/start.sh b/platform/p4/docker-sonic-p4/start.sh new file mode 100755 index 000000000000..7c8f9ce151c2 --- /dev/null +++ b/platform/p4/docker-sonic-p4/start.sh @@ -0,0 +1,91 @@ +#!/bin/bash -e + +# generate configuration +[ -d /etc/sonic ] || mkdir -p /etc/sonic + +if ! ip link show eth0 &> /dev/null; then + ip link add eth0 type dummy +fi + +SYSTEM_MAC_ADDRESS=$(ip link show eth0 | grep ether | awk '{print $2}') +sonic-cfggen -a '{"DEVICE_METADATA":{"localhost": {"mac": "'$SYSTEM_MAC_ADDRESS'"}}}' --print-data > /etc/sonic/init_cfg.json + +if [ -f /etc/sonic/config_db.json ]; then + sonic-cfggen -j /etc/sonic/config_db.json -j /etc/sonic/init_cfg.json --print-data > /tmp/config_db.json + mv /tmp/config_db.json /etc/sonic/config_db.json +else + sonic-cfggen -j /etc/sonic/init_cfg.json --print-data > /etc/sonic/config_db.json +fi + +mkdir -p /etc/swss/config.d/ + +rm -f /var/run/rsyslogd.pid + +echo "Start rsyslogd" +supervisorctl start rsyslogd + +mkdir -p /var/run/redis + +echo "Start redis" +supervisorctl start redis-server + +echo "Veth Setup" +veth_setup.sh > /tmp/veth_setup.log + +echo "Start BM" +rm -rf bm_logs/bridge_log.* +rm -rf bm_logs/router_log.* +rm -rf log.txt +mkdir -p bm_logs +supervisorctl start bm_bridge +supervisorctl start bm_router + +sleep 10 +echo "BM Default config" +config_bm.sh > /tmp/config_bm.log + +/usr/bin/configdb-load.sh + +echo "Start syncd" +supervisorctl start syncd + +echo "Start orchagent" +supervisorctl start orchagent + +echo "Start portsyncd" +supervisorctl start portsyncd + +echo "Start intfsyncd" +supervisorctl start intfsyncd + +echo "Start neighsyncd" +supervisorctl start neighsyncd + +echo "Start teamsyncd" +supervisorctl start teamsyncd + +echo "Start fpmsyncd" +supervisorctl start fpmsyncd + +echo "Start intfmgrd" +supervisorctl start intfmgrd + +echo "Start vlanmgrd" +supervisorctl start vlanmgrd + +echo "Start zebra" +supervisorctl start zebra + +echo "Start bgpd" +supervisorctl start bgpd + +if [ -f /etc/swss/config.d/default_config.json ]; then + swssconfig /etc/swss/config.d/default_config.json +fi + +# Start arp_update when VLAN exists +VLAN=`sonic-cfggen -d -v 'VLAN.keys() | join(" ") if VLAN'` +if [ "$VLAN" != "" ]; then + echo "Start arp_update" + supervisorctl start arp_update +fi diff --git a/platform/p4/docker-sonic-p4/supervisord.conf b/platform/p4/docker-sonic-p4/supervisord.conf new file mode 100644 index 000000000000..5815689f9301 --- /dev/null +++ b/platform/p4/docker-sonic-p4/supervisord.conf @@ -0,0 +1,141 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=false + +[program:start.sh] +command=/usr/bin/start.sh +priority=1 +autostart=true +autorestart=false +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:bm_router] +command=ip netns exec sw_net simple_switch -i 0@router_port1 -i 250@router_cpu_port --thrift-port 9091 --log-file bm_logs/router_log --log-flush --notifications-addr ipc:///tmp/bmv2-router-notifications.ipc /usr/share/p4-sai-bm/sai_router.json +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:bm_bridge] +command=ip netns exec sw_net simple_switch -i 0@sw_port0 -i 1@sw_port1 -i 2@sw_port2 -i 3@sw_port3 -i 4@sw_port4 -i 5@sw_port5 -i 6@sw_port6 -i 7@sw_port7 -i 7@sw_port7 -i 8@sw_port8 -i 9@sw_port9 -i 10@sw_port10 -i 11@sw_port11 -i 12@sw_port12 -i 13@sw_port13 -i 14@sw_port14 -i 15@sw_port15 -i 16@sw_port16 -i 17@sw_port17 -i 18@sw_port18 -i 19@sw_port19 -i 20@sw_port20 -i 21@sw_port21 -i 22@sw_port22 -i 23@sw_port23 -i 24@sw_port24 -i 25@sw_port25 -i 26@sw_port26 -i 27@sw_port27 -i 28@sw_port28 -i 29@sw_port29 -i 30@sw_port30 -i 31@sw_port31 -i 250@cpu_port -i 251@router_port0 --log-file bm_logs/bridge_log --log-flush /usr/share/p4-sai-bm/sai_bridge.json & +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:redis-server] +command=/usr/bin/redis-server /etc/redis/redis.conf +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:syncd] +command=/usr/bin/syncd -u +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:orchagent] +command=/usr/bin/orchagent.sh +priority=5 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:portsyncd] +command=/usr/bin/portsyncd -p /port_config.ini +priority=6 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:intfsyncd] +command=/usr/bin/intfsyncd +priority=7 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:neighsyncd] +command=/usr/bin/neighsyncd +priority=8 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:teamsyncd] +command=/usr/bin/teamsyncd +priority=9 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:vlanmgrd] +command=/usr/bin/vlanmgrd +priority=10 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:intfmgrd] +command=/usr/bin/intfmgrd +priority=11 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:zebra] +command=/usr/lib/quagga/zebra -A 127.0.0.1 +priority=12 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:bgpd] +command=/usr/lib/quagga/bgpd -A 127.0.0.1 -F +priority=13 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:fpmsyncd] +command=/usr/bin/fpmsyncd +priority=14 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:arp_update] +command=/usr/bin/arp_update +priority=15 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/p4/libsaithrift-dev.mk b/platform/p4/libsaithrift-dev.mk new file mode 100644 index 000000000000..68aec8ec3f2e --- /dev/null +++ b/platform/p4/libsaithrift-dev.mk @@ -0,0 +1,7 @@ +# libsaithrift-dev package + +LIBSAITHRIFT_DEV_P4 = libsaithrift-dev_1.0.4_amd64.deb +$(LIBSAITHRIFT_DEV_P4)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV_P4)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(THRIFT_COMPILER) $(P4_SWITCH) +$(LIBSAITHRIFT_DEV_P4)_RDEPENDS += $(LIBTHRIFT) $(P4_SWITCH) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV_P4) diff --git a/platform/p4/p4-bmv.mk b/platform/p4/p4-bmv.mk new file mode 100644 index 000000000000..affb0d5ac824 --- /dev/null +++ b/platform/p4/p4-bmv.mk @@ -0,0 +1,7 @@ +# p4 bmv package + +P4_BMV = sai-p4-bm_1.0.0_amd64.deb +$(P4_BMV)_DEPENDS += $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(P4C_BM) +$(P4_BMV)_RDEPENDS += $(LIBTHRIFT) $(PYTHON_THRIFT) $(THRIFT_COMPILER) +$(P4_BMV)_SRC_PATH = $(PLATFORM_PATH)/SAI-P4-BM/p4-switch +SONIC_DPKG_DEBS += $(P4_BMV) diff --git a/platform/p4/p4-hlir.mk b/platform/p4/p4-hlir.mk new file mode 100644 index 000000000000..61307c7ff79a --- /dev/null +++ b/platform/p4/p4-hlir.mk @@ -0,0 +1,9 @@ +# p4 bmv package + +P4_HLIR_V1_1 = python-p4-hlir-v1-1_1.1.7-1_all.deb +$(P4_HLIR_V1_1)_SRC_PATH = $(PLATFORM_PATH)/p4-hlir/p4-hlir-v1.1 +SONIC_PYTHON_STDEB_DEBS += $(P4_HLIR_V1_1) + +P4_HLIR = python-p4-hlir_0.9.36-1_all.deb +$(P4_HLIR)_SRC_PATH = $(PLATFORM_PATH)/p4-hlir/p4-hlir +SONIC_PYTHON_STDEB_DEBS += $(P4_HLIR) diff --git a/platform/p4/p4-hlir/p4-hlir b/platform/p4/p4-hlir/p4-hlir new file mode 160000 index 000000000000..0ab8e58f8a92 --- /dev/null +++ b/platform/p4/p4-hlir/p4-hlir @@ -0,0 +1 @@ +Subproject commit 0ab8e58f8a92ee469235028430795088af9cda77 diff --git a/platform/p4/p4-hlir/p4-hlir-v1.1 b/platform/p4/p4-hlir/p4-hlir-v1.1 new file mode 160000 index 000000000000..fdee55e2567f --- /dev/null +++ b/platform/p4/p4-hlir/p4-hlir-v1.1 @@ -0,0 +1 @@ +Subproject commit fdee55e2567fe65463f328d70558b5079894b420 diff --git a/platform/p4/p4-switch.mk b/platform/p4/p4-switch.mk new file mode 100644 index 000000000000..fb092fa2c5f3 --- /dev/null +++ b/platform/p4/p4-switch.mk @@ -0,0 +1,7 @@ +# p4 sai adapter package + +P4_SWITCH = p4-sai-adapter_0.1-0_amd64.deb +$(P4_SWITCH)_DEPENDS += $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(P4_BMV) +$(P4_SWITCH)_RDEPENDS += $(LIBTHRIFT) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(P4_BMV) +$(P4_SWITCH)_SRC_PATH = $(PLATFORM_PATH)/SAI-P4-BM/sai_adapter +SONIC_DPKG_DEBS += $(P4_SWITCH) diff --git a/platform/p4/p4c-bm.mk b/platform/p4/p4c-bm.mk new file mode 100644 index 000000000000..1982ee359212 --- /dev/null +++ b/platform/p4/p4c-bm.mk @@ -0,0 +1,7 @@ +# p4c bm package + +P4C_BM = python-p4c-bm_1.0.0-5415c416-1_all.deb +$(P4C_BM)_SRC_PATH = $(PLATFORM_PATH)/p4c-bm/p4c-bm +$(P4C_BM)_DEPENDS += $(TENJIN) $(P4_HLIR) $(P4_HLIR_V1_1) +$(P4C_BM)_RDEPENDS += $(TENJIN) $(P4_HLIR) $(P4_HLIR_V1_1) +SONIC_PYTHON_STDEB_DEBS += $(P4C_BM) diff --git a/platform/p4/p4c-bm/p4c-bm b/platform/p4/p4c-bm/p4c-bm new file mode 160000 index 000000000000..5415c4160aff --- /dev/null +++ b/platform/p4/p4c-bm/p4c-bm @@ -0,0 +1 @@ +Subproject commit 5415c4160aff025f27fe45301c62aa9aeb4bab40 diff --git a/platform/p4/rules.mk b/platform/p4/rules.mk new file mode 100644 index 000000000000..7fe6a60fadac --- /dev/null +++ b/platform/p4/rules.mk @@ -0,0 +1,14 @@ +# include $(PLATFORM_PATH)/p4-softswitch.mk +include $(PLATFORM_PATH)/tenjin.mk +include $(PLATFORM_PATH)/p4-hlir.mk +include $(PLATFORM_PATH)/p4c-bm.mk +# include $(PLATFORM_PATH)/p4-sai-bm.mk +include $(PLATFORM_PATH)/p4-bmv.mk +include $(PLATFORM_PATH)/p4-switch.mk +include $(PLATFORM_PATH)/docker-sonic-p4.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk + +SONIC_ALL += $(DOCKER_SONIC_P4) + +$(LIBSAIREDIS)_DEPENDS += $(P4_SWITCH) $(LIBSAITHRIFT_DEV_P4) +$(LIBSAIREDIS)_RDEPENDS += $(P4_SWITCH) diff --git a/platform/p4/tenjin.mk b/platform/p4/tenjin.mk new file mode 100644 index 000000000000..a9f38437d972 --- /dev/null +++ b/platform/p4/tenjin.mk @@ -0,0 +1,5 @@ +# tenjin package + +TENJIN = python-tenjin_1.1.1-1_all.deb +$(TENJIN)_SRC_PATH = $(PLATFORM_PATH)/tenjin +SONIC_MAKE_DEBS += $(TENJIN) diff --git a/platform/p4/tenjin/Makefile b/platform/p4/tenjin/Makefile new file mode 100644 index 000000000000..83b27d390abc --- /dev/null +++ b/platform/p4/tenjin/Makefile @@ -0,0 +1,19 @@ +SHELL = /bin/bash +.ONESHELL: + +TENJIN_VERSION = 1.1.1 +TENJIN_VERSION_FULL = $(TENJIN_VERSION)-1 + +MAIN_TARGET = python-tenjin_$(TENJIN_VERSION_FULL)_all.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf Tenjin-$(TENJIN_VERSION) + + wget -nc https://pypi.python.org/packages/source/T/Tenjin/Tenjin-$(TENJIN_VERSION).tar.gz + tar xzf Tenjin-$(TENJIN_VERSION).tar.gz + + pushd Tenjin-$(TENJIN_VERSION) + python setup.py --command-packages=stdeb.command bdist_deb + popd + + mv Tenjin-$(TENJIN_VERSION)/deb_dist/$* $(DEST)/ diff --git a/platform/vs/README.vsdocker.md b/platform/vs/README.vsdocker.md new file mode 100644 index 000000000000..42e1cafc8469 --- /dev/null +++ b/platform/vs/README.vsdocker.md @@ -0,0 +1,75 @@ +HOWTO Use Virtual Switch (Docker) + + +1. Create a docker with 32 front panel port + +``` +$ docker run -id --name sw debian bash +$ sudo ./create_vnet.sh sw +$ ip netns list +sw-srv31 (id: 37) +sw-srv30 (id: 35) +sw-srv29 (id: 34) +sw-srv28 (id: 33) +sw-srv27 (id: 32) +sw-srv26 (id: 31) +sw-srv25 (id: 30) +sw-srv24 (id: 29) +sw-srv23 (id: 28) +sw-srv22 (id: 27) +sw-srv21 (id: 26) +sw-srv20 (id: 25) +sw-srv19 (id: 24) +sw-srv18 (id: 23) +sw-srv17 (id: 22) +sw-srv16 (id: 21) +sw-srv15 (id: 20) +sw-srv14 (id: 19) +sw-srv13 (id: 18) +sw-srv12 (id: 17) +sw-srv11 (id: 16) +sw-srv10 (id: 15) +sw-srv9 (id: 14) +sw-srv8 (id: 13) +sw-srv7 (id: 12) +sw-srv6 (id: 11) +sw-srv5 (id: 10) +sw-srv4 (id: 9) +sw-srv3 (id: 8) +sw-srv2 (id: 7) +sw-srv1 (id: 6) +sw-srv0 (id: 5) +``` + +2. Start sonic virtual switch docker + +``` +$ docker run --privileged --network container:sw --name vs -d docker-sonic-vs +``` + +3. Setup IP in the virtual switch docker + +``` +$ docker exec -it vs bash +root@2e9b5c2dc2a2:/# ifconfig Ethernet0 10.0.0.0/31 up +root@2e9b5c2dc2a2:/# ifconfig Ethernet4 10.0.0.2/31 up +``` + +4. Setup IP in the server network namespace + +``` +$ sudo ip netns exec sw-srv0 ifconfig eth0 10.0.0.1/31 +$ sudo ip netns exec sw-srv0 ip route add default via 10.0.0.0 +$ sudo ip netns exec sw-srv1 ifconfig eth0 10.0.0.3/31 +$ sudo ip netns exec sw-srv1 ip route add default via 10.0.0.2 +``` + +5. Ping from sw-srv0 to sw-srv1 + +``` +$ sudo ip netns exec sw-srv0 ping 10.0.0.3 +PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data. +64 bytes from 10.0.0.3: icmp_seq=1 ttl=63 time=0.137 ms +64 bytes from 10.0.0.3: icmp_seq=2 ttl=63 time=0.148 ms +64 bytes from 10.0.0.3: icmp_seq=3 ttl=63 time=0.149 ms +``` diff --git a/platform/vs/README.vsvm.md b/platform/vs/README.vsvm.md new file mode 100644 index 000000000000..d627859578b4 --- /dev/null +++ b/platform/vs/README.vsvm.md @@ -0,0 +1,35 @@ +HOWTO Use Virtual Switch (VM) + +1. Install libvirt, kvm, qemu + +``` +sudo apt-get install libvirt-clients qemu-kvm libvirt-bin +``` + +2. Create SONiC VM + +``` +$ virsh +Welcome to virsh, the virtualization interactive terminal. + +Type: 'help' for help with commands + 'quit' to quit + +virsh # +virsh # create sonic.xml +Domain sonic created from sonic.xml + +virsh # +``` + +2. Connect SONiC VM via console + +``` +$ telnet 127.0.0.1 7000 +``` + +3. Connect SONiC VM via SSH + +``` +$ ssh -p 3040 admin@127.0.0.1 +``` diff --git a/platform/vs/create_vnet.sh b/platform/vs/create_vnet.sh new file mode 100755 index 000000000000..4746e16cbbaf --- /dev/null +++ b/platform/vs/create_vnet.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +SWNAME=$1 + +pid=$(docker inspect --format '{{.State.Pid}}' $SWNAME) + +echo Seting up servers + +SERVERS=31 + +for srv in `seq 0 $SERVERS`; do + + SRV="$SWNAME-srv$srv" + + NSS="ip netns exec $SRV" + + ip netns add $SRV + + $NSS ip addr add 127.0.0.1/8 dev lo + $NSS ip addr add ::1/128 dev lo + $NSS ip link set dev lo up + + # add virtual link between neighbor and the virtual switch docker + + IF="eth$((srv+1))" + + ip link add ${SRV}eth0 type veth peer name $IF + ip link set ${SRV}eth0 netns $SRV + ip link set $IF netns ${pid} + + echo "Bring ${SRV}eth0 up" + $NSS ip link set dev ${SRV}eth0 name eth0 + $NSS ip link set dev eth0 up + + echo "Bring $IF up in the virtual switch docker" + nsenter -t $pid -n ip link set dev $IF up + +done diff --git a/platform/vs/docker-orchagent-vs.mk b/platform/vs/docker-orchagent-vs.mk new file mode 100644 index 000000000000..185e3ce07701 --- /dev/null +++ b/platform/vs/docker-orchagent-vs.mk @@ -0,0 +1,24 @@ +# docker image for orchagent + +DOCKER_ORCHAGENT_VS = docker-orchagent-vs.gz +$(DOCKER_ORCHAGENT_VS)_PATH = $(DOCKERS_PATH)/docker-orchagent +$(DOCKER_ORCHAGENT_VS)_DEPENDS += $(SWSS) $(REDIS_TOOLS) $(IPROUTE2) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_ORCHAGENT_VS)_DEPENDS += $(SWSS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_ORCHAGENT_VS)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_VS) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_VS) + +$(DOCKER_ORCHAGENT_VS)_CONTAINER_NAME = swss +$(DOCKER_ORCHAGENT_VS)_RUN_OPT += --net=host --privileged -t +$(DOCKER_ORCHAGENT_VS)_RUN_OPT += -v /etc/network/interfaces:/etc/network/interfaces:ro +$(DOCKER_ORCHAGENT_VS)_RUN_OPT += -v /etc/network/interfaces.d/:/etc/network/interfaces.d/:ro +$(DOCKER_ORCHAGENT_VS)_RUN_OPT += -v /host/machine.conf:/host/machine.conf:ro +$(DOCKER_ORCHAGENT_VS)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_ORCHAGENT_VS)_RUN_OPT += -v /var/log/swss:/var/log/swss:rw + +$(DOCKER_ORCHAGENT_VS)_BASE_IMAGE_FILES += swssloglevel:/usr/bin/swssloglevel +$(DOCKER_ORCHAGENT_VS)_FILES += $(ARP_UPDATE_SCRIPT) diff --git a/platform/vs/docker-sonic-vs.mk b/platform/vs/docker-sonic-vs.mk new file mode 100644 index 000000000000..6b3f9f96c07e --- /dev/null +++ b/platform/vs/docker-sonic-vs.mk @@ -0,0 +1,37 @@ +# docker image for virtual switch based sonic docker image + +DOCKER_SONIC_VS = docker-sonic-vs.gz +$(DOCKER_SONIC_VS)_PATH = $(PLATFORM_PATH)/docker-sonic-vs +$(DOCKER_SONIC_VS)_DEPENDS += $(SWSS) \ + $(SYNCD_VS) \ + $(REDIS_TOOLS) \ + $(REDIS_SERVER) \ + $(PYTHON_SWSSCOMMON) \ + $(LIBTEAMDCT) \ + $(LIBTEAM_UTILS) \ + $(SONIC_DEVICE_DATA) \ + $(SONIC_UTILS) \ + $(IPROUTE2) + +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SONIC_VS)_DEPENDS += $(SWSS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIREDIS_DBG) \ + $(LIBSAIVS_DBG) \ + $(SYNCD_VS_DBG) +endif + +ifeq ($(SONIC_ROUTING_STACK), quagga) +$(DOCKER_SONIC_VS)_DEPENDS += $(QUAGGA) +else ifeq ($(SONIC_ROUTING_STACK), frr) +$(DOCKER_SONIC_VS)_DEPENDS += $(FRR) +else +$(DOCKER_SONIC_VS)_DEPENDS += $(GOBGP) +endif + +$(DOCKER_SONIC_VS)_FILES += $(CONFIGDB_LOAD_SCRIPT) \ + $(ARP_UPDATE_SCRIPT) \ + $(SONIC_VERSION) + +$(DOCKER_SONIC_VS)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SONIC_VS) diff --git a/platform/vs/docker-sonic-vs/50-default.conf b/platform/vs/docker-sonic-vs/50-default.conf new file mode 100644 index 000000000000..d672d83af789 --- /dev/null +++ b/platform/vs/docker-sonic-vs/50-default.conf @@ -0,0 +1,68 @@ +# Default rules for rsyslog. +# +# For more information see rsyslog.conf(5) and /etc/rsyslog.conf + +# +# First some standard log files. Log by facility. +# +auth,authpriv.* /var/log/auth.log +*.*;auth,authpriv.none -/var/log/syslog +#cron.* /var/log/cron.log +#daemon.* -/var/log/daemon.log +kern.* -/var/log/kern.log +#lpr.* -/var/log/lpr.log +mail.* -/var/log/mail.log +#user.* -/var/log/user.log + +# +# Logging for the mail system. Split it up so that +# it is easy to write scripts to parse these files. +# +#mail.info -/var/log/mail.info +#mail.warn -/var/log/mail.warn +mail.err /var/log/mail.err + +# +# Logging for INN news system. +# +news.crit /var/log/news/news.crit +news.err /var/log/news/news.err +news.notice -/var/log/news/news.notice + +# +# Some "catch-all" log files. +# +#*.=debug;\ +# auth,authpriv.none;\ +# news.none;mail.none -/var/log/debug +#*.=info;*.=notice;*.=warn;\ +# auth,authpriv.none;\ +# cron,daemon.none;\ +# mail,news.none -/var/log/messages + +# +# Emergencies are sent to everybody logged in. +# +*.emerg :omusrmsg:* + +# +# I like to have messages displayed on the console, but only on a virtual +# console I usually leave idle. +# +#daemon,mail.*;\ +# news.=crit;news.=err;news.=notice;\ +# *.=debug;*.=info;\ +# *.=notice;*.=warn /dev/tty8 + +# The named pipe /dev/xconsole is for the `xconsole' utility. To use it, +# you must invoke `xconsole' with the `-file' option: +# +# $ xconsole -file /dev/xconsole [...] +# +# NOTE: adjust the list below, or you'll go crazy if you have a reasonably +# busy site.. +# +daemon.*;mail.*;\ + news.err;\ + *.=debug;*.=info;\ + *.=notice;*.=warn |/dev/xconsole diff --git a/platform/vs/docker-sonic-vs/Dockerfile.j2 b/platform/vs/docker-sonic-vs/Dockerfile.j2 new file mode 100644 index 000000000000..c26da98da2aa --- /dev/null +++ b/platform/vs/docker-sonic-vs/Dockerfile.j2 @@ -0,0 +1,101 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY ["sonic-dev.gpg.key", "/etc/apt/"] +RUN apt-key add /etc/apt/sonic-dev.gpg.key +RUN echo "deb http://packages.microsoft.com/repos/sonic-dev/ jessie main" >> /etc/apt/sources.list +RUN apt-get update + +RUN apt-get install -y net-tools \ + arping \ + ndisc6 \ + ethtool \ + tcpdump \ + ifupdown \ + bridge-utils \ + python-ply \ + libqt5core5a \ + libqt5network5 \ + libboost-program-options1.55.0 \ + libboost-system1.55.0 \ + libboost-thread1.55.0 \ + libgmp10 \ + libjudydebian1 \ + libnanomsg0 \ + libdaemon0 \ + libjansson4 \ + libjemalloc1 \ + openssh-client \ + openssh-server \ + libc-ares2 \ + iproute \ + libpython2.7 \ + grub2-common \ + python-click-default-group \ + python-click \ + python-natsort \ + python-tabulate \ + bash-completion \ + libelf1 \ + libmnl0 \ + logrotate \ + apt-utils \ + psmisc \ + tcpdump \ + python-scapy + +RUN pip install setuptools +RUN pip install py2_ipaddress +RUN pip install six +RUN pip install pyroute2==0.5.3 netifaces==0.10.7 +RUN pip install monotonic==1.5 + +{% if docker_sonic_vs_debs.strip() -%} +# Copy locally-built Debian package dependencies +{%- for deb in docker_sonic_vs_debs.split(' ') %} +COPY debs/{{ deb }} /debs/ +{%- endfor %} + +# Install locally-built Debian packages and implicitly install their dependencies +{%- for deb in docker_sonic_vs_debs.split(' ') %} +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /debs/{{ deb }} +{%- endfor %} +{%- endif %} + +# Clean up +RUN apt-get clean -y +RUN apt-get autoclean -y +RUN apt-get autoremove -y +RUN rm -rf /debs ~/.cache + +RUN sed -ri 's/^(save .*$)/# \1/g; \ + s/^daemonize yes$/daemonize no/; \ + s/^logfile .*$/logfile ""/; \ + s/^# syslog-enabled no$/syslog-enabled no/; \ + s/^# unixsocket/unixsocket/; \ + s/notify-keyspace-events ""/notify-keyspace-events AKE/; \ + s/^client-output-buffer-limit pubsub [0-9]+mb [0-9]+mb [0-9]+/client-output-buffer-limit pubsub 0 0 0/ \ + ' /etc/redis/redis.conf + +COPY ["50-default.conf", "/etc/rsyslog.d/"] +COPY ["start.sh", "orchagent.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/configdb-load.sh", "/usr/bin/"] +COPY ["files/arp_update", "/usr/bin"] +COPY ["files/sonic_version.yml", "/etc/sonic/"] + +# Workaround the tcpdump issue +RUN mv /usr/sbin/tcpdump /usr/bin/tcpdump + +RUN echo "docker-sonic-vs" > /etc/hostname +RUN touch /etc/quagga/zebra.conf + +# Create /var/warmboot/teamd folder for teammgrd +RUN mkdir -p /var/warmboot/teamd + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/vs/docker-sonic-vs/orchagent.sh b/platform/vs/docker-sonic-vs/orchagent.sh new file mode 100755 index 000000000000..26dae28a6e15 --- /dev/null +++ b/platform/vs/docker-sonic-vs/orchagent.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +export platform=vs + +MAC_ADDRESS=`ip link show eth0 | grep ether | awk '{print $2}'` + +# Create a folder for SwSS record files +mkdir -p /var/log/swss +ORCHAGENT_ARGS="-d /var/log/swss " + +# Set orchagent pop batch size to 8192 +ORCHAGENT_ARGS+="-b 8192 " + +# Set mac address +ORCHAGENT_ARGS+="-m $MAC_ADDRESS" + +exec /usr/bin/orchagent ${ORCHAGENT_ARGS} diff --git a/platform/vs/docker-sonic-vs/sonic-dev.gpg.key b/platform/vs/docker-sonic-vs/sonic-dev.gpg.key new file mode 100644 index 000000000000..fb9a37901bc7 --- /dev/null +++ b/platform/vs/docker-sonic-vs/sonic-dev.gpg.key @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQENBFQ1bTIBCAC7oGfkv/ck0XsLuG8cdcSB2ISqxFAcBvH9BitEtxmpW2uhykKk +xY4rVD/4Uys1s3PF1/64QfPR+hYcewueOwz0ZAcLyFXXk4McICXaPq3NrLiWYKKX +UZLnrPzcrGZoW/kHDDp4OmBiDmT1PGvZlpuimwkMCusUzIr7Cbbp2dIy8MERL5tA +LcgLu3KL6clJ+aTW2jgepI1D7sTepOeGd7eRSb5njKg2M7k/93v/7MipZxiVtyXH +B74YiK6jSbst5JpuYsLa/Dqryvx7Xq3n53oif892pv3euTduo1fYw8Hgh/OOYdeT +c9WCj03KA1jCSFURjdrug0kR8BPlfjqtRLXFABEBAAG0JE1TIE9wZW4gVGVjaCA8 +aW50ZXJvcEBtaWNyb3NvZnQuY29tPokBOAQTAQIAIgUCVDVtMgIbAwYLCQgHAwIG +FQgCCQoLBBYCAwECHgECF4AACgkQsCxG30F6CJO1uAf/cmL68bM8YgF/61hkaY56 +LqrppUTJH/w4fKq47Pf6KfgSLvxfNU6soi2KHYRjIvTRx3tV4vUM5n2plaQg2s8V +/Epg4FeIRTk75YwiHAzLhLnp5cdUaTvC4j4mwxoB6j9Ty+fXJwQ0MvpDhIZb9vM4 +GXw/fEQHCT4f3gx4nReeqE+FB2wVHleX9+Lpodu98JyJTKJRBRHYLqy6S+/lyp2W +aBlsI1LOqBcx1uRK24U7duIpbYwIyrx0cafSruqR2GjVdu+imkhHyUn52VbzYhq1 +af0rqYiZ1VOamVOG0By8+hVyNa1MLc1K2uWGs0o5fDe9F5/swbvLHVXI+M50Vs+m +J7kBDQRUNW0yAQgAu7DkTVj0ZQC4F7bFivAwrdby8gCakTXOl1kcK622hjRJ8nam +aZeW+eADfLRsTmdUmXgZu1YWS5Gn2ZVngC8SGPUBT071+oRETCz4uNB7IimB9QfP +++orI6o2vmnVVsq5wWCbEdNU+TCVv1zjrYev5lwckkKpjHt6o8MNoX2DFuQymSyR +eZKaqhdKmcji4Ke7OIYqwgPjch3wxzE1b5gNOR/iwxWyjjOffZPLr/VhIfIJRs86 +dSXrwjHtEh810SKDLghHM0VAdY34nyC5ZZ61yhts5HtQDFK+9mNpH1mkc4gDBlgG +266pVvknumK6lPNm/osF/cpjWmEw24ypcQIvOQARAQABiQEfBBgBAgAJBQJUNW0y +AhsMAAoJELAsRt9BegiTMBUH/0sZ6gZy7mCTSAYT+NSXLFtGC2zNUVL80SWvfgYm +k9XPVI22MrefZfQ6M01RylyxtWXjRM8UoN8SDKWPpXumzJf831f/7om5zwutaG7b +tjDPYqRKJSbAIFZu2mN+uLrNQ2SV6XK7FoV0dtcrEX9S7RICb6i19D+70+Oh/qgU +R04H1jqS29XBzqAlIzdBoA+sYAwbOIJsSL3YyNQcUv3B5+5yR/bo/L8pnUJt6iuL +nWW+mi7r8gWPHDSrcdYq1TmmlOM7CwZPgWRZzkQPSeZz52Tt7IP47eyGJ09U4PIf +FtMH1ElL2UgHoA/F9Q88e7LkztaTqE59uXWbIYyuSMJVvRU= +=sb3d +-----END PGP PUBLIC KEY BLOCK----- diff --git a/platform/vs/docker-sonic-vs/start.sh b/platform/vs/docker-sonic-vs/start.sh new file mode 100755 index 000000000000..3871dc375ff5 --- /dev/null +++ b/platform/vs/docker-sonic-vs/start.sh @@ -0,0 +1,71 @@ +#!/bin/bash -e + +# generate configuration + +PLATFORM=x86_64-kvm_x86_64-r0 +HWSKU=Force10-S6000 + +ln -sf /usr/share/sonic/device/$PLATFORM/$HWSKU /usr/share/sonic/hwsku + +[ -d /etc/sonic ] || mkdir -p /etc/sonic + +SYSTEM_MAC_ADDRESS=$(ip link show eth0 | grep ether | awk '{print $2}') +sonic-cfggen -a '{"DEVICE_METADATA":{"localhost": {"mac": "'$SYSTEM_MAC_ADDRESS'"}}}' --print-data > /etc/sonic/init_cfg.json + +if [ -f /etc/sonic/config_db.json ]; then + sonic-cfggen -j /etc/sonic/config_db.json -j /etc/sonic/init_cfg.json --print-data > /tmp/config_db.json + mv /tmp/config_db.json /etc/sonic/config_db.json +else + # generate and merge buffers configuration into config file + sonic-cfggen -t /usr/share/sonic/hwsku/buffers.json.j2 > /tmp/buffers.json + sonic-cfggen -p /usr/share/sonic/hwsku/port_config.ini -k $HWSKU --print-data > /tmp/ports.json + sonic-cfggen -j /etc/sonic/init_cfg.json -j /tmp/buffers.json -j /tmp/ports.json --print-data > /etc/sonic/config_db.json +fi + +mkdir -p /etc/swss/config.d/ + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +mkdir -p /var/run/redis + +supervisorctl start redis-server + +/usr/bin/configdb-load.sh + +supervisorctl start syncd + +supervisorctl start orchagent + +supervisorctl start portsyncd + +supervisorctl start intfsyncd + +supervisorctl start neighsyncd + +supervisorctl start teamsyncd + +supervisorctl start fpmsyncd + +supervisorctl start teammgrd + +supervisorctl start portmgrd + +supervisorctl start intfmgrd + +supervisorctl start vlanmgrd + +supervisorctl start zebra + +supervisorctl start buffermgrd + +supervisorctl start vrfmgrd + +supervisorctl start nbrmgrd + +# Start arp_update when VLAN exists +VLAN=`sonic-cfggen -d -v 'VLAN.keys() | join(" ") if VLAN'` +if [ "$VLAN" != "" ]; then + supervisorctl start arp_update +fi diff --git a/platform/vs/docker-sonic-vs/supervisord.conf b/platform/vs/docker-sonic-vs/supervisord.conf new file mode 100644 index 000000000000..3fe3df30c2d4 --- /dev/null +++ b/platform/vs/docker-sonic-vs/supervisord.conf @@ -0,0 +1,174 @@ +[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:redis-server] +command=/usr/bin/redis-server /etc/redis/redis.conf +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:orchagent] +command=/usr/bin/orchagent.sh +priority=5 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:portsyncd] +command=/usr/bin/portsyncd -p /usr/share/sonic/hwsku/port_config.ini +priority=6 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:intfsyncd] +command=/usr/bin/intfsyncd +priority=7 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:neighsyncd] +command=/usr/bin/neighsyncd +priority=8 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:teamsyncd] +command=/usr/bin/teamsyncd +priority=9 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:vlanmgrd] +command=/usr/bin/vlanmgrd +priority=10 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:intfmgrd] +command=/usr/bin/intfmgrd +priority=11 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:portmgrd] +command=/usr/bin/portmgrd +priority=12 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:teammgrd] +command=/usr/bin/teammgrd +priority=12 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:zebra] +command=/usr/lib/quagga/zebra -A 127.0.0.1 +priority=13 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:bgpd] +command=/usr/lib/quagga/bgpd -A 127.0.0.1 -F +priority=14 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:fpmsyncd] +command=/usr/bin/fpmsyncd +priority=15 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:arp_update] +command=/usr/bin/arp_update +priority=16 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog + +[program:buffermgrd] +command=/usr/bin/buffermgrd -l /usr/share/sonic/hwsku/pg_profile_lookup.ini +priority=17 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:vrfmgrd] +command=/usr/bin/vrfmgrd +priority=18 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:restore_neighbors] +command=/usr/bin/restore_neighbors.py +priority=19 +autostart=false +autorestart=false +startsecs=0 +startretries=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:nbrmgrd] +command=/usr/bin/nbrmgrd +priority=20 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/vs/docker-syncd-vs.mk b/platform/vs/docker-syncd-vs.mk new file mode 100644 index 000000000000..12fbf65468a9 --- /dev/null +++ b/platform/vs/docker-syncd-vs.mk @@ -0,0 +1,14 @@ +# docker image for vs syncd + +DOCKER_SYNCD_VS = docker-syncd-vs.gz +$(DOCKER_SYNCD_VS)_PATH = $(PLATFORM_PATH)/docker-syncd-vs +$(DOCKER_SYNCD_VS)_DEPENDS += $(SYNCD_VS) +$(DOCKER_SYNCD_VS)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_VS) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_VS) + +$(DOCKER_SYNCD_VS)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_VS)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_VS)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_VS)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SYNCD_VS)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/vs/docker-syncd-vs/Dockerfile.j2 b/platform/vs/docker-syncd-vs/Dockerfile.j2 new file mode 100644 index 000000000000..7bef89fe57b5 --- /dev/null +++ b/platform/vs/docker-syncd-vs/Dockerfile.j2 @@ -0,0 +1,30 @@ +FROM docker-config-engine + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_syncd_vs_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_syncd_vs_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "/usr/bin/"] + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/vs/docker-syncd-vs/start.sh b/platform/vs/docker-syncd-vs/start.sh new file mode 100755 index 000000000000..98c7d9c15a0d --- /dev/null +++ b/platform/vs/docker-syncd-vs/start.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +PLATFORM_DIR=/usr/share/sonic/platform +HWSKU_DIR=/usr/share/sonic/hwsku + +SYNCD_SOCKET_FILE=/var/run/sswsyncd/sswsyncd.socket + +# Function: wait until syncd has created the socket for bcmcmd to connect to +wait_syncd() { + while true; do + if [ -e ${SYNCD_SOCKET_FILE} ]; then + break + fi + sleep 1 + done + + # wait until bcm sdk is ready to get a request + sleep 3 +} + + +# Remove stale files if they exist +rm -f /var/run/rsyslogd.pid +rm -f ${SYNCD_SOCKET_FILE} + +supervisorctl start rsyslogd + +mkdir -p /etc/sai.d/ + +# Create/Copy the sai.profile to /etc/sai.d/sai.profile +if [ -f $HWSKU_DIR/sai.profile.j2 ]; then + sonic-cfggen -d -t $HWSKU_DIR/sai.profile.j2 > /etc/sai.d/sai.profile +else + if [ -f $HWSKU_DIR/sai.profile ]; then + cp $HWSKU_DIR/sai.profile /etc/sai.d/sai.profile + fi +fi + +supervisorctl start syncd + +# If this platform has an initialization file for the Broadcom LED microprocessor, load it +if [ -r ${PLATFORM_DIR}/led_proc_init.soc ]; then + wait_syncd + supervisorctl start ledinit +fi diff --git a/platform/vs/docker-syncd-vs/supervisord.conf b/platform/vs/docker-syncd-vs/supervisord.conf new file mode 100644 index 000000000000..1af5d70a1d0c --- /dev/null +++ b/platform/vs/docker-syncd-vs/supervisord.conf @@ -0,0 +1,28 @@ +[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:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/vs/kvm-image.mk b/platform/vs/kvm-image.mk new file mode 100644 index 000000000000..4c1cdd18b0d6 --- /dev/null +++ b/platform/vs/kvm-image.mk @@ -0,0 +1,8 @@ +# sonic kvm image + +SONIC_KVM_IMAGE = sonic-vs.img.gz +$(SONIC_KVM_IMAGE)_MACHINE = vs +$(SONIC_KVM_IMAGE)_IMAGE_TYPE = kvm +$(SONIC_KVM_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +$(SONIC_KVM_IMAGE)_FILES = $(ONIE_RECOVERY_IMAGE) +SONIC_INSTALLERS += $(SONIC_KVM_IMAGE) diff --git a/platform/vs/one-image.mk b/platform/vs/one-image.mk new file mode 100644 index 000000000000..2adbf98f90e0 --- /dev/null +++ b/platform/vs/one-image.mk @@ -0,0 +1,7 @@ +# sonic vs one image installer + +SONIC_ONE_IMAGE = sonic-vs.bin +$(SONIC_ONE_IMAGE)_MACHINE = vs +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/vs/onie.mk b/platform/vs/onie.mk new file mode 100644 index 000000000000..09a807c25b2a --- /dev/null +++ b/platform/vs/onie.mk @@ -0,0 +1,4 @@ +ONIE_RECOVERY_IMAGE = onie-recovery-x86_64-kvm_x86_64-r0.iso +$(ONIE_RECOVERY_IMAGE)_URL = "https://sonicstorage.blob.core.windows.net/packages/onie/onie-recovery-x86_64-kvm_x86_64-r0.iso?sv=2015-04-05&sr=b&sig=XMAk1cttBFM369CMbihe5oZgXwe4uaDVfwg4CTLT%2F5U%3D&se=2155-10-13T10%3A40%3A13Z&sp=r" + +SONIC_ONLINE_FILES += $(ONIE_RECOVERY_IMAGE) diff --git a/platform/vs/platform.conf b/platform/vs/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/vs/rules.mk b/platform/vs/rules.mk new file mode 100644 index 000000000000..7ba2da0db0ff --- /dev/null +++ b/platform/vs/rules.mk @@ -0,0 +1,10 @@ +include $(PLATFORM_PATH)/syncd-vs.mk +include $(PLATFORM_PATH)/sonic-version.mk +include $(PLATFORM_PATH)/docker-sonic-vs.mk +include $(PLATFORM_PATH)/docker-syncd-vs.mk +include $(PLATFORM_PATH)/docker-orchagent-vs.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/onie.mk +include $(PLATFORM_PATH)/kvm-image.mk + +SONIC_ALL += $(SONIC_ONE_IMAGE) $(SONIC_KVM_IMAGE) $(DOCKER_SONIC_VS) diff --git a/platform/vs/sonic-version.mk b/platform/vs/sonic-version.mk new file mode 100644 index 000000000000..9e21573227b3 --- /dev/null +++ b/platform/vs/sonic-version.mk @@ -0,0 +1,13 @@ +# sonic version yml file + +sonic_version=$(SONIC_GET_VERSION) +sonic_asic_platform=$(CONFIGURED_PLATFORM) + +export sonic_version +export sonic_asic_platform + +SONIC_VERSION = sonic_version.yml +$(SONIC_VERSION)_SRC_PATH = $(PLATFORM_PATH)/sonic-version +SONIC_MAKE_FILES += $(SONIC_VERSION) + +SONIC_PHONY_TARGETS += $(addprefix $(FILES_PATH)/, $(SONIC_VERSION)) diff --git a/platform/vs/sonic-version/Makefile b/platform/vs/sonic-version/Makefile new file mode 100644 index 000000000000..2b2386031c9b --- /dev/null +++ b/platform/vs/sonic-version/Makefile @@ -0,0 +1,10 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = sonic_version.yml + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + ./build_sonic_version.sh $(MAIN_TARGET) + + mv $(MAIN_TARGET) $(DEST)/ diff --git a/platform/vs/sonic-version/build_sonic_version.sh b/platform/vs/sonic-version/build_sonic_version.sh new file mode 100755 index 000000000000..f118a1c20a6d --- /dev/null +++ b/platform/vs/sonic-version/build_sonic_version.sh @@ -0,0 +1,8 @@ +tee $1 > /dev/null < + sonic + 2048000 + 2048000 + 1 + + /machine + + + hvm + + + + + + + + destroy + restart + restart + + /usr/bin/qemu-system-x86_64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + diff --git a/platform/vs/syncd-vs.mk b/platform/vs/syncd-vs.mk new file mode 100644 index 000000000000..49035aaf958b --- /dev/null +++ b/platform/vs/syncd-vs.mk @@ -0,0 +1,13 @@ +$(LIBSAIREDIS)_DPKG_TARGET = binary-syncd-vs + +# inject libsaivs and libsaivs_dev to swss build dependency +$(SWSS)_DEPENDS += $(LIBSAIVS) $(LIBSAIVS_DEV) + +SYNCD_VS = syncd-vs_1.0.0_amd64.deb +$(SYNCD_VS)_RDEPENDS += $(LIBSAIREDIS) $(LIBSAIMETADATA) $(LIBSAIVS) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(SYNCD_VS))) + +SYNCD_VS_DBG = syncd-vs-dbg_1.0.0_amd64.deb +$(SYNCD_VS_DBG)_DEPENDS += $(SYNCD_VS) +$(SYNCD_VS_DBG)_RDEPENDS += $(SYNCD_VS) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(SYNCD_VS_DBG))) diff --git a/platform/vs/tests/README.md b/platform/vs/tests/README.md new file mode 100644 index 000000000000..29ba27db62fc --- /dev/null +++ b/platform/vs/tests/README.md @@ -0,0 +1,4 @@ +Requirements: + +- Enable IPv6 for docker engine +- pip install exabgp diff --git a/platform/vs/tests/bgp/files/invalid_nexthop/bgpd.conf b/platform/vs/tests/bgp/files/invalid_nexthop/bgpd.conf new file mode 100644 index 000000000000..b22bf17f92e3 --- /dev/null +++ b/platform/vs/tests/bgp/files/invalid_nexthop/bgpd.conf @@ -0,0 +1,7 @@ +router bgp 65501 + bgp router-id 1.1.1.1 + no bgp default ipv4-unicast + neighbor fc00::2 remote-as 65502 + address-family ipv6 + neighbor fc00::2 activate + exit-address-family diff --git a/platform/vs/tests/bgp/files/invalid_nexthop/invalid_nexthop.conf b/platform/vs/tests/bgp/files/invalid_nexthop/invalid_nexthop.conf new file mode 100644 index 000000000000..60a327d7121d --- /dev/null +++ b/platform/vs/tests/bgp/files/invalid_nexthop/invalid_nexthop.conf @@ -0,0 +1,19 @@ +neighbor fc00::1 { + router-id 1.2.3.4; + local-address fc00::2; + local-as 65502; + peer-as 65501; + group-updates false; + + family { + ipv4 unicast; + ipv6 unicast; + } + + static { + route 3333::0/64 { + next-hop 0.0.0.0; + next-hop fc00::2; + } + } +} diff --git a/platform/vs/tests/bgp/files/no_export/bgpd.conf b/platform/vs/tests/bgp/files/no_export/bgpd.conf new file mode 100644 index 000000000000..40322cedbc69 --- /dev/null +++ b/platform/vs/tests/bgp/files/no_export/bgpd.conf @@ -0,0 +1,13 @@ +router bgp 65501 + bgp router-id 1.1.1.1 + no bgp default ipv4-unicast + neighbor 10.0.0.1 remote-as 65502 + address-family ipv4 + neighbor 10.0.0.1 activate + maximum-paths 64 + exit-address-family + neighbor 10.0.0.3 remote-as 65503 + address-family ipv4 + neighbor 10.0.0.3 activate + maximum-paths 64 + exit-address-family diff --git a/platform/vs/tests/bgp/files/no_export/exabgp1.conf b/platform/vs/tests/bgp/files/no_export/exabgp1.conf new file mode 100644 index 000000000000..0e78bd61db42 --- /dev/null +++ b/platform/vs/tests/bgp/files/no_export/exabgp1.conf @@ -0,0 +1,21 @@ +neighbor 10.0.0.0 { + router-id 1.1.1.2; + local-address 10.0.0.1; + local-as 65502; + peer-as 65501; + group-updates false; + + family{ + ipv4 unicast; + } + + static { + route 1.1.1.1/32{ + next-hop 10.0.0.1; + community no-export; + } + route 2.2.2.2/32{ + next-hop 10.0.0.1; + } + } +} diff --git a/platform/vs/tests/bgp/files/no_export/exabgp2.conf b/platform/vs/tests/bgp/files/no_export/exabgp2.conf new file mode 100644 index 000000000000..3e67c18a82f6 --- /dev/null +++ b/platform/vs/tests/bgp/files/no_export/exabgp2.conf @@ -0,0 +1,11 @@ +neighbor 10.0.0.2 { + router-id 1.1.1.3; + local-address 10.0.0.3; + local-as 65503; + peer-as 65501; + group-updates false; + + family { + ipv4 unicast; + } +} diff --git a/platform/vs/tests/bgp/test_invalid_nexthop.py b/platform/vs/tests/bgp/test_invalid_nexthop.py new file mode 100644 index 000000000000..eb4f6c212e02 --- /dev/null +++ b/platform/vs/tests/bgp/test_invalid_nexthop.py @@ -0,0 +1,32 @@ +from swsscommon import swsscommon +import os +import re +import time +import json + +def test_InvalidNexthop(dvs, testlog): + + dvs.copy_file("/etc/quagga/", "bgp/files/invalid_nexthop/bgpd.conf") + dvs.runcmd("supervisorctl start bgpd") + dvs.runcmd("ip addr add fc00::1/126 dev Ethernet0") + dvs.runcmd("ifconfig Ethernet0 up") + + dvs.servers[0].runcmd("ip addr add fc00::2/126 dev eth0") + dvs.servers[0].runcmd("ifconfig eth0 up") + + time.sleep(5) + + print dvs.runcmd("supervisorctl status") + + p = dvs.servers[0].runcmd_async("exabgp -d bgp/files/invalid_nexthop/invalid_nexthop.conf") + + time.sleep(10) + + (exit_code, output) = dvs.runcmd(["vtysh", "-c", "show ipv6 bgp"]) + + p.terminate() + p = p.wait() + + print exit_code, output + + assert "3333::/64" in output diff --git a/platform/vs/tests/bgp/test_no_export.py b/platform/vs/tests/bgp/test_no_export.py new file mode 100644 index 000000000000..f2d06f31cd72 --- /dev/null +++ b/platform/vs/tests/bgp/test_no_export.py @@ -0,0 +1,45 @@ +from swsscommon import swsscommon +import os +import re +import time +import json + +def test_bounce(dvs, testlog): + dvs.servers[0].runcmd("pkill -f exabgp") + dvs.copy_file("/etc/quagga/", "bgp/files/no_export/bgpd.conf") + dvs.runcmd("supervisorctl start bgpd") + dvs.runcmd("ip addr add 10.0.0.0/31 dev Ethernet0") + dvs.runcmd("ifconfig Ethernet0 up") + + dvs.runcmd("ip addr add 10.0.0.2/31 dev Ethernet4") + dvs.runcmd("ifconfig Ethernet4 up") + + dvs.servers[0].runcmd("ip addr add 10.0.0.1/31 dev eth0") + dvs.servers[0].runcmd("ifconfig eth0 up") + + dvs.servers[1].runcmd("ip addr add 10.0.0.3/31 dev eth0") + dvs.servers[1].runcmd("ifconfig eth0 up") + + time.sleep(5) + + p1 = dvs.servers[0].runcmd_async("exabgp -d bgp/files/no_export/exabgp1.conf") + p2 = dvs.servers[1].runcmd_async("exabgp -d bgp/files/no_export/exabgp2.conf") + + time.sleep(60) + + (exit_code, sum_res) = dvs.runcmd(["vtysh", "-c", "show ip bgp sum"]) + (exit_code, all_route) = dvs.runcmd(["vtysh", "-c", "show ip bgp"]) + (exit_code, announce_route) = dvs.runcmd(["vtysh", "-c", "show ip bgp neighbors 10.0.0.3 advertised-routes"]) + + p1.terminate() + p1 = p1.wait() + + p2.terminate() + p2 = p2.wait() + + print sum_res + print announce_route + assert "1.1.1.1/32" in all_route + assert "1.1.1.1/32" not in announce_route + assert "2.2.2.2/32" in all_route + assert "2.2.2.2/32" in announce_route diff --git a/platform/vs/tests/conftest.py b/platform/vs/tests/conftest.py new file mode 120000 index 000000000000..9fef6363db02 --- /dev/null +++ b/platform/vs/tests/conftest.py @@ -0,0 +1 @@ +../../../src/sonic-swss/tests/conftest.py \ No newline at end of file diff --git a/platform/vs/tests/teamd/test_portchannel.py b/platform/vs/tests/teamd/test_portchannel.py new file mode 100644 index 000000000000..0632bf874e52 --- /dev/null +++ b/platform/vs/tests/teamd/test_portchannel.py @@ -0,0 +1,37 @@ +from swsscommon import swsscommon +import time +import re +import json + +def test_PortChannel(dvs, testlog): + appldb = swsscommon.DBConnector(0, dvs.redis_sock, 0) + statdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) + + # create the lag + dvs.runcmd("config portchannel add PortChannel0001") + time.sleep(1) + + # test lag table in appl db + tbl = swsscommon.Table(appldb, "LAG_TABLE") + (status, fvs) = tbl.get("PortChannel0001") + assert status == True + + # test lag table in state db + tbl = swsscommon.Table(statdb, "LAG_TABLE") + (status, fvs) = tbl.get("PortChannel0001") + assert status == True + + # create the lag member + dvs.runcmd("config portchannel member add PortChannel0001 Ethernet112") + time.sleep(1) + + # test lag member table in appl db + tbl = swsscommon.Table(appldb, "LAG_MEMBER_TABLE") + (status, fvs) = tbl.get("PortChannel0001:Ethernet112") + assert status == True + + # remove the lag member + dvs.runcmd("config portchannel member del PortChannel0001 Ethernet112") + + # remove the lag + dvs.runcmd("config portchannel del PortChannel0001") diff --git a/push_docker.sh b/push_docker.sh new file mode 100755 index 000000000000..3ba9abfae5bf --- /dev/null +++ b/push_docker.sh @@ -0,0 +1,42 @@ +DOCKER_IMAGE_FILE=$1 +REGISTRY_SERVER=$2 +REGISTRY_PORT=$3 +REGISTRY_USERNAME=$4 +REGISTRY_PASSWD=$5 +DOCKER_IMAGE_TAG=$6 + +set -e +docker load < $DOCKER_IMAGE_FILE + +## Fetch the Jenkins build number if inside it +[ ${BUILD_NUMBER} ] || { + echo "No BUILD_NUMBER found, setting to 0." + BUILD_NUMBER="0" +} + +## Prepare tag +docker_image_name=$(basename $DOCKER_IMAGE_FILE | cut -d. -f1) +remote_image_name=$REGISTRY_SERVER:$REGISTRY_PORT/$docker_image_name:$DOCKER_IMAGE_TAG +timestamp="$(date -u +%Y%m%d)" +build_version="${timestamp}.bld-${BUILD_NUMBER}" +build_remote_image_name=$REGISTRY_SERVER:$REGISTRY_PORT/$docker_image_name:$build_version + +## Add registry information as tag, so will push as latest +## Add additional tag with build information +docker tag $docker_image_name $remote_image_name +docker tag $docker_image_name $build_remote_image_name + +## Login the docker image registry server +## Note: user name and password are passed from command line +docker login -u $REGISTRY_USERNAME -p "$REGISTRY_PASSWD" $REGISTRY_SERVER:$REGISTRY_PORT + +## Push image to registry server +## And get the image digest SHA256 +echo "Pushing $remote_image_name" +image_sha=$(docker push $remote_image_name | sed -n "s/.*: digest: sha256:\([0-9a-f]*\).*/\\1/p") +docker rmi $remote_image_name || true +echo "Image sha256: $image_sha" +echo "Pushing $build_remote_image_name" +docker push $build_remote_image_name +docker rmi $build_remote_image_name || true +docker rmi $docker_image_name || true diff --git a/rules/asyncsnmp-py3.mk b/rules/asyncsnmp-py3.mk new file mode 100644 index 000000000000..cc0af244d856 --- /dev/null +++ b/rules/asyncsnmp-py3.mk @@ -0,0 +1,8 @@ +# asyncsnmp python2 wheel + +ASYNCSNMP_PY3 = asyncsnmp-2.1.0-py3-none-any.whl +$(ASYNCSNMP_PY3)_SRC_PATH = $(SRC_PATH)/sonic-snmpagent +$(ASYNCSNMP_PY3)_PYTHON_VERSION = 3 +# Depends on sonic-platform-common so it is possible to import sonic_psu +$(ASYNCSNMP_PY3)_DEPENDS += $(SWSSSDK_PY3) $(SONIC_PLATFORM_COMMON_PY3) +SONIC_PYTHON_WHEELS += $(ASYNCSNMP_PY3) diff --git a/rules/bash.mk b/rules/bash.mk new file mode 100644 index 000000000000..e31b237ae11b --- /dev/null +++ b/rules/bash.mk @@ -0,0 +1,17 @@ +# bash package +# +# Created to patch memory-leak issue in the bash-package included in Debian-8 (Jessie) +# release. This rule file, and the associated building-infra created to solve this +# bug (src/bash/), should be eliminated once the migration to Debian-9 (Stretch) is +# completed. + +# Bash major release-number corresponding to Debian-8 (Jessie) +BASH_VERSION_MAJOR = 4.3 +# Bash complete release-number. This image contains all 4.3 fixes up to patch '42'. +BASH_VERSION_FULL = $(BASH_VERSION_MAJOR)-14 + +export BASH_VERSION_MAJOR BASH_VERSION_FULL + +BASH = bash_$(BASH_VERSION_FULL)_amd64.deb +$(BASH)_SRC_PATH = $(SRC_PATH)/bash +SONIC_MAKE_DEBS += $(BASH) diff --git a/rules/config b/rules/config new file mode 100644 index 000000000000..86139c71540f --- /dev/null +++ b/rules/config @@ -0,0 +1,86 @@ +############################################################################### +## Configuration parameters for SONiC build system +############################################################################### + +# SONIC_CONFIG_PRINT_DEPENDENCIES - show dependencies for each invoked target. +# Before executing rule for each target its dependencies are printed to console. +# Uncomment next line to enable: +# SONIC_CONFIG_PRINT_DEPENDENCIES = y + +# SONIC_CONFIG_BUILD_JOBS - set number of jobs for parallel build. +# Corresponding -j argument will be passed to make command inside docker +# container. +SONIC_CONFIG_BUILD_JOBS = 1 + +# SONIC_CONFIG_MAKE_JOBS - set number of parallel make jobs per package. +# Corresponding -j argument will be passed to make/dpkg commands that build separate packages +SONIC_CONFIG_MAKE_JOBS = $(shell nproc) + +# SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD - use native dockerd for build. +# If set to y SONiC build container will use native dockerd instead of dind for faster build +# SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD = y + +# SONIC_CONFIG_ENABLE_COLORS - enable colored output in build system. +# Comment next line to disable: +# SONIC_CONFIG_ENABLE_COLORS = y + +# DEFAULT_USERNAME - default username for installer build +DEFAULT_USERNAME = admin + +# DEFAULT_PASSWORD - default password for installer build +DEFAULT_PASSWORD = YourPaSsWoRd + +# ENABLE_DHCP_GRAPH_SERVICE - specify the source of minigraph to generate configuration file. +# If set to y SONiC will get the minigraph from graph service. Graph service URL need to be +# passed through DHCP option 225. +# If not set (default behavior) the default minigraph built into the image will be used. +# ENABLE_DHCP_GRAPH_SERVICE = y + +# SHUTDOWN_BGP_ON_START - if set to y all bgp sessions will be in admin down state when +# bgp service starts. +# SHUTDOWN_BGP_ON_START = y + +# ENABLE_PFCWD_ON_START - if set to y PFC Watchdog (PFCWD) will be enabled all server-facing ports +# by default for TOR switch +# ENABLE_PFCWD_ON_START = y + +# SONIC_INSTALL_DEBUG_TOOLS - installs debugging tools in baseline docker +# Uncomment next line to enable: +# SONIC_INSTALL_DEBUG_TOOLS = y + +# SONIC_ROUTING_STACK - specify the routing-stack being elected to drive SONiC's control-plane. +# Supported routing stacks on SONiC are: +# routing-stacks: quagga, frr. +SONIC_ROUTING_STACK = quagga + +# ENABLE_SYNCD_RPC - build docker-syncd with rpc packages for testing purposes. +# Uncomment to enable: +# ENABLE_SYNCD_RPC = y + +# Enable Origanization Extensions - Specific to the deployment scenarios of the Organization +ENABLE_ORGANIZATION_EXTENSIONS = y + +# Debugging option allows sonic debian packages to get built including symbols +# information. Profiling option, disables compiler optimizations (-O0) as well +# as includes symbols information. Given that 'profiling' option is a superset +# of 'debugging' one, user should only enable either one option or the other -- +# if both options are enabled, the 'profiling' one will prevail. +#SONIC_DEBUGGING_ON = y +#SONIC_PROFILING_ON = y + +# ENABLE_SYSTEM_TELEMETRY - build docker-sonic-telemetry for system telemetry support +# ENABLE_SYSTEM_TELEMETRY = y + +# DEFAULT_KERNEL_PROCURE_METHOD - default method for obtaining kernel +# build: build kernel from source +# download: download pre-built kernel from Azure storage. +DEFAULT_KERNEL_PROCURE_METHOD = build + +# FRR user and group id values. These only take effect when SONIC_ROUTING_STACK is frr. +# Note: these values match the admin uid/gid of the host's admin account. If these values +# change and user doesn't want the frr uid/gid to potentially match a random user on the +# host, then either the appropriate account and group will need to be created on the host +# manually or changes need to be made when the image is built to create the account and +# group during installation. +FRR_USER_UID = 1000 +FRR_USER_GID = 1000 diff --git a/rules/dbsyncd-py2.mk b/rules/dbsyncd-py2.mk new file mode 100644 index 000000000000..220dc5fe7a1d --- /dev/null +++ b/rules/dbsyncd-py2.mk @@ -0,0 +1,7 @@ +# sonic-dbsyncd python2 wheel + +DBSYNCD_PY2 = sonic_d-2.0.0-py2-none-any.whl +$(DBSYNCD_PY2)_SRC_PATH = $(SRC_PATH)/sonic-dbsyncd +$(DBSYNCD_PY2)_PYTHON_VERSION = 2 +$(DBSYNCD_PY2)_DEPENDS += $(SWSSSDK_PY2) +SONIC_PYTHON_WHEELS += $(DBSYNCD_PY2) diff --git a/rules/docker-base.mk b/rules/docker-base.mk new file mode 100644 index 000000000000..891518790dd8 --- /dev/null +++ b/rules/docker-base.mk @@ -0,0 +1,18 @@ +# docker base image + +DOCKER_BASE = docker-base.gz +$(DOCKER_BASE)_PATH = $(DOCKERS_PATH)/docker-base +$(DOCKER_BASE)_DEPENDS += $(SUPERVISOR) +$(DOCKER_BASE)_DEPENDS += $(BASH) +$(DOCKER_BASE)_DEPENDS += $(SOCAT) + +ifeq ($(INSTALL_DEBUG_TOOLS),y) +GDB = gdb +VIM = vim +OPENSSH = openssh-client +SSHPASS = sshpass +STRACE = strace +$(DOCKER_BASE)_DBG_PACKAGES += $(GDB) $(VIM) $(OPENSSH) $(SSHPASS) $(STRACE) +endif + +SONIC_DOCKER_IMAGES += $(DOCKER_BASE) diff --git a/rules/docker-config-engine.mk b/rules/docker-config-engine.mk new file mode 100644 index 000000000000..f540bb66f350 --- /dev/null +++ b/rules/docker-config-engine.mk @@ -0,0 +1,8 @@ +# docker image for sonic config engine + +DOCKER_CONFIG_ENGINE = docker-config-engine.gz +$(DOCKER_CONFIG_ENGINE)_PATH = $(DOCKERS_PATH)/docker-config-engine +$(DOCKER_CONFIG_ENGINE)_PYTHON_WHEELS += $(SWSSSDK_PY2) +$(DOCKER_CONFIG_ENGINE)_PYTHON_WHEELS += $(SONIC_CONFIG_ENGINE) +$(DOCKER_CONFIG_ENGINE)_LOAD_DOCKERS += $(DOCKER_BASE) +SONIC_DOCKER_IMAGES += $(DOCKER_CONFIG_ENGINE) diff --git a/rules/docker-database.mk b/rules/docker-database.mk new file mode 100644 index 000000000000..eb7f6531f83e --- /dev/null +++ b/rules/docker-database.mk @@ -0,0 +1,14 @@ +# docker image for database + +DOCKER_DATABASE = docker-database.gz +$(DOCKER_DATABASE)_PATH = $(DOCKERS_PATH)/docker-database +$(DOCKER_DATABASE)_DEPENDS += $(REDIS_TOOLS) $(REDIS_SERVER) +$(DOCKER_DATABASE)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_DATABASE) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_DATABASE) + +$(DOCKER_DATABASE)_CONTAINER_NAME = database +$(DOCKER_DATABASE)_RUN_OPT += --net=host --privileged -t +$(DOCKER_DATABASE)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + +$(DOCKER_DATABASE)_BASE_IMAGE_FILES += redis-cli:/usr/bin/redis-cli diff --git a/rules/docker-dhcp-relay.mk b/rules/docker-dhcp-relay.mk new file mode 100644 index 000000000000..44d3904d7394 --- /dev/null +++ b/rules/docker-dhcp-relay.mk @@ -0,0 +1,13 @@ +# Docker image for DHCP relay + +DOCKER_DHCP_RELAY = docker-dhcp-relay.gz +$(DOCKER_DHCP_RELAY)_PATH = $(DOCKERS_PATH)/docker-dhcp-relay +$(DOCKER_DHCP_RELAY)_DEPENDS += $(ISC_DHCP_COMMON) $(ISC_DHCP_RELAY) +$(DOCKER_DHCP_RELAY)_LOAD_DOCKERS = $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_DHCP_RELAY) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_DHCP_RELAY) + + +$(DOCKER_DHCP_RELAY)_CONTAINER_NAME = dhcp_relay +$(DOCKER_DHCP_RELAY)_RUN_OPT += --net=host --privileged -t +$(DOCKER_DHCP_RELAY)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/rules/docker-fpm-frr.mk b/rules/docker-fpm-frr.mk new file mode 100644 index 000000000000..f9a858611fa1 --- /dev/null +++ b/rules/docker-fpm-frr.mk @@ -0,0 +1,14 @@ +# docker image for fpm-frr + +DOCKER_FPM_FRR = docker-fpm-frr.gz +$(DOCKER_FPM_FRR)_PATH = $(DOCKERS_PATH)/docker-fpm-frr +$(DOCKER_FPM_FRR)_DEPENDS += $(FRR) $(SWSS) +$(DOCKER_FPM_FRR)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_FPM_FRR) + +$(DOCKER_FPM_FRR)_CONTAINER_NAME = bgp +$(DOCKER_FPM_FRR)_RUN_OPT += --net=host --privileged -t +$(DOCKER_FPM_FRR)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_FPM_FRR)_RUN_OPT += -v /etc/sonic/frr:/etc/frr:rw + +$(DOCKER_FPM_FRR)_BASE_IMAGE_FILES += vtysh:/usr/bin/vtysh diff --git a/rules/docker-fpm-gobgp.mk b/rules/docker-fpm-gobgp.mk new file mode 100644 index 000000000000..12fa37dc1d97 --- /dev/null +++ b/rules/docker-fpm-gobgp.mk @@ -0,0 +1,11 @@ +# docker image for fpm-gobgp + +DOCKER_FPM_GOBGP = docker-fpm-gobgp.gz +$(DOCKER_FPM_GOBGP)_PATH = $(DOCKERS_PATH)/docker-fpm-gobgp +$(DOCKER_FPM_GOBGP)_DEPENDS += $(GOBGP) +$(DOCKER_FPM_GOBGP)_LOAD_DOCKERS += $(DOCKER_FPM_QUAGGA) +SONIC_DOCKER_IMAGES += $(DOCKER_FPM_GOBGP) + +$(DOCKER_FPM_GOBGP)_CONTAINER_NAME = bgp +$(DOCKER_FPM_GOBGP)_RUN_OPT += --net=host --privileged -t +$(DOCKER_FPM_GOBGP)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/rules/docker-fpm-quagga.mk b/rules/docker-fpm-quagga.mk new file mode 100644 index 000000000000..a9c0511ba173 --- /dev/null +++ b/rules/docker-fpm-quagga.mk @@ -0,0 +1,13 @@ +# docker image for fpm-quagga + +DOCKER_FPM_QUAGGA = docker-fpm-quagga.gz +$(DOCKER_FPM_QUAGGA)_PATH = $(DOCKERS_PATH)/docker-fpm-quagga +$(DOCKER_FPM_QUAGGA)_DEPENDS += $(QUAGGA) $(SWSS) +$(DOCKER_FPM_QUAGGA)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_FPM_QUAGGA) + +$(DOCKER_FPM_QUAGGA)_CONTAINER_NAME = bgp +$(DOCKER_FPM_QUAGGA)_RUN_OPT += --net=host --privileged -t +$(DOCKER_FPM_QUAGGA)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + +$(DOCKER_FPM_QUAGGA)_BASE_IMAGE_FILES += vtysh:/usr/bin/vtysh diff --git a/rules/docker-fpm.mk b/rules/docker-fpm.mk new file mode 100644 index 000000000000..b38ad99356f5 --- /dev/null +++ b/rules/docker-fpm.mk @@ -0,0 +1,9 @@ +# Docker-fpm rule-file is simply a wrapper containing routing-stack selection logic. + +ifeq ($(SONIC_ROUTING_STACK), quagga) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_FPM_QUAGGA) +else ifeq ($(SONIC_ROUTING_STACK), frr) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_FPM_FRR) +else +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_FPM_GOBGP) +endif diff --git a/rules/docker-lldp-sv2.mk b/rules/docker-lldp-sv2.mk new file mode 100644 index 000000000000..93f08a541239 --- /dev/null +++ b/rules/docker-lldp-sv2.mk @@ -0,0 +1,15 @@ +# docker image for lldp agent + +DOCKER_LLDP_SV2 = docker-lldp-sv2.gz +$(DOCKER_LLDP_SV2)_PATH = $(DOCKERS_PATH)/docker-lldp-sv2 +$(DOCKER_LLDP_SV2)_DEPENDS += $(LLDPD) $(LIBSWSSCOMMON) $(PYTHON_SWSSCOMMON) +$(DOCKER_LLDP_SV2)_PYTHON_WHEELS += $(DBSYNCD_PY2) +$(DOCKER_LLDP_SV2)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_LLDP_SV2) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_LLDP_SV2) + +$(DOCKER_LLDP_SV2)_CONTAINER_NAME = lldp +$(DOCKER_LLDP_SV2)_RUN_OPT += --net=host --privileged -t +$(DOCKER_LLDP_SV2)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + +$(DOCKER_LLDP_SV2)_BASE_IMAGE_FILES += lldpctl:/usr/bin/lldpctl diff --git a/rules/docker-platform-monitor.mk b/rules/docker-platform-monitor.mk new file mode 100644 index 000000000000..d6404e18c47f --- /dev/null +++ b/rules/docker-platform-monitor.mk @@ -0,0 +1,20 @@ +# Docker image for SONiC platform monitoring tools + +DOCKER_PLATFORM_MONITOR = docker-platform-monitor.gz +$(DOCKER_PLATFORM_MONITOR)_PATH = $(DOCKERS_PATH)/docker-platform-monitor +$(DOCKER_PLATFORM_MONITOR)_DEPENDS += $(LIBSWSSCOMMON) $(PYTHON_SWSSCOMMON) $(SONIC_LEDD) $(SONIC_XCVRD) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PLATFORM_COMMON_PY2) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SWSSSDK_PY2) +$(DOCKER_PLATFORM_MONITOR)_LOAD_DOCKERS = $(DOCKER_CONFIG_ENGINE) + +SONIC_DOCKER_IMAGES += $(DOCKER_PLATFORM_MONITOR) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_PLATFORM_MONITOR) + +$(DOCKER_PLATFORM_MONITOR)_CONTAINER_NAME = pmon +$(DOCKER_PLATFORM_MONITOR)_RUN_OPT += --net=host --privileged -t +$(DOCKER_PLATFORM_MONITOR)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + +# Mount Arista python library on Aboot images to be used by plugins +$(DOCKER_PLATFORM_MONITOR)_aboot_RUN_OPT += -v /usr/lib/python2.7/dist-packages/arista:/usr/lib/python2.7/dist-packages/arista:ro + +$(DOCKER_PLATFORM_MONITOR)_BASE_IMAGE_FILES += sensors:/usr/bin/sensors diff --git a/rules/docker-ptf.mk b/rules/docker-ptf.mk new file mode 100644 index 000000000000..2782c45339bd --- /dev/null +++ b/rules/docker-ptf.mk @@ -0,0 +1,6 @@ +# docker image for ptf + +DOCKER_PTF = docker-ptf.gz +$(DOCKER_PTF)_PATH = $(DOCKERS_PATH)/docker-ptf +$(DOCKER_PTF)_DEPENDS += $(LIBTHRIFT) $(PYTHON_THRIFT) $(PTF) +SONIC_DOCKER_IMAGES += $(DOCKER_PTF) diff --git a/rules/docker-router-advertiser.mk b/rules/docker-router-advertiser.mk new file mode 100644 index 000000000000..129246d8fa2d --- /dev/null +++ b/rules/docker-router-advertiser.mk @@ -0,0 +1,12 @@ +# Docker image for router advertiser + +DOCKER_ROUTER_ADVERTISER = docker-router-advertiser.gz +$(DOCKER_ROUTER_ADVERTISER)_PATH = $(DOCKERS_PATH)/docker-router-advertiser +$(DOCKER_ROUTER_ADVERTISER)_LOAD_DOCKERS = $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_ROUTER_ADVERTISER) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ROUTER_ADVERTISER) + + +$(DOCKER_ROUTER_ADVERTISER)_CONTAINER_NAME = radv +$(DOCKER_ROUTER_ADVERTISER)_RUN_OPT += --net=host --privileged -t +$(DOCKER_ROUTER_ADVERTISER)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/rules/docker-snmp-sv2.mk b/rules/docker-snmp-sv2.mk new file mode 100644 index 000000000000..2da1e8e685e6 --- /dev/null +++ b/rules/docker-snmp-sv2.mk @@ -0,0 +1,16 @@ +# docker image for snmp agent + +DOCKER_SNMP_SV2 = docker-snmp-sv2.gz +$(DOCKER_SNMP_SV2)_PATH = $(DOCKERS_PATH)/docker-snmp-sv2 +## TODO: remove LIBPY3_DEV if we can get pip3 directly +$(DOCKER_SNMP_SV2)_DEPENDS += $(SNMP) $(SNMPD) $(PY3) $(LIBPY3_DEV) +$(DOCKER_SNMP_SV2)_PYTHON_WHEELS += $(SONIC_PLATFORM_COMMON_PY3) $(SWSSSDK_PY3) $(ASYNCSNMP_PY3) +$(DOCKER_SNMP_SV2)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SNMP_SV2) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SNMP_SV2) + +$(DOCKER_SNMP_SV2)_CONTAINER_NAME = snmp +$(DOCKER_SNMP_SV2)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SNMP_SV2)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +# mount Arista platform python libraries to support corresponding platforms SNMP power status query +$(DOCKER_SNMP_SV2)_RUN_OPT += -v /usr/lib/python3/dist-packages/arista:/usr/lib/python3/dist-packages/arista:ro diff --git a/rules/docker-sonic-mgmt.mk b/rules/docker-sonic-mgmt.mk new file mode 100644 index 000000000000..2f4908e43d73 --- /dev/null +++ b/rules/docker-sonic-mgmt.mk @@ -0,0 +1,5 @@ +# docker image for sonic-mgmt +DOCKER_SONIC_MGMT = docker-sonic-mgmt.gz +$(DOCKER_SONIC_MGMT)_PATH = $(DOCKERS_PATH)/docker-sonic-mgmt +$(DOCKER_SONIC_MGMT)_DEPENDS += $(SONIC_DEVICE_DATA) +SONIC_DOCKER_IMAGES += $(DOCKER_SONIC_MGMT) diff --git a/rules/docker-teamd.mk b/rules/docker-teamd.mk new file mode 100644 index 000000000000..f4a2c7d412df --- /dev/null +++ b/rules/docker-teamd.mk @@ -0,0 +1,15 @@ +# docker image for teamd agent + +DOCKER_TEAMD = docker-teamd.gz +$(DOCKER_TEAMD)_PATH = $(DOCKERS_PATH)/docker-teamd +$(DOCKER_TEAMD)_DEPENDS += $(SWSS) $(LIBTEAMDCT) $(LIBTEAM_UTILS) $(REDIS_TOOLS) +$(DOCKER_TEAMD)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_TEAMD) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_TEAMD) + +$(DOCKER_TEAMD)_CONTAINER_NAME = teamd +$(DOCKER_TEAMD)_RUN_OPT += --net=host --privileged -t +$(DOCKER_TEAMD)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_TEAMD)_RUN_OPT += -v /host/warmboot:/var/warmboot + +$(DOCKER_TEAMD)_BASE_IMAGE_FILES += teamdctl:/usr/bin/teamdctl diff --git a/rules/docker-telemetry.mk b/rules/docker-telemetry.mk new file mode 100644 index 000000000000..fca3b8a39a70 --- /dev/null +++ b/rules/docker-telemetry.mk @@ -0,0 +1,15 @@ +# docker image for telemetry agent + +DOCKER_TELEMETRY = docker-sonic-telemetry.gz +$(DOCKER_TELEMETRY)_PATH = $(DOCKERS_PATH)/docker-sonic-telemetry +$(DOCKER_TELEMETRY)_DEPENDS += $(REDIS_TOOLS) $(SONIC_TELEMETRY) +$(DOCKER_TELEMETRY)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_TELEMETRY) +ifeq ($(ENABLE_SYSTEM_TELEMETRY), y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_TELEMETRY) +endif + +$(DOCKER_TELEMETRY)_CONTAINER_NAME = telemetry +$(DOCKER_TELEMETRY)_RUN_OPT += --net=host --privileged -t +$(DOCKER_TELEMETRY)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + diff --git a/rules/frr.mk b/rules/frr.mk new file mode 100644 index 000000000000..2b7cc1fa14e4 --- /dev/null +++ b/rules/frr.mk @@ -0,0 +1,9 @@ +# FRRouting (frr) package + +FRR_VERSION = 4.0 +export FRR_VERSION + +FRR = frr_$(FRR_VERSION)-1~sonic.debian8+1_amd64.deb +$(FRR)_DEPENDS += $(LIBSNMP_DEV) +$(FRR)_SRC_PATH = $(SRC_PATH)/sonic-frr +SONIC_MAKE_DEBS += $(FRR) diff --git a/rules/functions b/rules/functions new file mode 100644 index 000000000000..93e2a346274e --- /dev/null +++ b/rules/functions @@ -0,0 +1,98 @@ +############################################################################### +## FUNCTIONS +############################################################################### + +############################################################################### +## Colored output +############################################################################### + +# Enable colored output +ifeq ($(SONIC_CONFIG_ENABLE_COLORS),y) +ifeq ($(MAKE_TERMOUT),) +RED=\033[1;31m +PURPLE=\033[1;35m +CYAN=\033[1;36m +GREEN=\033[1;32m +GRAY=\033[0m +endif +endif + +# Print red colored output +# call: +# log_red message +log_red = echo -e "$(RED)$(1)$(GRAY)" + +# Print purple colored output +# call: +# log_purple message +log_purple = echo -e "$(PURPLE)$(1)$(GRAY)" + +# Print blue colored output +# call: +# log_blue message +log_blue = echo -e "$(CYAN)$(1)$(GRAY)" + +# Print green colored output +# call: +# log_green message +log_green = echo -e "$(GREEN)$(1)$(GRAY)" + +############################################################################### +## Logging +############################################################################### + +FLUSH_LOG = rm -f $@.log + +LOG = &>> $(PROJECT_ROOT)/$@.log || { [ $$? -eq 0 ] || pushd $(PROJECT_ROOT) > /dev/null ; ./update_screen.sh -e $@ ; popd > /dev/null ; false ; } + +############################################################################### +## Header and footer for each target +############################################################################### + +# Dump targets taht current depends on +ifeq ($(SONIC_CONFIG_PRINT_DEPENDENCIES),y) +PRINT_DEPENDENCIES = echo Dependencies for $@ are $^ $(LOG) +endif + +# header for each rule +define HEADER +@ +$(PRINT_DEPENDENCIES) +$(FLUSH_LOG) +./update_screen.sh -a $@ +endef + +# footer for each rule +define FOOTER +./update_screen.sh -d $@ +endef + +############################################################################### +## Definition of derived target +############################################################################### + +# call: +# add_derived_package some_deb.deb, some_derived_deb +define add_derived_package +$(2)_DEPENDS += $(1) +$(2)_RDEPENDS += $($(1)_RDEPENDS) +$(2)_MAIN_DEB = $(1) +$(1)_DERIVED_DEBS += $(2) +$(2)_URL = $($(1)_URL) +$(2)_SRC_PATH = $($(1)_SRC_PATH) +SONIC_DERIVED_DEBS += $(2) +endef + +# call: +# add_extra_package some_deb.deb, some_extra_deb +define add_extra_package +$(2)_MAIN_DEB = $(1) +$(1)_EXTRA_DEBS += $(2) +SONIC_EXTRA_DEBS += $(2) +endef + +############################################################################### +## Utility functions +############################################################################### + +expand = $(foreach d,$(1),$(call expand,$($(d)_$(2)),$(2))) $(1) diff --git a/rules/gobgp.mk b/rules/gobgp.mk new file mode 100644 index 000000000000..5ce566f7b630 --- /dev/null +++ b/rules/gobgp.mk @@ -0,0 +1,5 @@ +# gobgp package + +GOBGP = gobgp_1.16-01_amd64.deb +$(GOBGP)_SRC_PATH = $(SRC_PATH)/gobgp +SONIC_DPKG_DEBS += $(GOBGP) diff --git a/rules/hiredis.mk b/rules/hiredis.mk new file mode 100644 index 000000000000..600d1c72f5b2 --- /dev/null +++ b/rules/hiredis.mk @@ -0,0 +1,18 @@ +# libhiredis package + +HIREDIS_VERSION = 0.13.3 +HIREDIS_VERSION_FULL = $(HIREDIS_VERSION)-2 + +export HIREDIS_VERSION HIREDIS_VERSION_FULL + +LIBHIREDIS = libhiredis0.13_$(HIREDIS_VERSION_FULL)_amd64.deb +$(LIBHIREDIS)_SRC_PATH = $(SRC_PATH)/hiredis +$(LIBHIREDIS)_DEPENDS += $(REDIS_TOOLS) $(REDIS_SERVER) +$(LIBHIREDIS)_RDEPENDS += +SONIC_MAKE_DEBS += $(LIBHIREDIS) + +LIBHIREDIS_DEV = libhiredis-dev_$(HIREDIS_VERSION_FULL)_amd64.deb +$(eval $(call add_derived_package,$(LIBHIREDIS),$(LIBHIREDIS_DEV))) + +LIBHIREDIS_DBG = libhiredis-dbg_$(HIREDIS_VERSION_FULL)_amd64.deb +$(eval $(call add_derived_package,$(LIBHIREDIS),$(LIBHIREDIS_DBG))) diff --git a/rules/initramfs-tools.mk b/rules/initramfs-tools.mk new file mode 100644 index 000000000000..badc584dd2be --- /dev/null +++ b/rules/initramfs-tools.mk @@ -0,0 +1,13 @@ +# initramfs-tools package + +INITRAMFS_TOOLS_VERSION = 0.130 +export INITRAMFS_TOOLS_VERSION + +INITRAMFS_TOOLS = initramfs-tools_$(INITRAMFS_TOOLS_VERSION)_all.deb +$(INITRAMFS_TOOLS)_SRC_PATH = $(SRC_PATH)/initramfs-tools +SONIC_MAKE_DEBS += $(INITRAMFS_TOOLS) + +INITRAMFS_TOOLS_CORE = initramfs-tools-core_$(INITRAMFS_TOOLS_VERSION)_all.deb +$(eval $(call add_extra_package,$(INITRAMFS_TOOLS),$(INITRAMFS_TOOLS_CORE))) + +SONIC_STRETCH_DEBS += $(INITRAMFS_TOOLS) $(INITRAMFS_TOOLS_CORE) diff --git a/rules/iproute2.mk b/rules/iproute2.mk new file mode 100644 index 000000000000..10d8fe4cff3d --- /dev/null +++ b/rules/iproute2.mk @@ -0,0 +1,7 @@ +# iproute2 package + +IPROUTE2_VERSION = 4.9.0-1 + +IPROUTE2 = iproute2_$(IPROUTE2_VERSION)_amd64.deb +$(IPROUTE2)_SRC_PATH = $(SRC_PATH)/iproute2 +SONIC_MAKE_DEBS += $(IPROUTE2) diff --git a/rules/isc-dhcp.mk b/rules/isc-dhcp.mk new file mode 100644 index 000000000000..7b7f69c6cfc6 --- /dev/null +++ b/rules/isc-dhcp.mk @@ -0,0 +1,12 @@ +# isc-dhcp packages + +ISC_DHCP_VERSION = 4.3.3-6 + +export ISC_DHCP_VERSION + +ISC_DHCP_COMMON = isc-dhcp-common_$(ISC_DHCP_VERSION)_amd64.deb +$(ISC_DHCP_COMMON)_SRC_PATH = $(SRC_PATH)/isc-dhcp +SONIC_MAKE_DEBS += $(ISC_DHCP_COMMON) + +ISC_DHCP_RELAY = isc-dhcp-relay_$(ISC_DHCP_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(ISC_DHCP_COMMON),$(ISC_DHCP_RELAY))) diff --git a/rules/ixgbe.mk b/rules/ixgbe.mk new file mode 100644 index 000000000000..86a0e8453a2b --- /dev/null +++ b/rules/ixgbe.mk @@ -0,0 +1,11 @@ +# initramfs-tools package + +IXGBE_DRIVER_VERSION = 5.2.4 +export IXGBE_DRIVER_VERSION + +IXGBE_DRIVER = ixgbe.ko +$(IXGBE_DRIVER)_SRC_PATH = $(SRC_PATH)/ixgbe +$(IXGBE_DRIVER)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_MAKE_FILES += $(IXGBE_DRIVER) + +SONIC_STRETCH_FILES += $(IXGBE_DRIVER) diff --git a/rules/libnl3.mk b/rules/libnl3.mk new file mode 100644 index 000000000000..30e27c5c5157 --- /dev/null +++ b/rules/libnl3.mk @@ -0,0 +1,48 @@ +# libnl3 + +LIBNL3_VERSION_BASE = 3.2.27 +LIBNL3_VERSION = $(LIBNL3_VERSION_BASE)-2 + +export LIBNL3_VERSION_BASE +export LIBNL3_VERSION + +LIBNL3 = libnl-3-200_$(LIBNL3_VERSION)_amd64.deb +$(LIBNL3)_SRC_PATH = $(SRC_PATH)/libnl3 +SONIC_MAKE_DEBS += $(LIBNL3) + +LIBNL3_DEV = libnl-3-dev_$(LIBNL3_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL3_DEV))) + +LIBNL_GENL3 = libnl-genl-3-200_$(LIBNL3_VERSION)_amd64.deb +$(LIBNL_GENL3)_RDEPENDS += $(LIBNL3) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_GENL3))) + +LIBNL_GENL3_DEV = libnl-genl-3-dev_$(LIBNL3_VERSION)_amd64.deb +$(LIBNL_GENL3_DEV)_DEPENDS += $(LIBNL_GENL3) $(LIBNL3_DEV) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_GENL3_DEV))) + +LIBNL_ROUTE3 = libnl-route-3-200_$(LIBNL3_VERSION)_amd64.deb +$(LIBNL_ROUTE3)_RDEPENDS += $(LIBNL3) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_ROUTE3))) + +LIBNL_ROUTE3_DEV = libnl-route-3-dev_$(LIBNL3_VERSION)_amd64.deb +$(LIBNL_ROUTE3_DEV)_DEPENDS += $(LIBNL_ROUTE3) $(LIBNL3_DEV) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_ROUTE3_DEV))) + +LIBNL_NF3 = libnl-nf-3-200_$(LIBNL3_VERSION)_amd64.deb +$(LIBNL_NF3)_DEPENDS += $(LIBNL_ROUTE3_DEV) +$(LIBNL_NF3)_RDEPENDS += $(LIBNL_ROUTE3) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_NF3))) + +LIBNL_NF3_DEV = libnl-nf-3-dev_$(LIBNL3_VERSION)_amd64.deb +$(LIBNL_NF3_DEV)_DEPENDS += $(LIBNL_NF3) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_NF3_DEV))) + +LIBNL_CLI = libnl-cli-3-200_$(LIBNL3_VERSION)_amd64.deb +$(LIBNL_CLI)_DEPENDS += $(LIBNL_GENL3_DEV) $(LIBNL_NF3_DEV) $(LIBNL_ROUTE3_DEV) +$(LIBNL_CLI)_RDEPENDS += $(LIBNL_GENL3) $(LIBNL_NF3) $(LIBNL_ROUTE3) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_CLI))) + +LIBNL_CLI_DEV = libnl-cli-3-dev_$(LIBNL3_VERSION)_amd64.deb +$(LIBNL_CLI_DEV)_DEPENDS += $(LIBNL_CLI) $(LIBNL_GENL3_DEV) $(LIBNL_NF3_DEV) $(LIBNL_ROUTE3_DEV) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_CLI_DEV))) diff --git a/rules/libteam.mk b/rules/libteam.mk new file mode 100644 index 000000000000..9aecb07ce86a --- /dev/null +++ b/rules/libteam.mk @@ -0,0 +1,21 @@ +# libteam packages + +LIBTEAM_VERSION = 1.26-1 + +export LIBTEAM_VERSION + +LIBTEAM = libteam5_$(LIBTEAM_VERSION)_amd64.deb +$(LIBTEAM)_SRC_PATH = $(SRC_PATH)/libteam +$(LIBTEAM)_DEPENDS += $(LIBNL_GENL3_DEV) $(LIBNL_CLI_DEV) +SONIC_MAKE_DEBS += $(LIBTEAM) + +LIBTEAM_DEV = libteam-dev_$(LIBTEAM_VERSION)_amd64.deb +$(LIBTEAM_DEV)_DEPENDS += $(LIBTEAMDCT) +$(eval $(call add_derived_package,$(LIBTEAM),$(LIBTEAM_DEV))) + +LIBTEAMDCT = libteamdctl0_$(LIBTEAM_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(LIBTEAM),$(LIBTEAMDCT))) + +LIBTEAM_UTILS = libteam-utils_$(LIBTEAM_VERSION)_amd64.deb +$(LIBTEAM_UTILS)_DEPENDS += $(LIBTEAMDCT) +$(eval $(call add_derived_package,$(LIBTEAM),$(LIBTEAM_UTILS))) diff --git a/rules/linux-kernel.mk b/rules/linux-kernel.mk new file mode 100644 index 000000000000..05caf384bcc6 --- /dev/null +++ b/rules/linux-kernel.mk @@ -0,0 +1,18 @@ +# linux kernel package + +KVERSION_SHORT = 4.9.0-7 +KVERSION = $(KVERSION_SHORT)-amd64 +KERNEL_VERSION = 4.9.110 +KERNEL_SUBVERSION = 3+deb9u2 + +export KVERSION_SHORT KVERSION KERNEL_VERSION KERNEL_SUBVERSION + +LINUX_HEADERS_COMMON = linux-headers-$(KVERSION_SHORT)-common_$(KERNEL_VERSION)-$(KERNEL_SUBVERSION)_all.deb +$(LINUX_HEADERS_COMMON)_SRC_PATH = $(SRC_PATH)/sonic-linux-kernel +SONIC_MAKE_DEBS += $(LINUX_HEADERS_COMMON) + +LINUX_HEADERS = linux-headers-$(KVERSION)_$(KERNEL_VERSION)-$(KERNEL_SUBVERSION)_amd64.deb +$(eval $(call add_derived_package,$(LINUX_HEADERS_COMMON),$(LINUX_HEADERS))) + +LINUX_KERNEL = linux-image-$(KVERSION)_$(KERNEL_VERSION)-$(KERNEL_SUBVERSION)_amd64.deb +$(eval $(call add_derived_package,$(LINUX_HEADERS_COMMON),$(LINUX_KERNEL))) diff --git a/rules/lldpd.mk b/rules/lldpd.mk new file mode 100644 index 000000000000..0e0d13721f83 --- /dev/null +++ b/rules/lldpd.mk @@ -0,0 +1,17 @@ +# lldpd package + +LLDPD_VERSION = 0.9.6 + +LLDPD = lldpd_$(LLDPD_VERSION)-0_amd64.deb +$(LLDPD)_DEPENDS += $(LIBSNMP_DEV) +$(LLDPD)_RDEPENDS += $(LIBSNMP) +$(LLDPD)_SRC_PATH = $(SRC_PATH)/lldpd +SONIC_MAKE_DEBS += $(LLDPD) + +LIBLLDPCTL = liblldpctl-dev_$(LLDPD_VERSION)-0_amd64.deb +$(eval $(call add_derived_package,$(LLDPD),$(LIBLLDPCTL))) + +# Export these variables so they can be used in a sub-make +export LLDPD_VERSION +export LLDPD +export LIBLLDPCTL diff --git a/rules/mpdecimal.mk b/rules/mpdecimal.mk new file mode 100644 index 000000000000..849c65057192 --- /dev/null +++ b/rules/mpdecimal.mk @@ -0,0 +1,13 @@ +# mpdecimal package + +MPDECIMAL_VERSION = 2.4.2 +MPDECIMAL_VERSION_FULL = $(MPDECIMAL_VERSION)-1 + +export MPDECIMAL_VERSION MPDECIMAL_VERSION_FULL + +LIBMPDECIMAL = libmpdec2_$(MPDECIMAL_VERSION_FULL)_amd64.deb +$(LIBMPDECIMAL)_SRC_PATH = $(SRC_PATH)/mpdecimal +SONIC_MAKE_DEBS += $(LIBMPDECIMAL) + +LIBMPDECIMAL_DEV = libmpdec-dev_$(MPDECIMAL_VERSION_FULL)_amd64.deb +$(eval $(call add_derived_package,$(LIBMPDECIMAL),$(LIBMPDECIMAL_DEV))) diff --git a/rules/ptf.mk b/rules/ptf.mk new file mode 100644 index 000000000000..5fe275bdadae --- /dev/null +++ b/rules/ptf.mk @@ -0,0 +1,5 @@ +# ptf package + +PTF = python-ptf_0.9-1_all.deb +$(PTF)_SRC_PATH = $(SRC_PATH)/ptf +SONIC_DPKG_DEBS += $(PTF) diff --git a/rules/python-click.mk b/rules/python-click.mk new file mode 100644 index 000000000000..0212f5e5584a --- /dev/null +++ b/rules/python-click.mk @@ -0,0 +1,16 @@ +# python-click package +# +# Python Click versions < 6.7 have a bug which causes bash completion +# functionality to stop working after two sublevels. sonic-utilities depends +# on this package, and the most recent version provided by Debian Jessie and +# Stretch is v6.6. We build version 6.7 from source in order to fix this bug. +# TODO: If we upgrade to a distro which provides a version >= 6.7 we will no +# longer need to build this. + +PYTHON_CLICK_VERSION = 6.7-4 + +export PYTHON_CLICK_VERSION + +PYTHON_CLICK = python-click_$(PYTHON_CLICK_VERSION)_all.deb +$(PYTHON_CLICK)_SRC_PATH = $(SRC_PATH)/python-click +SONIC_MAKE_DEBS += $(PYTHON_CLICK) diff --git a/rules/python3.mk b/rules/python3.mk new file mode 100644 index 000000000000..2473c9aeb498 --- /dev/null +++ b/rules/python3.mk @@ -0,0 +1,35 @@ +PYTHON_VER=3.6.0-1 +PYTHON_PNAME=python3.6 + +export PYTHON_VER +export PYTHON_PNAME + +LIBPY3_MIN = lib$(PYTHON_PNAME)-minimal_$(PYTHON_VER)_amd64.deb +$(LIBPY3_MIN)_SRC_PATH = $(SRC_PATH)/python3 +$(LIBPY3_MIN)_DEPENDS += +$(LIBPY3_MIN)_RDEPENDS += +SONIC_MAKE_DEBS += $(LIBPY3_MIN) + +LIBPY3_STD = lib$(PYTHON_PNAME)-stdlib_$(PYTHON_VER)_amd64.deb +$(eval $(call add_derived_package,$(LIBPY3_MIN),$(LIBPY3_STD))) +$(LIBPY3_STD)_DEPENDS += $(LIBMPDECIMAL) +$(LIBPY3_STD)_RDEPENDS += $(LIBPY3_MIN) $(LIBMPDECIMAL) + +LIBPY3 = lib$(PYTHON_PNAME)_$(PYTHON_VER)_amd64.deb +$(eval $(call add_derived_package,$(LIBPY3_MIN),$(LIBPY3))) +$(LIBPY3)_DEPENDS += $(LIBPY3_STD) +$(LIBPY3)_RDEPENDS += $(LIBPY3_MIN) $(LIBPY3_STD) + +PY3_MIN = $(PYTHON_PNAME)-minimal_$(PYTHON_VER)_amd64.deb +$(eval $(call add_derived_package,$(LIBPY3_MIN),$(PY3_MIN))) +$(PY3_MIN)_RDEPENDS += $(LIBPY3_MIN) + +PY3 = $(PYTHON_PNAME)_$(PYTHON_VER)_amd64.deb +$(eval $(call add_derived_package,$(LIBPY3_MIN),$(PY3))) +$(PY3)_DEPENDS += $(PY3_MIN) $(LIBPY3) +$(PY3)_RDEPENDS += $(PY3_MIN) $(LIBPY3) $(LIBPY3_MIN) + +LIBPY3_DEV = lib$(PYTHON_PNAME)-dev_$(PYTHON_VER)_amd64.deb +$(eval $(call add_derived_package,$(LIBPY3_MIN),$(LIBPY3_DEV))) +$(LIBPY3_DEV)_DEPENDS += $(LIBPY3) $($(LIBPY3)_DEPENDS) +$(LIBPY3_DEV)_RDEPENDS += $(LIBPY3) $($(LIBPY3)_RDEPENDS) diff --git a/rules/quagga.mk b/rules/quagga.mk new file mode 100644 index 000000000000..f4ba4f2d0be8 --- /dev/null +++ b/rules/quagga.mk @@ -0,0 +1,6 @@ +# quagga package + +QUAGGA = quagga_0.99.24.1-2.1_amd64.deb +$(QUAGGA)_DEPENDS += $(LIBSNMP_DEV) +$(QUAGGA)_SRC_PATH = $(SRC_PATH)/sonic-quagga +SONIC_DPKG_DEBS += $(QUAGGA) diff --git a/rules/redis-dump-load-py2.mk b/rules/redis-dump-load-py2.mk new file mode 100644 index 000000000000..5f756caada9c --- /dev/null +++ b/rules/redis-dump-load-py2.mk @@ -0,0 +1,6 @@ +# redis_dump_load python2 wheel + +REDIS_DUMP_LOAD_PY2 = redis_dump_load-1.1-py2-none-any.whl +$(REDIS_DUMP_LOAD_PY2)_SRC_PATH = $(SRC_PATH)/redis-dump-load +$(REDIS_DUMP_LOAD_PY2)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(REDIS_DUMP_LOAD_PY2) diff --git a/rules/redis.mk b/rules/redis.mk new file mode 100644 index 000000000000..1adf209f6a6c --- /dev/null +++ b/rules/redis.mk @@ -0,0 +1,15 @@ +# redis package + +REDIS_VERSION = 3.2.4-1~bpo8+1 + +REDIS_TOOLS = redis-tools_$(REDIS_VERSION)_amd64.deb +$(REDIS_TOOLS)_SRC_PATH = $(SRC_PATH)/redis +SONIC_MAKE_DEBS += $(REDIS_TOOLS) + +REDIS_SERVER = redis-server_$(REDIS_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(REDIS_TOOLS),$(REDIS_SERVER))) + +REDIS_SENTINEL = redis-sentinel_$(REDIS_VERSION)_amd64.deb +$(REDIS_SENTINEL)_DEPENDS += $(REDIS_SERVER) +$(REDIS_SENTINEL)_RDEPENDS += $(REDIS_SERVER) +$(eval $(call add_derived_package,$(REDIS_TOOLS),$(REDIS_SENTINEL))) diff --git a/rules/sairedis.mk b/rules/sairedis.mk new file mode 100644 index 000000000000..fc481e620cd7 --- /dev/null +++ b/rules/sairedis.mk @@ -0,0 +1,61 @@ +# sairedis package + +LIBSAIREDIS = libsairedis_1.0.0_amd64.deb +$(LIBSAIREDIS)_SRC_PATH = $(SRC_PATH)/sonic-sairedis +$(LIBSAIREDIS)_DEPENDS += $(LIBSWSSCOMMON_DEV) $(LIBTHRIFT_DEV) +$(LIBSAIREDIS)_RDEPENDS += $(LIBSWSSCOMMON) +$(LIBSAIREDIS)_DEB_BUILD_OPTIONS = nocheck +SONIC_DPKG_DEBS += $(LIBSAIREDIS) + +LIBSAIREDIS_DEV = libsairedis-dev_1.0.0_amd64.deb +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIREDIS_DEV))) + +LIBSAIVS = libsaivs_1.0.0_amd64.deb +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIVS))) + +LIBSAIVS_DEV = libsaivs-dev_1.0.0_amd64.deb +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIVS_DEV))) + +ifneq ($(CONFIGURED_PLATFORM),vs) +SYNCD = syncd_1.0.0_amd64.deb +$(SYNCD)_RDEPENDS += $(LIBSAIREDIS) $(LIBSAIMETADATA) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(SYNCD))) + +SYNCD_RPC = syncd-rpc_1.0.0_amd64.deb +$(SYNCD_RPC)_RDEPENDS += $(LIBSAIREDIS) $(LIBSAIMETADATA) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(SYNCD_RPC))) +endif + +LIBSAIMETADATA = libsaimetadata_1.0.0_amd64.deb +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIMETADATA))) + +LIBSAIMETADATA_DEV = libsaimetadata-dev_1.0.0_amd64.deb +$(LIBSAIMETADATA_DEV)_DEPENDS += $(LIBSAIMETADATA) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIMETADATA_DEV))) + +LIBSAIREDIS_DBG = libsairedis-dbg_1.0.0_amd64.deb +$(LIBSAIREDIS_DBG)_DEPENDS += $(LIBSAIREDIS) +$(LIBSAIREDIS_DBG)_RDEPENDS += $(LIBSAIREDIS) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIREDIS_DBG))) + +LIBSAIVS_DBG = libsaivs-dbg_1.0.0_amd64.deb +$(LIBSAIVS_DBG)_DEPENDS += $(LIBSAIVS) +$(LIBSAIVS_DBG)_RDEPENDS += $(LIBSAIVS) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIVS_DBG))) + +ifneq ($(CONFIGURED_PLATFORM),vs) +SYNCD_DBG = syncd-dbg_1.0.0_amd64.deb +$(SYNCD_DBG)_DEPENDS += $(SYNCD) +$(SYNCD_DBG)_RDEPENDS += $(SYNCD) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(SYNCD_DBG))) + +SYNCD_RPC_DBG = syncd-rpc-dbg_1.0.0_amd64.deb +$(SYNCD_RPC_DBG)_DEPENDS += $(SYNCD_RPC) +$(SYNCD_RPC_DBG)_RDEPENDS += $(SYNCD_RPC) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(SYNCD_RPC_DBG))) +endif + +LIBSAIMETADATA_DBG = libsaimetadata-dbg_1.0.0_amd64.deb +$(LIBSAIMETADATA_DBG)_DEPENDS += $(LIBSAIMETADATA) +$(LIBSAIMETADATA_DBG)_RDEPENDS += $(LIBSAIMETADATA) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIMETADATA_DBG))) diff --git a/rules/scripts.mk b/rules/scripts.mk new file mode 100644 index 000000000000..fbefdd68d2cd --- /dev/null +++ b/rules/scripts.mk @@ -0,0 +1,11 @@ + +ARP_UPDATE_SCRIPT = arp_update +$(ARP_UPDATE_SCRIPT)_PATH = files/scripts + +CONFIGDB_LOAD_SCRIPT = configdb-load.sh +$(CONFIGDB_LOAD_SCRIPT)_PATH = files/scripts + +SONIC_COPY_FILES += $(CONFIGDB_LOAD_SCRIPT) \ + $(ARP_UPDATE_SCRIPT) + + diff --git a/rules/snmpd.mk b/rules/snmpd.mk new file mode 100644 index 000000000000..b7635cc7e032 --- /dev/null +++ b/rules/snmpd.mk @@ -0,0 +1,55 @@ +# snmpd package + +SNMPD_VERSION = 5.7.3+dfsg +SNMPD_VERSION_FULL = $(SNMPD_VERSION)-1.5 + +export SNMPD_VERSION SNMPD_VERSION_FULL + +LIBSNMP_BASE = libsnmp-base_$(SNMPD_VERSION_FULL)_all.deb +$(LIBSNMP_BASE)_SRC_PATH = $(SRC_PATH)/snmpd +$(LIBSNMP_BASE)_DEPENDS += $(LIBNL3_DEV) +$(LIBSNMP_BASE)_RDEPENDS += $(LIBNL3) +SONIC_MAKE_DEBS += $(LIBSNMP_BASE) + +SNMPTRAPD = snmptrapd_$(SNMPD_VERSION_FULL)_amd64.deb +$(SNMPTRAPD)_DEPENDS += $(LIBSNMP) $(SNMPD) +$(SNMPTRAPD)_RDEPENDS += $(LIBSNMP) $(SNMPD) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(SNMPTRAPD))) + +SNMP = snmp_$(SNMPD_VERSION_FULL)_amd64.deb +$(SNMP)_DEPENDS += $(LIBSNMP) +$(SNMP)_RDEPENDS += $(LIBSNMP) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(SNMP))) + +SNMPD = snmpd_$(SNMPD_VERSION_FULL)_amd64.deb +$(SNMPD)_DEPENDS += $(LIBSNMP) +$(SNMPD)_RDEPENDS += $(LIBSNMP) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(SNMPD))) + +LIBSNMP = libsnmp30_$(SNMPD_VERSION_FULL)_amd64.deb +$(LIBSNMP)_RDEPENDS += $(LIBSNMP_BASE) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(LIBSNMP))) + +LIBSNMP_DBG = libsnmp30-dbg_$(SNMPD_VERSION_FULL)_amd64.deb +$(LIBSNMP_DBG)_DEPENDS += $(LIBSNMP) +$(LIBSNMP_DBG)_RDEPENDS += $(LIBSNMP) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(LIBSNMP_DBG))) + +LIBSNMP_DEV = libsnmp-dev_$(SNMPD_VERSION_FULL)_amd64.deb +$(LIBSNMP_DEV)_DEPENDS += $(LIBSNMP) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(LIBSNMP_DEV))) + +LIBSNMP_PERL = libsnmp-perl_$(SNMPD_VERSION_FULL)_amd64.deb +$(LIBSNMP_PERL)_DEPENDS += $(LIBSNMP) +$(LIBSNMP_PERL)_RDEPENDS += $(LIBSNMP) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(LIBSNMP_PERL))) + +PYTHON_NETSNMP = python-netsnmp_$(SNMPD_VERSION_FULL)_amd64.deb +$(PYTHON_NETSNMP)_DEPENDS += $(LIBSNMP) +$(PYTHON_NETSNMP)_RDEPENDS += $(LIBSNMP) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(PYTHON_NETSNMP))) + +TKMIB = tkmib_$(SNMPD_VERSION_FULL)_all.deb +$(TKMIB)_DEPENDS += $(LIBSNMP_PERL) +$(TKMIB)_RDEPENDS += $(LIBSNMP_PERL) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(TKMIB))) diff --git a/rules/socat.mk b/rules/socat.mk new file mode 100644 index 000000000000..b93795223624 --- /dev/null +++ b/rules/socat.mk @@ -0,0 +1,9 @@ +# socat packages + +SOCAT_VERSION = 1.7.3.1-2+deb9u1 + +export SOCAT_VERSION + +SOCAT = socat_$(SOCAT_VERSION)_amd64.deb +$(SOCAT)_SRC_PATH = $(SRC_PATH)/socat +SONIC_MAKE_DEBS += $(SOCAT) diff --git a/rules/sonic-config.mk b/rules/sonic-config.mk new file mode 100644 index 000000000000..854b577b3362 --- /dev/null +++ b/rules/sonic-config.mk @@ -0,0 +1,7 @@ +# sonic-config-engine package + +SONIC_CONFIG_ENGINE = sonic_config_engine-1.0-py2-none-any.whl +$(SONIC_CONFIG_ENGINE)_SRC_PATH = $(SRC_PATH)/sonic-config-engine +$(SONIC_CONFIG_ENGINE)_DEPENDS += $(SWSSSDK_PY2) +$(SONIC_CONFIG_ENGINE)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(SONIC_CONFIG_ENGINE) diff --git a/rules/sonic-device-data.mk b/rules/sonic-device-data.mk new file mode 100644 index 000000000000..abf7d0501f93 --- /dev/null +++ b/rules/sonic-device-data.mk @@ -0,0 +1,10 @@ +# sonic-device-data Debian package + +SONIC_DEVICE_DATA_VERSION = 1.0 +SONIC_DEVICE_DATA_VERSION_FULL = $(SONIC_DEVICE_DATA_VERSION)-1 + +export SONIC_DEVICE_DATA_VERSION SONIC_DEVICE_DATA_VERSION_FULL + +SONIC_DEVICE_DATA = sonic-device-data_$(SONIC_DEVICE_DATA_VERSION_FULL)_all.deb +$(SONIC_DEVICE_DATA)_SRC_PATH = $(SRC_PATH)/sonic-device-data +SONIC_MAKE_DEBS += $(SONIC_DEVICE_DATA) diff --git a/rules/sonic-ledd.mk b/rules/sonic-ledd.mk new file mode 100644 index 000000000000..056f0f6c9bd8 --- /dev/null +++ b/rules/sonic-ledd.mk @@ -0,0 +1,5 @@ +# sonic-ledd (SONiC Front-panel LED control daemon) Debian package + +SONIC_LEDD = python-sonic-ledd_1.1-1_all.deb +$(SONIC_LEDD)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-ledd +SONIC_PYTHON_STDEB_DEBS += $(SONIC_LEDD) diff --git a/rules/sonic-platform-common.mk b/rules/sonic-platform-common.mk new file mode 100644 index 000000000000..95789354a4da --- /dev/null +++ b/rules/sonic-platform-common.mk @@ -0,0 +1,13 @@ +# sonic-platform-common package + +SONIC_PLATFORM_COMMON_PY2 = sonic_platform_common-1.0-py2-none-any.whl +$(SONIC_PLATFORM_COMMON_PY2)_SRC_PATH = $(SRC_PATH)/sonic-platform-common +$(SONIC_PLATFORM_COMMON_PY2)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(SONIC_PLATFORM_COMMON_PY2) + +# Als build sonic-platform-common into python3 wheel, so we can use PSU code in SNMP docker +# Note: _DEPENDS macro is not defined +SONIC_PLATFORM_COMMON_PY3 = sonic_platform_common-1.0-py3-none-any.whl +$(SONIC_PLATFORM_COMMON_PY3)_SRC_PATH = $(SRC_PATH)/sonic-platform-common +$(SONIC_PLATFORM_COMMON_PY3)_PYTHON_VERSION = 3 +SONIC_PYTHON_WHEELS += $(SONIC_PLATFORM_COMMON_PY3) diff --git a/rules/sonic-utilities.mk b/rules/sonic-utilities.mk new file mode 100644 index 000000000000..eba618d051dc --- /dev/null +++ b/rules/sonic-utilities.mk @@ -0,0 +1,16 @@ +# sonic utilities package +# +# NOTE: sonic-config-engine is a build-time dependency of sonic-utilities +# due to unit tests which are run during the build. However, +# sonic-platform-common and swsssdk are runtime dependencies, and should be +# added here also. However, the current build system assumes all runtime +# dependencies are .deb packages. +# +# TODO: Create a way to specify both .deb and .whl runtime dependencies +# then add the aforementioned runtime dependencies here. +# + +SONIC_UTILS = python-sonic-utilities_1.2-1_all.deb +$(SONIC_UTILS)_SRC_PATH = $(SRC_PATH)/sonic-utilities +$(SONIC_UTILS)_WHEEL_DEPENDS = $(SONIC_CONFIG_ENGINE) +SONIC_PYTHON_STDEB_DEBS += $(SONIC_UTILS) diff --git a/rules/sonic-xcvrd.mk b/rules/sonic-xcvrd.mk new file mode 100644 index 000000000000..b97f8dd11b79 --- /dev/null +++ b/rules/sonic-xcvrd.mk @@ -0,0 +1,5 @@ +# sonic-xcvrd (SONiC Transceiver monitoring daemon) Debian package + +SONIC_XCVRD = python-sonic-xcvrd_1.0-1_all.deb +$(SONIC_XCVRD)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-xcvrd +SONIC_PYTHON_STDEB_DEBS += $(SONIC_XCVRD) diff --git a/rules/supervisor.mk b/rules/supervisor.mk new file mode 100644 index 000000000000..cd97eabf801d --- /dev/null +++ b/rules/supervisor.mk @@ -0,0 +1,9 @@ +# supervisor package + +SUPERVISOR_VERSION = 3.3.3 + +export SUPERVISOR_VERSION + +SUPERVISOR = python-supervisor_$(SUPERVISOR_VERSION)-1_all.deb +$(SUPERVISOR)_SRC_PATH = $(SRC_PATH)/supervisor +SONIC_MAKE_DEBS += $(SUPERVISOR) diff --git a/rules/swss-common.mk b/rules/swss-common.mk new file mode 100644 index 000000000000..623410d4cdab --- /dev/null +++ b/rules/swss-common.mk @@ -0,0 +1,21 @@ +# libswsscommon package + +LIBSWSSCOMMON = libswsscommon_1.0.0_amd64.deb +$(LIBSWSSCOMMON)_SRC_PATH = $(SRC_PATH)/sonic-swss-common +$(LIBSWSSCOMMON)_DEPENDS += $(LIBHIREDIS_DEV) $(LIBNL3_DEV) $(LIBNL_GENL3_DEV) \ + $(LIBNL_ROUTE3_DEV) $(LIBNL_NF3_DEV) \ + $(LIBNL_CLI_DEV) +$(LIBSWSSCOMMON)_RDEPENDS += $(LIBHIREDIS) $(LIBNL3) $(LIBNL_GENL3) \ + $(LIBNL_ROUTE3) $(LIBNL_NF3) $(LIBNL_CLI) +SONIC_DPKG_DEBS += $(LIBSWSSCOMMON) + +LIBSWSSCOMMON_DEV = libswsscommon-dev_1.0.0_amd64.deb +$(eval $(call add_derived_package,$(LIBSWSSCOMMON),$(LIBSWSSCOMMON_DEV))) + +PYTHON_SWSSCOMMON = python-swsscommon_1.0.0_amd64.deb +$(eval $(call add_derived_package,$(LIBSWSSCOMMON),$(PYTHON_SWSSCOMMON))) + +LIBSWSSCOMMON_DBG = libswsscommon-dbg_1.0.0_amd64.deb +$(LIBSWSSCOMMON_DBG)_DEPENDS += $(LIBSWSSCOMMON) +$(LIBSWSSCOMMON_DBG)_RDEPENDS += $(LIBSWSSCOMMON) +$(eval $(call add_derived_package,$(LIBSWSSCOMMON),$(LIBSWSSCOMMON_DBG))) diff --git a/rules/swss.mk b/rules/swss.mk new file mode 100644 index 000000000000..429eb63ae822 --- /dev/null +++ b/rules/swss.mk @@ -0,0 +1,13 @@ +# swss package + +SWSS = swss_1.0.0_amd64.deb +$(SWSS)_SRC_PATH = $(SRC_PATH)/sonic-swss +$(SWSS)_DEPENDS += $(LIBSAIREDIS_DEV) $(LIBSAIMETADATA_DEV) $(LIBTEAM_DEV) \ + $(LIBTEAMDCT) $(LIBTEAM_UTILS) $(LIBSWSSCOMMON_DEV) +$(SWSS)_RDEPENDS += $(LIBSAIREDIS) $(LIBSAIMETADATA) $(LIBTEAM) $(LIBSWSSCOMMON) $(PYTHON_SWSSCOMMON) +SONIC_DPKG_DEBS += $(SWSS) + +SWSS_DBG = swss-dbg_1.0.0_amd64.deb +$(SWSS_DBG)_DEPENDS += $(SWSS) +$(SWSS_DBG)_RDEPENDS += $(SWSS) +$(eval $(call add_derived_package,$(SWSS),$(SWSS_DBG))) diff --git a/rules/swsssdk-py2.mk b/rules/swsssdk-py2.mk new file mode 100644 index 000000000000..a45677ae5882 --- /dev/null +++ b/rules/swsssdk-py2.mk @@ -0,0 +1,6 @@ +# swsssdk python2 wheel + +SWSSSDK_PY2 = swsssdk-2.0.1-py2-none-any.whl +$(SWSSSDK_PY2)_SRC_PATH = $(SRC_PATH)/sonic-py-swsssdk +$(SWSSSDK_PY2)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(SWSSSDK_PY2) diff --git a/rules/swsssdk-py3.mk b/rules/swsssdk-py3.mk new file mode 100644 index 000000000000..e2f3519e00ca --- /dev/null +++ b/rules/swsssdk-py3.mk @@ -0,0 +1,8 @@ +# swsssdk python3 wheel + +SWSSSDK_PY3 = swsssdk-2.0.1-py3-none-any.whl +$(SWSSSDK_PY3)_SRC_PATH = $(SRC_PATH)/sonic-py-swsssdk +$(SWSSSDK_PY3)_PYTHON_VERSION = 3 +# Synthetic dependency just to avoid race condition +$(SWSSSDK_PY3)_DEPENDS += $(SWSSSDK_PY2) +SONIC_PYTHON_WHEELS += $(SWSSSDK_PY3) diff --git a/rules/tacacs.mk b/rules/tacacs.mk new file mode 100644 index 000000000000..2d08710550f9 --- /dev/null +++ b/rules/tacacs.mk @@ -0,0 +1,32 @@ +# libpam-tacplus packages + +PAM_TACPLUS_VERSION = 1.4.1-1 + +export PAM_TACPLUS_VERSION + +LIBTAC2 = libtac2_$(PAM_TACPLUS_VERSION)_amd64.deb +$(LIBTAC2)_SRC_PATH = $(SRC_PATH)/tacacs/pam +SONIC_MAKE_DEBS += $(LIBTAC2) + +LIBPAM_TACPLUS = libpam-tacplus_$(PAM_TACPLUS_VERSION)_amd64.deb +$(LIBPAM_TACPLUS)_RDEPENDS += $(LIBTAC2) +$(eval $(call add_extra_package,$(LIBTAC2),$(LIBPAM_TACPLUS))) + +LIBTAC_DEV = libtac-dev_$(PAM_TACPLUS_VERSION)_amd64.deb +$(LIBTAC_DEV)_DEPENDS += $(LIBTAC2) +$(eval $(call add_derived_package,$(LIBTAC2),$(LIBTAC_DEV))) + + + +# libnss-tacplus packages +NSS_TACPLUS_VERSION = 1.0.4-1 + +export NSS_TACPLUS_VERSION + +LIBNSS_TACPLUS = libnss-tacplus_$(NSS_TACPLUS_VERSION)_amd64.deb +$(LIBNSS_TACPLUS)_DEPENDS += $(LIBTAC_DEV) +$(LIBNSS_TACPLUS)_RDEPENDS += $(LIBTAC2) +$(LIBNSS_TACPLUS)_SRC_PATH = $(SRC_PATH)/tacacs/nss +SONIC_MAKE_DEBS += $(LIBNSS_TACPLUS) + +SONIC_STRETCH_DEBS += $(LIBPAM_TACPLUS) $(LIBNSS_TACPLUS) diff --git a/rules/telemetry.mk b/rules/telemetry.mk new file mode 100644 index 000000000000..a160bf50899c --- /dev/null +++ b/rules/telemetry.mk @@ -0,0 +1,5 @@ +# SONiC telemetry package + +SONIC_TELEMETRY = sonic-telemetry_0.1_amd64.deb +$(SONIC_TELEMETRY)_SRC_PATH = $(SRC_PATH)/telemetry +SONIC_DPKG_DEBS += $(SONIC_TELEMETRY) diff --git a/rules/thrift.mk b/rules/thrift.mk new file mode 100644 index 000000000000..20b01359a1ee --- /dev/null +++ b/rules/thrift.mk @@ -0,0 +1,17 @@ +# thrift package + +THRIFT_VERSION = 0.9.3 +THRIFT_VERSION_FULL = $(THRIFT_VERSION)-2 + +LIBTHRIFT = libthrift-$(THRIFT_VERSION)_$(THRIFT_VERSION_FULL)_amd64.deb +$(LIBTHRIFT)_SRC_PATH = $(SRC_PATH)/thrift +SONIC_MAKE_DEBS += $(LIBTHRIFT) + +LIBTHRIFT_DEV = libthrift-dev_$(THRIFT_VERSION_FULL)_amd64.deb +$(eval $(call add_derived_package,$(LIBTHRIFT),$(LIBTHRIFT_DEV))) + +PYTHON_THRIFT = python-thrift_$(THRIFT_VERSION_FULL)_amd64.deb +$(eval $(call add_derived_package,$(LIBTHRIFT),$(PYTHON_THRIFT))) + +THRIFT_COMPILER = thrift-compiler_$(THRIFT_VERSION_FULL)_amd64.deb +$(eval $(call add_derived_package,$(LIBTHRIFT),$(THRIFT_COMPILER))) diff --git a/slave.mk b/slave.mk new file mode 100644 index 000000000000..93811b43371c --- /dev/null +++ b/slave.mk @@ -0,0 +1,655 @@ +############################################################################### +## Presettings +############################################################################### + +# Select bash for commands +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e +USER = $(shell id -un) +UID = $(shell id -u) +GUID = $(shell id -g) +SONIC_GET_VERSION=$(shell export BUILD_TIMESTAMP=$(BUILD_TIMESTAMP) && export BUILD_NUMBER=$(BUILD_NUMBER) && . functions.sh && sonic_get_version) + +.SECONDEXPANSION: + +NULL := +SPACE := $(NULL) $(NULL) + +############################################################################### +## General definitions +############################################################################### + +SRC_PATH = src +RULES_PATH = rules +TARGET_PATH = target +DOCKERS_PATH = dockers +DEBS_PATH = $(TARGET_PATH)/debs +FILES_PATH = $(TARGET_PATH)/files +PYTHON_WHEELS_PATH = $(TARGET_PATH)/python-wheels +PROJECT_ROOT = $(shell pwd) + +CONFIGURED_PLATFORM := $(shell [ -f .platform ] && cat .platform || echo generic) +PLATFORM_PATH = platform/$(CONFIGURED_PLATFORM) +export BUILD_NUMBER +export BUILD_TIMESTAMP +export CONFIGURED_PLATFORM + +############################################################################### +## Utility rules +## Define configuration, help etc. +############################################################################### + +.platform : +ifneq ($(CONFIGURED_PLATFORM),generic) + @echo Build system is not configured, please run make configure + @exit 1 +endif + +configure : + @mkdir -p target/debs + @mkdir -p target/files + @mkdir -p target/python-wheels + @echo $(PLATFORM) > .platform + +distclean : .platform clean + @rm -f .platform + +list : + @$(foreach target,$(SONIC_TARGET_LIST),echo $(target);) + +############################################################################### +## Include other rules +############################################################################### + +ifeq ($(SONIC_ENABLE_PFCWD_ON_START),y) +ENABLE_PFCWD_ON_START = y +endif + +ifeq ($(SONIC_ENABLE_SYSTEM_TELEMETRY),y) +ENABLE_SYSTEM_TELEMETRY = y +endif + +ifeq ($(SONIC_ENABLE_SYNCD_RPC),y) +ENABLE_SYNCD_RPC = y +endif + +ifeq ($(SONIC_INSTALL_DEBUG_TOOLS),y) +INSTALL_DEBUG_TOOLS = y +endif + +include $(RULES_PATH)/config +include $(RULES_PATH)/functions +include $(RULES_PATH)/*.mk +ifneq ($(CONFIGURED_PLATFORM), undefined) +include $(PLATFORM_PATH)/rules.mk +endif + +ifeq ($(USERNAME),) +override USERNAME := $(DEFAULT_USERNAME) +else +$(warning USERNAME given on command line: could be visible to other users) +endif + +ifeq ($(PASSWORD),) +override PASSWORD := $(DEFAULT_PASSWORD) +else +$(warning PASSWORD given on command line: could be visible to other users) +endif + +ifeq ($(SONIC_DEBUGGING_ON),y) +DEB_BUILD_OPTIONS_GENERIC := "nostrip" +endif + +ifeq ($(SONIC_PROFILING_ON),y) +DEB_BUILD_OPTIONS_GENERIC := "nostrip noopt" +endif + +ifeq ($(SONIC_BUILD_JOBS),) +override SONIC_BUILD_JOBS := $(SONIC_CONFIG_BUILD_JOBS) +endif + +ifeq ($(KERNEL_PROCURE_METHOD),) +override KERNEL_PROCURE_METHOD := $(DEFAULT_KERNEL_PROCURE_METHOD) +endif + +MAKEFLAGS += -j $(SONIC_BUILD_JOBS) +export SONIC_CONFIG_MAKE_JOBS + +############################################################################### +## Routing stack related exports +############################################################################### + +export SONIC_ROUTING_STACK +export FRR_USER_UID +export FRR_USER_GID + +############################################################################### +## Dumping key config attributes associated to current building exercise +############################################################################### + +$(info SONiC Build System) +$(info ) +$(info Build Configuration) +$(info "CONFIGURED_PLATFORM" : "$(if $(PLATFORM),$(PLATFORM),$(CONFIGURED_PLATFORM))") +$(info "SONIC_CONFIG_PRINT_DEPENDENCIES" : "$(SONIC_CONFIG_PRINT_DEPENDENCIES)") +$(info "SONIC_BUILD_JOBS" : "$(SONIC_BUILD_JOBS)") +$(info "SONIC_CONFIG_MAKE_JOBS" : "$(SONIC_CONFIG_MAKE_JOBS)") +$(info "USERNAME" : "$(USERNAME)") +$(info "PASSWORD" : "$(PASSWORD)") +$(info "ENABLE_DHCP_GRAPH_SERVICE" : "$(ENABLE_DHCP_GRAPH_SERVICE)") +$(info "SHUTDOWN_BGP_ON_START" : "$(SHUTDOWN_BGP_ON_START)") +$(info "ENABLE_PFCWD_ON_START" : "$(ENABLE_PFCWD_ON_START)") +$(info "INSTALL_DEBUG_TOOLS" : "$(INSTALL_DEBUG_TOOLS)") +$(info "ROUTING_STACK" : "$(SONIC_ROUTING_STACK)") +ifeq ($(SONIC_ROUTING_STACK),frr) +$(info "FRR_USER_UID" : "$(FRR_USER_UID)") +$(info "FRR_USER_GID" : "$(FRR_USER_GID)") +endif +$(info "ENABLE_SYNCD_RPC" : "$(ENABLE_SYNCD_RPC)") +$(info "ENABLE_ORGANIZATION_EXTENSIONS" : "$(ENABLE_ORGANIZATION_EXTENSIONS)") +$(info "HTTP_PROXY" : "$(HTTP_PROXY)") +$(info "HTTPS_PROXY" : "$(HTTPS_PROXY)") +$(info "ENABLE_SYSTEM_TELEMETRY" : "$(ENABLE_SYSTEM_TELEMETRY)") +$(info "SONIC_DEBUGGING_ON" : "$(SONIC_DEBUGGING_ON)") +$(info "SONIC_PROFILING_ON" : "$(SONIC_PROFILING_ON)") +$(info "KERNEL_PROCURE_METHOD" : "$(KERNEL_PROCURE_METHOD)") +$(info "BUILD_TIMESTAMP" : "$(BUILD_TIMESTAMP)") +$(info ) + +############################################################################### +## Generic rules section +## All rules must go after includes for propper targets expansion +############################################################################### + +export kernel_procure_method=$(KERNEL_PROCURE_METHOD) + +############################################################################### +## Local targets +############################################################################### + +# Copy debian packages from local directory +# Add new package for copy: +# SOME_NEW_DEB = some_new_deb.deb +# $(SOME_NEW_DEB)_PATH = path/to/some_new_deb.deb +# SONIC_COPY_DEBS += $(SOME_NEW_DEB) +$(addprefix $(DEBS_PATH)/, $(SONIC_COPY_DEBS)) : $(DEBS_PATH)/% : .platform + $(HEADER) + $(foreach deb,$* $($*_DERIVED_DEBS), \ + { cp $($(deb)_PATH)/$(deb) $(DEBS_PATH)/ $(LOG) || exit 1 ; } ; ) + $(FOOTER) + + +SONIC_TARGET_LIST += $(addprefix $(DEBS_PATH)/, $(SONIC_COPY_DEBS)) + +# Copy regular files from local directory +# Add new package for copy: +# SOME_NEW_FILE = some_new_file +# $(SOME_NEW_FILE)_PATH = path/to/some_new_file +# SONIC_COPY_FILES += $(SOME_NEW_FILE) +$(addprefix $(FILES_PATH)/, $(SONIC_COPY_FILES)) : $(FILES_PATH)/% : .platform + $(HEADER) + cp $($*_PATH)/$* $(FILES_PATH)/ $(LOG) || exit 1 + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(FILES_PATH)/, $(SONIC_COPY_FILES)) + +############################################################################### +## Online targets +############################################################################### + +# Download debian packages from online location +# Add new package for download: +# SOME_NEW_DEB = some_new_deb.deb +# $(SOME_NEW_DEB)_URL = https://url/to/this/deb.deb +# SONIC_ONLINE_DEBS += $(SOME_NEW_DEB) +$(addprefix $(DEBS_PATH)/, $(SONIC_ONLINE_DEBS)) : $(DEBS_PATH)/% : .platform + $(HEADER) + $(foreach deb,$* $($*_DERIVED_DEBS), \ + { wget --no-use-server-timestamps -O $(DEBS_PATH)/$(deb) $($(deb)_URL) $(LOG) || exit 1 ; } ; ) + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(DEBS_PATH)/, $(SONIC_ONLINE_DEBS)) + +# Download regular files from online location +# Files are stored in deb packages directory for convenience +# Add new file for download: +# SOME_NEW_FILE = some_new_file +# $(SOME_NEW_FILE)_URL = https://url/to/this/file +# SONIC_ONLINE_FILES += $(SOME_NEW_FILE) +$(addprefix $(FILES_PATH)/, $(SONIC_ONLINE_FILES)) : $(FILES_PATH)/% : .platform + $(HEADER) + wget --no-use-server-timestamps -O $@ $($*_URL) $(LOG) + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(FILES_PATH)/, $(SONIC_ONLINE_FILES)) + +############################################################################### +## Build targets +############################################################################### + +# Build project using build.sh script +# They are essentially a one-time build projects that get sources from some URL +# and compile them +# Add new file for build: +# SOME_NEW_FILE = some_new_deb.deb +# $(SOME_NEW_FILE)_SRC_PATH = $(SRC_PATH)/project_name +# $(SOME_NEW_FILE)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... +# SONIC_MAKE_FILES += $(SOME_NEW_FILE) +$(addprefix $(FILES_PATH)/, $(SONIC_MAKE_FILES)) : $(FILES_PATH)/% : .platform $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEPENDS))) + $(HEADER) + # Remove target to force rebuild + rm -f $(addprefix $(FILES_PATH)/, $*) + # Apply series of patches if exist + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && QUILT_PATCHES=../$(notdir $($*_SRC_PATH)).patch quilt push -a; popd; fi + # Build project and take package + make DEST=$(shell pwd)/$(FILES_PATH) -C $($*_SRC_PATH) $(shell pwd)/$(FILES_PATH)/$* $(LOG) + # Clean up + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && quilt pop -a -f; popd; fi + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(FILES_PATH)/, $(SONIC_MAKE_FILES)) + +############################################################################### +## Debian package related targets +############################################################################### + +# Build project using build.sh script +# They are essentially a one-time build projects that get sources from some URL +# and compile them +# Add new package for build: +# SOME_NEW_DEB = some_new_deb.deb +# $(SOME_NEW_DEB)_SRC_PATH = $(SRC_PATH)/project_name +# $(SOME_NEW_DEB)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... +# SONIC_MAKE_DEBS += $(SOME_NEW_DEB) +$(addprefix $(DEBS_PATH)/, $(SONIC_MAKE_DEBS)) : $(DEBS_PATH)/% : .platform $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEPENDS))) + $(HEADER) + # Remove target to force rebuild + rm -f $(addprefix $(DEBS_PATH)/, $* $($*_DERIVED_DEBS) $($*_EXTRA_DEBS)) + # Apply series of patches if exist + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && QUILT_PATCHES=../$(notdir $($*_SRC_PATH)).patch quilt push -a; popd; fi + # Build project and take package + DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC}" make DEST=$(shell pwd)/$(DEBS_PATH) -C $($*_SRC_PATH) $(shell pwd)/$(DEBS_PATH)/$* $(LOG) + # Clean up + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && quilt pop -a -f; popd; fi + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(DEBS_PATH)/, $(SONIC_MAKE_DEBS)) + +# Build project with dpkg-buildpackage +# Add new package for build: +# SOME_NEW_DEB = some_new_deb.deb +# $(SOME_NEW_DEB)_SRC_PATH = $(SRC_PATH)/project_name +# $(SOME_NEW_DEB)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... +# SONIC_DPKG_DEBS += $(SOME_NEW_DEB) +$(addprefix $(DEBS_PATH)/, $(SONIC_DPKG_DEBS)) : $(DEBS_PATH)/% : .platform $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEPENDS))) + $(HEADER) + # Remove old build logs if they exist + rm -f $($*_SRC_PATH)/debian/*.debhelper.log + # Apply series of patches if exist + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && QUILT_PATCHES=../$(notdir $($*_SRC_PATH)).patch quilt push -a; popd; fi + # Build project + pushd $($*_SRC_PATH) $(LOG) + [ ! -f ./autogen.sh ] || ./autogen.sh $(LOG) + $(if $($*_DPKG_TARGET), + DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC} ${$*_DEB_BUILD_OPTIONS}" dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --as-root -T$($*_DPKG_TARGET) $(LOG), + DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC} ${$*_DEB_BUILD_OPTIONS}" dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) $(LOG) + ) + popd $(LOG) + # Clean up + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && quilt pop -a -f; popd; fi + # Take built package(s) + mv $(addprefix $($*_SRC_PATH)/../, $* $($*_DERIVED_DEBS) $($*_EXTRA_DEBS)) $(DEBS_PATH) $(LOG) + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(DEBS_PATH)/, $(SONIC_DPKG_DEBS)) + +# Build project with python setup.py --command-packages=stdeb.command +# Add new package for build: +# SOME_NEW_DEB = some_new_deb.deb +# $(SOME_NEW_DEB)_SRC_PATH = $(SRC_PATH)/project_name +# $(SOME_NEW_DEB)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... +# SONIC_PYTHON_STDEB_DEBS += $(SOME_NEW_DEB) +$(addprefix $(DEBS_PATH)/, $(SONIC_PYTHON_STDEB_DEBS)) : $(DEBS_PATH)/% : .platform $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEPENDS))) \ + $$(addsuffix -install,$$(addprefix $(PYTHON_WHEELS_PATH)/,$$($$*_WHEEL_DEPENDS))) + $(HEADER) + # Apply series of patches if exist + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && QUILT_PATCHES=../$(notdir $($*_SRC_PATH)).patch quilt push -a; popd; fi + # Build project + pushd $($*_SRC_PATH) $(LOG) + rm -rf deb_dist/* $(LOG) + python setup.py --command-packages=stdeb.command bdist_deb $(LOG) + popd $(LOG) + # Clean up + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && quilt pop -a -f; popd; fi + # Take built package(s) + mv $(addprefix $($*_SRC_PATH)/deb_dist/, $* $($*_DERIVED_DEBS)) $(DEBS_PATH) $(LOG) + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(DEBS_PATH)/, $(SONIC_PYTHON_STDEB_DEBS)) + +# Rules for derived debian packages (dev, dbg, etc.) +# All noise takes place in main deb recipe, so we are just telling that +# we depend on it and move our deb to other targets +# Add new dev package: +# $(eval $(call add_derived_package,$(ORIGINAL_DEB),derived_deb_file.deb)) +$(addprefix $(DEBS_PATH)/, $(SONIC_DERIVED_DEBS)) : $(DEBS_PATH)/% : .platform $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEPENDS))) + $(HEADER) + # All noise takes place in main deb recipe, so we are just telling that + # we depend on it + # Put newer timestamp + [ -f $@ ] && touch $@ + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(DEBS_PATH)/, $(SONIC_DERIVED_DEBS)) + +# Rules for extra debian packages +# All noise takes place in main deb recipe, so we are just telling that +# we need to build the main deb and move our deb to other targets +# Add new dev package: +# $(eval $(call add_extra_package,$(ORIGINAL_DEB),extra_deb_file.deb)) +$(addprefix $(DEBS_PATH)/, $(SONIC_EXTRA_DEBS)) : $(DEBS_PATH)/% : .platform $$(addprefix $(DEBS_PATH)/,$$($$*_MAIN_DEB)) + $(HEADER) + # All noise takes place in main deb recipe, so we are just telling that + # we depend on it + # Put newer timestamp + [ -f $@ ] && touch $@ + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(DEBS_PATH)/, $(SONIC_EXTRA_DEBS)) + +# Targets for installing debian packages prior to build one that depends on them +SONIC_INSTALL_TARGETS = $(addsuffix -install,$(addprefix $(DEBS_PATH)/, \ + $(SONIC_ONLINE_DEBS) \ + $(SONIC_COPY_DEBS) \ + $(SONIC_MAKE_DEBS) \ + $(SONIC_DPKG_DEBS) \ + $(SONIC_PYTHON_STDEB_DEBS) \ + $(SONIC_DERIVED_DEBS) \ + $(SONIC_EXTRA_DEBS))) +$(SONIC_INSTALL_TARGETS) : $(DEBS_PATH)/%-install : .platform $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEPENDS))) $(DEBS_PATH)/$$* + $(HEADER) + [ -f $(DEBS_PATH)/$* ] || { echo $(DEBS_PATH)/$* does not exist $(LOG) && false $(LOG) } + # put a lock here because dpkg does not allow installing packages in parallel + while true; do + if mkdir $(DEBS_PATH)/dpkg_lock &> /dev/null; then + { sudo dpkg -i $(DEBS_PATH)/$* $(LOG) && rm -d $(DEBS_PATH)/dpkg_lock && break; } || { rm -d $(DEBS_PATH)/dpkg_lock && exit 1 ; } + fi + done + $(FOOTER) + +############################################################################### +## Python packages +############################################################################### + +# Build project using python setup.py bdist_wheel +# Projects that generate python wheels +# Add new package for build: +# SOME_NEW_WHL = some_new_whl.whl +# $(SOME_NEW_WHL)_SRC_PATH = $(SRC_PATH)/project_name +# $(SOME_NEW_WHL)_PYTHON_VERSION = 2 (or 3) +# $(SOME_NEW_WHL)_DEPENDS = $(SOME_OTHER_WHL1) $(SOME_OTHER_WHL2) ... +# SONIC_PYTHON_WHEELS += $(SOME_NEW_WHL) +$(addprefix $(PYTHON_WHEELS_PATH)/, $(SONIC_PYTHON_WHEELS)) : $(PYTHON_WHEELS_PATH)/% : .platform $$(addsuffix -install,$$(addprefix $(PYTHON_WHEELS_PATH)/,$$($$*_DEPENDS))) + $(HEADER) + pushd $($*_SRC_PATH) $(LOG) + # apply series of patches if exist + if [ -f ../$(notdir $($*_SRC_PATH)).patch/series ]; then QUILT_PATCHES=../$(notdir $($*_SRC_PATH)).patch quilt push -a; fi + [ "$($*_TEST)" = "n" ] || python$($*_PYTHON_VERSION) setup.py test $(LOG) + python$($*_PYTHON_VERSION) setup.py bdist_wheel $(LOG) + # clean up + if [ -f ../$(notdir $($*_SRC_PATH)).patch/series ]; then quilt pop -a -f; fi + popd $(LOG) + mv $($*_SRC_PATH)/dist/$* $(PYTHON_WHEELS_PATH) $(LOG) + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(PYTHON_WHEELS_PATH)/, $(SONIC_PYTHON_WHEELS)) + +# Targets for installing python wheels. +# Autogenerated +SONIC_INSTALL_WHEELS = $(addsuffix -install, $(addprefix $(PYTHON_WHEELS_PATH)/, $(SONIC_PYTHON_WHEELS))) +$(SONIC_INSTALL_WHEELS) : $(PYTHON_WHEELS_PATH)/%-install : .platform $$(addsuffix -install,$$(addprefix $(PYTHON_WHEELS_PATH)/,$$($$*_DEPENDS))) $(PYTHON_WHEELS_PATH)/$$* + $(HEADER) + [ -f $(PYTHON_WHEELS_PATH)/$* ] || { echo $(PYTHON_WHEELS_PATH)/$* does not exist $(LOG) && exit 1; } + # put a lock here to avoid race conditions + while true; do + if mkdir $(PYTHON_WHEELS_PATH)/pip_lock &> /dev/null; then + { sudo -E pip$($*_PYTHON_VERSION) install $(PYTHON_WHEELS_PATH)/$* $(LOG) && rm -d $(PYTHON_WHEELS_PATH)/pip_lock && break; } || { rm -d $(PYTHON_WHEELS_PATH)/pip_lock && exit 1 ; } + fi + done + $(FOOTER) + +############################################################################### +## Docker images related targets +############################################################################### + +# start docker daemon +docker-start : + @sudo sed -i '/http_proxy/d' /etc/default/docker + @sudo bash -c "echo \"export http_proxy=$$http_proxy\" >> /etc/default/docker" + @test x$(SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD) != x"y" && sudo service docker status &> /dev/null || ( sudo service docker start &> /dev/null && sleep 1 ) + +# targets for building simple docker images that do not depend on any debian packages +$(addprefix $(TARGET_PATH)/, $(SONIC_SIMPLE_DOCKER_IMAGES)) : $(TARGET_PATH)/%.gz : .platform docker-start $$(addsuffix -load,$$(addprefix $(TARGET_PATH)/,$$($$*.gz_LOAD_DOCKERS))) + $(HEADER) + # Apply series of patches if exist + if [ -f $($*.gz_PATH).patch/series ]; then pushd $($*.gz_PATH) && QUILT_PATCHES=../$(notdir $($*.gz_PATH)).patch quilt push -a; popd; fi + docker info $(LOG) + docker build --squash --no-cache \ + --build-arg http_proxy=$(HTTP_PROXY) \ + --build-arg https_proxy=$(HTTPS_PROXY) \ + --build-arg user=$(USER) \ + --build-arg uid=$(UID) \ + --build-arg guid=$(GUID) \ + --build-arg docker_container_name=$($*.gz_CONTAINER_NAME) \ + --label Tag=$(SONIC_GET_VERSION) \ + -t $* $($*.gz_PATH) $(LOG) + docker save $* | gzip -c > $@ + # Clean up + if [ -f $($*.gz_PATH).patch/series ]; then pushd $($*.gz_PATH) && quilt pop -a -f; popd; fi + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(TARGET_PATH)/, $(SONIC_SIMPLE_DOCKER_IMAGES)) + +# Targets for building docker images +$(addprefix $(TARGET_PATH)/, $(SONIC_DOCKER_IMAGES)) : $(TARGET_PATH)/%.gz : .platform docker-start $$(addprefix $(DEBS_PATH)/,$$($$*.gz_DEPENDS)) $$(addprefix $(FILES_PATH)/,$$($$*.gz_FILES)) $$(addprefix $(PYTHON_WHEELS_PATH)/,$$($$*.gz_PYTHON_WHEELS)) $$(addsuffix -load,$$(addprefix $(TARGET_PATH)/,$$($$*.gz_LOAD_DOCKERS))) $$($$*.gz_PATH)/Dockerfile.j2 + $(HEADER) + # Apply series of patches if exist + if [ -f $($*.gz_PATH).patch/series ]; then pushd $($*.gz_PATH) && QUILT_PATCHES=../$(notdir $($*.gz_PATH)).patch quilt push -a; popd; fi + mkdir -p $($*.gz_PATH)/debs $(LOG) + mkdir -p $($*.gz_PATH)/files $(LOG) + mkdir -p $($*.gz_PATH)/python-wheels $(LOG) + sudo mount --bind $(DEBS_PATH) $($*.gz_PATH)/debs $(LOG) + sudo mount --bind $(FILES_PATH) $($*.gz_PATH)/files $(LOG) + sudo mount --bind $(PYTHON_WHEELS_PATH) $($*.gz_PATH)/python-wheels $(LOG) + # Export variables for j2. Use path for unique variable names, e.g. docker_orchagent_debs + $(eval export $(subst -,_,$(notdir $($*.gz_PATH)))_debs=$(shell printf "$(subst $(SPACE),\n,$(call expand,$($*.gz_DEPENDS),RDEPENDS))\n" | awk '!a[$$0]++')) + $(eval export $(subst -,_,$(notdir $($*.gz_PATH)))_whls=$(shell printf "$(subst $(SPACE),\n,$(call expand,$($*.gz_PYTHON_WHEELS)))\n" | awk '!a[$$0]++')) + $(eval export $(subst -,_,$(notdir $($*.gz_PATH)))_dbgs=$(shell printf "$(subst $(SPACE),\n,$(call expand,$($*.gz_DBG_PACKAGES)))\n" | awk '!a[$$0]++')) + j2 $($*.gz_PATH)/Dockerfile.j2 > $($*.gz_PATH)/Dockerfile + docker info $(LOG) + docker build --squash --no-cache \ + --build-arg http_proxy=$(HTTP_PROXY) \ + --build-arg https_proxy=$(HTTPS_PROXY) \ + --build-arg user=$(USER) \ + --build-arg uid=$(UID) \ + --build-arg guid=$(GUID) \ + --build-arg docker_container_name=$($*.gz_CONTAINER_NAME) \ + --build-arg frr_user_uid=$(FRR_USER_UID) \ + --build-arg frr_user_gid=$(FRR_USER_GID) \ + --label Tag=$(SONIC_GET_VERSION) \ + -t $* $($*.gz_PATH) $(LOG) + docker save $* | gzip -c > $@ + # Clean up + if [ -f $($*.gz_PATH).patch/series ]; then pushd $($*.gz_PATH) && quilt pop -a -f; popd; fi + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(TARGET_PATH)/, $(SONIC_DOCKER_IMAGES)) + +DOCKER_LOAD_TARGETS = $(addsuffix -load,$(addprefix $(TARGET_PATH)/, \ + $(SONIC_SIMPLE_DOCKER_IMAGES) \ + $(SONIC_DOCKER_IMAGES))) +$(DOCKER_LOAD_TARGETS) : $(TARGET_PATH)/%.gz-load : .platform docker-start $$(TARGET_PATH)/$$*.gz + $(HEADER) + docker load -i $(TARGET_PATH)/$*.gz $(LOG) + $(FOOTER) + +############################################################################### +## Installers +############################################################################### + +# targets for building installers with base image +$(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ + .platform \ + onie-image.conf \ + build_debian.sh \ + build_image.sh \ + $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEPENDS))) \ + $$(addprefix $(DEBS_PATH)/,$$($$*_INSTALLS)) \ + $$(addprefix $(DEBS_PATH)/,$$($$*_LAZY_INSTALLS)) \ + $$(addprefix $(FILES_PATH)/,$$($$*_FILES)) \ + $(addprefix $(FILES_PATH)/,$(IXGBE_DRIVER)) \ + $(addprefix $(DEBS_PATH)/,$(INITRAMFS_TOOLS) \ + $(LINUX_KERNEL) \ + $(SONIC_DEVICE_DATA) \ + $(PYTHON_CLICK) \ + $(SONIC_UTILS) \ + $(BASH) \ + $(LIBPAM_TACPLUS) \ + $(LIBNSS_TACPLUS)) \ + $$(addprefix $(TARGET_PATH)/,$$($$*_DOCKERS)) \ + $$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_CONFIG_ENGINE)) \ + $$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_COMMON_PY2)) \ + $$(addprefix $(PYTHON_WHEELS_PATH)/,$(REDIS_DUMP_LOAD_PY2)) + $(HEADER) + # Pass initramfs and linux kernel explicitly. They are used for all platforms + export initramfs_tools="$(DEBS_PATH)/$(INITRAMFS_TOOLS)" + export linux_kernel="$(DEBS_PATH)/$(LINUX_KERNEL)" + export onie_recovery_image="$(FILES_PATH)/$(ONIE_RECOVERY_IMAGE)" + export kversion="$(KVERSION)" + export image_type="$($*_IMAGE_TYPE)" + export sonicadmin_user="$(USERNAME)" + export sonic_asic_platform="$(CONFIGURED_PLATFORM)" + export enable_organization_extensions="$(ENABLE_ORGANIZATION_EXTENSIONS)" + export enable_dhcp_graph_service="$(ENABLE_DHCP_GRAPH_SERVICE)" + export shutdown_bgp_on_start="$(SHUTDOWN_BGP_ON_START)" + export enable_pfcwd_on_start="$(ENABLE_PFCWD_ON_START)" + export installer_debs="$(addprefix $(DEBS_PATH)/,$($*_INSTALLS))" + export lazy_installer_debs="$(foreach deb, $($*_LAZY_INSTALLS),$(foreach device, $($(deb)_PLATFORM),$(addprefix $(device)@, $(DEBS_PATH)/$(deb))))" + export installer_images="$(addprefix $(TARGET_PATH)/,$($*_DOCKERS))" + export config_engine_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_CONFIG_ENGINE))" + export swsssdk_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SWSSSDK_PY2))" + export platform_common_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_COMMON_PY2))" + export redis_dump_load_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(REDIS_DUMP_LOAD_PY2))" + + $(foreach docker, $($*_DOCKERS),\ + export docker_image="$(docker)" + export docker_image_name="$(basename $(docker))" + export docker_container_name="$($(docker)_CONTAINER_NAME)" + $(eval $(docker)_RUN_OPT += $($(docker)_$($*_IMAGE_TYPE)_RUN_OPT)) + export docker_image_run_opt="$($(docker)_RUN_OPT)" + j2 files/build_templates/docker_image_ctl.j2 > $($(docker)_CONTAINER_NAME).sh + if [ -f files/build_templates/$($(docker)_CONTAINER_NAME).service.j2 ]; then + j2 files/build_templates/$($(docker)_CONTAINER_NAME).service.j2 > $($(docker)_CONTAINER_NAME).service + fi + chmod +x $($(docker)_CONTAINER_NAME).sh + ) + + export installer_start_scripts="$(foreach docker, $($*_DOCKERS),$(addsuffix .sh, $($(docker)_CONTAINER_NAME)))" + export installer_services="$(foreach docker, $($*_DOCKERS),$(addsuffix .service, $($(docker)_CONTAINER_NAME)))" + export installer_extra_files="$(foreach docker, $($*_DOCKERS), $(foreach file, $($(docker)_BASE_IMAGE_FILES), $($(docker)_PATH)/base_image_files/$(file)))" + + j2 -f env files/initramfs-tools/union-mount.j2 onie-image.conf > files/initramfs-tools/union-mount + j2 -f env files/initramfs-tools/arista-convertfs.j2 onie-image.conf > files/initramfs-tools/arista-convertfs + + j2 files/build_templates/updategraph.service.j2 > updategraph.service + + $(if $($*_DOCKERS), + j2 files/build_templates/sonic_debian_extension.j2 > sonic_debian_extension.sh + chmod +x sonic_debian_extension.sh, + ) + + USERNAME="$(USERNAME)" \ + PASSWORD="$(PASSWORD)" \ + ./build_debian.sh $(LOG) + + USERNAME="$(USERNAME)" \ + PASSWORD="$(PASSWORD)" \ + TARGET_MACHINE=$($*_MACHINE) \ + IMAGE_TYPE=$($*_IMAGE_TYPE) \ + ./build_image.sh $(LOG) + + $(foreach docker, $($*_DOCKERS), \ + rm -f $($(docker)_CONTAINER_NAME).sh + rm -f $($(docker)_CONTAINER_NAME).service + ) + + $(if $($*_DOCKERS), + rm sonic_debian_extension.sh, + ) + + chmod a+x $@ + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) + +############################################################################### +## Clean targets +############################################################################### + +SONIC_CLEAN_DEBS = $(addsuffix -clean,$(addprefix $(DEBS_PATH)/, \ + $(SONIC_ONLINE_DEBS) \ + $(SONIC_COPY_DEBS) \ + $(SONIC_MAKE_DEBS) \ + $(SONIC_DPKG_DEBS) \ + $(SONIC_PYTHON_STDEB_DEBS) \ + $(SONIC_DERIVED_DEBS) \ + $(SONIC_EXTRA_DEBS))) + +SONIC_CLEAN_FILES = $(addsuffix -clean,$(addprefix $(FILES_PATH)/, \ + $(SONIC_ONLINE_FILES) \ + $(SONIC_COPY_FILES) \ + $(SONIC_MAKE_FILES))) + +$(SONIC_CLEAN_DEBS) : $(DEBS_PATH)/%-clean : .platform $$(addsuffix -clean,$$(addprefix $(DEBS_PATH)/,$$($$*_MAIN_DEB))) + @# remove derived or extra targets if main one is removed, because we treat them + @# as part of one package + @rm -f $(addprefix $(DEBS_PATH)/, $* $($*_DERIVED_DEBS) $($*_EXTRA_DEBS)) + +$(SONIC_CLEAN_FILES) : $(FILES_PATH)/%-clean : .platform + @rm -f $(FILES_PATH)/$* + +SONIC_CLEAN_TARGETS += $(addsuffix -clean,$(addprefix $(TARGET_PATH)/, \ + $(SONIC_DOCKER_IMAGES) \ + $(SONIC_SIMPLE_DOCKER_IMAGES) \ + $(SONIC_INSTALLERS))) +$(SONIC_CLEAN_TARGETS) : $(TARGET_PATH)/%-clean : .platform + @rm -f $(TARGET_PATH)/$* + +SONIC_CLEAN_WHEELS = $(addsuffix -clean,$(addprefix $(PYTHON_WHEELS_PATH)/, \ + $(SONIC_PYTHON_WHEELS))) +$(SONIC_CLEAN_WHEELS) : $(PYTHON_WHEELS_PATH)/%-clean : .platform + @rm -f $(PYTHON_WHEELS_PATH)/$* + +clean-logs : .platform + @rm -f $(TARGET_PATH)/*.log $(DEBS_PATH)/*.log $(FILES_PATH)/*.log $(PYTHON_WHEELS_PATH)/*.log + +clean : .platform clean-logs $$(SONIC_CLEAN_DEBS) $$(SONIC_CLEAN_FILES) $$(SONIC_CLEAN_TARGETS) $$(SONIC_CLEAN_WHEELS) + +############################################################################### +## all +############################################################################### + +all : .platform $$(addprefix $(TARGET_PATH)/,$$(SONIC_ALL)) + +stretch : $$(addprefix $(DEBS_PATH)/,$$(SONIC_STRETCH_DEBS)) \ + $$(addprefix $(FILES_PATH)/,$$(SONIC_STRETCH_FILES)) + + +############################################################################### +## Standard targets +############################################################################### + +.PHONY : $(SONIC_CLEAN_DEBS) $(SONIC_CLEAN_FILES) $(SONIC_CLEAN_TARGETS) $(SONIC_CLEAN_WHEELS) $(SONIC_PHONY_TARGETS) clean distclean configure + +.INTERMEDIATE : $(SONIC_INSTALL_TARGETS) $(SONIC_INSTALL_WHEELS) $(DOCKER_LOAD_TARGETS) docker-start .platform diff --git a/sonic-slave-stretch/Dockerfile b/sonic-slave-stretch/Dockerfile new file mode 100644 index 000000000000..eeac24ae8475 --- /dev/null +++ b/sonic-slave-stretch/Dockerfile @@ -0,0 +1,258 @@ +FROM debian:stretch + +MAINTAINER gulv@microsoft.com + +RUN echo "deb http://debian-archive.trafficmanager.net/debian/ stretch main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src http://debian-archive.trafficmanager.net/debian/ stretch main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb http://debian-archive.trafficmanager.net/debian-security/ stretch/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src http://debian-archive.trafficmanager.net/debian-security/ stretch/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb http://debian-archive.trafficmanager.net/debian stretch-backports main" >> /etc/apt/sources.list + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y \ + apt-utils \ + default-jre-headless \ + openssh-server \ + curl \ + wget \ + unzip \ + git \ + build-essential \ + libtool \ + lintian \ + sudo \ + dh-make \ + dh-exec \ + kmod \ + libtinyxml2-4 \ + libboost-program-options1.62-dev \ + libtinyxml2-dev \ + python \ + python-pip \ + libncurses5-dev \ + texinfo \ + dh-autoreconf \ + python3-pip \ + doxygen \ + devscripts \ + git-buildpackage \ + perl-modules \ + libswitch-perl \ + dh-systemd \ +# For quagga build + libreadline-dev \ + texlive-latex-base \ + texlive-generic-recommended \ + texlive-fonts-recommended \ + libpam0g-dev \ + libpam-dev \ + libcap-dev \ + imagemagick \ + ghostscript \ + groff \ + libpcre3-dev \ + gawk \ + chrpath \ +# For frr build + libc-ares-dev \ + libsnmp-dev \ + libjson-c3 \ + libjson-c-dev \ + libsystemd-dev \ + python-ipaddr \ +# For libnl3 (local) build + cdbs \ +# For SAI meta build + libxml-simple-perl \ + graphviz \ + aspell \ +# For linux build + bc \ + fakeroot \ + build-essential \ + devscripts \ + quilt \ + stgit \ +# For platform-modules build + module-assistant \ +# For thrift build\ + gem2deb \ + libboost-all-dev \ + libevent-dev \ + libglib2.0-dev \ + libqt4-dev \ + python-all-dev \ + python-twisted \ + phpunit \ + libbit-vector-perl \ + openjdk-8-jdk \ + javahelper \ + maven-debian-helper \ + ant \ + libmaven-ant-tasks-java \ + libhttpclient-java \ + libslf4j-java \ + libservlet3.1-java \ + qt5-default \ +# For mellanox sdk build + libpcre3 \ + libpcre3-dev \ + byacc \ + flex \ + libglib2.0-dev \ + bison \ + expat \ + libexpat1-dev \ + dpatch \ + libdb-dev \ + iptables-dev \ + swig \ +# For mellanox sai build + libtool-bin \ + libxml2-dev \ +# For build image + cpio \ + squashfs-tools \ + zip \ +# For broadcom sdk build + linux-compiler-gcc-6-x86 \ + linux-kbuild-4.9 \ +# teamd build + libdaemon-dev \ + libdbus-1-dev \ + libjansson-dev \ +# For cavium sdk build + libpcap-dev \ + dnsutils \ + libusb-dev \ +# For debian image reconfiguration + augeas-tools \ +# For p4 build + libyaml-dev \ + libevent-dev \ + libjudy-dev \ + libedit-dev \ + libnanomsg-dev \ + python-stdeb \ +# For redis build + libjemalloc-dev \ +# For mft kernel module build + dkms \ +# For python3.5 build + sharutils \ + libncursesw5-dev \ + libbz2-dev \ + liblzma-dev \ + libgdbm-dev \ + tk-dev \ + blt-dev \ + libmpdec-dev \ + libbluetooth-dev \ + locales \ + libsqlite3-dev \ + libgpm2 \ + time \ + net-tools \ + xvfb \ + python-sphinx \ + python3-sphinx \ +# For Jenkins static analysis, unit testing and code coverage + cppcheck \ + clang \ + pylint \ + python-pytest \ + gcovr \ + python-pytest-cov \ + python-parse \ +# For snmpd + default-libmysqlclient-dev \ + libssl-dev \ + libperl-dev \ + libpci-dev \ + libpci3 \ + libsensors4 \ + libsensors4-dev \ + libwrap0-dev \ +# For mpdecimal + docutils-common \ + libjs-sphinxdoc \ + libjs-underscore \ + python-docutils \ + python-jinja2 \ + python-markupsafe \ + python-pygments \ + python-roman \ + python-sphinx \ + sphinx-common \ + python3-sphinx \ +# For sonic config engine testing + python-lxml \ + python-jinja2 \ + python-netaddr \ + python-ipaddr \ + python-yaml \ + python3-yaml \ +# For lockfile + procmail \ +# For gtest + libgtest-dev \ + cmake \ +# For pam_tacplus build + autoconf-archive \ +# For initramfs + bash-completion + +# For linux build +RUN apt-get -y build-dep linux + +# For gobgp build +RUN export VERSION=1.8.3 \ + && wget https://storage.googleapis.com/golang/go$VERSION.linux-amd64.tar.gz \ + && tar -C /usr/local -xzf go$VERSION.linux-amd64.tar.gz \ + && echo 'export GOROOT=/usr/local/go' >> /etc/bash.bashrc \ + && echo 'export PATH=$PATH:$GOROOT/bin' >> /etc/bash.bashrc + +# For p4 build +RUN pip install \ + ctypesgen \ + crc16 + +# For templating +RUN pip install j2cli + +# For sonic config engine testing +RUN pip install pyangbind==0.5.10 + +# For supervisor build +RUN pip install meld3 mock + +# Install dependencies for isc-dhcp-relay build +RUN apt-get -y build-dep isc-dhcp + +RUN cd /usr/src/gtest && cmake . && make -C /usr/src/gtest + +RUN mkdir /var/run/sshd +EXPOSE 22 + +# Install depot-tools (for git-retry) +RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git /usr/share/depot_tools +ENV PATH /usr/share/depot_tools:$PATH + +# Install docker engine 17.03.2~ce-0 inside docker and enable experimental feature +RUN apt-get update +RUN apt-get install -y \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg2 \ + software-properties-common +RUN curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - +RUN add-apt-repository \ + "deb [arch=amd64] https://download.docker.com/linux/debian \ + $(lsb_release -cs) \ + stable" +RUN apt-get update +RUN apt-get install -y docker-ce=17.03.2~ce-0~debian-stretch +RUN echo "DOCKER_OPTS=\"--experimental\"" >> /etc/default/docker diff --git a/sonic-slave-stretch/Dockerfile.user b/sonic-slave-stretch/Dockerfile.user new file mode 100644 index 000000000000..0b44faaf4a53 --- /dev/null +++ b/sonic-slave-stretch/Dockerfile.user @@ -0,0 +1,29 @@ +FROM sonic-slave-stretch-base + +# Add user +ARG user +ARG uid +ARG guid +ARG hostname + +ENV BUILD_HOSTNAME $hostname +ENV USER $user + +RUN groupadd -f -r -g $guid g$user + +RUN useradd $user -l -u $uid -g $guid -d /var/$user -m -s /bin/bash + +RUN gpasswd -a $user docker + +# Config git for stg +RUN su $user -c "git config --global user.name $user" +RUN su $user -c "git config --global user.email $user@contoso.com" + +COPY sonic-jenkins-id_rsa.pub /var/$user/.ssh/authorized_keys2 +RUN chown $user /var/$user/.ssh -R +RUN chmod go= /var/$user/.ssh -R + +# Add user to sudoers +RUN echo "$user ALL=(ALL) NOPASSWD:ALL" >>/etc/sudoers + +USER $user diff --git a/sonic-slave-stretch/sonic-jenkins-id_rsa.pub b/sonic-slave-stretch/sonic-jenkins-id_rsa.pub new file mode 100644 index 000000000000..2a19c9e70d3c --- /dev/null +++ b/sonic-slave-stretch/sonic-jenkins-id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC769BQUJVeSIOyPsN4/Vo8xTqXQ6RI7ysVyCw/ABP3FIxf+fxmtm8t/Nbp9hq0uLHOjCw8UQbJ+XltsThFWJfH6RJY5NbfvwG7nUDjfjjp+SGEIHaVgIlpiuqiPbZ6QMjZ8Q0Sgi5p5ts1xe/4TFThwOJBHmhwydD5nk3BH7P3DDwlOCov5gjM40uMZJkketlO83zGG+25zu7O0hfDVt1vyK9bNWAhhPmGc79zdetfeFCxjimsff2m31B1KuVXiT5PDB1w+BSrUK6nNzJubnYCRgjg4prVTjA50EhlT2P7EoJAbW3TnTq8vUDkcstsGe/HZpfIB1VHBX97u4fAfGJZ root@acs-jenkins diff --git a/sonic-slave/Dockerfile b/sonic-slave/Dockerfile new file mode 100644 index 000000000000..3fd4633d04aa --- /dev/null +++ b/sonic-slave/Dockerfile @@ -0,0 +1,322 @@ +FROM debian:jessie + +MAINTAINER johnar@microsoft.com + +RUN echo "deb http://debian-archive.trafficmanager.net/debian/ jessie main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src http://debian-archive.trafficmanager.net/debian/ jessie main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb http://debian-archive.trafficmanager.net/debian-security/ jessie/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src http://debian-archive.trafficmanager.net/debian-security/ jessie/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb http://debian-archive.trafficmanager.net/debian/ jessie-backports main contrib non-free" >> /etc/apt/sources.list + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y \ + apt-utils \ + default-jre-headless \ + openssh-server \ + curl \ + wget \ + unzip \ + git \ + build-essential \ + libtool \ + lintian \ + sudo \ + dh-make \ + dh-exec \ + kmod \ + libtinyxml2-2 \ + libboost-program-options1.55-dev \ + libtinyxml2-dev \ + python \ + python-pip \ + libncurses5-dev \ + texinfo \ + dh-autoreconf \ + python3-pip \ + doxygen \ + devscripts \ + git-buildpackage \ + perl-modules \ + libswitch-perl \ + dh-systemd \ +# For quagga build + libreadline-dev \ + texlive-latex-base \ + texlive-generic-recommended \ + texlive-fonts-recommended \ + libpam0g-dev \ + libpam-dev \ + libcap-dev \ + imagemagick \ + ghostscript \ + groff \ + libpcre3-dev \ + gawk \ + chrpath \ +# For frr build + libc-ares-dev \ + hardening-wrapper \ + libsnmp-dev \ + libjson0 \ + libjson0-dev \ + libsystemd-dev \ + python-ipaddr \ + install-info \ +# For libnl3 (local) build + cdbs \ +# For SAI meta build + libxml-simple-perl \ + graphviz \ + aspell \ +# For linux build + bc \ + fakeroot \ + build-essential \ + devscripts \ + quilt \ + stgit \ +# For platform-modules build + module-assistant \ +# For thrift build\ + gem2deb \ + libboost-all-dev \ + libevent-dev \ + libglib2.0-dev \ + libqt4-dev \ + python-all-dev \ + python-twisted \ + php5-dev \ + phpunit \ + libbit-vector-perl \ + openjdk-7-jdk \ + javahelper \ + maven-debian-helper \ + ant \ + libmaven-ant-tasks-java \ + libhttpclient-java \ + libslf4j-java \ + libservlet3.1-java \ + qt5-default \ +# For mellanox sdk build + libpcre3 \ + libpcre3-dev \ + byacc \ + flex \ + libglib2.0-dev \ + bison \ + expat \ + libexpat1-dev \ + dpatch \ + libdb-dev \ + iptables-dev \ + swig \ +# For mellanox sai build + libtool-bin \ + libxml2-dev \ +# For BFN sdk build + libusb-1.0-0-dev \ + libcurl3-nss-dev \ + libunwind8-dev \ + telnet \ +# For build image + cpio \ + squashfs-tools \ + zip \ +# For broadcom sdk build + linux-compiler-gcc-4.8-x86 \ + linux-kbuild-3.16 \ +# teamd build + libdaemon-dev \ + libdbus-1-dev \ + libjansson-dev \ +# For cavium sdk build + libpcap-dev \ + dnsutils \ + libusb-dev \ +# For debian image reconfiguration + augeas-tools \ +# For p4 build + libyaml-dev \ + libevent-dev \ + libjudy-dev \ + libedit-dev \ + libnanomsg-dev \ + python-stdeb \ +# For redis build + libjemalloc-dev \ +# For mft kernel module build + dkms \ +# For python3.5 build + sharutils \ + libncursesw5-dev \ + libbz2-dev \ + liblzma-dev \ + libgdbm-dev \ + tk-dev \ + blt-dev \ + libmpdec-dev \ + libbluetooth-dev \ + locales \ + libsqlite3-dev \ + libgpm2 \ + time \ + net-tools \ + xvfb \ + python-sphinx \ + python3-sphinx \ +# For Jenkins static analysis, unit testing and code coverage + cppcheck \ + clang \ + pylint \ + gcovr \ + python-pytest=2.6.3* \ + python3-pytest=2.6.3* \ + python-pytest-cov \ + python3-pytest-cov \ + python-parse \ +# For snmpd + libmysqlclient-dev \ + libmysqld-dev \ + libperl-dev \ + libpci-dev \ + libpci3 \ + libsensors4 \ + libsensors4-dev \ + libwrap0-dev \ +# For mpdecimal + docutils-common \ + libjs-sphinxdoc \ + libjs-underscore \ + python-docutils \ + python-markupsafe \ + python-pygments \ + python-roman \ + sphinx-common \ +# For sonic config engine testing + python-lxml \ + python-netaddr \ + python-ipaddr \ + python-yaml \ +# For lockfile + procmail \ +# For gtest + libgtest-dev \ + cmake \ +# For pam_tacplus build + autoconf-archive \ +# For python-based swsscommon + swig3.0 \ +# For iproute2 + cm-super-minimal \ + libatm1-dev \ + libelf-dev \ + libmnl-dev \ + libselinux1-dev \ + linuxdoc-tools \ + lynx \ + texlive-latex-extra \ + texlive-latex-recommended \ +# For python-click build + python-sphinx \ + python-docutils \ + python3-all \ + python3-setuptools \ + python3-sphinx \ + python3-docutils \ + python3-requests \ + python3-pytest \ + python3-colorama \ +# For bash + texi2html \ +# For initramfs + bash-completion \ +# For Mellanox CRIU build + libprotobuf-dev \ + libprotobuf-c0-dev \ + protobuf-c-compiler \ + protobuf-compiler \ + python-protobuf \ + pkg-config \ + libnet1-dev \ + libnet-dev \ + libaio-dev \ + asciidoc \ + xmlto \ + checkinstall \ +# For sonic vs image build + dosfstools \ + qemu-kvm \ + libvirt-bin + +# For linux build +RUN apt-get -y build-dep linux + +# For gobgp build +RUN export VERSION=1.11.2 \ + && wget https://storage.googleapis.com/golang/go$VERSION.linux-amd64.tar.gz \ + && tar -C /usr/local -xzf go$VERSION.linux-amd64.tar.gz \ + && echo 'export GOROOT=/usr/local/go' >> /etc/bash.bashrc \ + && echo 'export PATH=$PATH:$GOROOT/bin' >> /etc/bash.bashrc + +# Upgrade pip2 +# Note: use pip2 specific version so jinja2 2.10 will install +RUN python2 -m pip install -U pip==9.0.3 + +# For p4 build +RUN pip install \ + ctypesgen \ + crc16 + +# For sonic config engine testing +RUN pip install pyangbind==0.6.0 +# Note: force upgrade debian packaged jinja2, if installed +RUN pip install --force-reinstall --upgrade jinja2>=2.10 + +# For templating (requiring jinja2) +RUN pip install j2cli + +# For sonic utilities testing +RUN pip install click-default-group click natsort tabulate + +# For supervisor build +RUN pip install meld3 mock + +# For vs image build +RUN pip install pexpect==4.6.0 + +# Install dependencies for isc-dhcp-relay build +RUN apt-get -y build-dep isc-dhcp + +# Install vim +RUN apt-get install -y vim + +# Install rsyslog +RUN apt-get install -y rsyslog + +RUN cd /usr/src/gtest && cmake . && make -C /usr/src/gtest + +RUN mkdir /var/run/sshd +EXPOSE 22 + +# Install depot-tools (for git-retry) +RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git /usr/share/depot_tools +ENV PATH /usr/share/depot_tools:$PATH + +# Install docker engine 17.03.2~ce-0 inside docker and enable experimental feature +RUN apt-get update +RUN apt-get install -y \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg2 \ + software-properties-common +RUN curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - +RUN add-apt-repository \ + "deb [arch=amd64] https://download.docker.com/linux/debian \ + $(lsb_release -cs) \ + stable" +RUN apt-get update +RUN apt-get install -y docker-ce=17.03.2~ce-0~debian-jessie +RUN echo "DOCKER_OPTS=\"--experimental --storage-driver=vfs\"" >> /etc/default/docker diff --git a/sonic-slave/Dockerfile.user b/sonic-slave/Dockerfile.user new file mode 100644 index 000000000000..ff01f88a769c --- /dev/null +++ b/sonic-slave/Dockerfile.user @@ -0,0 +1,29 @@ +FROM sonic-slave-base + +# Add user +ARG user +ARG uid +ARG guid +ARG hostname + +ENV BUILD_HOSTNAME $hostname +ENV USER $user + +RUN groupadd -f -r -g $guid g$user + +RUN useradd $user -l -u $uid -g $guid -d /var/$user -m -s /bin/bash + +RUN gpasswd -a $user docker + +# Config git for stg +RUN su $user -c "git config --global user.name $user" +RUN su $user -c "git config --global user.email $user@contoso.com" + +COPY sonic-jenkins-id_rsa.pub /var/$user/.ssh/authorized_keys2 +RUN chown $user /var/$user/.ssh -R +RUN chmod go= /var/$user/.ssh -R + +# Add user to sudoers +RUN echo "$user ALL=(ALL) NOPASSWD:ALL" >>/etc/sudoers + +USER $user diff --git a/sonic-slave/sonic-jenkins-id_rsa.pub b/sonic-slave/sonic-jenkins-id_rsa.pub new file mode 100644 index 000000000000..2a19c9e70d3c --- /dev/null +++ b/sonic-slave/sonic-jenkins-id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC769BQUJVeSIOyPsN4/Vo8xTqXQ6RI7ysVyCw/ABP3FIxf+fxmtm8t/Nbp9hq0uLHOjCw8UQbJ+XltsThFWJfH6RJY5NbfvwG7nUDjfjjp+SGEIHaVgIlpiuqiPbZ6QMjZ8Q0Sgi5p5ts1xe/4TFThwOJBHmhwydD5nk3BH7P3DDwlOCov5gjM40uMZJkketlO83zGG+25zu7O0hfDVt1vyK9bNWAhhPmGc79zdetfeFCxjimsff2m31B1KuVXiT5PDB1w+BSrUK6nNzJubnYCRgjg4prVTjA50EhlT2P7EoJAbW3TnTq8vUDkcstsGe/HZpfIB1VHBX97u4fAfGJZ root@acs-jenkins diff --git a/src/bash/Makefile b/src/bash/Makefile new file mode 100644 index 000000000000..2e9f093aedb4 --- /dev/null +++ b/src/bash/Makefile @@ -0,0 +1,16 @@ +SHELL = /bin/bash +.ONESHELL: +.SHELLFLAGS += -e + +MAIN_TARGET = bash_$(BASH_VERSION_FULL)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf bash-$(BASH_VERSION_MAJOR) + + dget -u https://launchpad.net/debian/+archive/primary/+sourcefiles/bash/$(BASH_VERSION_FULL)/bash_$(BASH_VERSION_FULL).dsc + + pushd bash-$(BASH_VERSION_MAJOR) + DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + mv $* $(DEST)/ diff --git a/src/gobgp/Makefile b/src/gobgp/Makefile new file mode 100644 index 000000000000..4fda21013afb --- /dev/null +++ b/src/gobgp/Makefile @@ -0,0 +1,23 @@ +export GOPATH=/tmp/go + +INSTALL := /usr/bin/install + +all: gobgp gobgpd + +gobgpd: + /usr/local/go/bin/go get -v github.com/osrg/gobgp/cmd/gobgpd + +gobgp: + /usr/local/go/bin/go get -v github.com/osrg/gobgp/cmd/gobgp + +install: + $(INSTALL) -D ${GOPATH}/bin/gobgp $(DESTDIR)/usr/bin/gobgp + $(INSTALL) -D ${GOPATH}/bin/gobgpd $(DESTDIR)/usr/sbin/gobgpd + $(INSTALL) -D gobgpd.conf.sample $(DESTDIR)/etc/gobgp/gobgpd.conf.sample + +deinstall: + rm $(DESTDIR)/usr/bin/gobgp + rm $(DESTDIR)/usr/sbin/gobgpd + +clean: + rm -fr ${GOPATH} diff --git a/src/gobgp/debian/changelog b/src/gobgp/debian/changelog new file mode 100644 index 000000000000..ba412cc45ede --- /dev/null +++ b/src/gobgp/debian/changelog @@ -0,0 +1,5 @@ +gobgp (1.16-01) UNRELEASED; urgency=low + + * Initial release. + + -- Pavel Shirshov Sat, 25 Feb 2017 00:25:19 +0000 diff --git a/src/gobgp/debian/compat b/src/gobgp/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/src/gobgp/debian/compat @@ -0,0 +1 @@ +9 diff --git a/src/gobgp/debian/control b/src/gobgp/debian/control new file mode 100644 index 000000000000..7d534852a383 --- /dev/null +++ b/src/gobgp/debian/control @@ -0,0 +1,12 @@ +Source: gobgp +Maintainer: Pavel Shirshov +Build-Depends: debhelper (>= 8.0.0), + dh-systemd +Standards-Version: 3.9.3 +Section: net + +Package: gobgp +Priority: extra +Architecture: amd64 +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: gobgp BGP daemon diff --git a/src/gobgp/debian/gobgp.dirs b/src/gobgp/debian/gobgp.dirs new file mode 100644 index 000000000000..3e9f1c594d41 --- /dev/null +++ b/src/gobgp/debian/gobgp.dirs @@ -0,0 +1 @@ +etc/gobgp diff --git a/src/gobgp/debian/gobgp.init.d b/src/gobgp/debian/gobgp.init.d new file mode 100644 index 000000000000..189fdad05690 --- /dev/null +++ b/src/gobgp/debian/gobgp.init.d @@ -0,0 +1,50 @@ +#!/bin/bash +# +### BEGIN INIT INFO +# Provides: gobgp +# Required-Start: $local_fs $network $remote_fs $syslog +# Required-Stop: $local_fs $network $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: start and stop the gobgpd +# Description: gobgpd is an implementation of bgp daemon in Go +### END INIT INFO +# + +PATH=/bin:/usr/bin:/sbin:/usr/sbin +D_PATH=/usr/sbin +C_PATH=/etc/gobgp + +. /lib/lsb/init-functions + +######################################################### +# Main program # +######################################################### + +case "$1" in + start) + if [ -f /etc/gobgp/gobgpd.conf ] + then + /usr/sbin/gobgpd -f /etc/gobgp/gobgpd.conf -r + echo $! > /var/run/gobgpd.pid + else + echo /etc/gobgp/gobgpd.conf not found + fi + ;; + + stop) + kill -9 $(echo /var/run/gobgpd.pid) + ;; + + restart|force-reload) + $0 stop $2 + sleep 1 + $0 start $2 + ;; + *) + echo "Usage: /etc/init.d/gobgp {start|stop|restart|force-reload}" + exit 1 + ;; +esac + +exit 0 diff --git a/src/gobgp/debian/gobgp.service b/src/gobgp/debian/gobgp.service new file mode 100644 index 000000000000..68a0b595aa1d --- /dev/null +++ b/src/gobgp/debian/gobgp.service @@ -0,0 +1,16 @@ +[Unit] +Description=gobgp service +After=network.target +ConditionPathExists=/etc/gobgp/gobgpd.yml + +[Service] +EnvironmentFile=-/etc/default/gobgp +ExecStart=/usr/sbin/gobgpd $DAEMON_ARGS +#ExecReload=/bin/kill -HUP $MAINPID +KillMode=process +Restart=on-failure + +[Install] +WantedBy=multi-user.target +Alias=gobgpd.service + diff --git a/src/gobgp/debian/rules b/src/gobgp/debian/rules new file mode 100755 index 000000000000..b6bee2ee4e76 --- /dev/null +++ b/src/gobgp/debian/rules @@ -0,0 +1,3 @@ +#!/usr/bin/make -f +%: + dh $@ --with systemd diff --git a/src/gobgp/gobgpd.conf.sample b/src/gobgp/gobgpd.conf.sample new file mode 100644 index 000000000000..c308df15be2c --- /dev/null +++ b/src/gobgp/gobgpd.conf.sample @@ -0,0 +1,21 @@ +[global.config] + as = 65501 + router-id = "192.168.0.1" +[[neighbors]] + [neighbors.config] + peer-as = 65502 + neighbor-address = "192.168.0.2" + [neighbors.graceful-restart.config] + enabled = true + restart-time = 120 + [[neighbors.afi-safis]] + [neighbors.afi-safis.config] + afi-safi-name = "ipv4-unicast" + [neighbors.afi-safis.mp-graceful-restart.config] + enabled = true + +[zebra] + [zebra.config] + enabled = true + url = "unix:/var/run/quagga/zserv.api" + redistribute-route-type-list = ["connect"] diff --git a/src/hiredis/Makefile b/src/hiredis/Makefile new file mode 100644 index 000000000000..d302b327d312 --- /dev/null +++ b/src/hiredis/Makefile @@ -0,0 +1,22 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = libhiredis0.13_$(HIREDIS_VERSION_FULL)_amd64.deb +DERIVED_TARGETS = libhiredis-dbg_$(HIREDIS_VERSION_FULL)_amd64.deb libhiredis-dev_$(HIREDIS_VERSION_FULL)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf hiredis-$(HIREDIS_VERSION) + + wget -O hiredis_$(HIREDIS_VERSION).orig.tar.gz http://http.debian.net/debian/pool/main/h/hiredis/hiredis_$(HIREDIS_VERSION).orig.tar.gz + wget -O hiredis_$(HIREDIS_VERSION_FULL).debian.tar.xz http://http.debian.net/debian/pool/main/h/hiredis/hiredis_$(HIREDIS_VERSION_FULL).debian.tar.xz + wget -O hiredis_$(HIREDIS_VERSION_FULL).dsc http://http.debian.net/debian/pool/main/h/hiredis/hiredis_$(HIREDIS_VERSION_FULL).dsc + + dpkg-source -x hiredis_$(HIREDIS_VERSION_FULL).dsc + pushd hiredis-$(HIREDIS_VERSION) + fakeroot debian/rules -j$(SONIC_CONFIG_MAKE_JOBS) binary + popd + + mv $* $(DERIVED_TARGETS) $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/initramfs-tools/Makefile b/src/initramfs-tools/Makefile new file mode 100644 index 000000000000..0b08e4aa431e --- /dev/null +++ b/src/initramfs-tools/Makefile @@ -0,0 +1,27 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = initramfs-tools_$(INITRAMFS_TOOLS_VERSION)_all.deb +DERIVED_TARGETS = initramfs-tools-core_$(INITRAMFS_TOOLS_VERSION)_all.deb + +INITRAMFS_TOOLS_REVISION = 18fc98e1b63b012f9bcf06ae3f5477872a5880c0 + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Obtaining the initramfs-tools + rm -rf ./initramfs-tools + git clone --branch v0.130 https://salsa.debian.org/kernel-team/initramfs-tools.git ./initramfs-tools + + # Patch + pushd ./initramfs-tools + git checkout $(INITRAMFS_TOOLS_REVISION) + patch -p1 < ../loopback-file-system-support.patch + + # Build the package + rm -f debian/*.debhelper.log + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/patch/initramfs-tools/loopback-file-system-support.patch b/src/initramfs-tools/loopback-file-system-support.patch similarity index 100% rename from patch/initramfs-tools/loopback-file-system-support.patch rename to src/initramfs-tools/loopback-file-system-support.patch diff --git a/src/iproute2/Makefile b/src/iproute2/Makefile new file mode 100644 index 000000000000..0181c9ca6d31 --- /dev/null +++ b/src/iproute2/Makefile @@ -0,0 +1,20 @@ +SHELL = /bin/bash +.ONESHELL: +.SHELLFLAGS += -e + +IPROUTE2_VERSION = 4.9.0 +IPROUTE2_VERSION_FULL = $(IPROUTE2_VERSION)-1 + +MAIN_TARGET = iproute2_$(IPROUTE2_VERSION_FULL)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + wget -O iproute2_$(IPROUTE2_VERSION).orig.tar.xz -N "https://sonicstorage.blob.core.windows.net/packages/iproute2_4.9.0.orig.tar.xz?sv=2015-04-05&sr=b&sig=9nvybd1xkXyRQbaG6Fy6wBazPA8IbZV0AO41GWXPEP8%3D&se=2154-10-23T11%3A59%3A00Z&sp=r" + wget -O iproute2_$(IPROUTE2_VERSION_FULL).dsc -N "https://sonicstorage.blob.core.windows.net/packages/iproute2_4.9.0-1.dsc?sv=2015-04-05&sr=b&sig=m6FcMH9dOh8ggipBgOsONiXvDxoi6bfUO%2BxvidsMNMQ%3D&se=2154-10-23T11%3A59%3A53Z&sp=r" + wget -O iproute2_$(IPROUTE2_VERSION_FULL).debian.tar.xz -N "https://sonicstorage.blob.core.windows.net/packages/iproute2_4.9.0-1.debian.tar.xz?sv=2015-04-05&sr=b&sig=U5NFuwG5C3vZXlUUNvoPMnKDtMKk66zbweA9rQYbEVY%3D&se=2154-10-23T12%3A00%3A15Z&sp=r" + dpkg-source -x iproute2_$(IPROUTE2_VERSION_FULL).dsc + + pushd iproute2-$(IPROUTE2_VERSION) + dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + mv $* $(DEST)/ diff --git a/src/isc-dhcp/Makefile b/src/isc-dhcp/Makefile new file mode 100644 index 000000000000..ce4fbc62608f --- /dev/null +++ b/src/isc-dhcp/Makefile @@ -0,0 +1,32 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = isc-dhcp-common_$(ISC_DHCP_VERSION)_amd64.deb +DERIVED_TARGETS = isc-dhcp-relay_$(ISC_DHCP_VERSION)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf ./isc-dhcp + + # Clone isc-dhcp repo + git clone https://salsa.debian.org/berni/isc-dhcp.git + pushd ./isc-dhcp + + # Reset HEAD to the commit of the proper tag + # NOTE: Using "git checkout " here detaches our HEAD, + # which stg doesn't like, so we use this method instead + git reset --hard debian/$(ISC_DHCP_VERSION) + + # Apply patches + stg init + stg import -s ../patch/series + + # Build source and Debian packages + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + # Move the newly-built .deb packages to the destination directory + mv $* $(DERIVED_TARGETS) $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/isc-dhcp/patch/0001-Customizable-Option-82-circuit-ID-and-remote-ID-fiel.patch b/src/isc-dhcp/patch/0001-Customizable-Option-82-circuit-ID-and-remote-ID-fiel.patch new file mode 100644 index 000000000000..22a8f7faedd1 --- /dev/null +++ b/src/isc-dhcp/patch/0001-Customizable-Option-82-circuit-ID-and-remote-ID-fiel.patch @@ -0,0 +1,273 @@ +From 284c87ff4b3873d0215904273fe3c86b07b4ba94 Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Mon, 11 Dec 2017 23:21:08 +0000 +Subject: [PATCH 1/3] Customizable Option 82 circuit ID and remote ID fields + +--- + relay/dhcrelay.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 152 insertions(+), 30 deletions(-) + +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index 15b4997..b9f8326 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -73,6 +73,8 @@ int bad_circuit_id = 0; /* Circuit ID option in matching RAI option + did not match any known circuit ID. */ + int missing_circuit_id = 0; /* Circuit ID option in matching RAI option + was missing. */ ++const char *agent_circuit_id_fmt = NULL; /* Circuit ID custom format string. */ ++const char *agent_remote_id_fmt = NULL; /* Remote ID custom format string. */ + int max_hop_count = 10; /* Maximum hop count */ + + #ifdef DHCPv6 +@@ -140,9 +142,19 @@ static const char message[] = + static const char url[] = + "For info, please visit https://www.isc.org/software/dhcp/"; + ++#define DHCRELAY_OPTION82_USAGE \ ++"circuit_id/remote_id interpreted sequences are:\n" \ ++"\n" \ ++" %%%% A single %%\n" \ ++" %%h Hostname of device\n" \ ++" %%p Name of interface that generated the request\n" \ ++" %%P Hardware address of interface that generated the request\n" \ ++" %%C Client hardware address\n" \ ++" %%I DHCP relay agent IP Address\n" \ ++ + #ifdef DHCPv6 + #define DHCRELAY_USAGE \ +-"Usage: dhcrelay [-4] [-d] [-q] [-a] [-D]\n"\ ++"Usage: dhcrelay [-4] [-d] [-q] [-a ] [-D]\n"\ + " [-A ] [-c ] [-p ]\n" \ + " [-pf ] [--no-pid]\n"\ + " [-m append|replace|forward|discard]\n" \ +@@ -154,14 +166,15 @@ static const char url[] = + " -l lower0 [ ... -l lowerN]\n" \ + " -u upper0 [ ... -u upperN]\n" \ + " lower (client link): [address%%]interface[#index]\n" \ +-" upper (server link): [address%%]interface" ++" upper (server link): [address%%]interface\n\n" DHCRELAY_OPTION82_USAGE + #else + #define DHCRELAY_USAGE \ +-"Usage: dhcrelay [-d] [-q] [-a] [-D] [-A ] [-c ] [-p ]\n" \ +-" [-pf ] [--no-pid]\n" \ ++"Usage: dhcrelay [-d] [-q] [-a ] [-D]\n" \ ++" [-A ] [-c ] [-p ]\n" \ ++" [-pf ] [--no-pid]\n"\ + " [-m append|replace|forward|discard]\n" \ + " [-i interface0 [ ... -i interfaceN]\n" \ +-" server0 [ ... serverN]\n\n" ++" server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE + #endif + + static void usage() { +@@ -287,6 +300,15 @@ main(int argc, char **argv) { + local_family_set = 1; + local_family = AF_INET; + #endif ++ if (++i == argc) ++ usage(); ++ ++ if (argv[i] != NULL && argv[i][0] != '-') ++ agent_circuit_id_fmt = argv[i++]; ++ ++ if (argv[i] != NULL && argv[i][0] != '-') ++ agent_remote_id_fmt = argv[i]; ++ + add_agent_options = 1; + } else if (!strcmp(argv[i], "-A")) { + #ifdef DHCPv6 +@@ -938,6 +960,80 @@ find_interface_by_agent_option(struct dhcp_packet *packet, + } + + /* ++ * Format the message that will be used by circuit_id and remote_id ++ */ ++static int ++format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_packet *packet, ++ const char *format, char *msg, size_t msgn) { ++ size_t len = 0; ++ char hostname[HOST_NAME_MAX] = { 0 }; ++ char ifname[IFNAMSIZ] = { 0 }; ++ char *buf = msg; ++ ++ for ( ; format && *format && len < msgn; ++format) { ++ size_t strn = 0; ++ const char *str = NULL; ++ ++ if (*format == '%') { ++ switch (*++format) { ++ case '\0': ++ --format; ++ break; ++ ++ case '%': /* A literal '%' */ ++ str = "%"; ++ break; ++ ++ case 'h': /* Hostname */ ++ gethostname(hostname, HOST_NAME_MAX); ++ hostname[HOST_NAME_MAX - 1] = '\0'; ++ str = hostname; ++ break; ++ ++ case 'p': /* Name of interface that we received the request from */ ++ strncpy(ifname, ip->name, IFNAMSIZ); ++ str = ifname; ++ break; ++ ++ case 'P': /* Physical address of interface that we received the request from */ ++ str = print_hw_addr(ip->hw_address.hbuf[0], ip->hw_address.hlen - 1, &ip->hw_address.hbuf[1]); ++ break; ++ ++ case 'C': /* 24: Client hardware address */ ++ str = print_hw_addr(packet->htype, packet->hlen, packet->chaddr); ++ break; ++ ++ case 'I': /* 20: DHCP relay agent IP address */ ++ str = inet_ntoa(packet->giaddr); ++ break; ++ ++ default: ++ log_error("Option %%%c is unrecognized and will not be formatted!", *format); ++ continue; ++ } ++ ++ if (str) ++ strn = strlen(str); ++ } else { ++ str = format; ++ strn = 1; ++ } ++ ++ // Do we have room? ++ if ((strn+len) >= msgn) { ++ return 0; ++ } ++ ++ if (str && strn > 0) { ++ memcpy(buf+len, str, strn); ++ len += strn; ++ } ++ } ++ ++ return len; ++} ++ ++/* + * Examine a packet to see if it's a candidate to have a Relay + * Agent Information option tacked onto its tail. If it is, tack + * the option on. +@@ -946,8 +1042,11 @@ static int + add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet, + unsigned length, struct in_addr giaddr) { + int is_dhcp = 0, mms; +- unsigned optlen; ++ unsigned optlen = 0; + u_int8_t *op, *nextop, *sp, *max, *end_pad = NULL; ++ char circuit_id_buf[256] = { '\0' }; ++ char remote_id_buf[256] = { '\0' }; ++ size_t circuit_id_len = 0, remote_id_len = 0; + + /* If we're not adding agent options to packets, we can skip + this. */ +@@ -1077,24 +1176,47 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet, + op = sp; + #endif + +- /* Sanity check. Had better not ever happen. */ +- if ((ip->circuit_id_len > 255) ||(ip->circuit_id_len < 1)) +- log_fatal("Circuit ID length %d out of range [1-255] on " +- "%s\n", ip->circuit_id_len, ip->name); +- optlen = ip->circuit_id_len + 2; /* RAI_CIRCUIT_ID + len */ +- +- if (ip->remote_id) { +- if (ip->remote_id_len > 255 || ip->remote_id_len < 1) +- log_fatal("Remote ID length %d out of range [1-255] " +- "on %s\n", ip->circuit_id_len, ip->name); +- optlen += ip->remote_id_len + 2; /* RAI_REMOTE_ID + len */ +- } ++ /* option82: custom string for circuit_id */ ++ if (agent_circuit_id_fmt) { ++ circuit_id_len = format_relay_agent_rfc3046_msg(ip, packet, agent_circuit_id_fmt, ++ circuit_id_buf, sizeof(circuit_id_buf)); ++ ++ if (circuit_id_len == 0) { ++ strncpy(circuit_id_buf, ip->name, sizeof(ip->name)); ++ circuit_id_len = strlen(circuit_id_buf); ++ } ++ ++ /* Sanity check. Had better not ever happen. */ ++ if (circuit_id_len > 255 || circuit_id_len < 1) ++ log_fatal("Circuit ID length %d out of range [1-255] on %s\n", ++ (int)circuit_id_len, ip->name); ++ ++ optlen = circuit_id_len + 2; // RAI_CIRCUIT_ID + len ++ ++ //log_debug("Sending on %s option82:circuit_id='%s' (%d)", ++ // ip->name, circuit_id_buf, (int)circuit_id_len); ++ } ++ ++ /* option82: custom string for remote_id */ ++ if (agent_remote_id_fmt) { ++ remote_id_len = format_relay_agent_rfc3046_msg(ip, packet, agent_remote_id_fmt, ++ remote_id_buf, sizeof(remote_id_buf)); ++ ++ if (remote_id_len > 255 || remote_id_len < 1) ++ log_fatal("Remote ID length %d out of range [1-255] on %s\n", ++ (int)remote_id_len, ip->name); ++ ++ optlen += remote_id_len + 2; // RAI_REMOTE_ID + len ++ ++ //log_debug("Sending on %s option82:remote_id='%s' (%d)", ++ // ip->name, remote_id_buf, (int)remote_id_len); ++ } + +- /* We do not support relay option fragmenting(multiple options to +- * support an option data exceeding 255 bytes). ++ /* We do not support relay option fragmenting (multiple options to ++ * support an option data exceeding 255 bytes) + */ +- if ((optlen < 3) ||(optlen > 255)) +- log_fatal("Total agent option length(%u) out of range " ++ if (optlen < 3 || optlen > 255) ++ log_fatal("Total agent option length (%u) out of range " + "[3 - 255] on %s\n", optlen, ip->name); + + /* +@@ -1102,7 +1224,7 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet, + * If not, forward without adding the option. + */ + if (max - sp >= optlen + 3) { +- log_debug("Adding %d-byte relay agent option", optlen + 3); ++ //log_debug("Adding %d-byte relay agent option", optlen + 3); + + /* Okay, cons up *our* Relay Agent Information option. */ + *sp++ = DHO_DHCP_AGENT_OPTIONS; +@@ -1110,16 +1232,16 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet, + + /* Copy in the circuit id... */ + *sp++ = RAI_CIRCUIT_ID; +- *sp++ = ip->circuit_id_len; +- memcpy(sp, ip->circuit_id, ip->circuit_id_len); +- sp += ip->circuit_id_len; ++ *sp++ = circuit_id_len; ++ memcpy(sp, circuit_id_buf, circuit_id_len); ++ sp += circuit_id_len; + + /* Copy in remote ID... */ +- if (ip->remote_id) { ++ if (remote_id_len > 0) { + *sp++ = RAI_REMOTE_ID; +- *sp++ = ip->remote_id_len; +- memcpy(sp, ip->remote_id, ip->remote_id_len); +- sp += ip->remote_id_len; ++ *sp++ = remote_id_len; ++ memcpy(sp, remote_id_buf, remote_id_len); ++ sp += remote_id_len; + } + } else { + ++agent_option_errors; +-- +2.1.4 + diff --git a/src/isc-dhcp/patch/0002-Support-for-obtaining-name-of-physical-interface-tha.patch b/src/isc-dhcp/patch/0002-Support-for-obtaining-name-of-physical-interface-tha.patch new file mode 100644 index 000000000000..ee85a7736287 --- /dev/null +++ b/src/isc-dhcp/patch/0002-Support-for-obtaining-name-of-physical-interface-tha.patch @@ -0,0 +1,114 @@ +From caad3e05c31c9fad8cda378ce95a1969def771a2 Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Mon, 11 Dec 2017 23:39:10 +0000 +Subject: [PATCH 2/3] Support for obtaining name of physical interface that is + a member of a bridge interface + +--- + relay/dhcrelay.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 67 insertions(+), 2 deletions(-) + +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index b9f8326..8458ea9 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -758,6 +758,7 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet, + print_hw_addr(packet->htype, packet->hlen, + packet->chaddr), + inet_ntoa(sp->to.sin_addr)); ++ + ++client_packets_relayed; + } + } +@@ -917,6 +918,7 @@ find_interface_by_agent_option(struct dhcp_packet *packet, + ++corrupt_agent_options; + return (-1); + } ++ + switch(buf[i]) { + /* Remember where the circuit ID is... */ + case RAI_CIRCUIT_ID: +@@ -959,6 +961,47 @@ find_interface_by_agent_option(struct dhcp_packet *packet, + return (-1); + } + ++static int ++_bridgefdbquery(const char *hwAddr, char *interface, int *vlanid) { ++ ++#define xstr(s) str(s) ++#define str(s) #s ++#define FDB_STRING_LEN 100 ++#define FDB_BUFFER_LEN (FDB_STRING_LEN + 1) ++ ++/* ++ * Format for sscanf() to read the 1st, 3th, and 5th ++ * space-delimited fields ++ * ++ * bridge fdb show output ++ * 6c:64:1a:00:06:13 dev swp35 vlan 0 master bridge permanent ++ */ ++#define FDB_LINE_FORMAT "%" xstr(FDB_STRING_LEN) "s %*s " \ ++ "%" xstr(FDB_STRING_LEN) "s %*s %d %*s" ++ ++ char cmdstr[FDB_BUFFER_LEN]; ++ char buf[FDB_BUFFER_LEN]; ++ char macAddr[FDB_BUFFER_LEN]; ++ ++ if ((interface == NULL) || (vlanid == NULL)) { ++ return 0; ++ } ++ sprintf(cmdstr, "bridge fdb show | grep -m 1 %s", hwAddr); ++ FILE *cmd = popen(cmdstr, "r"); ++ ++ if (cmd != NULL) { ++ while (fgets(buf, sizeof(buf), cmd)) { ++ sscanf(buf, FDB_LINE_FORMAT, macAddr, interface, vlanid); ++ //log_debug("bridgefdbquery: macAddr: %s interface: %s vlanid: %d", ++ // macAddr, interface, *vlanid); ++ } ++ pclose(cmd); ++ return 0; ++ } ++ ++ return -1; ++} ++ + /* + * Format the message that will be used by circuit_id and remote_id + */ +@@ -991,8 +1034,30 @@ format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_pack + break; + + case 'p': /* Name of interface that we received the request from */ +- strncpy(ifname, ip->name, IFNAMSIZ); +- str = ifname; ++ /* ++ * Query FDB to identify the exact physical interface only when source MAC address ++ * is present and '20: DHCP relay agent IP address' (giaddr) is not present ++ */ ++ if (packet->htype && !packet->giaddr.s_addr) { ++ int ret = 0, vlanid = 0; ++ ++ ret = _bridgefdbquery(print_hw_addr(packet->htype, packet->hlen, packet->chaddr), ++ ifname, ++ &vlanid); ++ ++ // If we failed to find a physical interface using the source mac, default ++ // to the interface name we received it on. ++ if (ret < 0) { ++ //log_debug("MAC Address: %s (interface:%s vlan:%d) not found in bridge fdb show", ++ // print_hw_addr (packet->htype, packet->hlen, packet->chaddr), ++ // ip->name, ++ // vlanid); ++ ++ strncpy(ifname, ip->name, IFNAMSIZ); ++ } ++ ++ str = ifname; ++ } + break; + + case 'P': /* Physical address of interface that we received the request from */ +-- +2.1.4 + diff --git a/src/isc-dhcp/patch/0003-Support-for-loading-port-alias-map-file-to-replace-p.patch b/src/isc-dhcp/patch/0003-Support-for-loading-port-alias-map-file-to-replace-p.patch new file mode 100644 index 000000000000..7411e1c4ff3e --- /dev/null +++ b/src/isc-dhcp/patch/0003-Support-for-loading-port-alias-map-file-to-replace-p.patch @@ -0,0 +1,187 @@ +From 3a42b497716375c9347b51c3a28c5e91e7cd4cf4 Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Tue, 12 Dec 2017 00:49:09 +0000 +Subject: [PATCH 3/3] Support for loading port alias map file to replace port + name with alias in circuit id + +--- + relay/dhcrelay.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 105 insertions(+), 1 deletion(-) + +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index 8458ea9..15f0acf 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -122,6 +122,14 @@ static void setup_streams(void); + char *dhcrelay_sub_id = NULL; + #endif + ++struct interface_name_alias_tuple { ++ char if_name[IFNAMSIZ]; ++ char if_alias[IFNAMSIZ]; ++}; ++ ++static struct interface_name_alias_tuple *g_interface_name_alias_map = NULL; ++static size_t g_interface_name_alias_map_size = 0; ++ + static void do_relay4(struct interface_info *, struct dhcp_packet *, + unsigned int, unsigned int, struct iaddr, + struct hardware *); +@@ -134,6 +142,10 @@ static int strip_relay_agent_options(struct interface_info *, + struct interface_info **, + struct dhcp_packet *, unsigned); + ++static int load_interface_alias_map(const char *port_alias_map_file_path); ++static int get_interface_alias_by_name(const char *if_name, char *if_alias_out); ++static void free_interface_alias_map(void); ++ + static const char copyright[] = + "Copyright 2004-2015 Internet Systems Consortium."; + static const char arr[] = "All rights reserved."; +@@ -147,7 +159,7 @@ static const char url[] = + "\n" \ + " %%%% A single %%\n" \ + " %%h Hostname of device\n" \ +-" %%p Name of interface that generated the request\n" \ ++" %%p Alias of interface that generated the request\n" \ + " %%P Hardware address of interface that generated the request\n" \ + " %%C Client hardware address\n" \ + " %%I DHCP relay agent IP Address\n" \ +@@ -158,10 +170,12 @@ static const char url[] = + " [-A ] [-c ] [-p ]\n" \ + " [-pf ] [--no-pid]\n"\ + " [-m append|replace|forward|discard]\n" \ ++" [--name-alias-map-file ]\n" \ + " [-i interface0 [ ... -i interfaceN]\n" \ + " server0 [ ... serverN]\n\n" \ + " dhcrelay -6 [-d] [-q] [-I] [-c ] [-p ]\n" \ + " [-pf ] [--no-pid]\n" \ ++" [--name-alias-map-file ]\n" \ + " [-s ]\n" \ + " -l lower0 [ ... -l lowerN]\n" \ + " -u upper0 [ ... -u upperN]\n" \ +@@ -405,6 +419,11 @@ main(int argc, char **argv) { + no_dhcrelay_pid = ISC_TRUE; + } else if (!strcmp(argv[i], "--no-pid")) { + no_pid_file = ISC_TRUE; ++ } else if (!strcmp(argv[i], "--name-alias-map-file")) { ++ if (++i == argc) ++ usage(); ++ if (load_interface_alias_map(argv[i]) != 0) ++ log_fatal("Failed to load interface name-alias map."); + } else if (!strcmp(argv[i], "--version")) { + log_info("isc-dhcrelay-%s", PACKAGE_VERSION); + exit(0); +@@ -624,6 +643,8 @@ main(int argc, char **argv) { + dispatch(); + + /* In fact dispatch() never returns. */ ++ free_interface_alias_map(); ++ + return (0); + } + +@@ -1040,6 +1061,7 @@ format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_pack + */ + if (packet->htype && !packet->giaddr.s_addr) { + int ret = 0, vlanid = 0; ++ char ifalias[IFNAMSIZ] = { 0 }; + + ret = _bridgefdbquery(print_hw_addr(packet->htype, packet->hlen, packet->chaddr), + ifname, +@@ -1056,6 +1078,18 @@ format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_pack + strncpy(ifname, ip->name, IFNAMSIZ); + } + ++ // Attempt to translate SONiC interface name to vendor alias ++ ret = get_interface_alias_by_name(ifname, ifalias); ++ if (ret < 0) { ++ //log_debug("Failed to retrieve alias for interface name '%s'. Defaulting to interface name.", ifname); ++ } ++ else { ++ //log_debug("Mapped interface name '%s' to alias '%s'. Adding as option 82 interface alias for MAC Address %s", ++ // ifname, ifalias, print_hw_addr (packet->htype, packet->hlen, packet->chaddr)); ++ ++ strncpy(ifname, ifalias, IFNAMSIZ); ++ } ++ + str = ifname; + } + break; +@@ -1922,3 +1956,73 @@ dhcp_set_control_state(control_object_state_t oldstate, + + exit(0); + } ++ ++#define MAX_PORT_CONFIG_LINE_LEN 1024 ++ ++// Allocates and loads global map g_interface_name_alias_map ++// Also sets global g_interface_name_alias_map_size ++static int ++load_interface_alias_map(const char *port_alias_map_file_path) { ++ int i = 0; ++ FILE *fp = NULL; ++ char line[MAX_PORT_CONFIG_LINE_LEN] = { 0 }; ++ ++ fp = fopen(port_alias_map_file_path,"r"); ++ if (fp == NULL) { ++ log_error("Unable to open %s", port_alias_map_file_path); ++ return -1; ++ } ++ ++ g_interface_name_alias_map_size = 0; ++ ++ // Count the number of interfaces listed in the file ++ while (fgets(line, sizeof(line), fp)) { ++ g_interface_name_alias_map_size++; ++ } ++ ++ // Allocate our map accordingly ++ g_interface_name_alias_map = ((struct interface_name_alias_tuple *) ++ dmalloc((sizeof(struct interface_name_alias_tuple) * g_interface_name_alias_map_size), ++ MDL)); ++ ++ // Reset file position indicator to beginning of file ++ fseek(fp, 0, SEEK_SET); ++ ++ // Every line should contain exactly one name-alias pair ++ while (fgets(line, sizeof(line), fp)) { ++ // Each line should read as "" ++ sscanf(line, "%s %s", g_interface_name_alias_map[i].if_name, g_interface_name_alias_map[i].if_alias); ++ i++; ++ } ++ ++ fclose(fp); ++ ++ log_info("Loaded %d interface name-alias mappings", i); ++ ++ return 0; ++} ++ ++// Locates alias for port named if_name, copies alias into if_alias_out, up to a ++// max of IFNAMSIZ bytes. ++// Returns 0 on success, -1 on failure ++static int ++get_interface_alias_by_name(const char *if_name, char *if_alias_out) { ++ int i = 0; ++ ++ for (i = 0; i < g_interface_name_alias_map_size; i++) { ++ if (strncmp(if_name, g_interface_name_alias_map[i].if_name, IFNAMSIZ) == 0) { ++ strncpy(if_alias_out, g_interface_name_alias_map[i].if_alias, IFNAMSIZ); ++ return 0; ++ } ++ } ++ ++ return -1; ++} ++ ++// Frees global map g_interface_name_alias_map ++// Sets g_interface_name_alias_map_size to 0 ++static void ++free_interface_alias_map(void) { ++ free(g_interface_name_alias_map); ++ g_interface_name_alias_map_size = 0; ++} +-- +2.1.4 + diff --git a/src/isc-dhcp/patch/0004-Bugfix-Don-t-print-log-messages-to-stderr-in-release.patch b/src/isc-dhcp/patch/0004-Bugfix-Don-t-print-log-messages-to-stderr-in-release.patch new file mode 100644 index 000000000000..428f4471a1f7 --- /dev/null +++ b/src/isc-dhcp/patch/0004-Bugfix-Don-t-print-log-messages-to-stderr-in-release.patch @@ -0,0 +1,28 @@ +From 2bb21fcf4a9ad7535867809c50d2cf0ba1088e17 Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Fri, 9 Mar 2018 01:43:35 +0000 +Subject: [PATCH] [Bugfix] Don't print log messages to stderr in release builds + +--- + omapip/errwarn.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/omapip/errwarn.c b/omapip/errwarn.c +index 7c91d9d..aa74fd8 100644 +--- a/omapip/errwarn.c ++++ b/omapip/errwarn.c +@@ -39,9 +39,9 @@ + #include + + #ifdef DEBUG +-int log_perror = -1; +-#else + int log_perror = 1; ++#else ++int log_perror = 0; + #endif + void (*log_cleanup) (void); + +-- +2.1.4 + diff --git a/src/isc-dhcp/patch/0005-CVE-2017-3144.patch b/src/isc-dhcp/patch/0005-CVE-2017-3144.patch new file mode 100644 index 000000000000..fe066e177a8c --- /dev/null +++ b/src/isc-dhcp/patch/0005-CVE-2017-3144.patch @@ -0,0 +1,47 @@ +From: Thomas Markwalder +Date: Thu, 7 Dec 2017 11:23:36 -0500 +Subject: [master] Plugs a socket descriptor leak in OMAPI +Origin: https://source.isc.org/cgi-bin/gitweb.cgi?p=dhcp.git;a=commit;h=1a6b62fe17a42b00fa234d06b6dfde3d03451894 +Bug: https://bugs.isc.org/Public/Bug/Display.html?id=46767 +Bug-Debian: https://bugs.debian.org/887413 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-3144 + + Merges in rt46767. +--- + +diff --git a/omapip/buffer.c b/omapip/buffer.c +index 6e0621b5..a21f0a80 100644 +--- a/omapip/buffer.c ++++ b/omapip/buffer.c +@@ -565,6 +565,15 @@ isc_result_t omapi_connection_writer (omapi_object_t *h) + omapi_buffer_dereference (&buffer, MDL); + } + } ++ ++ /* If we had data left to write when we're told to disconnect, ++ * we need recall disconnect, now that we're done writing. ++ * See rt46767. */ ++ if (c->out_bytes == 0 && c->state == omapi_connection_disconnecting) { ++ omapi_disconnect (h, 1); ++ return ISC_R_SHUTTINGDOWN; ++ } ++ + return ISC_R_SUCCESS; + } + +diff --git a/omapip/message.c b/omapip/message.c +index ee15d821..37abbd25 100644 +--- a/omapip/message.c ++++ b/omapip/message.c +@@ -339,7 +339,7 @@ isc_result_t omapi_message_unregister (omapi_object_t *mo) + } + + #ifdef DEBUG_PROTOCOL +-static const char *omapi_message_op_name(int op) { ++const char *omapi_message_op_name(int op) { + switch (op) { + case OMAPI_OP_OPEN: return "OMAPI_OP_OPEN"; + case OMAPI_OP_REFRESH: return "OMAPI_OP_REFRESH"; +-- +2.16.2 + diff --git a/src/isc-dhcp/patch/0006-CVE-2018-5733.patch b/src/isc-dhcp/patch/0006-CVE-2018-5733.patch new file mode 100644 index 000000000000..f2ddff0503eb --- /dev/null +++ b/src/isc-dhcp/patch/0006-CVE-2018-5733.patch @@ -0,0 +1,145 @@ +From: Zhenggen Xu +Date: Thu, 11 Oct 2018 17:18:32 -0700 +Subject: [PATCH] Subject: [master] Corrected refcnt loss in option parsing + Origin: + https://source.isc.org/cgi-bin/gitweb.cgi?p=dhcp.git;a=commit;h=197b26f25309f947b97a83b8fdfc414b767798f8 + Bug: https://bugs.isc.org/Public/Bug/Display.html?id=47140 Bug-Debian: + https://bugs.debian.org/891785 Bug-Debian-Security: + https://security-tracker.debian.org/tracker/CVE-2018-5733 + + Merges in 47140. +--- + common/options.c | 2 + + common/tests/Makefile.am | 11 ++++- + common/tests/option_unittest.c | 79 ++++++++++++++++++++++++++++++++++ + 3 files changed, 91 insertions(+), 1 deletion(-) + create mode 100644 common/tests/option_unittest.c + +diff --git a/common/options.c b/common/options.c +index 74f1fb5..db28b5c 100644 +--- a/common/options.c ++++ b/common/options.c +@@ -177,6 +177,8 @@ int parse_option_buffer (options, buffer, length, universe) + + /* If the length is outrageous, the options are bad. */ + if (offset + len > length) { ++ /* Avoid reference count overflow */ ++ option_dereference(&option, MDL); + reason = "option length exceeds option buffer length"; + bogus: + log_error("parse_option_buffer: malformed option " +diff --git a/common/tests/Makefile.am b/common/tests/Makefile.am +index 32e055c..19521c9 100644 +--- a/common/tests/Makefile.am ++++ b/common/tests/Makefile.am +@@ -8,7 +8,8 @@ ATF_TESTS = + + if HAVE_ATF + +-ATF_TESTS += alloc_unittest dns_unittest misc_unittest ns_name_unittest ++ATF_TESTS += alloc_unittest dns_unittest misc_unittest ns_name_unittest \ ++ option_unittest + + alloc_unittest_SOURCES = test_alloc.c $(top_srcdir)/tests/t_api_dhcp.c + alloc_unittest_LDADD = $(ATF_LDFLAGS) +@@ -34,6 +35,14 @@ ns_name_unittest_LDADD += ../libdhcp.a \ + ../../omapip/libomapi.a ../../bind/lib/libirs.a \ + ../../bind/lib/libdns.a ../../bind/lib/libisccfg.a ../../bind/lib/libisc.a + ++option_unittest_SOURCES = option_unittest.c $(top_srcdir)/tests/t_api_dhcp.c ++option_unittest_LDADD = $(ATF_LDFLAGS) ++option_unittest_LDADD += ../libdhcp.@A@ ../../omapip/libomapi.@A@ \ ++ @BINDLIBIRSDIR@/libirs.@A@ \ ++ @BINDLIBDNSDIR@/libdns.@A@ \ ++ @BINDLIBISCCFGDIR@/libisccfg.@A@ \ ++ @BINDLIBISCDIR@/libisc.@A@ ++ + check: $(ATF_TESTS) + sh ${top_srcdir}/tests/unittest.sh + +diff --git a/common/tests/option_unittest.c b/common/tests/option_unittest.c +new file mode 100644 +index 0000000..36236b8 +--- /dev/null ++++ b/common/tests/option_unittest.c +@@ -0,0 +1,79 @@ ++/* ++ * Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC") ++ * ++ * This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH ++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, ++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE ++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ++ * PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include "dhcpd.h" ++ ++ATF_TC(option_refcnt); ++ ++ATF_TC_HEAD(option_refcnt, tc) ++{ ++ atf_tc_set_md_var(tc, "descr", ++ "Verify option reference count does not overflow."); ++} ++ ++/* This test does a simple check to see if option reference count is ++ * decremented even an error path exiting parse_option_buffer() ++ */ ++ATF_TC_BODY(option_refcnt, tc) ++{ ++ struct option_state *options; ++ struct option *option; ++ unsigned code; ++ int refcnt; ++ unsigned char buffer[3] = { 15, 255, 0 }; ++ ++ initialize_common_option_spaces(); ++ ++ options = NULL; ++ if (!option_state_allocate(&options, MDL)) { ++ atf_tc_fail("can't allocate option state"); ++ } ++ ++ option = NULL; ++ code = 15; /* domain-name */ ++ if (!option_code_hash_lookup(&option, dhcp_universe.code_hash, ++ &code, 0, MDL)) { ++ atf_tc_fail("can't find option 15"); ++ } ++ if (option == NULL) { ++ atf_tc_fail("option is NULL"); ++ } ++ refcnt = option->refcnt; ++ ++ buffer[0] = 15; ++ buffer[1] = 255; /* invalid */ ++ buffer[2] = 0; ++ ++ if (parse_option_buffer(options, buffer, 3, &dhcp_universe)) { ++ atf_tc_fail("parse_option_buffer is expected to fail"); ++ } ++ ++ if (refcnt != option->refcnt) { ++ atf_tc_fail("refcnt changed from %d to %d", refcnt, option->refcnt); ++ } ++} ++ ++/* This macro defines main() method that will call specified ++ test cases. tp and simple_test_case names can be whatever you want ++ as long as it is a valid variable identifier. */ ++ATF_TP_ADD_TCS(tp) ++{ ++ ATF_TP_ADD_TC(tp, option_refcnt); ++ ++ return (atf_no_error()); ++} + diff --git a/src/isc-dhcp/patch/0007-CVE-2018-5732.patch b/src/isc-dhcp/patch/0007-CVE-2018-5732.patch new file mode 100644 index 000000000000..d6c10e2e6532 --- /dev/null +++ b/src/isc-dhcp/patch/0007-CVE-2018-5732.patch @@ -0,0 +1,144 @@ +From: Thomas Markwalder +Date: Sat, 10 Feb 2018 12:15:27 -0500 +Subject: [master] Correct buffer overrun in pretty_print_option +Origin: https://source.isc.org/cgi-bin/gitweb.cgi?p=dhcp.git;a=commit;h=c5931725b48b121d232df4ba9e45bc41e0ba114d +Bug: https://bugs.isc.org/Public/Bug/Display.html?id=47139 +Bug-Debian: https://bugs.debian.org/891786 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2018-5732 + + Merges in rt47139. +--- + +diff --git a/common/options.c b/common/options.c +index 6f23bc15..fc0e0889 100644 +--- a/common/options.c ++++ b/common/options.c +@@ -1776,7 +1776,8 @@ format_min_length(format, oc) + + + /* Format the specified option so that a human can easily read it. */ +- ++/* Maximum pretty printed size */ ++#define MAX_OUTPUT_SIZE 32*1024 + const char *pretty_print_option (option, data, len, emit_commas, emit_quotes) + struct option *option; + const unsigned char *data; +@@ -1784,8 +1785,9 @@ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes) + int emit_commas; + int emit_quotes; + { +- static char optbuf [32768]; /* XXX */ +- static char *endbuf = &optbuf[sizeof(optbuf)]; ++ /* We add 128 byte pad so we don't have to add checks everywhere. */ ++ static char optbuf [MAX_OUTPUT_SIZE + 128]; /* XXX */ ++ static char *endbuf = optbuf + MAX_OUTPUT_SIZE; + int hunksize = 0; + int opthunk = 0; + int hunkinc = 0; +@@ -2211,7 +2213,14 @@ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes) + log_error ("Unexpected format code %c", + fmtbuf [j]); + } ++ + op += strlen (op); ++ if (op >= endbuf) { ++ log_error ("Option data exceeds" ++ " maximum size %d", MAX_OUTPUT_SIZE); ++ return (""); ++ } ++ + if (dp == data + len) + break; + if (j + 1 < numelem && comma != ':') +diff --git a/common/tests/option_unittest.c b/common/tests/option_unittest.c +index 36236b84..cd52cfb4 100644 +--- a/common/tests/option_unittest.c ++++ b/common/tests/option_unittest.c +@@ -43,7 +43,7 @@ ATF_TC_BODY(option_refcnt, tc) + if (!option_state_allocate(&options, MDL)) { + atf_tc_fail("can't allocate option state"); + } +- ++ + option = NULL; + code = 15; /* domain-name */ + if (!option_code_hash_lookup(&option, dhcp_universe.code_hash, +@@ -68,12 +68,75 @@ ATF_TC_BODY(option_refcnt, tc) + } + } + ++ATF_TC(pretty_print_option); ++ ++ATF_TC_HEAD(pretty_print_option, tc) ++{ ++ atf_tc_set_md_var(tc, "descr", ++ "Verify pretty_print_option does not overrun its buffer."); ++} ++ ++ ++/* ++ * This test verifies that pretty_print_option() will not overrun its ++ * internal, static buffer when given large 'x/X' format options. ++ * ++ */ ++ATF_TC_BODY(pretty_print_option, tc) ++{ ++ struct option *option; ++ unsigned code; ++ unsigned char bad_data[32*1024]; ++ unsigned char good_data[] = { 1,2,3,4,5,6 }; ++ int emit_commas = 1; ++ int emit_quotes = 1; ++ const char *output_buf; ++ ++ /* Initialize whole thing to non-printable chars */ ++ memset(bad_data, 0x1f, sizeof(bad_data)); ++ ++ initialize_common_option_spaces(); ++ ++ /* We'll use dhcp_client_identitifer because it happens to be format X */ ++ code = 61; ++ option = NULL; ++ if (!option_code_hash_lookup(&option, dhcp_universe.code_hash, ++ &code, 0, MDL)) { ++ atf_tc_fail("can't find option %d", code); ++ } ++ ++ if (option == NULL) { ++ atf_tc_fail("option is NULL"); ++ } ++ ++ /* First we will try a good value we know should fit. */ ++ output_buf = pretty_print_option (option, good_data, sizeof(good_data), ++ emit_commas, emit_quotes); ++ ++ /* Make sure we get what we expect */ ++ if (!output_buf || strcmp(output_buf, "1:2:3:4:5:6")) { ++ atf_tc_fail("pretty_print_option did not return \"\""); ++ } ++ ++ ++ /* Now we'll try a data value that's too large */ ++ output_buf = pretty_print_option (option, bad_data, sizeof(bad_data), ++ emit_commas, emit_quotes); ++ ++ /* Make sure we safely get an error */ ++ if (!output_buf || strcmp(output_buf, "")) { ++ atf_tc_fail("pretty_print_option did not return \"\""); ++ } ++} ++ ++ + /* This macro defines main() method that will call specified + test cases. tp and simple_test_case names can be whatever you want + as long as it is a valid variable identifier. */ + ATF_TP_ADD_TCS(tp) + { + ATF_TP_ADD_TC(tp, option_refcnt); ++ ATF_TP_ADD_TC(tp, pretty_print_option); + + return (atf_no_error()); + } +-- +2.16.2 + diff --git a/src/isc-dhcp/patch/series b/src/isc-dhcp/patch/series new file mode 100644 index 000000000000..3e1c15338687 --- /dev/null +++ b/src/isc-dhcp/patch/series @@ -0,0 +1,9 @@ +# This series applies on GIT commit ee3dffdda38a8cfc6ad2005d8d64a165d2a709ba +0001-Customizable-Option-82-circuit-ID-and-remote-ID-fiel.patch +0002-Support-for-obtaining-name-of-physical-interface-tha.patch +0003-Support-for-loading-port-alias-map-file-to-replace-p.patch +0004-Bugfix-Don-t-print-log-messages-to-stderr-in-release.patch +0005-CVE-2017-3144.patch +0006-CVE-2018-5733.patch +0007-CVE-2018-5732.patch + diff --git a/src/ixgbe/Makefile b/src/ixgbe/Makefile new file mode 100644 index 000000000000..90d20e606ef6 --- /dev/null +++ b/src/ixgbe/Makefile @@ -0,0 +1,22 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = ixgbe.ko + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf ./ixgbe-$(IXGBE_DRIVER_VERSION) + wget -O ixgbe-$(IXGBE_DRIVER_VERSION).tar.gz "https://sonicstorage.blob.core.windows.net/packages/ixgbe-5.2.4.tar.gz?sv=2015-04-05&sr=b&sig=AaqJHHaPiJRp8R3HKobi0GNDgHAVnqijk6hpahwJ0Mg%3D&se=2154-10-05T22%3A19%3A29Z&sp=r" + tar xzf ixgbe-$(IXGBE_DRIVER_VERSION).tar.gz + + # Patch + pushd ./ixgbe-$(IXGBE_DRIVER_VERSION) + + # Build the package + pushd src + export BUILD_KERNEL=$(KVERSION) + make + popd + + popd + mv ./ixgbe-$(IXGBE_DRIVER_VERSION)/src/$* $(DEST)/ diff --git a/src/libnl3/Makefile b/src/libnl3/Makefile new file mode 100644 index 000000000000..bf5ba60ab91d --- /dev/null +++ b/src/libnl3/Makefile @@ -0,0 +1,30 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = libnl-3-200_$(LIBNL3_VERSION)_amd64.deb +DERIVED_TARGETS = libnl-3-dev_$(LIBNL3_VERSION)_amd64.deb \ + libnl-genl-3-200_$(LIBNL3_VERSION)_amd64.deb \ + libnl-genl-3-dev_$(LIBNL3_VERSION)_amd64.deb \ + libnl-route-3-200_$(LIBNL3_VERSION)_amd64.deb \ + libnl-route-3-dev_$(LIBNL3_VERSION)_amd64.deb \ + libnl-nf-3-200_$(LIBNL3_VERSION)_amd64.deb \ + libnl-nf-3-dev_$(LIBNL3_VERSION)_amd64.deb \ + libnl-cli-3-200_$(LIBNL3_VERSION)_amd64.deb \ + libnl-cli-3-dev_$(LIBNL3_VERSION)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Obtaining the libnl3 + rm -rf ./libnl3-$(LIBNL3_VERSION_BASE) + wget -O libnl3_$(LIBNL3_VERSION_BASE).orig.tar.gz -N "https://sonicstorage.blob.core.windows.net/packages/libnl3_$(LIBNL3_VERSION_BASE).orig.tar.gz?sv=2015-04-05&sr=b&sig=b4DnqrIsyVBDLmYhw7qwfaUJWqGCX2lDVMmmx7ihfrU%3D&se=2028-06-16T21%3A06%3A00Z&sp=r" + wget -O libnl3_$(LIBNL3_VERSION).dsc -N "https://sonicstorage.blob.core.windows.net/packages/libnl3_$(LIBNL3_VERSION).dsc?sv=2015-04-05&sr=b&sig=AWTX45oDbeGA%2BRJZyiCcHmeIfCAgSeNV3IqopOBaRDg%3D&se=2028-06-16T21%3A05%3A30Z&sp=r" + wget -O libnl3_$(LIBNL3_VERSION).debian.tar.xz -N "https://sonicstorage.blob.core.windows.net/packages/libnl3_$(LIBNL3_VERSION).debian.tar.xz?sv=2015-04-05&sr=b&sig=upIZ9dp5WEcLqp3ODeWKJXq5pJWCfeT0TIM0bx76wxM%3D&se=2028-06-16T21%3A04%3A44Z&sp=r" + dpkg-source -x libnl3_$(LIBNL3_VERSION).dsc + + pushd ./libnl3-$(LIBNL3_VERSION_BASE) + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/libteam/0001-libteam-Add-team_get_port_enabled-function.patch b/src/libteam/0001-libteam-Add-team_get_port_enabled-function.patch new file mode 100644 index 000000000000..9bf08ce61308 --- /dev/null +++ b/src/libteam/0001-libteam-Add-team_get_port_enabled-function.patch @@ -0,0 +1,59 @@ +From 2f9248dd07d51361bc0a93ef70d0f8ac2631af35 Mon Sep 17 00:00:00 2001 +From: Shuotian Cheng +Date: Fri, 20 Jan 2017 12:10:13 -0800 +Subject: [PATCH] libteam: Add team_get_port_enabled function + +--- + include/team.h | 2 ++ + libteam/libteam.c | 22 ++++++++++++++++++++++ + 2 files changed, 24 insertions(+) + +diff --git a/include/team.h b/include/team.h +index 20ebcf6..9ae517d 100644 +--- a/include/team.h ++++ b/include/team.h +@@ -68,6 +68,8 @@ int team_get_bpf_hash_func(struct team_handle *th, struct sock_fprog *fp); + int team_set_bpf_hash_func(struct team_handle *th, const struct sock_fprog *fp); + int team_set_port_enabled(struct team_handle *th, + uint32_t port_ifindex, bool val); ++int team_get_port_enabled(struct team_handle *th, ++ uint32_t port_ifindex, bool *enabled); + int team_set_port_user_linkup_enabled(struct team_handle *th, + uint32_t port_ifindex, bool val); + int team_get_port_user_linkup(struct team_handle *th, +diff --git a/libteam/libteam.c b/libteam/libteam.c +index ac187aa..106e5cf 100644 +--- a/libteam/libteam.c ++++ b/libteam/libteam.c +@@ -1295,6 +1295,28 @@ int team_set_port_enabled(struct team_handle *th, + /** + * @param th libteam library context + * @param port_ifindex port interface index ++ * @param enabled where the enabled state will be stored ++ * ++ * @details Gets enabled state for port identified by port_ifindex ++ * ++ * @return Zero on success or negative number in case of an error. ++ **/ ++TEAM_EXPORT ++int team_get_port_enabled(struct team_handle *th, ++ uint32_t port_ifindex, bool *enabled) ++{ ++ struct team_option *option; ++ ++ option = team_get_option(th, "np", "enabled", port_ifindex); ++ if (!option) ++ return -ENOENT; ++ *enabled = team_get_option_value_bool(option); ++ return 0; ++} ++ ++/** ++ * @param th libteam library context ++ * @param port_ifindex port interface index + * @param val boolean value + * + * @details Enables or disable user linkup for port identified by port_ifindex +-- +2.1.4 + diff --git a/src/libteam/0002-libteam-Temporarily-remove-redundant-debug-mes.patch b/src/libteam/0002-libteam-Temporarily-remove-redundant-debug-mes.patch new file mode 100644 index 000000000000..a640f40e6e07 --- /dev/null +++ b/src/libteam/0002-libteam-Temporarily-remove-redundant-debug-mes.patch @@ -0,0 +1,25 @@ +From a5c8f3f41c575ebb7018e67cb3d1f724f0685850 Mon Sep 17 00:00:00 2001 +From: Shuotian Cheng +Date: Mon, 27 Feb 2017 14:21:09 -0800 +Subject: [PATCH] libteam: Temporarily remove redundant debug messages + +--- + teamd/teamd_runner_lacp.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c +index 9c77fae..5e37a4c 100644 +--- a/teamd/teamd_runner_lacp.c ++++ b/teamd/teamd_runner_lacp.c +@@ -922,8 +922,6 @@ static void lacp_port_actor_update(struct lacp_port *lacp_port) + state |= INFO_STATE_DEFAULTED; + if (teamd_port_count(lacp_port->ctx) > 0) + state |= INFO_STATE_AGGREGATION; +- teamd_log_dbg("%s: lacp info state: 0x%02X.", lacp_port->tdport->ifname, +- state); + lacp_port->actor.state = state; + } + +-- +2.1.4 + diff --git a/src/libteam/0003-teamd-lacp-runner-will-send-lacp-update-right-after-.patch b/src/libteam/0003-teamd-lacp-runner-will-send-lacp-update-right-after-.patch new file mode 100644 index 000000000000..1cae8bad21aa --- /dev/null +++ b/src/libteam/0003-teamd-lacp-runner-will-send-lacp-update-right-after-.patch @@ -0,0 +1,98 @@ +From 417e9dfdccbbee2cf86e46e994e8ece3433b46a4 Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Wed, 20 Sep 2017 00:34:07 +0000 +Subject: [PATCH] [teamd] lacp runner will send lacp update right after it + received SIGINT signal + +--- + teamd/teamd.c | 1 + + teamd/teamd.h | 3 +++ + teamd/teamd_events.c | 13 +++++++++++++ + teamd/teamd_runner_lacp.c | 10 ++++++++++ + 4 files changed, 27 insertions(+) + +diff --git a/teamd/teamd.c b/teamd/teamd.c +index aac2511..c987333 100644 +--- a/teamd/teamd.c ++++ b/teamd/teamd.c +@@ -386,6 +386,7 @@ static int teamd_run_loop_run(struct teamd_context *ctx) + case 'q': + if (quit_in_progress) + return -EBUSY; ++ teamd_refresh_ports(ctx); + err = teamd_flush_ports(ctx); + if (err) + return err; +diff --git a/teamd/teamd.h b/teamd/teamd.h +index 5dbfb9b..ef0fb1c 100644 +--- a/teamd/teamd.h ++++ b/teamd/teamd.h +@@ -189,11 +189,14 @@ struct teamd_event_watch_ops { + struct teamd_port *tdport, void *priv); + int (*port_ifname_changed)(struct teamd_context *ctx, + struct teamd_port *tdport, void *priv); ++ void (*refresh)(struct teamd_context *ctx, ++ struct teamd_port *tdport, void *priv); + int (*option_changed)(struct teamd_context *ctx, + struct team_option *option, void *priv); + char *option_changed_match_name; + }; + ++void teamd_refresh_ports(struct teamd_context *ctx); + int teamd_event_port_added(struct teamd_context *ctx, + struct teamd_port *tdport); + void teamd_event_port_removed(struct teamd_context *ctx, +diff --git a/teamd/teamd_events.c b/teamd/teamd_events.c +index 1a95974..5c2ef56 100644 +--- a/teamd/teamd_events.c ++++ b/teamd/teamd_events.c +@@ -34,6 +34,19 @@ struct event_watch_item { + void *priv; + }; + ++void teamd_refresh_ports(struct teamd_context *ctx) ++{ ++ struct teamd_port *tdport; ++ struct event_watch_item *watch; ++ ++ teamd_for_each_tdport(tdport, ctx) { ++ list_for_each_node_entry(watch, &ctx->event_watch_list, list) { ++ if (!watch->ops->refresh) continue; ++ watch->ops->refresh(ctx, tdport, watch->priv); ++ } ++ } ++} ++ + int teamd_event_port_added(struct teamd_context *ctx, + struct teamd_port *tdport) + { +diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c +index 9c77fae..e38c291 100644 +--- a/teamd/teamd_runner_lacp.c ++++ b/teamd/teamd_runner_lacp.c +@@ -1383,12 +1383,22 @@ static int lacp_event_watch_port_changed(struct teamd_context *ctx, + return lacp_port_link_update(lacp_port); + } + ++static void lacp_event_watch_refresh(struct teamd_context *ctx, struct teamd_port *tdport, void *priv) ++{ ++ struct lacp *lacp = priv; ++ ++ struct lacp_port *lacp_port = lacp_port_get(lacp, tdport); ++ if (lacp_port_selected(lacp_port)) ++ (void) lacpdu_send(lacp_port); ++} ++ + static const struct teamd_event_watch_ops lacp_event_watch_ops = { + .hwaddr_changed = lacp_event_watch_hwaddr_changed, + .port_added = lacp_event_watch_port_added, + .port_removed = lacp_event_watch_port_removed, + .port_changed = lacp_event_watch_port_changed, + .admin_state_changed = lacp_event_watch_admin_state_changed, ++ .refresh = lacp_event_watch_refresh, + }; + + static int lacp_carrier_init(struct teamd_context *ctx, struct lacp *lacp) +-- +2.7.4 + diff --git a/src/libteam/0004-libteam-Add-lacp-fallback-support-for-single-member-.patch b/src/libteam/0004-libteam-Add-lacp-fallback-support-for-single-member-.patch new file mode 100644 index 000000000000..3139f83f33a4 --- /dev/null +++ b/src/libteam/0004-libteam-Add-lacp-fallback-support-for-single-member-.patch @@ -0,0 +1,104 @@ +From ec966f9a0229bd7226e3abe15b56659b36af9d66 Mon Sep 17 00:00:00 2001 +From: Haiyang Zheng +Date: Fri, 15 Dec 2017 21:07:53 -0800 +Subject: [patch libteam] [libteam] Add fallback support for single-member-port + LAG + +Signed-off-by: Haiyang Zheng +--- + teamd/teamd_runner_lacp.c | 42 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 40 insertions(+), 2 deletions(-) + +diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c +index 9c77fae..a3646a6 100644 +--- a/teamd/teamd_runner_lacp.c ++++ b/teamd/teamd_runner_lacp.c +@@ -138,6 +138,8 @@ struct lacp { + #define LACP_CFG_DFLT_SYS_PRIO 0xffff + bool fast_rate; + #define LACP_CFG_DFLT_FAST_RATE false ++ bool fallback; ++#define LACP_CFG_DFLT_FALLBACK false + int min_ports; + #define LACP_CFG_DFLT_MIN_PORTS 1 + enum lacp_agg_select_policy agg_select_policy; +@@ -272,6 +274,11 @@ static int lacp_load_config(struct teamd_context *ctx, struct lacp *lacp) + lacp->cfg.fast_rate = LACP_CFG_DFLT_FAST_RATE; + teamd_log_dbg("Using fast_rate \"%d\".", lacp->cfg.fast_rate); + ++ err = teamd_config_bool_get(ctx, &lacp->cfg.fallback, "$.runner.fallback"); ++ if (err) ++ lacp->cfg.fallback = LACP_CFG_DFLT_FALLBACK; ++ teamd_log_dbg("Using fallback \"%d\".", lacp->cfg.fallback); ++ + err = teamd_config_int_get(ctx, &tmp, "$.runner.min_ports"); + if (err) { + lacp->cfg.min_ports = LACP_CFG_DFLT_MIN_PORTS; +@@ -308,9 +315,24 @@ static bool lacp_port_loopback_free(struct lacp_port *lacp_port) + return true; + } + ++/* ++ * is_lacp_fallback_eligible - is lacp_port eligible to go into lacp fallback mode ++ * ++ * Return true if it is, false otherwise ++ */ ++static bool is_lacp_fallback_eligible(struct lacp_port *lacp_port) ++{ ++ teamd_log_dbg("%s fallback eligible state \"%d \" cfg \"%d\".", ++ lacp_port->tdport->ifname, lacp_port->state, ++ lacp_port->lacp->cfg.fallback); ++ return lacp_port->state == PORT_STATE_DEFAULTED && ++ lacp_port->lacp->cfg.fallback; ++} ++ + static bool lacp_port_selectable_state(struct lacp_port *lacp_port) + { +- if (lacp_port->state == PORT_STATE_CURRENT) ++ if (lacp_port->state == PORT_STATE_CURRENT || ++ is_lacp_fallback_eligible(lacp_port)) + return true; + return false; + } +@@ -318,7 +340,8 @@ static bool lacp_port_selectable_state(struct lacp_port *lacp_port) + static bool lacp_port_unselectable_state(struct lacp_port *lacp_port) + { + if (lacp_port->state == PORT_STATE_CURRENT || +- lacp_port->state == PORT_STATE_EXPIRED) ++ lacp_port->state == PORT_STATE_EXPIRED || ++ is_lacp_fallback_eligible(lacp_port)) + return false; + return true; + } +@@ -1452,6 +1475,16 @@ static int lacp_state_fast_rate_get(struct teamd_context *ctx, + return 0; + } + ++static int lacp_state_fallback_get(struct teamd_context *ctx, ++ struct team_state_gsc *gsc, ++ void *priv) ++{ ++ struct lacp *lacp = priv; ++ ++ gsc->data.bool_val = lacp->cfg.fallback; ++ return 0; ++} ++ + static int lacp_state_select_policy_get(struct teamd_context *ctx, + struct team_state_gsc *gsc, + void *priv) +@@ -1479,6 +1512,11 @@ static const struct teamd_state_val lacp_state_vals[] = { + .getter = lacp_state_fast_rate_get, + }, + { ++ .subpath = "fallback", ++ .type = TEAMD_STATE_ITEM_TYPE_BOOL, ++ .getter = lacp_state_fallback_get, ++ }, ++ { + .subpath = "select_policy", + .type = TEAMD_STATE_ITEM_TYPE_STRING, + .getter = lacp_state_select_policy_get, +-- +2.7.4 + diff --git a/src/libteam/0005-libteam-Add-warm_reboot-mode.patch b/src/libteam/0005-libteam-Add-warm_reboot-mode.patch new file mode 100644 index 000000000000..625af96eaa16 --- /dev/null +++ b/src/libteam/0005-libteam-Add-warm_reboot-mode.patch @@ -0,0 +1,533 @@ +diff --git a/libteam/ifinfo.c b/libteam/ifinfo.c +index 72155ae..44de4ca 100644 +--- a/libteam/ifinfo.c ++++ b/libteam/ifinfo.c +@@ -105,15 +105,13 @@ static void update_hwaddr(struct team_ifinfo *ifinfo, struct rtnl_link *link) + hwaddr_len = nl_addr_get_len(nl_addr); + if (ifinfo->hwaddr_len != hwaddr_len) { + ifinfo->hwaddr_len = hwaddr_len; +- if (!ifinfo->master_ifindex) +- ifinfo->orig_hwaddr_len = hwaddr_len; ++ ifinfo->orig_hwaddr_len = hwaddr_len; + set_changed(ifinfo, CHANGED_HWADDR_LEN); + } + hwaddr = nl_addr_get_binary_addr(nl_addr); + if (memcmp(ifinfo->hwaddr, hwaddr, hwaddr_len)) { + memcpy(ifinfo->hwaddr, hwaddr, hwaddr_len); +- if (!ifinfo->master_ifindex) +- memcpy(ifinfo->orig_hwaddr, hwaddr, hwaddr_len); ++ memcpy(ifinfo->orig_hwaddr, hwaddr, hwaddr_len); + set_changed(ifinfo, CHANGED_HWADDR); + } + } +diff --git a/teamd/teamd.c b/teamd/teamd.c +index c987333..225b8c8 100644 +--- a/teamd/teamd.c ++++ b/teamd/teamd.c +@@ -116,7 +116,9 @@ static void print_help(const struct teamd_context *ctx) { + " -D --dbus-enable Enable D-Bus interface\n" + " -Z --zmq-enable=ADDRESS Enable ZeroMQ interface\n" + " -U --usock-enable Enable UNIX domain socket interface\n" +- " -u --usock-disable Disable UNIX domain socket interface\n", ++ " -u --usock-disable Disable UNIX domain socket interface\n" ++ " -w --warm-start Warm-start startup mode\n" ++ " -L --lacp-directory Directory for saving lacp pdu dumps\n", + ctx->argv0); + printf("Available runners: "); + for (i = 0; i < TEAMD_RUNNER_LIST_SIZE; i++) { +@@ -129,7 +131,7 @@ static void print_help(const struct teamd_context *ctx) { + + static int parse_command_line(struct teamd_context *ctx, + int argc, char *argv[]) { +- int opt; ++ int opt, err; + static const struct option long_options[] = { + { "help", no_argument, NULL, 'h' }, + { "daemonize", no_argument, NULL, 'd' }, +@@ -149,10 +151,12 @@ static int parse_command_line(struct teamd_context *ctx, + { "zmq-enable", required_argument, NULL, 'Z' }, + { "usock-enable", no_argument, NULL, 'U' }, + { "usock-disable", no_argument, NULL, 'u' }, ++ { "warm-start", no_argument, NULL, 'w' }, ++ { "lacp-directory", required_argument, NULL, 'L' }, + { NULL, 0, NULL, 0 } + }; + +- while ((opt = getopt_long(argc, argv, "hdkevf:c:p:groNt:nDZ:Uu", ++ while ((opt = getopt_long(argc, argv, "hdkevf:c:p:groNt:nDZ:UuwL:", + long_options, NULL)) >= 0) { + + switch(opt) { +@@ -230,11 +234,29 @@ static int parse_command_line(struct teamd_context *ctx, + case 'u': + ctx->usock.enabled = false; + break; ++ case 'w': ++ ctx->warm_start_read = true; ++ ctx->warm_start_carrier = true; ++ break; ++ case 'L': ++ ctx->lacp_directory = strdup(optarg); ++ if (access(ctx->lacp_directory, R_OK | W_OK | X_OK) != 0) { ++ fprintf(stderr, "Can't write to the lacp directory '%s': %s\n", ctx->lacp_directory, strerror(errno)); ++ free(ctx->lacp_directory); ++ ctx->lacp_directory = NULL; ++ } ++ break; + default: + return -1; + } + } + ++ if (ctx->warm_start_read && !ctx->lacp_directory) { ++ fprintf(stderr, "Can't enable warm-start mode without lacp-directory specified\n"); ++ ctx->warm_start_read = false; ++ ctx->warm_start_carrier = false; ++ } ++ + if (optind < argc) { + fprintf(stderr, "Too many arguments\n"); + return -1; +@@ -384,8 +406,14 @@ static int teamd_run_loop_run(struct teamd_context *ctx) + if (err != -1) { + switch(ctrl_byte) { + case 'q': ++ case 'w': + if (quit_in_progress) + return -EBUSY; ++ if (ctrl_byte == 'w') { ++ ctx->keep_ports = true; ++ ctx->no_quit_destroy = true; ++ teamd_ports_flush_data(ctx); ++ } + teamd_refresh_ports(ctx); + err = teamd_flush_ports(ctx); + if (err) +@@ -428,6 +456,12 @@ void teamd_run_loop_quit(struct teamd_context *ctx, int err) + teamd_run_loop_sent_ctrl_byte(ctx, 'q'); + } + ++static void teamd_run_loop_quit_w_boot(struct teamd_context *ctx, int err) ++{ ++ ctx->run_loop.err = err; ++ teamd_run_loop_sent_ctrl_byte(ctx, 'w'); ++} ++ + void teamd_run_loop_restart(struct teamd_context *ctx) + { + teamd_run_loop_sent_ctrl_byte(ctx, 'r'); +@@ -694,6 +728,10 @@ static int callback_daemon_signal(struct teamd_context *ctx, int events, + teamd_log_warn("Got SIGINT, SIGQUIT or SIGTERM."); + teamd_run_loop_quit(ctx, 0); + break; ++ case SIGUSR1: ++ teamd_log_warn("Got SIGUSR1."); ++ teamd_run_loop_quit_w_boot(ctx, 0); ++ break; + } + return 0; + } +@@ -1507,7 +1545,7 @@ static int teamd_start(struct teamd_context *ctx, enum teamd_exit_code *p_ret) + return -errno; + } + +- if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, 0) < 0) { ++ if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGUSR1, 0) < 0) { + teamd_log_err("Could not register signal handlers."); + daemon_retval_send(errno); + err = -errno; +diff --git a/teamd/teamd.h b/teamd/teamd.h +index ef0fb1c..622c365 100644 +--- a/teamd/teamd.h ++++ b/teamd/teamd.h +@@ -125,6 +125,10 @@ struct teamd_context { + char * hwaddr; + uint32_t hwaddr_len; + bool hwaddr_explicit; ++ bool warm_start_read; ++ bool warm_start_carrier; ++ bool keep_ports; ++ char * lacp_directory; + struct { + struct list_item callback_list; + int ctrl_pipe_r; +@@ -191,12 +195,15 @@ struct teamd_event_watch_ops { + struct teamd_port *tdport, void *priv); + void (*refresh)(struct teamd_context *ctx, + struct teamd_port *tdport, void *priv); ++ void (*port_flush_data)(struct teamd_context *ctx, ++ struct teamd_port *tdport, void *priv); + int (*option_changed)(struct teamd_context *ctx, + struct team_option *option, void *priv); + char *option_changed_match_name; + }; + + void teamd_refresh_ports(struct teamd_context *ctx); ++void teamd_ports_flush_data(struct teamd_context *ctx); + int teamd_event_port_added(struct teamd_context *ctx, + struct teamd_port *tdport); + void teamd_event_port_removed(struct teamd_context *ctx, +diff --git a/teamd/teamd_events.c b/teamd/teamd_events.c +index 5c2ef56..50e5a08 100644 +--- a/teamd/teamd_events.c ++++ b/teamd/teamd_events.c +@@ -47,6 +47,19 @@ void teamd_refresh_ports(struct teamd_context *ctx) + } + } + ++void teamd_ports_flush_data(struct teamd_context *ctx) ++{ ++ struct teamd_port *tdport; ++ struct event_watch_item *watch; ++ ++ teamd_for_each_tdport(tdport, ctx) { ++ list_for_each_node_entry(watch, &ctx->event_watch_list, list) { ++ if (!watch->ops->port_flush_data) continue; ++ watch->ops->port_flush_data(ctx, tdport, watch->priv); ++ } ++ } ++} ++ + int teamd_event_port_added(struct teamd_context *ctx, + struct teamd_port *tdport) + { +diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c +index 81324de..9e88ce0 100644 +--- a/teamd/teamd_runner_lacp.c ++++ b/teamd/teamd_runner_lacp.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #include "teamd.h" + #include "teamd_config.h" +@@ -131,6 +132,7 @@ struct lacp { + struct teamd_context *ctx; + struct lacp_port *selected_agg_lead; /* leading port of selected aggregator */ + bool carrier_up; ++ time_t warm_start_carrier_timer; + struct { + bool active; + #define LACP_CFG_DFLT_ACTIVE true +@@ -174,6 +176,9 @@ struct lacp_port { + struct lacp_port *agg_lead; /* leading port of aggregator. + * NULL in case this port is not selected */ + enum lacp_port_state state; ++ bool lacpdu_saved; ++ bool lacpdu_read; ++ struct lacpdu last_pdu; + struct { + uint32_t speed; + uint8_t duplex; +@@ -491,15 +496,28 @@ static int lacp_update_carrier(struct lacp *lacp) + bool state; + int err; + ++ #define WARM_START_CARRIER_TIMEOUT 3 ++ /* wait three seconds until disable warm_start_carrier mode */ ++ if (lacp->ctx->warm_start_carrier && ++ lacp->warm_start_carrier_timer >= (time(NULL) + WARM_START_CARRIER_TIMEOUT)) { ++ lacp->ctx->warm_start_carrier = false; ++ lacp->warm_start_carrier_timer = 0; ++ } ++ + ports_enabled = 0; + teamd_for_each_tdport(tdport, lacp->ctx) { + err = teamd_port_enabled(lacp->ctx, tdport, &state); + if (err) + return err; +- if (state && ++ports_enabled >= lacp->cfg.min_ports) ++ if (state && ++ports_enabled >= lacp->cfg.min_ports) { ++ lacp->ctx->warm_start_carrier = false; + return lacp_set_carrier(lacp, true); ++ } + } + ++ if (lacp->ctx->warm_start_carrier) ++ return 0; /* Don't put carrier down if we're in warm_start_carrier mode */ ++ + return lacp_set_carrier(lacp, false); + } + +@@ -917,6 +935,18 @@ static void lacp_port_actor_system_update(struct lacp_port *lacp_port) + memcpy(actor->system, lacp_port->ctx->hwaddr, ETH_ALEN); + } + ++static int lacp_portname_to_port_id(const char* name) ++{ ++#define PORT_PREFIX "Ethernet" ++ const char* strport_id = name + sizeof(PORT_PREFIX) - 1; ++ const int port_id = atoi(strport_id); ++ if ((port_id == 0) && strcmp(strport_id, "0")) { ++ teamd_log_err("%s: Can't convert from port name to port id. Port id is equal to 0, but this is not expected", name); ++ } ++ ++ return htons(port_id + 1); ++} ++ + static void lacp_port_actor_init(struct lacp_port *lacp_port) + { + struct lacpdu_info *actor = &lacp_port->actor; +@@ -924,7 +954,7 @@ static void lacp_port_actor_init(struct lacp_port *lacp_port) + actor->system_priority = htons(lacp_port->lacp->cfg.sys_prio); + actor->key = htons(lacp_port->cfg.lacp_key); + actor->port_priority = htons(lacp_port->cfg.lacp_prio); +- actor->port = htons(lacp_port->tdport->ifindex); ++ actor->port = lacp_portname_to_port_id(lacp_port->tdport->ifname); + lacp_port_actor_system_update(lacp_port); + } + +@@ -994,6 +1024,13 @@ static int lacp_port_set_state(struct lacp_port *lacp_port, + break; + } + ++ if (new_state != PORT_STATE_CURRENT) { ++ /* clean saved lacp pdu up when the current port: ++ disabled, expired, or defaulted */ ++ (void)memset(&lacp_port->last_pdu, 0, sizeof(struct lacpdu)); ++ lacp_port->lacpdu_saved = false; ++ } ++ + teamd_log_info("%s: Changed port state: \"%s\" -> \"%s\"", + lacp_port->tdport->ifname, + lacp_port_state_name[lacp_port->state], +@@ -1084,26 +1121,23 @@ static int lacpdu_send(struct lacp_port *lacp_port) + return err; + } + +-static int lacpdu_recv(struct lacp_port *lacp_port) ++static int lacpdu_process(struct lacp_port *lacp_port, struct lacpdu* lacpdu) + { +- struct lacpdu lacpdu; +- struct sockaddr_ll ll_from; + int err; + +- err = teamd_recvfrom(lacp_port->sock, &lacpdu, sizeof(lacpdu), 0, +- (struct sockaddr *) &ll_from, sizeof(ll_from)); +- if (err <= 0) +- return err; +- +- if (!lacpdu_check(&lacpdu)) { ++ if (!lacpdu_check(lacpdu)) { + teamd_log_warn("malformed LACP PDU came."); + return 0; + } + ++ /* save received lacp pdu frame */ ++ (void)memcpy(&lacp_port->last_pdu, lacpdu, sizeof(struct lacpdu)); ++ lacp_port->lacpdu_saved = true; ++ + /* Check if we have correct info about the other side */ +- if (memcmp(&lacpdu.actor, &lacp_port->partner, ++ if (memcmp(&lacpdu->actor, &lacp_port->partner, + sizeof(struct lacpdu_info))) { +- lacp_port->partner = lacpdu.actor; ++ lacp_port->partner = lacpdu->actor; + err = lacp_port_partner_update(lacp_port); + if (err) + return err; +@@ -1118,7 +1152,7 @@ static int lacpdu_recv(struct lacp_port *lacp_port) + + /* Check if the other side has correct info about us */ + if (!lacp_port->periodic_on && +- memcmp(&lacpdu.partner, &lacp_port->actor, ++ memcmp(&lacpdu->partner, &lacp_port->actor, + sizeof(struct lacpdu_info))) { + err = lacpdu_send(lacp_port); + if (err) +@@ -1133,6 +1167,65 @@ static int lacpdu_recv(struct lacp_port *lacp_port) + return 0; + } + ++static int lacpdu_recv(struct lacp_port *lacp_port) ++{ ++ struct lacpdu lacpdu; ++ struct sockaddr_ll ll_from; ++ int err; ++ ++ err = teamd_recvfrom(lacp_port->sock, &lacpdu, sizeof(lacpdu), 0, ++ (struct sockaddr *) &ll_from, sizeof(ll_from)); ++ if (err <= 0) ++ return err; ++ ++ return lacpdu_process(lacp_port, &lacpdu); ++} ++ ++static int lacpdu_read(struct lacp_port *lacp_port) ++{ ++ FILE* fp; ++ char filename[PATH_MAX]; ++ struct lacpdu lacpdu; ++ int err, nitems; ++ struct teamd_port *tdport; ++ ++ /* we read saved lacpdu for the current lacp_port */ ++ lacp_port->lacpdu_read = true; ++ ++ strcpy(filename, lacp_port->ctx->lacp_directory); ++ if (filename[strlen(filename) - 1] != '/') ++ strcat(filename, "/"); /* Add trailing slash if we don't have one in the filename */ ++ strcat(filename, lacp_port->tdport->ifname); ++ ++ /* check that file is readable. if there is no file, don't do anything */ ++ if (access(filename, R_OK) != 0) { ++ return 0; ++ } ++ ++ fp = fopen(filename, "r"); ++ if (!fp) { ++ teamd_log_err("Can't open lacp-saved dump from file %s: %s", filename, strerror(errno)); ++ return errno; ++ } ++ ++ nitems = fread(&lacpdu, sizeof(struct lacpdu), 1, fp); ++ (void)fclose(fp); ++ ++ err = unlink(filename); ++ if (err < 0) { ++ teamd_log_err("Can't remove file %s: %s", filename, strerror(errno)); ++ } ++ ++ if (nitems != 1) { ++ teamd_log_err("Can't read lacp-saved dump from file %s: %s", filename, strerror(errno)); ++ return err; ++ } ++ ++ teamd_log_info("%s: LACP state was read", lacp_port->tdport->ifname); ++ ++ return lacpdu_process(lacp_port, &lacpdu); ++} ++ + static int lacp_callback_timeout(struct teamd_context *ctx, int events, + void *priv) + { +@@ -1284,6 +1377,13 @@ static int lacp_port_added(struct teamd_context *ctx, + goto periodic_callback_del; + } + ++ /* refresh ports from the kernel */ ++ err = team_refresh(ctx->th); ++ if (err) { ++ teamd_log_err("%s: Team refresh failed.", tdport->ifname); ++ goto timeout_callback_del; ++ } ++ + /* Newly added ports are disabled */ + err = team_set_port_enabled(ctx->th, tdport->ifindex, false); + if (err) { +@@ -1299,6 +1399,13 @@ static int lacp_port_added(struct teamd_context *ctx, + lacp_port_actor_init(lacp_port); + lacp_port_link_update(lacp_port); + ++ /* Read data from file and process it */ ++ if (ctx->warm_start_read) { ++ err = lacpdu_read(lacp_port); ++ if (err) ++ goto timeout_callback_del; ++ } ++ + teamd_loop_callback_enable(ctx, LACP_SOCKET_CB_NAME, lacp_port); + return 0; + +@@ -1321,7 +1428,11 @@ static void lacp_port_removed(struct teamd_context *ctx, + { + struct lacp_port *lacp_port = priv; + +- lacp_port_set_state(lacp_port, PORT_STATE_DISABLED); ++ if (!lacp_port->ctx->keep_ports) { ++ /* Don't transition into DISABLED state, ++ which sends EXPIRED LACP PDU update */ ++ lacp_port_set_state(lacp_port, PORT_STATE_DISABLED); ++ } + teamd_loop_callback_del(ctx, LACP_TIMEOUT_CB_NAME, lacp_port); + teamd_loop_callback_del(ctx, LACP_PERIODIC_CB_NAME, lacp_port); + teamd_loop_callback_del(ctx, LACP_SOCKET_CB_NAME, lacp_port); +@@ -1413,6 +1524,31 @@ static void lacp_event_watch_refresh(struct teamd_context *ctx, struct teamd_por + (void) lacpdu_send(lacp_port); + } + ++static void lacp_event_watch_port_flush_data(struct teamd_context *ctx, struct teamd_port *tdport, void *priv) ++{ ++ struct lacp *lacp = priv; ++ ++ struct lacp_port *lacp_port = lacp_port_get(lacp, tdport); ++ if (lacp_port->lacpdu_saved && lacp_port->ctx->lacp_directory) { ++ char filename[PATH_MAX]; ++ strcpy(filename, lacp_port->ctx->lacp_directory); ++ if (filename[strlen(filename) - 1] != '/') ++ strcat(filename, "/"); /* Add trailing slash if we don't have one in the filename */ ++ strcat(filename, lacp_port->tdport->ifname); ++ FILE *fp = fopen(filename, "wb"); ++ if (fp != NULL) { ++ (void)fwrite(&lacp_port->last_pdu, sizeof(struct lacpdu), 1, fp); ++ (void)fclose(fp); ++ } else { ++ teamd_log_err("Can't open file %s for writing %s", filename, strerror(errno)); ++ } ++ } else { ++ teamd_log_err("Can't dump received lacp pdu for port %s. " ++ "Either it wasn't received, or directory to save wasn't configured", ++ lacp_port->tdport->ifname); ++ } ++} ++ + static const struct teamd_event_watch_ops lacp_event_watch_ops = { + .hwaddr_changed = lacp_event_watch_hwaddr_changed, + .port_added = lacp_event_watch_port_added, +@@ -1420,21 +1556,38 @@ static const struct teamd_event_watch_ops lacp_event_watch_ops = { + .port_changed = lacp_event_watch_port_changed, + .admin_state_changed = lacp_event_watch_admin_state_changed, + .refresh = lacp_event_watch_refresh, ++ .port_flush_data = lacp_event_watch_port_flush_data, + }; + + static int lacp_carrier_init(struct teamd_context *ctx, struct lacp *lacp) + { + int err; + +- /* initialize carrier control */ +- err = team_carrier_set(ctx->th, false); +- if (err && err != -EOPNOTSUPP) { +- teamd_log_err("Failed to set carrier down."); +- return err; ++ if (ctx->warm_start_carrier) { ++ /* Read the current carrier state, don't change it */ ++ bool state; ++ err = team_carrier_get(ctx->th, &state); ++ if (err && err != -EOPNOTSUPP) { ++ teamd_log_err("Failed to read carrier."); ++ return err; ++ } ++ lacp->carrier_up = state; ++ if (state) { ++ /* enable timer for warm_start_carrier mode */ ++ lacp->warm_start_carrier_timer = time(NULL); ++ } else { ++ /* disable warm_start_carrier mode. The LAG interface is already down. */ ++ ctx->warm_start_carrier = false; ++ } ++ } else { ++ err = team_carrier_set(ctx->th, false); ++ if (err && err != -EOPNOTSUPP) { ++ teamd_log_err("Failed to set carrier down."); ++ return err; ++ } ++ lacp->carrier_up = false; + } + +- lacp->carrier_up = false; +- + return 0; + } + +@@ -1946,7 +2099,7 @@ static void lacp_fini(struct teamd_context *ctx, void *priv) + teamd_state_val_unregister(ctx, &lacp_state_vg, lacp); + teamd_balancer_fini(lacp->tb); + teamd_event_watch_unregister(ctx, &lacp_event_watch_ops, lacp); +- lacp_carrier_fini(ctx, lacp); ++ if (!ctx->keep_ports) lacp_carrier_fini(ctx, lacp); + } + + const struct teamd_runner teamd_runner_lacp = { diff --git a/src/libteam/Makefile b/src/libteam/Makefile new file mode 100644 index 000000000000..50ad002c50c6 --- /dev/null +++ b/src/libteam/Makefile @@ -0,0 +1,39 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = libteam5_$(LIBTEAM_VERSION)_amd64.deb +DERIVED_TARGETS = libteam-dev_$(LIBTEAM_VERSION)_amd64.deb \ + libteamdctl0_$(LIBTEAM_VERSION)_amd64.deb \ + libteam-utils_$(LIBTEAM_VERSION)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Obtain libteam + rm -rf ./libteam + git clone https://github.com/jpirko/libteam.git + pushd ./libteam + git checkout -f v1.26 + + # Apply patch + git apply ../0001-libteam-Add-team_get_port_enabled-function.patch + git apply ../0002-libteam-Temporarily-remove-redundant-debug-mes.patch + git apply ../0003-teamd-lacp-runner-will-send-lacp-update-right-after-.patch + git apply ../0004-libteam-Add-lacp-fallback-support-for-single-member-.patch + git apply ../0005-libteam-Add-warm_reboot-mode.patch + popd + + # Obtain debian packaging + git clone https://salsa.debian.org/debian/libteam.git tmp + pushd ./tmp + git checkout -f da006f2 # v1.26 + popd + + mv tmp/debian libteam/ + rm -rf tmp + pushd ./libteam + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/lldpd/Makefile b/src/lldpd/Makefile new file mode 100644 index 000000000000..5f502b86863c --- /dev/null +++ b/src/lldpd/Makefile @@ -0,0 +1,32 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = $(LLDPD) +DERIVED_TARGETS = $(LIBLLDPCTL) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf ./lldpd + + # Clone lldpd repo + git clone https://github.com/vincentbernat/lldpd.git + pushd ./lldpd + + # Reset HEAD to the commit of the proper tag + # NOTE: Using "git checkout " here detaches our HEAD, + # which stg doesn't like, so we use this method instead + git reset --hard $(LLDPD_VERSION) + + # Apply patches + stg init + stg import -s ../patch/series + + # Build source and Debian packages + env "with_netlink_receive_bufsize=1024*1024" dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + # Move the newly-built .deb packages to the destination directory + mv $* $(DERIVED_TARGETS) $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/lldpd/patch/0001-return-error-when-port-does-not-exist.patch b/src/lldpd/patch/0001-return-error-when-port-does-not-exist.patch new file mode 100644 index 000000000000..e17d09a386d4 --- /dev/null +++ b/src/lldpd/patch/0001-return-error-when-port-does-not-exist.patch @@ -0,0 +1,39 @@ +From 15e692fb82a61203624829cdd872315211920077 Mon Sep 17 00:00:00 2001 +From: Guohan Lu +Date: Tue, 6 Mar 2018 09:36:51 +0000 +Subject: [PATCH] return error when port does not exist + +--- + src/client/conf-lldp.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/client/conf-lldp.c b/src/client/conf-lldp.c +index c16219b..b51e4eb 100644 +--- a/src/client/conf-lldp.c ++++ b/src/client/conf-lldp.c +@@ -148,6 +148,8 @@ cmd_portid_type_local(struct lldpctl_conn_t *conn, struct writer *w, + const char *name; + const char *id = cmdenv_get(env, "port-id"); + const char *descr = cmdenv_get(env, "port-descr"); ++ const char *portname = cmdenv_get(env, "ports"); ++ int find_port = 0; + + log_debug("lldpctl", "lldp PortID TLV Subtype Local port-id '%s' port-descr '%s'", id, descr); + +@@ -165,6 +167,12 @@ cmd_portid_type_local(struct lldpctl_conn_t *conn, struct writer *w, + log_warnx("lldpctl", "unable to set LLDP Port Description for %s." + " %s", name, lldpctl_last_strerror(conn)); + } ++ find_port = 1; ++ } ++ ++ if (!find_port) { ++ log_warnx("lldpctl", "cannot find port %s", portname); ++ return 0; + } + + return 1; +-- +2.7.4 + + diff --git a/src/lldpd/patch/0002-Let-linux-kernel-to-find-appropriate-nl_pid-automa.patch b/src/lldpd/patch/0002-Let-linux-kernel-to-find-appropriate-nl_pid-automa.patch new file mode 100644 index 000000000000..801fdd8ec96e --- /dev/null +++ b/src/lldpd/patch/0002-Let-linux-kernel-to-find-appropriate-nl_pid-automa.patch @@ -0,0 +1,25 @@ +From 2ee8585e8b716719a11235ab5c291b2f6ac9ce1a Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Wed, 17 Oct 2018 21:05:58 +0000 +Subject: [PATCH] Let linux kernel to find appropriate nl_pid automatically + +--- + src/daemon/netlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/daemon/netlink.c b/src/daemon/netlink.c +index 1a64a23..f4227b8 100644 +--- a/src/daemon/netlink.c ++++ b/src/daemon/netlink.c +@@ -93,7 +93,7 @@ netlink_connect(struct lldpd *cfg, int protocol, unsigned groups) + int s; + struct sockaddr_nl local = { + .nl_family = AF_NETLINK, +- .nl_pid = getpid(), ++ .nl_pid = 0, + .nl_groups = groups + }; + +-- +2.7.4 + diff --git a/src/lldpd/patch/series b/src/lldpd/patch/series new file mode 100644 index 000000000000..2ca46b575396 --- /dev/null +++ b/src/lldpd/patch/series @@ -0,0 +1,3 @@ +# This series applies on GIT commit 396961a038a38675d46f96eaa7b430b2a1f8701b +0001-return-error-when-port-does-not-exist.patch +0002-Let-linux-kernel-to-find-appropriate-nl_pid-automa.patch diff --git a/src/mpdecimal/Makefile b/src/mpdecimal/Makefile new file mode 100644 index 000000000000..5603c44b445f --- /dev/null +++ b/src/mpdecimal/Makefile @@ -0,0 +1,22 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = libmpdec2_$(MPDECIMAL_VERSION_FULL)_amd64.deb +DERIVED_TARGETS = libmpdec-dev_$(MPDECIMAL_VERSION_FULL)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf mpdecimal-$(MPDECIMAL_VERSION) + + wget -N -O mpdecimal_$(MPDECIMAL_VERSION).orig.tar.gz http://http.debian.net/debian/pool/main/m/mpdecimal/mpdecimal_$(MPDECIMAL_VERSION).orig.tar.gz + wget -N -O mpdecimal_$(MPDECIMAL_VERSION_FULL).debian.tar.xz http://http.debian.net/debian/pool/main/m/mpdecimal/mpdecimal_$(MPDECIMAL_VERSION_FULL).debian.tar.xz + wget -N -O mpdecimal_$(MPDECIMAL_VERSION_FULL).dsc http://http.debian.net/debian/pool/main/m/mpdecimal/mpdecimal_$(MPDECIMAL_VERSION_FULL).dsc + + dpkg-source -x mpdecimal_$(MPDECIMAL_VERSION_FULL).dsc + pushd mpdecimal-$(MPDECIMAL_VERSION) + dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + mv $* $(DERIVED_TARGETS) $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/ptf b/src/ptf new file mode 160000 index 000000000000..aac6efd0a78b --- /dev/null +++ b/src/ptf @@ -0,0 +1 @@ +Subproject commit aac6efd0a78bf51f63727e7a13dc79f91f13686e diff --git a/src/python-click/Makefile b/src/python-click/Makefile new file mode 100644 index 000000000000..4deb27257fd2 --- /dev/null +++ b/src/python-click/Makefile @@ -0,0 +1,26 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = python-click_$(PYTHON_CLICK_VERSION)_all.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf ./python-click + + # Clone python-click Debian repo + git clone https://salsa.debian.org/debian/python-click + + pushd ./python-click + + # Reset HEAD to the commit of the proper tag + # NOTE: Using "git checkout " here detaches our HEAD, + # which stg doesn't like, so we use this method instead + git reset --hard debian/$(PYTHON_CLICK_VERSION) + + # Build source and Debian packages + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + # Move the newly-built .deb package to the destination directory + mv $* $(DEST)/ diff --git a/src/python3/Makefile b/src/python3/Makefile new file mode 100644 index 000000000000..d7718cbeccf6 --- /dev/null +++ b/src/python3/Makefile @@ -0,0 +1,40 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +PYTHON_VER=3.6.0 +PYTHON_DEB_VER=1 +PYTHON_PNAME=python3.6 + +MAIN_TARGET = lib$(PYTHON_PNAME)-minimal_$(PYTHON_VER)-$(PYTHON_DEB_VER)_amd64.deb +DERIVED_TARGETS = lib$(PYTHON_PNAME)-stdlib_$(PYTHON_VER)-$(PYTHON_DEB_VER)_amd64.deb \ + lib$(PYTHON_PNAME)_$(PYTHON_VER)-$(PYTHON_DEB_VER)_amd64.deb \ + $(PYTHON_PNAME)-minimal_$(PYTHON_VER)-$(PYTHON_DEB_VER)_amd64.deb \ + $(PYTHON_PNAME)_$(PYTHON_VER)-$(PYTHON_DEB_VER)_amd64.deb \ + lib$(PYTHON_PNAME)-dev_$(PYTHON_VER)-$(PYTHON_DEB_VER)_amd64.deb + #$(PYTHON_PNAME)-dev_$(PYTHON_VER)-$(PYTHON_DEB_VER)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + ## Obtaining the python3 + wget 'https://sonicstorage.blob.core.windows.net/packages/$(PYTHON_PNAME)_$(PYTHON_VER).orig.tar.xz?sv=2015-04-05&sr=b&sig=d42Wh1CA9NZvlskhW4fpWcHVgc7N3IKhdFzyeO2zbRA%3D&se=2027-02-02T01%3A00%3A57Z&sp=r' -O $(PYTHON_PNAME)_$(PYTHON_VER).orig.tar.xz + wget 'https://sonicstorage.blob.core.windows.net/packages/$(PYTHON_PNAME)_$(PYTHON_VER)-$(PYTHON_DEB_VER).debian.tar.xz?sv=2015-04-05&sr=b&sig=KLX9pMJ3zpQvGBo6ZjzoZXgooMJRUUwMx8ZaTJtywK0%3D&se=2027-02-02T00%3A59%3A34Z&sp=r' -O $(PYTHON_PNAME)_$(PYTHON_VER)-$(PYTHON_DEB_VER).debian.tar.xz + wget 'https://sonicstorage.blob.core.windows.net/packages/$(PYTHON_PNAME)_$(PYTHON_VER)-$(PYTHON_DEB_VER).dsc?sv=2015-04-05&sr=b&sig=95s%2FC4vKY6bRKtkUTz%2BmHLqOllBOYbfP3zV5ayAuzSM%3D&se=2027-02-02T01%3A00%3A26Z&sp=r' -O $(PYTHON_PNAME)_$(PYTHON_VER)-$(PYTHON_DEB_VER).dsc + + ## Build + dpkg-source -x $(PYTHON_PNAME)_$(PYTHON_VER)-$(PYTHON_DEB_VER).dsc + pushd $(PYTHON_PNAME)-$(PYTHON_VER) + mk-build-deps + + # put a lock here because dpkg does not allow installing packages in parallel + while true; do + if mkdir $(DEST)/dpkg_lock &> /dev/null; then + { echo here && (sudo dpkg -i $(PYTHON_PNAME)-build-deps_$(PYTHON_VER)-$(PYTHON_DEB_VER)_amd64.deb || sudo apt-get install -f) && rm -d $(DEST)/dpkg_lock && break; } || { rm -d $(DEST)/dpkg_lock && exit 1 ; } + fi + done + + dpkg-buildpackage -rfakeroot -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + cp $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/redis-dump-load b/src/redis-dump-load new file mode 160000 index 000000000000..832a645e4ddf --- /dev/null +++ b/src/redis-dump-load @@ -0,0 +1 @@ +Subproject commit 832a645e4ddff0f38ec0d64e3be70f48013287e6 diff --git a/src/redis-dump-load.patch/0001-Use-pipelines-when-dumping-52.patch b/src/redis-dump-load.patch/0001-Use-pipelines-when-dumping-52.patch new file mode 100644 index 000000000000..5eea3faba2c3 --- /dev/null +++ b/src/redis-dump-load.patch/0001-Use-pipelines-when-dumping-52.patch @@ -0,0 +1,154 @@ +From ed20dced07d8b2d140e2c1d79d506be0e12f339e Mon Sep 17 00:00:00 2001 +From: Oleg Pudeyev +Date: Sat, 28 Jan 2017 15:37:43 -0500 +Subject: [PATCH] Use pipelines when dumping, #52 + +--- + redisdl.py | 102 +++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 75 insertions(+), 27 deletions(-) + +diff --git a/redisdl.py b/redisdl.py +index df2870b..1b6063b 100755 +--- a/redisdl.py ++++ b/redisdl.py +@@ -141,18 +141,18 @@ def dumps(host='localhost', port=6379, password=None, db=0, pretty=False, + class BytesWriteWrapper(object): + def __init__(self, stream): + self.stream = stream +- ++ + def write(self, str): + return self.stream.write(str.encode()) + + def dump(fp, host='localhost', port=6379, password=None, db=0, pretty=False, + unix_socket_path=None, encoding='utf-8', keys='*'): +- ++ + try: + fp.write('') + except TypeError: + fp = BytesWriteWrapper(fp) +- ++ + if pretty: + # hack to avoid implementing pretty printing + fp.write(dumps(host=host, port=port, password=password, db=db, +@@ -276,28 +276,76 @@ def _read_key(key, r, pretty, encoding): + return (type, ttl, value) + + def _reader(r, pretty, encoding, keys='*'): +- for encoded_key in r.keys(keys): +- key = encoded_key.decode(encoding) +- handled = False +- for i in range(10): +- try: +- type, ttl, value = _read_key(encoded_key, r, pretty, encoding) +- yield key, type, ttl, value +- handled = True +- break +- except KeyDeletedError: +- # do not dump the key +- handled = True +- break +- except redis.WatchError: +- # same logic as key type changed +- pass +- except KeyTypeChangedError: +- # retry reading type again +- pass +- if not handled: +- # ran out of retries +- raise ConcurrentModificationError('Key %s is being concurrently modified' % key) ++ encoded_keys = r.keys(keys) ++ i = 0 ++ while i < len(encoded_keys): ++ for key, type, ttl, value in _read_keys(r, encoded_keys[i:i+10000], ++ pretty=pretty, encoding=encoding): ++ yield key, type, ttl, value ++ i += 10000 ++ ++def _read_keys(r, encoded_keys, pretty, encoding): ++ decoded_keys = [encoded_key.decode() for encoded_key in encoded_keys] ++ do_keys = decoded_keys ++ retries = 5 ++ type_results = None ++ while len(do_keys) > 0 and retries > 0: ++ next_do_keys = [] ++ next_type_results = [] ++ ++ if type_results is None: ++ # first pass, need to get the types. ++ # on subsequent passes we know the types ++ # because the previous pass retrieved them and ++ # found a type mismatch ++ p = r.pipeline() ++ for key in do_keys: ++ p.type(key) ++ type_results = p.execute() ++ ++ p = r.pipeline() ++ for i in range(len(do_keys)): ++ key = decoded_keys[i] ++ type = type_results[i].decode('ascii') ++ if type == 'none': ++ # key was deleted by a concurrent operation on the data store. ++ # issue noops so that the number of results does not change ++ p.type(key) ++ p.type(key) ++ p.type(key) ++ continue ++ reader = readers.get(type) ++ if reader is None: ++ raise UnknownTypeError("Unknown key type: %s" % type) ++ reader.send_command(p, key) ++ r.pttl_or_ttl_pipeline(p, key) ++ p.type(key) ++ results = p.execute() ++ ++ for i in range(len(do_keys)): ++ key = decoded_keys[i] ++ original_type = type_results[i] ++ if original_type == 'none': ++ # this is where we actually skip a key that was deleted ++ # by concurrent operations ++ continue ++ final_type = results[i*3+2].decode('ascii') ++ if original_type != final_type: ++ # type changed, will retry ++ next_do_keys.append(key) ++ # need to update expected type ++ next_type_results.append(final_type) ++ continue ++ reader = readers.get(original_type) ++ value = reader.handle_response(results[i*3], pretty, encoding) ++ ttl = r.decode_pttl_or_ttl_pipeline_value(results[i*3+1]) ++ yield key, final_type, ttl, value ++ retries -= 1 ++ do_keys = next_do_keys ++ type_results = next_type_results ++ ++ if len(do_keys) > 0: ++ raise ConcurrentModificationError('Keys %s are being concurrently modified' % ', '.join(do_keys)) + + def _empty(r): + for key in r.keys(): +@@ -372,14 +420,14 @@ def ijson_top_level_items(file, local_streaming_backend): + class TextReadWrapper(object): + def __init__(self, fp): + self.fp = fp +- ++ + def read(self, *args, **kwargs): + return self.fp.read(*args, **kwargs).decode() + + class BytesReadWrapper(object): + def __init__(self, fp): + self.fp = fp +- ++ + def read(self, *args, **kwargs): + return self.fp.read(*args, **kwargs).encode('utf-8') + +-- +2.18.0 + diff --git a/src/redis-dump-load.patch/0002-Fix-setup.py-for-test-and-bdist_wheel.patch b/src/redis-dump-load.patch/0002-Fix-setup.py-for-test-and-bdist_wheel.patch new file mode 100644 index 000000000000..5bb319a61738 --- /dev/null +++ b/src/redis-dump-load.patch/0002-Fix-setup.py-for-test-and-bdist_wheel.patch @@ -0,0 +1,26 @@ +From c2c93fa3b702a4f2364383fd4ae69763068686d2 Mon Sep 17 00:00:00 2001 +From: Qi Luo +Date: Tue, 20 Nov 2018 03:21:31 +0000 +Subject: [PATCH] Fix setup.py for test and bdist_wheel + +Signed-off-by: Qi Luo +--- + setup.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/setup.py b/setup.py +index 8ccf31f..6457163 100644 +--- a/setup.py ++++ b/setup.py +@@ -1,7 +1,7 @@ + #!/usr/bin/env python + + import os.path +-from distutils.core import setup ++from setuptools import setup, find_packages + + package_name = 'redis-dump-load' + package_version = '1.1' +-- +2.18.0 + diff --git a/src/redis-dump-load.patch/series b/src/redis-dump-load.patch/series new file mode 100644 index 000000000000..c73c3b5caa97 --- /dev/null +++ b/src/redis-dump-load.patch/series @@ -0,0 +1,2 @@ +0001-Use-pipelines-when-dumping-52.patch +0002-Fix-setup.py-for-test-and-bdist_wheel.patch diff --git a/src/redis/Makefile b/src/redis/Makefile new file mode 100644 index 000000000000..8cd4458b4339 --- /dev/null +++ b/src/redis/Makefile @@ -0,0 +1,24 @@ +SHELL = /bin/bash +.ONESHELL: +.SHELLFLAGS += -e + +REDIS_VERSION = 3.2.4 +REDIS_VERSION_FULL = $(REDIS_VERSION)-1~bpo8+1 + +MAIN_TARGET = redis-server_$(REDIS_VERSION_FULL)_amd64.deb +DERIVED_TARGETS = redis-tools_$(REDIS_VERSION_FULL)_amd64.deb \ + redis-sentinel_$(REDIS_VERSION_FULL)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + wget -O redis_$(REDIS_VERSION).orig.tar.gz -N "https://sonicstorage.blob.core.windows.net/packages/redis_$(REDIS_VERSION).orig.tar.gz?sv=2015-04-05&sr=b&sig=B3qGEoSHe%2FBh5rVwvXHpKijgBtKF7dHeuJWp1p17UnU%3D&se=2026-11-26T22%3A31%3A31Z&sp=r" + wget -O redis_$(REDIS_VERSION_FULL).dsc -N "https://sonicstorage.blob.core.windows.net/packages/redis_$(REDIS_VERSION_FULL).dsc?sv=2015-04-05&sr=b&sig=LoUtjLXa%2BCcoM%2BsPewRLkY7YPRvSJTbsvQoW%2BL%2B3QWM%3D&se=2026-11-26T22%3A32%3A11Z&sp=r" + wget -O redis_$(REDIS_VERSION_FULL).debian.tar.xz -N "https://sonicstorage.blob.core.windows.net/packages/redis_$(REDIS_VERSION_FULL).debian.tar.xz?sv=2015-04-05&sr=b&sig=I33UsbDHiffEkQRndpFwY9y3I%2FrKTu0wmG%2FMXB98kys%3D&se=2026-11-26T22%3A32%3A34Z&sp=r" + dpkg-source -x redis_$(REDIS_VERSION_FULL).dsc + + pushd redis-$(REDIS_VERSION) + DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/snmpd/Makefile b/src/snmpd/Makefile new file mode 100644 index 000000000000..e9645b93b686 --- /dev/null +++ b/src/snmpd/Makefile @@ -0,0 +1,39 @@ +SHELL = /bin/bash +.ONESHELL: +.SHELLFLAGS += -e + +MAIN_TARGET = libsnmp-base_$(SNMPD_VERSION_FULL)_all.deb +DERIVED_TARGETS = snmptrapd_$(SNMPD_VERSION_FULL)_amd64.deb \ + snmp_$(SNMPD_VERSION_FULL)_amd64.deb \ + snmpd_$(SNMPD_VERSION_FULL)_amd64.deb \ + libsnmp30_$(SNMPD_VERSION_FULL)_amd64.deb \ + libsnmp30-dbg_$(SNMPD_VERSION_FULL)_amd64.deb \ + libsnmp-dev_$(SNMPD_VERSION_FULL)_amd64.deb \ + libsnmp-perl_$(SNMPD_VERSION_FULL)_amd64.deb \ + python-netsnmp_$(SNMPD_VERSION_FULL)_amd64.deb \ + tkmib_$(SNMPD_VERSION_FULL)_all.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf net-snmp-$(SNMPD_VERSION) + + # download debian net-snmp + wget -NO net-snmp_$(SNMPD_VERSION_FULL).dsc "https://sonicstorage.blob.core.windows.net/packages/net-snmp_5.7.3+dfsg-1.5.dsc?sv=2015-04-05&sr=b&sig=vDAYAKlwi7JjF%2FesdJUyf4VIEXPsCfLhqqTqNr75zBs%3D&se=2030-10-12T13%3A59%3A45Z&sp=r" + wget -NO net-snmp_$(SNMPD_VERSION).orig.tar.xz "https://sonicstorage.blob.core.windows.net/packages/net-snmp_5.7.3+dfsg.orig.tar.xz?sv=2015-04-05&sr=b&sig=UjIh%2FTcHrIEzEV7a%2BV2ZP4ks3xHlAA3wqyxkyV7Ms8I%3D&se=2030-10-12T13%3A58%3A19Z&sp=r" + wget -NO net-snmp_$(SNMPD_VERSION_FULL).debian.tar.xz "https://sonicstorage.blob.core.windows.net/packages/net-snmp_5.7.3+dfsg-1.5.debian.tar.xz?sv=2015-04-05&sr=b&sig=xJkmxjtKXYcPe4yR%2FuCA0TXUfT40rj4XUMBaiK9CjsA%3D&se=2030-10-12T14%3A00%3A15Z&sp=r" + dpkg-source -x net-snmp_$(SNMPD_VERSION_FULL).dsc + + pushd net-snmp-$(SNMPD_VERSION) + git init + git add -f * + git commit -m "unmodified snmpd source" + + # Apply patches + stg init + stg import -s ../patch-$(SNMPD_VERSION)/series + + fakeroot debian/rules -j$(SONIC_CONFIG_MAKE_JOBS) binary + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/snmpd/patch-5.7.3+dfsg/0001-SNMP-Stop-spamming-logs-with-statfs-permission-denie.patch b/src/snmpd/patch-5.7.3+dfsg/0001-SNMP-Stop-spamming-logs-with-statfs-permission-denie.patch new file mode 100644 index 000000000000..f832d0044071 --- /dev/null +++ b/src/snmpd/patch-5.7.3+dfsg/0001-SNMP-Stop-spamming-logs-with-statfs-permission-denie.patch @@ -0,0 +1,40 @@ +From a1edbce39e46b5c8bd5bd7db17fc11fa30e7dd73 Mon Sep 17 00:00:00 2001 +From: pavel-shirshov +Date: Mon, 27 Aug 2018 16:50:16 +0800 +Subject: [PATCH] [SNMP] Stop spamming logs with statfs permission denied log + message #1668 + +--- + agent/mibgroup/hardware/fsys/fsys_mntctl.c | 2 -- + agent/mibgroup/hardware/fsys/fsys_mntent.c | 2 -- + 2 files changed, 4 deletions(-) + +diff --git a/agent/mibgroup/hardware/fsys/fsys_mntctl.c b/agent/mibgroup/hardware/fsys/fsys_mntctl.c +index 9fbb068..adc38d6 100644 +--- a/agent/mibgroup/hardware/fsys/fsys_mntctl.c ++++ b/agent/mibgroup/hardware/fsys/fsys_mntctl.c +@@ -163,8 +163,6 @@ netsnmp_fsys_arch_load( void ) + continue; + + if ( statfs( entry->path, &stat_buf ) < 0 ) { +- snprintf( tmpbuf, sizeof(tmpbuf), "Cannot statfs %s", entry->path ); +- snmp_log_perror( tmpbuf ); + continue; + } + entry->units = stat_buf.f_bsize; +diff --git a/agent/mibgroup/hardware/fsys/fsys_mntent.c b/agent/mibgroup/hardware/fsys/fsys_mntent.c +index 94d23db..5ad5e43 100644 +--- a/agent/mibgroup/hardware/fsys/fsys_mntent.c ++++ b/agent/mibgroup/hardware/fsys/fsys_mntent.c +@@ -238,8 +238,6 @@ netsnmp_fsys_arch_load( void ) + if ( NSFS_STATFS( entry->path, &stat_buf ) < 0 ) + #endif + { +- snprintf( tmpbuf, sizeof(tmpbuf), "Cannot statfs %s", entry->path ); +- snmp_log_perror( tmpbuf ); + continue; + } + entry->units = stat_buf.NSFS_SIZE; +-- +2.7.4 + diff --git a/src/snmpd/patch-5.7.3+dfsg/0002-at.c-properly-check-return-status-from-realloc.-Than.patch b/src/snmpd/patch-5.7.3+dfsg/0002-at.c-properly-check-return-status-from-realloc.-Than.patch new file mode 100644 index 000000000000..ceb0c68352bf --- /dev/null +++ b/src/snmpd/patch-5.7.3+dfsg/0002-at.c-properly-check-return-status-from-realloc.-Than.patch @@ -0,0 +1,31 @@ +From e370973f273ffc1b32673bc94c5a46f75a846d82 Mon Sep 17 00:00:00 2001 +From: Niels Baggesen +Date: Wed, 31 Aug 2016 21:43:36 +0200 +Subject: [PATCH] at.c: properly check return status from realloc. Thanks to + Daniel Eiland (bug 2678) + +--- + agent/mibgroup/mibII/at.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/agent/mibgroup/mibII/at.c b/agent/mibgroup/mibII/at.c +index f57ba2a..a73fb8c 100644 +--- a/agent/mibgroup/mibII/at.c ++++ b/agent/mibgroup/mibII/at.c +@@ -638,11 +638,12 @@ ARP_Scan_Init(void) + struct arptab *newtab = (struct arptab *) + realloc(at, (sizeof(struct arptab) * + (arptab_curr_max_size + ARP_CACHE_INCR))); +- if (newtab == at) { ++ if (newtab == NULL) { + snmp_log(LOG_ERR, + "Error allocating more space for arpcache. " + "Cache will continue to be limited to %d entries", + arptab_curr_max_size); ++ newtab = at; + break; + } else { + arptab_curr_max_size += ARP_CACHE_INCR; +-- +2.7.4 + diff --git a/src/snmpd/patch-5.7.3+dfsg/0003-CHANGES-BUG-2743-snmpd-crashes-when-receiving-a-GetN.patch b/src/snmpd/patch-5.7.3+dfsg/0003-CHANGES-BUG-2743-snmpd-crashes-when-receiving-a-GetN.patch new file mode 100644 index 000000000000..cdf9b94be934 --- /dev/null +++ b/src/snmpd/patch-5.7.3+dfsg/0003-CHANGES-BUG-2743-snmpd-crashes-when-receiving-a-GetN.patch @@ -0,0 +1,36 @@ +From 2170e345858738e65d3156a49d3186e4a9288821 Mon Sep 17 00:00:00 2001 +From: Zhenggen Xu +Date: Fri, 12 Oct 2018 17:13:54 -0700 +Subject: [PATCH] Subject: [PATCH] CHANGES: BUG: 2743: snmpd crashes when + receiving a GetNext PDU with multiple Varbinds + +skip out-of-range varbinds when calling next handler +--- + agent/helpers/table.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/agent/helpers/table.c b/agent/helpers/table.c +index 882e84c..b943d6e 100644 +--- a/agent/helpers/table.c ++++ b/agent/helpers/table.c +@@ -406,6 +406,8 @@ table_helper_handler(netsnmp_mib_handler *handler, + if (reqinfo->mode == MODE_GET) + table_helper_cleanup(reqinfo, request, + SNMP_NOSUCHOBJECT); ++ else ++ request->processed = 1; /* skip if next handler called */ + continue; + } + +@@ -483,6 +485,8 @@ table_helper_handler(netsnmp_mib_handler *handler, + #endif /* NETSNMP_NO_WRITE_SUPPORT */ + table_helper_cleanup(reqinfo, request, + SNMP_NOSUCHOBJECT); ++ else ++ request->processed = 1; /* skip if next handler called */ + continue; + } + /* +-- +2.18.0 + diff --git a/src/snmpd/patch-5.7.3+dfsg/0004-Disable-SNMPv1.patch b/src/snmpd/patch-5.7.3+dfsg/0004-Disable-SNMPv1.patch new file mode 100644 index 000000000000..6782a18c7758 --- /dev/null +++ b/src/snmpd/patch-5.7.3+dfsg/0004-Disable-SNMPv1.patch @@ -0,0 +1,25 @@ +From db633987abf1ea093cb1785b3cd37adfdb55e4cc Mon Sep 17 00:00:00 2001 +From: Qi Luo +Date: Mon, 15 Oct 2018 22:30:28 +0000 +Subject: [PATCH] Disable SNMPv1 + +Signed-off-by: Qi Luo +--- + debian/rules | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/debian/rules b/debian/rules +index 9eb8d2d..4c3b5b6 100755 +--- a/debian/rules ++++ b/debian/rules +@@ -42,6 +42,7 @@ endif + override_dh_auto_configure: + dh_auto_configure -- --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man \ + --with-persistent-directory=/var/lib/snmp \ ++ --disable-snmpv1 \ + --enable-ucd-snmp-compatibility \ + --enable-shared --with-cflags="$(CFLAGS) -DNETSNMP_USE_INLINE" \ + --with-ldflags="$(LDFLAGS)" \ +-- +2.18.0 + diff --git a/src/snmpd/patch-5.7.3+dfsg/series b/src/snmpd/patch-5.7.3+dfsg/series new file mode 100644 index 000000000000..f3b91e2382f1 --- /dev/null +++ b/src/snmpd/patch-5.7.3+dfsg/series @@ -0,0 +1,4 @@ +0001-SNMP-Stop-spamming-logs-with-statfs-permission-denie.patch +0002-at.c-properly-check-return-status-from-realloc.-Than.patch +0003-CHANGES-BUG-2743-snmpd-crashes-when-receiving-a-GetN.patch +0004-Disable-SNMPv1.patch diff --git a/src/socat/Makefile b/src/socat/Makefile new file mode 100644 index 000000000000..e82208946ac1 --- /dev/null +++ b/src/socat/Makefile @@ -0,0 +1,28 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = socat_$(SOCAT_VERSION)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf ./socat-1.7.3.1 + + # Get source package + wget -NO socat_$(SOCAT_VERSION).dsc "https://sonicstorage.blob.core.windows.net/packages/debian/socat_1.7.3.1-2+deb9u1.dsc?sv=2015-04-05&sr=b&sig=Ph7aMqb%2F%2FE%2F8qwxMXoXb5oK1YPkfVt6PV8mBBv5Wi%2F4%3D&se=2155-07-05T11%3A42%3A29Z&sp=r" + wget -NO socat_$(SOCAT_VERSION).debian.tar.xz "https://sonicstorage.blob.core.windows.net/packages/debian/socat_1.7.3.1-2+deb9u1.debian.tar.xz?sv=2015-04-05&sr=b&sig=yv77Fr5RtZgRTPmJK3j0lZ0BzsCiGaSs2i7NqQKEy2Y%3D&se=2155-07-05T11%3A39%3A59Z&sp=r" + wget -NO socat_1.7.3.1.orig.tar.gz "https://sonicstorage.blob.core.windows.net/packages/debian/socat_1.7.3.1.orig.tar.gz?sv=2015-04-05&sr=b&sig=0Ai1FM604aGsF5uBu2yN8w9O1a6zNjIDCdaiTo24DyQ%3D&se=2155-07-05T11%3A40%3A14Z&sp=r" + + dpkg-source -x socat_$(SOCAT_VERSION).dsc + + # Build source and Debian packages + pushd socat-1.7.3.1 + patch -p0 < ../enable_readline.patch + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + # Move the newly-built .deb packages to the destination directory + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) + diff --git a/src/socat/enable_readline.patch b/src/socat/enable_readline.patch new file mode 100644 index 000000000000..f1914d3cb494 --- /dev/null +++ b/src/socat/enable_readline.patch @@ -0,0 +1,13 @@ +--- debian/rules.old 2018-08-12 11:48:42.220230100 +0000 ++++ debian/rules 2018-08-12 11:48:52.072230100 +0000 +@@ -12,9 +12,6 @@ + %: + dh $@ --with=autoreconf + +-override_dh_auto_configure: +- dh_auto_configure -- --disable-readline +- + override_dh_auto_test: + +-.PHONY: override_dh_auto_configure override_dh_auto_test ++.PHONY: override_dh_auto_test diff --git a/src/sonic-config-engine/MANIFEST.in b/src/sonic-config-engine/MANIFEST.in new file mode 100644 index 000000000000..8861dd66030e --- /dev/null +++ b/src/sonic-config-engine/MANIFEST.in @@ -0,0 +1 @@ +recursive-include tests *.j2 *.yml *.xml *.json diff --git a/src/sonic-config-engine/config_samples.py b/src/sonic-config-engine/config_samples.py new file mode 100644 index 000000000000..6cb417b9a50b --- /dev/null +++ b/src/sonic-config-engine/config_samples.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +import os +import sys +from natsort import natsorted + +def generate_t1_sample_config(data): + data['DEVICE_METADATA']['localhost']['hostname'] = 'sonic' + data['DEVICE_METADATA']['localhost']['type'] = 'LeafRouter' + data['DEVICE_METADATA']['localhost']['bgp_asn'] = '65100' + data['LOOPBACK_INTERFACE'] = {"Loopback0|10.1.0.1/32": {}} + data['BGP_NEIGHBOR'] = {} + data['DEVICE_NEIGHBOR'] = {} + data['INTERFACE'] = {} + port_count = 0 + total_port_amount = len(data['PORT']) + for port in natsorted(data['PORT'].keys()): + data['PORT'][port]['admin_status'] = 'up' + data['PORT'][port]['mtu'] = '9100' + local_addr = '10.0.{}.{}'.format(2 * port_count / 256, 2 * port_count % 256) + peer_addr = '10.0.{}.{}'.format(2 * port_count / 256, 2 * port_count % 256 + 1) + peer_name='ARISTA{0:02d}{1}'.format(1+port_count%(total_port_amount/2), 'T2' if port_count < (total_port_amount/2) else 'T0') + peer_asn = 65200 if port_count < total_port_amount/2 else 64001 + port_count - total_port_amount/2 + data['INTERFACE']['{}|{}/31'.format(port, local_addr)] = {} + data['BGP_NEIGHBOR'][peer_addr] = { + 'rrclient': 0, + 'name': peer_name, + 'local_addr': local_addr, + 'nhopself': 0, + 'holdtime': '180', + 'asn': str(peer_asn), + 'keepalive': '60' + } + port_count += 1 + return data; + +def generate_empty_config(data): + new_data = {'DEVICE_METADATA': data['DEVICE_METADATA']} + if not new_data['DEVICE_METADATA']['localhost'].has_key('hostname'): + new_data['DEVICE_METADATA']['localhost']['hostname'] = 'sonic' + if not new_data['DEVICE_METADATA']['localhost'].has_key('type'): + new_data['DEVICE_METADATA']['localhost']['type'] = 'LeafRouter' + return new_data + +def generate_l2_config(data): + if not data['DEVICE_METADATA']['localhost'].has_key('hostname'): + data['DEVICE_METADATA']['localhost']['hostname'] = 'sonic' + if not data['DEVICE_METADATA']['localhost'].has_key('type'): + data['DEVICE_METADATA']['localhost']['type'] = 'ToRRouter' + data['VLAN'] = {'Vlan1000': {'vlanid': '1000'}} + data['VLAN_MEMBER'] = {} + for port in natsorted(data['PORT'].keys()): + data['VLAN_MEMBER']['Vlan1000|{}'.format(port)] = {'tagging_mode': 'untagged'} + return data + +_sample_generators = { + 't1': generate_t1_sample_config, + 'l2': generate_l2_config, + 'empty': generate_empty_config + } + +def get_available_config(): + return _sample_generators.keys() + +def generate_sample_config(data, setting_name): + return _sample_generators[setting_name.lower()](data) + diff --git a/src/sonic-config-engine/data/l2switch.j2 b/src/sonic-config-engine/data/l2switch.j2 new file mode 100644 index 000000000000..ee24f5ebd19d --- /dev/null +++ b/src/sonic-config-engine/data/l2switch.j2 @@ -0,0 +1,21 @@ +{ + "DEVICE_METADATA": {{ DEVICE_METADATA | tojson }}, + "PORT": {{ PORT | tojson }}, + "VLAN": { + "Vlan1000": { + "vlanid": "1000" + } + }, + {% set ns = {'firstPrinted': False} -%} + "VLAN_MEMBER": { + {%- for port in PORT -%} + {%- if ns.firstPrinted %},{% endif %} + + "Vlan1000|{{ port }}": { + "tagging_mode": "untagged" + } + {%- if ns.update({'firstPrinted': True}) %}{% endif -%} + {%- endfor %} + + } +} diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py new file mode 100644 index 000000000000..138a61a00a66 --- /dev/null +++ b/src/sonic-config-engine/minigraph.py @@ -0,0 +1,641 @@ +#!/usr/bin/env python +import calendar +import math +import os +import sys +import socket +import struct +import json +import copy +import ipaddr as ipaddress +from collections import defaultdict + +from lxml import etree as ET +from lxml.etree import QName + +from portconfig import get_port_config + +"""minigraph.py +version_added: "1.9" +author: Guohan Lu (gulv@microsoft.com) +short_description: Parse minigraph xml file and device description xml file +""" + +ns = "Microsoft.Search.Autopilot.Evolution" +ns1 = "http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution" +ns2 = "Microsoft.Search.Autopilot.NetMux" +ns3 = "http://www.w3.org/2001/XMLSchema-instance" + +class minigraph_encoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, ( + ipaddress.IPv4Network, ipaddress.IPv6Network, + ipaddress.IPv4Address, ipaddress.IPv6Address + )): + return str(obj) + return json.JSONEncoder.default(self, obj) + +def parse_device(device): + lo_prefix = None + mgmt_prefix = None + d_type = None # don't shadow type() + hwsku = None + name = None + deployment_id = None + if str(QName(ns3, "type")) in device.attrib: + d_type = device.attrib[str(QName(ns3, "type"))] + + for node in device: + if node.tag == str(QName(ns, "Address")): + lo_prefix = node.find(str(QName(ns2, "IPPrefix"))).text + elif node.tag == str(QName(ns, "ManagementAddress")): + mgmt_prefix = node.find(str(QName(ns2, "IPPrefix"))).text + elif node.tag == str(QName(ns, "Hostname")): + name = node.text + elif node.tag == str(QName(ns, "HwSku")): + hwsku = node.text + elif node.tag == str(QName(ns, "DeploymentId")): + deployment_id = node.text + return (lo_prefix, mgmt_prefix, name, hwsku, d_type, deployment_id) + +def parse_png(png, hname): + neighbors = {} + devices = {} + console_dev = '' + console_port = '' + mgmt_dev = '' + mgmt_port = '' + port_speeds = {} + console_ports = {} + for child in png: + if child.tag == str(QName(ns, "DeviceInterfaceLinks")): + for link in child.findall(str(QName(ns, "DeviceLinkBase"))): + linktype = link.find(str(QName(ns, "ElementType"))).text + if linktype == "DeviceSerialLink": + enddevice = link.find(str(QName(ns, "EndDevice"))).text + endport = link.find(str(QName(ns, "EndPort"))).text + startdevice = link.find(str(QName(ns, "StartDevice"))).text + startport = link.find(str(QName(ns, "StartPort"))).text + baudrate = link.find(str(QName(ns, "Bandwidth"))).text + flowcontrol = 1 if link.find(str(QName(ns, "FlowControl"))) is not None and link.find(str(QName(ns, "FlowControl"))).text == 'true' else 0 + if enddevice.lower() == hname.lower(): + console_ports[endport] = { + 'remote_device': startdevice, + 'baud_rate': baudrate, + 'flow_control': flowcontrol + } + else: + console_ports[startport] = { + 'remote_device': enddevice, + 'baud_rate': baudrate, + 'flow_control': flowcontrol + } + continue + + if linktype != "DeviceInterfaceLink" and linktype != "UnderlayInterfaceLink": + continue + + enddevice = link.find(str(QName(ns, "EndDevice"))).text + endport = link.find(str(QName(ns, "EndPort"))).text + startdevice = link.find(str(QName(ns, "StartDevice"))).text + startport = link.find(str(QName(ns, "StartPort"))).text + bandwidth_node = link.find(str(QName(ns, "Bandwidth"))) + bandwidth = bandwidth_node.text if bandwidth_node is not None else None + + if enddevice.lower() == hname.lower(): + if port_alias_map.has_key(endport): + endport = port_alias_map[endport] + neighbors[endport] = {'name': startdevice, 'port': startport} + if bandwidth: + port_speeds[endport] = bandwidth + else: + if port_alias_map.has_key(startport): + startport = port_alias_map[startport] + neighbors[startport] = {'name': enddevice, 'port': endport} + if bandwidth: + port_speeds[startport] = bandwidth + + if child.tag == str(QName(ns, "Devices")): + for device in child.findall(str(QName(ns, "Device"))): + (lo_prefix, mgmt_prefix, name, hwsku, d_type, deployment_id) = parse_device(device) + device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku } + if deployment_id: + device_data['deployment_id'] = deployment_id + devices[name] = device_data + + if child.tag == str(QName(ns, "DeviceInterfaceLinks")): + for if_link in child.findall(str(QName(ns, 'DeviceLinkBase'))): + if str(QName(ns3, "type")) in if_link.attrib: + link_type = if_link.attrib[str(QName(ns3, "type"))] + if link_type == 'DeviceSerialLink': + for node in if_link: + if node.tag == str(QName(ns, "EndPort")): + console_port = node.text.split()[-1] + elif node.tag == str(QName(ns, "EndDevice")): + console_dev = node.text + elif link_type == 'DeviceMgmtLink': + for node in if_link: + if node.tag == str(QName(ns, "EndPort")): + mgmt_port = node.text.split()[-1] + elif node.tag == str(QName(ns, "EndDevice")): + mgmt_dev = node.text + + return (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speeds, console_ports) + + +def parse_dpg(dpg, hname): + for child in dpg: + hostname = child.find(str(QName(ns, "Hostname"))) + if hostname.text.lower() != hname.lower(): + continue + + ipintfs = child.find(str(QName(ns, "IPInterfaces"))) + intfs = {} + for ipintf in ipintfs.findall(str(QName(ns, "IPInterface"))): + intfalias = ipintf.find(str(QName(ns, "AttachTo"))).text + intfname = port_alias_map.get(intfalias, intfalias) + ipprefix = ipintf.find(str(QName(ns, "Prefix"))).text + intfs[(intfname, ipprefix)] = {} + + lointfs = child.find(str(QName(ns, "LoopbackIPInterfaces"))) + lo_intfs = {} + for lointf in lointfs.findall(str(QName(ns1, "LoopbackIPInterface"))): + intfname = lointf.find(str(QName(ns, "AttachTo"))).text + ipprefix = lointf.find(str(QName(ns1, "PrefixStr"))).text + lo_intfs[(intfname, ipprefix)] = {} + + mgmtintfs = child.find(str(QName(ns, "ManagementIPInterfaces"))) + mgmt_intf = {} + for mgmtintf in mgmtintfs.findall(str(QName(ns1, "ManagementIPInterface"))): + intfname = mgmtintf.find(str(QName(ns, "AttachTo"))).text + ipprefix = mgmtintf.find(str(QName(ns1, "PrefixStr"))).text + mgmtipn = ipaddress.IPNetwork(ipprefix) + gwaddr = ipaddress.IPAddress(int(mgmtipn.network) + 1) + mgmt_intf[(intfname, ipprefix)] = {'gwaddr': gwaddr} + + pcintfs = child.find(str(QName(ns, "PortChannelInterfaces"))) + pc_intfs = [] + pcs = {} + pc_members = {} + intfs_inpc = [] # List to hold all the LAG member interfaces + for pcintf in pcintfs.findall(str(QName(ns, "PortChannel"))): + pcintfname = pcintf.find(str(QName(ns, "Name"))).text + pcintfmbr = pcintf.find(str(QName(ns, "AttachTo"))).text + pcmbr_list = pcintfmbr.split(';') + pc_intfs.append(pcintfname) + for i, member in enumerate(pcmbr_list): + pcmbr_list[i] = port_alias_map.get(member, member) + intfs_inpc.append(pcmbr_list[i]) + pc_members[(pcintfname, pcmbr_list[i])] = {'NULL': 'NULL'} + if pcintf.find(str(QName(ns, "Fallback"))) != None: + pcs[pcintfname] = {'members': pcmbr_list, 'fallback': pcintf.find(str(QName(ns, "Fallback"))).text, 'min_links': str(int(math.ceil(len() * 0.75)))} + else: + pcs[pcintfname] = {'members': pcmbr_list, 'min_links': str(int(math.ceil(len(pcmbr_list) * 0.75)))} + + vlanintfs = child.find(str(QName(ns, "VlanInterfaces"))) + vlan_intfs = [] + vlans = {} + vlan_members = {} + for vintf in vlanintfs.findall(str(QName(ns, "VlanInterface"))): + vintfname = vintf.find(str(QName(ns, "Name"))).text + vlanid = vintf.find(str(QName(ns, "VlanID"))).text + vintfmbr = vintf.find(str(QName(ns, "AttachTo"))).text + vmbr_list = vintfmbr.split(';') + for i, member in enumerate(vmbr_list): + vmbr_list[i] = port_alias_map.get(member, member) + sonic_vlan_member_name = "Vlan%s" % (vlanid) + vlan_members[(sonic_vlan_member_name, vmbr_list[i])] = {'tagging_mode': 'untagged'} + + vlan_attributes = {'vlanid': vlanid} + + # If this VLAN requires a DHCP relay agent, it will contain a element + # containing a list of DHCP server IPs + vintf_node = vintf.find(str(QName(ns, "DhcpRelays"))) + if vintf_node is not None and vintf_node.text is not None: + vintfdhcpservers = vintf_node.text + vdhcpserver_list = vintfdhcpservers.split(';') + vlan_attributes['dhcp_servers'] = vdhcpserver_list + + sonic_vlan_name = "Vlan%s" % vlanid + if sonic_vlan_name != vintfname: + vlan_attributes['alias'] = vintfname + vlans[sonic_vlan_name] = vlan_attributes + + aclintfs = child.find(str(QName(ns, "AclInterfaces"))) + acls = {} + for aclintf in aclintfs.findall(str(QName(ns, "AclInterface"))): + aclname = aclintf.find(str(QName(ns, "InAcl"))).text.upper().replace(" ", "_").replace("-", "_") + aclattach = aclintf.find(str(QName(ns, "AttachTo"))).text.split(';') + acl_intfs = [] + is_mirror = False + + # TODO: Ensure that acl_intfs will only ever contain front-panel interfaces (e.g., + # maybe we should explicity ignore management and loopback interfaces?) because we + # decide an ACL is a Control Plane ACL if acl_intfs is empty below. + for member in aclattach: + member = member.strip() + if pcs.has_key(member): + # If try to attach ACL to a LAG interface then we shall add the LAG to + # to acl_intfs directly instead of break it into member ports, ACL attach + # to LAG will be applied to all the LAG members internally by SAI/SDK + acl_intfs.append(member) + elif vlans.has_key(member): + print >> sys.stderr, "Warning: ACL " + aclname + " is attached to a Vlan interface, which is currently not supported" + elif port_alias_map.has_key(member): + acl_intfs.append(port_alias_map[member]) + # Give a warning if trying to attach ACL to a LAG member interface, correct way is to attach ACL to the LAG interface + if port_alias_map[member] in intfs_inpc: + print >> sys.stderr, "Warning: ACL " + aclname + " is attached to a LAG member interface " + port_alias_map[member] + ", instead of LAG interface" + elif member.lower() == 'erspan': + is_mirror = True; + # Erspan session will be attached to all front panel ports, + # if panel ports is a member port of LAG, should add the LAG + # to acl table instead of the panel ports + acl_intfs = pc_intfs + for panel_port in port_alias_map.values(): + if panel_port not in intfs_inpc: + acl_intfs.append(panel_port) + break; + if acl_intfs: + acls[aclname] = {'policy_desc': aclname, + 'ports': acl_intfs, + 'type': 'MIRROR' if is_mirror else 'L3'} + elif is_mirror: + acls[aclname] = {'policy_desc': aclname, 'type': 'MIRROR'} + else: + # This ACL has no interfaces to attach to -- consider this a control plane ACL + try: + aclservice = aclintf.find(str(QName(ns, "Type"))).text + + # If we already have an ACL with this name and this ACL is bound to a different service, + # append the service to our list of services + if aclname in acls: + if acls[aclname]['type'] != 'CTRLPLANE': + print >> sys.stderr, "Warning: ACL '%s' type mismatch. Not updating ACL." % aclname + elif acls[aclname]['services'] == aclservice: + print >> sys.stderr, "Warning: ACL '%s' already contains service '%s'. Not updating ACL." % (aclname, aclservice) + else: + acls[aclname]['services'].append(aclservice) + else: + acls[aclname] = {'policy_desc': aclname, + 'type': 'CTRLPLANE', + 'services': [aclservice]} + except: + print >> sys.stderr, "Warning: Ignoring Control Plane ACL %s without type" % aclname + + return intfs, lo_intfs, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls + return None, None, None, None, None, None, None + + +def parse_cpg(cpg, hname): + bgp_sessions = {} + myasn = None + bgp_peers_with_range = {} + for child in cpg: + tag = child.tag + if tag == str(QName(ns, "PeeringSessions")): + for session in child.findall(str(QName(ns, "BGPSession"))): + start_router = session.find(str(QName(ns, "StartRouter"))).text + start_peer = session.find(str(QName(ns, "StartPeer"))).text + end_router = session.find(str(QName(ns, "EndRouter"))).text + end_peer = session.find(str(QName(ns, "EndPeer"))).text + rrclient = 1 if session.find(str(QName(ns, "RRClient"))) is not None else 0 + if session.find(str(QName(ns, "HoldTime"))) is not None: + holdtime = session.find(str(QName(ns, "HoldTime"))).text + else: + holdtime = 180 + if session.find(str(QName(ns, "KeepAliveTime"))) is not None: + keepalive = session.find(str(QName(ns, "KeepAliveTime"))).text + else: + keepalive = 60 + nhopself = 1 if session.find(str(QName(ns, "NextHopSelf"))) is not None else 0 + if end_router.lower() == hname.lower(): + bgp_sessions[start_peer.lower()] = { + 'name': start_router, + 'local_addr': end_peer.lower(), + 'rrclient': rrclient, + 'holdtime': holdtime, + 'keepalive': keepalive, + 'nhopself': nhopself + } + else: + bgp_sessions[end_peer.lower()] = { + 'name': end_router, + 'local_addr': start_peer.lower(), + 'rrclient': rrclient, + 'holdtime': holdtime, + 'keepalive': keepalive, + 'nhopself': nhopself + } + elif child.tag == str(QName(ns, "Routers")): + for router in child.findall(str(QName(ns1, "BGPRouterDeclaration"))): + asn = router.find(str(QName(ns1, "ASN"))).text + hostname = router.find(str(QName(ns1, "Hostname"))).text + if hostname.lower() == hname.lower(): + myasn = asn + peers = router.find(str(QName(ns1, "Peers"))) + for bgpPeer in peers.findall(str(QName(ns, "BGPPeer"))): + addr = bgpPeer.find(str(QName(ns, "Address"))).text + if bgpPeer.find(str(QName(ns1, "PeersRange"))) is not None: + name = bgpPeer.find(str(QName(ns1, "Name"))).text + ip_range = bgpPeer.find(str(QName(ns1, "PeersRange"))).text + ip_range_group = ip_range.split(';') if ip_range and ip_range != "" else [] + bgp_peers_with_range[name] = { + 'name': name, + 'ip_range': ip_range_group + } + else: + for peer in bgp_sessions: + bgp_session = bgp_sessions[peer] + if hostname.lower() == bgp_session['name'].lower(): + bgp_session['asn'] = asn + bgp_sessions = { key: bgp_sessions[key] for key in bgp_sessions if bgp_sessions[key].has_key('asn') and int(bgp_sessions[key]['asn']) != 0 } + return bgp_sessions, myasn, bgp_peers_with_range + + +def parse_meta(meta, hname): + syslog_servers = [] + dhcp_servers = [] + ntp_servers = [] + tacacs_servers = [] + mgmt_routes = [] + erspan_dst = [] + deployment_id = None + device_metas = meta.find(str(QName(ns, "Devices"))) + for device in device_metas.findall(str(QName(ns1, "DeviceMetadata"))): + if device.find(str(QName(ns1, "Name"))).text.lower() == hname.lower(): + properties = device.find(str(QName(ns1, "Properties"))) + for device_property in properties.findall(str(QName(ns1, "DeviceProperty"))): + name = device_property.find(str(QName(ns1, "Name"))).text + value = device_property.find(str(QName(ns1, "Value"))).text + value_group = value.strip().split(';') if value and value != "" else [] + if name == "DhcpResources": + dhcp_servers = value_group + elif name == "NtpResources": + ntp_servers = value_group + elif name == "SyslogResources": + syslog_servers = value_group + elif name == "TacacsServer": + tacacs_servers = value_group + elif name == "ForcedMgmtRoutes": + mgmt_routes = value_group + elif name == "ErspanDestinationIpv4": + erspan_dst = value_group + elif name == "DeploymentId": + deployment_id = value + return syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id + +def parse_deviceinfo(meta, hwsku): + port_speeds = {} + port_descriptions = {} + for device_info in meta.findall(str(QName(ns, "DeviceInfo"))): + dev_sku = device_info.find(str(QName(ns, "HwSku"))).text + if dev_sku == hwsku: + interfaces = device_info.find(str(QName(ns, "EthernetInterfaces"))) + for interface in interfaces.findall(str(QName(ns1, "EthernetInterface"))): + alias = interface.find(str(QName(ns, "InterfaceName"))).text + speed = interface.find(str(QName(ns, "Speed"))).text + desc = interface.find(str(QName(ns, "Description"))) + if desc != None: + port_descriptions[port_alias_map.get(alias, alias)] = desc.text + port_speeds[port_alias_map.get(alias, alias)] = speed + return port_speeds, port_descriptions + +def parse_xml(filename, platform=None, port_config_file=None): + root = ET.parse(filename).getroot() + mini_graph_path = filename + + u_neighbors = None + u_devices = None + hwsku = None + bgp_sessions = None + bgp_asn = None + intfs = None + vlan_intfs = None + pc_intfs = None + vlans = None + vlan_members = None + pcs = None + mgmt_intf = None + lo_intf = None + neighbors = None + devices = None + hostname = None + docker_routing_config_mode = "unified" + port_speeds_default = {} + port_speed_png = {} + port_descriptions = {} + console_ports = {} + syslog_servers = [] + dhcp_servers = [] + ntp_servers = [] + tacacs_servers = [] + mgmt_routes = [] + erspan_dst = [] + bgp_peers_with_range = None + deployment_id = None + + hwsku_qn = QName(ns, "HwSku") + hostname_qn = QName(ns, "Hostname") + docker_routing_config_mode_qn = QName(ns, "DockerRoutingConfigMode") + for child in root: + if child.tag == str(hwsku_qn): + hwsku = child.text + if child.tag == str(hostname_qn): + hostname = child.text + if child.tag == str(docker_routing_config_mode_qn): + docker_routing_config_mode = child.text + + (ports, alias_map) = get_port_config(hwsku, platform, port_config_file) + port_alias_map.update(alias_map) + for child in root: + if child.tag == str(QName(ns, "DpgDec")): + (intfs, lo_intfs, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls) = parse_dpg(child, hostname) + elif child.tag == str(QName(ns, "CpgDec")): + (bgp_sessions, bgp_asn, bgp_peers_with_range) = parse_cpg(child, hostname) + elif child.tag == str(QName(ns, "PngDec")): + (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speed_png, console_ports) = parse_png(child, hostname) + elif child.tag == str(QName(ns, "UngDec")): + (u_neighbors, u_devices, _, _, _, _, _, _) = parse_png(child, hostname) + elif child.tag == str(QName(ns, "MetadataDeclaration")): + (syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id) = parse_meta(child, hostname) + elif child.tag == str(QName(ns, "DeviceInfos")): + (port_speeds_default, port_descriptions) = parse_deviceinfo(child, hwsku) + + current_device = [devices[key] for key in devices if key.lower() == hostname.lower()][0] + results = {} + results['DEVICE_METADATA'] = {'localhost': { + 'bgp_asn': bgp_asn, + 'deployment_id': deployment_id, + 'docker_routing_config_mode': docker_routing_config_mode, + 'hostname': hostname, + 'hwsku': hwsku, + 'type': current_device['type'] + }} + results['BGP_NEIGHBOR'] = bgp_sessions + results['BGP_PEER_RANGE'] = bgp_peers_with_range + if mgmt_routes: + # TODO: differentiate v4 and v6 + mgmt_intf.itervalues().next()['forced_mgmt_routes'] = mgmt_routes + results['MGMT_PORT'] = {} + results['MGMT_INTERFACE'] = {} + mgmt_intf_count = 0 + mgmt_alias_reverse_mapping = {} + for key in mgmt_intf: + alias = key[0] + if mgmt_alias_reverse_mapping.has_key(alias): + name = mgmt_alias_reverse_mapping[alias] + else: + name = 'eth' + str(mgmt_intf_count) + mgmt_intf_count += 1 + mgmt_alias_reverse_mapping[alias] = name + results['MGMT_PORT'][name] = {'alias': alias, 'admin_status': 'up'} + results['MGMT_INTERFACE'][(name, key[1])] = mgmt_intf[key] + results['LOOPBACK_INTERFACE'] = lo_intfs + + phyport_intfs = {} + vlan_intfs = {} + pc_intfs = {} + vlan_invert_mapping = { v['alias']:k for k,v in vlans.items() if v.has_key('alias') } + + for intf in intfs: + if intf[0][0:4] == 'Vlan': + vlan_intfs[intf] = {} + elif vlan_invert_mapping.has_key(intf[0]): + vlan_intfs[(vlan_invert_mapping[intf[0]], intf[1])] = {} + elif intf[0][0:11] == 'PortChannel': + pc_intfs[intf] = {} + else: + phyport_intfs[intf] = {} + + results['INTERFACE'] = phyport_intfs + results['VLAN_INTERFACE'] = vlan_intfs + + for port_name in port_speeds_default: + # ignore port not in port_config.ini + if not ports.has_key(port_name): + continue + + ports.setdefault(port_name, {})['speed'] = port_speeds_default[port_name] + + for port_name in port_speed_png: + # not consider port not in port_config.ini + if port_name not in ports: + print >> sys.stderr, "Warning: ignore interface '%s' as it is not in the port_config.ini" % port_name + continue + + ports.setdefault(port_name, {})['speed'] = port_speed_png[port_name] + + for port_name, port in ports.items(): + if port.get('speed') == '100000': + port['fec'] = 'rs' + + for port_name in port_descriptions: + # ignore port not in port_config.ini + if not ports.has_key(port_name): + continue + + ports.setdefault(port_name, {})['description'] = port_descriptions[port_name] + + # set default port MTU as 9100 + for port in ports.itervalues(): + port['mtu'] = '9100' + + # set physical port default admin status up + for port in phyport_intfs: + if port[0] in ports: + ports.get(port[0])['admin_status'] = 'up' + + for member in pc_members.keys() + vlan_members.keys(): + port = ports.get(member[1]) + if port: + port['admin_status'] = 'up' + + results['PORT'] = ports + results['CONSOLE_PORT'] = console_ports + + if port_config_file: + port_set = set(ports.keys()) + for (pc_name, mbr_map) in pcs.items(): + # remove portchannels that contain ports not existing in port_config.ini + # when port_config.ini exists + if not set(mbr_map['members']).issubset(port_set): + print >> sys.stderr, "Warning: ignore '%s' as part of its member interfaces is not in the port_config.ini" % pc_name + del pcs[pc_name] + + # set default port channel MTU as 9100 and admin status up + for pc in pcs.itervalues(): + pc['mtu'] = '9100' + pc['admin_status'] = 'up' + + results['PORTCHANNEL'] = pcs + results['PORTCHANNEL_MEMBER'] = pc_members + + for pc_intf in pc_intfs.keys(): + # remove portchannels not in PORTCHANNEL dictionary + if pc_intf[0] not in pcs: + print >> sys.stderr, "Warning: ignore '%s' interface '%s' as '%s' is not in the valid PortChannel list" % (pc_intf[0], pc_intf[1], pc_intf[0]) + del pc_intfs[pc_intf] + + results['PORTCHANNEL_INTERFACE'] = pc_intfs + + results['VLAN'] = vlans + results['VLAN_MEMBER'] = vlan_members + + for nghbr in neighbors.keys(): + # remove port not in port_config.ini + if nghbr not in ports: + print >> sys.stderr, "Warning: ignore interface '%s' in DEVICE_NEIGHBOR as it is not in the port_config.ini" % nghbr + del neighbors[nghbr] + + results['DEVICE_NEIGHBOR'] = neighbors + results['DEVICE_NEIGHBOR_METADATA'] = { key:devices[key] for key in devices if key.lower() != hostname.lower() } + results['SYSLOG_SERVER'] = dict((item, {}) for item in syslog_servers) + results['DHCP_SERVER'] = dict((item, {}) for item in dhcp_servers) + results['NTP_SERVER'] = dict((item, {}) for item in ntp_servers) + results['TACPLUS_SERVER'] = dict((item, {'priority': '1', 'tcp_port': '49'}) for item in tacacs_servers) + + results['ACL_TABLE'] = acls + mirror_sessions = {} + if erspan_dst: + lo_addr = '0.0.0.0' + for lo in lo_intfs: + lo_network = ipaddress.IPNetwork(lo[1]) + if lo_network.version == 4: + lo_addr = str(lo_network.ip) + break + count = 0 + for dst in erspan_dst: + mirror_sessions['everflow{}'.format(count)] = {"dst_ip": dst, "src_ip": lo_addr} + count += 1 + results['MIRROR_SESSION'] = mirror_sessions + + return results + + +def parse_device_desc_xml(filename): + root = ET.parse(filename).getroot() + (lo_prefix, mgmt_prefix, hostname, hwsku, d_type, _) = parse_device(root) + + results = {} + results['DEVICE_METADATA'] = {'localhost': { + 'hostname': hostname, + 'hwsku': hwsku, + }} + + results['LOOPBACK_INTERFACE'] = {('lo', lo_prefix): {}} + + mgmt_intf = {} + mgmtipn = ipaddress.IPNetwork(mgmt_prefix) + gwaddr = ipaddress.IPAddress(int(mgmtipn.network) + 1) + results['MGMT_INTERFACE'] = {('eth0', mgmt_prefix): {'gwaddr': gwaddr}} + + return results + + +port_alias_map = {} + + +def print_parse_xml(filename): + results = parse_xml(filename) + print(json.dumps(results, indent=3, cls=minigraph_encoder)) diff --git a/src/sonic-config-engine/openconfig_acl.py b/src/sonic-config-engine/openconfig_acl.py new file mode 100644 index 000000000000..cb29183652e7 --- /dev/null +++ b/src/sonic-config-engine/openconfig_acl.py @@ -0,0 +1,7542 @@ +# This file is auto generated by pyangbind: https://github.com/robshakir/pyangbind +# from https://github.com/openconfig/public/blob/master/release/models/acl/openconfig-acl.yang +# +# Detail step to regenerate this file: +# 1. Sync openconfig ACL yang models from https://github.com/openconfig/public/tree/master/release/models/acl +# 2. Sync inet yang models which contain type dependencies for openconfig ACL yang models from https://github.com/YangModels/yang/tree/master/standard/ietf/RFC , and put them in the same folder with models from step 1. +# 3. Install PyangBind: +# pip install pyangbind +# 4. Get PyangBind install path: +# export PYBINDPLUGIN=`/usr/bin/env python -c \ +# 'import pyangbind; import os; print "%s/plugin" % os.path.dirname(pyangbind.__file__)'` +# 5. Generate this file with pyang: +# pyang --plugindir $PYBINDPLUGIN -f pybind -o openconfig_acl.py openconfig-acl.yang + +from operator import attrgetter +from pyangbind.lib.yangtypes import RestrictedPrecisionDecimalType, RestrictedClassType, TypedListType +from pyangbind.lib.yangtypes import YANGBool, YANGListType, YANGDynClass, ReferenceType +from pyangbind.lib.base import PybindBase +from decimal import Decimal +from bitarray import bitarray +import __builtin__ +class yc_state_openconfig_acl__acl_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Global operational state data for ACLs + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__counter_capability',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__counter_capability = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-acl:AGGREGATE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:INTERFACE_AGGREGATE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'AGGREGATE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'INTERFACE_AGGREGATE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'INTERFACE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:INTERFACE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="counter-capability", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'state'] + + def _get_counter_capability(self): + """ + Getter method for counter_capability, mapped from YANG variable /acl/state/counter_capability (identityref) + + YANG Description: System reported indication of how ACL counters are reported +by the target + """ + return self.__counter_capability + + def _set_counter_capability(self, v, load=False): + """ + Setter method for counter_capability, mapped from YANG variable /acl/state/counter_capability (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_counter_capability is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_counter_capability() directly. + + YANG Description: System reported indication of how ACL counters are reported +by the target + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-acl:AGGREGATE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:INTERFACE_AGGREGATE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'AGGREGATE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'INTERFACE_AGGREGATE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'INTERFACE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:INTERFACE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="counter-capability", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """counter_capability must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-acl:AGGREGATE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:INTERFACE_AGGREGATE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'AGGREGATE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'INTERFACE_AGGREGATE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'INTERFACE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:INTERFACE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="counter-capability", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False)""", + }) + + self.__counter_capability = t + if hasattr(self, '_set'): + self._set() + + def _unset_counter_capability(self): + self.__counter_capability = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-acl:AGGREGATE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:INTERFACE_AGGREGATE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'AGGREGATE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'INTERFACE_AGGREGATE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'INTERFACE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:INTERFACE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="counter-capability", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + + counter_capability = __builtin__.property(_get_counter_capability) + + + _pyangbind_elements = {'counter_capability': counter_capability, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Access list config + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__name','__description',) + + _yang_name = 'config' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__name = YANGDynClass(base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + self.__description = YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'config'] + + def _get_name(self): + """ + Getter method for name, mapped from YANG variable /acl/acl_sets/acl_set/config/name (string) + + YANG Description: The name of the access-list set + """ + return self.__name + + def _set_name(self, v, load=False): + """ + Setter method for name, mapped from YANG variable /acl/acl_sets/acl_set/config/name (string) + If this variable is read-only (config: false) in the + source YANG file, then _set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_name() directly. + + YANG Description: The name of the access-list set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """name must be of a type compatible with string""", + 'defined-type': "string", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True)""", + }) + + self.__name = t + if hasattr(self, '_set'): + self._set() + + def _unset_name(self): + self.__name = YANGDynClass(base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + + + def _get_description(self): + """ + Getter method for description, mapped from YANG variable /acl/acl_sets/acl_set/config/description (string) + + YANG Description: Description, or comment, for the ACL set + """ + return self.__description + + def _set_description(self, v, load=False): + """ + Setter method for description, mapped from YANG variable /acl/acl_sets/acl_set/config/description (string) + If this variable is read-only (config: false) in the + source YANG file, then _set_description is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_description() directly. + + YANG Description: Description, or comment, for the ACL set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """description must be of a type compatible with string""", + 'defined-type': "string", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True)""", + }) + + self.__description = t + if hasattr(self, '_set'): + self._set() + + def _unset_description(self): + self.__description = YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + + name = __builtin__.property(_get_name, _set_name) + description = __builtin__.property(_get_description, _set_description) + + + _pyangbind_elements = {'name': name, 'description': description, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Access list state information + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__name','__description',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__name = YANGDynClass(base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + self.__description = YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'state'] + + def _get_name(self): + """ + Getter method for name, mapped from YANG variable /acl/acl_sets/acl_set/state/name (string) + + YANG Description: The name of the access-list set + """ + return self.__name + + def _set_name(self, v, load=False): + """ + Setter method for name, mapped from YANG variable /acl/acl_sets/acl_set/state/name (string) + If this variable is read-only (config: false) in the + source YANG file, then _set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_name() directly. + + YANG Description: The name of the access-list set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """name must be of a type compatible with string""", + 'defined-type': "string", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False)""", + }) + + self.__name = t + if hasattr(self, '_set'): + self._set() + + def _unset_name(self): + self.__name = YANGDynClass(base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + + + def _get_description(self): + """ + Getter method for description, mapped from YANG variable /acl/acl_sets/acl_set/state/description (string) + + YANG Description: Description, or comment, for the ACL set + """ + return self.__description + + def _set_description(self, v, load=False): + """ + Setter method for description, mapped from YANG variable /acl/acl_sets/acl_set/state/description (string) + If this variable is read-only (config: false) in the + source YANG file, then _set_description is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_description() directly. + + YANG Description: Description, or comment, for the ACL set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """description must be of a type compatible with string""", + 'defined-type': "string", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False)""", + }) + + self.__description = t + if hasattr(self, '_set'): + self._set() + + def _unset_description(self): + self.__description = YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + + name = __builtin__.property(_get_name) + description = __builtin__.property(_get_description) + + + _pyangbind_elements = {'name': name, 'description': description, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Access list entries config + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__description',) + + _yang_name = 'config' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__sequence_id = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=True) + self.__description = YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'config'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/config/sequence_id (uint32) + + YANG Description: The sequence id determines the order in which ACL entries +are applied. The sequence id must be unique for each entry +in an ACL set. Target devices should apply the ACL entry +rules in the order determined by sequence id, rather than +the relying only on order in the list. + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/config/sequence_id (uint32) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: The sequence id determines the order in which ACL entries +are applied. The sequence id must be unique for each entry +in an ACL set. Target devices should apply the ACL entry +rules in the order determined by sequence id, rather than +the relying only on order in the list. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with uint32""", + 'defined-type': "uint32", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=True)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=True) + + + def _get_description(self): + """ + Getter method for description, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/config/description (string) + + YANG Description: A user-defined description, or comment, for this Access List +Entry. + """ + return self.__description + + def _set_description(self, v, load=False): + """ + Setter method for description, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/config/description (string) + If this variable is read-only (config: false) in the + source YANG file, then _set_description is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_description() directly. + + YANG Description: A user-defined description, or comment, for this Access List +Entry. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """description must be of a type compatible with string""", + 'defined-type': "string", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True)""", + }) + + self.__description = t + if hasattr(self, '_set'): + self._set() + + def _unset_description(self): + self.__description = YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + + sequence_id = __builtin__.property(_get_sequence_id, _set_sequence_id) + description = __builtin__.property(_get_description, _set_description) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'description': description, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: State information for ACL entries + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__description','__matched_packets','__matched_octets',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__matched_octets = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + self.__sequence_id = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=False) + self.__description = YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + self.__matched_packets = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'state'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/sequence_id (uint32) + + YANG Description: The sequence id determines the order in which ACL entries +are applied. The sequence id must be unique for each entry +in an ACL set. Target devices should apply the ACL entry +rules in the order determined by sequence id, rather than +the relying only on order in the list. + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/sequence_id (uint32) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: The sequence id determines the order in which ACL entries +are applied. The sequence id must be unique for each entry +in an ACL set. Target devices should apply the ACL entry +rules in the order determined by sequence id, rather than +the relying only on order in the list. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with uint32""", + 'defined-type': "uint32", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=False)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=False) + + + def _get_description(self): + """ + Getter method for description, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/description (string) + + YANG Description: A user-defined description, or comment, for this Access List +Entry. + """ + return self.__description + + def _set_description(self, v, load=False): + """ + Setter method for description, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/description (string) + If this variable is read-only (config: false) in the + source YANG file, then _set_description is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_description() directly. + + YANG Description: A user-defined description, or comment, for this Access List +Entry. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """description must be of a type compatible with string""", + 'defined-type': "string", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False)""", + }) + + self.__description = t + if hasattr(self, '_set'): + self._set() + + def _unset_description(self): + self.__description = YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + + + def _get_matched_packets(self): + """ + Getter method for matched_packets, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/matched_packets (yang:counter64) + + YANG Description: Count of the number of packets matching the current ACL +entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + return self.__matched_packets + + def _set_matched_packets(self, v, load=False): + """ + Setter method for matched_packets, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/matched_packets (yang:counter64) + If this variable is read-only (config: false) in the + source YANG file, then _set_matched_packets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_matched_packets() directly. + + YANG Description: Count of the number of packets matching the current ACL +entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """matched_packets must be of a type compatible with yang:counter64""", + 'defined-type': "yang:counter64", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False)""", + }) + + self.__matched_packets = t + if hasattr(self, '_set'): + self._set() + + def _unset_matched_packets(self): + self.__matched_packets = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + + def _get_matched_octets(self): + """ + Getter method for matched_octets, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/matched_octets (yang:counter64) + + YANG Description: Count of the number of octets (bytes) matching the current +ACL entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + return self.__matched_octets + + def _set_matched_octets(self, v, load=False): + """ + Setter method for matched_octets, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/matched_octets (yang:counter64) + If this variable is read-only (config: false) in the + source YANG file, then _set_matched_octets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_matched_octets() directly. + + YANG Description: Count of the number of octets (bytes) matching the current +ACL entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """matched_octets must be of a type compatible with yang:counter64""", + 'defined-type': "yang:counter64", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False)""", + }) + + self.__matched_octets = t + if hasattr(self, '_set'): + self._set() + + def _unset_matched_octets(self): + self.__matched_octets = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + sequence_id = __builtin__.property(_get_sequence_id) + description = __builtin__.property(_get_description) + matched_packets = __builtin__.property(_get_matched_packets) + matched_octets = __builtin__.property(_get_matched_octets) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'description': description, 'matched_packets': matched_packets, 'matched_octets': matched_octets, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/l2/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configuration data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__source_mac','__source_mac_mask','__destination_mac','__destination_mac_mask','__ethertype',) + + _yang_name = 'config' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__source_mac = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + self.__destination_mac = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + self.__destination_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + self.__ethertype = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'1..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=True) + self.__source_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'l2', u'config'] + + def _get_source_mac(self): + """ + Getter method for source_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/source_mac (yang:mac-address) + + YANG Description: Source IEEE 802 MAC address. + """ + return self.__source_mac + + def _set_source_mac(self, v, load=False): + """ + Setter method for source_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/source_mac (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_mac is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_mac() directly. + + YANG Description: Source IEEE 802 MAC address. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_mac must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True)""", + }) + + self.__source_mac = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_mac(self): + self.__source_mac = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + + + def _get_source_mac_mask(self): + """ + Getter method for source_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/source_mac_mask (yang:mac-address) + + YANG Description: Source IEEE 802 MAC address mask. + """ + return self.__source_mac_mask + + def _set_source_mac_mask(self, v, load=False): + """ + Setter method for source_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/source_mac_mask (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_mac_mask is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_mac_mask() directly. + + YANG Description: Source IEEE 802 MAC address mask. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_mac_mask must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True)""", + }) + + self.__source_mac_mask = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_mac_mask(self): + self.__source_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + + + def _get_destination_mac(self): + """ + Getter method for destination_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/destination_mac (yang:mac-address) + + YANG Description: Destination IEEE 802 MAC address. + """ + return self.__destination_mac + + def _set_destination_mac(self, v, load=False): + """ + Setter method for destination_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/destination_mac (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_mac is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_mac() directly. + + YANG Description: Destination IEEE 802 MAC address. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_mac must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True)""", + }) + + self.__destination_mac = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_mac(self): + self.__destination_mac = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + + + def _get_destination_mac_mask(self): + """ + Getter method for destination_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/destination_mac_mask (yang:mac-address) + + YANG Description: Destination IEEE 802 MAC address mask. + """ + return self.__destination_mac_mask + + def _set_destination_mac_mask(self, v, load=False): + """ + Setter method for destination_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/destination_mac_mask (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_mac_mask is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_mac_mask() directly. + + YANG Description: Destination IEEE 802 MAC address mask. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_mac_mask must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True)""", + }) + + self.__destination_mac_mask = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_mac_mask(self): + self.__destination_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + + + def _get_ethertype(self): + """ + Getter method for ethertype, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/ethertype (oc-pkt-match-types:ethertype-type) + + YANG Description: Ethertype field to match in Ethernet packets + """ + return self.__ethertype + + def _set_ethertype(self, v, load=False): + """ + Setter method for ethertype, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/ethertype (oc-pkt-match-types:ethertype-type) + If this variable is read-only (config: false) in the + source YANG file, then _set_ethertype is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ethertype() directly. + + YANG Description: Ethertype field to match in Ethernet packets + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'1..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ethertype must be of a type compatible with oc-pkt-match-types:ethertype-type""", + 'defined-type': "oc-pkt-match-types:ethertype-type", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'1..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=True)""", + }) + + self.__ethertype = t + if hasattr(self, '_set'): + self._set() + + def _unset_ethertype(self): + self.__ethertype = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'1..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=True) + + source_mac = __builtin__.property(_get_source_mac, _set_source_mac) + source_mac_mask = __builtin__.property(_get_source_mac_mask, _set_source_mac_mask) + destination_mac = __builtin__.property(_get_destination_mac, _set_destination_mac) + destination_mac_mask = __builtin__.property(_get_destination_mac_mask, _set_destination_mac_mask) + ethertype = __builtin__.property(_get_ethertype, _set_ethertype) + + + _pyangbind_elements = {'source_mac': source_mac, 'source_mac_mask': source_mac_mask, 'destination_mac': destination_mac, 'destination_mac_mask': destination_mac_mask, 'ethertype': ethertype, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/l2/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: State Information. + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__source_mac','__source_mac_mask','__destination_mac','__destination_mac_mask','__ethertype',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__source_mac = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + self.__destination_mac = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + self.__destination_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + self.__ethertype = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'1..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=False) + self.__source_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'l2', u'state'] + + def _get_source_mac(self): + """ + Getter method for source_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/source_mac (yang:mac-address) + + YANG Description: Source IEEE 802 MAC address. + """ + return self.__source_mac + + def _set_source_mac(self, v, load=False): + """ + Setter method for source_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/source_mac (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_mac is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_mac() directly. + + YANG Description: Source IEEE 802 MAC address. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_mac must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False)""", + }) + + self.__source_mac = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_mac(self): + self.__source_mac = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + + + def _get_source_mac_mask(self): + """ + Getter method for source_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/source_mac_mask (yang:mac-address) + + YANG Description: Source IEEE 802 MAC address mask. + """ + return self.__source_mac_mask + + def _set_source_mac_mask(self, v, load=False): + """ + Setter method for source_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/source_mac_mask (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_mac_mask is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_mac_mask() directly. + + YANG Description: Source IEEE 802 MAC address mask. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_mac_mask must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False)""", + }) + + self.__source_mac_mask = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_mac_mask(self): + self.__source_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + + + def _get_destination_mac(self): + """ + Getter method for destination_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/destination_mac (yang:mac-address) + + YANG Description: Destination IEEE 802 MAC address. + """ + return self.__destination_mac + + def _set_destination_mac(self, v, load=False): + """ + Setter method for destination_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/destination_mac (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_mac is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_mac() directly. + + YANG Description: Destination IEEE 802 MAC address. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_mac must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False)""", + }) + + self.__destination_mac = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_mac(self): + self.__destination_mac = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + + + def _get_destination_mac_mask(self): + """ + Getter method for destination_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/destination_mac_mask (yang:mac-address) + + YANG Description: Destination IEEE 802 MAC address mask. + """ + return self.__destination_mac_mask + + def _set_destination_mac_mask(self, v, load=False): + """ + Setter method for destination_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/destination_mac_mask (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_mac_mask is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_mac_mask() directly. + + YANG Description: Destination IEEE 802 MAC address mask. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_mac_mask must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False)""", + }) + + self.__destination_mac_mask = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_mac_mask(self): + self.__destination_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + + + def _get_ethertype(self): + """ + Getter method for ethertype, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/ethertype (oc-pkt-match-types:ethertype-type) + + YANG Description: Ethertype field to match in Ethernet packets + """ + return self.__ethertype + + def _set_ethertype(self, v, load=False): + """ + Setter method for ethertype, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/ethertype (oc-pkt-match-types:ethertype-type) + If this variable is read-only (config: false) in the + source YANG file, then _set_ethertype is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ethertype() directly. + + YANG Description: Ethertype field to match in Ethernet packets + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'1..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ethertype must be of a type compatible with oc-pkt-match-types:ethertype-type""", + 'defined-type': "oc-pkt-match-types:ethertype-type", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'1..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=False)""", + }) + + self.__ethertype = t + if hasattr(self, '_set'): + self._set() + + def _unset_ethertype(self): + self.__ethertype = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'1..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=False) + + source_mac = __builtin__.property(_get_source_mac) + source_mac_mask = __builtin__.property(_get_source_mac_mask) + destination_mac = __builtin__.property(_get_destination_mac) + destination_mac_mask = __builtin__.property(_get_destination_mac_mask) + ethertype = __builtin__.property(_get_ethertype) + + + _pyangbind_elements = {'source_mac': source_mac, 'source_mac_mask': source_mac_mask, 'destination_mac': destination_mac, 'destination_mac_mask': destination_mac_mask, 'ethertype': ethertype, } + + +class yc_l2_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/l2. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Ethernet header fields + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__config','__state',) + + _yang_name = 'l2' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'l2'] + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config (container) + + YANG Description: Configuration data + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configuration data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state (container) + + YANG Description: State Information. + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: State Information. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + config = __builtin__.property(_get_config, _set_config) + state = __builtin__.property(_get_state, _set_state) + + + _pyangbind_elements = {'config': config, 'state': state, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/ip/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configuration data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__ip_version','__source_ip_address','__source_ip_flow_label','__destination_ip_address','__destination_ip_flow_label','__dscp','__protocol','__hop_limit',) + + _yang_name = 'config' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__hop_limit = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=True) + self.__protocol = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..254']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=True) + self.__dscp = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=True) + self.__source_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True) + self.__destination_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True) + self.__ip_version = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'unknown': {'value': 0}, u'ipv4': {'value': 1}, u'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=True) + self.__destination_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True) + self.__source_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'ip', u'config'] + + def _get_ip_version(self): + """ + Getter method for ip_version, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/ip_version (inet:ip-version) + + YANG Description: IP version of the header. + """ + return self.__ip_version + + def _set_ip_version(self, v, load=False): + """ + Setter method for ip_version, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/ip_version (inet:ip-version) + If this variable is read-only (config: false) in the + source YANG file, then _set_ip_version is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ip_version() directly. + + YANG Description: IP version of the header. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'unknown': {'value': 0}, u'ipv4': {'value': 1}, u'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ip_version must be of a type compatible with inet:ip-version""", + 'defined-type': "inet:ip-version", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'unknown': {'value': 0}, u'ipv4': {'value': 1}, u'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=True)""", + }) + + self.__ip_version = t + if hasattr(self, '_set'): + self._set() + + def _unset_ip_version(self): + self.__ip_version = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'unknown': {'value': 0}, u'ipv4': {'value': 1}, u'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=True) + + + def _get_source_ip_address(self): + """ + Getter method for source_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/source_ip_address (inet:ip-prefix) + + YANG Description: Destination IP address prefix. + """ + return self.__source_ip_address + + def _set_source_ip_address(self, v, load=False): + """ + Setter method for source_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/source_ip_address (inet:ip-prefix) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_ip_address is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_ip_address() directly. + + YANG Description: Destination IP address prefix. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_ip_address must be of a type compatible with inet:ip-prefix""", + 'defined-type': "inet:ip-prefix", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True)""", + }) + + self.__source_ip_address = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_ip_address(self): + self.__source_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True) + + + def _get_source_ip_flow_label(self): + """ + Getter method for source_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/source_ip_flow_label (inet:ipv6-flow-label) + + YANG Description: Source IPv6 Flow label. + """ + return self.__source_ip_flow_label + + def _set_source_ip_flow_label(self, v, load=False): + """ + Setter method for source_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/source_ip_flow_label (inet:ipv6-flow-label) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_ip_flow_label is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_ip_flow_label() directly. + + YANG Description: Source IPv6 Flow label. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_ip_flow_label must be of a type compatible with inet:ipv6-flow-label""", + 'defined-type': "inet:ipv6-flow-label", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True)""", + }) + + self.__source_ip_flow_label = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_ip_flow_label(self): + self.__source_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True) + + + def _get_destination_ip_address(self): + """ + Getter method for destination_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/destination_ip_address (inet:ip-prefix) + + YANG Description: Destination IP address prefix. + """ + return self.__destination_ip_address + + def _set_destination_ip_address(self, v, load=False): + """ + Setter method for destination_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/destination_ip_address (inet:ip-prefix) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_ip_address is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_ip_address() directly. + + YANG Description: Destination IP address prefix. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_ip_address must be of a type compatible with inet:ip-prefix""", + 'defined-type': "inet:ip-prefix", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True)""", + }) + + self.__destination_ip_address = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_ip_address(self): + self.__destination_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True) + + + def _get_destination_ip_flow_label(self): + """ + Getter method for destination_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/destination_ip_flow_label (inet:ipv6-flow-label) + + YANG Description: Destination IPv6 Flow label. + """ + return self.__destination_ip_flow_label + + def _set_destination_ip_flow_label(self, v, load=False): + """ + Setter method for destination_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/destination_ip_flow_label (inet:ipv6-flow-label) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_ip_flow_label is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_ip_flow_label() directly. + + YANG Description: Destination IPv6 Flow label. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_ip_flow_label must be of a type compatible with inet:ipv6-flow-label""", + 'defined-type': "inet:ipv6-flow-label", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True)""", + }) + + self.__destination_ip_flow_label = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_ip_flow_label(self): + self.__destination_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True) + + + def _get_dscp(self): + """ + Getter method for dscp, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/dscp (inet:dscp) + + YANG Description: Value of diffserv codepoint. + """ + return self.__dscp + + def _set_dscp(self, v, load=False): + """ + Setter method for dscp, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/dscp (inet:dscp) + If this variable is read-only (config: false) in the + source YANG file, then _set_dscp is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_dscp() directly. + + YANG Description: Value of diffserv codepoint. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """dscp must be of a type compatible with inet:dscp""", + 'defined-type': "inet:dscp", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=True)""", + }) + + self.__dscp = t + if hasattr(self, '_set'): + self._set() + + def _unset_dscp(self): + self.__dscp = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=True) + + + def _get_protocol(self): + """ + Getter method for protocol, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/protocol (oc-pkt-match-types:ip-protocol-type) + + YANG Description: Internet Protocol number. + """ + return self.__protocol + + def _set_protocol(self, v, load=False): + """ + Setter method for protocol, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/protocol (oc-pkt-match-types:ip-protocol-type) + If this variable is read-only (config: false) in the + source YANG file, then _set_protocol is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_protocol() directly. + + YANG Description: Internet Protocol number. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..254']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """protocol must be of a type compatible with oc-pkt-match-types:ip-protocol-type""", + 'defined-type': "oc-pkt-match-types:ip-protocol-type", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..254']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=True)""", + }) + + self.__protocol = t + if hasattr(self, '_set'): + self._set() + + def _unset_protocol(self): + self.__protocol = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..254']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=True) + + + def _get_hop_limit(self): + """ + Getter method for hop_limit, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/hop_limit (uint8) + + YANG Description: The IP packet's hop limit -- known as TTL (in hops) in +IPv4 packets, and hop limit in IPv6 + """ + return self.__hop_limit + + def _set_hop_limit(self, v, load=False): + """ + Setter method for hop_limit, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/hop_limit (uint8) + If this variable is read-only (config: false) in the + source YANG file, then _set_hop_limit is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_hop_limit() directly. + + YANG Description: The IP packet's hop limit -- known as TTL (in hops) in +IPv4 packets, and hop limit in IPv6 + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """hop_limit must be of a type compatible with uint8""", + 'defined-type': "uint8", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=True)""", + }) + + self.__hop_limit = t + if hasattr(self, '_set'): + self._set() + + def _unset_hop_limit(self): + self.__hop_limit = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=True) + + ip_version = __builtin__.property(_get_ip_version, _set_ip_version) + source_ip_address = __builtin__.property(_get_source_ip_address, _set_source_ip_address) + source_ip_flow_label = __builtin__.property(_get_source_ip_flow_label, _set_source_ip_flow_label) + destination_ip_address = __builtin__.property(_get_destination_ip_address, _set_destination_ip_address) + destination_ip_flow_label = __builtin__.property(_get_destination_ip_flow_label, _set_destination_ip_flow_label) + dscp = __builtin__.property(_get_dscp, _set_dscp) + protocol = __builtin__.property(_get_protocol, _set_protocol) + hop_limit = __builtin__.property(_get_hop_limit, _set_hop_limit) + + + _pyangbind_elements = {'ip_version': ip_version, 'source_ip_address': source_ip_address, 'source_ip_flow_label': source_ip_flow_label, 'destination_ip_address': destination_ip_address, 'destination_ip_flow_label': destination_ip_flow_label, 'dscp': dscp, 'protocol': protocol, 'hop_limit': hop_limit, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/ip/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: State information + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__ip_version','__source_ip_address','__source_ip_flow_label','__destination_ip_address','__destination_ip_flow_label','__dscp','__protocol','__hop_limit',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__hop_limit = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=False) + self.__protocol = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..254']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=False) + self.__dscp = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=False) + self.__source_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False) + self.__destination_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False) + self.__ip_version = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'unknown': {'value': 0}, u'ipv4': {'value': 1}, u'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=False) + self.__destination_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False) + self.__source_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'ip', u'state'] + + def _get_ip_version(self): + """ + Getter method for ip_version, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/ip_version (inet:ip-version) + + YANG Description: IP version of the header. + """ + return self.__ip_version + + def _set_ip_version(self, v, load=False): + """ + Setter method for ip_version, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/ip_version (inet:ip-version) + If this variable is read-only (config: false) in the + source YANG file, then _set_ip_version is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ip_version() directly. + + YANG Description: IP version of the header. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'unknown': {'value': 0}, u'ipv4': {'value': 1}, u'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ip_version must be of a type compatible with inet:ip-version""", + 'defined-type': "inet:ip-version", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'unknown': {'value': 0}, u'ipv4': {'value': 1}, u'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=False)""", + }) + + self.__ip_version = t + if hasattr(self, '_set'): + self._set() + + def _unset_ip_version(self): + self.__ip_version = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'unknown': {'value': 0}, u'ipv4': {'value': 1}, u'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=False) + + + def _get_source_ip_address(self): + """ + Getter method for source_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/source_ip_address (inet:ip-prefix) + + YANG Description: Destination IP address prefix. + """ + return self.__source_ip_address + + def _set_source_ip_address(self, v, load=False): + """ + Setter method for source_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/source_ip_address (inet:ip-prefix) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_ip_address is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_ip_address() directly. + + YANG Description: Destination IP address prefix. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_ip_address must be of a type compatible with inet:ip-prefix""", + 'defined-type': "inet:ip-prefix", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False)""", + }) + + self.__source_ip_address = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_ip_address(self): + self.__source_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False) + + + def _get_source_ip_flow_label(self): + """ + Getter method for source_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/source_ip_flow_label (inet:ipv6-flow-label) + + YANG Description: Source IPv6 Flow label. + """ + return self.__source_ip_flow_label + + def _set_source_ip_flow_label(self, v, load=False): + """ + Setter method for source_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/source_ip_flow_label (inet:ipv6-flow-label) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_ip_flow_label is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_ip_flow_label() directly. + + YANG Description: Source IPv6 Flow label. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_ip_flow_label must be of a type compatible with inet:ipv6-flow-label""", + 'defined-type': "inet:ipv6-flow-label", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False)""", + }) + + self.__source_ip_flow_label = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_ip_flow_label(self): + self.__source_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False) + + + def _get_destination_ip_address(self): + """ + Getter method for destination_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/destination_ip_address (inet:ip-prefix) + + YANG Description: Destination IP address prefix. + """ + return self.__destination_ip_address + + def _set_destination_ip_address(self, v, load=False): + """ + Setter method for destination_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/destination_ip_address (inet:ip-prefix) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_ip_address is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_ip_address() directly. + + YANG Description: Destination IP address prefix. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_ip_address must be of a type compatible with inet:ip-prefix""", + 'defined-type': "inet:ip-prefix", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False)""", + }) + + self.__destination_ip_address = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_ip_address(self): + self.__destination_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False) + + + def _get_destination_ip_flow_label(self): + """ + Getter method for destination_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/destination_ip_flow_label (inet:ipv6-flow-label) + + YANG Description: Destination IPv6 Flow label. + """ + return self.__destination_ip_flow_label + + def _set_destination_ip_flow_label(self, v, load=False): + """ + Setter method for destination_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/destination_ip_flow_label (inet:ipv6-flow-label) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_ip_flow_label is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_ip_flow_label() directly. + + YANG Description: Destination IPv6 Flow label. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_ip_flow_label must be of a type compatible with inet:ipv6-flow-label""", + 'defined-type': "inet:ipv6-flow-label", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False)""", + }) + + self.__destination_ip_flow_label = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_ip_flow_label(self): + self.__destination_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False) + + + def _get_dscp(self): + """ + Getter method for dscp, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/dscp (inet:dscp) + + YANG Description: Value of diffserv codepoint. + """ + return self.__dscp + + def _set_dscp(self, v, load=False): + """ + Setter method for dscp, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/dscp (inet:dscp) + If this variable is read-only (config: false) in the + source YANG file, then _set_dscp is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_dscp() directly. + + YANG Description: Value of diffserv codepoint. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """dscp must be of a type compatible with inet:dscp""", + 'defined-type': "inet:dscp", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=False)""", + }) + + self.__dscp = t + if hasattr(self, '_set'): + self._set() + + def _unset_dscp(self): + self.__dscp = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=False) + + + def _get_protocol(self): + """ + Getter method for protocol, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/protocol (oc-pkt-match-types:ip-protocol-type) + + YANG Description: Internet Protocol number. + """ + return self.__protocol + + def _set_protocol(self, v, load=False): + """ + Setter method for protocol, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/protocol (oc-pkt-match-types:ip-protocol-type) + If this variable is read-only (config: false) in the + source YANG file, then _set_protocol is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_protocol() directly. + + YANG Description: Internet Protocol number. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..254']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """protocol must be of a type compatible with oc-pkt-match-types:ip-protocol-type""", + 'defined-type': "oc-pkt-match-types:ip-protocol-type", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..254']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=False)""", + }) + + self.__protocol = t + if hasattr(self, '_set'): + self._set() + + def _unset_protocol(self): + self.__protocol = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..254']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=False) + + + def _get_hop_limit(self): + """ + Getter method for hop_limit, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/hop_limit (uint8) + + YANG Description: The IP packet's hop limit -- known as TTL (in hops) in +IPv4 packets, and hop limit in IPv6 + """ + return self.__hop_limit + + def _set_hop_limit(self, v, load=False): + """ + Setter method for hop_limit, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/hop_limit (uint8) + If this variable is read-only (config: false) in the + source YANG file, then _set_hop_limit is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_hop_limit() directly. + + YANG Description: The IP packet's hop limit -- known as TTL (in hops) in +IPv4 packets, and hop limit in IPv6 + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """hop_limit must be of a type compatible with uint8""", + 'defined-type': "uint8", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=False)""", + }) + + self.__hop_limit = t + if hasattr(self, '_set'): + self._set() + + def _unset_hop_limit(self): + self.__hop_limit = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=False) + + ip_version = __builtin__.property(_get_ip_version) + source_ip_address = __builtin__.property(_get_source_ip_address) + source_ip_flow_label = __builtin__.property(_get_source_ip_flow_label) + destination_ip_address = __builtin__.property(_get_destination_ip_address) + destination_ip_flow_label = __builtin__.property(_get_destination_ip_flow_label) + dscp = __builtin__.property(_get_dscp) + protocol = __builtin__.property(_get_protocol) + hop_limit = __builtin__.property(_get_hop_limit) + + + _pyangbind_elements = {'ip_version': ip_version, 'source_ip_address': source_ip_address, 'source_ip_flow_label': source_ip_flow_label, 'destination_ip_address': destination_ip_address, 'destination_ip_flow_label': destination_ip_flow_label, 'dscp': dscp, 'protocol': protocol, 'hop_limit': hop_limit, } + + +class yc_ip_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/ip. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Top level container + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__config','__state',) + + _yang_name = 'ip' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'ip'] + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config (container) + + YANG Description: Configuration data + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configuration data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state (container) + + YANG Description: State information + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: State information + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + config = __builtin__.property(_get_config, _set_config) + state = __builtin__.property(_get_state, _set_state) + + + _pyangbind_elements = {'config': config, 'state': state, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/transport/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configuration data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__source_port','__destination_port','__tcp_flags',) + + _yang_name = 'config' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__source_port = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True) + self.__tcp_flags = YANGDynClass(base=TypedListType(allowed_type=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + self.__destination_port = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'transport', u'config'] + + def _get_source_port(self): + """ + Getter method for source_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config/source_port (oc-pkt-match-types:port-num-range) + + YANG Description: Source port or range + """ + return self.__source_port + + def _set_source_port(self, v, load=False): + """ + Setter method for source_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config/source_port (oc-pkt-match-types:port-num-range) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_port is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_port() directly. + + YANG Description: Source port or range + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_port must be of a type compatible with oc-pkt-match-types:port-num-range""", + 'defined-type': "oc-pkt-match-types:port-num-range", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True)""", + }) + + self.__source_port = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_port(self): + self.__source_port = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True) + + + def _get_destination_port(self): + """ + Getter method for destination_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config/destination_port (oc-pkt-match-types:port-num-range) + + YANG Description: Destination port or range + """ + return self.__destination_port + + def _set_destination_port(self, v, load=False): + """ + Setter method for destination_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config/destination_port (oc-pkt-match-types:port-num-range) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_port is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_port() directly. + + YANG Description: Destination port or range + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_port must be of a type compatible with oc-pkt-match-types:port-num-range""", + 'defined-type': "oc-pkt-match-types:port-num-range", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True)""", + }) + + self.__destination_port = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_port(self): + self.__destination_port = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True) + + + def _get_tcp_flags(self): + """ + Getter method for tcp_flags, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config/tcp_flags (identityref) + + YANG Description: List of TCP flags to match + """ + return self.__tcp_flags + + def _set_tcp_flags(self, v, load=False): + """ + Setter method for tcp_flags, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config/tcp_flags (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_tcp_flags is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_tcp_flags() directly. + + YANG Description: List of TCP flags to match + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=TypedListType(allowed_type=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """tcp_flags must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=TypedListType(allowed_type=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True)""", + }) + + self.__tcp_flags = t + if hasattr(self, '_set'): + self._set() + + def _unset_tcp_flags(self): + self.__tcp_flags = YANGDynClass(base=TypedListType(allowed_type=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + + source_port = __builtin__.property(_get_source_port, _set_source_port) + destination_port = __builtin__.property(_get_destination_port, _set_destination_port) + tcp_flags = __builtin__.property(_get_tcp_flags, _set_tcp_flags) + + + _pyangbind_elements = {'source_port': source_port, 'destination_port': destination_port, 'tcp_flags': tcp_flags, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/transport/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: State data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__source_port','__destination_port','__tcp_flags',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__source_port = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False) + self.__tcp_flags = YANGDynClass(base=TypedListType(allowed_type=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + self.__destination_port = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'transport', u'state'] + + def _get_source_port(self): + """ + Getter method for source_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state/source_port (oc-pkt-match-types:port-num-range) + + YANG Description: Source port or range + """ + return self.__source_port + + def _set_source_port(self, v, load=False): + """ + Setter method for source_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state/source_port (oc-pkt-match-types:port-num-range) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_port is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_port() directly. + + YANG Description: Source port or range + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_port must be of a type compatible with oc-pkt-match-types:port-num-range""", + 'defined-type': "oc-pkt-match-types:port-num-range", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False)""", + }) + + self.__source_port = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_port(self): + self.__source_port = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False) + + + def _get_destination_port(self): + """ + Getter method for destination_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state/destination_port (oc-pkt-match-types:port-num-range) + + YANG Description: Destination port or range + """ + return self.__destination_port + + def _set_destination_port(self, v, load=False): + """ + Setter method for destination_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state/destination_port (oc-pkt-match-types:port-num-range) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_port is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_port() directly. + + YANG Description: Destination port or range + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_port must be of a type compatible with oc-pkt-match-types:port-num-range""", + 'defined-type': "oc-pkt-match-types:port-num-range", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False)""", + }) + + self.__destination_port = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_port(self): + self.__destination_port = YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False) + + + def _get_tcp_flags(self): + """ + Getter method for tcp_flags, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state/tcp_flags (identityref) + + YANG Description: List of TCP flags to match + """ + return self.__tcp_flags + + def _set_tcp_flags(self, v, load=False): + """ + Setter method for tcp_flags, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state/tcp_flags (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_tcp_flags is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_tcp_flags() directly. + + YANG Description: List of TCP flags to match + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=TypedListType(allowed_type=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """tcp_flags must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=TypedListType(allowed_type=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False)""", + }) + + self.__tcp_flags = t + if hasattr(self, '_set'): + self._set() + + def _unset_tcp_flags(self): + self.__tcp_flags = YANGDynClass(base=TypedListType(allowed_type=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + + source_port = __builtin__.property(_get_source_port) + destination_port = __builtin__.property(_get_destination_port) + tcp_flags = __builtin__.property(_get_tcp_flags) + + + _pyangbind_elements = {'source_port': source_port, 'destination_port': destination_port, 'tcp_flags': tcp_flags, } + + +class yc_transport_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/transport. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Transport fields container + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__config','__state',) + + _yang_name = 'transport' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'transport'] + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config (container) + + YANG Description: Configuration data + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configuration data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state (container) + + YANG Description: State data + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: State data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + config = __builtin__.property(_get_config, _set_config) + state = __builtin__.property(_get_state, _set_state) + + + _pyangbind_elements = {'config': config, 'state': state, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/input-interface/interface-ref/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configured reference to interface / subinterface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__interface','__subinterface',) + + _yang_name = 'config' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__interface = YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__subinterface = YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'input-interface', u'interface-ref', u'config'] + + def _get_interface(self): + """ + Getter method for interface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/config/interface (leafref) + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + return self.__interface + + def _set_interface(self, v, load=False): + """ + Setter method for interface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/config/interface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface() directly. + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__interface = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface(self): + self.__interface = YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_subinterface(self): + """ + Getter method for subinterface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/config/subinterface (leafref) + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + return self.__subinterface + + def _set_subinterface(self, v, load=False): + """ + Setter method for subinterface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/config/subinterface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_subinterface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_subinterface() directly. + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """subinterface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__subinterface = t + if hasattr(self, '_set'): + self._set() + + def _unset_subinterface(self): + self.__subinterface = YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + interface = __builtin__.property(_get_interface, _set_interface) + subinterface = __builtin__.property(_get_subinterface, _set_subinterface) + + + _pyangbind_elements = {'interface': interface, 'subinterface': subinterface, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/input-interface/interface-ref/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state for interface-ref + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__interface','__subinterface',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__interface = YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + self.__subinterface = YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'input-interface', u'interface-ref', u'state'] + + def _get_interface(self): + """ + Getter method for interface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/state/interface (leafref) + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + return self.__interface + + def _set_interface(self, v, load=False): + """ + Setter method for interface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/state/interface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface() directly. + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__interface = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface(self): + self.__interface = YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + + def _get_subinterface(self): + """ + Getter method for subinterface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/state/subinterface (leafref) + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + return self.__subinterface + + def _set_subinterface(self, v, load=False): + """ + Setter method for subinterface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/state/subinterface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_subinterface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_subinterface() directly. + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """subinterface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__subinterface = t + if hasattr(self, '_set'): + self._set() + + def _unset_subinterface(self): + self.__subinterface = YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + interface = __builtin__.property(_get_interface) + subinterface = __builtin__.property(_get_subinterface) + + + _pyangbind_elements = {'interface': interface, 'subinterface': subinterface, } + + +class yc_interface_ref_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/input-interface/interface-ref. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Reference to an interface or subinterface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__config','__state',) + + _yang_name = 'interface-ref' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'input-interface', u'interface-ref'] + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/config (container) + + YANG Description: Configured reference to interface / subinterface + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configured reference to interface / subinterface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/state (container) + + YANG Description: Operational state for interface-ref + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state for interface-ref + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + config = __builtin__.property(_get_config, _set_config) + state = __builtin__.property(_get_state, _set_state) + + + _pyangbind_elements = {'config': config, 'state': state, } + + +class yc_input_interface_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/input-interface. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Input interface container + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__interface_ref',) + + _yang_name = 'input-interface' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__interface_ref = YANGDynClass(base=yc_interface_ref_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'input-interface'] + + def _get_interface_ref(self): + """ + Getter method for interface_ref, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref (container) + + YANG Description: Reference to an interface or subinterface + """ + return self.__interface_ref + + def _set_interface_ref(self, v, load=False): + """ + Setter method for interface_ref, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface_ref is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface_ref() directly. + + YANG Description: Reference to an interface or subinterface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_interface_ref_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface_ref must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_interface_ref_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__interface_ref = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface_ref(self): + self.__interface_ref = YANGDynClass(base=yc_interface_ref_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + interface_ref = __builtin__.property(_get_interface_ref, _set_interface_ref) + + + _pyangbind_elements = {'interface_ref': interface_ref, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/actions/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Config data for ACL actions + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__forwarding_action','__log_action',) + + _yang_name = 'config' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__forwarding_action = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + self.__log_action = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), default=unicode("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'actions', u'config'] + + def _get_forwarding_action(self): + """ + Getter method for forwarding_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/config/forwarding_action (identityref) + + YANG Description: Specifies the forwarding action. One forwarding action +must be specified for each ACL entry + """ + return self.__forwarding_action + + def _set_forwarding_action(self, v, load=False): + """ + Setter method for forwarding_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/config/forwarding_action (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_forwarding_action is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_forwarding_action() directly. + + YANG Description: Specifies the forwarding action. One forwarding action +must be specified for each ACL entry + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """forwarding_action must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True)""", + }) + + self.__forwarding_action = t + if hasattr(self, '_set'): + self._set() + + def _unset_forwarding_action(self): + self.__forwarding_action = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + + + def _get_log_action(self): + """ + Getter method for log_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/config/log_action (identityref) + + YANG Description: Specifies the log action and destination for +matched packets. The default is not to log the +packet. + """ + return self.__log_action + + def _set_log_action(self, v, load=False): + """ + Setter method for log_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/config/log_action (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_log_action is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_log_action() directly. + + YANG Description: Specifies the log action and destination for +matched packets. The default is not to log the +packet. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), default=unicode("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """log_action must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), default=unicode("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True)""", + }) + + self.__log_action = t + if hasattr(self, '_set'): + self._set() + + def _unset_log_action(self): + self.__log_action = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), default=unicode("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + + forwarding_action = __builtin__.property(_get_forwarding_action, _set_forwarding_action) + log_action = __builtin__.property(_get_log_action, _set_log_action) + + + _pyangbind_elements = {'forwarding_action': forwarding_action, 'log_action': log_action, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/actions/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: State information for ACL actions + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__forwarding_action','__log_action',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__forwarding_action = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + self.__log_action = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), default=unicode("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'actions', u'state'] + + def _get_forwarding_action(self): + """ + Getter method for forwarding_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/state/forwarding_action (identityref) + + YANG Description: Specifies the forwarding action. One forwarding action +must be specified for each ACL entry + """ + return self.__forwarding_action + + def _set_forwarding_action(self, v, load=False): + """ + Setter method for forwarding_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/state/forwarding_action (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_forwarding_action is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_forwarding_action() directly. + + YANG Description: Specifies the forwarding action. One forwarding action +must be specified for each ACL entry + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """forwarding_action must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False)""", + }) + + self.__forwarding_action = t + if hasattr(self, '_set'): + self._set() + + def _unset_forwarding_action(self): + self.__forwarding_action = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + + + def _get_log_action(self): + """ + Getter method for log_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/state/log_action (identityref) + + YANG Description: Specifies the log action and destination for +matched packets. The default is not to log the +packet. + """ + return self.__log_action + + def _set_log_action(self, v, load=False): + """ + Setter method for log_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/state/log_action (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_log_action is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_log_action() directly. + + YANG Description: Specifies the log action and destination for +matched packets. The default is not to log the +packet. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), default=unicode("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """log_action must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), default=unicode("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False)""", + }) + + self.__log_action = t + if hasattr(self, '_set'): + self._set() + + def _unset_log_action(self): + self.__log_action = YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), default=unicode("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + + forwarding_action = __builtin__.property(_get_forwarding_action) + log_action = __builtin__.property(_get_log_action) + + + _pyangbind_elements = {'forwarding_action': forwarding_action, 'log_action': log_action, } + + +class yc_actions_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/actions. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Enclosing container for list of ACL actions associated +with an entry + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__config','__state',) + + _yang_name = 'actions' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry', u'actions'] + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/config (container) + + YANG Description: Config data for ACL actions + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Config data for ACL actions + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/state (container) + + YANG Description: State information for ACL actions + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: State information for ACL actions + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + config = __builtin__.property(_get_config, _set_config) + state = __builtin__.property(_get_state, _set_state) + + + _pyangbind_elements = {'config': config, 'state': state, } + + +class yc_acl_entry_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of ACL entries comprising an ACL set + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__config','__state','__l2','__ip','__transport','__input_interface','__actions',) + + _yang_name = 'acl-entry' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__ip = YANGDynClass(base=yc_ip_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip, is_container='container', yang_name="ip", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__input_interface = YANGDynClass(base=yc_input_interface_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface, is_container='container', yang_name="input-interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__actions = YANGDynClass(base=yc_actions_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions, is_container='container', yang_name="actions", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__sequence_id = YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__l2 = YANGDynClass(base=yc_l2_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2, is_container='container', yang_name="l2", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__transport = YANGDynClass(base=yc_transport_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport, is_container='container', yang_name="transport", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries', u'acl-entry'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/sequence_id (leafref) + + YANG Description: references the list key + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/sequence_id (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: references the list key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/config (container) + + YANG Description: Access list entries config + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Access list entries config + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state (container) + + YANG Description: State information for ACL entries + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: State information for ACL entries + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_l2(self): + """ + Getter method for l2, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2 (container) + + YANG Description: Ethernet header fields + """ + return self.__l2 + + def _set_l2(self, v, load=False): + """ + Setter method for l2, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2 (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_l2 is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_l2() directly. + + YANG Description: Ethernet header fields + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_l2_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2, is_container='container', yang_name="l2", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """l2 must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_l2_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2, is_container='container', yang_name="l2", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__l2 = t + if hasattr(self, '_set'): + self._set() + + def _unset_l2(self): + self.__l2 = YANGDynClass(base=yc_l2_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2, is_container='container', yang_name="l2", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_ip(self): + """ + Getter method for ip, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip (container) + + YANG Description: Top level container + """ + return self.__ip + + def _set_ip(self, v, load=False): + """ + Setter method for ip, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_ip is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ip() directly. + + YANG Description: Top level container + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_ip_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip, is_container='container', yang_name="ip", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ip must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_ip_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip, is_container='container', yang_name="ip", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__ip = t + if hasattr(self, '_set'): + self._set() + + def _unset_ip(self): + self.__ip = YANGDynClass(base=yc_ip_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip, is_container='container', yang_name="ip", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_transport(self): + """ + Getter method for transport, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport (container) + + YANG Description: Transport fields container + """ + return self.__transport + + def _set_transport(self, v, load=False): + """ + Setter method for transport, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_transport is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_transport() directly. + + YANG Description: Transport fields container + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_transport_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport, is_container='container', yang_name="transport", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """transport must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_transport_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport, is_container='container', yang_name="transport", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__transport = t + if hasattr(self, '_set'): + self._set() + + def _unset_transport(self): + self.__transport = YANGDynClass(base=yc_transport_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport, is_container='container', yang_name="transport", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_input_interface(self): + """ + Getter method for input_interface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface (container) + + YANG Description: Input interface container + """ + return self.__input_interface + + def _set_input_interface(self, v, load=False): + """ + Setter method for input_interface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_input_interface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_input_interface() directly. + + YANG Description: Input interface container + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_input_interface_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface, is_container='container', yang_name="input-interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """input_interface must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_input_interface_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface, is_container='container', yang_name="input-interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__input_interface = t + if hasattr(self, '_set'): + self._set() + + def _unset_input_interface(self): + self.__input_interface = YANGDynClass(base=yc_input_interface_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface, is_container='container', yang_name="input-interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_actions(self): + """ + Getter method for actions, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions (container) + + YANG Description: Enclosing container for list of ACL actions associated +with an entry + """ + return self.__actions + + def _set_actions(self, v, load=False): + """ + Setter method for actions, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_actions is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_actions() directly. + + YANG Description: Enclosing container for list of ACL actions associated +with an entry + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_actions_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions, is_container='container', yang_name="actions", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """actions must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_actions_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions, is_container='container', yang_name="actions", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__actions = t + if hasattr(self, '_set'): + self._set() + + def _unset_actions(self): + self.__actions = YANGDynClass(base=yc_actions_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions, is_container='container', yang_name="actions", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + sequence_id = __builtin__.property(_get_sequence_id, _set_sequence_id) + config = __builtin__.property(_get_config, _set_config) + state = __builtin__.property(_get_state, _set_state) + l2 = __builtin__.property(_get_l2, _set_l2) + ip = __builtin__.property(_get_ip, _set_ip) + transport = __builtin__.property(_get_transport, _set_transport) + input_interface = __builtin__.property(_get_input_interface, _set_input_interface) + actions = __builtin__.property(_get_actions, _set_actions) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'config': config, 'state': state, 'l2': l2, 'ip': ip, 'transport': transport, 'input_interface': input_interface, 'actions': actions, } + + +class yc_acl_entries_openconfig_acl__acl_acl_sets_acl_set_acl_entries(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Access list entries container + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__acl_entry',) + + _yang_name = 'acl-entries' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__acl_entry = YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set', u'acl-entries'] + + def _get_acl_entry(self): + """ + Getter method for acl_entry, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry (list) + + YANG Description: List of ACL entries comprising an ACL set + """ + return self.__acl_entry + + def _set_acl_entry(self, v, load=False): + """ + Setter method for acl_entry, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_entry is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_entry() directly. + + YANG Description: List of ACL entries comprising an ACL set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_entry must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True)""", + }) + + self.__acl_entry = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_entry(self): + self.__acl_entry = YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + acl_entry = __builtin__.property(_get_acl_entry, _set_acl_entry) + + + _pyangbind_elements = {'acl_entry': acl_entry, } + + +class yc_acl_set_openconfig_acl__acl_acl_sets_acl_set(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of ACL sets, each comprising of a list of ACL +entries + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__name','__config','__state','__acl_entries',) + + _yang_name = 'acl-set' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__name = YANGDynClass(base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__acl_entries = YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_acl_sets_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets', u'acl-set'] + + def _get_name(self): + """ + Getter method for name, mapped from YANG variable /acl/acl_sets/acl_set/name (leafref) + + YANG Description: Reference to the name list key + """ + return self.__name + + def _set_name(self, v, load=False): + """ + Setter method for name, mapped from YANG variable /acl/acl_sets/acl_set/name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_name() directly. + + YANG Description: Reference to the name list key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__name = t + if hasattr(self, '_set'): + self._set() + + def _unset_name(self): + self.__name = YANGDynClass(base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/config (container) + + YANG Description: Access list config + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Access list config + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/state (container) + + YANG Description: Access list state information + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Access list state information + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_acl_entries(self): + """ + Getter method for acl_entries, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries (container) + + YANG Description: Access list entries container + """ + return self.__acl_entries + + def _set_acl_entries(self, v, load=False): + """ + Setter method for acl_entries, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_entries is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_entries() directly. + + YANG Description: Access list entries container + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_acl_entries_openconfig_acl__acl_acl_sets_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_entries must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_acl_sets_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__acl_entries = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_entries(self): + self.__acl_entries = YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_acl_sets_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + name = __builtin__.property(_get_name, _set_name) + config = __builtin__.property(_get_config, _set_config) + state = __builtin__.property(_get_state, _set_state) + acl_entries = __builtin__.property(_get_acl_entries, _set_acl_entries) + + + _pyangbind_elements = {'name': name, 'config': config, 'state': state, 'acl_entries': acl_entries, } + + +class yc_acl_sets_openconfig_acl__acl_acl_sets(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Access list entries variables enclosing container + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__acl_set',) + + _yang_name = 'acl-sets' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__acl_set = YANGDynClass(base=YANGListType("name",yc_acl_set_openconfig_acl__acl_acl_sets_acl_set, yang_name="acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='name', extensions=None), is_container='list', yang_name="acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'acl-sets'] + + def _get_acl_set(self): + """ + Getter method for acl_set, mapped from YANG variable /acl/acl_sets/acl_set (list) + + YANG Description: List of ACL sets, each comprising of a list of ACL +entries + """ + return self.__acl_set + + def _set_acl_set(self, v, load=False): + """ + Setter method for acl_set, mapped from YANG variable /acl/acl_sets/acl_set (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_set is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_set() directly. + + YANG Description: List of ACL sets, each comprising of a list of ACL +entries + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("name",yc_acl_set_openconfig_acl__acl_acl_sets_acl_set, yang_name="acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='name', extensions=None), is_container='list', yang_name="acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_set must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("name",yc_acl_set_openconfig_acl__acl_acl_sets_acl_set, yang_name="acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='name', extensions=None), is_container='list', yang_name="acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True)""", + }) + + self.__acl_set = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_set(self): + self.__acl_set = YANGDynClass(base=YANGListType("name",yc_acl_set_openconfig_acl__acl_acl_sets_acl_set, yang_name="acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='name', extensions=None), is_container='list', yang_name="acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + acl_set = __builtin__.property(_get_acl_set, _set_acl_set) + + + _pyangbind_elements = {'acl_set': acl_set, } + + +class yc_config_openconfig_acl__acl_interfaces_interface_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configuration for ACL per-interface data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__id',) + + _yang_name = 'config' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__id = YANGDynClass(base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'config'] + + def _get_id(self): + """ + Getter method for id, mapped from YANG variable /acl/interfaces/interface/config/id (oc-if:interface-id) + + YANG Description: User-defined identifier for the interface -- a common +convention could be '.' + """ + return self.__id + + def _set_id(self, v, load=False): + """ + Setter method for id, mapped from YANG variable /acl/interfaces/interface/config/id (oc-if:interface-id) + If this variable is read-only (config: false) in the + source YANG file, then _set_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_id() directly. + + YANG Description: User-defined identifier for the interface -- a common +convention could be '.' + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """id must be of a type compatible with oc-if:interface-id""", + 'defined-type': "oc-if:interface-id", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=True)""", + }) + + self.__id = t + if hasattr(self, '_set'): + self._set() + + def _unset_id(self): + self.__id = YANGDynClass(base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=True) + + id = __builtin__.property(_get_id, _set_id) + + + _pyangbind_elements = {'id': id, } + + +class yc_state_openconfig_acl__acl_interfaces_interface_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state for ACL per-interface data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__id',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__id = YANGDynClass(base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'state'] + + def _get_id(self): + """ + Getter method for id, mapped from YANG variable /acl/interfaces/interface/state/id (oc-if:interface-id) + + YANG Description: User-defined identifier for the interface -- a common +convention could be '.' + """ + return self.__id + + def _set_id(self, v, load=False): + """ + Setter method for id, mapped from YANG variable /acl/interfaces/interface/state/id (oc-if:interface-id) + If this variable is read-only (config: false) in the + source YANG file, then _set_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_id() directly. + + YANG Description: User-defined identifier for the interface -- a common +convention could be '.' + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """id must be of a type compatible with oc-if:interface-id""", + 'defined-type': "oc-if:interface-id", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=False)""", + }) + + self.__id = t + if hasattr(self, '_set'): + self._set() + + def _unset_id(self): + self.__id = YANGDynClass(base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=False) + + id = __builtin__.property(_get_id) + + + _pyangbind_elements = {'id': id, } + + +class yc_config_openconfig_acl__acl_interfaces_interface_interface_ref_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/interface-ref/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configured reference to interface / subinterface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__interface','__subinterface',) + + _yang_name = 'config' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__interface = YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__subinterface = YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'interface-ref', u'config'] + + def _get_interface(self): + """ + Getter method for interface, mapped from YANG variable /acl/interfaces/interface/interface_ref/config/interface (leafref) + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + return self.__interface + + def _set_interface(self, v, load=False): + """ + Setter method for interface, mapped from YANG variable /acl/interfaces/interface/interface_ref/config/interface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface() directly. + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__interface = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface(self): + self.__interface = YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_subinterface(self): + """ + Getter method for subinterface, mapped from YANG variable /acl/interfaces/interface/interface_ref/config/subinterface (leafref) + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + return self.__subinterface + + def _set_subinterface(self, v, load=False): + """ + Setter method for subinterface, mapped from YANG variable /acl/interfaces/interface/interface_ref/config/subinterface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_subinterface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_subinterface() directly. + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """subinterface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__subinterface = t + if hasattr(self, '_set'): + self._set() + + def _unset_subinterface(self): + self.__subinterface = YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + interface = __builtin__.property(_get_interface, _set_interface) + subinterface = __builtin__.property(_get_subinterface, _set_subinterface) + + + _pyangbind_elements = {'interface': interface, 'subinterface': subinterface, } + + +class yc_state_openconfig_acl__acl_interfaces_interface_interface_ref_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/interface-ref/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state for interface-ref + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__interface','__subinterface',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__interface = YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + self.__subinterface = YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'interface-ref', u'state'] + + def _get_interface(self): + """ + Getter method for interface, mapped from YANG variable /acl/interfaces/interface/interface_ref/state/interface (leafref) + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + return self.__interface + + def _set_interface(self, v, load=False): + """ + Setter method for interface, mapped from YANG variable /acl/interfaces/interface/interface_ref/state/interface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface() directly. + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__interface = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface(self): + self.__interface = YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + + def _get_subinterface(self): + """ + Getter method for subinterface, mapped from YANG variable /acl/interfaces/interface/interface_ref/state/subinterface (leafref) + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + return self.__subinterface + + def _set_subinterface(self, v, load=False): + """ + Setter method for subinterface, mapped from YANG variable /acl/interfaces/interface/interface_ref/state/subinterface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_subinterface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_subinterface() directly. + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """subinterface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__subinterface = t + if hasattr(self, '_set'): + self._set() + + def _unset_subinterface(self): + self.__subinterface = YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + interface = __builtin__.property(_get_interface) + subinterface = __builtin__.property(_get_subinterface) + + + _pyangbind_elements = {'interface': interface, 'subinterface': subinterface, } + + +class yc_interface_ref_openconfig_acl__acl_interfaces_interface_interface_ref(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/interface-ref. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Reference to an interface or subinterface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__config','__state',) + + _yang_name = 'interface-ref' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'interface-ref'] + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/interfaces/interface/interface_ref/config (container) + + YANG Description: Configured reference to interface / subinterface + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/interfaces/interface/interface_ref/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configured reference to interface / subinterface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_interfaces_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/interfaces/interface/interface_ref/state (container) + + YANG Description: Operational state for interface-ref + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/interfaces/interface/interface_ref/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state for interface-ref + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_interfaces_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + config = __builtin__.property(_get_config, _set_config) + state = __builtin__.property(_get_state, _set_state) + + + _pyangbind_elements = {'config': config, 'state': state, } + + +class yc_config_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets/ingress-acl-set/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configuration data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__set_name',) + + _yang_name = 'config' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__set_name = YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'ingress-acl-sets', u'ingress-acl-set', u'config'] + + def _get_set_name(self): + """ + Getter method for set_name, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/config/set_name (leafref) + + YANG Description: Reference to the ACL set applied on ingress + """ + return self.__set_name + + def _set_set_name(self, v, load=False): + """ + Setter method for set_name, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/config/set_name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_set_name() directly. + + YANG Description: Reference to the ACL set applied on ingress + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """set_name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__set_name = t + if hasattr(self, '_set'): + self._set() + + def _unset_set_name(self): + self.__set_name = YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + set_name = __builtin__.property(_get_set_name, _set_set_name) + + + _pyangbind_elements = {'set_name': set_name, } + + +class yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets/ingress-acl-set/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state data for interface ingress ACLs + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__set_name',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__set_name = YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'ingress-acl-sets', u'ingress-acl-set', u'state'] + + def _get_set_name(self): + """ + Getter method for set_name, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/state/set_name (leafref) + + YANG Description: Reference to the ACL set applied on ingress + """ + return self.__set_name + + def _set_set_name(self, v, load=False): + """ + Setter method for set_name, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/state/set_name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_set_name() directly. + + YANG Description: Reference to the ACL set applied on ingress + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """set_name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__set_name = t + if hasattr(self, '_set'): + self._set() + + def _unset_set_name(self): + self.__set_name = YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + set_name = __builtin__.property(_get_set_name) + + + _pyangbind_elements = {'set_name': set_name, } + + +class yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets/ingress-acl-set/acl-entries/acl-entry/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state data for per-interface ACL entries + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__matched_packets','__matched_octets',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__sequence_id = YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + self.__matched_packets = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + self.__matched_octets = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'ingress-acl-sets', u'ingress-acl-set', u'acl-entries', u'acl-entry', u'state'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state/sequence_id (leafref) + + YANG Description: Reference to an entry in the ACL set applied to an +interface + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state/sequence_id (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: Reference to an entry in the ACL set applied to an +interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + + def _get_matched_packets(self): + """ + Getter method for matched_packets, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state/matched_packets (yang:counter64) + + YANG Description: Count of the number of packets matching the current ACL +entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + return self.__matched_packets + + def _set_matched_packets(self, v, load=False): + """ + Setter method for matched_packets, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state/matched_packets (yang:counter64) + If this variable is read-only (config: false) in the + source YANG file, then _set_matched_packets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_matched_packets() directly. + + YANG Description: Count of the number of packets matching the current ACL +entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """matched_packets must be of a type compatible with yang:counter64""", + 'defined-type': "yang:counter64", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False)""", + }) + + self.__matched_packets = t + if hasattr(self, '_set'): + self._set() + + def _unset_matched_packets(self): + self.__matched_packets = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + + def _get_matched_octets(self): + """ + Getter method for matched_octets, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state/matched_octets (yang:counter64) + + YANG Description: Count of the number of octets (bytes) matching the current +ACL entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + return self.__matched_octets + + def _set_matched_octets(self, v, load=False): + """ + Setter method for matched_octets, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state/matched_octets (yang:counter64) + If this variable is read-only (config: false) in the + source YANG file, then _set_matched_octets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_matched_octets() directly. + + YANG Description: Count of the number of octets (bytes) matching the current +ACL entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """matched_octets must be of a type compatible with yang:counter64""", + 'defined-type': "yang:counter64", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False)""", + }) + + self.__matched_octets = t + if hasattr(self, '_set'): + self._set() + + def _unset_matched_octets(self): + self.__matched_octets = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + sequence_id = __builtin__.property(_get_sequence_id) + matched_packets = __builtin__.property(_get_matched_packets) + matched_octets = __builtin__.property(_get_matched_octets) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'matched_packets': matched_packets, 'matched_octets': matched_octets, } + + +class yc_acl_entry_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets/ingress-acl-set/acl-entries/acl-entry. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of ACL entries assigned to an interface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__state',) + + _yang_name = 'acl-entry' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__sequence_id = YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'ingress-acl-sets', u'ingress-acl-set', u'acl-entries', u'acl-entry'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/sequence_id (leafref) + + YANG Description: Reference to per-interface acl entry key + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/sequence_id (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: Reference to per-interface acl entry key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state (container) + + YANG Description: Operational state data for per-interface ACL entries + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state data for per-interface ACL entries + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False) + + sequence_id = __builtin__.property(_get_sequence_id) + state = __builtin__.property(_get_state) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'state': state, } + + +class yc_acl_entries_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets/ingress-acl-set/acl-entries. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Enclosing container for list of references to ACLs + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__acl_entry',) + + _yang_name = 'acl-entries' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__acl_entry = YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'ingress-acl-sets', u'ingress-acl-set', u'acl-entries'] + + def _get_acl_entry(self): + """ + Getter method for acl_entry, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry (list) + + YANG Description: List of ACL entries assigned to an interface + """ + return self.__acl_entry + + def _set_acl_entry(self, v, load=False): + """ + Setter method for acl_entry, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_entry is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_entry() directly. + + YANG Description: List of ACL entries assigned to an interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_entry must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False)""", + }) + + self.__acl_entry = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_entry(self): + self.__acl_entry = YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False) + + acl_entry = __builtin__.property(_get_acl_entry) + + + _pyangbind_elements = {'acl_entry': acl_entry, } + + +class yc_ingress_acl_set_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets/ingress-acl-set. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of ingress ACLs on the interface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__set_name','__config','__state','__acl_entries',) + + _yang_name = 'ingress-acl-set' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__set_name = YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__acl_entries = YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'ingress-acl-sets', u'ingress-acl-set'] + + def _get_set_name(self): + """ + Getter method for set_name, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/set_name (leafref) + + YANG Description: Reference to set name list key + """ + return self.__set_name + + def _set_set_name(self, v, load=False): + """ + Setter method for set_name, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/set_name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_set_name() directly. + + YANG Description: Reference to set name list key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """set_name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__set_name = t + if hasattr(self, '_set'): + self._set() + + def _unset_set_name(self): + self.__set_name = YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/config (container) + + YANG Description: Configuration data + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configuration data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/state (container) + + YANG Description: Operational state data for interface ingress ACLs + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state data for interface ingress ACLs + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_acl_entries(self): + """ + Getter method for acl_entries, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries (container) + + YANG Description: Enclosing container for list of references to ACLs + """ + return self.__acl_entries + + def _set_acl_entries(self, v, load=False): + """ + Setter method for acl_entries, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_entries is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_entries() directly. + + YANG Description: Enclosing container for list of references to ACLs + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_entries must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__acl_entries = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_entries(self): + self.__acl_entries = YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + set_name = __builtin__.property(_get_set_name, _set_set_name) + config = __builtin__.property(_get_config, _set_config) + state = __builtin__.property(_get_state, _set_state) + acl_entries = __builtin__.property(_get_acl_entries, _set_acl_entries) + + + _pyangbind_elements = {'set_name': set_name, 'config': config, 'state': state, 'acl_entries': acl_entries, } + + +class yc_ingress_acl_sets_openconfig_acl__acl_interfaces_interface_ingress_acl_sets(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Enclosing container the list of ingress ACLs on the +interface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__ingress_acl_set',) + + _yang_name = 'ingress-acl-sets' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__ingress_acl_set = YANGDynClass(base=YANGListType("set_name",yc_ingress_acl_set_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set, yang_name="ingress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="ingress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'ingress-acl-sets'] + + def _get_ingress_acl_set(self): + """ + Getter method for ingress_acl_set, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set (list) + + YANG Description: List of ingress ACLs on the interface + """ + return self.__ingress_acl_set + + def _set_ingress_acl_set(self, v, load=False): + """ + Setter method for ingress_acl_set, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_ingress_acl_set is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ingress_acl_set() directly. + + YANG Description: List of ingress ACLs on the interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("set_name",yc_ingress_acl_set_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set, yang_name="ingress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="ingress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ingress_acl_set must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("set_name",yc_ingress_acl_set_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set, yang_name="ingress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="ingress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True)""", + }) + + self.__ingress_acl_set = t + if hasattr(self, '_set'): + self._set() + + def _unset_ingress_acl_set(self): + self.__ingress_acl_set = YANGDynClass(base=YANGListType("set_name",yc_ingress_acl_set_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set, yang_name="ingress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="ingress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + ingress_acl_set = __builtin__.property(_get_ingress_acl_set, _set_ingress_acl_set) + + + _pyangbind_elements = {'ingress_acl_set': ingress_acl_set, } + + +class yc_config_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets/egress-acl-set/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configuration data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__set_name',) + + _yang_name = 'config' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__set_name = YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'egress-acl-sets', u'egress-acl-set', u'config'] + + def _get_set_name(self): + """ + Getter method for set_name, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/config/set_name (leafref) + + YANG Description: Reference to the ACL set applied on egress + """ + return self.__set_name + + def _set_set_name(self, v, load=False): + """ + Setter method for set_name, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/config/set_name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_set_name() directly. + + YANG Description: Reference to the ACL set applied on egress + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """set_name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__set_name = t + if hasattr(self, '_set'): + self._set() + + def _unset_set_name(self): + self.__set_name = YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + set_name = __builtin__.property(_get_set_name, _set_set_name) + + + _pyangbind_elements = {'set_name': set_name, } + + +class yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets/egress-acl-set/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state data for interface egress ACLs + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__set_name',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__set_name = YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'egress-acl-sets', u'egress-acl-set', u'state'] + + def _get_set_name(self): + """ + Getter method for set_name, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/state/set_name (leafref) + + YANG Description: Reference to the ACL set applied on egress + """ + return self.__set_name + + def _set_set_name(self, v, load=False): + """ + Setter method for set_name, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/state/set_name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_set_name() directly. + + YANG Description: Reference to the ACL set applied on egress + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """set_name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__set_name = t + if hasattr(self, '_set'): + self._set() + + def _unset_set_name(self): + self.__set_name = YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + set_name = __builtin__.property(_get_set_name) + + + _pyangbind_elements = {'set_name': set_name, } + + +class yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets/egress-acl-set/acl-entries/acl-entry/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state data for per-interface ACL entries + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__matched_packets','__matched_octets',) + + _yang_name = 'state' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__sequence_id = YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + self.__matched_packets = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + self.__matched_octets = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'egress-acl-sets', u'egress-acl-set', u'acl-entries', u'acl-entry', u'state'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state/sequence_id (leafref) + + YANG Description: Reference to an entry in the ACL set applied to an +interface + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state/sequence_id (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: Reference to an entry in the ACL set applied to an +interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + + def _get_matched_packets(self): + """ + Getter method for matched_packets, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state/matched_packets (yang:counter64) + + YANG Description: Count of the number of packets matching the current ACL +entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + return self.__matched_packets + + def _set_matched_packets(self, v, load=False): + """ + Setter method for matched_packets, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state/matched_packets (yang:counter64) + If this variable is read-only (config: false) in the + source YANG file, then _set_matched_packets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_matched_packets() directly. + + YANG Description: Count of the number of packets matching the current ACL +entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """matched_packets must be of a type compatible with yang:counter64""", + 'defined-type': "yang:counter64", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False)""", + }) + + self.__matched_packets = t + if hasattr(self, '_set'): + self._set() + + def _unset_matched_packets(self): + self.__matched_packets = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + + def _get_matched_octets(self): + """ + Getter method for matched_octets, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state/matched_octets (yang:counter64) + + YANG Description: Count of the number of octets (bytes) matching the current +ACL entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + return self.__matched_octets + + def _set_matched_octets(self, v, load=False): + """ + Setter method for matched_octets, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state/matched_octets (yang:counter64) + If this variable is read-only (config: false) in the + source YANG file, then _set_matched_octets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_matched_octets() directly. + + YANG Description: Count of the number of octets (bytes) matching the current +ACL entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """matched_octets must be of a type compatible with yang:counter64""", + 'defined-type': "yang:counter64", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False)""", + }) + + self.__matched_octets = t + if hasattr(self, '_set'): + self._set() + + def _unset_matched_octets(self): + self.__matched_octets = YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + sequence_id = __builtin__.property(_get_sequence_id) + matched_packets = __builtin__.property(_get_matched_packets) + matched_octets = __builtin__.property(_get_matched_octets) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'matched_packets': matched_packets, 'matched_octets': matched_octets, } + + +class yc_acl_entry_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets/egress-acl-set/acl-entries/acl-entry. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of ACL entries assigned to an interface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__state',) + + _yang_name = 'acl-entry' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__sequence_id = YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'egress-acl-sets', u'egress-acl-set', u'acl-entries', u'acl-entry'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/sequence_id (leafref) + + YANG Description: Reference to per-interface acl entry key + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/sequence_id (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: Reference to per-interface acl entry key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state (container) + + YANG Description: Operational state data for per-interface ACL entries + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state data for per-interface ACL entries + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False) + + sequence_id = __builtin__.property(_get_sequence_id) + state = __builtin__.property(_get_state) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'state': state, } + + +class yc_acl_entries_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets/egress-acl-set/acl-entries. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Enclosing container for list of references to ACLs + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__acl_entry',) + + _yang_name = 'acl-entries' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__acl_entry = YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'egress-acl-sets', u'egress-acl-set', u'acl-entries'] + + def _get_acl_entry(self): + """ + Getter method for acl_entry, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry (list) + + YANG Description: List of ACL entries assigned to an interface + """ + return self.__acl_entry + + def _set_acl_entry(self, v, load=False): + """ + Setter method for acl_entry, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_entry is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_entry() directly. + + YANG Description: List of ACL entries assigned to an interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_entry must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False)""", + }) + + self.__acl_entry = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_entry(self): + self.__acl_entry = YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False) + + acl_entry = __builtin__.property(_get_acl_entry) + + + _pyangbind_elements = {'acl_entry': acl_entry, } + + +class yc_egress_acl_set_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets/egress-acl-set. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of egress ACLs on the interface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__set_name','__config','__state','__acl_entries',) + + _yang_name = 'egress-acl-set' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__set_name = YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__acl_entries = YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'egress-acl-sets', u'egress-acl-set'] + + def _get_set_name(self): + """ + Getter method for set_name, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/set_name (leafref) + + YANG Description: Reference to set name list key + """ + return self.__set_name + + def _set_set_name(self, v, load=False): + """ + Setter method for set_name, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/set_name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_set_name() directly. + + YANG Description: Reference to set name list key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """set_name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__set_name = t + if hasattr(self, '_set'): + self._set() + + def _unset_set_name(self): + self.__set_name = YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/config (container) + + YANG Description: Configuration data + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configuration data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/state (container) + + YANG Description: Operational state data for interface egress ACLs + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state data for interface egress ACLs + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_acl_entries(self): + """ + Getter method for acl_entries, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries (container) + + YANG Description: Enclosing container for list of references to ACLs + """ + return self.__acl_entries + + def _set_acl_entries(self, v, load=False): + """ + Setter method for acl_entries, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_entries is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_entries() directly. + + YANG Description: Enclosing container for list of references to ACLs + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_entries must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__acl_entries = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_entries(self): + self.__acl_entries = YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + set_name = __builtin__.property(_get_set_name, _set_set_name) + config = __builtin__.property(_get_config, _set_config) + state = __builtin__.property(_get_state, _set_state) + acl_entries = __builtin__.property(_get_acl_entries, _set_acl_entries) + + + _pyangbind_elements = {'set_name': set_name, 'config': config, 'state': state, 'acl_entries': acl_entries, } + + +class yc_egress_acl_sets_openconfig_acl__acl_interfaces_interface_egress_acl_sets(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Enclosing container the list of egress ACLs on the +interface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__egress_acl_set',) + + _yang_name = 'egress-acl-sets' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__egress_acl_set = YANGDynClass(base=YANGListType("set_name",yc_egress_acl_set_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set, yang_name="egress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="egress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface', u'egress-acl-sets'] + + def _get_egress_acl_set(self): + """ + Getter method for egress_acl_set, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set (list) + + YANG Description: List of egress ACLs on the interface + """ + return self.__egress_acl_set + + def _set_egress_acl_set(self, v, load=False): + """ + Setter method for egress_acl_set, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_egress_acl_set is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_egress_acl_set() directly. + + YANG Description: List of egress ACLs on the interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("set_name",yc_egress_acl_set_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set, yang_name="egress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="egress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """egress_acl_set must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("set_name",yc_egress_acl_set_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set, yang_name="egress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="egress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True)""", + }) + + self.__egress_acl_set = t + if hasattr(self, '_set'): + self._set() + + def _unset_egress_acl_set(self): + self.__egress_acl_set = YANGDynClass(base=YANGListType("set_name",yc_egress_acl_set_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set, yang_name="egress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="egress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + egress_acl_set = __builtin__.property(_get_egress_acl_set, _set_egress_acl_set) + + + _pyangbind_elements = {'egress_acl_set': egress_acl_set, } + + +class yc_interface_openconfig_acl__acl_interfaces_interface(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of interfaces on which ACLs are set + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__id','__config','__state','__interface_ref','__ingress_acl_sets','__egress_acl_sets',) + + _yang_name = 'interface' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__ingress_acl_sets = YANGDynClass(base=yc_ingress_acl_sets_openconfig_acl__acl_interfaces_interface_ingress_acl_sets, is_container='container', yang_name="ingress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__egress_acl_sets = YANGDynClass(base=yc_egress_acl_sets_openconfig_acl__acl_interfaces_interface_egress_acl_sets, is_container='container', yang_name="egress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__id = YANGDynClass(base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__interface_ref = YANGDynClass(base=yc_interface_ref_openconfig_acl__acl_interfaces_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces', u'interface'] + + def _get_id(self): + """ + Getter method for id, mapped from YANG variable /acl/interfaces/interface/id (leafref) + + YANG Description: Reference to the interface id list key + """ + return self.__id + + def _set_id(self, v, load=False): + """ + Setter method for id, mapped from YANG variable /acl/interfaces/interface/id (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_id() directly. + + YANG Description: Reference to the interface id list key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """id must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__id = t + if hasattr(self, '_set'): + self._set() + + def _unset_id(self): + self.__id = YANGDynClass(base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/interfaces/interface/config (container) + + YANG Description: Configuration for ACL per-interface data + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/interfaces/interface/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configuration for ACL per-interface data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_interfaces_interface_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/interfaces/interface/state (container) + + YANG Description: Operational state for ACL per-interface data + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/interfaces/interface/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state for ACL per-interface data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_interfaces_interface_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_interface_ref(self): + """ + Getter method for interface_ref, mapped from YANG variable /acl/interfaces/interface/interface_ref (container) + + YANG Description: Reference to an interface or subinterface + """ + return self.__interface_ref + + def _set_interface_ref(self, v, load=False): + """ + Setter method for interface_ref, mapped from YANG variable /acl/interfaces/interface/interface_ref (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface_ref is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface_ref() directly. + + YANG Description: Reference to an interface or subinterface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_interface_ref_openconfig_acl__acl_interfaces_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface_ref must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_interface_ref_openconfig_acl__acl_interfaces_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__interface_ref = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface_ref(self): + self.__interface_ref = YANGDynClass(base=yc_interface_ref_openconfig_acl__acl_interfaces_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_ingress_acl_sets(self): + """ + Getter method for ingress_acl_sets, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets (container) + + YANG Description: Enclosing container the list of ingress ACLs on the +interface + """ + return self.__ingress_acl_sets + + def _set_ingress_acl_sets(self, v, load=False): + """ + Setter method for ingress_acl_sets, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_ingress_acl_sets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ingress_acl_sets() directly. + + YANG Description: Enclosing container the list of ingress ACLs on the +interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_ingress_acl_sets_openconfig_acl__acl_interfaces_interface_ingress_acl_sets, is_container='container', yang_name="ingress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ingress_acl_sets must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_ingress_acl_sets_openconfig_acl__acl_interfaces_interface_ingress_acl_sets, is_container='container', yang_name="ingress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__ingress_acl_sets = t + if hasattr(self, '_set'): + self._set() + + def _unset_ingress_acl_sets(self): + self.__ingress_acl_sets = YANGDynClass(base=yc_ingress_acl_sets_openconfig_acl__acl_interfaces_interface_ingress_acl_sets, is_container='container', yang_name="ingress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_egress_acl_sets(self): + """ + Getter method for egress_acl_sets, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets (container) + + YANG Description: Enclosing container the list of egress ACLs on the +interface + """ + return self.__egress_acl_sets + + def _set_egress_acl_sets(self, v, load=False): + """ + Setter method for egress_acl_sets, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_egress_acl_sets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_egress_acl_sets() directly. + + YANG Description: Enclosing container the list of egress ACLs on the +interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_egress_acl_sets_openconfig_acl__acl_interfaces_interface_egress_acl_sets, is_container='container', yang_name="egress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """egress_acl_sets must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_egress_acl_sets_openconfig_acl__acl_interfaces_interface_egress_acl_sets, is_container='container', yang_name="egress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__egress_acl_sets = t + if hasattr(self, '_set'): + self._set() + + def _unset_egress_acl_sets(self): + self.__egress_acl_sets = YANGDynClass(base=yc_egress_acl_sets_openconfig_acl__acl_interfaces_interface_egress_acl_sets, is_container='container', yang_name="egress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + id = __builtin__.property(_get_id, _set_id) + config = __builtin__.property(_get_config, _set_config) + state = __builtin__.property(_get_state, _set_state) + interface_ref = __builtin__.property(_get_interface_ref, _set_interface_ref) + ingress_acl_sets = __builtin__.property(_get_ingress_acl_sets, _set_ingress_acl_sets) + egress_acl_sets = __builtin__.property(_get_egress_acl_sets, _set_egress_acl_sets) + + + _pyangbind_elements = {'id': id, 'config': config, 'state': state, 'interface_ref': interface_ref, 'ingress_acl_sets': ingress_acl_sets, 'egress_acl_sets': egress_acl_sets, } + + +class yc_interfaces_openconfig_acl__acl_interfaces(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Enclosing container for the list of interfaces on which +ACLs are set + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__interface',) + + _yang_name = 'interfaces' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__interface = YANGDynClass(base=YANGListType("id",yc_interface_openconfig_acl__acl_interfaces_interface, yang_name="interface", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='id', extensions=None), is_container='list', yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl', u'interfaces'] + + def _get_interface(self): + """ + Getter method for interface, mapped from YANG variable /acl/interfaces/interface (list) + + YANG Description: List of interfaces on which ACLs are set + """ + return self.__interface + + def _set_interface(self, v, load=False): + """ + Setter method for interface, mapped from YANG variable /acl/interfaces/interface (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface() directly. + + YANG Description: List of interfaces on which ACLs are set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("id",yc_interface_openconfig_acl__acl_interfaces_interface, yang_name="interface", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='id', extensions=None), is_container='list', yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("id",yc_interface_openconfig_acl__acl_interfaces_interface, yang_name="interface", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='id', extensions=None), is_container='list', yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True)""", + }) + + self.__interface = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface(self): + self.__interface = YANGDynClass(base=YANGListType("id",yc_interface_openconfig_acl__acl_interfaces_interface, yang_name="interface", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='id', extensions=None), is_container='list', yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + interface = __builtin__.property(_get_interface, _set_interface) + + + _pyangbind_elements = {'interface': interface, } + + +class yc_acl_openconfig_acl__acl(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Top level enclosing container for ACL model config +and operational state data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__state','__acl_sets','__interfaces',) + + _yang_name = 'acl' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__acl_sets = YANGDynClass(base=yc_acl_sets_openconfig_acl__acl_acl_sets, is_container='container', yang_name="acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__interfaces = YANGDynClass(base=yc_interfaces_openconfig_acl__acl_interfaces, is_container='container', yang_name="interfaces", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [u'acl'] + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/state (container) + + YANG Description: Global operational state data for ACLs + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Global operational state data for ACLs + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_acl_sets(self): + """ + Getter method for acl_sets, mapped from YANG variable /acl/acl_sets (container) + + YANG Description: Access list entries variables enclosing container + """ + return self.__acl_sets + + def _set_acl_sets(self, v, load=False): + """ + Setter method for acl_sets, mapped from YANG variable /acl/acl_sets (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_sets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_sets() directly. + + YANG Description: Access list entries variables enclosing container + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_acl_sets_openconfig_acl__acl_acl_sets, is_container='container', yang_name="acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_sets must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_acl_sets_openconfig_acl__acl_acl_sets, is_container='container', yang_name="acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__acl_sets = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_sets(self): + self.__acl_sets = YANGDynClass(base=yc_acl_sets_openconfig_acl__acl_acl_sets, is_container='container', yang_name="acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_interfaces(self): + """ + Getter method for interfaces, mapped from YANG variable /acl/interfaces (container) + + YANG Description: Enclosing container for the list of interfaces on which +ACLs are set + """ + return self.__interfaces + + def _set_interfaces(self, v, load=False): + """ + Setter method for interfaces, mapped from YANG variable /acl/interfaces (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_interfaces is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interfaces() directly. + + YANG Description: Enclosing container for the list of interfaces on which +ACLs are set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_interfaces_openconfig_acl__acl_interfaces, is_container='container', yang_name="interfaces", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interfaces must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_interfaces_openconfig_acl__acl_interfaces, is_container='container', yang_name="interfaces", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__interfaces = t + if hasattr(self, '_set'): + self._set() + + def _unset_interfaces(self): + self.__interfaces = YANGDynClass(base=yc_interfaces_openconfig_acl__acl_interfaces, is_container='container', yang_name="interfaces", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + state = __builtin__.property(_get_state, _set_state) + acl_sets = __builtin__.property(_get_acl_sets, _set_acl_sets) + interfaces = __builtin__.property(_get_interfaces, _set_interfaces) + + + _pyangbind_elements = {'state': state, 'acl_sets': acl_sets, 'interfaces': interfaces, } + + +class openconfig_acl(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /openconfig-acl. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: This module defines configuration and operational state +data for network access control lists (i.e., filters, rules, +etc.). ACLs are organized into ACL sets, with each set +containing one or more ACL entries. ACL sets are identified +by a unique name, while each entry within a set is assigned +a sequence-id that determines the order in which the ACL +rules are applied to a packet. + +The model allows individual ACL rules to combine match criteria +from various fields in the packet, along with an action that +defines how matching packets should be handled. Note that some +device implementations may require separate entries for match +criteria that cross protocol layers, e.g., MAC layer and IP +layer matches. + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__acl',) + + _yang_name = 'openconfig-acl' + + _pybind_generated_by = 'container' + + def __init__(self, *args, **kwargs): + + self._path_helper = False + + self._extmethods = False + self.__acl = YANGDynClass(base=yc_acl_openconfig_acl__acl, is_container='container', yang_name="acl", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [] + + def _get_acl(self): + """ + Getter method for acl, mapped from YANG variable /acl (container) + + YANG Description: Top level enclosing container for ACL model config +and operational state data + """ + return self.__acl + + def _set_acl(self, v, load=False): + """ + Setter method for acl, mapped from YANG variable /acl (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl() directly. + + YANG Description: Top level enclosing container for ACL model config +and operational state data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_acl_openconfig_acl__acl, is_container='container', yang_name="acl", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_acl_openconfig_acl__acl, is_container='container', yang_name="acl", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__acl = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl(self): + self.__acl = YANGDynClass(base=yc_acl_openconfig_acl__acl, is_container='container', yang_name="acl", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + acl = __builtin__.property(_get_acl, _set_acl) + + + _pyangbind_elements = {'acl': acl, } diff --git a/src/sonic-config-engine/portconfig.py b/src/sonic-config-engine/portconfig.py new file mode 100644 index 000000000000..db2baa308174 --- /dev/null +++ b/src/sonic-config-engine/portconfig.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +import os +import sys + + +def get_port_config_file_name(hwsku=None, platform=None): + port_config_candidates = [] + port_config_candidates.append('/usr/share/sonic/hwsku/port_config.ini') + if hwsku: + if platform: + port_config_candidates.append(os.path.join('/usr/share/sonic/device', platform, hwsku, 'port_config.ini')) + port_config_candidates.append(os.path.join('/usr/share/sonic/platform', hwsku, 'port_config.ini')) + port_config_candidates.append(os.path.join('/usr/share/sonic', hwsku, 'port_config.ini')) + for candidate in port_config_candidates: + if os.path.isfile(candidate): + return candidate + return None + + +def get_port_config(hwsku=None, platform=None, port_config_file=None): + if not port_config_file: + port_config_file = get_port_config_file_name(hwsku, platform) + if not port_config_file: + return ({}, {}) + return parse_port_config_file(port_config_file) + + +def parse_port_config_file(port_config_file): + ports = {} + port_alias_map = {} + # Default column definition + titles = ['name', 'lanes', 'alias', 'index'] + with open(port_config_file) as data: + for line in data: + if line.startswith('#'): + if "name" in line: + titles = line.strip('#').split() + continue; + tokens = line.split() + if len(tokens) < 2: + continue + name_index = titles.index('name') + name = tokens[name_index] + data = {} + for i, item in enumerate(tokens): + if i == name_index: + continue + data[titles[i]] = item + data.setdefault('alias', name) + ports[name] = data + port_alias_map[data['alias']] = name + return (ports, port_alias_map) + + diff --git a/src/sonic-config-engine/setup.py b/src/sonic-config-engine/setup.py new file mode 100755 index 000000000000..8375b6af89ad --- /dev/null +++ b/src/sonic-config-engine/setup.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +from setuptools import setup +import os.path +import unittest +import glob + +def get_test_suite(): + test_loader = unittest.TestLoader() + test_suite = test_loader.discover('tests', pattern='*.py') + return test_suite + +setup(name='sonic-config-engine', + version='1.0', + description='Utilities for generating SONiC configuration files', + author='Taoyu Li', + author_email='taoyl@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + py_modules=['portconfig', 'minigraph', 'openconfig_acl', 'sonic_platform', 'config_samples'], + scripts=['sonic-cfggen'], + install_requires=['lxml', 'jinja2>=2.10', 'netaddr', 'ipaddr', 'pyyaml', 'pyangbind==0.6.0'], + test_suite='setup.get_test_suite', + data_files=[ + ('/usr/share/sonic/templates', glob.glob('data/*')), + ], + ) diff --git a/src/sonic-config-engine/sonic-cfggen b/src/sonic-config-engine/sonic-cfggen new file mode 100755 index 000000000000..f923cc4bc6c2 --- /dev/null +++ b/src/sonic-config-engine/sonic-cfggen @@ -0,0 +1,263 @@ +#!/usr/bin/env python +"""sonic-cfggen + +A tool to read SONiC config data from one or more of the following sources: +minigraph file, config DB, json file(s), yaml files(s), command line input, +and write the data into DB, print as json, or render a jinja2 config template. + +Examples: + Render template with minigraph: + sonic-cfggen -m -t /usr/share/template/bgpd.conf.j2 + Dump config DB content into json file: + sonic-cfggen -d --print-data > db_dump.json + Load content of json file into config DB: + sonic-cfggen -j db_dump.json --write-to-db +See usage string for detail description for arguments. +""" + +from __future__ import print_function +import sys +import os.path +import argparse +import yaml +import jinja2 +import netaddr +import json +from functools import partial +from minigraph import minigraph_encoder +from minigraph import parse_xml +from minigraph import parse_device_desc_xml +from portconfig import get_port_config +from sonic_platform import get_machine_info +from sonic_platform import get_platform_info +from sonic_platform import get_system_mac +from config_samples import generate_sample_config +from config_samples import get_available_config +from swsssdk import ConfigDBConnector +from collections import OrderedDict +from natsort import natsorted + +def sort_by_port_index(value): + if not value: + return + if isinstance(value, list): + value.sort(key = lambda k: int(k[8:])) + +def is_ipv4(value): + if not value: + return False + if isinstance(value, netaddr.IPNetwork): + addr = value + else: + try: + addr = netaddr.IPNetwork(str(value)) + except: + return False + return addr.version == 4 + +def is_ipv6(value): + if not value: + return False + if isinstance(value, netaddr.IPNetwork): + addr = value + else: + try: + addr = netaddr.IPNetwork(str(value)) + except: + return False + return addr.version == 6 + +def prefix_attr(attr, value): + if not value: + return None + else: + try: + prefix = netaddr.IPNetwork(str(value)) + except: + return None + return str(getattr(prefix, attr)) + +def unique_name(l): + name_list = [] + new_list = [] + for item in l: + if item['name'] not in name_list: + name_list.append(item['name']) + new_list.append(item) + return new_list + + +class FormatConverter: + """Convert config DB based schema to legacy minigraph based schema for backward capability. +We will move to DB schema and remove this class when the config templates are modified. + +TODO(taoyl): Current version of config db only supports BGP admin states. + All other configuration are still loaded from minigraph. Plan to remove + minigraph and move everything into config db in a later commit. + """ + @staticmethod + def db_to_output(db_data): + return db_data + + @staticmethod + def output_to_db(output_data): + db_data = {} + for table_name in output_data: + if table_name[0].isupper(): + db_data[table_name] = output_data[table_name] + return db_data + + @staticmethod + def to_serialized(data): + for table in data: + if type(data[table]) is dict: + data[table] = OrderedDict(natsorted(data[table].items())) + for key in data[table].keys(): + new_key = ConfigDBConnector.serialize_key(key) + if new_key != key: + data[table][new_key] = data[table].pop(key) + return data + + @staticmethod + def to_deserialized(data): + for table in data: + if type(data[table]) is dict: + for key in data[table].keys(): + new_key = ConfigDBConnector.deserialize_key(key) + if new_key != key: + data[table][new_key] = data[table].pop(key) + return data + + +def deep_update(dst, src): + for key, value in src.iteritems(): + if isinstance(value, dict): + node = dst.setdefault(key, {}) + deep_update(node, value) + else: + dst[key] = value + return dst + +def sort_data(data): + for table in data: + if type(data[table]) is dict: + data[table] = OrderedDict(natsorted(data[table].items())) + return data + + +def main(): + parser=argparse.ArgumentParser(description="Render configuration file from minigraph data and jinja2 template.") + group = parser.add_mutually_exclusive_group() + group.add_argument("-m", "--minigraph", help="minigraph xml file", nargs='?', const='/etc/sonic/minigraph.xml') + group.add_argument("-M", "--device-description", help="device description xml file") + group.add_argument("-k", "--hwsku", help="HwSKU") + parser.add_argument("-p", "--port-config", help="port config file, used with -m or -k", nargs='?', const=None) + parser.add_argument("-y", "--yaml", help="yaml file that contains additional variables", action='append', default=[]) + parser.add_argument("-j", "--json", help="json file that contains additional variables", action='append', default=[]) + parser.add_argument("-a", "--additional-data", help="addition data, in json string") + parser.add_argument("-d", "--from-db", help="read config from configdb", action='store_true') + parser.add_argument("-H", "--platform-info", help="read platform and hardware info", action='store_true') + parser.add_argument("-s", "--redis-unix-sock-file", help="unix sock file for redis connection") + group = parser.add_mutually_exclusive_group() + group.add_argument("-t", "--template", help="render the data with the template file") + group.add_argument("-v", "--var", help="print the value of a variable, support jinja2 expression") + group.add_argument("--var-json", help="print the value of a variable, in json format") + group.add_argument("--write-to-db", help="write config into configdb", action='store_true') + group.add_argument("--print-data", help="print all data", action='store_true') + group.add_argument("--preset", help="generate sample configuration from a preset template", choices=get_available_config()) + args = parser.parse_args() + + platform = get_platform_info(get_machine_info()) + + db_kwargs = {} + if args.redis_unix_sock_file != None: + db_kwargs['unix_socket_path'] = args.redis_unix_sock_file + + data = {} + hwsku = args.hwsku + + if hwsku is not None: + hardware_data = {'DEVICE_METADATA': {'localhost': { + 'hwsku': hwsku + }}} + deep_update(data, hardware_data) + (ports, _) = get_port_config(hwsku, platform, args.port_config) + if not ports: + print('Failed to get port config', file=sys.stderr) + sys.exit(1) + deep_update(data, {'PORT': ports}) + + if args.minigraph != None: + minigraph = args.minigraph + if platform: + if args.port_config != None: + deep_update(data, parse_xml(minigraph, platform, args.port_config)) + else: + deep_update(data, parse_xml(minigraph, platform)) + else: + deep_update(data, parse_xml(minigraph, port_config_file=args.port_config)) + + if args.device_description != None: + deep_update(data, parse_device_desc_xml(args.device_description)) + + for yaml_file in args.yaml: + with open(yaml_file, 'r') as stream: + additional_data = yaml.load(stream) + deep_update(data, FormatConverter.to_deserialized(additional_data)) + + for json_file in args.json: + with open(json_file, 'r') as stream: + deep_update(data, FormatConverter.to_deserialized(json.load(stream))) + + if args.additional_data != None: + deep_update(data, json.loads(args.additional_data)) + + if args.from_db: + configdb = ConfigDBConnector(**db_kwargs) + configdb.connect() + deep_update(data, FormatConverter.db_to_output(configdb.get_config())) + + if args.platform_info: + hardware_data = {'DEVICE_METADATA': {'localhost': { + 'platform': platform, + 'mac': get_system_mac() + }}} + deep_update(data, hardware_data) + + if args.template != None: + template_file = os.path.abspath(args.template) + paths = ['/', '/usr/share/sonic/templates', os.path.dirname(template_file)] + loader = jinja2.FileSystemLoader(paths) + + env = jinja2.Environment(loader=loader, trim_blocks=True) + env.filters['sort_by_port_index'] = sort_by_port_index + env.filters['ipv4'] = is_ipv4 + env.filters['ipv6'] = is_ipv6 + env.filters['unique_name'] = unique_name + for attr in ['ip', 'network', 'prefixlen', 'netmask']: + env.filters[attr] = partial(prefix_attr, attr) + template = env.get_template(template_file) + print(template.render(sort_data(data))) + + if args.var != None: + template = jinja2.Template('{{' + args.var + '}}') + print(template.render(data)) + + if args.var_json != None: + print(json.dumps(FormatConverter.to_serialized(data[args.var_json]), indent=4, cls=minigraph_encoder)) + + if args.write_to_db: + configdb = ConfigDBConnector(**db_kwargs) + configdb.connect(False) + configdb.mod_config(FormatConverter.output_to_db(data)) + + if args.print_data: + print(json.dumps(FormatConverter.to_serialized(data), indent=4, cls=minigraph_encoder)) + + if args.preset != None: + data = generate_sample_config(data, args.preset) + print(json.dumps(FormatConverter.to_serialized(data), indent=4, cls=minigraph_encoder)) + + +if __name__ == "__main__": + main() diff --git a/src/sonic-config-engine/sonic_platform.py b/src/sonic-config-engine/sonic_platform.py new file mode 100644 index 000000000000..20890d765cab --- /dev/null +++ b/src/sonic-config-engine/sonic_platform.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +import os +import yaml +import subprocess + +DOCUMENTATION = ''' +--- +module: sonic_platform +version_added: "1.9" +short_description: Retrive platform related facts for a device. +description: + - Retrieve platform related facts from config files. +''' + +def get_machine_info(): + if not os.path.isfile('/host/machine.conf'): + return None + machine_vars = {} + with open('/host/machine.conf') as machine_file: + for line in machine_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + machine_vars[tokens[0]] = tokens[1].strip() + return machine_vars + +def get_platform_info(machine_info): + if machine_info != None: + if machine_info.has_key('onie_platform'): + return machine_info['onie_platform'] + elif machine_info.has_key('aboot_platform'): + return machine_info['aboot_platform'] + return None + +def get_sonic_version_info(): + if not os.path.isfile('/etc/sonic/sonic_version.yml'): + return None + data = {} + with open('/etc/sonic/sonic_version.yml') as stream: + data = yaml.load(stream) + return data + +def get_system_mac(): + version_info = get_sonic_version_info() + + if (version_info['asic_type'] == 'mellanox'): + get_mac_cmd = "sudo decode-syseeprom -m" + else: + get_mac_cmd = "ip link show eth0 | grep ether | awk '{print $2}'" + + proc = subprocess.Popen(get_mac_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (mac, err) = proc.communicate() + if err: + return None + + mac = mac.strip() + + # Align last byte of MAC if necessary + if version_info and (version_info['asic_type'] == 'mellanox' or version_info['asic_type'] == 'centec'): + last_byte = mac[-2:] + aligned_last_byte = format(int(int(last_byte, 16) & 0b11000000), '02x') + mac = mac[:-2] + aligned_last_byte + return mac + +# +# Function to obtain the routing-stack being utilized. Function is not +# platform-specific; it's being placed in this file temporarily till a more +# suitable location is identified as part of upcoming refactoring efforts. +# +def get_system_routing_stack(): + command = "sudo docker ps | grep bgp | awk '{print$2}' | cut -d'-' -f3 | cut -d':' -f1" + + try: + proc = subprocess.Popen(command, + stdout=subprocess.PIPE, + shell=True, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n') + + except OSError, e: + raise OSError("Cannot detect routing-stack") + + return result diff --git a/src/sonic-config-engine/tests/.gitignore b/src/sonic-config-engine/tests/.gitignore new file mode 100644 index 000000000000..bee8a64b79a9 --- /dev/null +++ b/src/sonic-config-engine/tests/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/src/sonic-config-engine/tests/__init__.py b/src/sonic-config-engine/tests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/sonic-config-engine/tests/device.xml b/src/sonic-config-engine/tests/device.xml new file mode 100644 index 000000000000..2995c4dde133 --- /dev/null +++ b/src/sonic-config-engine/tests/device.xml @@ -0,0 +1,17 @@ + + ToRRouter +
+ 10.10.0.12/32 +
+ + ::/0 + + + 10.0.1.5/28 + + + ::/0 + + switch1 + ACS-MSN2700 +
diff --git a/src/sonic-config-engine/tests/pc-test-graph.xml b/src/sonic-config-engine/tests/pc-test-graph.xml new file mode 100644 index 000000000000..6709d65c4969 --- /dev/null +++ b/src/sonic-config-engine/tests/pc-test-graph.xml @@ -0,0 +1,207 @@ + + + + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/112;fortyGigE0/116;fortyGigE0/120;fortyGigE0/124 + + + + + + Vlan1000 + fortyGigE0/4;fortyGigE0/8;fortyGigE0/12;fortyGigE0/16;fortyGigE0/20;fortyGigE0/24;fortyGigE0/28;fortyGigE0/32;fortyGigE0/36;fortyGigE0/40;fortyGigE0/44;fortyGigE0/48;fortyGigE0/52;fortyGigE0/56;fortyGigE0/60;fortyGigE0/64;fortyGigE0/68;fortyGigE0/72;fortyGigE0/76;fortyGigE0/80;fortyGigE0/84;fortyGigE0/88;fortyGigE0/92;fortyGigE0/96 + False + 0.0.0.0/0 + + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + Vlan1000 + 192.168.0.1/27 + + + + + + PortChannel01;PortChannel02;PortChannel03;PortChannel04 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + + + + + + + + DeviceInterfaceLink + ARISTA01T1 + Ethernet1/1 + switch-t0 + fortyGigE0/112 + + + DeviceInterfaceLink + ARISTA02T1 + Ethernet1/1 + switch-t0 + fortyGigE0/116 + + + DeviceInterfaceLink + ARISTA03T1 + Ethernet1/1 + switch-t0 + fortyGigE0/120 + + + DeviceInterfaceLink + ARISTA04T1 + Ethernet1/1 + switch-t0 + fortyGigE0/124 + + + + + switch-t0 + Force10-S6000 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/sample-dell-6100-t0-minigraph.xml b/src/sonic-config-engine/tests/sample-dell-6100-t0-minigraph.xml new file mode 100644 index 000000000000..536a2c8a73c7 --- /dev/null +++ b/src/sonic-config-engine/tests/sample-dell-6100-t0-minigraph.xml @@ -0,0 +1,770 @@ + + + + + + ARISTA01T1 + 10.0.0.1 + s6100-dev-1 + 10.0.0.0 + 1 + 180 + 60 + + + ARISTA02T1 + 10.0.0.5 + s6100-dev-1 + 10.0.0.4 + 1 + 180 + 60 + + + ARISTA03T1 + 10.0.0.9 + s6100-dev-1 + 10.0.0.8 + 1 + 180 + 60 + + + ARISTA04T1 + 10.0.0.13 + s6100-dev-1 + 10.0.0.12 + 1 + 180 + 60 + + + ARISTA01T1 + FC00::2 + s6100-dev-1 + FC00::1 + 1 + 180 + 60 + + + ARISTA02T1 + FC00::A + s6100-dev-1 + FC00::9 + 1 + 180 + 60 + + + ARISTA03T1 + FC00::12 + s6100-dev-1 + FC00::11 + 1 + 180 + 60 + + + ARISTA04T1 + FC00::1A + s6100-dev-1 + FC00::19 + 1 + 180 + 60 + + + + + 64601 + s6100-dev-1 + + + BGPPeer +
10.0.0.1
+ + + +
+ + BGPPeer +
10.0.0.5
+ + + +
+ + BGPPeer +
10.0.0.9
+ + + +
+ + BGPPeer +
10.0.0.13
+ + + +
+ + BGPPeer +
FC00::2
+ + + +
+ + BGPPeer +
FC00::A
+ + + +
+ + BGPPeer +
FC00::12
+ + + +
+ + BGPPeer +
FC00::1A
+ + + +
+
+ +
+ + 64802 + ARISTA01T1 + + + + 64802 + ARISTA02T1 + + + + 64802 + ARISTA03T1 + + + + 64802 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.243/23 + + 10.0.0.243/23 + + + + + + s6100-dev-1 + + + PortChannelInterface + PortChannel1 + fortyGigE1/1/1;fortyGigE1/1/2 + + + + PortChannelInterface + PortChannel4 + fortyGigE1/1/5;fortyGigE1/1/6 + + + + PortChannelInterface + PortChannel16 + fortyGigE1/2/1;fortyGigE1/2/2 + + + + PortChannelInterface + PortChannel20 + fortyGigE1/2/5;fortyGigE1/2/6 + + + + + + VlanInterface + Vlan2 + fortyGigE1/1/7;fortyGigE1/1/8;fortyGigE1/1/9;fortyGigE1/1/10;fortyGigE1/1/11;fortyGigE1/1/12;fortyGigE1/1/13;fortyGigE1/1/14;fortyGigE1/1/15;fortyGigE1/1/16;fortyGigE1/3/1;fortyGigE1/3/5;fortyGigE1/3/6;fortyGigE1/3/7;fortyGigE1/3/8;fortyGigE1/3/9;fortyGigE1/3/10;fortyGigE1/3/11;fortyGigE1/2/7;fortyGigE1/2/8;fortyGigE1/2/9;fortyGigE1/2/10;fortyGigE1/2/11;fortyGigE1/2/12;fortyGigE1/2/13;fortyGigE1/2/14;fortyGigE1/2/15;fortyGigE1/2/16;fortyGigE1/4/1;fortyGigE1/4/5;fortyGigE1/4/6;fortyGigE1/4/7;fortyGigE1/4/8;fortyGigE1/4/9;fortyGigE1/4/10;fortyGigE1/4/11 + False + 0.0.0.0/0 + + 2 + 2 + 172.0.0.0/21 + + + + + IPInterface + + PortChannel1 + 10.0.0.0/31 + + + IPInterface + + PortChannel4 + 10.0.0.4/31 + + + IPInterface + + PortChannel16 + 10.0.0.8/31 + + + IPInterface + + PortChannel20 + 10.0.0.12/31 + + + IPInterface + + PortChannel1 + FC00::1/126 + + + IPInterface + + PortChannel4 + FC00::9/126 + + + IPInterface + + PortChannel16 + FC00::11/126 + + + IPInterface + + PortChannel20 + FC00::19/126 + + + IPInterface + + Vlan2 + 172.0.0.1/21 + + + + + + + + + + + + DeviceInterfaceLink + true + 40000 + ARISTA01T1 + Ethernet1 + true + s6100-dev-1 + fortyGigE1/1/1 + + + DeviceInterfaceLink + true + 40000 + ARISTA01T1 + Ethernet2 + true + s6100-dev-1 + fortyGigE1/1/2 + + + DeviceInterfaceLink + true + 40000 + ARISTA02T1 + Ethernet1 + true + s6100-dev-1 + fortyGigE1/1/5 + + + DeviceInterfaceLink + true + 40000 + ARISTA02T1 + Ethernet2 + true + s6100-dev-1 + fortyGigE1/1/6 + + + DeviceInterfaceLink + true + 40000 + ARISTA03T1 + Ethernet1 + true + s6100-dev-1 + fortyGigE1/2/1 + + + DeviceInterfaceLink + true + 40000 + ARISTA03T1 + Ethernet2 + true + s6100-dev-1 + fortyGigE1/2/2 + + + DeviceInterfaceLink + true + 40000 + ARISTA04T1 + Ethernet1 + true + s6100-dev-1 + fortyGigE1/2/5 + + + DeviceInterfaceLink + true + 40000 + ARISTA04T1 + Ethernet2 + true + s6100-dev-1 + fortyGigE1/2/6 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/7 + true + server-01 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/8 + true + server-02 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/9 + true + server-03 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/10 + true + server-04 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/11 + true + server-05 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/12 + true + server-06 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/13 + true + server-07 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/14 + true + server-08 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/15 + true + server-09 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/16 + true + server-10 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/1 + true + server-11 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/5 + true + server-12 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/6 + true + server-13 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/7 + true + server-14 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/8 + true + server-15 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/9 + true + server-16 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/10 + true + server-17 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/11 + true + server-18 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/7 + true + server-19 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/8 + true + server-20 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/9 + true + server-21 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/10 + true + server-22 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/11 + true + server-23 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/12 + true + server-24 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/13 + true + server-25 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/14 + true + server-26 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/15 + true + server-27 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/16 + true + server-28 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/1 + true + server-29 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/5 + true + server-30 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/6 + true + server-31 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/7 + true + server-32 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/8 + true + server-33 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/9 + true + server-34 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/10 + true + server-35 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/11 + true + server-36 + 0 + + + + + s6100-dev-1 + Force10-S6100 + + 10.0.0.243 + + + + + + + + s6100-dev-1 + + + ErspanDestinationIpv4 + + 10.0.0.16 + + + + + + + s6100-dev-1 + Force10-S6100 +
\ No newline at end of file diff --git a/src/sonic-config-engine/tests/sample-port-config-mlnx.ini b/src/sonic-config-engine/tests/sample-port-config-mlnx.ini new file mode 100644 index 000000000000..816bb0e94a70 --- /dev/null +++ b/src/sonic-config-engine/tests/sample-port-config-mlnx.ini @@ -0,0 +1,33 @@ +# name lanes +Ethernet0 0,1,2,3 +Ethernet4 4,5,6,7 +Ethernet8 8,9,10,11 +Ethernet12 12,13,14,15 +Ethernet16 16,17,18,19 +Ethernet20 20,21,22,23 +Ethernet24 24,25,26,27 +Ethernet28 28,29,30,31 +Ethernet32 32,33,34,35 +Ethernet36 36,37,38,39 +Ethernet40 40,41,42,43 +Ethernet44 44,45,46,47 +Ethernet48 48,49,50,51 +Ethernet52 52,53,54,55 +Ethernet56 56,57,58,59 +Ethernet60 60,61,62,63 +Ethernet64 64,65,66,67 +Ethernet68 68,69,70,71 +Ethernet72 72,73,74,75 +Ethernet76 76,77,78,79 +Ethernet80 80,81,82,83 +Ethernet84 84,85,86,87 +Ethernet88 88,89,90,91 +Ethernet92 92,93,94,95 +Ethernet96 96,97,98,99 +Ethernet100 100,101,102,103 +Ethernet104 104,105,106,107 +Ethernet108 108,109,110,111 +Ethernet112 112,113,114,115 +Ethernet116 116,117,118,119 +Ethernet120 120,121,122,123 +Ethernet124 124,125,126,127 diff --git a/src/sonic-config-engine/tests/sample_graph.xml b/src/sonic-config-engine/tests/sample_graph.xml new file mode 100644 index 000000000000..47efabf7d81c --- /dev/null +++ b/src/sonic-config-engine/tests/sample_graph.xml @@ -0,0 +1,129 @@ + + + + + + OCPSCH0104001MS + 10.10.1.14 + OCPSCH01040DDLF + 10.10.1.13 + 1 + 10 + 3 + + + OCPSCH0104002MS + 10.10.2.14 + OCPSCH01040DDLF + 10.10.2.13 + 1 + 10 + 3 + + + + + 64536 + OCPSCH01040DDLF + + +
10.10.1.14
+ + +
+ +
10.10.2.14
+ + +
+
+ +
+ + 64542 + OCPSCH0104001MS + + + + 64543 + OCPSCH0104002MS + + +
+
+ + + + + + HostIP + Loopback0 + + 100.0.0.6/32 + + 100.0.0.6/32 + + + + + ManagementIP1 + Management0 + + 192.168.200.15/24 + + 192.168.200.15/24 + + + + + + OCPSCH01040DDLF + + + + + + Ethernet0 + 10.10.1.13/30 + + + + Ethernet1 + 10.10.2.13/30 + + + + + + + + + + + + 40000 + DeviceInterfaceLink + OCPSCH01040DDLF + Ethernet0 + OCPSCH0104012MS + Ethernet12 + + + 40000 + DeviceInterfaceLink + OCPCH01040DDLF + Ethernet1 + OCPSCH0104002MS + Ethernet12 + + + + + OCPSCH01040DDLF + Force10-Z9100 + + + + OCPSCH01040DDLF + Force10-Z9100 +
diff --git a/src/sonic-config-engine/tests/sample_output/bgpd_quagga.conf b/src/sonic-config-engine/tests/sample_output/bgpd_quagga.conf new file mode 100644 index 000000000000..86ce28f3b67d --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/bgpd_quagga.conf @@ -0,0 +1,99 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/bgpd.conf.j2 with config DB data +! file: bgpd.conf +! +! +hostname switch-t0 +password zebra +log syslog informational +log facility local4 +! enable password ! +! +! bgp multiple-instance +! +route-map FROM_BGP_SPEAKER_V4 permit 10 +! +route-map TO_BGP_SPEAKER_V4 deny 10 +! +router bgp 65100 + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast + bgp graceful-restart + bgp router-id 10.1.0.32 + network 10.1.0.32/32 + address-family ipv6 + network fc00:1::32/64 + exit-address-family + network 192.168.0.1/27 + neighbor 10.0.0.57 remote-as 64600 + neighbor 10.0.0.57 description ARISTA01T1 + address-family ipv4 + neighbor 10.0.0.57 allowas-in 1 + neighbor 10.0.0.57 activate + neighbor 10.0.0.57 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor 10.0.0.59 remote-as 64600 + neighbor 10.0.0.59 description ARISTA02T1 + address-family ipv4 + neighbor 10.0.0.59 allowas-in 1 + neighbor 10.0.0.59 activate + neighbor 10.0.0.59 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor 10.0.0.61 remote-as 64600 + neighbor 10.0.0.61 description ARISTA03T1 + address-family ipv4 + neighbor 10.0.0.61 allowas-in 1 + neighbor 10.0.0.61 activate + neighbor 10.0.0.61 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor 10.0.0.63 remote-as 64600 + neighbor 10.0.0.63 description ARISTA04T1 + address-family ipv4 + neighbor 10.0.0.63 allowas-in 1 + neighbor 10.0.0.63 activate + neighbor 10.0.0.63 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor fc00::7a remote-as 64600 + neighbor fc00::7a description ARISTA03T1 + address-family ipv6 + neighbor fc00::7a allowas-in 1 + neighbor fc00::7a activate + neighbor fc00::7a soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor fc00::7e remote-as 64600 + neighbor fc00::7e description ARISTA04T1 + address-family ipv6 + neighbor fc00::7e allowas-in 1 + neighbor fc00::7e activate + neighbor fc00::7e soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor fc00::72 remote-as 64600 + neighbor fc00::72 description ARISTA01T1 + address-family ipv6 + neighbor fc00::72 allowas-in 1 + neighbor fc00::72 activate + neighbor fc00::72 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor fc00::76 remote-as 64600 + neighbor fc00::76 description ARISTA02T1 + address-family ipv6 + neighbor fc00::76 allowas-in 1 + neighbor fc00::76 activate + neighbor fc00::76 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family +! +maximum-paths 64 +! +route-map ISOLATE permit 10 +set as-path prepend 65100 +! diff --git a/src/sonic-config-engine/tests/sample_output/buffers-dell6100.json b/src/sonic-config-engine/tests/sample_output/buffers-dell6100.json new file mode 100644 index 000000000000..6552f6225737 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/buffers-dell6100.json @@ -0,0 +1,127 @@ + +{ + "CABLE_LENGTH": { + "AZURE": { + "Ethernet0": "5m", + "Ethernet1": "5m", + "Ethernet2": "5m", + "Ethernet3": "5m", + "Ethernet4": "5m", + "Ethernet5": "5m", + "Ethernet6": "5m", + "Ethernet7": "5m", + "Ethernet8": "5m", + "Ethernet9": "5m", + "Ethernet10": "5m", + "Ethernet11": "5m", + "Ethernet12": "5m", + "Ethernet13": "5m", + "Ethernet14": "5m", + "Ethernet15": "5m", + "Ethernet16": "5m", + "Ethernet17": "5m", + "Ethernet18": "5m", + "Ethernet19": "5m", + "Ethernet20": "5m", + "Ethernet21": "5m", + "Ethernet22": "5m", + "Ethernet23": "5m", + "Ethernet24": "5m", + "Ethernet25": "5m", + "Ethernet26": "5m", + "Ethernet27": "5m", + "Ethernet28": "5m", + "Ethernet29": "5m", + "Ethernet30": "5m", + "Ethernet31": "5m", + "Ethernet32": "5m", + "Ethernet33": "5m", + "Ethernet34": "5m", + "Ethernet35": "5m", + "Ethernet36": "5m", + "Ethernet37": "5m", + "Ethernet38": "5m", + "Ethernet39": "5m", + "Ethernet40": "5m", + "Ethernet41": "5m", + "Ethernet42": "5m", + "Ethernet43": "5m", + "Ethernet44": "5m", + "Ethernet45": "5m", + "Ethernet46": "5m", + "Ethernet47": "5m", + "Ethernet48": "5m", + "Ethernet49": "5m", + "Ethernet50": "5m", + "Ethernet51": "5m", + "Ethernet52": "5m", + "Ethernet53": "5m", + "Ethernet54": "5m", + "Ethernet55": "5m", + "Ethernet56": "5m", + "Ethernet57": "5m", + "Ethernet58": "5m", + "Ethernet59": "5m", + "Ethernet60": "5m", + "Ethernet61": "5m", + "Ethernet62": "5m", + "Ethernet63": "5m" + } + }, + + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11213696", + "type": "ingress", + "mode": "dynamic", + "xoff": "3855488" + }, + "egress_lossy_pool": { + "size": "9532224", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"3995680" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "Ethernet0,Ethernet1,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet48,Ethernet52,Ethernet53,Ethernet54,Ethernet55,Ethernet56,Ethernet57,Ethernet58|0-1": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet0,Ethernet1,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet48,Ethernet52,Ethernet53,Ethernet54,Ethernet55,Ethernet56,Ethernet57,Ethernet58|5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, + + "BUFFER_QUEUE": { + "Ethernet0,Ethernet1,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet48,Ethernet52,Ethernet53,Ethernet54,Ethernet55,Ethernet56,Ethernet57,Ethernet58|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet0,Ethernet1,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet48,Ethernet52,Ethernet53,Ethernet54,Ethernet55,Ethernet56,Ethernet57,Ethernet58|0-1": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet0,Ethernet1,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet48,Ethernet52,Ethernet53,Ethernet54,Ethernet55,Ethernet56,Ethernet57,Ethernet58|5": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/docker-dhcp-relay.supervisord.conf b/src/sonic-config-engine/tests/sample_output/docker-dhcp-relay.supervisord.conf new file mode 100644 index 000000000000..ed14f2ca0f8c --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/docker-dhcp-relay.supervisord.conf @@ -0,0 +1,33 @@ +[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 + +[group:isc-dhcp-relay] +programs=isc-dhcp-relay-Vlan1000 + +[program:isc-dhcp-relay-Vlan1000] +command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -i Vlan1000 -i PortChannel01 -i PortChannel02 -i PortChannel03 -i PortChannel04 192.0.0.1 192.0.0.2 +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + + diff --git a/src/sonic-config-engine/tests/sample_output/frr.conf b/src/sonic-config-engine/tests/sample_output/frr.conf new file mode 100644 index 000000000000..7ea45508f236 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/frr.conf @@ -0,0 +1,136 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr/frr.conf.j2 with config DB data +! file: frr.conf +! +! +hostname switch-t0 +password zebra +log syslog informational +log facility local4 +! enable password ! +! Enable link-detect (default disabled) +interface PortChannel01 +link-detect +! +interface PortChannel02 +link-detect +! +interface PortChannel03 +link-detect +! +interface PortChannel04 +link-detect +! +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.0.0.1 200 +! +! Set ip source to loopback for bgp learned routes +route-map RM_SET_SRC permit 10 + set src 10.1.0.32 +! + +route-map RM_SET_SRC6 permit 10 + set src fc00:1::32 +! +ip protocol bgp route-map RM_SET_SRC +! +ipv6 protocol bgp route-map RM_SET_SRC6 +! +! +! +! bgp multiple-instance +! +route-map FROM_BGP_SPEAKER_V4 permit 10 +! +route-map TO_BGP_SPEAKER_V4 deny 10 +! +router bgp 65100 + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast + bgp graceful-restart + bgp router-id 10.1.0.32 + network 10.1.0.32/32 + address-family ipv6 + network fc00:1::32/128 + exit-address-family + network 192.168.0.1/27 + neighbor 10.0.0.57 remote-as 64600 + neighbor 10.0.0.57 description ARISTA01T1 + address-family ipv4 + neighbor 10.0.0.57 allowas-in 1 + neighbor 10.0.0.57 activate + neighbor 10.0.0.57 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor 10.0.0.59 remote-as 64600 + neighbor 10.0.0.59 description ARISTA02T1 + address-family ipv4 + neighbor 10.0.0.59 allowas-in 1 + neighbor 10.0.0.59 activate + neighbor 10.0.0.59 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor 10.0.0.61 remote-as 64600 + neighbor 10.0.0.61 description ARISTA03T1 + address-family ipv4 + neighbor 10.0.0.61 allowas-in 1 + neighbor 10.0.0.61 activate + neighbor 10.0.0.61 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor 10.0.0.63 remote-as 64600 + neighbor 10.0.0.63 description ARISTA04T1 + address-family ipv4 + neighbor 10.0.0.63 allowas-in 1 + neighbor 10.0.0.63 activate + neighbor 10.0.0.63 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor fc00::7a remote-as 64600 + neighbor fc00::7a description ARISTA03T1 + address-family ipv6 + neighbor fc00::7a allowas-in 1 + neighbor fc00::7a activate + neighbor fc00::7a soft-reconfiguration inbound + neighbor fc00::7a route-map set-next-hop-global-v6 in + maximum-paths 64 + exit-address-family + neighbor fc00::7e remote-as 64600 + neighbor fc00::7e description ARISTA04T1 + address-family ipv6 + neighbor fc00::7e allowas-in 1 + neighbor fc00::7e activate + neighbor fc00::7e soft-reconfiguration inbound + neighbor fc00::7e route-map set-next-hop-global-v6 in + maximum-paths 64 + exit-address-family + neighbor fc00::72 remote-as 64600 + neighbor fc00::72 description ARISTA01T1 + address-family ipv6 + neighbor fc00::72 allowas-in 1 + neighbor fc00::72 activate + neighbor fc00::72 soft-reconfiguration inbound + neighbor fc00::72 route-map set-next-hop-global-v6 in + maximum-paths 64 + exit-address-family + neighbor fc00::76 remote-as 64600 + neighbor fc00::76 description ARISTA02T1 + address-family ipv6 + neighbor fc00::76 allowas-in 1 + neighbor fc00::76 activate + neighbor fc00::76 soft-reconfiguration inbound + neighbor fc00::76 route-map set-next-hop-global-v6 in + maximum-paths 64 + exit-address-family +! +maximum-paths 64 +! +route-map ISOLATE permit 10 +set as-path prepend 65100 +! +route-map set-next-hop-global-v6 permit 10 +set ipv6 next-hop prefer-global +! diff --git a/src/sonic-config-engine/tests/sample_output/interfaces b/src/sonic-config-engine/tests/sample_output/interfaces new file mode 100644 index 000000000000..4e53e2a5189a --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/interfaces @@ -0,0 +1,50 @@ +# +# =============== Managed by SONiC Config Engine DO NOT EDIT! =============== +# generated from /usr/share/sonic/templates/interfaces.j2 using sonic-cfggen +# file: /etc/network/interfaces +# +# The loopback network interface +auto lo +iface lo inet loopback +# Use command 'ip addr list dev lo' to check all addresses +iface lo inet static + address 10.1.0.32 + netmask 255.255.255.255 +# +iface lo inet6 static + address fc00:1::32 + netmask 128 +# +iface lo inet static + address 10.10.0.99 + netmask 255.255.255.255 +# + +# The management network interface +auto eth0 +iface eth0 inet static + address 10.0.0.100 + netmask 255.255.255.0 + ########## management network policy routing rules + # management port up rules + up ip -4 route add default via 10.0.0.1 dev eth0 table default + up ip -4 route add 10.0.0.0/24 dev eth0 table default + up ip -4 rule add from 10.0.0.100/32 table default + # management port down rules + down ip -4 route delete default via 10.0.0.1 dev eth0 table default + down ip -4 route delete 10.0.0.0/24 dev eth0 table default + down ip -4 rule delete from 10.0.0.100/32 table default +iface eth0 inet6 static + address 2603:10e2:0:2902::8 + netmask 64 + ########## management network policy routing rules + # management port up rules + up ip -6 route add default via 2603:10e2:0:2902::1 dev eth0 table default + up ip -6 route add 2603:10e2:0:2902::/64 dev eth0 table default + up ip -6 rule add from 2603:10e2:0:2902::8/128 table default + # management port down rules + down ip -6 route delete default via 2603:10e2:0:2902::1 dev eth0 table default + down ip -6 route delete 2603:10e2:0:2902::/64 dev eth0 table default + down ip -6 rule delete from 2603:10e2:0:2902::8/128 table default +# + diff --git a/src/sonic-config-engine/tests/sample_output/ipinip.json b/src/sonic-config-engine/tests/sample_output/ipinip.json new file mode 100644 index 000000000000..e4028ea01a2d --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/ipinip.json @@ -0,0 +1,23 @@ +[ + { + "TUNNEL_DECAP_TABLE:IPINIP_TUNNEL" : { + "tunnel_type":"IPINIP", + "dst_ip":"10.1.0.32,10.0.0.56,10.0.0.58,10.0.0.60,10.0.0.62,192.168.0.1", + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", + "ttl_mode":"pipe" + }, + "OP": "SET" + } + , + { + "TUNNEL_DECAP_TABLE:IPINIP_V6_TUNNEL" : { + "tunnel_type":"IPINIP", + "dst_ip":"fc00:1::32,fc00::71,fc00::75,fc00::79,fc00::7d", + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", + "ttl_mode":"pipe" + }, + "OP": "SET" + } +] diff --git a/src/sonic-config-engine/tests/sample_output/l2switch.json b/src/sonic-config-engine/tests/sample_output/l2switch.json new file mode 100644 index 000000000000..e8af54869e02 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/l2switch.json @@ -0,0 +1,107 @@ +{ + "DEVICE_METADATA": {"localhost": {"hwsku": "Mellanox-SN2700"}}, + "PORT": {"Ethernet0": {"alias": "fortyGigE0/0", "lanes": "29,30,31,32"}, "Ethernet100": {"alias": "fortyGigE0/100", "lanes": "125,126,127,128"}, "Ethernet104": {"alias": "fortyGigE0/104", "lanes": "85,86,87,88"}, "Ethernet108": {"alias": "fortyGigE0/108", "lanes": "81,82,83,84"}, "Ethernet112": {"alias": "fortyGigE0/112", "lanes": "89,90,91,92"}, "Ethernet116": {"alias": "fortyGigE0/116", "lanes": "93,94,95,96"}, "Ethernet12": {"alias": "fortyGigE0/12", "lanes": "33,34,35,36"}, "Ethernet120": {"alias": "fortyGigE0/120", "lanes": "97,98,99,100"}, "Ethernet124": {"alias": "fortyGigE0/124", "lanes": "101,102,103,104"}, "Ethernet16": {"alias": "fortyGigE0/16", "lanes": "41,42,43,44"}, "Ethernet20": {"alias": "fortyGigE0/20", "lanes": "45,46,47,48"}, "Ethernet24": {"alias": "fortyGigE0/24", "lanes": "5,6,7,8"}, "Ethernet28": {"alias": "fortyGigE0/28", "lanes": "1,2,3,4"}, "Ethernet32": {"alias": "fortyGigE0/32", "lanes": "9,10,11,12"}, "Ethernet36": {"alias": "fortyGigE0/36", "lanes": "13,14,15,16"}, "Ethernet4": {"alias": "fortyGigE0/4", "lanes": "25,26,27,28"}, "Ethernet40": {"alias": "fortyGigE0/40", "lanes": "21,22,23,24"}, "Ethernet44": {"alias": "fortyGigE0/44", "lanes": "17,18,19,20"}, "Ethernet48": {"alias": "fortyGigE0/48", "lanes": "49,50,51,52"}, "Ethernet52": {"alias": "fortyGigE0/52", "lanes": "53,54,55,56"}, "Ethernet56": {"alias": "fortyGigE0/56", "lanes": "61,62,63,64"}, "Ethernet60": {"alias": "fortyGigE0/60", "lanes": "57,58,59,60"}, "Ethernet64": {"alias": "fortyGigE0/64", "lanes": "65,66,67,68"}, "Ethernet68": {"alias": "fortyGigE0/68", "lanes": "69,70,71,72"}, "Ethernet72": {"alias": "fortyGigE0/72", "lanes": "77,78,79,80"}, "Ethernet76": {"alias": "fortyGigE0/76", "lanes": "73,74,75,76"}, "Ethernet8": {"alias": "fortyGigE0/8", "lanes": "37,38,39,40"}, "Ethernet80": {"alias": "fortyGigE0/80", "lanes": "105,106,107,108"}, "Ethernet84": {"alias": "fortyGigE0/84", "lanes": "109,110,111,112"}, "Ethernet88": {"alias": "fortyGigE0/88", "lanes": "117,118,119,120"}, "Ethernet92": {"alias": "fortyGigE0/92", "lanes": "113,114,115,116"}, "Ethernet96": {"alias": "fortyGigE0/96", "lanes": "121,122,123,124"}}, + "VLAN": { + "Vlan1000": { + "vlanid": "1000" + } + }, + "VLAN_MEMBER": { + "Vlan1000|Ethernet0": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet4": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet8": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet12": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet16": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet20": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet24": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet28": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet32": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet36": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet40": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet44": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet48": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet52": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet56": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet60": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet64": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet68": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet72": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet76": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet80": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet84": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet88": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet92": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet96": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet100": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet104": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet108": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet112": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet116": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet120": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet124": { + "tagging_mode": "untagged" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/lldpd.conf b/src/sonic-config-engine/tests/sample_output/lldpd.conf new file mode 100644 index 000000000000..29739cb890d0 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/lldpd.conf @@ -0,0 +1,2 @@ +configure ports eth0 lldp portidsubtype local eth0 + diff --git a/src/sonic-config-engine/tests/sample_output/msn27.32ports.json b/src/sonic-config-engine/tests/sample_output/msn27.32ports.json new file mode 100644 index 000000000000..fd457c4be9b4 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/msn27.32ports.json @@ -0,0 +1,120 @@ +{ + "CABLE_LENGTH": { + "AZURE": { + "Ethernet0": "300m", + "Ethernet4": "300m", + "Ethernet8": "300m", + "Ethernet12": "300m", + "Ethernet16": "300m", + "Ethernet20": "300m", + "Ethernet24": "300m", + "Ethernet28": "300m", + "Ethernet32": "300m", + "Ethernet36": "300m", + "Ethernet40": "300m", + "Ethernet44": "300m", + "Ethernet48": "300m", + "Ethernet52": "300m", + "Ethernet56": "300m", + "Ethernet60": "300m", + "Ethernet64": "300m", + "Ethernet68": "300m", + "Ethernet72": "300m", + "Ethernet76": "300m", + "Ethernet80": "300m", + "Ethernet84": "300m", + "Ethernet88": "300m", + "Ethernet92": "300m", + "Ethernet96": "300m", + "Ethernet100": "300m", + "Ethernet104": "300m", + "Ethernet108": "300m", + "Ethernet112": "300m", + "Ethernet116": "300m", + "Ethernet120": "300m", + "Ethernet124": "300m" + } + }, + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "2097152", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "5242880", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "16777152", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "5242880", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"0" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "pg_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + }, + "q_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "q_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + } + }, + "BUFFER_PORT_INGRESS_PROFILE_LIST": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124": { + "profile_list" : "[BUFFER_PROFILE|ingress_lossless_profile],[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, + "BUFFER_PORT_EGRESS_PROFILE_LIST": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124": { + "profile_list" : "[BUFFER_PROFILE|egress_lossless_profile],[BUFFER_PROFILE|egress_lossy_profile]" + } + }, + "BUFFER_PG": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0-1": { + "profile" : "[BUFFER_PROFILE|pg_lossy_profile]" + } + }, + "BUFFER_QUEUE": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|3-4": { + "profile" : "[BUFFER_PROFILE|q_lossless_profile]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/ports.json b/src/sonic-config-engine/tests/sample_output/ports.json new file mode 100644 index 000000000000..62fe4bbb5ccd --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/ports.json @@ -0,0 +1,30 @@ +[ + { + "PORT_TABLE:Ethernet0": { + "speed": "10000", + "description": "" + }, + "OP": "SET" + }, + { + "PORT_TABLE:Ethernet4": { + "speed": "25000", + "description": "" + }, + "OP": "SET" + }, + { + "PORT_TABLE:Ethernet8": { + "speed": "1000", + "description": "Interface description" + }, + "OP": "SET" + }, + { + "PORT_TABLE:Ethernet12": { + "speed": "100000", + "description": "Interface description" + }, + "OP": "SET" + } +] diff --git a/src/sonic-config-engine/tests/sample_output/qos-dell6100.json b/src/sonic-config-engine/tests/sample_output/qos-dell6100.json new file mode 100644 index 000000000000..2d442ca2525e --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/qos-dell6100.json @@ -0,0 +1,888 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0" : "0", + "1" : "0", + "2" : "0", + "3" : "3", + "4" : "4", + "5" : "0", + "6" : "0", + "7" : "0", + "8" : "1", + "9" : "0", + "10": "0", + "11": "0", + "12": "0", + "13": "0", + "14": "0", + "15": "0", + "16": "0", + "17": "0", + "18": "0", + "19": "0", + "20": "0", + "21": "0", + "22": "0", + "23": "0", + "24": "0", + "25": "0", + "26": "0", + "27": "0", + "28": "0", + "29": "0", + "30": "0", + "31": "0", + "32": "0", + "33": "0", + "34": "0", + "35": "0", + "36": "0", + "37": "0", + "38": "0", + "39": "0", + "40": "0", + "41": "0", + "42": "0", + "43": "0", + "44": "0", + "45": "0", + "46": "5", + "47": "0", + "48": "0", + "49": "0", + "50": "0", + "51": "0", + "52": "0", + "53": "0", + "54": "0", + "55": "0", + "56": "0", + "57": "0", + "58": "0", + "59": "0", + "60": "0", + "61": "0", + "62": "0", + "63": "0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + "Ethernet0,Ethernet1,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet48,Ethernet52,Ethernet53,Ethernet54,Ethernet55,Ethernet56,Ethernet57,Ethernet58": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "1048576", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, + "QUEUE": { + "Ethernet0|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet1|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet4|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet5|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet6|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet7|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet8|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet9|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet10|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet11|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet12|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet13|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet14|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet15|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet16|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet17|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet20|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet21|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet22|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet23|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet24|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet25|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet26|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet27|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet28|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet29|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet30|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet31|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet32|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet36|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet37|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet38|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet39|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet40|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet41|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet42|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet48|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet52|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet53|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet54|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet55|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet56|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet57|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet58|3": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet1|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet4|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet5|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet6|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet7|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet8|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet9|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet10|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet11|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet12|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet13|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet14|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet15|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet16|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet17|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet20|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet21|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet22|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet23|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet24|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet25|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet26|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet27|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet28|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet29|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet30|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet31|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet32|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet36|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet37|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet38|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet39|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet40|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet41|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet42|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet48|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet52|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet53|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet54|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet55|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet56|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet57|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet58|4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet5|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet6|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet7|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet9|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet10|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet11|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet13|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet14|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet15|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet17|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet21|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet22|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet23|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet25|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet26|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet27|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet29|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet30|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet31|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet37|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet38|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet39|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet41|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet42|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet53|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet54|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet55|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet57|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet58|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet0|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet5|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet6|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet7|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet9|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet10|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet11|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet13|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet14|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet15|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet17|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet21|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet22|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet23|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet25|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet26|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet27|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet29|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet30|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet31|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet37|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet38|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet39|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet41|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet42|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet53|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet54|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet55|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet57|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet58|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet0|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet5|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet6|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet7|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet9|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet10|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet11|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet13|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet14|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet15|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet17|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet21|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet22|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet23|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet25|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet26|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet27|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet29|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet30|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet31|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet37|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet38|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet39|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet41|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet42|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet53|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet54|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet55|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet57|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet58|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel01.conf b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel01.conf new file mode 100644 index 000000000000..d69c0d6697b2 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel01.conf @@ -0,0 +1,17 @@ +{ + "device": "PortChannel01", + "hwaddr": "e4:1d:2d:a5:f3:ad", + "runner": { + "name": "lacp", + "active": true, + "min_ports": 1, + "tx_hash": ["eth", "ipv4", "ipv6"] + }, + "link_watch": { + "name": "ethtool" + }, + "ports": { + "Ethernet112": {} + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel02.conf b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel02.conf new file mode 100644 index 000000000000..e9b2ff4f1ad9 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel02.conf @@ -0,0 +1,17 @@ +{ + "device": "PortChannel02", + "hwaddr": "e4:1d:2d:a5:f3:ad", + "runner": { + "name": "lacp", + "active": true, + "min_ports": 1, + "tx_hash": ["eth", "ipv4", "ipv6"] + }, + "link_watch": { + "name": "ethtool" + }, + "ports": { + "Ethernet116": {} + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel03.conf b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel03.conf new file mode 100644 index 000000000000..a73617abade0 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel03.conf @@ -0,0 +1,17 @@ +{ + "device": "PortChannel03", + "hwaddr": "e4:1d:2d:a5:f3:ad", + "runner": { + "name": "lacp", + "active": true, + "min_ports": 1, + "tx_hash": ["eth", "ipv4", "ipv6"] + }, + "link_watch": { + "name": "ethtool" + }, + "ports": { + "Ethernet120": {} + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel04.conf b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel04.conf new file mode 100644 index 000000000000..073b8057d461 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel04.conf @@ -0,0 +1,17 @@ +{ + "device": "PortChannel04", + "hwaddr": "e4:1d:2d:a5:f3:ad", + "runner": { + "name": "lacp", + "active": true, + "min_ports": 1, + "tx_hash": ["eth", "ipv4", "ipv6"] + }, + "link_watch": { + "name": "ethtool" + }, + "ports": { + "Ethernet124": {} + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/wait_for_intf.sh b/src/sonic-config-engine/tests/sample_output/wait_for_intf.sh new file mode 100644 index 000000000000..0f06235eb0dc --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/wait_for_intf.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +function wait_until_iface_ready +{ + IFACE=$1 + + echo "Waiting until interface $IFACE is up..." + + # Wait for the interface to come up (i.e., 'ip link show' returns 0) + until ip link show dev $IFACE up > /dev/null 2>&1; do + sleep 1 + done + + echo "Interface $IFACE is up" + + echo "Waiting until interface $IFACE has an IPv4 address..." + + # Wait until the interface gets assigned an IPv4 address + while true; do + IP=$(ip -4 addr show dev $IFACE | grep "inet " | awk '{ print $2 }' | cut -d '/' -f1) + + if [ -n "$IP" ]; then + break + fi + + sleep 1 + done + + echo "Interface $IFACE is configured with IP $IP" +} + + +# Wait for all interfaces to come up and have IPv4 addresses assigned +wait_until_iface_ready Vlan1000 +wait_until_iface_ready PortChannel01 +wait_until_iface_ready PortChannel01 +wait_until_iface_ready PortChannel02 +wait_until_iface_ready PortChannel02 +wait_until_iface_ready PortChannel03 +wait_until_iface_ready PortChannel03 +wait_until_iface_ready PortChannel04 +wait_until_iface_ready PortChannel04 + diff --git a/src/sonic-config-engine/tests/sample_output/zebra_quagga.conf b/src/sonic-config-engine/tests/sample_output/zebra_quagga.conf new file mode 100644 index 000000000000..aa3486b0163a --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/zebra_quagga.conf @@ -0,0 +1,44 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/zebra.conf.j2 using config DB data +! file: zebra.conf +! +! +hostname switch-t0 +password zebra +enable password zebra +! +! Enable link-detect (default disabled) +interface PortChannel01 +link-detect +! +interface PortChannel02 +link-detect +! +interface PortChannel03 +link-detect +! +interface PortChannel04 +link-detect +! +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.0.0.1 200 +! +! Set ip source to loopback for bgp learned routes +route-map RM_SET_SRC permit 10 + set src 10.1.0.32 +! + +route-map RM_SET_SRC6 permit 10 + set src fc00:1::32 +! +ip protocol bgp route-map RM_SET_SRC +! +ipv6 protocol bgp route-map RM_SET_SRC6 +! +! +log syslog informational +log facility local4 +! + diff --git a/src/sonic-config-engine/tests/simple-sample-graph-case.xml b/src/sonic-config-engine/tests/simple-sample-graph-case.xml new file mode 100644 index 000000000000..5a776099017d --- /dev/null +++ b/src/sonic-config-engine/tests/simple-sample-graph-case.xml @@ -0,0 +1,332 @@ + + + + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/4 + + + + + + ab1 + fortyGigE0/8 + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + fortyGigE0/0 + 10.0.0.58/31 + + + + fortyGigE0/0 + FC00::75/126 + + + + ab1 + 192.168.0.1/27 + + + + + + PortChannel01 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + + + + + + + + DeviceSerialLink + 9600 + switch-t0 + 1 + true + managed_device + console + + + DeviceInterfaceLink + true + 10000 + switch-t0 + fortyGigE0/0 + switch-01t1 + port1 + + + + + switch-t0 + Force10-S6000 + + + switch-01t1 +
+ 10.1.0.186/32 +
+ 2 + + + 10.7.0.196/26 + + Force10-S6000 +
+
+
+ + + + switch-t0 + + + DeploymentId + + 1 + + + ErspanDestinationIpv4 + + 10.0.100.1 + + + NtpResources + + 10.0.10.1;10.0.10.2 + + + + SnmpResources + + 10.0.10.3;10.0.10.4 + + + + SyslogResources + + 10.0.10.5;10.0.10.6; + + + + TacacsServer + + 10.0.10.7;10.0.10.8 + + + + + + + + + true + + + DeviceInterface + + true + true + 1 + fortyGigE0/0 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + true + 1 + fortyGigE0/4 + + false + 0 + 0 + 25000 + + + DeviceInterface + + true + true + 1 + fortyGigE0/8 + + false + 0 + 0 + 40000 + Interface description + + + DeviceInterface + + true + true + 1 + fortyGigE0/12 + + false + 0 + 0 + 100000 + Interface description + + + true + 0 + Force10-S6000 + + + switch-T0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/simple-sample-graph-metadata.xml b/src/sonic-config-engine/tests/simple-sample-graph-metadata.xml new file mode 100644 index 000000000000..28044f1c8780 --- /dev/null +++ b/src/sonic-config-engine/tests/simple-sample-graph-metadata.xml @@ -0,0 +1,317 @@ + + + + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/4 + + + + + + ab1 + fortyGigE0/8 + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + fortyGigE0/0 + 10.0.0.58/31 + + + + fortyGigE0/0 + FC00::75/126 + + + + ab1 + 192.168.0.1/27 + + + + + + PortChannel01 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + + + + + + + + + switch-t0 + Force10-S6000 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + + + + switch-t0 + + + DeploymentId + + 1 + + + ErspanDestinationIpv4 + + 10.0.100.1 + + + NtpResources + + 10.0.10.1;10.0.10.2 + + + + SnmpResources + + 10.0.10.3;10.0.10.4 + + + + SyslogResources + + 10.0.10.5;10.0.10.6; + + + + TacacsServer + + 10.0.10.7;10.0.10.8 + + + + + + + + + true + + + DeviceInterface + + true + true + 1 + fortyGigE0/0 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + true + 1 + fortyGigE0/4 + + false + 0 + 0 + 25000 + + + DeviceInterface + + true + true + 1 + fortyGigE0/8 + + false + 0 + 0 + 40000 + Interface description + + + DeviceInterface + + true + true + 1 + fortyGigE0/12 + + false + 0 + 0 + 100000 + Interface description + + + true + 0 + Force10-S6000 + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/simple-sample-graph.xml b/src/sonic-config-engine/tests/simple-sample-graph.xml new file mode 100644 index 000000000000..f5054bb084d3 --- /dev/null +++ b/src/sonic-config-engine/tests/simple-sample-graph.xml @@ -0,0 +1,349 @@ + + + + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/4 + + + + PortChannel1001 + fortyGigE0/1;fortyGigE0/2 + + + + + + ab1 + fortyGigE0/8 + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + PortChannel1001 + 10.0.0.57/31 + + + + PortChannel1001 + FC00::72/126 + + + + fortyGigE0/0 + 10.0.0.58/31 + + + + fortyGigE0/0 + FC00::75/126 + + + + ab1 + 192.168.0.1/27 + + + + + + PortChannel01 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + + + + + + + + DeviceInterfaceLink + true + 1000 + ARISTA01T1 + et1 + true + switch-t0 + fortyGigE0/8 + true + + + DeviceInterfaceLink + true + 10000 + switch-t0 + fortyGigE0/1 + true + ARISTA05T1 + Ethernet1/32 + true + + + DeviceInterfaceLink + true + 10000 + switch-t0 + fortyGigE0/2 + true + ARISTA06T1 + Ethernet1/33 + true + + + + + switch-t0 + Force10-S6000 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + + + true + + + DeviceInterface + + true + true + 1 + fortyGigE0/0 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + true + 1 + Ethernet1 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + true + 1 + Ethernet2 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + true + 1 + fortyGigE0/4 + + false + 0 + 0 + 25000 + + + DeviceInterface + + true + true + 1 + fortyGigE0/8 + + false + 0 + 0 + 40000 + Interface description + + + DeviceInterface + + true + true + 1 + fortyGigE0/12 + + false + 0 + 0 + 100000 + Interface description + + + true + 0 + Force10-S6000 + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/t0-sample-acl.json b/src/sonic-config-engine/tests/t0-sample-acl.json new file mode 100644 index 000000000000..1caf2ff02959 --- /dev/null +++ b/src/sonic-config-engine/tests/t0-sample-acl.json @@ -0,0 +1,176 @@ +{ + "acl": { + "acl-sets": { + "acl-set": { + "dataacl": { + "acl-entries": { + "acl-entry": { + "1": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 1 + }, + "ip": { + "config": { + "protocol": "IP_UDP", + "source-ip-address": "10.0.0.0/8" + } + } + }, + "2": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 2 + }, + "ip": { + "config": { + "protocol": "IP_UDP", + "source-ip-address": "100.64.0.0/10" + } + } + }, + "3": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 3 + }, + "ip": { + "config": { + "protocol": "IP_UDP", + "source-ip-address": "25.0.0.0/8" + } + } + }, + "4": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 4 + }, + "ip": { + "config": { + "protocol": "IP_TCP" + } + }, + "transport": { + "config": { + "tcp-flags": [ + "TCP_ACK" + ] + } + } + } + } + }, + "config": { + "name": "dataacl" + } + }, + "everflow": { + "acl-entries": { + "acl-entry": { + "1": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 1 + }, + "ip": { + "config": { + "destination-ip-address": "127.0.0.1/32", + "protocol": "IP_TCP", + "source-ip-address": "127.0.0.1/32" + } + }, + "transport": { + "config": { + "destination-port": "0", + "source-port": "0" + } + } + } + } + }, + "config": { + "name": "everflow" + } + }, + "SNMP-ACL": { + "acl-entries": { + "acl-entry": { + "1": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 1 + }, + "ip": { + "config": { + "protocol": "IP_UDP", + "source-ip-address": "10.0.0.0/8" + } + } + }, + "2": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 2 + }, + "ip": { + "config": { + "protocol": "IP_UDP", + "source-ip-address": "100.64.0.0/10" + } + } + }, + "3": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 3 + }, + "ip": { + "config": { + "protocol": "IP_UDP", + "source-ip-address": "25.0.0.0/8" + } + } + } + } + }, + "config": { + "name": "SNMP-ACL" + } + } + } + } + } +} diff --git a/src/sonic-config-engine/tests/t0-sample-bgp-speaker.xml b/src/sonic-config-engine/tests/t0-sample-bgp-speaker.xml new file mode 100644 index 000000000000..f2690985d9f3 --- /dev/null +++ b/src/sonic-config-engine/tests/t0-sample-bgp-speaker.xml @@ -0,0 +1,351 @@ + + + + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.60 + ARISTA03T1 + 10.0.0.61 + 1 + 180 + 60 + + + switch-t0 + FC00::79 + ARISTA03T1 + FC00::7A + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.62 + ARISTA04T1 + 10.0.0.63 + 1 + 180 + 60 + + + switch-t0 + FC00::7D + ARISTA04T1 + FC00::7E + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+ +
10.0.0.61
+ + + +
+ +
10.0.0.63
+ + + +
+ +
10.1.0.32
+ BGPSLBPassive + 10.10.10.10/26;100.100.100.100/26 +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/112 + + + + PortChannel02 + fortyGigE0/116 + + + + PortChannel03 + fortyGigE0/120 + + + + PortChannel04 + fortyGigE0/124 + + + + + + Vlan1000 + fortyGigE0/4;fortyGigE0/8;fortyGigE0/12;fortyGigE0/16;fortyGigE0/20;fortyGigE0/24;fortyGigE0/28;fortyGigE0/32;fortyGigE0/36;fortyGigE0/40;fortyGigE0/44;fortyGigE0/48;fortyGigE0/52;fortyGigE0/56;fortyGigE0/60;fortyGigE0/64;fortyGigE0/68;fortyGigE0/72;fortyGigE0/76;fortyGigE0/80;fortyGigE0/84;fortyGigE0/88;fortyGigE0/92;fortyGigE0/96 + False + 0.0.0.0/0 + + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + PortChannel02 + 10.0.0.58/31 + + + + PortChannel02 + FC00::75/126 + + + + PortChannel03 + 10.0.0.60/31 + + + + PortChannel03 + FC00::79/126 + + + + PortChannel04 + 10.0.0.62/31 + + + + PortChannel04 + FC00::7D/126 + + + + Vlan1000 + 192.168.0.1/27 + + + + + + PortChannel01;PortChannel02;PortChannel03;PortChannel04 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + + + + + + + + DeviceInterfaceLink + ARISTA01T1 + Ethernet1/1 + switch-t0 + fortyGigE0/112 + + + DeviceInterfaceLink + ARISTA02T1 + Ethernet1/1 + switch-t0 + fortyGigE0/116 + + + DeviceInterfaceLink + ARISTA03T1 + Ethernet1/1 + switch-t0 + fortyGigE0/120 + + + DeviceInterfaceLink + ARISTA04T1 + Ethernet1/1 + switch-t0 + fortyGigE0/124 + + + + + switch-t0 + Force10-S6000 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + + + + switch-t0 + + + ErspanDestinationIpv4 + + 2.2.2.2 + + + DeploymentId + 1 + + + + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/t0-sample-graph-everflow.xml b/src/sonic-config-engine/tests/t0-sample-graph-everflow.xml new file mode 100644 index 000000000000..6a078b48cf99 --- /dev/null +++ b/src/sonic-config-engine/tests/t0-sample-graph-everflow.xml @@ -0,0 +1,321 @@ + + + + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.60 + ARISTA03T1 + 10.0.0.61 + 1 + 180 + 60 + + + switch-t0 + FC00::79 + ARISTA03T1 + FC00::7A + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.62 + ARISTA04T1 + 10.0.0.63 + 1 + 180 + 60 + + + switch-t0 + FC00::7D + ARISTA04T1 + FC00::7E + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+ +
10.0.0.61
+ + + +
+ +
10.0.0.63
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/112 + + + + PortChannel02 + fortyGigE0/116 + + + + PortChannel03 + fortyGigE0/120 + + + + PortChannel04 + fortyGigE0/124 + + + + + + Vlan1000 + fortyGigE0/4;fortyGigE0/8;fortyGigE0/12;fortyGigE0/16;fortyGigE0/20;fortyGigE0/24;fortyGigE0/28;fortyGigE0/32;fortyGigE0/36;fortyGigE0/40;fortyGigE0/44;fortyGigE0/48;fortyGigE0/52;fortyGigE0/56;fortyGigE0/60;fortyGigE0/64;fortyGigE0/68;fortyGigE0/72;fortyGigE0/76;fortyGigE0/80;fortyGigE0/84;fortyGigE0/88;fortyGigE0/92;fortyGigE0/96 + False + 0.0.0.0/0 + + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + PortChannel02 + 10.0.0.58/31 + + + + PortChannel02 + FC00::75/126 + + + + PortChannel03 + 10.0.0.60/31 + + + + PortChannel03 + FC00::79/126 + + + + PortChannel04 + 10.0.0.62/31 + + + + PortChannel04 + FC00::7D/126 + + + + Vlan1000 + 192.168.0.1/27 + + + + + + ERSPAN + everflow + + + + + + + + + + DeviceInterfaceLink + ARISTA01T1 + Ethernet1/1 + switch-t0 + fortyGigE0/112 + + + DeviceInterfaceLink + ARISTA02T1 + Ethernet1/1 + switch-t0 + fortyGigE0/116 + + + DeviceInterfaceLink + ARISTA03T1 + Ethernet1/1 + switch-t0 + fortyGigE0/120 + + + DeviceInterfaceLink + ARISTA04T1 + Ethernet1/1 + switch-t0 + fortyGigE0/124 + + + + + switch-t0 + Force10-S6000 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/t0-sample-graph.xml b/src/sonic-config-engine/tests/t0-sample-graph.xml new file mode 100644 index 000000000000..5eace767c468 --- /dev/null +++ b/src/sonic-config-engine/tests/t0-sample-graph.xml @@ -0,0 +1,393 @@ + + + + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.60 + ARISTA03T1 + 10.0.0.61 + 1 + 180 + 60 + + + switch-t0 + FC00::79 + ARISTA03T1 + FC00::7A + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.62 + ARISTA04T1 + 10.0.0.63 + 1 + 180 + 60 + + + switch-t0 + FC00::7D + ARISTA04T1 + FC00::7E + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+ +
10.0.0.61
+ + + +
+ +
10.0.0.63
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + LoopbackIP1 + Loopback1 + + 10.10.0.99/32 + + 10.10.0.99/32 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + HostIP + eth0 + + 2603:10e2:0:2902::8/64 + + 2603:10e2:0:2902::8/64 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/112 + + + + PortChannel02 + fortyGigE0/116 + + + + PortChannel03 + fortyGigE0/120 + + + + PortChannel04 + fortyGigE0/124 + + + + + + Vlan1000 + fortyGigE0/4;fortyGigE0/8;fortyGigE0/12;fortyGigE0/16;fortyGigE0/20;fortyGigE0/24;fortyGigE0/28;fortyGigE0/32;fortyGigE0/36;fortyGigE0/40;fortyGigE0/44;fortyGigE0/48;fortyGigE0/52;fortyGigE0/56;fortyGigE0/60;fortyGigE0/64;fortyGigE0/68;fortyGigE0/72;fortyGigE0/76;fortyGigE0/80;fortyGigE0/84;fortyGigE0/88;fortyGigE0/92;fortyGigE0/96 + False + 0.0.0.0/0 + + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + PortChannel02 + 10.0.0.58/31 + + + + PortChannel02 + FC00::75/126 + + + + PortChannel03 + 10.0.0.60/31 + + + + PortChannel03 + FC00::79/126 + + + + PortChannel04 + 10.0.0.62/31 + + + + PortChannel04 + FC00::7D/126 + + + + Vlan1000 + 192.168.0.1/27 + + + + + + PortChannel01;PortChannel02;PortChannel03;PortChannel04 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + NTP + NTP_ACL + NTP + + + SSH + SSH_ACL + SSH + + + SSH + ROUTER-PROTECT + SSH + + + SNMP + ROUTER-PROTECT + SNMP + + + NTP + NTP_ACL + + + + + + + + + + DeviceInterfaceLink + ARISTA01T1 + Ethernet1/1 + switch-t0 + fortyGigE0/112 + + + DeviceInterfaceLink + ARISTA02T1 + Ethernet1/1 + switch-t0 + fortyGigE0/116 + + + DeviceInterfaceLink + ARISTA03T1 + Ethernet1/1 + switch-t0 + fortyGigE0/120 + + + DeviceInterfaceLink + ARISTA04T1 + Ethernet1/1 + switch-t0 + fortyGigE0/124 + + + DeviceInterfaceLink + true + 10000 + switch-t0 + fortyGigE0/2 + true + ARISTA05T1 + Ethernet1/33 + true + + + + + switch-t0 + Force10-S6000 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + + + + switch-t0 + + + ErspanDestinationIpv4 + + 2.2.2.2 + + + + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/t0-sample-port-config.ini b/src/sonic-config-engine/tests/t0-sample-port-config.ini new file mode 100644 index 000000000000..06898f1d7964 --- /dev/null +++ b/src/sonic-config-engine/tests/t0-sample-port-config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 29,30,31,32 fortyGigE0/0 +Ethernet4 25,26,27,28 fortyGigE0/4 +Ethernet8 37,38,39,40 fortyGigE0/8 +Ethernet12 33,34,35,36 fortyGigE0/12 +Ethernet16 41,42,43,44 fortyGigE0/16 +Ethernet20 45,46,47,48 fortyGigE0/20 +Ethernet24 5,6,7,8 fortyGigE0/24 +Ethernet28 1,2,3,4 fortyGigE0/28 +Ethernet32 9,10,11,12 fortyGigE0/32 +Ethernet36 13,14,15,16 fortyGigE0/36 +Ethernet40 21,22,23,24 fortyGigE0/40 +Ethernet44 17,18,19,20 fortyGigE0/44 +Ethernet48 49,50,51,52 fortyGigE0/48 +Ethernet52 53,54,55,56 fortyGigE0/52 +Ethernet56 61,62,63,64 fortyGigE0/56 +Ethernet60 57,58,59,60 fortyGigE0/60 +Ethernet64 65,66,67,68 fortyGigE0/64 +Ethernet68 69,70,71,72 fortyGigE0/68 +Ethernet72 77,78,79,80 fortyGigE0/72 +Ethernet76 73,74,75,76 fortyGigE0/76 +Ethernet80 105,106,107,108 fortyGigE0/80 +Ethernet84 109,110,111,112 fortyGigE0/84 +Ethernet88 117,118,119,120 fortyGigE0/88 +Ethernet92 113,114,115,116 fortyGigE0/92 +Ethernet96 121,122,123,124 fortyGigE0/96 +Ethernet100 125,126,127,128 fortyGigE0/100 +Ethernet104 85,86,87,88 fortyGigE0/104 +Ethernet108 81,82,83,84 fortyGigE0/108 +Ethernet112 89,90,91,92 fortyGigE0/112 +Ethernet116 93,94,95,96 fortyGigE0/116 +Ethernet120 97,98,99,100 fortyGigE0/120 +Ethernet124 101,102,103,104 fortyGigE0/124 diff --git a/src/sonic-config-engine/tests/t1-sample-graph-mlnx.xml b/src/sonic-config-engine/tests/t1-sample-graph-mlnx.xml new file mode 100644 index 000000000000..04fc88c34370 --- /dev/null +++ b/src/sonic-config-engine/tests/t1-sample-graph-mlnx.xml @@ -0,0 +1,2240 @@ + + + + + + ARISTA01T0 + 10.0.0.33 + arc-switch1026 + 10.0.0.32 + 1 + 10 + 3 + + + ARISTA01T0 + FC00::42 + arc-switch1026 + FC00::41 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.0 + ARISTA01T2 + 10.0.0.1 + 1 + 10 + 3 + + + arc-switch1026 + FC00::1 + ARISTA01T2 + FC00::2 + 1 + 10 + 3 + + + ARISTA02T0 + 10.0.0.35 + arc-switch1026 + 10.0.0.34 + 1 + 10 + 3 + + + ARISTA02T0 + FC00::46 + arc-switch1026 + FC00::45 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.2 + ARISTA02T2 + 10.0.0.3 + 1 + 10 + 3 + + + arc-switch1026 + FC00::5 + ARISTA02T2 + FC00::6 + 1 + 10 + 3 + + + ARISTA03T0 + 10.0.0.37 + arc-switch1026 + 10.0.0.36 + 1 + 10 + 3 + + + ARISTA03T0 + FC00::4A + arc-switch1026 + FC00::49 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.4 + ARISTA03T2 + 10.0.0.5 + 1 + 10 + 3 + + + arc-switch1026 + FC00::9 + ARISTA03T2 + FC00::A + 1 + 10 + 3 + + + ARISTA04T0 + 10.0.0.39 + arc-switch1026 + 10.0.0.38 + 1 + 10 + 3 + + + ARISTA04T0 + FC00::4E + arc-switch1026 + FC00::4D + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.6 + ARISTA04T2 + 10.0.0.7 + 1 + 10 + 3 + + + arc-switch1026 + FC00::D + ARISTA04T2 + FC00::E + 1 + 10 + 3 + + + ARISTA05T0 + 10.0.0.41 + arc-switch1026 + 10.0.0.40 + 1 + 10 + 3 + + + ARISTA05T0 + FC00::52 + arc-switch1026 + FC00::51 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.8 + ARISTA05T2 + 10.0.0.9 + 1 + 10 + 3 + + + arc-switch1026 + FC00::11 + ARISTA05T2 + FC00::12 + 1 + 10 + 3 + + + ARISTA06T0 + 10.0.0.43 + arc-switch1026 + 10.0.0.42 + 1 + 10 + 3 + + + ARISTA06T0 + FC00::56 + arc-switch1026 + FC00::55 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.10 + ARISTA06T2 + 10.0.0.11 + 1 + 10 + 3 + + + arc-switch1026 + FC00::15 + ARISTA06T2 + FC00::16 + 1 + 10 + 3 + + + ARISTA07T0 + 10.0.0.45 + arc-switch1026 + 10.0.0.44 + 1 + 10 + 3 + + + ARISTA07T0 + FC00::5A + arc-switch1026 + FC00::59 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.12 + ARISTA07T2 + 10.0.0.13 + 1 + 10 + 3 + + + arc-switch1026 + FC00::19 + ARISTA07T2 + FC00::1A + 1 + 10 + 3 + + + ARISTA08T0 + 10.0.0.47 + arc-switch1026 + 10.0.0.46 + 1 + 10 + 3 + + + ARISTA08T0 + FC00::5E + arc-switch1026 + FC00::5D + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.14 + ARISTA08T2 + 10.0.0.15 + 1 + 10 + 3 + + + arc-switch1026 + FC00::1D + ARISTA08T2 + FC00::1E + 1 + 10 + 3 + + + ARISTA09T0 + 10.0.0.49 + arc-switch1026 + 10.0.0.48 + 1 + 10 + 3 + + + ARISTA09T0 + FC00::62 + arc-switch1026 + FC00::61 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.16 + ARISTA09T2 + 10.0.0.17 + 1 + 10 + 3 + + + arc-switch1026 + FC00::21 + ARISTA09T2 + FC00::22 + 1 + 10 + 3 + + + ARISTA10T0 + 10.0.0.51 + arc-switch1026 + 10.0.0.50 + 1 + 10 + 3 + + + ARISTA10T0 + FC00::66 + arc-switch1026 + FC00::65 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.18 + ARISTA10T2 + 10.0.0.19 + 1 + 10 + 3 + + + arc-switch1026 + FC00::25 + ARISTA10T2 + FC00::26 + 1 + 10 + 3 + + + ARISTA11T0 + 10.0.0.53 + arc-switch1026 + 10.0.0.52 + 1 + 10 + 3 + + + ARISTA11T0 + FC00::6A + arc-switch1026 + FC00::69 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.20 + ARISTA11T2 + 10.0.0.21 + 1 + 10 + 3 + + + arc-switch1026 + FC00::29 + ARISTA11T2 + FC00::2A + 1 + 10 + 3 + + + ARISTA12T0 + 10.0.0.55 + arc-switch1026 + 10.0.0.54 + 1 + 10 + 3 + + + ARISTA12T0 + FC00::6E + arc-switch1026 + FC00::6D + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.22 + ARISTA12T2 + 10.0.0.23 + 1 + 10 + 3 + + + arc-switch1026 + FC00::2D + ARISTA12T2 + FC00::2E + 1 + 10 + 3 + + + ARISTA13T0 + 10.0.0.57 + arc-switch1026 + 10.0.0.56 + 1 + 10 + 3 + + + ARISTA13T0 + FC00::72 + arc-switch1026 + FC00::71 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.24 + ARISTA13T2 + 10.0.0.25 + 1 + 10 + 3 + + + arc-switch1026 + FC00::31 + ARISTA13T2 + FC00::32 + 1 + 10 + 3 + + + ARISTA14T0 + 10.0.0.59 + arc-switch1026 + 10.0.0.58 + 1 + 10 + 3 + + + ARISTA14T0 + FC00::76 + arc-switch1026 + FC00::75 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.26 + ARISTA14T2 + 10.0.0.27 + 1 + 10 + 3 + + + arc-switch1026 + FC00::35 + ARISTA14T2 + FC00::36 + 1 + 10 + 3 + + + ARISTA15T0 + 10.0.0.61 + arc-switch1026 + 10.0.0.60 + 1 + 10 + 3 + + + ARISTA15T0 + FC00::7A + arc-switch1026 + FC00::79 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.28 + ARISTA15T2 + 10.0.0.29 + 1 + 10 + 3 + + + arc-switch1026 + FC00::39 + ARISTA15T2 + FC00::3A + 1 + 10 + 3 + + + ARISTA16T0 + 10.0.0.63 + arc-switch1026 + 10.0.0.62 + 1 + 10 + 3 + + + ARISTA16T0 + FC00::7E + arc-switch1026 + FC00::7D + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.30 + ARISTA16T2 + 10.0.0.31 + 1 + 10 + 3 + + + arc-switch1026 + FC00::3D + ARISTA16T2 + FC00::3E + 1 + 10 + 3 + + + + + 65100 + arc-switch1026 + + +
10.0.0.33
+ + +
+ +
10.0.0.1
+ + +
+ +
10.0.0.35
+ + +
+ +
10.0.0.3
+ + +
+ +
10.0.0.37
+ + +
+ +
10.0.0.5
+ + +
+ +
10.0.0.39
+ + +
+ +
10.0.0.7
+ + +
+ +
10.0.0.41
+ + +
+ +
10.0.0.9
+ + +
+ +
10.0.0.43
+ + +
+ +
10.0.0.11
+ + +
+ +
10.0.0.45
+ + +
+ +
10.0.0.13
+ + +
+ +
10.0.0.47
+ + +
+ +
10.0.0.15
+ + +
+ +
10.0.0.49
+ + +
+ +
10.0.0.17
+ + +
+ +
10.0.0.51
+ + +
+ +
10.0.0.19
+ + +
+ +
10.0.0.53
+ + +
+ +
10.0.0.21
+ + +
+ +
10.0.0.55
+ + +
+ +
10.0.0.23
+ + +
+ +
10.0.0.57
+ + +
+ +
10.0.0.25
+ + +
+ +
10.0.0.59
+ + +
+ +
10.0.0.27
+ + +
+ +
10.0.0.61
+ + +
+ +
10.0.0.29
+ + +
+ +
10.0.0.63
+ + +
+ +
10.0.0.31
+ + +
+
+ +
+ + 64001 + ARISTA01T0 + + + + 65200 + ARISTA01T2 + + + + 64002 + ARISTA02T0 + + + + 65200 + ARISTA02T2 + + + + 64003 + ARISTA03T0 + + + + 65200 + ARISTA03T2 + + + + 64004 + ARISTA04T0 + + + + 65200 + ARISTA04T2 + + + + 64005 + ARISTA05T0 + + + + 65200 + ARISTA05T2 + + + + 64006 + ARISTA06T0 + + + + 65200 + ARISTA06T2 + + + + 64007 + ARISTA07T0 + + + + 65200 + ARISTA07T2 + + + + 64008 + ARISTA08T0 + + + + 65200 + ARISTA08T2 + + + + 64009 + ARISTA09T0 + + + + 65200 + ARISTA09T2 + + + + 64010 + ARISTA10T0 + + + + 65200 + ARISTA10T2 + + + + 64011 + ARISTA11T0 + + + + 65200 + ARISTA11T2 + + + + 64012 + ARISTA12T0 + + + + 65200 + ARISTA12T2 + + + + 64013 + ARISTA13T0 + + + + 65200 + ARISTA13T2 + + + + 64014 + ARISTA14T0 + + + + 65200 + ARISTA14T2 + + + + 64015 + ARISTA15T0 + + + + 65200 + ARISTA15T2 + + + + 64016 + ARISTA16T0 + + + + 65200 + ARISTA16T2 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.224.23.80/24 + + 10.224.23.80/24 + + + V6HostIP + eth0 + + FC00:2::32/64 + + FC00:2::32/64 + + + + + + arc-switch1026 + + + + + + Ethernet0 + 10.0.0.0/31 + + + + Ethernet0 + FC00::1/126 + + + + Ethernet4 + 10.0.0.2/31 + + + + Ethernet4 + FC00::5/126 + + + + Ethernet8 + 10.0.0.4/31 + + + + Ethernet8 + FC00::9/126 + + + + Ethernet12 + 10.0.0.6/31 + + + + Ethernet12 + FC00::D/126 + + + + Ethernet16 + 10.0.0.8/31 + + + + Ethernet16 + FC00::11/126 + + + + Ethernet20 + 10.0.0.10/31 + + + + Ethernet20 + FC00::15/126 + + + + Ethernet24 + 10.0.0.12/31 + + + + Ethernet24 + FC00::19/126 + + + + Ethernet28 + 10.0.0.14/31 + + + + Ethernet28 + FC00::1D/126 + + + + Ethernet32 + 10.0.0.16/31 + + + + Ethernet32 + FC00::21/126 + + + + Ethernet36 + 10.0.0.18/31 + + + + Ethernet36 + FC00::25/126 + + + + Ethernet40 + 10.0.0.20/31 + + + + Ethernet40 + FC00::29/126 + + + + Ethernet44 + 10.0.0.22/31 + + + + Ethernet44 + FC00::2D/126 + + + + Ethernet48 + 10.0.0.24/31 + + + + Ethernet48 + FC00::31/126 + + + + Ethernet52 + 10.0.0.26/31 + + + + Ethernet52 + FC00::35/126 + + + + Ethernet56 + 10.0.0.28/31 + + + + Ethernet56 + FC00::39/126 + + + + Ethernet60 + 10.0.0.30/31 + + + + Ethernet60 + FC00::3D/126 + + + + Ethernet64 + 10.0.0.32/31 + + + + Ethernet64 + FC00::41/126 + + + + Ethernet68 + 10.0.0.34/31 + + + + Ethernet68 + FC00::45/126 + + + + Ethernet72 + 10.0.0.36/31 + + + + Ethernet72 + FC00::49/126 + + + + Ethernet76 + 10.0.0.38/31 + + + + Ethernet76 + FC00::4D/126 + + + + Ethernet80 + 10.0.0.40/31 + + + + Ethernet80 + FC00::51/126 + + + + Ethernet84 + 10.0.0.42/31 + + + + Ethernet84 + FC00::55/126 + + + + Ethernet88 + 10.0.0.44/31 + + + + Ethernet88 + FC00::59/126 + + + + Ethernet92 + 10.0.0.46/31 + + + + Ethernet92 + FC00::5D/126 + + + + Ethernet96 + 10.0.0.48/31 + + + + Ethernet96 + FC00::61/126 + + + + Ethernet100 + 10.0.0.50/31 + + + + Ethernet100 + FC00::65/126 + + + + Ethernet104 + 10.0.0.52/31 + + + + Ethernet104 + FC00::69/126 + + + + Ethernet108 + 10.0.0.54/31 + + + + Ethernet108 + FC00::6D/126 + + + + Ethernet112 + 10.0.0.56/31 + + + + Ethernet112 + FC00::71/126 + + + + Ethernet116 + 10.0.0.58/31 + + + + Ethernet116 + FC00::75/126 + + + + Ethernet120 + 10.0.0.60/31 + + + + Ethernet120 + FC00::79/126 + + + + Ethernet124 + 10.0.0.62/31 + + + + Ethernet124 + FC00::7D/126 + + + + + + + + + + + + DeviceInterfaceLink + arc-switch1026 + Ethernet0 + ARISTA01T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet4 + ARISTA02T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet8 + ARISTA03T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet12 + ARISTA04T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet16 + ARISTA05T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet20 + ARISTA06T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet24 + ARISTA07T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet28 + ARISTA08T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet32 + ARISTA09T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet36 + ARISTA10T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet40 + ARISTA11T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet44 + ARISTA12T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet48 + ARISTA13T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet52 + ARISTA14T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet56 + ARISTA15T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet60 + ARISTA16T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet64 + ARISTA01T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet68 + ARISTA02T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet72 + ARISTA03T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet76 + ARISTA04T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet80 + ARISTA05T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet84 + ARISTA06T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet88 + ARISTA07T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet92 + ARISTA08T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet96 + ARISTA09T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet100 + ARISTA10T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet104 + ARISTA11T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet108 + ARISTA12T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet112 + ARISTA13T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet116 + ARISTA14T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet120 + ARISTA15T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet124 + ARISTA16T0 + Ethernet1 + + + + + arc-switch1026 + ACS-MSN2700 + + 10.224.23.80 + + + + "ARISTA01T0" + Arista-VM + + 10.224.23.196 + + + + "ARISTA01T2" + Arista-VM + + 10.224.23.180 + + + + "ARISTA02T0" + Arista-VM + + 10.224.23.197 + + + + "ARISTA02T2" + Arista-VM + + 10.224.23.181 + + + + "ARISTA03T0" + Arista-VM + + 10.224.23.198 + + + + "ARISTA03T2" + Arista-VM + + 10.224.23.182 + + + + "ARISTA04T0" + Arista-VM + + 10.224.23.199 + + + + "ARISTA04T2" + Arista-VM + + 10.224.23.183 + + + + "ARISTA05T0" + Arista-VM + + 10.224.23.200 + + + + "ARISTA05T2" + Arista-VM + + 10.224.23.184 + + + + "ARISTA06T0" + Arista-VM + + 10.224.23.201 + + + + "ARISTA06T2" + Arista-VM + + 10.224.23.185 + + + + "ARISTA07T0" + Arista-VM + + 10.224.23.202 + + + + "ARISTA07T2" + Arista-VM + + 10.224.23.186 + + + + "ARISTA08T0" + Arista-VM + + 10.224.23.203 + + + + "ARISTA08T2" + Arista-VM + + 10.224.23.187 + + + + "ARISTA09T0" + Arista-VM + + 10.224.23.152 + + + + "ARISTA09T2" + Arista-VM + + 10.224.23.188 + + + + "ARISTA10T0" + Arista-VM + + 10.224.23.153 + + + + "ARISTA10T2" + Arista-VM + + 10.224.23.189 + + + + "ARISTA11T0" + Arista-VM + + 10.224.23.154 + + + + "ARISTA11T2" + Arista-VM + + 10.224.23.190 + + + + "ARISTA12T0" + Arista-VM + + 10.224.23.155 + + + + "ARISTA12T2" + Arista-VM + + 10.224.23.191 + + + + "ARISTA13T0" + Arista-VM + + 10.224.23.156 + + + + "ARISTA13T2" + Arista-VM + + 10.224.23.192 + + + + "ARISTA14T0" + Arista-VM + + 10.224.23.157 + + + + "ARISTA14T2" + Arista-VM + + 10.224.23.193 + + + + "ARISTA15T0" + Arista-VM + + 10.224.23.158 + + + + "ARISTA15T2" + Arista-VM + + 10.224.23.194 + + + + "ARISTA16T0" + Arista-VM + + 10.224.23.159 + + + + "ARISTA16T2" + Arista-VM + + 10.224.23.195 + + + + + + + true + + + DeviceInterface + + true + true + 1 + Ethernet0 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet4 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet8 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet12 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet16 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet20 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet24 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet28 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet32 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet36 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet40 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet44 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet48 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet52 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet56 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet60 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet64 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet68 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet72 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet76 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet80 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet84 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet88 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet92 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet96 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet100 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet104 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet108 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet112 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet116 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet120 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet124 + + false + 0 + 0 + 40000 + + + true + 0 + ACS-MSN2700 + + + + + + + arc-switch1026 + + + DhcpResources + + 10.0.0.1 + + + NTPResources + + 10.0.0.1;10.0.0.2 + + + DeploymentId + + 1 + + + QosProfile + + Profile0 + + + RadiusResources + + + + + SnmpResources + + 10.0.0.9 + + + SyslogResources + + 10.0.0.5;10.0.0.6 + + + TacacsGroup + + testlab + + + TacacsServer + + 10.0.0.9;10.0.0.8 + + + ForcedMgmtRoutes + + 10.0.0.100/31;10.250.0.8;10.255.0.0/28 + + + ErspanDestinationIpv4 + + 10.0.0.7 + + + + + + + arc-switch1026 + ACS-MSN2700 +
diff --git a/src/sonic-config-engine/tests/test.j2 b/src/sonic-config-engine/tests/test.j2 new file mode 100644 index 000000000000..787a1f0a2c41 --- /dev/null +++ b/src/sonic-config-engine/tests/test.j2 @@ -0,0 +1,3 @@ +{% for item in yml_item -%} +{{ item }} +{% endfor %} diff --git a/src/sonic-config-engine/tests/test.yml b/src/sonic-config-engine/tests/test.yml new file mode 100644 index 000000000000..dc08eb66bed1 --- /dev/null +++ b/src/sonic-config-engine/tests/test.yml @@ -0,0 +1,3 @@ +yml_item: + - value1 + - value2 diff --git a/src/sonic-config-engine/tests/test_cfggen.py b/src/sonic-config-engine/tests/test_cfggen.py new file mode 100644 index 000000000000..f4ac56807ec5 --- /dev/null +++ b/src/sonic-config-engine/tests/test_cfggen.py @@ -0,0 +1,228 @@ +from unittest import TestCase +import subprocess +import os + +class TestCfgGen(TestCase): + + def setUp(self): + self.test_dir = os.path.dirname(os.path.realpath(__file__)) + self.script_file = os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.sample_graph = os.path.join(self.test_dir, 'sample_graph.xml') + self.sample_graph_t0 = os.path.join(self.test_dir, 't0-sample-graph.xml') + self.sample_graph_simple = os.path.join(self.test_dir, 'simple-sample-graph.xml') + self.sample_graph_metadata = os.path.join(self.test_dir, 'simple-sample-graph-metadata.xml') + self.sample_graph_pc_test = os.path.join(self.test_dir, 'pc-test-graph.xml') + self.sample_graph_bgp_speaker = os.path.join(self.test_dir, 't0-sample-bgp-speaker.xml') + self.sample_device_desc = os.path.join(self.test_dir, 'device.xml') + self.port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini') + + def run_script(self, argument, check_stderr=False): + print '\n Running sonic-cfggen ' + argument + if check_stderr: + output = subprocess.check_output(self.script_file + ' ' + argument, stderr=subprocess.STDOUT, shell=True) + else: + output = subprocess.check_output(self.script_file + ' ' + argument, shell=True) + + linecount = output.strip().count('\n') + if linecount <= 0: + print ' Output: ' + output.strip() + else: + print ' Output: ({0} lines, {1} bytes)'.format(linecount + 1, len(output)) + return output + + def test_dummy_run(self): + argument = '' + output = self.run_script(argument) + self.assertEqual(output, '') + + def test_device_desc(self): + argument = '-v "DEVICE_METADATA[\'localhost\'][\'hwsku\']" -M "' + self.sample_device_desc + '"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'ACS-MSN2700') + + def test_device_desc_mgmt_ip(self): + argument = '-v "MGMT_INTERFACE.keys()[0]" -M "' + self.sample_device_desc + '"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "('eth0', '10.0.1.5/28')") + + def test_minigraph_sku(self): + argument = '-v "DEVICE_METADATA[\'localhost\'][\'hwsku\']" -m "' + self.sample_graph + '"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'Force10-Z9100') + + def test_print_data(self): + argument = '-m "' + self.sample_graph + '" --print-data' + output = self.run_script(argument) + self.assertTrue(len(output.strip()) > 0) + + def test_jinja_expression(self): + argument = '-m "' + self.sample_graph + '" -v "DEVICE_METADATA[\'localhost\'][\'type\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'LeafRouter') + + def test_additional_json_data(self): + argument = '-a \'{"key1":"value1"}\' -v key1' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'value1') + + def test_read_yaml(self): + argument = '-v yml_item -y ' + os.path.join(self.test_dir, 'test.yml') + output = self.run_script(argument) + self.assertEqual(output.strip(), '[\'value1\', \'value2\']') + + def test_render_template(self): + argument = '-y ' + os.path.join(self.test_dir, 'test.yml') + ' -t ' + os.path.join(self.test_dir, 'test.j2') + output = self.run_script(argument) + self.assertEqual(output.strip(), 'value1\nvalue2') + + def test_minigraph_acl(self): + argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v ACL_TABLE' + output = self.run_script(argument, True) + self.assertEqual(output.strip(), "Warning: Ignoring Control Plane ACL NTP_ACL without type\n" + "Warning: ignore interface 'fortyGigE0/2' as it is not in the port_config.ini\n" + "Warning: ignore interface 'fortyGigE0/2' in DEVICE_NEIGHBOR as it is not in the port_config.ini\n" + "{'SSH_ACL': {'services': ['SSH'], 'type': 'CTRLPLANE', 'policy_desc': 'SSH_ACL'}," + " 'SNMP_ACL': {'services': ['SNMP'], 'type': 'CTRLPLANE', 'policy_desc': 'SNMP_ACL'}," + " 'DATAACL': {'type': 'L3', 'policy_desc': 'DATAACL', 'ports': ['PortChannel01', 'PortChannel02', 'PortChannel03', 'PortChannel04']}," + " 'NTP_ACL': {'services': ['NTP'], 'type': 'CTRLPLANE', 'policy_desc': 'NTP_ACL'}," + " 'ROUTER_PROTECT': {'services': ['SSH', 'SNMP'], 'type': 'CTRLPLANE', 'policy_desc': 'ROUTER_PROTECT'}}") + + def test_minigraph_everflow(self): + argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v MIRROR_SESSION' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'everflow0': {'src_ip': '10.1.0.32', 'dst_ip': '2.2.2.2'}}") + + def test_minigraph_mgmt_ports(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v MGMT_PORT' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'eth0': {'alias': 'Management0', 'admin_status': 'up'}}") + + def test_minigraph_interfaces(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "INTERFACE.keys()"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "[('Ethernet0', '10.0.0.58/31'), ('Ethernet0', 'FC00::75/126')]") + + def test_minigraph_vlans(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v VLAN' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'Vlan1000': {'alias': 'ab1', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '1000'}}") + + def test_minigraph_vlan_members(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v VLAN_MEMBER' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{('Vlan1000', 'Ethernet8'): {'tagging_mode': 'untagged'}}") + + def test_minigraph_vlan_interfaces(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "VLAN_INTERFACE.keys()"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "[('Vlan1000', '192.168.0.1/27')]") + + def test_minigraph_portchannels(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v PORTCHANNEL' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'PortChannel01': {'admin_status': 'up', 'min_links': '1', 'members': ['Ethernet4'], 'mtu': '9100'}}") + + def test_minigraph_portchannel_with_more_member(self): + argument = '-m "' + self.sample_graph_pc_test + '" -p "' + self.port_config + '" -v PORTCHANNEL' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'PortChannel01': {'admin_status': 'up', 'min_links': '3', 'members': ['Ethernet112', 'Ethernet116', 'Ethernet120', 'Ethernet124'], 'mtu': '9100'}}") + + def test_minigraph_portchannel_members(self): + argument = '-m "' + self.sample_graph_pc_test + '" -p "' + self.port_config + '" -v "PORTCHANNEL_MEMBER.keys()"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "[('PortChannel01', 'Ethernet120'), ('PortChannel01', 'Ethernet116'), ('PortChannel01', 'Ethernet124'), ('PortChannel01', 'Ethernet112')]") + + def test_minigraph_portchannel_interfaces(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORTCHANNEL_INTERFACE.keys()"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "[('PortChannel01', 'FC00::71/126'), ('PortChannel01', '10.0.0.56/31')]") + + def test_minigraph_neighbors(self): + argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v "DEVICE_NEIGHBOR[\'Ethernet124\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'name': 'ARISTA04T1', 'port': 'Ethernet1/1'}") + + def test_minigraph_extra_neighbors(self): + argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v DEVICE_NEIGHBOR' + output = self.run_script(argument) + self.assertEqual(output.strip(), \ + "{'Ethernet116': {'name': 'ARISTA02T1', 'port': 'Ethernet1/1'}, " + "'Ethernet124': {'name': 'ARISTA04T1', 'port': 'Ethernet1/1'}, " + "'Ethernet112': {'name': 'ARISTA01T1', 'port': 'Ethernet1/1'}, " + "'Ethernet120': {'name': 'ARISTA03T1', 'port': 'Ethernet1/1'}}") + + def test_minigraph_bgp(self): + argument = '-m "' + self.sample_graph_bgp_speaker + '" -p "' + self.port_config + '" -v "BGP_NEIGHBOR[\'10.0.0.59\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'rrclient': 0, 'name': 'ARISTA02T1', 'local_addr': '10.0.0.58', 'nhopself': 0, 'holdtime': '180', 'asn': '64600', 'keepalive': '60'}") + + def test_minigraph_peers_with_range(self): + argument = '-m "' + self.sample_graph_bgp_speaker + '" -p "' + self.port_config + '" -v BGP_PEER_RANGE.values\(\)' + output = self.run_script(argument) + self.assertEqual(output.strip(), "[{'name': 'BGPSLBPassive', 'ip_range': ['10.10.10.10/26', '100.100.100.100/26']}]") + + def test_minigraph_deployment_id(self): + argument = '-m "' + self.sample_graph_bgp_speaker + '" -p "' + self.port_config + '" -v "DEVICE_METADATA[\'localhost\'][\'deployment_id\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "1") + + def test_minigraph_ethernet_interfaces(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet8\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'lanes': '37,38,39,40', 'description': 'Interface description', 'mtu': '9100', 'alias': 'fortyGigE0/8', 'admin_status': 'up', 'speed': '1000'}") + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet12\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'lanes': '33,34,35,36', 'description': 'Interface description', 'mtu': '9100', 'alias': 'fortyGigE0/12', 'speed': '100000', 'fec': 'rs'}") + + def test_minigraph_extra_ethernet_interfaces(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORT"' + output = self.run_script(argument) + self.assertEqual(output.strip(), \ + "{'Ethernet8': {'lanes': '37,38,39,40', 'description': 'Interface description', 'mtu': '9100', 'alias': 'fortyGigE0/8', 'admin_status': 'up', 'speed': '1000'}, " + "'Ethernet0': {'alias': 'fortyGigE0/0', 'admin_status': 'up', 'lanes': '29,30,31,32', 'speed': '10000', 'mtu': '9100'}, " + "'Ethernet4': {'alias': 'fortyGigE0/4', 'admin_status': 'up', 'lanes': '25,26,27,28', 'speed': '25000', 'mtu': '9100'}, " + "'Ethernet108': {'alias': 'fortyGigE0/108', 'lanes': '81,82,83,84', 'mtu': '9100'}, " + "'Ethernet100': {'alias': 'fortyGigE0/100', 'lanes': '125,126,127,128', 'mtu': '9100'}, " + "'Ethernet104': {'alias': 'fortyGigE0/104', 'lanes': '85,86,87,88', 'mtu': '9100'}, " + "'Ethernet68': {'alias': 'fortyGigE0/68', 'lanes': '69,70,71,72', 'mtu': '9100'}, " + "'Ethernet96': {'alias': 'fortyGigE0/96', 'lanes': '121,122,123,124', 'mtu': '9100'}, " + "'Ethernet124': {'alias': 'fortyGigE0/124', 'lanes': '101,102,103,104', 'mtu': '9100'}, " + "'Ethernet92': {'alias': 'fortyGigE0/92', 'lanes': '113,114,115,116', 'mtu': '9100'}, " + "'Ethernet120': {'alias': 'fortyGigE0/120', 'lanes': '97,98,99,100', 'mtu': '9100'}, " + "'Ethernet52': {'alias': 'fortyGigE0/52', 'lanes': '53,54,55,56', 'mtu': '9100'}, " + "'Ethernet56': {'alias': 'fortyGigE0/56', 'lanes': '61,62,63,64', 'mtu': '9100'}, " + "'Ethernet76': {'alias': 'fortyGigE0/76', 'lanes': '73,74,75,76', 'mtu': '9100'}, " + "'Ethernet72': {'alias': 'fortyGigE0/72', 'lanes': '77,78,79,80', 'mtu': '9100'}, " + "'Ethernet64': {'alias': 'fortyGigE0/64', 'lanes': '65,66,67,68', 'mtu': '9100'}, " + "'Ethernet32': {'alias': 'fortyGigE0/32', 'lanes': '9,10,11,12', 'mtu': '9100'}, " + "'Ethernet16': {'alias': 'fortyGigE0/16', 'lanes': '41,42,43,44', 'mtu': '9100'}, " + "'Ethernet36': {'alias': 'fortyGigE0/36', 'lanes': '13,14,15,16', 'mtu': '9100'}, " + "'Ethernet12': {'lanes': '33,34,35,36', 'description': 'Interface description', 'mtu': '9100', 'alias': 'fortyGigE0/12', 'speed': '100000', 'fec': 'rs'}, " + "'Ethernet88': {'alias': 'fortyGigE0/88', 'lanes': '117,118,119,120', 'mtu': '9100'}, " + "'Ethernet116': {'alias': 'fortyGigE0/116', 'lanes': '93,94,95,96', 'mtu': '9100'}, " + "'Ethernet80': {'alias': 'fortyGigE0/80', 'lanes': '105,106,107,108', 'mtu': '9100'}, " + "'Ethernet112': {'alias': 'fortyGigE0/112', 'lanes': '89,90,91,92', 'mtu': '9100'}, " + "'Ethernet84': {'alias': 'fortyGigE0/84', 'lanes': '109,110,111,112', 'mtu': '9100'}, " + "'Ethernet48': {'alias': 'fortyGigE0/48', 'lanes': '49,50,51,52', 'mtu': '9100'}, " + "'Ethernet44': {'alias': 'fortyGigE0/44', 'lanes': '17,18,19,20', 'mtu': '9100'}, " + "'Ethernet40': {'alias': 'fortyGigE0/40', 'lanes': '21,22,23,24', 'mtu': '9100'}, " + "'Ethernet28': {'alias': 'fortyGigE0/28', 'lanes': '1,2,3,4', 'mtu': '9100'}, " + "'Ethernet60': {'alias': 'fortyGigE0/60', 'lanes': '57,58,59,60', 'mtu': '9100'}, " + "'Ethernet20': {'alias': 'fortyGigE0/20', 'lanes': '45,46,47,48', 'mtu': '9100'}, " + "'Ethernet24': {'alias': 'fortyGigE0/24', 'lanes': '5,6,7,8', 'mtu': '9100'}}") + + def test_metadata_everflow(self): + argument = '-m "' + self.sample_graph_metadata + '" -p "' + self.port_config + '" -v "MIRROR_SESSION"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'everflow0': {'src_ip': '10.1.0.32', 'dst_ip': '10.0.100.1'}}") + + def test_metadata_tacacs(self): + argument = '-m "' + self.sample_graph_metadata + '" -p "' + self.port_config + '" -v "TACPLUS_SERVER"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'10.0.10.7': {'priority': '1', 'tcp_port': '49'}, '10.0.10.8': {'priority': '1', 'tcp_port': '49'}}") + + def test_metadata_ntp(self): + argument = '-m "' + self.sample_graph_metadata + '" -p "' + self.port_config + '" -v "NTP_SERVER"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'10.0.10.1': {}, '10.0.10.2': {}}") + diff --git a/src/sonic-config-engine/tests/test_j2files.py b/src/sonic-config-engine/tests/test_j2files.py new file mode 100644 index 000000000000..d6066b628e61 --- /dev/null +++ b/src/sonic-config-engine/tests/test_j2files.py @@ -0,0 +1,136 @@ +import filecmp +import os +import subprocess +import json +import shutil + +from unittest import TestCase + +class TestJ2Files(TestCase): + def setUp(self): + self.test_dir = os.path.dirname(os.path.realpath(__file__)) + self.script_file = os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.simple_minigraph = os.path.join(self.test_dir, 'simple-sample-graph.xml') + self.t0_minigraph = os.path.join(self.test_dir, 't0-sample-graph.xml') + self.pc_minigraph = os.path.join(self.test_dir, 'pc-test-graph.xml') + self.t0_port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini') + self.t1_mlnx_minigraph = os.path.join(self.test_dir, 't1-sample-graph-mlnx.xml') + self.mlnx_port_config = os.path.join(self.test_dir, 'sample-port-config-mlnx.ini') + self.dell6100_t0_minigraph = os.path.join(self.test_dir, 'sample-dell-6100-t0-minigraph.xml') + self.output_file = os.path.join(self.test_dir, 'output') + + def run_script(self, argument): + print 'CMD: sonic-cfggen ' + argument + return subprocess.check_output(self.script_file + ' ' + argument, shell=True) + + def run_diff(self, file1, file2, diff): + return subprocess.check_output('diff {} {} >{}'.format(file1, file2, diff), shell=True) + + def test_interfaces(self): + interfaces_template = os.path.join(self.test_dir, '..', '..', '..', 'files', 'image_config', 'interfaces', 'interfaces.j2') + argument = '-m ' + self.t0_minigraph + ' -a \'{\"hwaddr\":\"e4:1d:2d:a5:f3:ad\"}\' -t ' + interfaces_template + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'interfaces'), self.output_file)) + + def test_ports_json(self): + ports_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-orchagent', 'ports.json.j2') + argument = '-m ' + self.simple_minigraph + ' -p ' + self.t0_port_config + ' -t ' + ports_template + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'ports.json'), self.output_file)) + + def test_dhcp_relay(self): + # Test generation of wait_for_intf.sh + template_path = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-dhcp-relay', 'wait_for_intf.sh.j2') + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + template_path + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'wait_for_intf.sh'), self.output_file)) + + # Test generation of docker-dhcp-relay.supervisord.conf + template_path = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-dhcp-relay', 'docker-dhcp-relay.supervisord.conf.j2') + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + template_path + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'docker-dhcp-relay.supervisord.conf'), self.output_file)) + + def test_lldp(self): + lldpd_conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-lldp-sv2', 'lldpd.conf.j2') + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + lldpd_conf_template + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'lldpd.conf'), self.output_file)) + + def test_bgpd_quagga(self): + conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-quagga', 'bgpd.conf.j2') + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + conf_template + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'bgpd_quagga.conf'), self.output_file)) + + def test_zebra_quagga(self): + conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-quagga', 'zebra.conf.j2') + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + conf_template + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'zebra_quagga.conf'), self.output_file)) + + def test_config_frr(self): + conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-frr', 'frr.conf.j2') + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + conf_template + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'frr.conf'), self.output_file)) + + def test_ipinip(self): + ipinip_file = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-orchagent', 'ipinip.json.j2') + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + ipinip_file + ' > ' + self.output_file + self.run_script(argument) + + sample_output_file = os.path.join(self.test_dir, 'sample_output', 'ipinip.json') + assert filecmp.cmp(sample_output_file, self.output_file) + + def test_sku_render_template(self): + argument = '-k Mellanox-SN2700 -t ' + os.path.join(self.test_dir, '../data/l2switch.j2') + ' -p ' + self.t0_port_config + ' > ' + self.output_file + self.run_script(argument) + + sample_output_file = os.path.join(self.test_dir, 'sample_output', 'l2switch.json') + + self.assertTrue(filecmp.cmp(sample_output_file, self.output_file)) + + def test_qos_dell6100_render_template(self): + dell_dir_path = os.path.join(self.test_dir, '..', '..', '..', 'device', 'dell', 'x86_64-dell_s6100_c2538-r0', 'Force10-S6100') + qos_file = os.path.join(dell_dir_path, 'qos.json.j2') + port_config_ini_file = os.path.join(dell_dir_path, 'port_config.ini') + + # copy qos_config.j2 to the Dell S6100 directory to have all templates in one directory + qos_config_file = os.path.join(self.test_dir, '..', '..', '..', 'files', 'build_templates', 'qos_config.j2') + shutil.copy2(qos_config_file, dell_dir_path) + + argument = '-m ' + self.dell6100_t0_minigraph + ' -p ' + port_config_ini_file + ' -t ' + qos_file + ' > ' + self.output_file + self.run_script(argument) + + # cleanup + qos_config_file_new = os.path.join(dell_dir_path, 'qos_config.j2') + os.remove(qos_config_file_new) + + sample_output_file = os.path.join(self.test_dir, 'sample_output', 'qos-dell6100.json') + assert filecmp.cmp(sample_output_file, self.output_file) + + def test_buffers_dell6100_render_template(self): + dell_dir_path = os.path.join(self.test_dir, '..', '..', '..', 'device', 'dell', 'x86_64-dell_s6100_c2538-r0', 'Force10-S6100') + buffers_file = os.path.join(dell_dir_path, 'buffers.json.j2') + port_config_ini_file = os.path.join(dell_dir_path, 'port_config.ini') + + # copy buffers_config.j2 to the Dell S6100 directory to have all templates in one directory + buffers_config_file = os.path.join(self.test_dir, '..', '..', '..', 'files', 'build_templates', 'buffers_config.j2') + shutil.copy2(buffers_config_file, dell_dir_path) + + argument = '-m ' + self.dell6100_t0_minigraph + ' -p ' + port_config_ini_file + ' -t ' + buffers_file + ' > ' + self.output_file + self.run_script(argument) + + # cleanup + buffers_config_file_new = os.path.join(dell_dir_path, 'buffers_config.j2') + os.remove(buffers_config_file_new) + + sample_output_file = os.path.join(self.test_dir, 'sample_output', 'buffers-dell6100.json') + assert filecmp.cmp(sample_output_file, self.output_file) + + def tearDown(self): + try: + os.remove(self.output_file) + except OSError: + pass diff --git a/src/sonic-config-engine/tests/test_minigraph_case.py b/src/sonic-config-engine/tests/test_minigraph_case.py new file mode 100644 index 000000000000..b58d8e05e1dd --- /dev/null +++ b/src/sonic-config-engine/tests/test_minigraph_case.py @@ -0,0 +1,121 @@ +from unittest import TestCase +import subprocess +import os + +class TestCfgGenCaseInsensitive(TestCase): + + def setUp(self): + self.test_dir = os.path.dirname(os.path.realpath(__file__)) + self.script_file = os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.sample_graph = os.path.join(self.test_dir, 'simple-sample-graph-case.xml') + self.port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini') + + def run_script(self, argument, check_stderr=False): + print '\n Running sonic-cfggen ' + argument + if check_stderr: + output = subprocess.check_output(self.script_file + ' ' + argument, stderr=subprocess.STDOUT, shell=True) + else: + output = subprocess.check_output(self.script_file + ' ' + argument, shell=True) + + linecount = output.strip().count('\n') + if linecount <= 0: + print ' Output: ' + output.strip() + else: + print ' Output: ({0} lines, {1} bytes)'.format(linecount + 1, len(output)) + return output + + def test_dummy_run(self): + argument = '' + output = self.run_script(argument) + self.assertEqual(output, '') + + def test_minigraph_sku(self): + argument = '-v "DEVICE_METADATA[\'localhost\'][\'hwsku\']" -m "' + self.sample_graph + '"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'Force10-S6000') + + def test_print_data(self): + argument = '-m "' + self.sample_graph + '" --print-data' + output = self.run_script(argument) + self.assertTrue(len(output.strip()) > 0) + + def test_jinja_expression(self): + argument = '-m "' + self.sample_graph + '" -v "DEVICE_METADATA[\'localhost\'][\'type\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'ToRRouter') + + def test_additional_json_data(self): + argument = '-a \'{"key1":"value1"}\' -v key1' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'value1') + + def test_read_yaml(self): + argument = '-v yml_item -y ' + os.path.join(self.test_dir, 'test.yml') + output = self.run_script(argument) + self.assertEqual(output.strip(), '[\'value1\', \'value2\']') + + def test_render_template(self): + argument = '-y ' + os.path.join(self.test_dir, 'test.yml') + ' -t ' + os.path.join(self.test_dir, 'test.j2') + output = self.run_script(argument) + self.assertEqual(output.strip(), 'value1\nvalue2') + + def test_minigraph_everflow(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v MIRROR_SESSION' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'everflow0': {'src_ip': '10.1.0.32', 'dst_ip': '10.0.100.1'}}") + + def test_minigraph_interfaces(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v \'INTERFACE.keys()\'' + output = self.run_script(argument) + self.assertEqual(output.strip(), "[('Ethernet0', '10.0.0.58/31'), ('Ethernet0', 'FC00::75/126')]") + + def test_minigraph_vlans(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v VLAN' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'Vlan1000': {'alias': 'ab1', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '1000'}}") + + def test_minigraph_vlan_members(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v VLAN_MEMBER' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{('Vlan1000', 'Ethernet8'): {'tagging_mode': 'untagged'}}") + + def test_minigraph_vlan_interfaces(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "VLAN_INTERFACE.keys()"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "[('Vlan1000', '192.168.0.1/27')]") + + def test_minigraph_portchannels(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v PORTCHANNEL' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'PortChannel01': {'admin_status': 'up', 'min_links': '1', 'members': ['Ethernet4'], 'mtu': '9100'}}") + + def test_minigraph_console_port(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v CONSOLE_PORT' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'1': {'baud_rate': '9600', 'remote_device': 'managed_device', 'flow_control': 1}}") + + def test_minigraph_deployment_id(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DEVICE_METADATA[\'localhost\'][\'deployment_id\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "1") + + def test_minigraph_neighbor_metadata(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DEVICE_NEIGHBOR_METADATA"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'switch-01t1': {'lo_addr': '10.1.0.186/32', 'mgmt_addr': '10.7.0.196/26', 'hwsku': 'Force10-S6000', 'type': 'LeafRouter', 'deployment_id': '2'}}") + + def test_metadata_everflow(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "MIRROR_SESSION"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'everflow0': {'src_ip': '10.1.0.32', 'dst_ip': '10.0.100.1'}}") + + def test_metadata_tacacs(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "TACPLUS_SERVER"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'10.0.10.7': {'priority': '1', 'tcp_port': '49'}, '10.0.10.8': {'priority': '1', 'tcp_port': '49'}}") + + def test_metadata_ntp(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "NTP_SERVER"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'10.0.10.1': {}, '10.0.10.2': {}}") + diff --git a/src/sonic-dbsyncd b/src/sonic-dbsyncd new file mode 160000 index 000000000000..1cdcffc08f6e --- /dev/null +++ b/src/sonic-dbsyncd @@ -0,0 +1 @@ +Subproject commit 1cdcffc08f6ea1c3fc53f7aeeef5b5632124496f diff --git a/src/sonic-device-data/LICENSE b/src/sonic-device-data/LICENSE new file mode 100644 index 000000000000..2ff086dedcdd --- /dev/null +++ b/src/sonic-device-data/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2017 Microsoft + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/src/sonic-device-data/MAINTAINERS b/src/sonic-device-data/MAINTAINERS new file mode 100644 index 000000000000..fde1eede3214 --- /dev/null +++ b/src/sonic-device-data/MAINTAINERS @@ -0,0 +1,7 @@ +# This file describes the maintainers for sonic-device-data +# See the SONiC project governance document for more information + +Name = "Joe LeVeque" +Email = "jolevequ@microsoft.com" +Github = jleveque +Mailinglist = sonicproject@googlegroups.com diff --git a/src/sonic-device-data/Makefile b/src/sonic-device-data/Makefile new file mode 100644 index 000000000000..b258db960727 --- /dev/null +++ b/src/sonic-device-data/Makefile @@ -0,0 +1,22 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = sonic-device-data_$(SONIC_DEVICE_DATA_VERSION_FULL)_all.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + pushd ./src + + # Remove any stale data + rm -rf ./device + + # Create a new dir and copy all ONIE-platform-string-named dirs into it + mkdir ./device + cp -r -L ../../../device/*/* ./device/ + + # Build the package + dpkg-buildpackage -rfakeroot -b -us -uc + + popd + + mv $* $(DEST)/ diff --git a/src/sonic-device-data/README.md b/src/sonic-device-data/README.md new file mode 100644 index 000000000000..e8ccad58b819 --- /dev/null +++ b/src/sonic-device-data/README.md @@ -0,0 +1,4 @@ +# sonic-device-data +Device-specific data for the SONiC project + +See the [SONiC Website](http://azure.github.io/SONiC/) for more information about the SONiC project. diff --git a/src/sonic-device-data/src/Makefile b/src/sonic-device-data/src/Makefile new file mode 100644 index 000000000000..9c0037fd50c7 --- /dev/null +++ b/src/sonic-device-data/src/Makefile @@ -0,0 +1,11 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +test: + # Execute Broadcom config file test + pushd ../tests/ + for f in $$(find ../../../device -name "*.config.bcm"); do + ./config_checker $$f + done + popd diff --git a/src/sonic-device-data/src/debian/changelog b/src/sonic-device-data/src/debian/changelog new file mode 100644 index 000000000000..9cf0041aa890 --- /dev/null +++ b/src/sonic-device-data/src/debian/changelog @@ -0,0 +1,5 @@ +sonic-device-data (1.0-1) UNRELEASED; urgency=low + + * Initial release. (Closes: #XXXXXX) + + -- Joe LeVeque Tue, 20 Feb 2017 14:00:00 -0700 diff --git a/src/sonic-device-data/src/debian/compat b/src/sonic-device-data/src/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/src/sonic-device-data/src/debian/compat @@ -0,0 +1 @@ +9 diff --git a/src/sonic-device-data/src/debian/control b/src/sonic-device-data/src/debian/control new file mode 100644 index 000000000000..a9969efc4b84 --- /dev/null +++ b/src/sonic-device-data/src/debian/control @@ -0,0 +1,11 @@ +Source: sonic-device-data +Maintainer: Joe LeVeque +Section: misc +Priority: optional +Standards-Version: 0.1 +Build-Depends: debhelper (>=9) + +Package: sonic-device-data +Architecture: all +Depends: ${misc:Depends} +Description: Device-specific data files for SONiC diff --git a/src/sonic-device-data/src/debian/copyright b/src/sonic-device-data/src/debian/copyright new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/sonic-device-data/src/debian/install b/src/sonic-device-data/src/debian/install new file mode 100644 index 000000000000..707d39adfccb --- /dev/null +++ b/src/sonic-device-data/src/debian/install @@ -0,0 +1 @@ +device/ usr/share/sonic/ diff --git a/src/sonic-device-data/src/debian/rules b/src/sonic-device-data/src/debian/rules new file mode 100755 index 000000000000..a5e2f5acfc1f --- /dev/null +++ b/src/sonic-device-data/src/debian/rules @@ -0,0 +1,6 @@ +#!/usr/bin/make -f + +build: + +%: + dh $@ diff --git a/src/sonic-device-data/tests/LICENSE b/src/sonic-device-data/tests/LICENSE new file mode 100644 index 000000000000..fd8968a9bd4e --- /dev/null +++ b/src/sonic-device-data/tests/LICENSE @@ -0,0 +1,42 @@ +Copyright: Copyright 2017 Broadcom Corporation. + +This program is the proprietary software of Broadcom Corporation +and/or its licensors, and may only be used, duplicated, modified +or distributed pursuant to the terms and conditions of a separate, +written license agreement executed between you and Broadcom +(an "Authorized License"). Except as set forth in an Authorized +License, Broadcom grants no license (express or implied), right +to use, or waiver of any kind with respect to the Software, and +Broadcom expressly reserves all rights in and to the Software +and all intellectual property rights therein. IF YOU HAVE +NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS SOFTWARE +IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE +ALL USE OF THE SOFTWARE. + + Except as expressly set forth in the Authorized License, + + 1. This program, including its structure, sequence and organization, +constitutes the valuable trade secrets of Broadcom, and you shall use +all reasonable efforts to protect the confidentiality thereof, +and to use this information only in connection with your use of +Broadcom integrated circuit products. + + 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS +PROVIDED "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, +REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, +OR OTHERWISE, WITH RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY +DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, +NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, +ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR +CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING +OUT OF USE OR PERFORMANCE OF THE SOFTWARE. + + 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL +BROADCOM OR ITS LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, +INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY DAMAGES WHATSOEVER +ARISING OUT OF OR IN ANY WAY RELATING TO YOUR USE OF OR INABILITY +TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF +THE AMOUNT ACTUALLY PAID FOR THE SOFTWARE ITSELF OR USD 1.00, +WHICHEVER IS GREATER. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING +ANY FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. diff --git a/src/sonic-device-data/tests/config_checker b/src/sonic-device-data/tests/config_checker new file mode 100755 index 000000000000..6e59d1f44ce4 --- /dev/null +++ b/src/sonic-device-data/tests/config_checker @@ -0,0 +1,87 @@ +#!/usr/bin/env python +import re +import sys +import glob + +permitted_properties = [] + +def usage(): + print "Usage: " + sys.argv[0] + " " + sys.exit(1) + +def check_property(p): + + if p in permitted_properties: + return True + return False + +def check_file(file_name): + try: + file_ok = True + failed_properties = [] + lineno = 0 + with open(file_name) as f: + for line in f.readlines(): + lineno = lineno + 1 + # Check both commented and uncommented lines + line = line.strip().lstrip('#').strip().lower() + # Check if = in the line + if line.find("=") == -1: + continue + p = line.split("=", 1)[0] + + # Remove trailing unit ".$" + p = re.sub(r"\.[0-9]+$", '', p) + # Remove trailing port name + p = re.sub(r"_[cxg]e(\d+)?$", '', p) + # Remove trailing port name example + p = re.sub(r"_$", '', p) + # Remove trailing port number + if p != "phy_84752" and p != "phy_84328": + p = re.sub(r"_(port)?\d+$", '', p) + # Remove trailing higig port + p = re.sub(r"_hg$", '', p) + # Remove trailing lane number + p = re.sub(r"_lane\d+$", '', p) + # Remove trailing "{.}$" + p = re.sub(r"{[0-9]+\.[0-9]+}$", '', p) + + if not check_property(p): + file_ok = False + print("[line %d] Error: %s is not permitted" % (lineno, p)) + if file_ok: + print "Result: " + file_name + " PASSED the config check!" + else: + print "Result: " + file_name + " FAILED the config check!" + return file_ok + except IOError: + print "Error: Cannot open file " + file_name + return False + + +def main(argv): + global permitted_properties + + if len(argv) > 0 and argv[0] == "-h": + usage() + + # Load permitted properties + with open("permitted_list") as f: + permitted_properties = [p.strip().lower() for p in f.readlines()] + + # Load target file + if len(argv) == 0: + files = glob.glob('*.config.bcm') + else: + files = argv + + all_good = True + for f in files: + good = check_file(f) + all_good = all_good and good + + if not all_good: + sys.exit(-1) + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/src/sonic-device-data/tests/permitted_list b/src/sonic-device-data/tests/permitted_list new file mode 100644 index 000000000000..ba07b29c0cc7 --- /dev/null +++ b/src/sonic-device-data/tests/permitted_list @@ -0,0 +1,142 @@ +arl_clean_timeout_usec +asf_mem_profile +bcm_linkscan_interval +bcm_num_cos +bcm_stat_flags +bcm_stat_interval +bcm_stat_jumbo +bcm_tunnel_term_compatible_mode +bcm_xlate_port_enable +bcm56340_4x10 +bcm56340_2x10 +bcm56340_config +cdma_timeout_usec +core_clock_frequency +ctr_evict_enable +dma_desc_timeout_usec +dport_map_direct +dport_map_enable +dport_map_indexed +dport_map_port +dpp_clock_ratio +ext_sram_freq +ext_tcam_freq +force_core_pll +fpem_mem_entries +higig2_hdr_mode +ipmc_do_vlan +ipv6_lpm_128b_enable +knet_filter_persist +l2_mem_entries +l2delete_chunks +l2mod_dma_intr_enable +l2xmsg_hostbuf_size +l2xmsg_mode +l3_alpm_enable +l3_intf_vlan_split_egress +l3_max_ecmp_mode +l3_mem_entries +lls_num_l2uc +load_firmware +logical_ports +lpm_ipv6_128b_reserved +lpm_scaling_enable +max_vp_lags +mdio_output_delay +mem_cache_enable +mem_check_nocache_override +mem_clear_hw_a +mem_nocache +mem_scan_enable +memcmd_intr_enable +miim_intr_enable +miim_timeout_usec +mmu_init_config +mmu_lossless +module_64ports +multicast_l2_r +multicast_l2_range +multicast_l3_range +no_leds_proc +num_ipv6_lpm_128b_entries +os +oversubscribe_mode +parity_correction +parity_enable +pbmp_oversubscribe +pbmp_xport +pci2eb_overrid +pfc_deadlock_seq_control +phy_84328 +phy_84752 +phy_an_allow_pll_change +phy_an_allow_pll_change_hg +phy_an_c37 +phy_an_c73 +phy_an_fec +phy_automedium +phy_aux_voltage_enable +phy_chain_rx_lane_map_physical +phy_chain_rx_polarity_flip_physical +phy_chain_tx_lane_map_physical +phy_chain_tx_polarity_flip_physical +phy_ext_rom_boot +phy_fiber_pref +phy_gearbox_enable +phy_null +phy_line_tx_mode +phy_pcs_rx_polarity_flip +phy_pcs_tx_polarity_flip +phy_port_primary_and_offset +phy_rx_polarity_flip +phy_system_tx_mode +phy_sgmii_autoneg +phy_tx_polarity_flip +phy_xaui_rx_polarity_flip +phy_xaui_tx_polarity_flip +physical_ports +port_init_autoneg +port_init_cl72 +port_init_speed +port_phy_addr +port_phy_clause +port_phy_id0 +port_phy_id1 +portgroup +portmap +prbs_polynomial +ptp_bs_fref +ptp_ts_pll_fref +rate_ext_mdio_divisor +robust_hash_disable_egress_vlan +robust_hash_disable_mpls +robust_hash_disable_vlan +schan_intr_enable +schan_timeout_usec +serdes_automed +serdes_automedium +serdes_driver_current +serdes_fiber_pref +serdes_firmware_mode +serdes_if_type +serdes_pre_driver_current +serdes_preemphasis +serdes_rx_los +serdes_sgmii_m +skip_L2_USER_ENTRY +sram_scan_enable +stable_size +start_vlan +stat_if_parity_enable +switch_bypass_mode +table_dma_enable +tdma_intr_enable +tdma_timeout_usec +tslam_dma_enable +tslam_intr_enable +tslam_timeout_usec +uplink_ports +xgxs_lcpll_xtal_refclk +xgxs_pdetect +xgxs_rx_lane_map +xgxs_tx_lane_map diff --git a/src/sonic-frr/Makefile b/src/sonic-frr/Makefile new file mode 100644 index 000000000000..d5db7168bf11 --- /dev/null +++ b/src/sonic-frr/Makefile @@ -0,0 +1,41 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = frr_$(FRR_VERSION)-1~sonic.debian8+1_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + + # Build the package + pushd ./frr + + # clean up the previous build + rm -rf debian + rm -f frr*.tar.gz + rm -f frr*.tar.xz + rm -f frr*.dsc + + # make a dist tarball + ./bootstrap.sh + ./configure + make dist + + # Create backports debian sources + cp -a debianpkg debian + make -f debian/rules backports + + # new directory to build the package + rm -rf frrpkg + mkdir frrpkg + cd frrpkg + tar xf ../frr_*.orig.tar.gz + cd frr* + tar xf ../../frr_*sonic.debian8*.debian.tar.xz + + # build package + dpkg-buildpackage -rfakeroot -b -us -uc + cd .. + mv $* $(DEST)/ + + popd + diff --git a/src/sonic-frr/frr b/src/sonic-frr/frr new file mode 160000 index 000000000000..aaf54fda1378 --- /dev/null +++ b/src/sonic-frr/frr @@ -0,0 +1 @@ +Subproject commit aaf54fda1378167d7ce317f5b4a16c3a61ef59eb diff --git a/src/sonic-linux-kernel b/src/sonic-linux-kernel new file mode 160000 index 000000000000..ad754bdcc094 --- /dev/null +++ b/src/sonic-linux-kernel @@ -0,0 +1 @@ +Subproject commit ad754bdcc094f6499b3fd6af067c828b0546f96c diff --git a/src/sonic-platform-common b/src/sonic-platform-common new file mode 160000 index 000000000000..d4bf78c9db4d --- /dev/null +++ b/src/sonic-platform-common @@ -0,0 +1 @@ +Subproject commit d4bf78c9db4daf21497274a778748da4d8301866 diff --git a/src/sonic-platform-daemons b/src/sonic-platform-daemons new file mode 160000 index 000000000000..bc23ab0b0b87 --- /dev/null +++ b/src/sonic-platform-daemons @@ -0,0 +1 @@ +Subproject commit bc23ab0b0b87b3ed022a7728c069e580b70bf23d diff --git a/src/sonic-py-swsssdk b/src/sonic-py-swsssdk new file mode 160000 index 000000000000..cb4fec9d078f --- /dev/null +++ b/src/sonic-py-swsssdk @@ -0,0 +1 @@ +Subproject commit cb4fec9d078f72ca378ecba5e6a112e3028c2221 diff --git a/src/sonic-quagga b/src/sonic-quagga new file mode 160000 index 000000000000..4b7825c2ee71 --- /dev/null +++ b/src/sonic-quagga @@ -0,0 +1 @@ +Subproject commit 4b7825c2ee71c9e8603d1ade3aaf76982f7dbf49 diff --git a/src/sonic-sairedis b/src/sonic-sairedis new file mode 160000 index 000000000000..1288f7705794 --- /dev/null +++ b/src/sonic-sairedis @@ -0,0 +1 @@ +Subproject commit 1288f770579461d7a5c86975b473695faedd41f9 diff --git a/src/sonic-snmpagent b/src/sonic-snmpagent new file mode 160000 index 000000000000..10f59f2d77b8 --- /dev/null +++ b/src/sonic-snmpagent @@ -0,0 +1 @@ +Subproject commit 10f59f2d77b8ab7fe44ace7403d62c778c43af73 diff --git a/src/sonic-swss b/src/sonic-swss new file mode 160000 index 000000000000..7fd158f3f966 --- /dev/null +++ b/src/sonic-swss @@ -0,0 +1 @@ +Subproject commit 7fd158f3f966df10582ec85cc01e09e0ad96335f diff --git a/src/sonic-swss-common b/src/sonic-swss-common new file mode 160000 index 000000000000..edbfeec663f3 --- /dev/null +++ b/src/sonic-swss-common @@ -0,0 +1 @@ +Subproject commit edbfeec663f32585cbf3468a88deb950fed3bb69 diff --git a/src/sonic-utilities b/src/sonic-utilities new file mode 160000 index 000000000000..17519cf5b64d --- /dev/null +++ b/src/sonic-utilities @@ -0,0 +1 @@ +Subproject commit 17519cf5b64dee857659cb80347dc121174cb76a diff --git a/src/supervisor/Makefile b/src/supervisor/Makefile new file mode 100644 index 000000000000..3f989c3d0173 --- /dev/null +++ b/src/supervisor/Makefile @@ -0,0 +1,29 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = python-supervisor_$(SUPERVISOR_VERSION)-1_all.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf ./supervisor + + # Clone supervisor repo + git clone https://github.com/Supervisor/supervisor.git + pushd ./supervisor + + # Reset HEAD to the commit of the proper tag + # NOTE: Using "git checkout " here detaches our HEAD, + # which stg doesn't like, so we use this method instead + git reset --hard $(SUPERVISOR_VERSION) + + # Apply patches + stg init + stg import -s ../patch/series + + # Build Python and Debian package + python setup.py --command-packages=stdeb.command bdist_deb + popd + + # Move the newly-built .deb packages to the destination directory + mv ./supervisor/deb_dist/$* $(DEST)/ diff --git a/src/supervisor/patch/0001-Prevent-excessive-hanging-delays-in-process-state-tr.patch b/src/supervisor/patch/0001-Prevent-excessive-hanging-delays-in-process-state-tr.patch new file mode 100644 index 000000000000..c0263e9baf10 --- /dev/null +++ b/src/supervisor/patch/0001-Prevent-excessive-hanging-delays-in-process-state-tr.patch @@ -0,0 +1,83 @@ +From bac496af4c2051b3c15038e06533f9094b1c3604 Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Tue, 16 Jan 2018 20:42:13 +0000 +Subject: [PATCH 1/2] Prevent excessive hanging/delays in process state + transitions if the system time rolls backward + +--- + supervisor/process.py | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/supervisor/process.py b/supervisor/process.py +index f9ddcd9..216372f 100644 +--- a/supervisor/process.py ++++ b/supervisor/process.py +@@ -357,6 +357,12 @@ class Subprocess: + """ Log a 'waiting for x to stop' message with throttling. """ + if self.state == ProcessStates.STOPPING: + now = time.time() ++ ++ # If the system clock has moved backward, reset ++ # self.laststopreport to current system time ++ if now < self.laststopreport: ++ self.laststopreport = now; ++ + if now > (self.laststopreport + 2): # every 2 seconds + self.config.options.logger.info( + 'waiting for %s to stop' % self.config.name) +@@ -604,12 +610,27 @@ class Subprocess: + # STOPPED -> STARTING + self.spawn() + elif state == ProcessStates.BACKOFF: ++ if self.delay > 0 and now < self.delay - self.backoff: ++ # The system clock appears to have moved backward ++ # Reset self.delay accordingly ++ self.delay = now + self.backoff ++ + if self.backoff <= self.config.startretries: + if now > self.delay: + # BACKOFF -> STARTING + self.spawn() + + if state == ProcessStates.STARTING: ++ if now < self.laststart: ++ # The system clock appears to have moved backward ++ # Reset self.laststart to current system time ++ self.laststart = now; ++ ++ if self.delay > 0 and now < self.delay - self.config.startsecs: ++ # The system clock appears to have moved backward ++ # Reset self.delay accordingly ++ self.delay = now + self.config.startsecs ++ + if now - self.laststart > self.config.startsecs: + # STARTING -> RUNNING if the proc has started + # successfully and it has stayed up for at least +@@ -633,6 +654,11 @@ class Subprocess: + logger.info('gave up: %s %s' % (self.config.name, msg)) + + elif state == ProcessStates.STOPPING: ++ if self.delay > 0 and now < self.delay - self.config.stopwaitsecs: ++ # The system clock appears to have moved backward ++ # Reset self.delay accordingly ++ self.delay = now + self.config.stopwaitsecs ++ + time_left = self.delay - now + if time_left <= 0: + # kill processes which are taking too long to stop with a final +@@ -805,6 +831,12 @@ class EventListenerPool(ProcessGroupBase): + if dispatch_capable: + if self.dispatch_throttle: + now = time.time() ++ ++ # If the system clock has moved backward, reset ++ # self.last_dispatch to current system time ++ if now < self.last_dispatch: ++ self.last_dispatch = now; ++ + if now - self.last_dispatch < self.dispatch_throttle: + return + self.dispatch() +-- +2.1.4 + diff --git a/src/supervisor/patch/0002-Add-unit-test-cases-to-ensure-state-transitions-work.patch b/src/supervisor/patch/0002-Add-unit-test-cases-to-ensure-state-transitions-work.patch new file mode 100644 index 000000000000..cb01665ba80b --- /dev/null +++ b/src/supervisor/patch/0002-Add-unit-test-cases-to-ensure-state-transitions-work.patch @@ -0,0 +1,184 @@ +From 43b6f3ee93593f666af2c6a7af897bf3b5ee762d Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Wed, 17 Jan 2018 22:27:56 +0000 +Subject: [PATCH 2/2] Add unit test cases to ensure state transitions work if + system time has rolled backward + +--- + supervisor/tests/test_process.py | 146 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 146 insertions(+) + +diff --git a/supervisor/tests/test_process.py b/supervisor/tests/test_process.py +index 7f9bab2..ea16315 100644 +--- a/supervisor/tests/test_process.py ++++ b/supervisor/tests/test_process.py +@@ -736,6 +736,40 @@ class SubprocessTests(unittest.TestCase): + instance.stop_report() + self.assertEqual(len(options.logger.data), 1) # throttled + ++ def test_stop_report_laststopreport_in_future(self): ++ future_time = time.time() + 3600 # 1 hour into the future ++ options = DummyOptions() ++ config = DummyPConfig(options, 'test', '/test') ++ instance = self._makeOne(config) ++ instance.pid = 11 ++ dispatcher = DummyDispatcher(writable=True) ++ instance.dispatchers = {'foo':dispatcher} ++ from supervisor.states import ProcessStates ++ instance.state = ProcessStates.STOPPING ++ instance.laststopreport = future_time ++ ++ # This iteration of stop_report() should reset instance.laststopreport ++ # to the current time ++ instance.stop_report() ++ ++ # No logging should have taken place ++ self.assertEqual(len(options.logger.data), 0) ++ ++ # Ensure instance.laststopreport has rolled backward ++ self.assertTrue(instance.laststopreport < future_time) ++ ++ # Sleep for 2 seconds ++ time.sleep(2) ++ ++ # This iteration of stop_report() should actaully trigger the report ++ instance.stop_report() ++ ++ self.assertEqual(len(options.logger.data), 1) ++ self.assertEqual(options.logger.data[0], 'waiting for test to stop') ++ self.assertNotEqual(instance.laststopreport, 0) ++ instance.stop_report() ++ self.assertEqual(len(options.logger.data), 1) # throttled ++ + def test_give_up(self): + options = DummyOptions() + config = DummyPConfig(options, 'test', '/test') +@@ -1402,6 +1436,92 @@ class SubprocessTests(unittest.TestCase): + event = L[0] + self.assertEqual(event.__class__, events.ProcessStateRunningEvent) + ++ def test_transition_starting_to_running_laststart_in_future(self): ++ from supervisor import events ++ L = [] ++ events.subscribe(events.ProcessStateEvent, lambda x: L.append(x)) ++ from supervisor.states import ProcessStates ++ ++ future_time = time.time() + 3600 # 1 hour into the future ++ options = DummyOptions() ++ test_startsecs = 2 ++ ++ # this should go from STARTING to RUNNING via transition() ++ pconfig = DummyPConfig(options, 'process', 'process','/bin/process', ++ startsecs=test_startsecs) ++ process = self._makeOne(pconfig) ++ process.backoff = 1 ++ process.delay = 1 ++ process.system_stop = False ++ process.laststart = future_time ++ process.pid = 1 ++ process.stdout_buffer = 'abc' ++ process.stderr_buffer = 'def' ++ process.state = ProcessStates.STARTING ++ ++ # This iteration of transition() should reset process.laststart ++ # to the current time ++ process.transition() ++ ++ # Process state should still be STARTING ++ self.assertEqual(process.state, ProcessStates.STARTING) ++ ++ # Ensure process.laststart has rolled backward ++ self.assertTrue(process.laststart < future_time) ++ ++ # Sleep for (startsecs + 1) ++ time.sleep(test_startsecs + 1) ++ ++ # This iteration of transition() should actaully trigger the state ++ # transition to RUNNING ++ process.transition() ++ ++ # this implies RUNNING ++ self.assertEqual(process.backoff, 0) ++ self.assertEqual(process.delay, 0) ++ self.assertFalse(process.system_stop) ++ self.assertEqual(process.state, ProcessStates.RUNNING) ++ self.assertEqual(options.logger.data[0], ++ 'success: process entered RUNNING state, process has ' ++ 'stayed up for > than {} seconds (startsecs)'.format(test_startsecs)) ++ self.assertEqual(len(L), 1) ++ event = L[0] ++ self.assertEqual(event.__class__, events.ProcessStateRunningEvent) ++ ++ def test_transition_backoff_to_starting_delay_in_future(self): ++ from supervisor import events ++ L = [] ++ events.subscribe(events.ProcessStateEvent, lambda x: L.append(x)) ++ from supervisor.states import ProcessStates, SupervisorStates ++ ++ future_time = time.time() + 3600 # 1 hour into the future ++ options = DummyOptions() ++ ++ pconfig = DummyPConfig(options, 'process', 'process','/bin/process') ++ process = self._makeOne(pconfig) ++ process.laststart = 1 ++ process.delay = future_time ++ process.backoff = 0 ++ process.state = ProcessStates.BACKOFF ++ ++ # This iteration of transition() should reset process.delay ++ # to the current time ++ process.transition() ++ ++ # Process state should still be BACKOFF ++ self.assertEqual(process.state, ProcessStates.BACKOFF) ++ ++ # Ensure process.delay has rolled backward ++ self.assertTrue(process.delay < future_time) ++ ++ # This iteration of transition() should actaully trigger the state ++ # transition to STARTING ++ process.transition() ++ ++ self.assertEqual(process.state, ProcessStates.STARTING) ++ self.assertEqual(len(L), 1) ++ self.assertEqual(L[0].__class__, events.ProcessStateStartingEvent) ++ + def test_transition_backoff_to_fatal(self): + from supervisor import events + L = [] +@@ -2033,6 +2153,32 @@ class EventListenerPoolTests(ProcessGroupBaseTests): + self.assertEqual(process1.listener_state, EventListenerStates.BUSY) + self.assertEqual(process1.event, event) + ++ def test_transition_event_proc_running_with_dispatch_throttle_last_dispatch_in_future(self): ++ future_time = time.time() + 3600 # 1 hour into the future ++ options = DummyOptions() ++ from supervisor.states import ProcessStates ++ pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1') ++ process1 = DummyProcess(pconfig1, state=ProcessStates.RUNNING) ++ gconfig = DummyPGroupConfig(options, pconfigs=[pconfig1]) ++ pool = self._makeOne(gconfig) ++ pool.dispatch_throttle = 5 ++ pool.last_dispatch = future_time ++ pool.processes = {'process1': process1} ++ event = DummyEvent() ++ from supervisor.states import EventListenerStates ++ process1.listener_state = EventListenerStates.READY ++ class DummyGroup: ++ config = gconfig ++ process1.group = DummyGroup ++ pool._acceptEvent(event) ++ pool.transition() ++ ++ self.assertEqual(process1.transitioned, True) ++ self.assertEqual(pool.event_buffer, [event]) # not popped ++ ++ # Ensure pool.last_dispatch has been rolled backward ++ self.assertTrue(pool.last_dispatch < future_time) ++ + def test__dispatchEvent_notready(self): + options = DummyOptions() + from supervisor.states import ProcessStates +-- +2.1.4 + diff --git a/src/supervisor/patch/series b/src/supervisor/patch/series new file mode 100644 index 000000000000..d141fddf3301 --- /dev/null +++ b/src/supervisor/patch/series @@ -0,0 +1,2 @@ +0001-Prevent-excessive-hanging-delays-in-process-state-tr.patch +0002-Add-unit-test-cases-to-ensure-state-transitions-work.patch diff --git a/src/tacacs/nss/0001-Modify-user-map-profile.patch b/src/tacacs/nss/0001-Modify-user-map-profile.patch new file mode 100644 index 000000000000..971f1f682f71 --- /dev/null +++ b/src/tacacs/nss/0001-Modify-user-map-profile.patch @@ -0,0 +1,1459 @@ +From 43096cf9813d6def1d1f8f1d8a0c122466c8c06b Mon Sep 17 00:00:00 2001 +From: Liuqu +Date: Mon, 9 Oct 2017 02:44:37 -0700 +Subject: [PATCH] Modify user map profile + +* Removed dependence from libtacplus_map and libaudit +* Removed NSS entry point for getpwuid() +* Modified user map profile, create local user account for each TACACS+ user + which not found in local. +* Added "many_to_one" mode, create one local user for many TACACS+ users which + has the same privilege. +* Modified configuration parse and file to adapt to the new user map profile. +--- + Makefile.am | 4 +- + Makefile.in | 2 +- + configure.ac | 2 +- + debian/changelog | 11 + + debian/control | 11 +- + debian/libnss-tacplus.symbols | 1 - + nss_tacplus.c | 1004 +++++++++++++++++++---------------------- + tacplus_nss.conf | 91 ++-- + 8 files changed, 518 insertions(+), 608 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 293951e..b33c455 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -19,7 +19,7 @@ nss_tacplus.h + libnss_tacplus_la_CFLAGS = $(AM_CFLAGS) + # Version 2.0 because that's the NSS module version, and they must match + libnss_tacplus_la_LDFLAGS = -module -version-info 2:0:0 -shared +-libnss_tacplus_la_LIBADD = -ltacplus_map -ltac -laudit ++libnss_tacplus_la_LIBADD = -ltac + + + EXTRA_DIST = tacplus_nss.conf README ChangeLog +@@ -52,7 +52,7 @@ install-data-hook: + rm -f $(DESTDIR)$(libdir)/libnss_tacplus.so $(DESTDIR)$(libdir)/libnss_tacplus.so.2.0.0 + $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(sysconfdir) + cd .libs && $(INSTALL_PROGRAM) libnss_tacplus.so $(DESTDIR)$(libdir)/$(NSS_TACPLUS_LIBC_VERSIONED) +- $(STRIP) --keep-symbol=_nss_tacplus_getpwnam_r --keep-symbol=_nss_tacplus_getpwuid_r $(DESTDIR)$(libdir)/$(NSS_TACPLUS_LIBC_VERSIONED) ++ $(STRIP) --keep-symbol=_nss_tacplus_getpwnam_r $(DESTDIR)$(libdir)/$(NSS_TACPLUS_LIBC_VERSIONED) + cd $(DESTDIR)$(libdir); ln -sf $(NSS_TACPLUS_LIBC_VERSIONED) $(NSS_TACPLUS_NSS_VERSIONED) + ${INSTALL} -m 644 tacplus_nss.conf $(DESTDIR)$(sysconfdir) + +diff --git a/Makefile.in b/Makefile.in +index 0d18ce7..5159b37 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -273,7 +273,7 @@ nss_tacplus.h + libnss_tacplus_la_CFLAGS = $(AM_CFLAGS) + # Version 2.0 because that's the NSS module version, and they must match + libnss_tacplus_la_LDFLAGS = -module -version-info 2:0:0 -shared +-libnss_tacplus_la_LIBADD = -ltacplus_map -ltac -laudit ++libnss_tacplus_la_LIBADD = -ltac + EXTRA_DIST = tacplus_nss.conf README ChangeLog + MAINTAINERCLEANFILES = Makefile.in config.h.in configure aclocal.m4 \ + config/config.guess config/config.sub config/depcomp \ +diff --git a/configure.ac b/configure.ac +index 42fb8f9..8c04668 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -53,7 +53,7 @@ dnl -------------------------------------------------------------------- + dnl Checks for header files. + AC_HEADER_STDC + AC_CHECK_HEADERS([nss.h fcntl.h stdlib.h string.h strings.h sys/socket.h sys/time.h syslog.h unistd.h]) +-AC_CHECK_HEADERS([tacplus/libtac.h]) ++AC_CHECK_HEADERS([libtac/libtac.h]) + + dnl -------------------------------------------------------------------- + dnl Checks for typedefs, structures, and compiler characteristics. +diff --git a/debian/changelog b/debian/changelog +index b24ac24..d4103ed 100644 +--- a/debian/changelog ++++ b/debian/changelog +@@ -1,3 +1,14 @@ ++libnss-tacplus (1.0.4-1) unstable; urgency=low ++ * Removed dependence from libtacplus_map and libaudit ++ * Removed NSS entry point for getpwuid() ++ * Modified user map profile, create local user account for each TACACS+ user ++ which not found in local. ++ * Added "many_to_one" mode, create one local user for many TACACS+ users which ++ has the same privilege. ++ * Modified configuration parse and file to adapt to the new user map profile. ++ ++ -- Chenchen Qi Tue, 10 Oct 2017 14:23:44 +0800 ++ + libnss-tacplus (1.0.3-2) unstable; urgency=low + * Fixed package remove to clean up plugin entries in nsswitch.conf + * New Disabled: added user_homedir config variable to allow per-user +diff --git a/debian/control b/debian/control +index ea65d0b..bdc888f 100644 +--- a/debian/control ++++ b/debian/control +@@ -1,17 +1,14 @@ + Source: libnss-tacplus + Priority: optional + Maintainer: Dave Olson +-Build-Depends: debhelper (>= 9), autotools-dev, libtac-dev (>= 1.4.1~), +- libtacplus-map-dev, libaudit-dev, autoconf, libpam-tacplus-dev, +- dpkg-dev (>= 1.16.1), git ++Build-Depends: debhelper (>= 9), autotools-dev, libtac-dev (>= 1.4.1~) + Section: libs + Standards-Version: 3.9.6 + Homepage: http://www.cumulusnetworks.com + + Package: libnss-tacplus + Architecture: any +-Depends: ${shlibs:Depends}, ${misc:Depends}, libtac2 (>= 1.4.1~), +- libtacplus-map1, libaudit1 ++Depends: ${shlibs:Depends}, ${misc:Depends}, libtac2 (>= 1.4.1~) + Description: NSS module for TACACS+ authentication without local passwd entry +- Performs getpwname and getpwuid lookups via NSS for users logged in via +- tacacs authentication, and mapping done with libtacplus_map ++ Performs getpwname lookups via NSS for users logged in via ++ tacacs authentication +diff --git a/debian/libnss-tacplus.symbols b/debian/libnss-tacplus.symbols +index 2bf9b88..f476e7d 100644 +--- a/debian/libnss-tacplus.symbols ++++ b/debian/libnss-tacplus.symbols +@@ -1,3 +1,2 @@ + libnss_tacplus.so.2 libnss-tacplus #MINVER# + _nss_tacplus_getpwnam_r@Base 1.0.1 +- _nss_tacplus_getpwuid_r@Base 1.0.1 +diff --git a/nss_tacplus.c b/nss_tacplus.c +index 79e62b9..ecfa0b0 100644 +--- a/nss_tacplus.c ++++ b/nss_tacplus.c +@@ -1,7 +1,9 @@ + /* +- * Copyright (C) 2014, 2015, 2016, 2017 Cumulus Networks, Inc. ++ * Copyright (C) 2014, 2015, 2016 Cumulus Networks, Inc. ++ * Copyright (C) 2017 Chenchen Qi + * All rights reserved. + * Author: Dave Olson ++ * Chenchen Qi + * + * 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 +@@ -18,15 +20,9 @@ + */ + + /* +- * This plugin implements getpwnam_r for NSS over TACACS+ +- * and implements getpwuid_r for UIDs if and only if a mapped +- * TACACS+ user is currently logged in (libtacplus_map) +- * This means that if you do, e.g.: ls -ld ~tacacs15, you will +- * sometimes get a mapped username, and other times get tacacs15, +- * depending on whether a mapped user is logged in or not. ++ * This plugin implements getpwnam_r for NSS over TACACS+. + */ + +- + #include + #include + #include +@@ -35,18 +31,18 @@ + #include + #include + #include ++#include + #include +-#include +-#include +-#include + +-#include +-#include ++#include + +-#include "nss_tacplus.h" ++#define MIN_TACACS_USER_PRIV (1) ++#define MAX_TACACS_USER_PRIV (15) + + static const char *nssname = "nss_tacplus"; /* for syslogs */ + static const char *config_file = "/etc/tacplus_nss.conf"; ++static const char *user_conf = "/etc/tacplus_user"; ++static const char *user_conf_tmp = "/tmp/tacplus_user_tmp"; + + /* + * pwbuf is used to reduce number of arguments passed around; the strings in +@@ -63,255 +59,239 @@ struct pwbuf { + typedef struct { + struct addrinfo *addr; + char *key; +-} tacplus_server_t; ++ int timeout; ++}tacplus_server_t; ++ ++typedef struct { ++ char *info; ++ int gid; ++ char *secondary_grp; ++ char *shell; ++}useradd_info_t; + + /* set from configuration file parsing */ + static tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; +-static int tac_srv_no, tac_key_no; +-static char tac_service[] = "shell"; +-static char tac_protocol[] = "ssh"; +-static char tac_rhost[INET6_ADDRSTRLEN]; +-static char vrfname[64]; +-static char *exclude_users; +-static uid_t min_uid = ~0U; /* largest possible */ +-static int debug; +-uint16_t use_tachome; +-static int conf_parsed = 0; +- +-static void get_remote_addr(void); +- +-#define MAX_INCL 8 /* max config level nesting */ +- +-/* reset all config variables when we are going to re-parse */ +-static void +-reset_config(void) +-{ +- int i, nservers; ++static int tac_srv_no; ++static useradd_info_t useradd_grp_list[MAX_TACACS_USER_PRIV + 1]; + +- /* reset the config variables that we use, freeing memory where needed */ +- nservers = tac_srv_no; +- tac_srv_no = 0; +- tac_key_no = 0; +- vrfname[0] = '\0'; +- if(exclude_users) { +- (void)free(exclude_users); +- exclude_users = NULL; +- } +- debug = 0; +- use_tachome = 0; +- tac_timeout = 0; +- min_uid = ~0U; +- +- for(i = 0; i < nservers; i++) { +- if(tac_srv[i].key) { +- free(tac_srv[i].key); +- tac_srv[i].key = NULL; +- } +- tac_srv[i].addr = NULL; +- } +-} ++static char *tac_service = "shell"; ++static char *tac_protocol = "ssh"; ++static bool debug = false; ++static bool many_to_one = false; + +-static int nss_tacplus_config(int *errnop, const char *cfile, int top) ++static int parse_tac_server(char *srv_buf) + { +- FILE *conf; +- char lbuf[256]; +- static struct stat lastconf[MAX_INCL]; +- static char *cfilelist[MAX_INCL]; +- struct stat st, *lst; +- +- if(top > MAX_INCL) { +- syslog(LOG_NOTICE, "%s: Config file include depth > %d, ignoring %s", +- nssname, MAX_INCL, cfile); +- return 1; +- } +- +- lst = &lastconf[top-1]; +- if(conf_parsed && top == 1) { +- /* +- * check to see if the config file(s) have changed since last time, +- * in case we are part of a long-lived daemon. If any changed, +- * reparse. If not, return the appropriate status (err or OK) +- * This is somewhat complicated by the include file mechanism. +- * When we have nested includes, we have to check all the config +- * files we saw previously, not just the top level config file. +- */ +- int i; +- for(i=0; i < MAX_INCL; i++) { +- struct stat *cst; +- cst = &lastconf[i]; +- if(!cst->st_ino || !cfilelist[i]) /* end of files */ +- return conf_parsed == 2 ? 0 : 1; +- if (stat(cfilelist[i], &st) || st.st_ino != cst->st_ino || +- st.st_mtime != cst->st_mtime || st.st_ctime != cst->st_ctime) +- break; /* found removed or different file, so re-parse */ +- } +- reset_config(); +- syslog(LOG_NOTICE, "%s: Configuration file(s) have changed, re-initializing", +- nssname); +- } +- +- /* don't check for failures, we'll just skip, don't want to error out */ +- cfilelist[top-1] = strdup(cfile); +- conf = fopen(cfile, "r"); +- if(conf == NULL) { +- *errnop = errno; +- if(!conf_parsed && debug) /* debug because privileges may not allow */ +- syslog(LOG_DEBUG, "%s: can't open config file %s: %m", +- nssname, cfile); +- return 1; +- } +- if (fstat(fileno(conf), lst) != 0) +- memset(lst, 0, sizeof *lst); /* avoid stale data, no warning */ +- +- while(fgets(lbuf, sizeof lbuf, conf)) { +- if(*lbuf == '#' || isspace(*lbuf)) +- continue; /* skip comments, white space lines, etc. */ +- strtok(lbuf, " \t\n\r\f"); /* terminate buffer at first whitespace */ +- if(!strncmp(lbuf, "include=", 8)) { +- /* +- * allow include files, useful for centralizing tacacs +- * server IP address and secret. When running non-privileged, +- * may not be able to read one or more config files. +- */ +- if(lbuf[8]) +- (void)nss_tacplus_config(errnop, &lbuf[8], top+1); +- } +- else if(!strncmp(lbuf, "debug=", 6)) +- debug = strtoul(lbuf+6, NULL, 0); +- else if (!strncmp (lbuf, "user_homedir=", 13)) +- use_tachome = (uint16_t)strtoul(lbuf+13, NULL, 0); +- else if (!strncmp (lbuf, "timeout=", 8)) { +- tac_timeout = (int)strtoul(lbuf+8, NULL, 0); +- if (tac_timeout < 0) /* explict neg values disable poll() use */ +- tac_timeout = 0; +- else /* poll() only used if timeout is explictly set */ +- tac_readtimeout_enable = 1; +- } +- /* +- * This next group is here to prevent a warning in the +- * final "else" case. We don't need them, but if there +- * is a common included file, we might see them. +- */ +- else if(!strncmp(lbuf, "service=", 8) || +- !strncmp(lbuf, "protocol=", 9) || +- !strncmp(lbuf, "login=", 6)) +- ; +- else if(!strncmp(lbuf, "secret=", 7)) { +- int i; +- /* no need to complain if too many on this one */ +- if(tac_key_no < TAC_PLUS_MAXSERVERS) { +- if((tac_srv[tac_key_no].key = strdup(lbuf+7))) +- tac_key_no++; +- else +- syslog(LOG_ERR, "%s: unable to copy server secret %s", +- nssname, lbuf+7); +- } +- /* handle case where 'secret=' was given after a 'server=' +- * parameter, fill in the current secret */ +- for(i = tac_srv_no-1; i >= 0; i--) { +- if (tac_srv[i].key) +- continue; +- tac_srv[i].key = strdup(lbuf+7); +- } +- } +- else if(!strncmp(lbuf, "exclude_users=", 14)) { +- /* +- * Don't lookup users in this comma-separated list for both +- * robustness and performnce. Typically root and other commonly +- * used local users. If set, we also look up the uids +- * locally, and won't do remote lookup on those uids either. +- */ +- exclude_users = strdup(lbuf+14); +- } +- else if(!strncmp(lbuf, "min_uid=", 8)) { +- /* +- * Don't lookup uids that are local, typically set to either +- * 0 or smallest always local user's uid +- */ +- unsigned long uid; +- char *valid; +- uid = strtoul(lbuf+8, &valid, 0); +- if (valid > (lbuf+8)) +- min_uid = (uid_t)uid; +- } +- else if(!strncmp(lbuf, "vrf=", 4)) +- strncpy(vrfname, lbuf + 4, sizeof(vrfname)); +- else if(!strncmp(lbuf, "server=", 7)) { +- if(tac_srv_no < TAC_PLUS_MAXSERVERS) { +- struct addrinfo hints, *servers, *server; ++ char *token; ++ char delim[] = " ,\t\n\r\f"; ++ ++ token = strsep(&srv_buf, delim); ++ while(token) { ++ if('\0' != token) { ++ if(!strncmp(token, "server=", 7)) { ++ struct addrinfo hints, *server; + int rv; +- char *port, server_buf[sizeof lbuf]; ++ char *srv, *port; + + memset(&hints, 0, sizeof hints); +- hints.ai_family = AF_UNSPEC; /* use IPv4 or IPv6, whichever */ ++ hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + +- strcpy(server_buf, lbuf + 7); +- +- port = strchr(server_buf, ':'); +- if(port != NULL) { ++ srv = token + 7; ++ port = strchr(srv, ':'); ++ if(port) { + *port = '\0'; +- port++; ++ port++; + } +- if((rv = getaddrinfo(server_buf, (port == NULL) ? +- "49" : port, &hints, &servers)) == 0) { +- for(server = servers; server != NULL && +- tac_srv_no < TAC_PLUS_MAXSERVERS; +- server = server->ai_next) { ++ ++ if((rv = getaddrinfo(srv, (port == NULL) ? "49" : port, &hints, ++ &server)) == 0) { ++ if(server) { ++ if(tac_srv[tac_srv_no].addr) ++ freeaddrinfo(tac_srv[tac_srv_no].addr); ++ if(tac_srv[tac_srv_no].key) ++ free(tac_srv[tac_srv_no].key); ++ memset(tac_srv + tac_srv_no, 0, sizeof(tacplus_server_t)); ++ + tac_srv[tac_srv_no].addr = server; +- /* use current key, if our index not yet set */ +- if(tac_key_no && !tac_srv[tac_srv_no].key) +- tac_srv[tac_srv_no].key = +- strdup(tac_srv[tac_key_no-1].key); +- tac_srv_no++; ++ } ++ else { ++ syslog(LOG_ERR, "%s: server NULL", nssname); + } + } + else { +- syslog(LOG_ERR, +- "%s: skip invalid server: %s (getaddrinfo: %s)", +- nssname, server_buf, gai_strerror(rv)); ++ syslog(LOG_ERR, "%s: invalid server: %s (getaddrinfo: %s)", ++ nssname, srv, gai_strerror(rv)); ++ return -1; ++ } ++ } ++ else if(!strncmp(token, "secret=", 7)) { ++ if(tac_srv[tac_srv_no].key) ++ free(tac_srv[tac_srv_no].key); ++ tac_srv[tac_srv_no].key = strdup(token + 7); ++ } ++ else if(!strncmp(token, "timeout=", 8)) { ++ tac_srv[tac_srv_no].timeout = (int)strtoul(token + 8, NULL, 0); ++ if(tac_srv[tac_srv_no].timeout < 0) ++ tac_srv[tac_srv_no].timeout = 0; ++ /* Limit timeout to make sure upper application not wait ++ * for a long time*/ ++ if(tac_srv[tac_srv_no].timeout > 5) ++ tac_srv[tac_srv_no].timeout = 5; ++ } ++ } ++ token = strsep(&srv_buf, delim); ++ } ++ ++ return 0; ++} ++ ++static int parse_user_priv(char *buf) ++{ ++ char *token; ++ char delim[] = ";\n\r"; ++ int priv = 0; ++ int gid = 0; ++ char *info = NULL; ++ char *group = NULL; ++ char *shell = NULL; ++ ++ token = strsep(&buf, delim); ++ while(token) { ++ if('\0' != token) { ++ if(!strncmp(token, "user_priv=", 10)) { ++ priv = (int)strtoul(token + 10, NULL, 0); ++ if(priv > MAX_TACACS_USER_PRIV || priv < MIN_TACACS_USER_PRIV) ++ { ++ priv = 0; ++ syslog(LOG_WARNING, "%s: user_priv %d out of range", ++ nssname, priv); + } + } +- else { +- syslog(LOG_WARNING, "%s: maximum number of servers (%d) " +- "exceeded, skipping", nssname, TAC_PLUS_MAXSERVERS); ++ else if(!strncmp(token, "pw_info=", 8)) { ++ if(!info) ++ info = strdup(token + 8); ++ } ++ else if(!strncmp(token, "gid=", 4)) { ++ gid = (int)strtoul(token + 4, NULL, 0); ++ } ++ else if(!strncmp(token, "group=", 6)) { ++ if(!group) ++ group = strdup(token + 6); ++ } ++ else if(!strncmp(token, "shell=", 6)) { ++ if(!shell) ++ shell = strdup(token + 6); + } + } +- else if(debug) /* ignore unrecognized lines, unless debug on */ +- syslog(LOG_WARNING, "%s: unrecognized parameter: %s", +- nssname, lbuf); ++ token = strsep(&buf, delim); + } +- fclose(conf); + ++ if(priv && gid && info && group && shell) { ++ useradd_info_t *user = &useradd_grp_list[priv]; ++ if(user->info) ++ free(user->info); ++ if(user->secondary_grp) ++ free(user->secondary_grp); ++ if(user->shell) ++ free(user->shell); ++ ++ user->gid = gid; ++ user->info = info; ++ user->secondary_grp = group; ++ user->shell = shell; ++ syslog(LOG_DEBUG, "%s: user_priv=%d info=%s gid=%d group=%s shell=%s", ++ nssname, priv, info, gid, group, shell); ++ } ++ else { ++ if(info) ++ free(info); ++ if(group) ++ free(group); ++ if(shell) ++ free(shell); ++ } + + return 0; + } + +-/* +- * Separate function so we can print first time we try to connect, +- * rather than during config. +- * Don't print at config, because often the uid lookup is one we +- * skip due to min_uid, so no reason to clutter the log. +- */ +-static void print_servers(void) ++static void init_useradd_info() + { +- static int printed = 0; +- int n; +- +- if (printed || !debug) +- return; +- printed = 1; +- +- if(tac_srv_no == 0) +- syslog(LOG_DEBUG, "%s:%s: no TACACS %s in config (or no perm)," +- " giving up", +- nssname, __FUNCTION__, tac_srv_no ? "service" : +- (*tac_service ? "server" : "service and no server")); +- +- for(n = 0; n < tac_srv_no; n++) +- syslog(LOG_DEBUG, "%s: server[%d] { addr=%s, key='%s' }", nssname, +- n, tac_srv[n].addr ? tac_ntop(tac_srv[n].addr->ai_addr) +- : "unknown", tac_srv[n].key); ++ useradd_info_t *user; ++ ++ user = &useradd_grp_list[MIN_TACACS_USER_PRIV]; ++ user->gid = 100; ++ user->info = strdup("remote_user"); ++ user->secondary_grp = strdup("users"); ++ user->shell = strdup("/bin/bash"); ++ ++ user = &useradd_grp_list[MAX_TACACS_USER_PRIV]; ++ user->gid = 1000; ++ user->info = strdup("remote_user_su"); ++ user->secondary_grp = strdup("sudo,docker"); ++ user->shell = strdup("/bin/bash"); ++} ++ ++static int parse_config(const char *file) ++{ ++ FILE *fp; ++ char buf[512] = {0}; ++ ++ init_useradd_info(); ++ fp = fopen(file, "r"); ++ if(!fp) { ++ syslog(LOG_ERR, "%s: %s fopen failed", nssname, file); ++ return NSS_STATUS_UNAVAIL; ++ } ++ ++ debug = false; ++ tac_srv_no = 0; ++ while(fgets(buf, sizeof buf, fp)) { ++ if('#' == *buf || isspace(*buf)) ++ continue; ++ ++ if(!strncmp(buf, "debug=on", 8)) { ++ debug = true; ++ } ++ else if(!strncmp(buf, "many_to_one=y", 13)) { ++ many_to_one = true; ++ } ++ else if(!strncmp(buf, "user_priv=", 10)) { ++ parse_user_priv(buf); ++ } ++ else if(!strncmp(buf, "server=", 7)) { ++ if(TAC_PLUS_MAXSERVERS <= tac_srv_no) { ++ syslog(LOG_ERR, "%s: tac server num is more than %d", ++ nssname, TAC_PLUS_MAXSERVERS); ++ } ++ else if(0 == parse_tac_server(buf)) ++ ++tac_srv_no; ++ } ++ } ++ fclose(fp); ++ ++ if(debug) { ++ int n; ++ useradd_info_t *user; ++ ++ for(n = 0; n < tac_srv_no; n++) { ++ syslog(LOG_DEBUG, "%s: server[%d] { addr=%s, key=%c*****, timeout=%d }", ++ nssname, n, tac_ntop(tac_srv[n].addr->ai_addr), ++ tac_srv[n].key[0], tac_srv[n].timeout); ++ } ++ syslog(LOG_DEBUG, "%s: many_to_one %s", nssname, 1 == many_to_one ++ ? "enable" : "disable"); ++ for(n = MIN_TACACS_USER_PRIV; n <= MAX_TACACS_USER_PRIV; n++) { ++ user = &useradd_grp_list[n]; ++ if(user) { ++ syslog(LOG_DEBUG, "%s: user_priv[%d] { gid=%d, info=%s, group=%s, shell=%s }", ++ nssname, n, user->gid, NULL == user->info ? "NULL" : user->info, ++ NULL == user->secondary_grp ? "NULL" : user->secondary_grp, ++ NULL == user->shell ? "NULL" : user->shell); ++ } ++ } ++ } ++ ++ return 0; + } + + /* +@@ -324,15 +304,13 @@ static void print_servers(void) + */ + static int + pwcopy(char *buf, size_t len, struct passwd *srcpw, struct passwd *destpw, +- const char *usename, uint16_t tachome) ++ const char *usename) + { +- int needlen, cnt, origlen = len; +- char *shell; ++ size_t needlen; ++ int cnt; + +- if(!usename) { ++ if(!usename) + usename = srcpw->pw_name; +- tachome = 0; /* early lookups; no tachome */ +- } + + needlen = usename ? strlen(usename) + 1 : 1 + + srcpw->pw_dir ? strlen(srcpw->pw_dir) + 1 : 1 + +@@ -341,8 +319,8 @@ pwcopy(char *buf, size_t len, struct passwd *srcpw, struct passwd *destpw, + srcpw->pw_passwd ? strlen(srcpw->pw_passwd) + 1 : 1; + if(needlen > len) { + if(debug) +- syslog(LOG_DEBUG, "%s provided password buffer too small (%ld<%d)", +- nssname, (long)len, needlen); ++ syslog(LOG_DEBUG, "%s provided password buffer too small (%ld<%ld)", ++ nssname, (long)len, (long)needlen); + return 1; + } + +@@ -354,21 +332,14 @@ pwcopy(char *buf, size_t len, struct passwd *srcpw, struct passwd *destpw, + cnt++; /* allow for null byte also */ + buf += cnt; + len -= cnt; +- cnt = snprintf(buf, len, "%s", srcpw->pw_passwd ? srcpw->pw_passwd : ""); ++ /* If many-to-one mapping, set pw_passwd "a" for pam_account success */ ++ cnt = snprintf(buf, len, "%s", 0 == many_to_one ? "x" : "a"); + destpw->pw_passwd = buf; + cnt++; + buf += cnt; + len -= cnt; + cnt = snprintf(buf, len, "%s", srcpw->pw_shell ? srcpw->pw_shell : ""); + destpw->pw_shell = buf; +- shell = strrchr(buf, '/'); +- shell = shell ? shell+1 : buf; +- if (tachome && *shell == 'r') { +- tachome = 0; +- if(debug > 1) +- syslog(LOG_DEBUG, "%s tacacs login %s with user_homedir not allowed; " +- "shell is %s", nssname, srcpw->pw_name, buf); +- } + cnt++; + buf += cnt; + len -= cnt; +@@ -377,148 +348,227 @@ pwcopy(char *buf, size_t len, struct passwd *srcpw, struct passwd *destpw, + cnt++; + buf += cnt; + len -= cnt; +- if (tachome && usename) { +- char *slash, dbuf[strlen(srcpw->pw_dir) + strlen(usename)]; +- snprintf(dbuf, sizeof dbuf, "%s", srcpw->pw_dir ? srcpw->pw_dir : ""); +- slash = strrchr(dbuf, '/'); +- if (slash) { +- slash++; +- snprintf(slash, sizeof dbuf - (slash-dbuf), "%s", usename); +- } +- cnt = snprintf(buf, len, "%s", dbuf); +- } +- else +- cnt = snprintf(buf, len, "%s", srcpw->pw_dir ? srcpw->pw_dir : ""); ++ cnt = snprintf(buf, len, "%s", srcpw->pw_dir ? srcpw->pw_dir : ""); + destpw->pw_dir = buf; + cnt++; + buf += cnt; + len -= cnt; +- if(len < 0) { +- if(debug) +- syslog(LOG_DEBUG, "%s provided password buffer too small (%ld<%d)", +- nssname, (long)origlen, origlen-(int)len); +- return 1; +- } + + return 0; + } + + /* +- * Find the username or the matching tacacs privilege user in /etc/passwd +- * We use fgetpwent() so we can check the local file, always. +- * This could cause problems if somebody is using local users, ldap, and tacacs, +- * but we just require that the mapped user always be a local user. Since the +- * local user password isn't supposed to be used, that should be OK. +- * +- * We shouldn't normally find the username, because tacacs lookup should be +- * configured to follow local in nsswitch.conf, but somebody may configure the +- * other way, so we look for both the given user, and our "matching" user name +- * based on the tacacs authorization level. +- * +- * If not found, then try to map to a localuser tacacsN where N <= to the +- * TACACS+ privilege level, using the APIs in libtacplus_map.so +- * algorithm in update_mapuser() +- * Returns 0 on success, else 1 ++ * If useradd finished, user name should be deleted in conf. + */ +-static int +-find_pw_userpriv(unsigned priv, struct pwbuf *pb) ++static int delete_conf_line(const char *name) + { +- FILE *pwfile; +- struct passwd upw, tpw, *ent; +- int matches, ret, retu, rett; +- unsigned origpriv = priv; +- char ubuf[pb->buflen], tbuf[pb->buflen]; +- char tacuser[9]; /* "tacacs" followed by 1-2 digits */ +- +- tacuser[0] = '\0'; +- +- pwfile = fopen("/etc/passwd", "r"); +- if(!pwfile) { +- syslog(LOG_WARNING, "%s: failed to open /etc/passwd: %m", nssname); +- return 1; ++ FILE *fp, *fp_tmp; ++ char line[128]; ++ char del_line[128]; ++ int len = strlen(name); ++ ++ if(len >= 126) { ++ syslog(LOG_ERR, "%s: user name %s out of range 128", nssname, name); ++ return -1; ++ } ++ else { ++ snprintf(del_line, 128, "%s\n", name); + } + +-recheck: +- snprintf(tacuser, sizeof tacuser, "tacacs%u", priv); +- tpw.pw_name = upw.pw_name = NULL; +- retu = 0, rett = 0; +- for(matches=0; matches < 2 && (ent = fgetpwent(pwfile)); ) { +- if(!ent->pw_name) +- continue; /* shouldn't happen */ +- if(!strcmp(ent->pw_name, pb->name)) { +- retu = pwcopy(ubuf, sizeof(ubuf), ent, &upw, NULL, use_tachome); +- matches++; +- } +- else if(!strcmp(ent->pw_name, tacuser)) { +- rett = pwcopy(tbuf, sizeof(tbuf), ent, &tpw, NULL, use_tachome); +- matches++; ++ fp = fopen(user_conf, "r"); ++ if(!fp) { ++ syslog(LOG_ERR, "%s: %s fopen failed", nssname, user_conf); ++ return NSS_STATUS_UNAVAIL; ++ } ++ fp_tmp = fopen(user_conf_tmp, "w"); ++ if(!fp_tmp) { ++ syslog(LOG_ERR, "%s: %s fopen failed", nssname, user_conf_tmp); ++ fclose(fp); ++ return NSS_STATUS_UNAVAIL; ++ } ++ ++ while(fgets(line, sizeof line, fp)) { ++ if(strcmp(line, del_line)) { ++ fprintf(fp_tmp, "%s", line); + } + } +- if(!matches && priv > 0) { +- priv--; +- rewind(pwfile); +- goto recheck; +- } +- ret = 1; +- fclose(pwfile); +- if(matches) { +- if(priv != origpriv && debug) +- syslog(LOG_DEBUG, "%s: local user not found at privilege=%u," +- " using %s", nssname, origpriv, tacuser); +- if(upw.pw_name && !retu) +- ret = pwcopy(pb->buf, pb->buflen, &upw, pb->pw, pb->name, +- use_tachome); +- else if(tpw.pw_name && !rett) +- ret = pwcopy(pb->buf, pb->buflen, &tpw, pb->pw, pb->name, +- use_tachome); +- } +- if(ret) +- *pb->errnop = ERANGE; ++ fclose(fp_tmp); ++ fclose(fp); + +- return ret; ++ if(0 != remove(user_conf) || 0 != rename(user_conf_tmp, user_conf)) { ++ syslog(LOG_ERR, "%s: %s rewrite failed", nssname, user_conf); ++ return -1; ++ } ++ ++ return 0; + } + + /* +- * This is similar to find_pw_userpriv(), but passes in a fixed +- * name for UID lookups, where we have the mapped name from the +- * map file, so trying multiple tacacsN users would be wrong. +- * Some commonality, but ugly to factor +- * Only applies to mapped users +- * returns 0 on success ++ * If not found in local, look up in tacacs user conf. If user name is not in ++ * conf, it will be written in conf and created by command 'useradd'. When ++ * useradd command use getpwnam(), it will return when username found in conf. + */ +-static int +-find_pw_user(const char *logname, const char *tacuser, struct pwbuf *pb, +- uint16_t usetachome) ++static int create_local_user(const char *name, int level) + { +- FILE *pwfile; +- struct passwd *ent; +- int ret = 1; ++ FILE *fp; ++ useradd_info_t *user; ++ char buf[512]; ++ int len = 512; ++ int lvl, cnt; ++ bool found = false; ++ ++ fp = fopen(user_conf, "ab+"); ++ if(!fp) { ++ syslog(LOG_ERR, "%s: %s fopen failed", nssname, user_conf); ++ return -1; ++ } + +- if(!tacuser) { ++ while(fgets(buf, sizeof buf, fp)) { ++ if('#' == *buf || isspace(*buf)) ++ continue; ++ // Delete line break ++ cnt = strlen(buf); ++ buf[cnt - 1] = '\0'; ++ if(!strcmp(buf, name)) { ++ found = true; ++ break; ++ } ++ } ++ ++ /* ++ * If user is found in user_conf, it means that getpwnam is called by ++ * useradd in this NSS module. ++ */ ++ if(found) { + if(debug) +- syslog(LOG_DEBUG, "%s: passed null username, failing", nssname); ++ syslog(LOG_DEBUG, "%s: %s found in %s", nssname, name, user_conf); ++ fclose(fp); + return 1; + } + +- pwfile = fopen("/etc/passwd", "r"); +- if(!pwfile) { +- syslog(LOG_WARNING, "%s: failed to open /etc/passwd: %m", +- nssname); +- return 1; ++ snprintf(buf, len, "%s\n", name); ++ if(EOF == fputs(buf, fp)) { ++ syslog(LOG_ERR, "%s: %s write local user failed", nssname, name); ++ fclose(fp); ++ return -1; ++ } ++ fclose(fp); ++ ++ lvl = level; ++ while(lvl >= MIN_TACACS_USER_PRIV) { ++ user = &useradd_grp_list[lvl]; ++ if(user->info && user->secondary_grp && user->shell) { ++ snprintf(buf, len, "useradd -G %s \"%s\" -g %d -c \"%s\" -d /home/%s -m -s %s", ++ user->secondary_grp, name, user->gid, user->info, name, user->shell); ++ fp = popen(buf, "r"); ++ if(!fp || -1 == pclose(fp)) { ++ syslog(LOG_ERR, "%s: useradd popen failed errno=%d %s", ++ nssname, errno, strerror(errno)); ++ delete_conf_line(name); ++ return -1; ++ } ++ if(debug) ++ syslog(LOG_DEBUG, "%s: create local user %s success", nssname, name); ++ delete_conf_line(name); ++ return 0; ++ } ++ lvl--; ++ } ++ ++ return -1; ++} ++ ++/* ++ * Lookup user in /etc/passwd, and fill up passwd info if found. ++ */ ++static int lookup_pw_local(char* username, struct pwbuf *pb, bool *found) ++{ ++ FILE *fp; ++ struct passwd *pw = NULL; ++ int ret = 0; ++ ++ if(!username) { ++ syslog(LOG_ERR, "%s: username invalid in check passwd", nssname); ++ return -1; + } + +- pb->pw->pw_name = NULL; /* be paranoid */ +- for(ret = 1; ret && (ent = fgetpwent(pwfile)); ) { +- if(!ent->pw_name) +- continue; /* shouldn't happen */ +- if(!strcmp(ent->pw_name, tacuser)) { +- ret = pwcopy(pb->buf, pb->buflen, ent, pb->pw, logname, usetachome); ++ fp = fopen("/etc/passwd", "r"); ++ if(!fp) { ++ syslog(LOG_ERR, "%s: /etc/passwd fopen failed", nssname); ++ return -1; ++ } ++ ++ while(0 != (pw = fgetpwent(fp))) { ++ if(!strcmp(pw->pw_name, username)) { ++ *found = true; ++ ret = pwcopy(pb->buf, pb->buflen, pw, pb->pw, username); ++ if(ret) ++ *pb->errnop = ERANGE; + break; + } + } +- fclose(pwfile); +- if(ret) +- *pb->errnop = ERANGE; ++ fclose(fp); ++ return ret; ++} ++ ++/* ++ * Lookup local user passwd info for TACACS+ user. If not found, local user will ++ * be created by user mapping strategy. ++ */ ++static int lookup_user_pw(struct pwbuf *pb, int level) ++{ ++ char *username = NULL; ++ char buf[128]; ++ int len = 128; ++ bool found = false; ++ int ret = 0; ++ ++ if(level < MIN_TACACS_USER_PRIV || level > MAX_TACACS_USER_PRIV) { ++ syslog(LOG_ERR, "%s: TACACS+ user %s privilege %d invalid", nssname, pb->name, level); ++ return -1; ++ } ++ ++ /* ++ * If many-to-one user mapping disable, create local user for each TACACS+ user ++ * The username of local user and TACACS+ user is the same. If many-to-one enable, ++ * look up the mapped local user name and passwd info. ++ */ ++ if(0 == many_to_one) { ++ username = pb->name; ++ } ++ else { ++ int lvl = level; ++ useradd_info_t *user; ++ ++ while(lvl >= MIN_TACACS_USER_PRIV) { ++ user = &useradd_grp_list[lvl]; ++ if(user->info && user->secondary_grp && user->shell) { ++ snprintf(buf, len, "%s", user->info); ++ username = buf; ++ if(debug) ++ syslog(LOG_DEBUG, "%s: %s mapping local user %s", nssname, ++ pb->name, username); ++ break; ++ } ++ lvl--; ++ } ++ } ++ ++ ret = lookup_pw_local(username, pb, &found); ++ if(debug) ++ syslog(LOG_DEBUG, "%s: %s passwd %s found in local", nssname, username, ++ found ? "is" : "isn't"); ++ if(0 != ret || found) ++ return ret; ++ ++ if(0 != create_local_user(username, level)) ++ return -1; ++ ++ ret = lookup_pw_local(username, pb, &found); ++ if(0 == ret && !found) { ++ syslog(LOG_ERR, "%s: %s not found in local after useradd", nssname, pb->name); ++ ret = -1; ++ } + + return ret; + } +@@ -532,6 +582,7 @@ static int + got_tacacs_user(struct tac_attrib *attr, struct pwbuf *pb) + { + unsigned long priv_level = 0; ++ int ret; + + while(attr != NULL) { + /* we are looking for the privilege attribute, can be in several forms, +@@ -550,14 +601,20 @@ got_tacacs_user(struct tac_attrib *attr, struct pwbuf *pb) + /* if this fails, we leave priv_level at 0, which is + * least privileged, so that's OK, but at least report it + */ +- if(ok == val && debug) +- syslog(LOG_WARNING, "%s: non-numeric privilege for %s, (%s)", +- nssname, pb->name, attr->attr); ++ if(debug) ++ syslog(LOG_DEBUG, "%s: privilege for %s, (%lu)", ++ nssname, pb->name, priv_level); + } + attr = attr->next; + } + +- return find_pw_userpriv(priv_level, pb); ++ ret = lookup_user_pw(pb, priv_level); ++ if(!ret && debug) ++ syslog(LOG_DEBUG, "%s: pw_name=%s, pw_passwd=%s, pw_shell=%s, dir=%s", ++ nssname, pb->pw->pw_name, pb->pw->pw_passwd, pb->pw->pw_shell, ++ pb->pw->pw_dir); ++ ++ return ret; + } + + /* +@@ -570,9 +627,13 @@ connect_tacacs(struct tac_attrib **attr, int srvr) + { + int fd; + ++ if(!*tac_service) /* reported at config file processing */ ++ return -1; ++ + fd = tac_connect_single(tac_srv[srvr].addr, tac_srv[srvr].key, NULL, +- vrfname[0]?vrfname:NULL); ++ tac_srv[srvr].timeout); + if(fd >= 0) { ++ *attr = NULL; /* so tac_add_attr() allocates memory */ + tac_add_attrib(attr, "service", tac_service); + if(tac_protocol[0]) + tac_add_attrib(attr, "protocol", tac_protocol); +@@ -598,34 +659,9 @@ lookup_tacacs_user(struct pwbuf *pb) + { + struct areply arep; + int ret = 1, done = 0; +- struct tac_attrib *attr = NULL; ++ struct tac_attrib *attr; + int tac_fd, srvr; + +- if (exclude_users) { +- char *user, *list; +- list = strdup(exclude_users); +- if (list) { +- static const char *delim = ", \t\n"; +- bool islocal = 0; +- user = strtok(list, delim); +- list = NULL; +- while (user) { +- if(!strcmp(user, pb->name)) { +- islocal = 1; +- break; +- } +- user = strtok(NULL, delim); +- } +- free(list); +- if (islocal) +- return 2; +- } +- } +- +- if(!*tac_service) /* reported at config file processing */ +- return ret; +- print_servers(); +- + for(srvr=0; srvr < tac_srv_no && !done; srvr++) { + arep.msg = NULL; + arep.attr = NULL; +@@ -636,14 +672,13 @@ lookup_tacacs_user(struct pwbuf *pb) + syslog(LOG_WARNING, "%s: failed to connect TACACS+ server %s," + " ret=%d: %m", nssname, tac_srv[srvr].addr ? + tac_ntop(tac_srv[srvr].addr->ai_addr) : "unknown", tac_fd); +- tac_free_attrib(&attr); + continue; + } +- ret = tac_author_send(tac_fd, pb->name, "", tac_rhost, attr); ++ ret = tac_author_send(tac_fd, pb->name, "", "", attr); + if(ret < 0) { + if(debug) +- syslog(LOG_WARNING, "%s: TACACS+ server %s authorization failed (%d) " +- " user (%s)", nssname, tac_srv[srvr].addr ? ++ syslog(LOG_WARNING, "%s: TACACS+ server %s send failed (%d) for" ++ " user %s: %m", nssname, tac_srv[srvr].addr ? + tac_ntop(tac_srv[srvr].addr->ai_addr) : "unknown", ret, + pb->name); + } +@@ -668,14 +703,11 @@ lookup_tacacs_user(struct pwbuf *pb) + if(arep.status == AUTHOR_STATUS_PASS_ADD || + arep.status == AUTHOR_STATUS_PASS_REPL) { + ret = got_tacacs_user(arep.attr, pb); +- if(debug>1) ++ if(debug) + syslog(LOG_DEBUG, "%s: TACACS+ server %s successful for user %s." + " local lookup %s", nssname, + tac_ntop(tac_srv[srvr].addr->ai_addr), pb->name, +- ret?"OK":"no match"); +- else if(debug) +- syslog(LOG_DEBUG, "%s: TACACS+ server %s successful for user %s", +- nssname, tac_ntop(tac_srv[srvr].addr->ai_addr), pb->name); ++ ret == 0?"OK":"no match"); + done = 1; /* break out of loop after arep cleanup */ + } + else { +@@ -692,30 +724,12 @@ lookup_tacacs_user(struct pwbuf *pb) + tac_free_attrib(&arep.attr); + } + +- return ret < 0? 1 : ret; +-} +- +-static int +-lookup_mapped_uid(struct pwbuf *pb, uid_t uid, uid_t auid, int session) +-{ +- char *loginname, mappedname[256]; +- uint16_t flag; +- +- mappedname[0] = '\0'; +- loginname = lookup_mapuid(uid, auid, session, +- mappedname, sizeof mappedname, &flag); +- if(loginname) +- return find_pw_user(loginname, mappedname, pb, flag & MAP_USERHOMEDIR); +- return 1; ++ return ret; + } + + /* + * This is an NSS entry point. +- * We implement getpwnam(), because we remap from the tacacs login +- * to the local tacacs0 ... tacacs15 users for all other info, and so +- * the normal order of "passwd tacplus" (possibly with ldap or anything +- * else prior to tacplus) will mean we only get used when there isn't +- * a local user to be found. ++ * We implement getpwnam(), because we remap from the tacacs. + * + * We try the lookup to the tacacs server first. If we can't make a + * connection to the server for some reason, we also try looking up +@@ -730,20 +744,25 @@ enum nss_status _nss_tacplus_getpwnam_r(const char *name, struct passwd *pw, + int result; + struct pwbuf pbuf; + +- result = nss_tacplus_config(errnop, config_file, 1); +- conf_parsed = result == 0 ? 2 : 1; ++ /* ++ * When filename completion is used with the tab key in bash, getpwnam ++ * is invoked. And the parameter "name" is '*'. In order not to connect to ++ * TACACS+ server frequently, check user name whether is valid. ++ */ ++ if(!strcmp(name, "*")) ++ return NSS_STATUS_NOTFOUND; + +- get_remote_addr(); ++ result = parse_config(config_file); + +- if(result) { /* no config file, no servers, etc. */ +- /* this is a debug because privileges may not allow access */ +- if(debug) +- syslog(LOG_DEBUG, "%s: bad config or server line for nss_tacplus", ++ if(result) { ++ syslog(LOG_ERR, "%s: bad config or server line for nss_tacplus", ++ nssname); ++ } ++ else if(0 == tac_srv_no) { ++ syslog(LOG_WARNING, "%s: no tacacs server in config for nss_tacplus", + nssname); + } + else { +- int lookup; +- + /* marshal the args for the lower level functions */ + pbuf.name = (char *)name; + pbuf.pw = pw; +@@ -751,126 +770,13 @@ enum nss_status _nss_tacplus_getpwnam_r(const char *name, struct passwd *pw, + pbuf.buflen = buflen; + pbuf.errnop = errnop; + +- lookup = lookup_tacacs_user(&pbuf); +- if(!lookup) ++ if(0 == lookup_tacacs_user(&pbuf)) { + status = NSS_STATUS_SUCCESS; +- else if(lookup == 1) { /* 2 means exclude_users match */ +- uint16_t flag; +- /* +- * If we can't contact a tacacs server (either not configured, or +- * more likely, we aren't running as root and the config for the +- * server is not readable by our uid for security reasons), see if +- * we can find the user via the mapping database, and if so, use +- * that. This will work for non-root users as long as the requested +- * name is in use (that is, logged in), which will be the most +- * common case of wanting to use the original login name by non-root +- * users. +- */ +- char *mapname = lookup_mapname(name, -1, -1, NULL, &flag); +- if(mapname != name && !find_pw_user(name, mapname, &pbuf, +- flag & MAP_USERHOMEDIR)) +- status = NSS_STATUS_SUCCESS; ++ if(debug) ++ syslog(LOG_DEBUG, "%s: name=%s, pw_name=%s, pw_passwd=%s, pw_shell=%s", ++ nssname, name, pw->pw_name, pw->pw_passwd, pw->pw_shell); + } + } +- return status; +-} + +-/* +- * This is an NSS entry point. +- * We implement getpwuid(), for anything that wants to get the original +- * login name from the uid. +- * If it matches an entry in the map, we use that data to replace +- * the data from the local passwd file (not via NSS). +- * locally from the map. +- * +- * This can be made to work 2 different ways, and we need to choose +- * one, or make it configurable. +- * +- * 1) Given a valid auid and a session id, and a mapped user logged in, +- * we'll match only that user. That is, we can only do the lookup +- * successfully for child processes of the mapped tacacs login, and +- * only while still logged in (map entry is valid). +- * +- * 2) Use auid/session wildcards, and and always match on the first valid +- * tacacs map file entry. This means if two tacacs users are logged in +- * at the same privilege level at the same time, uid lookups for ps, ls, +- * etc. will return the first (in the map file, not necessarily first +- * logged in) mapped name. +- * +- * For now, if auid and session are set, I try them, and if that lookup +- * fails, try the wildcard. +- * +- * Only works while the UID is in use for a mapped user, and only +- * for processes invoked from that session. Other callers will +- * just get the files, ldap, or nis entry for the UID +- * Only works while the UID is in use for a mapped user, and returns +- * the first match from the mapped users. +- */ +-enum nss_status _nss_tacplus_getpwuid_r(uid_t uid, struct passwd *pw, +- char *buffer, size_t buflen, int *errnop) +-{ +- struct pwbuf pb; +- enum nss_status status = NSS_STATUS_NOTFOUND; +- int session, ret; +- uid_t auid; +- +- ret = nss_tacplus_config(errnop, config_file, 1); +- conf_parsed = ret == 0 ? 2 : 1; +- +- if (min_uid != ~0U && uid < min_uid) { +- if(debug > 1) +- syslog(LOG_DEBUG, "%s: uid %u < min_uid %u, don't lookup", +- nssname, uid, min_uid); +- return status; +- } +- +- auid = audit_getloginuid(); /* audit_setloginuid not called */ +- session = map_get_sessionid(); +- +- /* marshal the args for the lower level functions */ +- pb.pw = pw; +- pb.buf = buffer; +- pb.buflen = buflen; +- pb.errnop = errnop; +- pb.name = NULL; +- +- /* +- * the else case will only be called if we don't have an auid or valid +- * sessionid, since otherwise the first call will be using wildcards, +- * since the getloginuid and get_sessionid calls will "fail". +- */ +- if(!lookup_mapped_uid(&pb, uid, auid, session)) +- status = NSS_STATUS_SUCCESS; +- else if((auid != (uid_t)-1 || session != ~0U) && +- !lookup_mapped_uid(&pb, uid, (uid_t)-1, ~0)) +- status = NSS_STATUS_SUCCESS; + return status; + } +- +-static void get_remote_addr(void) +-{ +- struct sockaddr_storage addr; +- socklen_t len = sizeof addr; +- char ipstr[INET6_ADDRSTRLEN]; +- +- /* This is so we can fill in the rhost field when we talk to the +- * TACACS+ server, when it's an ssh connection, so sites that refuse +- * authorization unless from specific IP addresses will get that +- * information. It's pretty much of a hack, but it works. +- */ +- if (getpeername(0, (struct sockaddr*)&addr, &len) == -1) +- return; +- +- *ipstr = 0; +- if (addr.ss_family == AF_INET) { +- struct sockaddr_in *s = (struct sockaddr_in *)&addr; +- inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr); +- } else { +- struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr; +- inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr); +- } +- +- snprintf(tac_rhost, sizeof tac_rhost, "%s", ipstr); +- if(debug > 1 && tac_rhost[0]) +- syslog(LOG_DEBUG, "%s: rhost=%s", nssname, tac_rhost); +-} +diff --git a/tacplus_nss.conf b/tacplus_nss.conf +index bb4eb1e..7cb756f 100644 +--- a/tacplus_nss.conf ++++ b/tacplus_nss.conf +@@ -1,53 +1,50 @@ +-#%NSS_TACPLUS-1.0 +-# Install this file as /etc/tacplus_nss.conf +-# Edit /etc/nsswitch.conf to add tacplus to the passwd lookup, similar to this +-# where tacplus precede compat (or files), and depending on local policy can +-# follow or precede ldap, nis, etc. +-# passwd: tacplus compat +-# +-# Servers are tried in the order listed, and once a server +-# replies, no other servers are attempted in a given process instantiation +-# +-# This configuration is similar to the libpam_tacplus configuration, but +-# is maintained as a configuration file, since nsswitch.conf doesn't +-# support passing parameters. Parameters must start in the first +-# column, and parsing stops at the first whitespace +- +-# if set, errors and other issues are logged with syslog +-# debug=1 ++# Configuration for libnss-tacplus + +-# min_uid is the minimum uid to lookup via tacacs. Setting this to 0 +-# means uid 0 (root) is never looked up, good for robustness and performance +-# Cumulus Linux ships with it set to 1001, so we never lookup our standard +-# local users, including the cumulus uid of 1000. Should not be greater +-# than the local tacacs{0..15} uids +-min_uid=1001 ++# debug - If you want to open debug log, set it on ++# ++# Default: off ++# debug=on + +-# This is a comma separated list of usernames that are never sent to +-# a tacacs server, they cause an early not found return. ++# src_ip - set source address of TACACS+ protocl packets + # +-# "*" is not a wild card. While it's not a legal username, it turns out +-# that during pathname completion, bash can do an NSS lookup on "*" +-# To avoid server round trip delays, or worse, unreachable server delays +-# on filename completion, we include "*" in the exclusion list. +-exclude_users=root,cumulus,quagga,sshd,ntp,* ++# Default: None (it means the ip address of out port) ++# src_ip=2.2.2.2 + +-# The include keyword allows centralizing the tacacs+ server information +-# including the IP address and shared secret +-include=/etc/tacplus_servers ++# server - set ip address, tcp port, secret string and timeout for TACACS+ servers ++# The maximum number of servers is 8. If there is no TACACS+ server, libnss-tacplus ++# will always return pwname not found. ++# ++# Default: None (no TACACS+ server) ++# server=1.1.1.1:49,secret=test,timeout=3 + +-# The server IP address can be optionally followed by a ':' and a port +-# number (server=1.1.1.1:49). It is strongly recommended that you NOT +-# add secret keys to this file, because it is world readable. +-#secret=SECRET1 +-#server=1.1.1.1 ++# user_priv - set the map between TACACS+ user privilege and local user's passwd ++# If TACACS+ user validate ok, it will get passwd info from local user which is ++# specially created for TACACS+ user in libnss-tacplus. This configuration is provided ++# to create local user. There is two user privilege map by default. ++# If the TACACS+ user's privilege value is in [1, 14], the config of user_priv 1 is ++# used to create local user. If user_priv 7 is added, the TACACS+ user which privilege ++# value is in [1, 6] will get the config of user_priv 1, and the value in [7, 14] will ++# get user_priv 7. ++# ++# If the passwd info of mapped local user is modified, like gid and shell, the new TACACS+ ++# user will create local user by the new config. But the old TACACS+ user which has logged ++# will not modify its mapped local user's passwd info. So it's better to keep this ++# configuration unchanged, not to modified at the running time. Or simply delete the old ++# mapped local user after modified. ++# ++# NOTE: If many_to_one enables, 'pw_info' is used for mapped local user name. So note the ++# naming rule for Linux user name when you set 'pw_info', and keep it different from other ++# 'pw_info'. ++# ++# Default: ++# user_priv=15;pw_info=remote_user_su;gid=1000;group=sudo,docker;shell=/bin/bash ++# user_priv=1;pw_info=remote_user;gid=999;group=docker;shell=/bin/bash + +-# The connection timeout for an NSS library should be short, since it is +-# invoked for many programs and daemons, and a failure is usually not +-# catastrophic. Not set or set to a negative value disables use of poll(). +-# This follows the include of tacplus_servers, so it can override any +-# timeout value set in that file. +-# It's important to have this set in this file, even if the same value +-# as in tacplus_servers, since tacplus_servers should not be readable +-# by users other than root. +-timeout=5 ++# many_to_one - create one local user for many TACACS+ users which has the same privilege ++# The parameter 'pw_info' in 'user_priv' is used for the mapped local user name. ++# The default config is one to one mapping. It will create local user for each TACACS+ user ++# which has different username. The user mapping strategy should be set before enables ++# TACACS+, and keep constant at the running time. ++# ++# Default: many_to_one=n ++# many_to_one=y +-- +2.7.4 + diff --git a/src/tacacs/nss/0002-Enable-modifying-local-user-permission.patch b/src/tacacs/nss/0002-Enable-modifying-local-user-permission.patch new file mode 100644 index 000000000000..2c476354705a --- /dev/null +++ b/src/tacacs/nss/0002-Enable-modifying-local-user-permission.patch @@ -0,0 +1,71 @@ +From 7045acb8f530331d3fbabef20bcf2787d3430c55 Mon Sep 17 00:00:00 2001 +From: Taoyu Li +Date: Thu, 21 Jun 2018 19:21:01 +0000 +Subject: [PATCH] Do authorization and modify user permission even if local + user exists + +--- + nss_tacplus.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/nss_tacplus.c b/nss_tacplus.c +index 63f01d4..a13c278 100644 +--- a/nss_tacplus.c ++++ b/nss_tacplus.c +@@ -408,7 +408,7 @@ static int delete_conf_line(const char *name) + * conf, it will be written in conf and created by command 'useradd'. When + * useradd command use getpwnam(), it will return when username found in conf. + */ +-static int create_local_user(const char *name, int level) ++static int create_or_modify_local_user(const char *name, int level, bool existing_user) + { + FILE *fp; + useradd_info_t *user; +@@ -416,6 +416,7 @@ static int create_local_user(const char *name, int level) + int len = 512; + int lvl, cnt; + bool found = false; ++ const char* command = existing_user ? "/usr/sbin/usermod": "/usr/sbin/useradd"; + + fp = fopen(user_conf, "ab+"); + if(!fp) { +@@ -458,17 +459,18 @@ static int create_local_user(const char *name, int level) + while(lvl >= MIN_TACACS_USER_PRIV) { + user = &useradd_grp_list[lvl]; + if(user->info && user->secondary_grp && user->shell) { +- snprintf(buf, len, "useradd -G %s \"%s\" -g %d -c \"%s\" -d /home/%s -m -s %s", +- user->secondary_grp, name, user->gid, user->info, name, user->shell); ++ snprintf(buf, len, "%s -G %s \"%s\" -g %d -c \"%s\" -d /home/%s -m -s %s", ++ command, user->secondary_grp, name, user->gid, user->info, name, user->shell); ++ if(debug) syslog(LOG_DEBUG, "%s", buf); + fp = popen(buf, "r"); + if(!fp || -1 == pclose(fp)) { +- syslog(LOG_ERR, "%s: useradd popen failed errno=%d %s", +- nssname, errno, strerror(errno)); ++ syslog(LOG_ERR, "%s: %s popen failed errno=%d %s", ++ nssname, command, errno, strerror(errno)); + delete_conf_line(name); + return -1; + } + if(debug) +- syslog(LOG_DEBUG, "%s: create local user %s success", nssname, name); ++ syslog(LOG_DEBUG, "%s: %s %s success", nssname, command, name); + delete_conf_line(name); + return 0; + } +@@ -558,10 +560,10 @@ static int lookup_user_pw(struct pwbuf *pb, int level) + if(debug) + syslog(LOG_DEBUG, "%s: %s passwd %s found in local", nssname, username, + found ? "is" : "isn't"); +- if(0 != ret || found) ++ if(0 != ret) + return ret; + +- if(0 != create_local_user(username, level)) ++ if(0 != create_or_modify_local_user(username, level, found)) + return -1; + + ret = lookup_pw_local(username, pb, &found); +-- +2.9.3 + diff --git a/src/tacacs/nss/0003-management-vrf-support.patch b/src/tacacs/nss/0003-management-vrf-support.patch new file mode 100644 index 000000000000..35e30f0781b3 --- /dev/null +++ b/src/tacacs/nss/0003-management-vrf-support.patch @@ -0,0 +1,43 @@ +From b20aad31e186e27cc83432b405555420f94c6049 Mon Sep 17 00:00:00 2001 +From: Kannan KVS +Date: Mon, 8 Oct 2018 03:10:55 -0700 +Subject: [PATCH] MANAGEMENT_VRF_TACACS_NSS_CHANGES + +--- + nss_tacplus.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/nss_tacplus.c b/nss_tacplus.c +index 6e4fddd..1e222dd 100644 +--- a/nss_tacplus.c ++++ b/nss_tacplus.c +@@ -76,6 +76,7 @@ static useradd_info_t useradd_grp_list[MAX_TACACS_USER_PRIV + 1]; + + static char *tac_service = "shell"; + static char *tac_protocol = "ssh"; ++static char vrfname[64]; + static bool debug = false; + static bool many_to_one = false; + +@@ -124,6 +125,9 @@ static int parse_tac_server(char *srv_buf) + return -1; + } + } ++ else if(!strncmp(token, "vrf=", 4)){ ++ strncpy(vrfname, token + 4, sizeof(vrfname)); ++ } + else if(!strncmp(token, "secret=", 7)) { + if(tac_srv[tac_srv_no].key) + free(tac_srv[tac_srv_no].key); +@@ -633,7 +637,7 @@ connect_tacacs(struct tac_attrib **attr, int srvr) + return -1; + + fd = tac_connect_single(tac_srv[srvr].addr, tac_srv[srvr].key, NULL, +- tac_srv[srvr].timeout); ++ tac_srv[srvr].timeout, vrfname[0] ? vrfname : NULL); + if(fd >= 0) { + *attr = NULL; /* so tac_add_attr() allocates memory */ + tac_add_attrib(attr, "service", tac_service); +-- +2.7.4 + diff --git a/src/tacacs/nss/Makefile b/src/tacacs/nss/Makefile new file mode 100644 index 000000000000..d9c858bdcb38 --- /dev/null +++ b/src/tacacs/nss/Makefile @@ -0,0 +1,24 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = libnss-tacplus_$(NSS_TACPLUS_VERSION)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Obtain libnss-tacplus + rm -rf ./libnss-tacplus + git clone https://github.com/daveolson53/libnss-tacplus.git + pushd ./libnss-tacplus + git checkout -f 19008ab + + # Apply patch + git am ../0001-Modify-user-map-profile.patch + git am ../0002-Enable-modifying-local-user-permission.patch + git am ../0003-management-vrf-support.patch + + dpkg-buildpackage -rfakeroot -b -us -uc + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/tacacs/pam/0001-Don-t-init-declarations-in-a-for-loop.patch b/src/tacacs/pam/0001-Don-t-init-declarations-in-a-for-loop.patch new file mode 100644 index 000000000000..f9a9c29eb93f --- /dev/null +++ b/src/tacacs/pam/0001-Don-t-init-declarations-in-a-for-loop.patch @@ -0,0 +1,45 @@ +From f293353127c504490f8d892afe39766ec94137bf Mon Sep 17 00:00:00 2001 +From: Liuqu +Date: Sun, 8 Oct 2017 07:32:11 -0700 +Subject: [PATCH 1/2] Don't init declarations in a for loop + +* It comes from the commit "3299028... Don't init declarations in + a for loop", and modified source format to resolve conflict in + v1.4.1 +--- + libtac/lib/author_r.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/libtac/lib/author_r.c b/libtac/lib/author_r.c +index a028144..f3b544e 100644 +--- a/libtac/lib/author_r.c ++++ b/libtac/lib/author_r.c +@@ -47,6 +47,7 @@ int tac_author_read(int fd, struct areply *re) { + char *msg = NULL; + int timeleft; + re->msg = NULL; ++ unsigned int r = 0; + + bzero(re, sizeof(struct areply)); + if (tac_readtimeout_enable && +@@ -132,7 +133,7 @@ int tac_author_read(int fd, struct areply *re) { + pktp = (u_char *) tb + TAC_AUTHOR_REPLY_FIXED_FIELDS_SIZE; + + /* cycle through the arguments supplied in the packet */ +- for (unsigned int r = 0; r < tb->arg_cnt && r < TAC_PLUS_MAX_ARGCOUNT; r++) { ++ for (r = 0; r < tb->arg_cnt && r < TAC_PLUS_MAX_ARGCOUNT; r++) { + if (len_from_body > packet_read || ((void *)pktp - (void *) tb) > packet_read) { + TACSYSLOG((LOG_ERR,\ + "%s: arguments supplied in packet seem to exceed its size",\ +@@ -205,7 +206,7 @@ int tac_author_read(int fd, struct areply *re) { + TACSYSLOG((LOG_DEBUG, "Args cnt %d", tb->arg_cnt)); + /* argp points to current argument string + pktp points to current argument length */ +- for (unsigned int r = 0; r < tb->arg_cnt && r < TAC_PLUS_MAX_ARGCOUNT; ++ for (r = 0; r < tb->arg_cnt && r < TAC_PLUS_MAX_ARGCOUNT; + r++) { + unsigned char buff[256]; + unsigned char *sep; +-- +2.7.4 + diff --git a/src/tacacs/pam/0002-Fix-libtac2-bin-install-directory-error.patch b/src/tacacs/pam/0002-Fix-libtac2-bin-install-directory-error.patch new file mode 100644 index 000000000000..28518b3d2449 --- /dev/null +++ b/src/tacacs/pam/0002-Fix-libtac2-bin-install-directory-error.patch @@ -0,0 +1,19 @@ +From 85bae6b84d93c4b243d29ee08ff7030376bf80cb Mon Sep 17 00:00:00 2001 +From: Liuqu +Date: Sun, 8 Oct 2017 19:39:23 -0700 +Subject: [PATCH 2/2] Fix libtac2-bin install directory error + +--- + debian/libtac2-bin.install | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/debian/libtac2-bin.install b/debian/libtac2-bin.install +index 236670a..1df36c6 100644 +--- a/debian/libtac2-bin.install ++++ b/debian/libtac2-bin.install +@@ -1 +1 @@ +-usr/sbin ++usr/bin/* +-- +2.7.4 + diff --git a/src/tacacs/pam/0003-Obfuscate-key-before-printing-to-syslog.patch b/src/tacacs/pam/0003-Obfuscate-key-before-printing-to-syslog.patch new file mode 100644 index 000000000000..1d1f5d3efe89 --- /dev/null +++ b/src/tacacs/pam/0003-Obfuscate-key-before-printing-to-syslog.patch @@ -0,0 +1,25 @@ +From 254e6cb86b667f6324bcbfd89fe982e865d05189 Mon Sep 17 00:00:00 2001 +From: Taoyu Li +Date: Sat, 3 Mar 2018 02:22:49 +0000 +Subject: [PATCH] obfuscate key before printing to syslog + +--- + support.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/support.c b/support.c +index 44efee3..f9ab8aa 100644 +--- a/support.c ++++ b/support.c +@@ -282,7 +282,7 @@ int _pam_parse (int argc, const char **argv) { + _pam_log(LOG_DEBUG, "%d servers defined", tac_srv_no); + + for(n = 0; n < tac_srv_no; n++) { +- _pam_log(LOG_DEBUG, "server[%d] { addr=%s, key='%s' }", n, tac_ntop(tac_srv[n].addr->ai_addr), tac_srv[n].key); ++ _pam_log(LOG_DEBUG, "server[%d] { addr=%s, key='%c*****' }", n, tac_ntop(tac_srv[n].addr->ai_addr), tac_srv[n].key[0]); + } + + _pam_log(LOG_DEBUG, "tac_service='%s'", tac_service); +-- +2.9.3 + diff --git a/src/tacacs/pam/0004-management-vrf-support.patch b/src/tacacs/pam/0004-management-vrf-support.patch new file mode 100644 index 000000000000..4ff6ecc28dc2 --- /dev/null +++ b/src/tacacs/pam/0004-management-vrf-support.patch @@ -0,0 +1,240 @@ +From 6005f4a884f250787bdc070235879b14186ade2c Mon Sep 17 00:00:00 2001 +From: Kannan KVS +Date: Mon, 8 Oct 2018 02:58:42 -0700 +Subject: [PATCH] MANAGEMENT_VRF_TACACS_PAM_CHANGES + +--- + libtac/include/libtac.h | 4 ++-- + libtac/lib/connect.c | 21 +++++++++++++++++---- + pam_tacplus.c | 12 +++++++----- + support.c | 3 +++ + tacc.c | 15 ++++++++++----- + 5 files changed, 39 insertions(+), 16 deletions(-) + +diff --git a/libtac/include/libtac.h b/libtac/include/libtac.h +index 6dc42ab..0c9d3d2 100644 +--- a/libtac/include/libtac.h ++++ b/libtac/include/libtac.h +@@ -135,8 +135,8 @@ extern int tac_readtimeout_enable; + /* connect.c */ + extern int tac_timeout; + +-int tac_connect(struct addrinfo **, char **, int); +-int tac_connect_single(const struct addrinfo *, const char *, struct addrinfo *, int); ++int tac_connect(struct addrinfo **, char **, int, char *); ++int tac_connect_single(const struct addrinfo *, const char *, struct addrinfo *, int, char *); + char *tac_ntop(const struct sockaddr *); + + int tac_authen_send(int, const char *, const char *, const char *, +diff --git a/libtac/lib/connect.c b/libtac/lib/connect.c +index 47f598a..5035135 100644 +--- a/libtac/lib/connect.c ++++ b/libtac/lib/connect.c +@@ -42,7 +42,7 @@ int tac_timeout = 5; + * >= 0 : valid fd + * < 0 : error status code, see LIBTAC_STATUS_... + */ +-int tac_connect(struct addrinfo **server, char **key, int servers) { ++int tac_connect(struct addrinfo **server, char **key, int servers, char *iface) { + int tries; + int fd=-1; + +@@ -50,7 +50,7 @@ int tac_connect(struct addrinfo **server, char **key, int servers) { + TACSYSLOG((LOG_ERR, "%s: no TACACS+ servers defined", __FUNCTION__)) + } else { + for ( tries = 0; tries < servers; tries++ ) { +- if((fd=tac_connect_single(server[tries], key[tries], NULL, tac_timeout)) >= 0 ) { ++ if((fd=tac_connect_single(server[tries], key[tries], NULL, tac_timeout, iface)) >= 0 ) { + /* tac_secret was set in tac_connect_single on success */ + break; + } +@@ -66,8 +66,9 @@ int tac_connect(struct addrinfo **server, char **key, int servers) { + /* return value: + * >= 0 : valid fd + * < 0 : error status code, see LIBTAC_STATUS_... ++ * If iface is non-null, try to BIND to that interface, to support specific routing, including VRF. + */ +-int tac_connect_single(const struct addrinfo *server, const char *key, struct addrinfo *srcaddr, int timeout) { ++int tac_connect_single(const struct addrinfo *server, const char *key, struct addrinfo *srcaddr, int timeout, char *iface) { + int retval = LIBTAC_STATUS_CONN_ERR; /* default retval */ + int fd = -1; + int flags, rc; +@@ -91,6 +92,19 @@ int tac_connect_single(const struct addrinfo *server, const char *key, struct ad + return LIBTAC_STATUS_CONN_ERR; + } + ++ if (iface) { ++ /* do not fail if the bind fails, connection may still succeed */ ++ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, iface, ++ strlen(iface)+1) < 0) { ++ TACSYSLOG((LOG_WARNING, ":%s: Binding socket to device %s failed.", ++ __FUNCTION__, iface)) ++ } else { ++ TACDEBUG((LOG_DEBUG, "%s: Binding socket to device %s succeeded.", ++ __FUNCTION__, iface)) ++ } ++ ++ } ++ + /* get flags for restoration later */ + flags = fcntl(fd, F_GETFL, 0); + +@@ -166,7 +180,6 @@ int tac_connect_single(const struct addrinfo *server, const char *key, struct ad + } + + /* connected ok */ +- TACDEBUG((LOG_DEBUG, "%s: connected to %s", __FUNCTION__, ip)) + retval = fd; + + /* set current tac_secret */ +diff --git a/pam_tacplus.c b/pam_tacplus.c +index 2b7d2cd..38e2a70 100644 +--- a/pam_tacplus.c ++++ b/pam_tacplus.c +@@ -53,6 +53,8 @@ static tacplus_server_t active_server; + /* accounting task identifier */ + static short int task_id = 0; + ++extern char *__vrfname; ++ + + /* Helper functions */ + int _pam_send_account(int tac_fd, int type, const char *user, char *tty, +@@ -175,7 +177,7 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, + + status = PAM_SESSION_ERR; + for(srv_i = 0; srv_i < tac_srv_no; srv_i++) { +- tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL, tac_timeout); ++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL, tac_timeout, __vrfname); + if (tac_fd < 0) { + _pam_log(LOG_WARNING, "%s: error sending %s (fd)", + __FUNCTION__, typemsg); +@@ -274,9 +276,9 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: trying srv %d", __FUNCTION__, srv_i ); + +- tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL, tac_timeout); ++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL, tac_timeout, __vrfname); + if (tac_fd < 0) { +- _pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i); ++ _pam_log(LOG_ERR, "%s: connection to srv %d failed", __FUNCTION__, srv_i); + continue; + } + if (tac_authen_send(tac_fd, user, pass, tty, r_addr, TAC_PLUS_AUTHEN_LOGIN) < 0) { +@@ -577,7 +579,7 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, + if(tac_protocol[0] != '\0') + tac_add_attrib(&attr, "protocol", tac_protocol); + +- tac_fd = tac_connect_single(active_server.addr, active_server.key, NULL, tac_timeout); ++ tac_fd = tac_connect_single(active_server.addr, active_server.key, NULL, tac_timeout, __vrfname); + if(tac_fd < 0) { + _pam_log (LOG_ERR, "TACACS+ server unavailable"); + if(arep.msg != NULL) +@@ -760,7 +762,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: trying srv %d", __FUNCTION__, srv_i ); + +- tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL, tac_timeout); ++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL, tac_timeout, __vrfname); + if (tac_fd < 0) { + _pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i); + continue; +diff --git a/support.c b/support.c +index 44efee3..be0142d 100644 +--- a/support.c ++++ b/support.c +@@ -36,6 +36,7 @@ int tac_srv_no = 0; + char tac_service[64]; + char tac_protocol[64]; + char tac_prompt[64]; ++char *__vrfname=NULL; + + void _pam_log(int err, const char *format,...) { + char msg[256]; +@@ -271,6 +272,8 @@ int _pam_parse (int argc, const char **argv) { + } else { + tac_readtimeout_enable = 1; + } ++ } else if(!strncmp(*argv, "vrf=", 4)) { ++ __vrfname = strdup(*argv + 4); + } else { + _pam_log (LOG_WARNING, "unrecognized option: %s", *argv); + } +diff --git a/tacc.c b/tacc.c +index d7c6e1a..fcc7d8c 100644 +--- a/tacc.c ++++ b/tacc.c +@@ -76,6 +76,7 @@ int tac_encryption = 1; + typedef unsigned char flag; + flag quiet = 0; + char *user = NULL; /* global, because of signal handler */ ++char *iface = NULL; /* -I interface or VRF to use for connection */ + + /* command line options */ + static struct option long_options[] = { +@@ -97,6 +98,7 @@ static struct option long_options[] = { + { "service", required_argument, NULL, 'S' }, + { "protocol", required_argument, NULL, 'P' }, + { "remote", required_argument, NULL, 'r' }, ++ { "interface", required_argument, NULL, 'I' }, + { "login", required_argument, NULL, 'L' }, + + /* modifiers */ +@@ -107,7 +109,7 @@ static struct option long_options[] = { + { 0, 0, 0, 0 } }; + + /* command line letters */ +-char *opt_string = "TRAVhu:p:s:k:c:qr:wnS:P:L:"; ++char *opt_string = "TRAVIhu:p:s:k:c:qr:wnS:P:L:"; + + int main(int argc, char **argv) { + char *pass = NULL; +@@ -168,6 +170,9 @@ int main(int argc, char **argv) { + showversion(argv[0]); + case 'h': + showusage(argv[0]); ++ case 'I': ++ iface = optarg; ++ break; + case 'u': + user = optarg; + break; +@@ -283,7 +288,7 @@ int main(int argc, char **argv) { + tac_add_attrib(&attr, "service", service); + tac_add_attrib(&attr, "protocol", protocol); + +- tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60); ++ tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60, iface); + if (tac_fd < 0) { + if (!quiet) + printf("Error connecting to TACACS+ server: %m\n"); +@@ -321,7 +326,7 @@ int main(int argc, char **argv) { + tac_add_attrib(&attr, "service", service); + tac_add_attrib(&attr, "protocol", protocol); + +- tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60); ++ tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60, iface); + if (tac_fd < 0) { + if (!quiet) + printf("Error connecting to TACACS+ server: %m\n"); +@@ -404,7 +409,7 @@ int main(int argc, char **argv) { + sprintf(buf, "%hu", task_id); + tac_add_attrib(&attr, "task_id", buf); + +- tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60); ++ tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60, iface); + if (tac_fd < 0) { + if (!quiet) + printf("Error connecting to TACACS+ server: %m\n"); +@@ -445,7 +450,7 @@ void authenticate(const struct addrinfo *tac_server, const char *tac_secret, + int ret; + struct areply arep; + +- tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60); ++ tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60, iface); + if (tac_fd < 0) { + if (!quiet) + printf("Error connecting to TACACS+ server: %m\n"); +-- +2.7.4 + diff --git a/src/tacacs/pam/Makefile b/src/tacacs/pam/Makefile new file mode 100644 index 000000000000..a54f577bc847 --- /dev/null +++ b/src/tacacs/pam/Makefile @@ -0,0 +1,27 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = libpam-tacplus_$(PAM_TACPLUS_VERSION)_amd64.deb +DERIVED_TARGETS = libtac2_$(PAM_TACPLUS_VERSION)_amd64.deb \ + libtac-dev_$(PAM_TACPLUS_VERSION)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Obtain pam_tacplus + rm -rf ./pam_tacplus + git clone https://github.com/jeroennijhof/pam_tacplus.git + pushd ./pam_tacplus + git checkout -f v1.4.1 + + # Apply patch + git apply ../0001-Don-t-init-declarations-in-a-for-loop.patch + git apply ../0002-Fix-libtac2-bin-install-directory-error.patch + git apply ../0003-Obfuscate-key-before-printing-to-syslog.patch + git apply ../0004-management-vrf-support.patch + + dpkg-buildpackage -rfakeroot -b -us -uc + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/telemetry/Makefile b/src/telemetry/Makefile new file mode 100644 index 000000000000..91a822d4f93c --- /dev/null +++ b/src/telemetry/Makefile @@ -0,0 +1,20 @@ +export GOPATH=/tmp/go + +INSTALL := /usr/bin/install + +all: sonic-telemetry + +sonic-telemetry: + /usr/local/go/bin/go get -v github.com/Azure/sonic-telemetry/telemetry + /usr/local/go/bin/go get -v github.com/Azure/sonic-telemetry/dialout/dialout_client_cli + +install: + $(INSTALL) -D ${GOPATH}/bin/telemetry $(DESTDIR)/usr/sbin/telemetry + $(INSTALL) -D ${GOPATH}/bin/dialout_client_cli $(DESTDIR)/usr/sbin/dialout_client_cli + +deinstall: + rm $(DESTDIR)/usr/sbin/telemetry + rm $(DESTDIR)/usr/sbin/dialout_client_cli + +clean: + rm -fr ${GOPATH} diff --git a/src/telemetry/debian/changelog b/src/telemetry/debian/changelog new file mode 100644 index 000000000000..77dab629040e --- /dev/null +++ b/src/telemetry/debian/changelog @@ -0,0 +1,5 @@ +sonic-telemetry (0.1) UNRELEASED; urgency=medium + + * Initial release. + + -- Jipan Yang Sat, 24 Mar 2018 12:48:22 -0700 diff --git a/src/telemetry/debian/compat b/src/telemetry/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/src/telemetry/debian/compat @@ -0,0 +1 @@ +9 diff --git a/src/telemetry/debian/control b/src/telemetry/debian/control new file mode 100644 index 000000000000..f1b6a7c07282 --- /dev/null +++ b/src/telemetry/debian/control @@ -0,0 +1,17 @@ +Source: sonic-telemetry +Section: devel +Priority: optional +Maintainer: Jipan Yang +Build-Depends: debhelper (>= 8.0.0), + dh-systemd +Standards-Version: 3.9.3 +Homepage: https://github.com/Azure/sonic-telemetry +XS-Go-Import-Path: github.com/Azure/sonic-telemetry + +Package: sonic-telemetry +Architecture: any +Built-Using: ${misc:Built-Using} +Depends: ${misc:Depends}, + ${shlibs:Depends} +Description: SONiC telemetry + sonic-telemetry \ No newline at end of file diff --git a/src/telemetry/debian/rules b/src/telemetry/debian/rules new file mode 100644 index 000000000000..3995a26d7fcd --- /dev/null +++ b/src/telemetry/debian/rules @@ -0,0 +1,3 @@ +#!/usr/bin/make -f +%: + dh $@ --with systemd diff --git a/src/telemetry/debian/telemetry.init.d b/src/telemetry/debian/telemetry.init.d new file mode 100644 index 000000000000..2fea32e17c49 --- /dev/null +++ b/src/telemetry/debian/telemetry.init.d @@ -0,0 +1,14 @@ +#!/bin/bash +# +### BEGIN INIT INFO +# Provides: sonic-telemetry +# Required-Start: $local_fs $network $remote_fs $syslog +# Required-Stop: $local_fs $network $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: start and stop the telemetry +# Description: sonic-telemetry is an implementation of sonic telemetry daemon in Go +### END INIT INFO +# + +exit 0 diff --git a/src/thrift/Makefile b/src/thrift/Makefile new file mode 100644 index 000000000000..077b7fb308bd --- /dev/null +++ b/src/thrift/Makefile @@ -0,0 +1,31 @@ +SHELL = /bin/bash +.ONESHELL: +.SHELLFLAGS += -e + +THRIFT_VERSION = 0.9.3 +THRIFT_VERSION_FULL = $(THRIFT_VERSION)-2 + +MAIN_TARGET = libthrift-$(THRIFT_VERSION)_$(THRIFT_VERSION_FULL)_amd64.deb +DERIVED_TARGETS = libthrift-dev_$(THRIFT_VERSION_FULL)_amd64.deb \ + python-thrift_$(THRIFT_VERSION_FULL)_amd64.deb \ + thrift-compiler_$(THRIFT_VERSION_FULL)_amd64.deb + +#THRIFT_LINK_PRE = http://http.debian.net/debian/pool/main/t/thrift +THRIFT_LINK_PRE = https://sonicstorage.blob.core.windows.net/packages/debian + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf thrift-$(THRIFT_VERSION) + + wget -NO "thrift_$(THRIFT_VERSION).orig.tar.gz" "$(THRIFT_LINK_PRE)/thrift_$(THRIFT_VERSION).orig.tar.gz?sv=2015-04-05&sr=b&sig=wM3B01UnZQYYr7ZGXmCvRn6MMeS5hn5Oa5G5%2Btub53g%3D&se=2028-11-11T02%3A20%3A36Z&sp=r" + wget -NO "thrift_$(THRIFT_VERSION_FULL).debian.tar.xz" "$(THRIFT_LINK_PRE)/thrift_$(THRIFT_VERSION_FULL).debian.tar.xz?sv=2015-04-05&sr=b&sig=76bx%2BN8uxYbuI%2BEq8uK%2B8cTKTzVmjtjsQ9weejWNINk%3D&se=2028-11-11T02%3A19%3A30Z&sp=r" + wget -NO "thrift_$(THRIFT_VERSION_FULL).dsc" "$(THRIFT_LINK_PRE)/thrift_$(THRIFT_VERSION_FULL).dsc?sv=2015-04-05&sr=b&sig=Vpk1eJ97I5aWrtjAYS8w8AKyLXcJKFGIVFOOBGR3a5I%3D&se=2028-11-11T02%3A20%3A20Z&sp=r" + + dpkg-source -x thrift_$(THRIFT_VERSION_FULL).dsc + pushd thrift-$(THRIFT_VERSION) + patch -p1 < ../patch/THRIFT-3577-assertion-failed.patch + DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -d -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/thrift/patch/THRIFT-3577-assertion-failed.patch b/src/thrift/patch/THRIFT-3577-assertion-failed.patch new file mode 100644 index 000000000000..ad984ebbdb73 --- /dev/null +++ b/src/thrift/patch/THRIFT-3577-assertion-failed.patch @@ -0,0 +1,27 @@ +From 9f96e358fb5bdac8a6570dc3c79e9416e4f407ce Mon Sep 17 00:00:00 2001 +From: Nobuaki Sukegawa +Date: Mon, 22 Feb 2016 01:33:27 +0900 +Subject: [PATCH] THRIFT-3577 assertion failed at line 512 of + testcontainertest.c + +--- + lib/c_glib/test/testcontainertest.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/c_glib/test/testcontainertest.c b/lib/c_glib/test/testcontainertest.c +index 852254b..1cbc55c 100644 +--- a/lib/c_glib/test/testcontainertest.c ++++ b/lib/c_glib/test/testcontainertest.c +@@ -507,9 +507,9 @@ main(int argc, char *argv[]) + + /* Make sure the server stopped only because it was interrupted (by the + child process terminating) */ +- g_assert (g_error_matches (error, +- THRIFT_SERVER_SOCKET_ERROR, +- THRIFT_SERVER_SOCKET_ERROR_ACCEPT)); ++ g_assert(!error || g_error_matches(error, ++ THRIFT_SERVER_SOCKET_ERROR, ++ THRIFT_SERVER_SOCKET_ERROR_ACCEPT)); + + /* Free our resources */ + g_object_unref (server); diff --git a/update_screen.sh b/update_screen.sh new file mode 100755 index 000000000000..de54774cc6c6 --- /dev/null +++ b/update_screen.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +lockfile .screen + +target_list_file=/tmp/target_list +touch ${target_list_file} + +function scroll_up { +# Check if TERM is available +[[ "${TERM}" == "dumb" ]] && return + +for i in $(cat ${target_list_file}); do + tput cuu1 + tput el +done +} + +function print_targets { +# Check if TERM is available +[[ "${TERM}" == "dumb" ]] && return + +count=1 +for i in $(cat ${target_list_file}); do + printf "[ %02d ] [ %s ]\n" "${count}" "$i" + ((count++)) +done +} + +function remove_target { +# Check if TERM is available +[[ "${TERM}" == "dumb" ]] && echo "[ finished ] [ $1 ] " && return + +old_list=$(cat ${target_list_file}) +rm ${target_list_file} +for target in ${old_list}; do + if [[ "${target}" != "$1" ]]; then + echo ${target} >> ${target_list_file} + fi +done +touch ${target_list_file} +} + +function add_target { +# Check if TERM is available +[[ "${TERM}" == "dumb" ]] && echo "[ building ] [ $1 ] " && return + +echo $1 >> ${target_list_file} +} + +function print_targets_delay { +sleep 2 && print_targets && rm -f .screen & +exit 0 +} + +while getopts ":a:d:e:" opt; do + case $opt in + a) + scroll_up + add_target ${OPTARG} + print_targets + ;; + d) + scroll_up + remove_target ${OPTARG} + print_targets + ;; + e) + scroll_up + remove_target ${OPTARG} + echo "[ FAIL LOG START ] [ ${OPTARG} ]" + cat ${OPTARG}.log + echo "[ FAIL LOG END ] [ ${OPTARG} ]" + print_targets_delay + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + rm -f .screen + exit 1 + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + rm -f .screen + exit 1 + ;; + esac +done + +rm -f .screen